54 lines
1.6 KiB
Python
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
|
|
}
|