from decimal import Decimal from django.db.models import DecimalField, Sum, Value from django.db.models.functions import Coalesce from finance.models import Account, ReconciliationCheckpoint, Transaction from .base import lock, money, save, write _MONEY_FIELD = DecimalField(max_digits=24, decimal_places=2) _ZERO = Decimal("0.00") def _ledger_balance_through(account_id, as_of_date): total = Transaction.objects.filter( account_id=account_id, posting_date__lte=as_of_date, ).aggregate( total=Coalesce( Sum("amount"), Value(_ZERO), output_field=_MONEY_FIELD, ) )["total"] return money(total, allow_zero=True) @write("reconciliation_checkpoint.created") def create_reconciliation_checkpoint(*, account_id, as_of_date, institution_balance): account = lock(Account, account_id, active=True) institution_balance = money(institution_balance, allow_zero=True) ledger_balance = _ledger_balance_through(account.pk, as_of_date) checkpoint = save(ReconciliationCheckpoint( account=account, as_of_date=as_of_date, institution_balance=institution_balance, ledger_balance_at_creation=ledger_balance, difference_at_creation=money(institution_balance - ledger_balance, allow_zero=True), )) return checkpoint, [ "account", "as_of_date", "institution_balance", "ledger_balance_at_creation", "difference_at_creation", ]