| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967 |
- """质量检测 — 第三方/实验室主数据、质检工单、质检任务 API"""
- from typing import Any, Dict, List, Optional
- from fastapi import APIRouter, Depends, Query
- from pydantic import BaseModel, ConfigDict, Field
- from sqlalchemy.orm import Session
- from app.core.database import get_db
- from app.core.menu_guard import require_admin_or_super_admin, require_menu_code
- from app.core.response import error_response, success_response
- from app.crud import qc_lab_test_item as lab_svc
- from app.crud import qc_item_param as param_svc
- from app.crud import qc_task_result as result_svc
- from app.crud import qc_task as task_svc
- from app.crud import qc_third_party_company as tpc_svc
- from app.crud import qc_third_party_item as tpi_svc
- from app.crud import qc_material as mat_svc
- from app.crud import qc_material_usage as mu_svc
- from app.crud import qc_work_order as wo_svc
- from app.crud.collection_protocol import total_pages
- from app.api.sample_reception import _get_current_user_id, _get_tenant_no, _page_payload
- router = APIRouter(prefix="/web/admin", tags=["质量检测"])
- # ---------- 第三方检测公司 ----------
- class ThirdPartyCompanyBody(BaseModel):
- model_config = ConfigDict(populate_by_name=True)
- company_code: str = Field(..., alias="companyCode")
- company_name: str = Field(..., alias="companyName")
- contact_name: Optional[str] = Field(None, alias="contactName")
- contact_phone: Optional[str] = Field(None, alias="contactPhone")
- address: Optional[str] = None
- invoice_title: Optional[str] = Field(None, alias="invoiceTitle")
- tax_id: Optional[str] = Field(None, alias="taxId")
- bank_name: Optional[str] = Field(None, alias="bankName")
- bank_account: Optional[str] = Field(None, alias="bankAccount")
- status: str = "1"
- order_num: Optional[int] = Field(None, alias="orderNum")
- remark: Optional[str] = None
- class ThirdPartyCompanyUpdateBody(BaseModel):
- model_config = ConfigDict(populate_by_name=True)
- company_code: Optional[str] = Field(None, alias="companyCode")
- company_name: Optional[str] = Field(None, alias="companyName")
- contact_name: Optional[str] = Field(None, alias="contactName")
- contact_phone: Optional[str] = Field(None, alias="contactPhone")
- address: Optional[str] = None
- invoice_title: Optional[str] = Field(None, alias="invoiceTitle")
- tax_id: Optional[str] = Field(None, alias="taxId")
- bank_name: Optional[str] = Field(None, alias="bankName")
- bank_account: Optional[str] = Field(None, alias="bankAccount")
- status: Optional[str] = None
- order_num: Optional[int] = Field(None, alias="orderNum")
- remark: Optional[str] = None
- @router.get("/qc-third-party-companies")
- async def list_qc_third_party_companies(
- page: int = Query(1, ge=1),
- pageSize: int = Query(10, ge=1, le=100),
- keyword: Optional[str] = None,
- status: Optional[str] = None,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcThirdPartyCompany:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- items, total = tpc_svc.list_companies(
- db, page=page, page_size=pageSize, keyword=keyword, status=status, tenant_no=tenant_no
- )
- return success_response(_page_payload(items, total, page, pageSize))
- except PermissionError as e:
- return error_response(str(e), code=403)
- except Exception as e:
- return error_response(str(e))
- @router.get("/qc-third-party-companies/options")
- async def list_qc_third_party_company_options(
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcWorkOrder:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- return success_response(tpc_svc.list_company_options(db, tenant_no))
- except PermissionError as e:
- return error_response(str(e), code=403)
- except Exception as e:
- return error_response(str(e))
- @router.post("/qc-third-party-companies")
- async def create_qc_third_party_company(
- body: ThirdPartyCompanyBody,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcThirdPartyCompany:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- obj = tpc_svc.create_company(
- db,
- company_code=body.company_code,
- company_name=body.company_name,
- contact_name=body.contact_name,
- contact_phone=body.contact_phone,
- address=body.address,
- invoice_title=body.invoice_title,
- tax_id=body.tax_id,
- bank_name=body.bank_name,
- bank_account=body.bank_account,
- status=body.status,
- tenant_no=tenant_no,
- order_num=body.order_num,
- remark=body.remark,
- user_id=_get_current_user_id(user),
- )
- return success_response(tpc_svc._row_to_dict(obj), message="创建成功")
- except PermissionError as e:
- return error_response(str(e), code=403)
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- @router.put("/qc-third-party-companies/{company_id}")
- async def update_qc_third_party_company(
- company_id: str,
- body: ThirdPartyCompanyUpdateBody,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcThirdPartyCompany:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- obj = tpc_svc.update_company(
- db,
- company_id,
- company_code=body.company_code,
- company_name=body.company_name,
- contact_name=body.contact_name,
- contact_phone=body.contact_phone,
- address=body.address,
- invoice_title=body.invoice_title,
- tax_id=body.tax_id,
- bank_name=body.bank_name,
- bank_account=body.bank_account,
- status=body.status,
- order_num=body.order_num,
- remark=body.remark,
- user_id=_get_current_user_id(user),
- tenant_no=tenant_no,
- )
- return success_response(tpc_svc._row_to_dict(obj), message="更新成功")
- except PermissionError as e:
- return error_response(str(e), code=403)
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- @router.delete("/qc-third-party-companies/{company_id}")
- async def delete_qc_third_party_company(
- company_id: str,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcThirdPartyCompany:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- tpc_svc.soft_delete_company(db, company_id, tenant_no=tenant_no)
- return success_response(None, message="删除成功")
- except PermissionError as e:
- return error_response(str(e), code=403)
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- # ---------- 第三方检测项目 ----------
- class ThirdPartyItemBody(BaseModel):
- model_config = ConfigDict(populate_by_name=True)
- company_id: str = Field(..., alias="companyId")
- item_code: str = Field(..., alias="itemCode")
- item_name: str = Field(..., alias="itemName")
- fee_amount: float = Field(..., alias="feeAmount")
- status: str = "1"
- order_num: Optional[int] = Field(None, alias="orderNum")
- remark: Optional[str] = None
- class ThirdPartyItemUpdateBody(BaseModel):
- model_config = ConfigDict(populate_by_name=True)
- company_id: Optional[str] = Field(None, alias="companyId")
- item_code: Optional[str] = Field(None, alias="itemCode")
- item_name: Optional[str] = Field(None, alias="itemName")
- fee_amount: Optional[float] = Field(None, alias="feeAmount")
- status: Optional[str] = None
- order_num: Optional[int] = Field(None, alias="orderNum")
- remark: Optional[str] = None
- @router.get("/qc-third-party-items")
- async def list_qc_third_party_items(
- page: int = Query(1, ge=1),
- pageSize: int = Query(10, ge=1, le=100),
- keyword: Optional[str] = None,
- status: Optional[str] = None,
- companyId: Optional[str] = None,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcThirdPartyCompany:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- items, total = tpi_svc.list_items(
- db,
- page=page,
- page_size=pageSize,
- keyword=keyword,
- status=status,
- company_id=companyId,
- tenant_no=tenant_no,
- )
- return success_response(_page_payload(items, total, page, pageSize))
- except PermissionError as e:
- return error_response(str(e), code=403)
- except Exception as e:
- return error_response(str(e))
- @router.get("/qc-third-party-items/active")
- async def list_qc_third_party_items_active(
- companyId: Optional[str] = None,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcWorkOrder:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- return success_response(tpi_svc.list_active_items(db, tenant_no, company_id=companyId))
- except PermissionError as e:
- return error_response(str(e), code=403)
- except Exception as e:
- return error_response(str(e))
- @router.post("/qc-third-party-items")
- async def create_qc_third_party_item(
- body: ThirdPartyItemBody,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcThirdPartyCompany:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- obj = tpi_svc.create_item(
- db,
- company_id=body.company_id,
- item_code=body.item_code,
- item_name=body.item_name,
- fee_amount=body.fee_amount,
- status=body.status,
- tenant_no=tenant_no,
- order_num=body.order_num,
- remark=body.remark,
- user_id=_get_current_user_id(user),
- )
- return success_response(tpi_svc._row_to_dict(obj, ""), message="创建成功")
- except PermissionError as e:
- return error_response(str(e), code=403)
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- @router.put("/qc-third-party-items/{item_id}")
- async def update_qc_third_party_item(
- item_id: str,
- body: ThirdPartyItemUpdateBody,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcThirdPartyCompany:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- obj = tpi_svc.update_item(
- db,
- item_id,
- company_id=body.company_id,
- item_code=body.item_code,
- item_name=body.item_name,
- fee_amount=body.fee_amount,
- status=body.status,
- order_num=body.order_num,
- remark=body.remark,
- user_id=_get_current_user_id(user),
- tenant_no=tenant_no,
- )
- return success_response(tpi_svc._row_to_dict(obj, ""), message="更新成功")
- except PermissionError as e:
- return error_response(str(e), code=403)
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- @router.delete("/qc-third-party-items/{item_id}")
- async def delete_qc_third_party_item(
- item_id: str,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcThirdPartyCompany:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- tpi_svc.soft_delete_item(db, item_id, tenant_no=tenant_no)
- return success_response(None, message="删除成功")
- except PermissionError as e:
- return error_response(str(e), code=403)
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- # ---------- 实验室自检项目 ----------
- class LabTestItemBody(BaseModel):
- model_config = ConfigDict(populate_by_name=True)
- item_code: str = Field(..., alias="itemCode")
- item_name: str = Field(..., alias="itemName")
- description: Optional[str] = None
- status: str = "1"
- order_num: Optional[int] = Field(None, alias="orderNum")
- remark: Optional[str] = None
- class LabTestItemUpdateBody(BaseModel):
- model_config = ConfigDict(populate_by_name=True)
- item_code: Optional[str] = Field(None, alias="itemCode")
- item_name: Optional[str] = Field(None, alias="itemName")
- description: Optional[str] = None
- status: Optional[str] = None
- order_num: Optional[int] = Field(None, alias="orderNum")
- remark: Optional[str] = None
- # ---------- 检测项目参数模板 ----------
- class ItemParamBody(BaseModel):
- model_config = ConfigDict(populate_by_name=True)
- params: List[Dict[str, Any]] = Field(default_factory=list, alias="params")
- class TaskResultBody(BaseModel):
- model_config = ConfigDict(populate_by_name=True)
- results: List[Dict[str, Any]] = Field(default_factory=list, alias="results")
- class TaskCompleteWithResultBody(BaseModel):
- model_config = ConfigDict(populate_by_name=True)
- conclusion: str = Field(..., alias="conclusion")
- results: List[Dict[str, Any]] = Field(default_factory=list, alias="results")
- remark: Optional[str] = Field(None, alias="remark")
- third_party_attachments: Optional[str] = Field(None, alias="thirdPartyAttachments")
- material_usages: Optional[List[Dict[str, Any]]] = Field(None, alias="materialUsages")
- @router.get("/qc-lab-test-items")
- async def list_qc_lab_test_items(
- page: int = Query(1, ge=1),
- pageSize: int = Query(10, ge=1, le=100),
- keyword: Optional[str] = None,
- status: Optional[str] = None,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcLabTestItem:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- items, total = lab_svc.list_lab_items(
- db, page=page, page_size=pageSize, keyword=keyword, status=status, tenant_no=tenant_no
- )
- return success_response(_page_payload(items, total, page, pageSize))
- except PermissionError as e:
- return error_response(str(e), code=403)
- except Exception as e:
- return error_response(str(e))
- @router.get("/qc-lab-test-items/active")
- async def list_qc_lab_test_items_active(
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcWorkOrder:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- return success_response(lab_svc.list_active_lab_items(db, tenant_no))
- except PermissionError as e:
- return error_response(str(e), code=403)
- except Exception as e:
- return error_response(str(e))
- @router.post("/qc-lab-test-items")
- async def create_qc_lab_test_item(
- body: LabTestItemBody,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcLabTestItem:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- obj = lab_svc.create_lab_item(
- db,
- item_code=body.item_code,
- item_name=body.item_name,
- description=body.description,
- status=body.status,
- tenant_no=tenant_no,
- order_num=body.order_num,
- remark=body.remark,
- user_id=_get_current_user_id(user),
- )
- return success_response(lab_svc._row_to_dict(obj), message="创建成功")
- except PermissionError as e:
- return error_response(str(e), code=403)
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- @router.put("/qc-lab-test-items/{item_id}")
- async def update_qc_lab_test_item(
- item_id: str,
- body: LabTestItemUpdateBody,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcLabTestItem:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- obj = lab_svc.update_lab_item(
- db,
- item_id,
- item_code=body.item_code,
- item_name=body.item_name,
- description=body.description,
- status=body.status,
- order_num=body.order_num,
- remark=body.remark,
- user_id=_get_current_user_id(user),
- tenant_no=tenant_no,
- )
- return success_response(lab_svc._row_to_dict(obj), message="更新成功")
- except PermissionError as e:
- return error_response(str(e), code=403)
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- @router.delete("/qc-lab-test-items/{item_id}")
- async def delete_qc_lab_test_item(
- item_id: str,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcLabTestItem:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- lab_svc.soft_delete_lab_item(db, item_id, tenant_no=tenant_no)
- return success_response(None, message="删除成功")
- except PermissionError as e:
- return error_response(str(e), code=403)
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- # ---------- 检测项目参数模板 ----------
- @router.get("/qc-item-params")
- async def list_item_params(
- itemSource: str = Query(...),
- itemId: str = Query(...),
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcLabTestItem:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- return success_response(param_svc.list_params_by_item(db, itemSource, itemId, tenant_no))
- except PermissionError as e:
- return error_response(str(e), code=403)
- except Exception as e:
- return error_response(str(e))
- @router.put("/qc-item-params")
- async def save_item_params(
- body: ItemParamBody,
- itemSource: str = Query(...),
- itemId: str = Query(...),
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcLabTestItem:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- return success_response(
- param_svc.save_params_for_item(db, itemSource, itemId, body.params, tenant_no, _get_current_user_id(user)),
- message="保存成功",
- )
- except PermissionError as e:
- return error_response(str(e), code=403)
- except Exception as e:
- return error_response(str(e))
- # ---------- 质检工单 ----------
- class WorkOrderConfigureBody(BaseModel):
- model_config = ConfigDict(populate_by_name=True)
- has_lab: bool = Field(False, alias="hasLab")
- has_third_party: bool = Field(False, alias="hasThirdParty")
- lab_item_ids: List[str] = Field(default_factory=list, alias="labItemIds")
- third_party_item_ids: List[str] = Field(default_factory=list, alias="thirdPartyItemIds")
- @router.get("/qc-work-orders")
- async def list_qc_work_orders(
- page: int = Query(1, ge=1),
- pageSize: int = Query(10, ge=1, le=100),
- keyword: Optional[str] = None,
- workOrderStatus: Optional[str] = None,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcWorkOrder:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- items, total = wo_svc.list_work_orders(
- db,
- page=page,
- page_size=pageSize,
- keyword=keyword,
- work_order_status=workOrderStatus,
- tenant_no=tenant_no,
- )
- return success_response(_page_payload(items, total, page, pageSize))
- except PermissionError as e:
- return error_response(str(e), code=403)
- except Exception as e:
- return error_response(str(e))
- @router.get("/qc-work-orders/{work_order_id}")
- async def get_qc_work_order_detail(
- work_order_id: str,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcWorkOrder:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- data = wo_svc.get_work_order_detail(db, work_order_id, tenant_no)
- return success_response(data)
- except PermissionError as e:
- return error_response(str(e), code=403)
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- @router.post("/qc-work-orders/{work_order_id}/configure")
- async def configure_qc_work_order(
- work_order_id: str,
- body: WorkOrderConfigureBody,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcWorkOrder:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- obj = wo_svc.configure_work_order(
- db,
- work_order_id,
- has_lab=body.has_lab,
- has_third_party=body.has_third_party,
- lab_item_ids=body.lab_item_ids,
- third_party_item_ids=body.third_party_item_ids,
- tenant_no=tenant_no,
- user_id=_get_current_user_id(user),
- )
- return success_response(wo_svc._wo_to_dict(obj), message="配置成功")
- except PermissionError as e:
- return error_response(str(e), code=403)
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- # ---------- 质检任务 ----------
- class TaskAttachmentsBody(BaseModel):
- model_config = ConfigDict(populate_by_name=True)
- third_party_attachments: str = Field("", alias="thirdPartyAttachments")
- @router.get("/qc-tasks")
- async def list_qc_tasks(
- page: int = Query(1, ge=1),
- pageSize: int = Query(10, ge=1, le=100),
- keyword: Optional[str] = None,
- taskType: Optional[str] = None,
- taskStatus: Optional[str] = None,
- workOrderId: Optional[str] = None,
- qcBizType: Optional[str] = None,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcTask:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- items, total = task_svc.list_tasks(
- db,
- page=page,
- page_size=pageSize,
- keyword=keyword,
- task_type=taskType,
- task_status=taskStatus,
- work_order_id=workOrderId,
- qc_biz_type=qcBizType,
- tenant_no=tenant_no,
- )
- return success_response(_page_payload(items, total, page, pageSize))
- except PermissionError as e:
- return error_response(str(e), code=403)
- except Exception as e:
- return error_response(str(e))
- @router.get("/qc-tasks/{task_id}")
- async def get_qc_task_detail(
- task_id: str,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcTask:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- data = task_svc.get_task_detail(db, task_id, tenant_no)
- return success_response(data)
- except PermissionError as e:
- return error_response(str(e), code=403)
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- @router.post("/qc-tasks/{task_id}/start")
- async def start_qc_task(
- task_id: str,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcTask:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- obj = task_svc.start_task(db, task_id, tenant_no=tenant_no, user_id=_get_current_user_id(user))
- return success_response(task_svc._task_to_dict(obj), message="已开始")
- except PermissionError as e:
- return error_response(str(e), code=403)
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- @router.post("/qc-tasks/{task_id}/complete")
- async def complete_qc_task(
- task_id: str,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcTask:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- obj = task_svc.complete_task(
- db, task_id, tenant_no=tenant_no, user_id=_get_current_user_id(user)
- )
- return success_response(task_svc._task_to_dict(obj), message="已完成")
- except PermissionError as e:
- return error_response(str(e), code=403)
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- @router.get("/qc-tasks/{task_id}/results")
- async def get_task_results(
- task_id: str,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcTask:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- return success_response(result_svc.list_results_by_task(db, task_id, tenant_no))
- except PermissionError as e:
- return error_response(str(e), code=403)
- except Exception as e:
- return error_response(str(e))
- @router.post("/qc-tasks/{task_id}/complete-with-result")
- async def complete_task_with_result(
- task_id: str,
- body: TaskCompleteWithResultBody,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcTask:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- user_id = _get_current_user_id(user)
- t = task_svc.get_task(db, task_id, tenant_no=tenant_no)
- if not t:
- return error_response("任务不存在")
- was_done = (t.task_status or "").strip() == "ywc"
- if body.results:
- result_svc.save_results_for_task(db, task_id, body.results, tenant_no, user_id)
- concl = (body.conclusion or "").strip()
- if concl not in ("tg", "btg"):
- return error_response("请选择检测结论(通过/不通过)")
- if body.third_party_attachments is not None:
- task_svc.update_task_attachments(
- db, task_id, attachments=body.third_party_attachments,
- tenant_no=tenant_no, user_id=user_id,
- )
- # 物料扣减(可选,仅当传了 materialUsages 时)
- if body.material_usages:
- task_obj_pre = task_svc.get_task(db, task_id, tenant_no=tenant_no)
- task_no = task_obj_pre.task_no if task_obj_pre else ""
- mu_svc.deduct_for_task(
- db,
- task_id,
- task_no=task_no,
- material_usages=body.material_usages,
- tenant_no=tenant_no,
- user_id=user_id,
- )
- obj = task_svc.apply_task_result(
- db,
- task_id,
- tenant_no=tenant_no,
- user_id=user_id,
- conclusion=concl,
- remark=body.remark,
- )
- return success_response(
- task_svc._task_to_dict(obj, work_order_no="", db=db, tenant_no=tenant_no),
- message="已保存" if was_done else "已完成",
- )
- except PermissionError as e:
- return error_response(str(e), code=403)
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- @router.put("/qc-tasks/{task_id}/attachments")
- async def update_qc_task_attachments(
- task_id: str,
- body: TaskAttachmentsBody,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcTask:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- obj = task_svc.update_task_attachments(
- db,
- task_id,
- attachments=body.third_party_attachments,
- tenant_no=tenant_no,
- user_id=_get_current_user_id(user),
- )
- return success_response(task_svc._task_to_dict(obj), message="已保存")
- except PermissionError as e:
- return error_response(str(e), code=403)
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- # ---------- 质检物料库 ----------
- class QcMaterialBody(BaseModel):
- model_config = ConfigDict(populate_by_name=True)
- material_code: str = Field(..., alias="materialCode")
- material_name: str = Field(..., alias="materialName")
- spec_model: Optional[str] = Field(None, alias="specModel")
- unit: Optional[str] = None
- warning_qty: Optional[float] = Field(0, alias="warningQty")
- status: str = "1"
- remark: Optional[str] = None
- class QcMaterialUpdateBody(BaseModel):
- model_config = ConfigDict(populate_by_name=True)
- material_code: Optional[str] = Field(None, alias="materialCode")
- material_name: Optional[str] = Field(None, alias="materialName")
- spec_model: Optional[str] = Field(None, alias="specModel")
- unit: Optional[str] = None
- warning_qty: Optional[float] = Field(None, alias="warningQty")
- status: Optional[str] = None
- remark: Optional[str] = None
- class StockInBody(BaseModel):
- model_config = ConfigDict(populate_by_name=True)
- qty: float = Field(..., gt=0)
- remark: Optional[str] = None
- @router.get("/qc-materials")
- async def list_qc_materials(
- page: int = Query(1, ge=1),
- pageSize: int = Query(10, ge=1, le=100),
- keyword: Optional[str] = None,
- status: Optional[str] = None,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcMaterial:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- items, total = mat_svc.list_materials(
- db, page=page, page_size=pageSize, keyword=keyword, status=status, tenant_no=tenant_no,
- )
- return success_response(_page_payload(items, total, page, pageSize))
- except PermissionError as e:
- return error_response(str(e), code=403)
- except Exception as e:
- return error_response(str(e))
- @router.get("/qc-materials/options")
- async def qc_material_options(
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcMaterial:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- return success_response(mat_svc.options_list(db, tenant_no=tenant_no))
- except Exception as e:
- return error_response(str(e))
- @router.post("/qc-materials")
- async def create_qc_material(
- body: QcMaterialBody,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcMaterial:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- user_id = _get_current_user_id(user)
- obj = mat_svc.create_material(db, body.model_dump(by_alias=True, exclude_none=True), tenant_no=tenant_no, user_id=user_id)
- return success_response(obj, message="创建成功")
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- @router.put("/qc-materials/{material_id}")
- async def update_qc_material(
- material_id: str,
- body: QcMaterialUpdateBody,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcMaterial:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- user_id = _get_current_user_id(user)
- obj = mat_svc.update_material(db, material_id, body.model_dump(by_alias=True, exclude_none=True), tenant_no=tenant_no, user_id=user_id)
- return success_response(obj, message="更新成功")
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- @router.delete("/qc-materials/{material_id}")
- async def delete_qc_material(
- material_id: str,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcMaterial:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- user_id = _get_current_user_id(user)
- mat_svc.soft_delete_material(db, material_id, tenant_no=tenant_no, user_id=user_id)
- return success_response(None, message="删除成功")
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- @router.post("/qc-materials/{material_id}/stock-in")
- async def stock_in_qc_material(
- material_id: str,
- body: StockInBody,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcMaterial:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- user_id = _get_current_user_id(user)
- obj = mat_svc.stock_in(db, material_id, qty=body.qty, remark=body.remark, tenant_no=tenant_no, user_id=user_id)
- return success_response(obj, message="入库成功")
- except ValueError as e:
- return error_response(str(e))
- except Exception as e:
- return error_response(str(e))
- # ---------- 物料变动记录 ----------
- @router.get("/qc-material-usages")
- async def list_qc_material_usages(
- page: int = Query(1, ge=1),
- pageSize: int = Query(10, ge=1, le=100),
- materialId: Optional[str] = None,
- changeType: Optional[str] = None,
- startTime: Optional[str] = None,
- endTime: Optional[str] = None,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:qcMaterialUsage:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- items, total = mu_svc.list_usages(
- db, tenant_no, page=page, page_size=pageSize,
- material_id=materialId, change_type=changeType,
- start_time=startTime, end_time=endTime,
- )
- return success_response(_page_payload(items, total, page, pageSize))
- except PermissionError as e:
- return error_response(str(e), code=403)
- except Exception as e:
- return error_response(str(e))
|