Corp/backend/finance/payroll/balances.py

54 lines
1.6 KiB
Python

"""Payroll balances reconstructed from explicit correction input lines."""
from __future__ import annotations
from collections.abc import Iterable
from decimal import Decimal
from django.db.models import Q, Sum
from finance.enums import ApprovalStatus, InputSource
from finance.models import PayrollInputLine, PayrollPeriod
def opening_balances(
period: PayrollPeriod,
employee_ids: Iterable[int],
) -> dict[int, Decimal]:
"""Return the cumulative balance from approved earlier corrections."""
requested_ids = set(employee_ids)
if not requested_ids:
return {}
rows = (
PayrollInputLine.objects.filter(
employee_id__in=requested_ids,
period__currency=period.currency,
period__date_to__lt=period.date_from,
status=ApprovalStatus.APPROVED,
include_in_carryover=True,
component_code__in=("CORRECTION_CREDIT", "CORRECTION_DEBIT"),
)
.exclude(
source=InputSource.API,
source_ref__startswith="payroll-carryover:",
)
.values("employee_id")
.annotate(
credit_total=Sum(
"amount",
filter=Q(component_code="CORRECTION_CREDIT"),
default=Decimal("0.00"),
),
debit_total=Sum(
"amount",
filter=Q(component_code="CORRECTION_DEBIT"),
default=Decimal("0.00"),
),
)
)
return {
row["employee_id"]: row["debit_total"] - row["credit_total"]
for row in rows
}