Files
zkxw/backend/app/services/sample_payment_period_summary.py
T
zlwuandCursor b8b20dcebe fix(backend): count period paid amount as yjf only
Align displayPaidAmount/arrears with business rule: 已缴费 excludes
已付款 and 付款确认中 transfers.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-12 18:01:06 +08:00

91 lines
2.5 KiB
Python

from __future__ import annotations
from decimal import Decimal
from typing import Any, Dict, Iterable, List, Mapping
def _dec(v: Any) -> Decimal:
if v is None or v == "":
return Decimal("0")
return Decimal(str(v))
def _status(row: Mapping[str, Any], *keys: str) -> str:
for k in keys:
if k in row and row[k] is not None:
return str(row[k]).strip()
return ""
_DISPLAY_PAID_STATUSES = ("yjf",)
def summarize_period(
*,
due_amount: Any,
transfers: Iterable[Mapping[str, Any]],
) -> Dict[str, Any]:
"""
displayPaidAmount: 已缴费金额仅计付款完成(yjf)
arrearsAmount: max(due - displayPaidAmount, 0)
financeAudit: jfqrz > (confirmed>=due 且无确认中 → yjf) > (0<confirmed → partial) > dfj
payDate: 首笔 transferTime 的日期部分(调用方应按 create_time ASC 传入)
payTypeSummary: 0 笔空;1 笔用该笔 type;多笔「多笔」
"""
trs: List[Mapping[str, Any]] = list(transfers or [])
display_paid = sum(
(
_dec(t.get("transferAmount", t.get("transfer_amount")))
for t in trs
if _status(t, "payStatus", "pay_status") in _DISPLAY_PAID_STATUSES
),
Decimal("0"),
)
due = _dec(due_amount)
arrears = due - display_paid
if arrears < 0:
arrears = Decimal("0")
has_jfqrz = any(_status(t, "payStatus", "pay_status") == "jfqrz" for t in trs)
confirmed = sum(
(
_dec(t.get("transferAmount", t.get("transfer_amount")))
for t in trs
if _status(t, "payStatus", "pay_status") == "yjf"
),
Decimal("0"),
)
if has_jfqrz:
audit = "jfqrz"
elif due > 0 and confirmed >= due:
audit = "yjf"
elif confirmed > 0:
audit = "partial"
else:
audit = "dfj"
pay_date = ""
if trs:
raw = str(trs[0].get("transferTime") or trs[0].get("transfer_time") or "")
pay_date = raw[:10] if len(raw) >= 10 else raw
types = [
_status(t, "transferType", "transfer_type")
for t in trs
if _status(t, "transferType", "transfer_type")
]
if len(types) == 0:
pay_type = ""
elif len(set(types)) == 1 and len(types) == 1:
pay_type = types[0]
else:
pay_type = "多笔"
return {
"displayPaidAmount": display_paid,
"arrearsAmount": arrears,
"payDate": pay_date,
"payTypeSummary": pay_type,
"financeAudit": audit,
}