"""缺料审批接口 核心原则: - 所有写操作仅在 pms_db(PmsMaterialApproval 表)中进行 - 绝对禁止对 inventory_db 进行任何写操作 - 物料信息(MaterialBase)仅从只读库查询,不进行写操作 """ from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.orm import Session from app.database import get_db_pms from app.models import PmsWorkOrder, PmsMaterialApproval, MaterialBase, ApprovalStatus from app.schemas.approval import ( ApprovalCreate, ApprovalStatusUpdate, ApprovalDetailResponse, ) router = APIRouter(prefix="/api/approvals", tags=["缺料审批"]) @router.post( "", response_model=ApprovalDetailResponse, status_code=201, summary="员工提交缺料审批申请", ) async def create_approval(data: ApprovalCreate, db: Session = Depends(get_db_pms)): work_order = db.query(PmsWorkOrder).filter( PmsWorkOrder.id == data.work_order_id ).first() if not work_order: raise HTTPException(status_code=400, detail=f"工单 ID={data.work_order_id} 不存在") material = db.query(MaterialBase).filter( MaterialBase.id == data.missing_material_id ).first() if not material: raise HTTPException(status_code=400, detail=f"物料 ID={data.missing_material_id} 不存在") approval = PmsMaterialApproval( work_order_id=data.work_order_id, missing_material_id=data.missing_material_id, required_qty=data.required_qty, reason=data.reason, status=ApprovalStatus.PENDING, ) db.add(approval) db.commit() db.refresh(approval) return ApprovalDetailResponse( id=approval.id, work_order_id=approval.work_order_id, work_order_no=work_order.work_order_no, missing_material_id=approval.missing_material_id, material_name=material.name, required_qty=approval.required_qty, reason=approval.reason, status=approval.status, created_at=approval.created_at, ) @router.get( "", response_model=list[ApprovalDetailResponse], summary="查询待审批列表", ) async def list_pending_approvals( skip: int = Query(0, ge=0), limit: int = Query(20, gt=0, le=100), db: Session = Depends(get_db_pms) ): approvals = db.query(PmsMaterialApproval).filter( PmsMaterialApproval.status == ApprovalStatus.PENDING ).order_by( PmsMaterialApproval.created_at.desc() ).offset(skip).limit(limit).all() if not approvals: return [] work_order_ids = list(set(a.work_order_id for a in approvals)) material_ids = list(set(a.missing_material_id for a in approvals)) work_orders = { wo.id: wo for wo in db.query(PmsWorkOrder).filter( PmsWorkOrder.id.in_(work_order_ids) ).all() } materials = { m.id: m for m in db.query(MaterialBase).filter( MaterialBase.id.in_(material_ids) ).all() } result = [] for approval in approvals: wo = work_orders.get(approval.work_order_id) mat = materials.get(approval.missing_material_id) result.append(ApprovalDetailResponse( id=approval.id, work_order_id=approval.work_order_id, work_order_no=wo.work_order_no if wo else f"WO-{approval.work_order_id}", missing_material_id=approval.missing_material_id, material_name=mat.name if mat else f"物料-{approval.missing_material_id}", required_qty=approval.required_qty, reason=approval.reason, status=approval.status, created_at=approval.created_at, )) return result @router.put( "/{approval_id}/status", response_model=ApprovalDetailResponse, summary="主管审批", ) async def update_approval_status( approval_id: int, data: ApprovalStatusUpdate, db: Session = Depends(get_db_pms) ): approval = db.query(PmsMaterialApproval).filter( PmsMaterialApproval.id == approval_id ).first() if not approval: raise HTTPException(status_code=404, detail=f"审批记录 ID={approval_id} 不存在") if approval.status != ApprovalStatus.PENDING: raise HTTPException(status_code=400, detail=f"当前状态为 {approval.status.value},终态不可再次修改") if data.status == ApprovalStatus.PENDING: raise HTTPException(status_code=400, detail="不允许将状态改回 PENDING") approval.status = data.status db.commit() db.refresh(approval) work_order = db.query(PmsWorkOrder).filter( PmsWorkOrder.id == approval.work_order_id ).first() material = db.query(MaterialBase).filter( MaterialBase.id == approval.missing_material_id ).first() return ApprovalDetailResponse( id=approval.id, work_order_id=approval.work_order_id, work_order_no=work_order.work_order_no if work_order else f"WO-{approval.work_order_id}", missing_material_id=approval.missing_material_id, material_name=material.name if material else f"物料-{approval.missing_material_id}", required_qty=approval.required_qty, reason=approval.reason, status=approval.status, created_at=approval.created_at, ) @router.get( "/{approval_id}", response_model=ApprovalDetailResponse, summary="获取审批详情", ) async def get_approval( approval_id: int, db: Session = Depends(get_db_pms) ): approval = db.query(PmsMaterialApproval).filter( PmsMaterialApproval.id == approval_id ).first() if not approval: raise HTTPException(status_code=404, detail=f"审批记录 ID={approval_id} 不存在") work_order = db.query(PmsWorkOrder).filter( PmsWorkOrder.id == approval.work_order_id ).first() material = db.query(MaterialBase).filter( MaterialBase.id == approval.missing_material_id ).first() return ApprovalDetailResponse( id=approval.id, work_order_id=approval.work_order_id, work_order_no=work_order.work_order_no if work_order else f"WO-{approval.work_order_id}", missing_material_id=approval.missing_material_id, material_name=material.name if material else f"物料-{approval.missing_material_id}", required_qty=approval.required_qty, reason=approval.reason, status=approval.status, created_at=approval.created_at, )