"""出库放行审核 API""" from typing import Optional from fastapi import APIRouter, Depends, Query 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 outbound_release_review as svc from app.models.models import SysUser from app.schemas.outbound_release_review import ( OutboundBatchReviewBody, OutboundReviewSubmitBody, ) from app.schemas.outbound_release_material import OutboundReleaseMaterialSaveBody from app.crud import outbound_release_material as orm_svc router = APIRouter(prefix="/web/admin", tags=["出库放行审核"]) def _get_tenant_no(db: Session, user: dict) -> str: user_id = user.get("user_id") if not user_id: raise PermissionError("用户身份信息缺失") sys_user = db.query(SysUser).filter(SysUser.id == user_id).first() if not sys_user or not sys_user.tenant_no: raise PermissionError("用户租户信息缺失") return sys_user.tenant_no def _get_current_user_id(user: dict) -> str: user_id = user.get("user_id") if not user_id: raise PermissionError("用户身份信息缺失") return str(user_id) @router.get("/pilot-release-reviews") async def list_pilot_release_reviews( page: int = Query(1, ge=1), pageSize: int = Query(10, ge=1, le=100), keyword: Optional[str] = None, reviewConclusion: Optional[str] = None, scheduleStatus: Optional[str] = None, qcStatus: Optional[str] = None, bizType: Optional[str] = None, infusionTimeStart: Optional[str] = None, infusionTimeEnd: Optional[str] = None, db: Session = Depends(get_db), user: dict = Depends(require_menu_code("biz:outboundReleaseReview:list")), ): try: tenant_no = _get_tenant_no(db, user) result = svc.list_reviews_paginated( db, tenant_no=tenant_no, keyword=keyword, review_conclusion=reviewConclusion, schedule_status=scheduleStatus, qc_status=qcStatus, biz_type=bizType, infusion_time_start=infusionTimeStart, infusion_time_end=infusionTimeEnd, page=page, page_size=pageSize, user_info=user, ) return success_response(result) except PermissionError as e: return error_response(403, str(e)) except Exception as e: return error_response(400, str(e)) @router.get("/pilot-release-reviews/{schedule_id}/detail") async def get_pilot_release_review_detail( schedule_id: str, db: Session = Depends(get_db), user: dict = Depends(require_menu_code("biz:outboundReleaseReview:list")), ): try: tenant_no = _get_tenant_no(db, user) detail = svc.get_schedule_detail(db, schedule_id, tenant_no) if not detail: return error_response(404, "输注计划不存在") return success_response(detail) except PermissionError as e: return error_response(403, str(e)) except Exception as e: return error_response(400, str(e)) @router.put("/pilot-release-reviews/{schedule_id}/review") async def submit_single_review( schedule_id: str, body: OutboundReviewSubmitBody, db: Session = Depends(get_db), user: dict = Depends(require_admin_or_super_admin), ): try: tenant_no = _get_tenant_no(db, user) user_id = _get_current_user_id(user) result = svc.review_schedule( db, schedule_id, conclusion=body.reviewConclusion, remark=body.reviewRemark, attachments=body.reviewAttachments, tenant_no=tenant_no, user_id=user_id, ) db.commit() return success_response(result) except PermissionError as e: return error_response(403, str(e)) except ValueError as e: return error_response(400, str(e)) except Exception as e: return error_response(400, str(e)) @router.put("/pilot-release-reviews/batch-review") async def batch_review( body: OutboundBatchReviewBody, db: Session = Depends(get_db), user: dict = Depends(require_admin_or_super_admin), ): try: tenant_no = _get_tenant_no(db, user) user_id = _get_current_user_id(user) result = svc.batch_review( db, body.scheduleIds, conclusion=body.reviewConclusion, remark=body.reviewRemark, attachments=body.reviewAttachments, tenant_no=tenant_no, user_id=user_id, ) db.commit() return success_response(result) except PermissionError as e: return error_response(403, str(e)) except ValueError as e: return error_response(400, str(e)) except Exception as e: return error_response(400, str(e)) @router.get("/pilot-release-reviews/{schedule_id}/outbound-materials") async def get_outbound_release_materials( schedule_id: str, db: Session = Depends(get_db), user: dict = Depends(require_menu_code("biz:outboundReleaseReview:list")), ): try: tenant_no = _get_tenant_no(db, user) result = orm_svc.get_outbound_material(db, schedule_id, tenant_no) return success_response(result) except PermissionError as e: return error_response(403, str(e)) except Exception as e: if hasattr(e, "status_code") and getattr(e, "status_code") == 404: return error_response(404, str(getattr(e, "detail", e))) return error_response(400, str(getattr(e, "detail", e))) @router.put("/pilot-release-reviews/{schedule_id}/outbound-materials") async def save_outbound_release_materials( schedule_id: str, body: OutboundReleaseMaterialSaveBody, db: Session = Depends(get_db), user: dict = Depends(require_admin_or_super_admin), ): try: tenant_no = _get_tenant_no(db, user) user_id = _get_current_user_id(user) sys_user = db.query(SysUser).filter(SysUser.id == user_id).first() dept_id = (sys_user.dept_id or "") if sys_user else "" result = orm_svc.save_outbound_material( db, schedule_id, paper_attachments=body.paperAttachments, paper_materials=[p.model_dump(by_alias=True) for p in body.paperMaterials], remark=body.remark, cells=[c.model_dump(by_alias=True) for c in body.cells], qc_materials=[m.model_dump(by_alias=True) for m in body.qcMaterials], tenant_no=tenant_no, user_id=user_id, create_dept_id=dept_id, ) db.commit() return success_response(result) except PermissionError as e: return error_response(403, str(e)) except Exception as e: db.rollback() if hasattr(e, "status_code"): code = int(getattr(e, "status_code", 400)) detail = getattr(e, "detail", str(e)) return error_response(code, detail if isinstance(detail, str) else str(detail)) return error_response(400, str(getattr(e, "detail", e)))