210 lines
6.8 KiB
Python
210 lines
6.8 KiB
Python
"""客户详情:关联协议与同单家庭成员聚合。"""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
from typing import Any, Dict, List, Optional, Tuple
|
|
|
|
from sqlalchemy import or_
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.crud import customer as customer_crud
|
|
from app.models.models import BizCollectionProtocol, BizProtocolPartyCustomer
|
|
from app.models.research_donation import BizResearchDonation, BizResearchDonationParty
|
|
|
|
_ROLE_SPECS = (
|
|
{
|
|
"role": "mother",
|
|
"id_attr": "customer_id",
|
|
"name_attr": "mother_name",
|
|
"phone_attr": "mother_phone",
|
|
"id_card_attr": "mother_id_card",
|
|
},
|
|
{
|
|
"role": "father",
|
|
"id_attr": "father_customer_id",
|
|
"name_attr": "father_name",
|
|
"phone_attr": "father_phone",
|
|
"id_card_attr": "father_id_card",
|
|
},
|
|
{
|
|
"role": "newborn",
|
|
"id_attr": "newborn_customer_id",
|
|
"name_attr": "newborn_name",
|
|
"phone_attr": None,
|
|
"id_card_attr": "newborn_id_card",
|
|
},
|
|
)
|
|
|
|
|
|
def resolve_my_role(party: Any, customer_id: str) -> str:
|
|
cid = (customer_id or "").strip()
|
|
if not cid:
|
|
return ""
|
|
if (getattr(party, "customer_id", None) or "").strip() == cid:
|
|
return "mother"
|
|
if (getattr(party, "father_customer_id", None) or "").strip() == cid:
|
|
return "father"
|
|
if (getattr(party, "newborn_customer_id", None) or "").strip() == cid:
|
|
return "newborn"
|
|
return ""
|
|
|
|
|
|
def party_members(party: Any) -> List[Dict[str, str]]:
|
|
out: List[Dict[str, str]] = []
|
|
for spec in _ROLE_SPECS:
|
|
name = (getattr(party, spec["name_attr"], None) or "").strip()
|
|
if not name:
|
|
continue
|
|
phone_attr = spec["phone_attr"]
|
|
phone = (getattr(party, phone_attr, None) or "").strip() if phone_attr else ""
|
|
out.append(
|
|
{
|
|
"role": spec["role"],
|
|
"customerId": (getattr(party, spec["id_attr"], None) or "").strip(),
|
|
"name": name,
|
|
"phone": phone,
|
|
"idCardNo": (getattr(party, spec["id_card_attr"], None) or "").strip(),
|
|
}
|
|
)
|
|
return out
|
|
|
|
|
|
def _fmt_date(val: Any) -> str:
|
|
if val is None:
|
|
return ""
|
|
if isinstance(val, datetime):
|
|
return val.strftime("%Y%m%d")
|
|
return str(val).strip()
|
|
|
|
|
|
def _group_sort_key(group: Dict[str, Any]) -> datetime:
|
|
ct = group.get("_createTime")
|
|
if isinstance(ct, datetime):
|
|
return ct
|
|
return datetime.min
|
|
|
|
|
|
def _storage_group(party: Any, protocol: Any, customer_id: str) -> Dict[str, Any]:
|
|
return {
|
|
"bizType": "cell_storage",
|
|
"protocolId": protocol.id,
|
|
"protocolNo": (protocol.protocol_no or "").strip(),
|
|
"protocolStatus": (protocol.protocol_status or "").strip(),
|
|
"registerDate": _fmt_date(protocol.register_date),
|
|
"myRole": resolve_my_role(party, customer_id),
|
|
"members": party_members(party),
|
|
"_createTime": protocol.create_time,
|
|
}
|
|
|
|
|
|
def _donation_group(party: Any, donation: Any, customer_id: str) -> Dict[str, Any]:
|
|
return {
|
|
"bizType": "research_donation",
|
|
"protocolId": donation.id,
|
|
"protocolNo": (donation.donation_no or "").strip(),
|
|
"protocolStatus": (donation.donation_status or "").strip(),
|
|
"registerDate": _fmt_date(donation.donation_date),
|
|
"myRole": resolve_my_role(party, customer_id),
|
|
"members": party_members(party),
|
|
"_createTime": donation.create_time,
|
|
}
|
|
|
|
|
|
def _fetch_storage_party_rows(
|
|
db: Session, customer_id: str, tenant_no: str
|
|
) -> List[Tuple[Any, Any]]:
|
|
cid = (customer_id or "").strip()
|
|
rows = (
|
|
db.query(BizProtocolPartyCustomer, BizCollectionProtocol)
|
|
.join(
|
|
BizCollectionProtocol,
|
|
BizCollectionProtocol.id == BizProtocolPartyCustomer.collection_protocol_id,
|
|
)
|
|
.filter(
|
|
BizProtocolPartyCustomer.tenant_no == tenant_no,
|
|
BizProtocolPartyCustomer.del_flag == 0,
|
|
BizCollectionProtocol.tenant_no == tenant_no,
|
|
BizCollectionProtocol.del_flag == 0,
|
|
or_(
|
|
BizProtocolPartyCustomer.customer_id == cid,
|
|
BizProtocolPartyCustomer.father_customer_id == cid,
|
|
BizProtocolPartyCustomer.newborn_customer_id == cid,
|
|
),
|
|
)
|
|
.all()
|
|
)
|
|
return list(rows)
|
|
|
|
|
|
def _fetch_donation_party_rows(
|
|
db: Session, customer_id: str, tenant_no: str
|
|
) -> List[Tuple[Any, Any]]:
|
|
cid = (customer_id or "").strip()
|
|
rows = (
|
|
db.query(BizResearchDonationParty, BizResearchDonation)
|
|
.join(
|
|
BizResearchDonation,
|
|
BizResearchDonation.id == BizResearchDonationParty.research_donation_id,
|
|
)
|
|
.filter(
|
|
BizResearchDonationParty.tenant_no == tenant_no,
|
|
BizResearchDonationParty.del_flag == 0,
|
|
BizResearchDonation.tenant_no == tenant_no,
|
|
BizResearchDonation.del_flag == 0,
|
|
or_(
|
|
BizResearchDonationParty.customer_id == cid,
|
|
BizResearchDonationParty.father_customer_id == cid,
|
|
BizResearchDonationParty.newborn_customer_id == cid,
|
|
),
|
|
)
|
|
.all()
|
|
)
|
|
return list(rows)
|
|
|
|
|
|
def build_customer_relations(
|
|
db: Session, customer_id: str, tenant_no: str
|
|
) -> Optional[Dict[str, Any]]:
|
|
customer = customer_crud.get_customer(db, customer_id, tenant_no=tenant_no)
|
|
if not customer:
|
|
return None
|
|
|
|
groups: List[Dict[str, Any]] = []
|
|
for party, protocol in _fetch_storage_party_rows(db, customer_id, tenant_no):
|
|
groups.append(_storage_group(party, protocol, customer_id))
|
|
for party, donation in _fetch_donation_party_rows(db, customer_id, tenant_no):
|
|
groups.append(_donation_group(party, donation, customer_id))
|
|
|
|
groups.sort(key=_group_sort_key, reverse=True)
|
|
|
|
related_groups: List[Dict[str, Any]] = []
|
|
protocols: List[Dict[str, Any]] = []
|
|
for g in groups:
|
|
related_groups.append(
|
|
{
|
|
"bizType": g["bizType"],
|
|
"protocolId": g["protocolId"],
|
|
"protocolNo": g["protocolNo"],
|
|
"protocolStatus": g["protocolStatus"],
|
|
"registerDate": g["registerDate"],
|
|
"myRole": g["myRole"],
|
|
"members": g["members"],
|
|
}
|
|
)
|
|
protocols.append(
|
|
{
|
|
"bizType": g["bizType"],
|
|
"protocolId": g["protocolId"],
|
|
"protocolNo": g["protocolNo"],
|
|
"protocolStatus": g["protocolStatus"],
|
|
"registerDate": g["registerDate"],
|
|
"myRole": g["myRole"],
|
|
}
|
|
)
|
|
|
|
return {
|
|
"customer": customer_crud._row_to_dict(customer),
|
|
"relatedGroups": related_groups,
|
|
"protocols": protocols,
|
|
}
|