|
|
@@ -33,6 +33,7 @@ _WORK_ORDER_STATUS_LABELS = {
|
|
|
"dpz": "待配置",
|
|
|
"jxz": "进行中",
|
|
|
"ywc": "已完成",
|
|
|
+ "yzf": "已作废",
|
|
|
}
|
|
|
_RECEPTION_SOURCE_LABELS = {
|
|
|
"cell_storage": "细胞存储",
|
|
|
@@ -100,6 +101,8 @@ def _wo_to_dict(wo: BizProductionWorkOrder) -> Dict[str, Any]:
|
|
|
getattr(wo, "reception_source", "cell_storage") or "cell_storage",
|
|
|
),
|
|
|
"infusionScheduleId": getattr(wo, "infusion_schedule_id", None) or None,
|
|
|
+ "bizType": getattr(wo, "biz_type", None) or None,
|
|
|
+ "bizTypeLabel": {"pilot_service": "中试服务", "clinical_application": "临床应用"}.get(getattr(wo, "biz_type", None) or "", ""),
|
|
|
"workOrderStatus": wo.work_order_status,
|
|
|
"workOrderStatusLabel": _WORK_ORDER_STATUS_LABELS.get(wo.work_order_status, wo.work_order_status),
|
|
|
"receptionTime": "",
|
|
|
@@ -117,6 +120,65 @@ def _enrich_wo_items(db: Session, items: List[Dict[str, Any]]) -> List[Dict[str,
|
|
|
return qc_wo_svc._enrich_work_order_list_items(db, items)
|
|
|
|
|
|
|
|
|
+_BIZ_TYPE_LABELS = {"pilot_service": "中试服务", "clinical_application": "临床应用"}
|
|
|
+
|
|
|
+
|
|
|
+def _enrich_outbound_items(db: Session, items: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
|
|
+ """为 outbound 类型工单附加申请单号、细胞类型、规格、输注时间等关联数据。"""
|
|
|
+ from app.models.models import (
|
|
|
+ BizPilotApplication,
|
|
|
+ BizPilotInfusionPlan,
|
|
|
+ BizPilotInfusionSchedule,
|
|
|
+ )
|
|
|
+
|
|
|
+ outbound_ids = [
|
|
|
+ it["infusionScheduleId"]
|
|
|
+ for it in items
|
|
|
+ if it.get("workOrderType") == "outbound" and it.get("infusionScheduleId")
|
|
|
+ ]
|
|
|
+ if not outbound_ids:
|
|
|
+ return items
|
|
|
+
|
|
|
+ schedules = (
|
|
|
+ db.query(BizPilotInfusionSchedule)
|
|
|
+ .filter(
|
|
|
+ BizPilotInfusionSchedule.id.in_(outbound_ids),
|
|
|
+ BizPilotInfusionSchedule.del_flag == 0,
|
|
|
+ )
|
|
|
+ .all()
|
|
|
+ )
|
|
|
+ sched_map = {s.id: s for s in schedules}
|
|
|
+
|
|
|
+ plan_ids = list({s.infusion_plan_id for s in schedules if s.infusion_plan_id})
|
|
|
+ plan_map = {}
|
|
|
+ if plan_ids:
|
|
|
+ plans = db.query(BizPilotInfusionPlan).filter(BizPilotInfusionPlan.id.in_(plan_ids)).all()
|
|
|
+ plan_map = {p.id: p for p in plans}
|
|
|
+
|
|
|
+ app_ids = list({p.pilot_application_id for p in plan_map.values() if p.pilot_application_id})
|
|
|
+ app_map = {}
|
|
|
+ if app_ids:
|
|
|
+ apps = db.query(BizPilotApplication).filter(BizPilotApplication.id.in_(app_ids)).all()
|
|
|
+ app_map = {a.id: a for a in apps}
|
|
|
+
|
|
|
+ for it in items:
|
|
|
+ if it.get("workOrderType") != "outbound" or not it.get("infusionScheduleId"):
|
|
|
+ continue
|
|
|
+ sched = sched_map.get(it["infusionScheduleId"])
|
|
|
+ if not sched:
|
|
|
+ continue
|
|
|
+ plan = plan_map.get(sched.infusion_plan_id) if sched.infusion_plan_id else None
|
|
|
+ app = app_map.get(plan.pilot_application_id) if plan and plan.pilot_application_id else None
|
|
|
+
|
|
|
+ it["applicationNo"] = app.application_no if app else ""
|
|
|
+ it["cellType"] = sched.cell_type or ""
|
|
|
+ it["specText"] = sched.spec_text or ""
|
|
|
+ it["infusionTime"] = _fmt_dt(sched.infusion_time) if sched.infusion_time else ""
|
|
|
+ it["infusionLocation"] = sched.infusion_location or ""
|
|
|
+
|
|
|
+ return items
|
|
|
+
|
|
|
+
|
|
|
def _reception_source_label(source: Optional[str]) -> str:
|
|
|
key = (source or "").strip() or "cell_storage"
|
|
|
return _RECEPTION_SOURCE_LABELS.get(key, key)
|
|
|
@@ -157,10 +219,54 @@ def _attach_reception_detail(
|
|
|
}
|
|
|
|
|
|
|
|
|
+def _attach_outbound_detail(
|
|
|
+ db: Session, wo: BizProductionWorkOrder, out: Dict[str, Any]
|
|
|
+) -> None:
|
|
|
+ """outbound 工单详情附加申请单 + 输注计划信息。"""
|
|
|
+ from app.models.models import (
|
|
|
+ BizPilotApplication,
|
|
|
+ BizPilotInfusionPlan,
|
|
|
+ BizPilotInfusionSchedule,
|
|
|
+ )
|
|
|
+
|
|
|
+ _APP_STATUS_LABELS = {"dks": "待开始", "jxz": "进行中", "ywc": "已完成", "yzf": "已作废"}
|
|
|
+
|
|
|
+ sched = (
|
|
|
+ db.query(BizPilotInfusionSchedule)
|
|
|
+ .filter(BizPilotInfusionSchedule.id == wo.infusion_schedule_id, BizPilotInfusionSchedule.del_flag == 0)
|
|
|
+ .first()
|
|
|
+ )
|
|
|
+ plan = None
|
|
|
+ app = None
|
|
|
+ if sched and sched.infusion_plan_id:
|
|
|
+ plan = db.query(BizPilotInfusionPlan).filter(BizPilotInfusionPlan.id == sched.infusion_plan_id).first()
|
|
|
+ if plan and plan.pilot_application_id:
|
|
|
+ app = db.query(BizPilotApplication).filter(BizPilotApplication.id == plan.pilot_application_id).first()
|
|
|
+
|
|
|
+ out["reception"] = {}
|
|
|
+ out["pilotApplication"] = {
|
|
|
+ "applicationNo": app.application_no if app else "",
|
|
|
+ "applicationName": app.application_name if app else "",
|
|
|
+ "applicationStatus": app.application_status if app else "",
|
|
|
+ "applicationStatusLabel": _APP_STATUS_LABELS.get(app.application_status, "") if app else "",
|
|
|
+ } if app else {}
|
|
|
+ out["infusionSchedule"] = {
|
|
|
+ "cellType": sched.cell_type if sched else "",
|
|
|
+ "specText": sched.spec_text if sched else "",
|
|
|
+ "infusionTime": _fmt_dt(sched.infusion_time) if sched and sched.infusion_time else "",
|
|
|
+ "infusionLocation": sched.infusion_location if sched else "",
|
|
|
+ "infusionMethod": sched.infusion_method if sched else "",
|
|
|
+ "scheduleStatus": sched.schedule_status if sched else "",
|
|
|
+ } if sched else {}
|
|
|
+
|
|
|
+
|
|
|
def _wo_to_response_dict(db: Session, wo: BizProductionWorkOrder) -> Dict[str, Any]:
|
|
|
"""工单响应(含接收记录关联的样本类型、接收人、接收时间及 reception 详情)。"""
|
|
|
out = _enrich_wo_items(db, [_wo_to_dict(wo)])[0]
|
|
|
- _attach_reception_detail(db, wo, out, wo.tenant_no or "")
|
|
|
+ if wo.work_order_type == "outbound" and wo.infusion_schedule_id:
|
|
|
+ _attach_outbound_detail(db, wo, out)
|
|
|
+ else:
|
|
|
+ _attach_reception_detail(db, wo, out, wo.tenant_no or "")
|
|
|
return out
|
|
|
|
|
|
|
|
|
@@ -341,6 +447,7 @@ def list_production_work_orders(
|
|
|
.all()
|
|
|
)
|
|
|
items = _enrich_wo_items(db, [_wo_to_dict(x) for x in rows])
|
|
|
+ items = _enrich_outbound_items(db, items)
|
|
|
return {"items": items, "total": int(total)}
|
|
|
|
|
|
|
|
|
@@ -643,6 +750,7 @@ def create_outbound_production_work_order(
|
|
|
user_id: Optional[str] = None,
|
|
|
create_dept_id: str = "",
|
|
|
remark: str = "",
|
|
|
+ biz_type: str = "pilot_service",
|
|
|
) -> BizProductionWorkOrder:
|
|
|
existing = (
|
|
|
db.query(BizProductionWorkOrder)
|
|
|
@@ -666,6 +774,7 @@ def create_outbound_production_work_order(
|
|
|
sample_code=None,
|
|
|
reception_source="outbound",
|
|
|
infusion_schedule_id=schedule_id,
|
|
|
+ biz_type=biz_type,
|
|
|
work_order_status="dpz",
|
|
|
tenant_no=tenant_no,
|
|
|
remark=remark,
|