| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693 |
- """工艺路线 CRUD(biz_process_route + biz_process_route_step + 4张步骤子表)"""
- from __future__ import annotations
- import math
- from datetime import datetime
- from typing import Any, Dict, List, Optional, Tuple
- from sqlalchemy import and_, func, or_
- from sqlalchemy.orm import Session
- from app.core.utils import generate_uuid
- from app.crud.equipment_snapshot import parse_equipment_ids, resolve_equipment_list_snapshot
- from app.models.models import (
- BizProductionProductType,
- BizProcess,
- BizProcessReagent,
- BizProcessConsumable,
- BizProcessOutput,
- BizProcessDataCollection,
- BizProcessRoute,
- BizProcessRouteStep,
- BizProcessRouteStepReagent,
- BizProcessRouteStepConsumable,
- BizProcessRouteStepOutput,
- BizProcessRouteStepDataCollection,
- )
- # ---------------------------------------------------------------------------
- # 序列化函数
- # ---------------------------------------------------------------------------
- def _route_row_to_dict(r: BizProcessRoute) -> Dict[str, Any]:
- return {
- "id": r.id,
- "routeCode": r.route_code,
- "routeName": r.route_name,
- "productTypeId": r.product_type_id or "",
- "version": r.version or "",
- "isCurrent": r.is_current if r.is_current is not None else "0",
- "equipmentIds": parse_equipment_ids(getattr(r, "equipment_ids", None)),
- "equipmentName": getattr(r, "equipment_name", None) or "",
- "tenantNo": r.tenant_no,
- "orderNum": r.order_num if r.order_num is not None else 0,
- "remark": r.remark or "",
- "isBuiltin": getattr(r, "is_builtin", None) or "0",
- "createTime": r.create_time.strftime("%Y-%m-%d %H:%M:%S") if r.create_time else "",
- "updateTime": r.update_time.strftime("%Y-%m-%d %H:%M:%S") if r.update_time else "",
- }
- def _step_row_to_dict(s: BizProcessRouteStep) -> Dict[str, Any]:
- return {
- "id": s.id,
- "routeId": s.route_id,
- "processId": s.process_id or "",
- "stepOrder": s.step_order if s.step_order is not None else 0,
- "processCode": s.process_code or "",
- "categoryId": s.category_id or "",
- "processName": s.process_name or "",
- "description": s.description or "",
- "estimatedDuration": s.estimated_duration or "",
- "sopIds": s.sop_ids or "",
- "sopContent": s.sop_content or "",
- "remark": s.remark or "",
- }
- def _step_reagent_row_to_dict(r: BizProcessRouteStepReagent) -> Dict[str, Any]:
- return {
- "id": r.id,
- "stepId": r.step_id,
- "reagentCode": r.reagent_code or "",
- "reagentName": r.reagent_name or "",
- "spec": r.spec or "",
- "standardUsage": r.standard_usage or "",
- "unit": r.unit or "",
- "isKeyMaterial": r.is_key_material if r.is_key_material is not None else "0",
- "orderNum": r.order_num if r.order_num is not None else 0,
- "remark": r.remark or "",
- }
- def _step_consumable_row_to_dict(c: BizProcessRouteStepConsumable) -> Dict[str, Any]:
- return {
- "id": c.id,
- "stepId": c.step_id,
- "consumableCode": c.consumable_code or "",
- "consumableName": c.consumable_name or "",
- "specModel": c.spec_model or "",
- "standardUsage": c.standard_usage or "",
- "unit": c.unit or "",
- "isRequired": c.is_required if c.is_required is not None else "1",
- "orderNum": c.order_num if c.order_num is not None else 0,
- "remark": c.remark or "",
- }
- def _step_output_row_to_dict(o: BizProcessRouteStepOutput) -> Dict[str, Any]:
- return {
- "id": o.id,
- "stepId": o.step_id,
- "outputTypeId": o.output_type_id or "",
- "outputName": o.output_name or "",
- "outputBarcode": o.output_barcode or "",
- "orderNum": o.order_num if o.order_num is not None else 0,
- "remark": o.remark or "",
- }
- def _step_data_collection_row_to_dict(d: BizProcessRouteStepDataCollection) -> Dict[str, Any]:
- return {
- "id": d.id,
- "stepId": d.step_id,
- "collectionName": d.collection_name or "",
- "unit": d.unit or "",
- "orderNum": d.order_num if d.order_num is not None else 0,
- "remark": d.remark or "",
- }
- # ---------------------------------------------------------------------------
- # 路线主表 CRUD
- # ---------------------------------------------------------------------------
- def list_routes(db: Session, *, page: int = 1, page_size: int = 10,
- route_name: Optional[str] = None, route_code: Optional[str] = None,
- product_type_id: Optional[str] = None,
- tenant_no: Optional[str] = None,
- user_info=None) -> Tuple[List[Dict], int]:
- def _filtered():
- q = db.query(BizProcessRoute).filter(BizProcessRoute.del_flag == 0)
- if tenant_no:
- q = q.filter(BizProcessRoute.tenant_no == tenant_no)
- if route_name and route_name.strip():
- q = q.filter(BizProcessRoute.route_name.like(f"%{route_name.strip()}%"))
- if route_code and route_code.strip():
- q = q.filter(BizProcessRoute.route_code == route_code.strip())
- if product_type_id and product_type_id.strip():
- q = q.filter(BizProcessRoute.product_type_id == product_type_id.strip())
- if user_info:
- from app.core.data_scope import apply_data_scope
- q = apply_data_scope(q, BizProcessRoute, user_info, db, tenant_no)
- return q
- total = _filtered().order_by(None).with_entities(func.count(BizProcessRoute.id)).scalar() or 0
- page = max(1, page)
- page_size = min(max(1, page_size), 100)
- rows = (
- _filtered()
- .outerjoin(
- BizProductionProductType,
- and_(
- BizProcessRoute.product_type_id == BizProductionProductType.id,
- BizProductionProductType.del_flag == 0,
- ),
- )
- .order_by(
- BizProductionProductType.product_type_name.is_(None),
- BizProductionProductType.product_type_name.asc(),
- BizProcessRoute.create_time.desc(),
- )
- .offset((page - 1) * page_size)
- .limit(page_size)
- .all()
- )
- return [_route_row_to_dict(x) for x in rows], int(total)
- def get_route(db: Session, route_id: str) -> Optional[BizProcessRoute]:
- return db.query(BizProcessRoute).filter(
- and_(BizProcessRoute.id == route_id, BizProcessRoute.del_flag == 0)
- ).first()
- def get_step(db: Session, step_id: str) -> Optional[BizProcessRouteStep]:
- return db.query(BizProcessRouteStep).filter(
- and_(BizProcessRouteStep.id == step_id, BizProcessRouteStep.del_flag == 0)
- ).first()
- def is_super_admin_user(user: Optional[Dict[str, Any]]) -> bool:
- return bool(user) and (user.get("role") or "") == "super_admin"
- def assert_route_writable(
- db: Session, route_id: str, user: Optional[Dict[str, Any]] = None
- ) -> BizProcessRoute:
- """内置模版仅超级管理员可写;返回路线对象。"""
- route = get_route(db, route_id)
- if not route:
- raise ValueError("路线不存在")
- if (getattr(route, "is_builtin", None) or "0") == "1" and not is_super_admin_user(user):
- raise ValueError("内置模版仅超级管理员可修改")
- return route
- def assert_step_route_writable(
- db: Session, step_id: str, user: Optional[Dict[str, Any]] = None
- ) -> BizProcessRouteStep:
- step = get_step(db, step_id)
- if not step:
- raise ValueError("步骤不存在")
- assert_route_writable(db, step.route_id, user)
- return step
- def get_route_detail(db: Session, route_id: str) -> Optional[Dict[str, Any]]:
- route = get_route(db, route_id)
- if not route:
- return None
- result = _route_row_to_dict(route)
- steps = (
- db.query(BizProcessRouteStep)
- .filter(and_(BizProcessRouteStep.route_id == route_id, BizProcessRouteStep.del_flag == 0))
- .order_by(BizProcessRouteStep.step_order.asc(), BizProcessRouteStep.create_time.asc())
- .all()
- )
- step_list = []
- for s in steps:
- sd = _step_row_to_dict(s)
- reagents = db.query(BizProcessRouteStepReagent).filter(
- and_(BizProcessRouteStepReagent.step_id == s.id, BizProcessRouteStepReagent.del_flag == 0)
- ).order_by(BizProcessRouteStepReagent.order_num.asc(), BizProcessRouteStepReagent.create_time.asc()).all()
- consumables = db.query(BizProcessRouteStepConsumable).filter(
- and_(BizProcessRouteStepConsumable.step_id == s.id, BizProcessRouteStepConsumable.del_flag == 0)
- ).order_by(BizProcessRouteStepConsumable.order_num.asc(), BizProcessRouteStepConsumable.create_time.asc()).all()
- outputs = db.query(BizProcessRouteStepOutput).filter(
- and_(BizProcessRouteStepOutput.step_id == s.id, BizProcessRouteStepOutput.del_flag == 0)
- ).order_by(BizProcessRouteStepOutput.order_num.asc(), BizProcessRouteStepOutput.create_time.asc()).all()
- data_collections = db.query(BizProcessRouteStepDataCollection).filter(
- and_(BizProcessRouteStepDataCollection.step_id == s.id, BizProcessRouteStepDataCollection.del_flag == 0)
- ).order_by(BizProcessRouteStepDataCollection.order_num.asc(), BizProcessRouteStepDataCollection.create_time.asc()).all()
- sd["reagents"] = [_step_reagent_row_to_dict(r) for r in reagents]
- sd["consumables"] = [_step_consumable_row_to_dict(c) for c in consumables]
- sd["outputs"] = [_step_output_row_to_dict(o) for o in outputs]
- sd["dataCollections"] = [_step_data_collection_row_to_dict(d) for d in data_collections]
- step_list.append(sd)
- result["steps"] = step_list
- return result
- def create_route(db: Session, *, route_code: str, route_name: str,
- product_type_id: Optional[str] = None, version: Optional[str] = None,
- remark: Optional[str] = None, tenant_no: str = "zkxw",
- user_id: Optional[str] = None) -> BizProcessRoute:
- rc = (route_code or "").strip()
- if not rc:
- raise ValueError("路线编码不能为空")
- now = datetime.now()
- obj = BizProcessRoute(
- id=generate_uuid(),
- route_code=rc,
- route_name=(route_name or "").strip() or rc,
- product_type_id=(product_type_id or "").strip() or None,
- version=(version or "").strip() or None,
- is_current="0",
- tenant_no=tenant_no,
- order_num=0,
- remark=(remark or "").strip() or None,
- is_builtin="0",
- create_by=user_id,
- create_dept_id="",
- create_time=now,
- update_by=user_id,
- update_time=now,
- del_flag=0,
- )
- db.add(obj)
- db.commit()
- db.refresh(obj)
- return obj
- def update_route(db: Session, route_id: str, *, user_id: Optional[str] = None, **kwargs) -> BizProcessRoute:
- obj = get_route(db, route_id)
- if not obj:
- raise ValueError("路线不存在")
- for field in ["route_code", "route_name", "product_type_id", "version", "remark"]:
- val = kwargs.get(field)
- if val is not None:
- setattr(obj, field, (val or "").strip() or None if field != "route_code" else (val or "").strip())
- if "equipment_ids" in kwargs:
- eids, enames = resolve_equipment_list_snapshot(
- db, kwargs.get("equipment_ids"), obj.tenant_no or "zkxw"
- )
- obj.equipment_ids = eids
- obj.equipment_name = enames
- obj.update_by = user_id
- obj.update_time = datetime.now()
- db.add(obj)
- db.commit()
- db.refresh(obj)
- return obj
- def set_current_route(db: Session, route_id: str, tenant_no: str) -> BizProcessRoute:
- obj = get_route(db, route_id)
- if not obj:
- raise ValueError("路线不存在")
- now = datetime.now()
- siblings = db.query(BizProcessRoute).filter(
- and_(BizProcessRoute.route_code == obj.route_code,
- BizProcessRoute.tenant_no == tenant_no,
- BizProcessRoute.del_flag == 0)
- ).all()
- for s in siblings:
- s.is_current = "0"
- s.update_time = now
- db.add(s)
- obj.is_current = "1"
- obj.update_time = now
- db.add(obj)
- db.commit()
- db.refresh(obj)
- return obj
- # ---------------------------------------------------------------------------
- # 步骤子表辅助
- # ---------------------------------------------------------------------------
- def _soft_delete_sub_records(db: Session, model_class, step_id: str, now: datetime) -> None:
- rows = db.query(model_class).filter(
- and_(model_class.step_id == step_id, model_class.del_flag == 0)
- ).all()
- for r in rows:
- r.del_flag = 1
- r.update_time = now
- db.add(r)
- def _create_step_reagent(db, step_id, tenant_no, user_id, now, data):
- db.add(BizProcessRouteStepReagent(
- id=generate_uuid(), step_id=step_id, tenant_no=tenant_no,
- reagent_code=(data.get("reagent_code") or "").strip() or None,
- reagent_name=(data.get("reagent_name") or "").strip() or None,
- spec=(data.get("spec") or "").strip() or None,
- standard_usage=(data.get("standard_usage") or "").strip() or None,
- unit=(data.get("unit") or "").strip() or None,
- is_key_material=data.get("is_key_material", "0"),
- remark=(data.get("remark") or "").strip() or None,
- order_num=data.get("order_num", 0) or 0,
- create_by=user_id, create_dept_id="",
- create_time=now, update_by=user_id, update_time=now, del_flag=0,
- ))
- def _create_step_consumable(db, step_id, tenant_no, user_id, now, data):
- db.add(BizProcessRouteStepConsumable(
- id=generate_uuid(), step_id=step_id, tenant_no=tenant_no,
- consumable_code=(data.get("consumable_code") or "").strip() or None,
- consumable_name=(data.get("consumable_name") or "").strip() or None,
- spec_model=(data.get("spec_model") or "").strip() or None,
- standard_usage=(data.get("standard_usage") or "").strip() or None,
- unit=(data.get("unit") or "").strip() or None,
- is_required=data.get("is_required", "1"),
- remark=(data.get("remark") or "").strip() or None,
- order_num=data.get("order_num", 0) or 0,
- create_by=user_id, create_dept_id="",
- create_time=now, update_by=user_id, update_time=now, del_flag=0,
- ))
- def _create_step_output(db, step_id, tenant_no, user_id, now, data):
- db.add(BizProcessRouteStepOutput(
- id=generate_uuid(), step_id=step_id, tenant_no=tenant_no,
- output_type_id=(data.get("output_type_id") or "").strip() or None,
- output_name=(data.get("output_name") or "").strip() or None,
- output_barcode=(data.get("output_barcode") or "").strip() or None,
- remark=(data.get("remark") or "").strip() or None,
- order_num=data.get("order_num", 0) or 0,
- create_by=user_id, create_dept_id="",
- create_time=now, update_by=user_id, update_time=now, del_flag=0,
- ))
- def _create_step_data_collection(db, step_id, tenant_no, user_id, now, data):
- db.add(BizProcessRouteStepDataCollection(
- id=generate_uuid(), step_id=step_id, tenant_no=tenant_no,
- collection_name=(data.get("collection_name") or "").strip() or None,
- unit=(data.get("unit") or "").strip() or None,
- order_num=data.get("order_num", 0) or 0,
- remark=(data.get("remark") or "").strip() or None,
- create_by=user_id, create_dept_id="",
- create_time=now, update_by=user_id, update_time=now, del_flag=0,
- ))
- # ---------------------------------------------------------------------------
- # 步骤 CRUD
- # ---------------------------------------------------------------------------
- def add_step(db: Session, *, route_id: str, process_id: str, step_order: Optional[int] = None,
- tenant_no: str = "zkxw", user_id: Optional[str] = None) -> Dict[str, Any]:
- route = get_route(db, route_id)
- if not route:
- raise ValueError("路线不存在")
- proc = db.query(BizProcess).filter(
- and_(BizProcess.id == process_id, BizProcess.del_flag == 0)
- ).first()
- if not proc:
- raise ValueError("工艺不存在")
- now = datetime.now()
- if step_order is None:
- max_order = db.query(func.max(BizProcessRouteStep.step_order)).filter(
- and_(BizProcessRouteStep.route_id == route_id, BizProcessRouteStep.del_flag == 0)
- ).scalar()
- step_order = (max_order or 0) + 1
- step = BizProcessRouteStep(
- id=generate_uuid(), route_id=route_id, process_id=process_id,
- step_order=step_order,
- process_code=proc.process_code, category_id=proc.category_id,
- process_name=proc.process_name, description=proc.description,
- estimated_duration=proc.estimated_duration,
- sop_ids=proc.sop_ids,
- sop_content=proc.sop_content,
- tenant_no=tenant_no, order_num=0,
- remark=None, create_by=user_id, create_dept_id="",
- create_time=now, update_by=user_id, update_time=now, del_flag=0,
- )
- db.add(step)
- db.flush()
- src_reagents = db.query(BizProcessReagent).filter(
- and_(BizProcessReagent.process_id == process_id, BizProcessReagent.del_flag == 0)
- ).all()
- for r in src_reagents:
- _create_step_reagent(db, step.id, tenant_no, user_id, now, {
- "reagent_code": r.reagent_code, "reagent_name": r.reagent_name,
- "spec": r.spec, "standard_usage": r.standard_usage,
- "unit": r.unit, "is_key_material": r.is_key_material,
- })
- src_consumables = db.query(BizProcessConsumable).filter(
- and_(BizProcessConsumable.process_id == process_id, BizProcessConsumable.del_flag == 0)
- ).all()
- for c in src_consumables:
- _create_step_consumable(db, step.id, tenant_no, user_id, now, {
- "consumable_code": c.consumable_code, "consumable_name": c.consumable_name,
- "spec_model": c.spec_model, "standard_usage": c.standard_usage,
- "unit": c.unit, "is_required": c.is_required, "remark": c.remark,
- })
- src_outputs = db.query(BizProcessOutput).filter(
- and_(BizProcessOutput.process_id == process_id, BizProcessOutput.del_flag == 0)
- ).all()
- for o in src_outputs:
- _create_step_output(db, step.id, tenant_no, user_id, now, {
- "output_type_id": o.output_type_id, "output_name": o.output_name,
- "output_barcode": o.output_barcode,
- })
- src_collections = db.query(BizProcessDataCollection).filter(
- and_(BizProcessDataCollection.process_id == process_id, BizProcessDataCollection.del_flag == 0)
- ).all()
- for d in src_collections:
- _create_step_data_collection(db, step.id, tenant_no, user_id, now, {
- "collection_name": d.collection_name, "unit": d.unit, "order_num": d.order_num,
- })
- db.commit()
- detail = get_route_detail(db, route_id)
- return detail["steps"][-1] if detail and detail["steps"] else _step_row_to_dict(step)
- def update_step(db: Session, step_id: str, *, user_id: Optional[str] = None, **kwargs) -> BizProcessRouteStep:
- step = db.query(BizProcessRouteStep).filter(
- and_(BizProcessRouteStep.id == step_id, BizProcessRouteStep.del_flag == 0)
- ).first()
- if not step:
- raise ValueError("步骤不存在")
- for field in ["process_code", "category_id", "process_name", "description",
- "estimated_duration", "sop_ids", "sop_content"]:
- val = kwargs.get(field)
- if val is not None:
- if field == "sop_content":
- setattr(step, field, val if str(val).strip() else None)
- else:
- setattr(step, field, (val or "").strip() or None)
- step.update_by = user_id
- step.update_time = datetime.now()
- db.add(step)
- db.commit()
- db.refresh(step)
- return step
- def reorder_steps(db: Session, route_id: str, step_ids: List[str]) -> None:
- now = datetime.now()
- for idx, sid in enumerate(step_ids):
- step = db.query(BizProcessRouteStep).filter(
- and_(BizProcessRouteStep.id == sid, BizProcessRouteStep.route_id == route_id,
- BizProcessRouteStep.del_flag == 0)
- ).first()
- if step:
- step.step_order = idx + 1
- step.update_time = now
- db.add(step)
- db.commit()
- def copy_step(db: Session, step_id: str, *, tenant_no: str = "zkxw",
- user_id: Optional[str] = None) -> Dict[str, Any]:
- """复制步骤,插入到原步骤之后,名称追加(复制)"""
- src = db.query(BizProcessRouteStep).filter(
- and_(BizProcessRouteStep.id == step_id, BizProcessRouteStep.del_flag == 0)
- ).first()
- if not src:
- raise ValueError("步骤不存在")
- now = datetime.now()
- new_order = src.step_order + 1
- # 后续步骤 step_order +1
- later_steps = db.query(BizProcessRouteStep).filter(
- and_(
- BizProcessRouteStep.route_id == src.route_id,
- BizProcessRouteStep.del_flag == 0,
- BizProcessRouteStep.step_order > src.step_order,
- )
- ).order_by(BizProcessRouteStep.step_order.asc()).all()
- for ls in later_steps:
- ls.step_order += 1
- ls.update_time = now
- db.add(ls)
- # 创建新步骤
- new_name = (src.process_name or "").strip()
- if not new_name.endswith("(复制)"):
- new_name += "(复制)"
- new_step = BizProcessRouteStep(
- id=generate_uuid(), route_id=src.route_id, process_id=src.process_id,
- step_order=new_order,
- process_code=src.process_code, category_id=src.category_id,
- process_name=new_name, description=src.description,
- estimated_duration=src.estimated_duration,
- sop_ids=src.sop_ids,
- sop_content=src.sop_content,
- tenant_no=tenant_no, order_num=0,
- remark=src.remark, create_by=user_id, create_dept_id="",
- create_time=now, update_by=user_id, update_time=now, del_flag=0,
- )
- db.add(new_step)
- db.flush()
- # 复制子表:试剂
- for r in db.query(BizProcessRouteStepReagent).filter(
- and_(BizProcessRouteStepReagent.step_id == step_id, BizProcessRouteStepReagent.del_flag == 0)
- ).order_by(
- BizProcessRouteStepReagent.order_num.asc(),
- BizProcessRouteStepReagent.create_time.asc(),
- ).all():
- _create_step_reagent(db, new_step.id, tenant_no, user_id, now, {
- "reagent_code": r.reagent_code, "reagent_name": r.reagent_name,
- "spec": r.spec, "standard_usage": r.standard_usage,
- "unit": r.unit, "is_key_material": r.is_key_material,
- "order_num": r.order_num,
- "remark": r.remark,
- })
- # 复制子表:耗材
- for c in db.query(BizProcessRouteStepConsumable).filter(
- and_(BizProcessRouteStepConsumable.step_id == step_id, BizProcessRouteStepConsumable.del_flag == 0)
- ).order_by(
- BizProcessRouteStepConsumable.order_num.asc(),
- BizProcessRouteStepConsumable.create_time.asc(),
- ).all():
- _create_step_consumable(db, new_step.id, tenant_no, user_id, now, {
- "consumable_code": c.consumable_code, "consumable_name": c.consumable_name,
- "spec_model": c.spec_model, "standard_usage": c.standard_usage,
- "unit": c.unit, "is_required": c.is_required,
- "order_num": c.order_num,
- "remark": c.remark,
- })
- # 复制子表:产出
- for o in db.query(BizProcessRouteStepOutput).filter(
- and_(BizProcessRouteStepOutput.step_id == step_id, BizProcessRouteStepOutput.del_flag == 0)
- ).order_by(
- BizProcessRouteStepOutput.order_num.asc(),
- BizProcessRouteStepOutput.create_time.asc(),
- ).all():
- _create_step_output(db, new_step.id, tenant_no, user_id, now, {
- "output_type_id": o.output_type_id, "output_name": o.output_name,
- "output_barcode": o.output_barcode,
- "order_num": o.order_num,
- "remark": o.remark,
- })
- # 复制子表:数据采集
- for d in db.query(BizProcessRouteStepDataCollection).filter(
- and_(BizProcessRouteStepDataCollection.step_id == step_id, BizProcessRouteStepDataCollection.del_flag == 0)
- ).order_by(
- BizProcessRouteStepDataCollection.order_num.asc(),
- BizProcessRouteStepDataCollection.create_time.asc(),
- ).all():
- _create_step_data_collection(db, new_step.id, tenant_no, user_id, now, {
- "collection_name": d.collection_name, "unit": d.unit,
- "order_num": d.order_num, "remark": d.remark,
- })
- db.commit()
- detail = get_route_detail(db, src.route_id)
- return detail["steps"][-1] if detail and detail["steps"] else _step_row_to_dict(new_step)
- def soft_delete_step(db: Session, step_id: str) -> None:
- step = db.query(BizProcessRouteStep).filter(
- and_(BizProcessRouteStep.id == step_id, BizProcessRouteStep.del_flag == 0)
- ).first()
- if not step:
- raise ValueError("步骤不存在")
- now = datetime.now()
- step.del_flag = 1
- step.update_time = now
- db.add(step)
- _soft_delete_sub_records(db, BizProcessRouteStepReagent, step_id, now)
- _soft_delete_sub_records(db, BizProcessRouteStepConsumable, step_id, now)
- _soft_delete_sub_records(db, BizProcessRouteStepOutput, step_id, now)
- _soft_delete_sub_records(db, BizProcessRouteStepDataCollection, step_id, now)
- db.commit()
- def soft_delete_route(db: Session, route_id: str) -> None:
- route = get_route(db, route_id)
- if not route:
- raise ValueError("路线不存在")
- now = datetime.now()
- route.del_flag = 1
- route.update_time = now
- db.add(route)
- steps = db.query(BizProcessRouteStep).filter(
- and_(BizProcessRouteStep.route_id == route_id, BizProcessRouteStep.del_flag == 0)
- ).all()
- for s in steps:
- s.del_flag = 1
- s.update_time = now
- db.add(s)
- _soft_delete_sub_records(db, BizProcessRouteStepReagent, s.id, now)
- _soft_delete_sub_records(db, BizProcessRouteStepConsumable, s.id, now)
- _soft_delete_sub_records(db, BizProcessRouteStepOutput, s.id, now)
- _soft_delete_sub_records(db, BizProcessRouteStepDataCollection, s.id, now)
- db.commit()
- # ---------------------------------------------------------------------------
- # 子表完整替换更新
- # ---------------------------------------------------------------------------
- def update_step_reagents(db: Session, step_id: str, items: List[Dict], tenant_no: str, user_id: Optional[str] = None):
- now = datetime.now()
- _soft_delete_sub_records(db, BizProcessRouteStepReagent, step_id, now)
- for it in items:
- _create_step_reagent(db, step_id, tenant_no, user_id, now, it)
- db.commit()
- def update_step_consumables(db: Session, step_id: str, items: List[Dict], tenant_no: str, user_id: Optional[str] = None):
- now = datetime.now()
- _soft_delete_sub_records(db, BizProcessRouteStepConsumable, step_id, now)
- for it in items:
- _create_step_consumable(db, step_id, tenant_no, user_id, now, it)
- db.commit()
- def update_step_outputs(db: Session, step_id: str, items: List[Dict], tenant_no: str, user_id: Optional[str] = None):
- now = datetime.now()
- _soft_delete_sub_records(db, BizProcessRouteStepOutput, step_id, now)
- for it in items:
- _create_step_output(db, step_id, tenant_no, user_id, now, it)
- db.commit()
- def update_step_data_collections(db: Session, step_id: str, items: List[Dict], tenant_no: str, user_id: Optional[str] = None):
- now = datetime.now()
- _soft_delete_sub_records(db, BizProcessRouteStepDataCollection, step_id, now)
- for it in items:
- _create_step_data_collection(db, step_id, tenant_no, user_id, now, it)
- db.commit()
- def total_pages(total: int, page_size: int) -> int:
- if total <= 0:
- return 0
- return int(math.ceil(total / float(page_size)))
|