customer_relations.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. """客户详情:关联协议与同单家庭成员聚合。"""
  2. from __future__ import annotations
  3. from datetime import datetime
  4. from typing import Any, Dict, List, Optional, Tuple
  5. from sqlalchemy import or_
  6. from sqlalchemy.orm import Session
  7. from app.crud import customer as customer_crud
  8. from app.models.models import BizCollectionProtocol, BizProtocolPartyCustomer
  9. from app.models.research_donation import BizResearchDonation, BizResearchDonationParty
  10. _ROLE_SPECS = (
  11. {
  12. "role": "mother",
  13. "id_attr": "customer_id",
  14. "name_attr": "mother_name",
  15. "phone_attr": "mother_phone",
  16. "id_card_attr": "mother_id_card",
  17. },
  18. {
  19. "role": "father",
  20. "id_attr": "father_customer_id",
  21. "name_attr": "father_name",
  22. "phone_attr": "father_phone",
  23. "id_card_attr": "father_id_card",
  24. },
  25. {
  26. "role": "newborn",
  27. "id_attr": "newborn_customer_id",
  28. "name_attr": "newborn_name",
  29. "phone_attr": None,
  30. "id_card_attr": "newborn_id_card",
  31. },
  32. )
  33. def resolve_my_role(party: Any, customer_id: str) -> str:
  34. cid = (customer_id or "").strip()
  35. if not cid:
  36. return ""
  37. if (getattr(party, "customer_id", None) or "").strip() == cid:
  38. return "mother"
  39. if (getattr(party, "father_customer_id", None) or "").strip() == cid:
  40. return "father"
  41. if (getattr(party, "newborn_customer_id", None) or "").strip() == cid:
  42. return "newborn"
  43. return ""
  44. def party_members(party: Any) -> List[Dict[str, str]]:
  45. out: List[Dict[str, str]] = []
  46. for spec in _ROLE_SPECS:
  47. name = (getattr(party, spec["name_attr"], None) or "").strip()
  48. if not name:
  49. continue
  50. phone_attr = spec["phone_attr"]
  51. phone = (getattr(party, phone_attr, None) or "").strip() if phone_attr else ""
  52. out.append(
  53. {
  54. "role": spec["role"],
  55. "customerId": (getattr(party, spec["id_attr"], None) or "").strip(),
  56. "name": name,
  57. "phone": phone,
  58. "idCardNo": (getattr(party, spec["id_card_attr"], None) or "").strip(),
  59. }
  60. )
  61. return out
  62. def _fmt_date(val: Any) -> str:
  63. if val is None:
  64. return ""
  65. if isinstance(val, datetime):
  66. return val.strftime("%Y%m%d")
  67. return str(val).strip()
  68. def _group_sort_key(group: Dict[str, Any]) -> datetime:
  69. ct = group.get("_createTime")
  70. if isinstance(ct, datetime):
  71. return ct
  72. return datetime.min
  73. def _storage_group(party: Any, protocol: Any, customer_id: str) -> Dict[str, Any]:
  74. return {
  75. "bizType": "cell_storage",
  76. "protocolId": protocol.id,
  77. "protocolNo": (protocol.protocol_no or "").strip(),
  78. "protocolStatus": (protocol.protocol_status or "").strip(),
  79. "registerDate": _fmt_date(protocol.register_date),
  80. "myRole": resolve_my_role(party, customer_id),
  81. "members": party_members(party),
  82. "_createTime": protocol.create_time,
  83. }
  84. def _donation_group(party: Any, donation: Any, customer_id: str) -> Dict[str, Any]:
  85. return {
  86. "bizType": "research_donation",
  87. "protocolId": donation.id,
  88. "protocolNo": (donation.donation_no or "").strip(),
  89. "protocolStatus": (donation.donation_status or "").strip(),
  90. "registerDate": _fmt_date(donation.donation_date),
  91. "myRole": resolve_my_role(party, customer_id),
  92. "members": party_members(party),
  93. "_createTime": donation.create_time,
  94. }
  95. def _fetch_storage_party_rows(
  96. db: Session, customer_id: str, tenant_no: str
  97. ) -> List[Tuple[Any, Any]]:
  98. cid = (customer_id or "").strip()
  99. rows = (
  100. db.query(BizProtocolPartyCustomer, BizCollectionProtocol)
  101. .join(
  102. BizCollectionProtocol,
  103. BizCollectionProtocol.id == BizProtocolPartyCustomer.collection_protocol_id,
  104. )
  105. .filter(
  106. BizProtocolPartyCustomer.tenant_no == tenant_no,
  107. BizProtocolPartyCustomer.del_flag == 0,
  108. BizCollectionProtocol.tenant_no == tenant_no,
  109. BizCollectionProtocol.del_flag == 0,
  110. or_(
  111. BizProtocolPartyCustomer.customer_id == cid,
  112. BizProtocolPartyCustomer.father_customer_id == cid,
  113. BizProtocolPartyCustomer.newborn_customer_id == cid,
  114. ),
  115. )
  116. .all()
  117. )
  118. return list(rows)
  119. def _fetch_donation_party_rows(
  120. db: Session, customer_id: str, tenant_no: str
  121. ) -> List[Tuple[Any, Any]]:
  122. cid = (customer_id or "").strip()
  123. rows = (
  124. db.query(BizResearchDonationParty, BizResearchDonation)
  125. .join(
  126. BizResearchDonation,
  127. BizResearchDonation.id == BizResearchDonationParty.research_donation_id,
  128. )
  129. .filter(
  130. BizResearchDonationParty.tenant_no == tenant_no,
  131. BizResearchDonationParty.del_flag == 0,
  132. BizResearchDonation.tenant_no == tenant_no,
  133. BizResearchDonation.del_flag == 0,
  134. or_(
  135. BizResearchDonationParty.customer_id == cid,
  136. BizResearchDonationParty.father_customer_id == cid,
  137. BizResearchDonationParty.newborn_customer_id == cid,
  138. ),
  139. )
  140. .all()
  141. )
  142. return list(rows)
  143. def build_customer_relations(
  144. db: Session, customer_id: str, tenant_no: str
  145. ) -> Optional[Dict[str, Any]]:
  146. customer = customer_crud.get_customer(db, customer_id, tenant_no=tenant_no)
  147. if not customer:
  148. return None
  149. groups: List[Dict[str, Any]] = []
  150. for party, protocol in _fetch_storage_party_rows(db, customer_id, tenant_no):
  151. groups.append(_storage_group(party, protocol, customer_id))
  152. for party, donation in _fetch_donation_party_rows(db, customer_id, tenant_no):
  153. groups.append(_donation_group(party, donation, customer_id))
  154. groups.sort(key=_group_sort_key, reverse=True)
  155. related_groups: List[Dict[str, Any]] = []
  156. protocols: List[Dict[str, Any]] = []
  157. for g in groups:
  158. related_groups.append(
  159. {
  160. "bizType": g["bizType"],
  161. "protocolId": g["protocolId"],
  162. "protocolNo": g["protocolNo"],
  163. "protocolStatus": g["protocolStatus"],
  164. "registerDate": g["registerDate"],
  165. "myRole": g["myRole"],
  166. "members": g["members"],
  167. }
  168. )
  169. protocols.append(
  170. {
  171. "bizType": g["bizType"],
  172. "protocolId": g["protocolId"],
  173. "protocolNo": g["protocolNo"],
  174. "protocolStatus": g["protocolStatus"],
  175. "registerDate": g["registerDate"],
  176. "myRole": g["myRole"],
  177. }
  178. )
  179. return {
  180. "customer": customer_crud._row_to_dict(customer),
  181. "relatedGroups": related_groups,
  182. "protocols": protocols,
  183. }