Merge pull request #355

feat(rules): add rule function to fetch transactions totals and balance
This commit is contained in:
Herculino Trotta
2025-08-30 15:45:45 -03:00
committed by GitHub
3 changed files with 61 additions and 2 deletions

View File

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