|
|
@@ -0,0 +1,149 @@
|
|
|
+"""样本客户服务扩展 CRUD。"""
|
|
|
+from __future__ import annotations
|
|
|
+
|
|
|
+from datetime import date, datetime
|
|
|
+from typing import Any, Dict, List, Optional
|
|
|
+
|
|
|
+from sqlalchemy.orm import Session
|
|
|
+
|
|
|
+from app.core.utils import generate_uuid
|
|
|
+from app.crud.customer_service_dict import ensure_dict_value
|
|
|
+from app.models.models import BizSampleCustomerService
|
|
|
+from app.services.sample_customer_service_register import (
|
|
|
+ CUSTOMER_SERVICE_FIELD_KEYS,
|
|
|
+ merge_customer_service_fields,
|
|
|
+ normalize_dict_value,
|
|
|
+)
|
|
|
+
|
|
|
+DICT_TYPE_BY_FIELD = {
|
|
|
+ "sms_send_status": "sms_send_status",
|
|
|
+ "microbe_followup_status": "microbe_followup_status",
|
|
|
+ "fullmoon_followup_status": "fullmoon_followup_status",
|
|
|
+ "household_registered": "household_registered",
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+def _format_date(value: Optional[date]) -> Optional[str]:
|
|
|
+ if value is None:
|
|
|
+ return None
|
|
|
+ if isinstance(value, datetime):
|
|
|
+ return value.strftime("%Y-%m-%d")
|
|
|
+ return value.strftime("%Y-%m-%d")
|
|
|
+
|
|
|
+
|
|
|
+def _format_datetime(value: Optional[datetime]) -> Optional[str]:
|
|
|
+ if value is None:
|
|
|
+ return None
|
|
|
+ return value.strftime("%Y-%m-%d %H:%M:%S")
|
|
|
+
|
|
|
+
|
|
|
+def _row_field_dict(row: BizSampleCustomerService) -> Dict[str, Any]:
|
|
|
+ return {key: getattr(row, key) for key in CUSTOMER_SERVICE_FIELD_KEYS}
|
|
|
+
|
|
|
+
|
|
|
+def get_by_sample_code(
|
|
|
+ db: Session, tenant_no: str, sample_code: str
|
|
|
+) -> Optional[BizSampleCustomerService]:
|
|
|
+ code = (sample_code or "").strip()
|
|
|
+ if not code:
|
|
|
+ return None
|
|
|
+ return (
|
|
|
+ db.query(BizSampleCustomerService)
|
|
|
+ .filter(
|
|
|
+ BizSampleCustomerService.tenant_no == tenant_no,
|
|
|
+ BizSampleCustomerService.sample_code == code,
|
|
|
+ BizSampleCustomerService.del_flag == 0,
|
|
|
+ )
|
|
|
+ .first()
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+def get_map_by_sample_codes(
|
|
|
+ db: Session, tenant_no: str, sample_codes: List[str]
|
|
|
+) -> Dict[str, BizSampleCustomerService]:
|
|
|
+ codes = list({(c or "").strip() for c in sample_codes if (c or "").strip()})
|
|
|
+ if not codes:
|
|
|
+ return {}
|
|
|
+ rows = (
|
|
|
+ db.query(BizSampleCustomerService)
|
|
|
+ .filter(
|
|
|
+ BizSampleCustomerService.tenant_no == tenant_no,
|
|
|
+ BizSampleCustomerService.sample_code.in_(codes),
|
|
|
+ BizSampleCustomerService.del_flag == 0,
|
|
|
+ )
|
|
|
+ .all()
|
|
|
+ )
|
|
|
+ return {row.sample_code: row for row in rows}
|
|
|
+
|
|
|
+
|
|
|
+def row_to_dict(row: BizSampleCustomerService) -> Dict[str, Any]:
|
|
|
+ return {
|
|
|
+ "id": row.id,
|
|
|
+ "sampleCode": row.sample_code,
|
|
|
+ "collectionProtocolId": row.collection_protocol_id,
|
|
|
+ "smsSendDate": _format_date(row.sms_send_date),
|
|
|
+ "smsSendStatus": row.sms_send_status,
|
|
|
+ "microbeFollowupDate": _format_date(row.microbe_followup_date),
|
|
|
+ "microbeFollowupStatus": row.microbe_followup_status,
|
|
|
+ "fullmoonFollowupDate": _format_date(row.fullmoon_followup_date),
|
|
|
+ "fullmoonFollowupStatus": row.fullmoon_followup_status,
|
|
|
+ "householdRegistered": row.household_registered,
|
|
|
+ "einvoiceSendTime": _format_datetime(row.einvoice_send_time),
|
|
|
+ "effectiveAddress": row.effective_address,
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+def upsert_by_sample_code(
|
|
|
+ db: Session,
|
|
|
+ *,
|
|
|
+ tenant_no: str,
|
|
|
+ sample_code: str,
|
|
|
+ collection_protocol_id: Optional[str],
|
|
|
+ user_id: Optional[str],
|
|
|
+ incoming: Dict[str, Any],
|
|
|
+) -> BizSampleCustomerService:
|
|
|
+ code = (sample_code or "").strip()
|
|
|
+ if not code:
|
|
|
+ raise ValueError("sample_code is required")
|
|
|
+
|
|
|
+ row = get_by_sample_code(db, tenant_no, code)
|
|
|
+ now = datetime.now()
|
|
|
+ if row is None:
|
|
|
+ row = BizSampleCustomerService(
|
|
|
+ id=generate_uuid(),
|
|
|
+ sample_code=code,
|
|
|
+ collection_protocol_id=collection_protocol_id,
|
|
|
+ tenant_no=tenant_no,
|
|
|
+ create_by=user_id,
|
|
|
+ create_dept_id="",
|
|
|
+ create_time=now,
|
|
|
+ update_by=user_id,
|
|
|
+ update_time=now,
|
|
|
+ del_flag=0,
|
|
|
+ )
|
|
|
+ db.add(row)
|
|
|
+ else:
|
|
|
+ if collection_protocol_id and not row.collection_protocol_id:
|
|
|
+ row.collection_protocol_id = collection_protocol_id
|
|
|
+ row.update_by = user_id
|
|
|
+ row.update_time = now
|
|
|
+
|
|
|
+ existing = _row_field_dict(row)
|
|
|
+ merged = merge_customer_service_fields(existing, incoming)
|
|
|
+
|
|
|
+ for field, dict_type in DICT_TYPE_BY_FIELD.items():
|
|
|
+ if field not in merged:
|
|
|
+ continue
|
|
|
+ value = merged[field]
|
|
|
+ if value is None or normalize_dict_value(value) is None:
|
|
|
+ continue
|
|
|
+ merged[field] = ensure_dict_value(
|
|
|
+ db, tenant_no, dict_type, value, user_id=user_id
|
|
|
+ )
|
|
|
+
|
|
|
+ for key in CUSTOMER_SERVICE_FIELD_KEYS:
|
|
|
+ if key in merged:
|
|
|
+ setattr(row, key, merged[key])
|
|
|
+
|
|
|
+ db.flush()
|
|
|
+ return row
|