feat(rules): add rule function to fetch transactions totals and balance

This commit is contained in:
Herculino Trotta
2025-08-30 15:36:07 -03:00
parent 3e2c1184ce
commit 670bee4325
3 changed files with 61 additions and 2 deletions

View File

@@ -2,7 +2,6 @@ import decimal
import logging import logging
from datetime import datetime, date from datetime import datetime, date
from decimal import Decimal from decimal import Decimal
from typing import Any
from cachalot.api import cachalot_disabled from cachalot.api import cachalot_disabled
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
@@ -11,6 +10,7 @@ from procrastinate.contrib.django import app
from simpleeval import EvalWithCompoundTypes from simpleeval import EvalWithCompoundTypes
from apps.accounts.models import Account from apps.accounts.models import Account
from apps.common.middleware.thread_local import write_current_user, delete_current_user
from apps.rules.models import ( from apps.rules.models import (
TransactionRule, TransactionRule,
TransactionRuleAction, TransactionRuleAction,
@@ -21,7 +21,7 @@ from apps.transactions.models import (
TransactionTag, TransactionTag,
TransactionEntity, TransactionEntity,
) )
from apps.common.middleware.thread_local import write_current_user, delete_current_user from apps.rules.utils import transactions
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -58,6 +58,7 @@ def check_for_transaction_rules(
"decimal": decimal.Decimal, "decimal": decimal.Decimal,
"datetime": datetime, "datetime": datetime,
"date": date, "date": date,
"transactions": transactions.TransactionsGetter,
} }
names = _get_names(instance) names = _get_names(instance)

View File

View File

@@ -0,0 +1,58 @@
import logging
from decimal import Decimal
from django.db.models import Sum, Value, DecimalField, Case, When, F
from django.db.models.functions import Coalesce
from apps.transactions.models import (
Transaction,
)
logger = logging.getLogger(__name__)
class TransactionsGetter:
def __init__(self, **filters):
self.__queryset = Transaction.objects.filter(**filters)
@property
def sum(self):
return self.__queryset.aggregate(
total=Coalesce(
Sum("amount"), Value(Decimal("0")), output_field=DecimalField()
)
)["total"]
@property
def balance(self):
return abs(
self.__queryset.aggregate(
balance=Coalesce(
Sum(
Case(
When(type=Transaction.Type.EXPENSE, then=-F("amount")),
default=F("amount"),
output_field=DecimalField(),
)
),
Value(Decimal("0")),
output_field=DecimalField(),
)
)["balance"]
)
@property
def raw_balance(self):
return self.__queryset.aggregate(
balance=Coalesce(
Sum(
Case(
When(type=Transaction.Type.EXPENSE, then=-F("amount")),
default=F("amount"),
output_field=DecimalField(),
)
),
Value(Decimal("0")),
output_field=DecimalField(),
)
)["balance"]