sample_payment_period_summary.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. from __future__ import annotations
  2. from decimal import Decimal
  3. from typing import Any, Dict, Iterable, List, Mapping
  4. def _dec(v: Any) -> Decimal:
  5. if v is None or v == "":
  6. return Decimal("0")
  7. return Decimal(str(v))
  8. def _status(row: Mapping[str, Any], *keys: str) -> str:
  9. for k in keys:
  10. if k in row and row[k] is not None:
  11. return str(row[k]).strip()
  12. return ""
  13. _DISPLAY_PAID_STATUSES = ("yjf",)
  14. def summarize_period(
  15. *,
  16. due_amount: Any,
  17. transfers: Iterable[Mapping[str, Any]],
  18. ) -> Dict[str, Any]:
  19. """
  20. displayPaidAmount: 已缴费金额仅计付款完成(yjf)
  21. arrearsAmount: max(due - displayPaidAmount, 0)
  22. financeAudit: jfqrz > (confirmed>=due 且无确认中 → yjf) > (0<confirmed → partial) > dfj
  23. payDate: 首笔 transferTime 的日期部分(调用方应按 create_time ASC 传入)
  24. payTypeSummary: 0 笔空;1 笔用该笔 type;多笔「多笔」
  25. """
  26. trs: List[Mapping[str, Any]] = list(transfers or [])
  27. display_paid = sum(
  28. (
  29. _dec(t.get("transferAmount", t.get("transfer_amount")))
  30. for t in trs
  31. if _status(t, "payStatus", "pay_status") in _DISPLAY_PAID_STATUSES
  32. ),
  33. Decimal("0"),
  34. )
  35. due = _dec(due_amount)
  36. arrears = due - display_paid
  37. if arrears < 0:
  38. arrears = Decimal("0")
  39. has_jfqrz = any(_status(t, "payStatus", "pay_status") == "jfqrz" for t in trs)
  40. confirmed = sum(
  41. (
  42. _dec(t.get("transferAmount", t.get("transfer_amount")))
  43. for t in trs
  44. if _status(t, "payStatus", "pay_status") == "yjf"
  45. ),
  46. Decimal("0"),
  47. )
  48. if has_jfqrz:
  49. audit = "jfqrz"
  50. elif due > 0 and confirmed >= due:
  51. audit = "yjf"
  52. elif confirmed > 0:
  53. audit = "partial"
  54. else:
  55. audit = "dfj"
  56. pay_date = ""
  57. if trs:
  58. raw = str(trs[0].get("transferTime") or trs[0].get("transfer_time") or "")
  59. pay_date = raw[:10] if len(raw) >= 10 else raw
  60. types = [
  61. _status(t, "transferType", "transfer_type")
  62. for t in trs
  63. if _status(t, "transferType", "transfer_type")
  64. ]
  65. if len(types) == 0:
  66. pay_type = ""
  67. elif len(set(types)) == 1 and len(types) == 1:
  68. pay_type = types[0]
  69. else:
  70. pay_type = "多笔"
  71. return {
  72. "displayPaidAmount": display_paid,
  73. "arrearsAmount": arrears,
  74. "payDate": pay_date,
  75. "payTypeSummary": pay_type,
  76. "financeAudit": audit,
  77. }