feat(backend): expose payment detail transferTime in protocol summary.

Let protocol-audit list show first-pay times from transfer records.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-10-09 10:00:41 +08:00
1 parent 0da75fb855
commit 38f9822d49
3 files changed
+46 -7

No files matched your search

@@ -16,9 +16,9 @@ from app.models.models import (
_PAY_MODE_LABELS = {"dj": "趸交", "fq": "分期", "djfq": "趸交+分期"}
_PAY_STATUS_LABELS = {
"dfj": "待缴费",
"dfj": "已缴费",
"jfqrz": "缴费确认中",
"yjf": "已缴费",
"yjf": "缴费成功",
"tfqrz": "退费确认中",
"ytf": "已退费",
}
@@ -64,12 +64,12 @@ def _protocol_status_hint(pay_mode: str, statuses: List[str]) -> str:
if confirm:
parts.append(f"{confirm} 期待确认")
if pending:
parts.append(f"{pending} 期待缴费")
parts.append(f"{pending} 期已缴费")
return " · ".join(parts) if len(parts) > 1 else parts[0]
if confirm:
return f"{confirm} 期待确认" if confirm > 1 else "收款确认中"
return f"{confirm} 期待确认" if confirm > 1 else "缴费确认中"
if pending:
return "待缴费"
return "已缴费"
return ""
@@ -89,9 +89,9 @@ def _protocol_overall_status(
):
return {"overallPayStatus": "cleared", "overallPayStatusLabel": "已缴清", "overallPayStatusTagType": "success"}
if "jfqrz" in statuses:
return {"overallPayStatus": "jfqrz", "overallPayStatusLabel": "收款确认中", "overallPayStatusTagType": "warning"}
return {"overallPayStatus": "jfqrz", "overallPayStatusLabel": "缴费确认中", "overallPayStatusTagType": "warning"}
if "dfj" in statuses:
return {"overallPayStatus": "dfj", "overallPayStatusLabel": "待缴费", "overallPayStatusTagType": "info"}
return {"overallPayStatus": "dfj", "overallPayStatusLabel": "已缴费", "overallPayStatusTagType": "primary"}
return {"overallPayStatus": "", "overallPayStatusLabel": "—", "overallPayStatusTagType": "info"}
@@ -102,6 +102,15 @@ def _fmt_ymd(val: Any) -> str:
return s
def _fmt_dt(v):
if v is None:
return ""
if isinstance(v, datetime):
return v.strftime("%Y-%m-%d %H:%M:%S")
s = str(v).strip()
return s
def _payment_detail_row(d: BizProtocolPaymentDetail, pay_mode: str, idx: int) -> Dict[str, Any]:
st = (d.pay_status or "").strip()
inst_no = d.installment_no
@@ -117,6 +126,7 @@ def _payment_detail_row(d: BizProtocolPaymentDetail, pay_mode: str, idx: int) ->
"transferAmount": _dec(d.transfer_amount),
"payStatus": st,
"payStatusLabel": _PAY_STATUS_LABELS.get(st, st or "—"),
"transferTime": _fmt_dt(getattr(d, "transfer_time", None)),
}
@@ -0,0 +1,28 @@
"""payment summary detail includes transferTime"""
from datetime import datetime
from types import SimpleNamespace
import unittest
from app.services.qc_work_order_fee_summary import build_protocol_payment_summary
class TestPaymentSummaryTransferTime(unittest.TestCase):
def test_detail_includes_transfer_time(self):
pay = SimpleNamespace(pay_mode="fq", contract_amount=10000)
detail = SimpleNamespace(
installment_no=1,
order_num=1,
create_time=datetime(2025, 9, 1, 10, 0, 0),
installment_due_date="20250901",
due_amount=5000,
transfer_amount=5000,
pay_status="yjf",
transfer_time=datetime(2025, 9, 15, 9, 20, 0),
)
summary = build_protocol_payment_summary(pay, [detail])
self.assertIsNotNone(summary)
self.assertEqual(summary["paymentDetails"][0]["transferTime"], "2025-09-15 09:20:00")
if __name__ == "__main__":
unittest.main()
+1
View File
@@ -25,6 +25,7 @@ export type QcProtocolPaymentDetailSummary = {
transferAmount?: number | null
payStatus?: string
payStatusLabel?: string
transferTime?: string
}
export type QcProtocolSiblingSample = {