diff --git a/app/apps/rules/tasks.py b/app/apps/rules/tasks.py index d222324..828c635 100644 --- a/app/apps/rules/tasks.py +++ b/app/apps/rules/tasks.py @@ -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) diff --git a/app/apps/rules/utils/__init__.py b/app/apps/rules/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/apps/rules/utils/transactions.py b/app/apps/rules/utils/transactions.py new file mode 100644 index 0000000..b119570 --- /dev/null +++ b/app/apps/rules/utils/transactions.py @@ -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"]