diff --git a/app/apps/transactions/models.py b/app/apps/transactions/models.py index be85547..8399e3a 100644 --- a/app/apps/transactions/models.py +++ b/app/apps/transactions/models.py @@ -937,8 +937,10 @@ class RecurringTransaction(models.Model): notes=self.notes if self.add_notes_to_transaction else "", owner=self.account.owner, ) - created_transaction.tags.set(self.tags.all()) - created_transaction.entities.set(self.entities.all()) + # Unfiltered managers: generation also runs without a current user, or with a + # different one, and the scoped default manager would hide private rows. + created_transaction.tags.set(self.tags(manager="all_objects").all()) + created_transaction.entities.set(self.entities(manager="all_objects").all()) def get_recurrence_delta(self): if self.recurrence_type == self.RecurrenceType.DAY: @@ -1030,9 +1032,11 @@ class RecurringTransaction(models.Model): self.notes if self.add_notes_to_transaction else "" ) - # Update many-to-many relationships - existing_transaction.tags.set(self.tags.all()) - existing_transaction.entities.set(self.entities.all()) + # Update many-to-many relationships (see create_transaction) + existing_transaction.tags.set(self.tags(manager="all_objects").all()) + existing_transaction.entities.set( + self.entities(manager="all_objects").all() + ) # Save updated transaction existing_transaction.save() diff --git a/app/apps/transactions/tests/test_models.py b/app/apps/transactions/tests/test_models.py index 546d6b3..72e4340 100644 --- a/app/apps/transactions/tests/test_models.py +++ b/app/apps/transactions/tests/test_models.py @@ -7,6 +7,7 @@ from django.utils import timezone from apps.transactions.models import ( TransactionCategory, TransactionTag, + TransactionEntity, Transaction, InstallmentPlan, RecurringTransaction, @@ -240,3 +241,27 @@ class RecurringTransactionTests(TestCase): self.assertFalse(recurring.is_paused) self.assertEqual(recurring.recurrence_interval, 1) self.assertEqual(recurring.account.currency.code, "USD") + + def test_generate_upcoming_transactions_keeps_tags_and_entities(self): + """Generation must copy tags/entities even with no current user""" + tag = TransactionTag.objects.create(name="Essential") + entity = TransactionEntity.objects.create(name="Landlord") + recurring = RecurringTransaction.objects.create( + account=self.account, + type=Transaction.Type.EXPENSE, + amount=Decimal("100.00"), + description="Monthly Payment", + start_date=timezone.now().date(), + recurrence_type=RecurringTransaction.RecurrenceType.MONTH, + recurrence_interval=1, + ) + recurring.tags.set([tag]) + recurring.entities.set([entity]) + + RecurringTransaction.generate_upcoming_transactions() + + generated = Transaction.all_objects.filter(recurring_transaction=recurring) + self.assertTrue(generated.exists()) + for transaction in generated: + self.assertIn(tag, transaction.tags(manager="all_objects").all()) + self.assertIn(entity, transaction.entities(manager="all_objects").all())