feat(transactions): let new recurring transactions and installment plans adopt an existing transaction

This commit is contained in:
Herculino Trotta committed 2026-10-09 23:25:19 -03:00
1 parent d500bef481
commit cd6069f857
2 files changed
+36 -5

No files matched your search

+10 -4
View File
@@ -887,11 +887,17 @@ class InstallmentPlanForm(forms.ModelForm):
),
)
def save(self, **kwargs):
def save(self, source_transaction=None, **kwargs):
is_new = not self.instance.id
instance = super().save(**kwargs)
if is_new:
if is_new and source_transaction:
# The converted transaction becomes the first installment
source_transaction.installment_plan = instance
source_transaction.installment_id = instance.installment_start
source_transaction.save()
instance.update_transactions()
elif is_new:
instance.create_transactions()
else:
instance.update_transactions()
@@ -1145,12 +1151,12 @@ class RecurringTransactionForm(forms.ModelForm):
return cleaned_data
def save(self, **kwargs):
def save(self, source_transaction=None, **kwargs):
is_new = not self.instance.id
instance = super().save(**kwargs)
if is_new:
instance.create_upcoming_transactions()
instance.create_upcoming_transactions(first_transaction=source_transaction)
else:
instance.update_unpaid_transactions()
instance.generate_upcoming_transactions()
+26 -1
View File
@@ -915,7 +915,7 @@ class RecurringTransaction(models.Model):
instance = super().save(*args, **kwargs)
return instance
def create_upcoming_transactions(self):
def create_upcoming_transactions(self, first_transaction=None):
current_date = self.start_date
reference_date = self.reference_date
end_date = min(
@@ -925,6 +925,12 @@ class RecurringTransaction(models.Model):
timezone.now().date() + (self.get_recurrence_delta() * self.keep_at_most),
)
# When converting an existing transaction, it becomes the first occurrence
if first_transaction:
self.adopt_transaction(first_transaction, current_date, reference_date)
current_date = self.get_next_date(current_date)
reference_date = self.get_next_date(reference_date)
while current_date <= end_date:
self.create_transaction(current_date, reference_date)
current_date = self.get_next_date(current_date)
@@ -959,6 +965,25 @@ class RecurringTransaction(models.Model):
created_transaction.tags.set(self.tags(manager="all_objects").all())
created_transaction.entities.set(self.entities(manager="all_objects").all())
def adopt_transaction(self, existing_transaction, date, reference_date):
existing_transaction.account = self.account
existing_transaction.type = self.type
existing_transaction.date = date
existing_transaction.reference_date = reference_date.replace(day=1)
existing_transaction.description = (
self.description if self.add_description_to_transaction else ""
)
existing_transaction.category = self.category
existing_transaction.notes = self.notes if self.add_notes_to_transaction else ""
existing_transaction.recurring_transaction = self
if not existing_transaction.is_paid: # Don't update value for paid transactions
existing_transaction.amount = self.amount
existing_transaction.save()
existing_transaction.tags.set(self.tags(manager="all_objects").all())
existing_transaction.entities.set(self.entities(manager="all_objects").all())
def get_recurrence_delta(self):
if self.recurrence_type == self.RecurrenceType.DAY:
return relativedelta(days=self.recurrence_interval)