245 lines
8.0 KiB
Python
245 lines
8.0 KiB
Python
"""协议/捐赠列表卡片:按样本编码批量取接收结论与门禁质检结论(轻量字段)。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections import defaultdict
|
|
from typing import Any, Dict, List, Optional
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.models.models import BizQcTask, BizQcWorkOrder, BizSampleReception
|
|
from app.services.qc_work_order_conclusion import (
|
|
build_qc_conclusion_fields,
|
|
work_order_qc_conclusion_label,
|
|
)
|
|
|
|
_ACCEPT_CONCLUSION_LABELS = {"js": "接收", "bj": "拒收"}
|
|
_VALID_QC_CONCLUSIONS = frozenset({"tg", "btg"})
|
|
_QC_WORK_ORDER_STATUS_LABELS = {
|
|
"dpz": "待配置",
|
|
"ypz": "已配置",
|
|
"ywc": "已完成",
|
|
"yzf": "已作废",
|
|
}
|
|
|
|
|
|
def empty_gate_qc_summary_fields() -> Dict[str, str]:
|
|
return {
|
|
"qcWorkOrderNo": "",
|
|
"qcWorkOrderStatus": "",
|
|
"qcWorkOrderStatusLabel": "",
|
|
"qcConclusion": "",
|
|
"qcConclusionLabel": "",
|
|
}
|
|
|
|
|
|
def _empty_gate_qc_summary_fields() -> Dict[str, str]:
|
|
return empty_gate_qc_summary_fields()
|
|
|
|
|
|
def _load_derived_qc_conclusions_by_work_order_ids(
|
|
db: Session,
|
|
work_order_ids: List[str],
|
|
) -> Dict[str, List[Optional[str]]]:
|
|
conclusions_by_wo: Dict[str, List[Optional[str]]] = defaultdict(list)
|
|
ids = list({(i or "").strip() for i in work_order_ids if (i or "").strip()})
|
|
if not ids:
|
|
return conclusions_by_wo
|
|
task_rows = (
|
|
db.query(BizQcTask.work_order_id, BizQcTask.conclusion)
|
|
.filter(
|
|
BizQcTask.del_flag == 0,
|
|
BizQcTask.work_order_id.in_(ids),
|
|
)
|
|
.all()
|
|
)
|
|
for wo_id, conc in task_rows:
|
|
wid = (wo_id or "").strip()
|
|
if wid:
|
|
conclusions_by_wo[wid].append(conc)
|
|
return conclusions_by_wo
|
|
|
|
|
|
def _build_gate_qc_summary_fields(
|
|
wo: BizQcWorkOrder,
|
|
conclusions_by_wo: Dict[str, List[Optional[str]]],
|
|
) -> Dict[str, str]:
|
|
stored = (getattr(wo, "conclusion", None) or "").strip()
|
|
if stored in _VALID_QC_CONCLUSIONS:
|
|
qc_conclusion = stored
|
|
qc_label = work_order_qc_conclusion_label(stored)
|
|
else:
|
|
wid = (wo.id or "").strip()
|
|
fields = build_qc_conclusion_fields(conclusions_by_wo.get(wid, []))
|
|
qc_conclusion = fields["qcConclusion"]
|
|
qc_label = fields["qcConclusionLabel"]
|
|
status = (wo.work_order_status or "").strip()
|
|
return {
|
|
"qcWorkOrderNo": (wo.work_order_no or "").strip(),
|
|
"qcWorkOrderStatus": status,
|
|
"qcWorkOrderStatusLabel": _QC_WORK_ORDER_STATUS_LABELS.get(status, status),
|
|
"qcConclusion": qc_conclusion,
|
|
"qcConclusionLabel": qc_label,
|
|
}
|
|
|
|
|
|
def _build_gate_qc_summaries_for_work_orders(
|
|
db: Session,
|
|
work_orders: List[BizQcWorkOrder],
|
|
) -> Dict[str, Dict[str, str]]:
|
|
if not work_orders:
|
|
return {}
|
|
need_derive_ids: List[str] = []
|
|
for wo in work_orders:
|
|
stored = (getattr(wo, "conclusion", None) or "").strip()
|
|
if stored not in _VALID_QC_CONCLUSIONS:
|
|
wid = (wo.id or "").strip()
|
|
if wid:
|
|
need_derive_ids.append(wid)
|
|
conclusions_by_wo = _load_derived_qc_conclusions_by_work_order_ids(db, need_derive_ids)
|
|
out: Dict[str, Dict[str, str]] = {}
|
|
for wo in work_orders:
|
|
wid = (wo.id or "").strip()
|
|
if wid:
|
|
out[wid] = _build_gate_qc_summary_fields(wo, conclusions_by_wo)
|
|
return out
|
|
|
|
|
|
def build_sample_item_reception_qc_fields(
|
|
reception: Optional[Dict[str, Any]],
|
|
qc: Optional[Dict[str, Any]],
|
|
) -> Dict[str, Any]:
|
|
"""合并接收/质检结论摘要为列表 sampleItems 字段。"""
|
|
conclusion = ""
|
|
remark = ""
|
|
if reception:
|
|
conclusion = (reception.get("acceptConclusion") or "").strip()
|
|
remark = (reception.get("remark") or "").strip()
|
|
qc_code = ""
|
|
qc_label = ""
|
|
if qc:
|
|
qc_code = (qc.get("qcConclusion") or "").strip()
|
|
qc_label = (qc.get("qcConclusionLabel") or "").strip()
|
|
if qc_code and not qc_label:
|
|
qc_label = work_order_qc_conclusion_label(qc_code)
|
|
return {
|
|
"receptionAcceptConclusion": conclusion,
|
|
"receptionAcceptConclusionLabel": _ACCEPT_CONCLUSION_LABELS.get(conclusion, ""),
|
|
"receptionRemark": remark,
|
|
"qcConclusion": qc_code,
|
|
"qcConclusionLabel": qc_label,
|
|
}
|
|
|
|
|
|
def get_list_reception_summary_map_by_sample_codes(
|
|
db: Session,
|
|
tenant_no: str,
|
|
sample_codes: List[str],
|
|
*,
|
|
reception_source: str,
|
|
) -> Dict[str, Dict[str, str]]:
|
|
"""按租户 + 样本编码 + 来源返回接收摘要(acceptConclusion / remark),同码取首条。"""
|
|
codes = list({(c or "").strip() for c in sample_codes if (c or "").strip()})
|
|
if not tenant_no or not codes or not (reception_source or "").strip():
|
|
return {}
|
|
rows = (
|
|
db.query(BizSampleReception)
|
|
.filter(
|
|
BizSampleReception.tenant_no == tenant_no,
|
|
BizSampleReception.del_flag == 0,
|
|
BizSampleReception.reception_source == reception_source,
|
|
BizSampleReception.sample_code.in_(codes),
|
|
)
|
|
.all()
|
|
)
|
|
out: Dict[str, Dict[str, str]] = {}
|
|
for rec in rows:
|
|
code = (rec.sample_code or "").strip()
|
|
if not code or code in out:
|
|
continue
|
|
out[code] = {
|
|
"acceptConclusion": (rec.accept_conclusion or "").strip(),
|
|
"remark": (rec.remark or "").strip(),
|
|
}
|
|
return out
|
|
|
|
|
|
def get_list_gate_qc_summary_map_by_reception_ids(
|
|
db: Session,
|
|
tenant_no: str,
|
|
reception_ids: List[str],
|
|
) -> Dict[str, Dict[str, str]]:
|
|
"""按 reception_id 批量返回样本接收触发的门禁质检摘要(工单号、状态、结论)。"""
|
|
ids = list({(i or "").strip() for i in reception_ids if (i or "").strip()})
|
|
if not tenant_no or not ids:
|
|
return {}
|
|
rows = (
|
|
db.query(BizQcWorkOrder)
|
|
.filter(
|
|
BizQcWorkOrder.tenant_no == tenant_no,
|
|
BizQcWorkOrder.del_flag == 0,
|
|
BizQcWorkOrder.trigger_source == "reception",
|
|
BizQcWorkOrder.reception_id.in_(ids),
|
|
)
|
|
.all()
|
|
)
|
|
summaries_by_wo_id = _build_gate_qc_summaries_for_work_orders(db, rows)
|
|
out: Dict[str, Dict[str, str]] = {}
|
|
for wo in rows:
|
|
rid = (wo.reception_id or "").strip()
|
|
wid = (wo.id or "").strip()
|
|
if not rid or rid in out or not wid:
|
|
continue
|
|
out[rid] = summaries_by_wo_id.get(wid) or _empty_gate_qc_summary_fields()
|
|
return out
|
|
|
|
|
|
def get_list_qc_conclusion_map_by_sample_codes(
|
|
db: Session,
|
|
tenant_no: str,
|
|
sample_codes: List[str],
|
|
*,
|
|
reception_source: str,
|
|
) -> Dict[str, Dict[str, str]]:
|
|
"""按租户 + 样本编码 + 来源返回门禁质检摘要(工单号、状态、结论)。"""
|
|
codes = list({(c or "").strip() for c in sample_codes if (c or "").strip()})
|
|
if not tenant_no or not codes or not (reception_source or "").strip():
|
|
return {}
|
|
rows = (
|
|
db.query(BizQcWorkOrder)
|
|
.filter(
|
|
BizQcWorkOrder.tenant_no == tenant_no,
|
|
BizQcWorkOrder.del_flag == 0,
|
|
BizQcWorkOrder.reception_source == reception_source,
|
|
BizQcWorkOrder.trigger_source == "reception",
|
|
BizQcWorkOrder.sample_code.in_(codes),
|
|
)
|
|
.all()
|
|
)
|
|
code_to_wo: Dict[str, BizQcWorkOrder] = {}
|
|
for wo in rows:
|
|
code = (wo.sample_code or "").strip()
|
|
if code and code not in code_to_wo:
|
|
code_to_wo[code] = wo
|
|
|
|
summaries_by_wo_id = _build_gate_qc_summaries_for_work_orders(db, list(code_to_wo.values()))
|
|
|
|
out: Dict[str, Dict[str, str]] = {}
|
|
for code, wo in code_to_wo.items():
|
|
wid = (wo.id or "").strip()
|
|
out[code] = summaries_by_wo_id.get(wid) or _empty_gate_qc_summary_fields()
|
|
return out
|
|
|
|
|
|
# 兼容旧调用名
|
|
def get_list_qc_status_map_by_sample_codes(
|
|
db: Session,
|
|
tenant_no: str,
|
|
sample_codes: List[str],
|
|
*,
|
|
reception_source: str,
|
|
) -> Dict[str, Dict[str, str]]:
|
|
return get_list_qc_conclusion_map_by_sample_codes(
|
|
db, tenant_no, sample_codes, reception_source=reception_source
|
|
)
|