|
23 | 23 |
|
24 | 24 | from django.contrib.postgres.fields.array import ArrayField
|
25 | 25 | from django.db import models
|
| 26 | +from django.db.models.signals import post_save, post_delete |
| 27 | +from django.dispatch import receiver |
26 | 28 | from django.db import transaction as db_transaction
|
27 | 29 | from django.db.models import JSONField
|
28 | 30 | from django.utils import timezone
|
@@ -138,6 +140,27 @@ class Account(MPTTModel):
|
138 | 140 | default=defaults.CURRENCIES,
|
139 | 141 | verbose_name=_("currencies"),
|
140 | 142 | )
|
| 143 | + running_totals = ArrayField( |
| 144 | + MoneyField( |
| 145 | + max_digits=MAX_DIGITS, |
| 146 | + decimal_places=DECIMAL_PLACES, |
| 147 | + default_currency=defaults.INTERNAL_CURRENCY, |
| 148 | + ), |
| 149 | + default=list, |
| 150 | + help_text="Running totals for each currency. This field should be considered an estimated value calculated for performance reasons. It is not guaranteed to be accurate.", |
| 151 | + verbose_name=_("running totals"), |
| 152 | + ) |
| 153 | + running_incomes = ArrayField( |
| 154 | + MoneyField( |
| 155 | + max_digits=MAX_DIGITS, |
| 156 | + decimal_places=DECIMAL_PLACES, |
| 157 | + help_text="Record debits as positive, credits as negative", |
| 158 | + default_currency=defaults.INTERNAL_CURRENCY, |
| 159 | + ), |
| 160 | + default=list, |
| 161 | + help_text="Running incomes for each currency. This field should be considered an estimated value calculated for performance reasons. It is not guaranteed to be accurate.", |
| 162 | + verbose_name=_("running incomes"), |
| 163 | + ) |
141 | 164 |
|
142 | 165 | objects = AccountManager.from_queryset(AccountQuerySet)()
|
143 | 166 |
|
@@ -549,6 +572,45 @@ class Meta:
|
549 | 572 | verbose_name = _("Leg")
|
550 | 573 |
|
551 | 574 |
|
| 575 | +@receiver(post_save, sender=Leg) |
| 576 | +def update_running_totals(sender, instance, created, **kwargs): |
| 577 | + """Update the running total of the account associated with the leg""" |
| 578 | + if created: |
| 579 | + instance.account.running_totals[instance.amount.currency] += instance.amount |
| 580 | + else: |
| 581 | + # We are updating the leg, so we need to get the old amount |
| 582 | + old_amount = sender.objects.get(pk=instance.pk).amount |
| 583 | + instance.account.running_totals[instance.amount.currency] += instance.amount - old_amount |
| 584 | + |
| 585 | + |
| 586 | +@receiver(post_save, sender=Leg) |
| 587 | +def update_running_incomes(sender, instance, created, **kwargs): |
| 588 | + """Update the running income of the account associated with the leg""" |
| 589 | + if created: |
| 590 | + if instance.is_credit(): |
| 591 | + instance.account.running_income += instance.amount |
| 592 | + else: |
| 593 | + # We are updating the leg, so we need to get the old amount |
| 594 | + old_amount = sender.objects.get(pk=instance.pk).amount |
| 595 | + if instance.is_credit(): |
| 596 | + instance.account.running_income += instance.amount - old_amount |
| 597 | + elif old_amount.amount < 0: |
| 598 | + instance.account.running_income += old_amount |
| 599 | + |
| 600 | + |
| 601 | +@receiver(post_delete, sender=Leg) |
| 602 | +def update_running_totals_on_delete(sender, instance, **kwargs): |
| 603 | + """Update the running total of the account associated with the leg""" |
| 604 | + instance.account.running_totals[instance.amount.currency] -= instance.amount |
| 605 | + |
| 606 | + |
| 607 | +@receiver(post_delete, sender=Leg) |
| 608 | +def update_running_incomes_on_delete(sender, instance, **kwargs): |
| 609 | + """Update the running income of the account associated with the leg""" |
| 610 | + if instance.is_credit(): |
| 611 | + instance.account.running_income -= instance.amount |
| 612 | + |
| 613 | + |
552 | 614 | class StatementImportManager(models.Manager):
|
553 | 615 | def get_by_natural_key(self, uuid):
|
554 | 616 | return self.get(uuid=uuid)
|
|
0 commit comments