mirror of
https://github.com/eitchtee/WYGIWYH.git
synced 2026-04-23 17:18:44 +02:00
Merge pull request #482 from eitchtee/dev
fix(import_restore): unable to restore installment plans when there's multiple accounts with the same name
This commit is contained in:
@@ -1,8 +1,10 @@
|
|||||||
from import_export import fields, resources
|
from import_export import fields, resources
|
||||||
from import_export.widgets import ForeignKeyWidget
|
|
||||||
|
|
||||||
from apps.accounts.models import Account
|
from apps.accounts.models import Account
|
||||||
from apps.export_app.widgets.foreign_key import AutoCreateForeignKeyWidget
|
from apps.export_app.widgets.foreign_key import (
|
||||||
|
AllObjectsForeignKeyWidget,
|
||||||
|
AutoCreateForeignKeyWidget,
|
||||||
|
)
|
||||||
from apps.export_app.widgets.many_to_many import AutoCreateManyToManyWidget
|
from apps.export_app.widgets.many_to_many import AutoCreateManyToManyWidget
|
||||||
from apps.export_app.widgets.string import EmptyStringToNoneField
|
from apps.export_app.widgets.string import EmptyStringToNoneField
|
||||||
from apps.transactions.models import (
|
from apps.transactions.models import (
|
||||||
@@ -20,7 +22,7 @@ class TransactionResource(resources.ModelResource):
|
|||||||
account = fields.Field(
|
account = fields.Field(
|
||||||
attribute="account",
|
attribute="account",
|
||||||
column_name="account",
|
column_name="account",
|
||||||
widget=ForeignKeyWidget(Account, "name"),
|
widget=AllObjectsForeignKeyWidget(Account, "name"),
|
||||||
)
|
)
|
||||||
|
|
||||||
category = fields.Field(
|
category = fields.Field(
|
||||||
@@ -86,7 +88,7 @@ class RecurringTransactionResource(resources.ModelResource):
|
|||||||
account = fields.Field(
|
account = fields.Field(
|
||||||
attribute="account",
|
attribute="account",
|
||||||
column_name="account",
|
column_name="account",
|
||||||
widget=ForeignKeyWidget(Account, "name"),
|
widget=AllObjectsForeignKeyWidget(Account, "name"),
|
||||||
)
|
)
|
||||||
|
|
||||||
category = fields.Field(
|
category = fields.Field(
|
||||||
@@ -119,12 +121,16 @@ class RecurringTransactionResource(resources.ModelResource):
|
|||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return RecurringTransaction.all_objects.all()
|
return RecurringTransaction.all_objects.all()
|
||||||
|
|
||||||
|
def dehydrate_account_owner(self, obj):
|
||||||
|
"""Export the account's owner ID for proper import matching."""
|
||||||
|
return obj.account.owner_id if obj.account else None
|
||||||
|
|
||||||
|
|
||||||
class InstallmentPlanResource(resources.ModelResource):
|
class InstallmentPlanResource(resources.ModelResource):
|
||||||
account = fields.Field(
|
account = fields.Field(
|
||||||
attribute="account",
|
attribute="account",
|
||||||
column_name="account",
|
column_name="account",
|
||||||
widget=ForeignKeyWidget(Account, "name"),
|
widget=AllObjectsForeignKeyWidget(Account, "name"),
|
||||||
)
|
)
|
||||||
|
|
||||||
category = fields.Field(
|
category = fields.Field(
|
||||||
@@ -156,3 +162,7 @@ class InstallmentPlanResource(resources.ModelResource):
|
|||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return InstallmentPlan.all_objects.all()
|
return InstallmentPlan.all_objects.all()
|
||||||
|
|
||||||
|
def dehydrate_account_owner(self, obj):
|
||||||
|
"""Export the account's owner ID for proper import matching."""
|
||||||
|
return obj.account.owner_id if obj.account else None
|
||||||
|
|||||||
@@ -1,6 +1,60 @@
|
|||||||
from import_export.widgets import ForeignKeyWidget
|
from import_export.widgets import ForeignKeyWidget
|
||||||
|
|
||||||
|
|
||||||
|
class AllObjectsForeignKeyWidget(ForeignKeyWidget):
|
||||||
|
"""
|
||||||
|
ForeignKeyWidget that uses 'all_objects' manager for lookups,
|
||||||
|
bypassing user-filtered managers like SharedObjectManager.
|
||||||
|
Also filters by owner if available in the row data.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_queryset(self, value, row, *args, **kwargs):
|
||||||
|
# Use all_objects manager if available, otherwise fall back to default
|
||||||
|
if hasattr(self.model, "all_objects"):
|
||||||
|
qs = self.model.all_objects.all()
|
||||||
|
# Filter by owner if the row has an owner field and the model has owner
|
||||||
|
if row:
|
||||||
|
# Check for direct owner field first
|
||||||
|
owner_id = row.get("owner") if "owner" in row else None
|
||||||
|
# Fall back to account_owner for models like InstallmentPlan
|
||||||
|
if not owner_id and "account_owner" in row:
|
||||||
|
owner_id = row.get("account_owner")
|
||||||
|
# If still no owner, try to get it from the existing record's account
|
||||||
|
# This handles backward compatibility with older exports
|
||||||
|
if not owner_id and "id" in row and row.get("id"):
|
||||||
|
try:
|
||||||
|
# Try to find the existing record and get owner from its account
|
||||||
|
from apps.transactions.models import (
|
||||||
|
InstallmentPlan,
|
||||||
|
RecurringTransaction,
|
||||||
|
)
|
||||||
|
|
||||||
|
record_id = row.get("id")
|
||||||
|
# Try to find the existing InstallmentPlan or RecurringTransaction
|
||||||
|
for model_class in [InstallmentPlan, RecurringTransaction]:
|
||||||
|
try:
|
||||||
|
existing = model_class.all_objects.get(id=record_id)
|
||||||
|
if existing.account:
|
||||||
|
owner_id = existing.account.owner_id
|
||||||
|
break
|
||||||
|
except model_class.DoesNotExist:
|
||||||
|
continue
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
# Final fallback: use the current logged-in user
|
||||||
|
# This handles restoring to a fresh database with older exports
|
||||||
|
if not owner_id:
|
||||||
|
from apps.common.middleware.thread_local import get_current_user
|
||||||
|
|
||||||
|
user = get_current_user()
|
||||||
|
if user and user.is_authenticated:
|
||||||
|
owner_id = user.id
|
||||||
|
if owner_id:
|
||||||
|
qs = qs.filter(owner_id=owner_id)
|
||||||
|
return qs
|
||||||
|
return super().get_queryset(value, row, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class AutoCreateForeignKeyWidget(ForeignKeyWidget):
|
class AutoCreateForeignKeyWidget(ForeignKeyWidget):
|
||||||
def clean(self, value, row=None, *args, **kwargs):
|
def clean(self, value, row=None, *args, **kwargs):
|
||||||
if value:
|
if value:
|
||||||
|
|||||||
Reference in New Issue
Block a user