214 lines
6.0 KiB
Python
214 lines
6.0 KiB
Python
"""中试服务出库生产/质检工单与输注计划生产状态、质检状态双向联动。"""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.models.models import (
|
|
BizPilotInfusionSchedule,
|
|
BizProductionWorkOrder,
|
|
BizQcWorkOrder,
|
|
)
|
|
|
|
|
|
def _is_pilot_outbound_production(wo: BizProductionWorkOrder) -> bool:
|
|
return (
|
|
(getattr(wo, "work_order_type", None) or "") == "outbound"
|
|
and (getattr(wo, "biz_type", None) or "") == "pilot_service"
|
|
and bool(getattr(wo, "infusion_schedule_id", None))
|
|
)
|
|
|
|
|
|
def _is_pilot_outbound_qc(wo: BizQcWorkOrder) -> bool:
|
|
return (
|
|
(getattr(wo, "work_order_type", None) or "") == "outbound"
|
|
and (getattr(wo, "biz_type", None) or "") == "pilot_service"
|
|
and bool(getattr(wo, "infusion_schedule_id", None))
|
|
)
|
|
|
|
|
|
def _get_schedule(
|
|
db: Session, schedule_id: str, tenant_no: str
|
|
) -> Optional[BizPilotInfusionSchedule]:
|
|
if not (schedule_id or "").strip():
|
|
return None
|
|
return (
|
|
db.query(BizPilotInfusionSchedule)
|
|
.filter(
|
|
BizPilotInfusionSchedule.id == schedule_id.strip(),
|
|
BizPilotInfusionSchedule.tenant_no == tenant_no,
|
|
BizPilotInfusionSchedule.del_flag == 0,
|
|
)
|
|
.first()
|
|
)
|
|
|
|
|
|
def _touch(row, user_id: Optional[str]) -> None:
|
|
now = datetime.now()
|
|
if user_id:
|
|
row.update_by = user_id
|
|
row.update_time = now
|
|
|
|
|
|
def sync_schedule_from_production_work_order(
|
|
db: Session,
|
|
wo: BizProductionWorkOrder,
|
|
*,
|
|
user_id: Optional[str] = None,
|
|
) -> None:
|
|
"""出库生产工单状态 → 输注计划 schedule_status。"""
|
|
if not _is_pilot_outbound_production(wo):
|
|
return
|
|
sched = _get_schedule(db, wo.infusion_schedule_id or "", wo.tenant_no or "")
|
|
if not sched:
|
|
return
|
|
|
|
wo_status = (wo.work_order_status or "").strip()
|
|
current = (sched.schedule_status or "").strip()
|
|
new_status: Optional[str] = None
|
|
|
|
if wo_status in ("dpz", "jxz"):
|
|
if current not in ("ysc", "yjf", "yqx"):
|
|
new_status = "dsc"
|
|
elif wo_status == "ywc":
|
|
if current not in ("yjf", "yqx"):
|
|
new_status = "ysc"
|
|
elif wo_status == "yzf":
|
|
new_status = "yqx"
|
|
|
|
if new_status and new_status != current:
|
|
sched.schedule_status = new_status
|
|
_touch(sched, user_id)
|
|
db.add(sched)
|
|
|
|
|
|
def sync_schedule_from_qc_work_order(
|
|
db: Session,
|
|
wo: BizQcWorkOrder,
|
|
*,
|
|
user_id: Optional[str] = None,
|
|
) -> None:
|
|
"""出库质检工单状态 → 输注计划 qc_status。"""
|
|
if not _is_pilot_outbound_qc(wo):
|
|
return
|
|
sched = _get_schedule(db, wo.infusion_schedule_id or "", wo.tenant_no or "")
|
|
if not sched:
|
|
return
|
|
|
|
wo_status = (wo.work_order_status or "").strip()
|
|
current = (sched.qc_status or "").strip()
|
|
new_status: Optional[str] = None
|
|
|
|
if wo_status in ("dpz", "ypz"):
|
|
if current not in ("yzj", "yqx"):
|
|
new_status = "dzc"
|
|
elif wo_status == "ywc":
|
|
if current != "yqx":
|
|
new_status = "yzj"
|
|
elif wo_status == "yzf":
|
|
new_status = "yqx"
|
|
|
|
if new_status and new_status != current:
|
|
sched.qc_status = new_status
|
|
_touch(sched, user_id)
|
|
db.add(sched)
|
|
|
|
|
|
def sync_production_work_order_from_schedule(
|
|
db: Session,
|
|
schedule: BizPilotInfusionSchedule,
|
|
*,
|
|
user_id: Optional[str] = None,
|
|
) -> None:
|
|
"""输注计划 schedule_status → 出库生产工单状态。"""
|
|
schedule_id = schedule.id or ""
|
|
tenant_no = schedule.tenant_no or ""
|
|
if not schedule_id:
|
|
return
|
|
|
|
wo = (
|
|
db.query(BizProductionWorkOrder)
|
|
.filter(
|
|
BizProductionWorkOrder.infusion_schedule_id == schedule_id,
|
|
BizProductionWorkOrder.tenant_no == tenant_no,
|
|
BizProductionWorkOrder.del_flag == 0,
|
|
BizProductionWorkOrder.work_order_type == "outbound",
|
|
BizProductionWorkOrder.biz_type == "pilot_service",
|
|
)
|
|
.first()
|
|
)
|
|
if not wo:
|
|
return
|
|
|
|
sched_status = (schedule.schedule_status or "").strip()
|
|
current = (wo.work_order_status or "").strip()
|
|
new_status: Optional[str] = None
|
|
|
|
if sched_status in ("ysc", "yjf"):
|
|
if current not in ("ywc", "yzf"):
|
|
new_status = "ywc"
|
|
elif sched_status == "yqx":
|
|
if current != "ywc":
|
|
new_status = "yzf"
|
|
|
|
if new_status and new_status != current:
|
|
wo.work_order_status = new_status
|
|
_touch(wo, user_id)
|
|
db.add(wo)
|
|
|
|
|
|
def sync_qc_work_order_from_schedule(
|
|
db: Session,
|
|
schedule: BizPilotInfusionSchedule,
|
|
*,
|
|
user_id: Optional[str] = None,
|
|
) -> None:
|
|
"""输注计划 qc_status → 出库质检工单状态。"""
|
|
schedule_id = schedule.id or ""
|
|
tenant_no = schedule.tenant_no or ""
|
|
if not schedule_id:
|
|
return
|
|
|
|
wo = (
|
|
db.query(BizQcWorkOrder)
|
|
.filter(
|
|
BizQcWorkOrder.infusion_schedule_id == schedule_id,
|
|
BizQcWorkOrder.tenant_no == tenant_no,
|
|
BizQcWorkOrder.del_flag == 0,
|
|
BizQcWorkOrder.work_order_type == "outbound",
|
|
BizQcWorkOrder.biz_type == "pilot_service",
|
|
)
|
|
.first()
|
|
)
|
|
if not wo:
|
|
return
|
|
|
|
qc_status = (schedule.qc_status or "").strip()
|
|
current = (wo.work_order_status or "").strip()
|
|
new_status: Optional[str] = None
|
|
|
|
if qc_status == "yzj":
|
|
if current not in ("ywc", "yzf"):
|
|
new_status = "ywc"
|
|
elif qc_status == "yqx":
|
|
if current != "ywc":
|
|
new_status = "yzf"
|
|
|
|
if new_status and new_status != current:
|
|
wo.work_order_status = new_status
|
|
_touch(wo, user_id)
|
|
db.add(wo)
|
|
|
|
|
|
def sync_pilot_outbound_from_schedule(
|
|
db: Session,
|
|
schedule: BizPilotInfusionSchedule,
|
|
*,
|
|
user_id: Optional[str] = None,
|
|
) -> None:
|
|
"""输注计划状态变更后,回写关联出库工单。"""
|
|
sync_production_work_order_from_schedule(db, schedule, user_id=user_id)
|
|
sync_qc_work_order_from_schedule(db, schedule, user_id=user_id)
|