from typing import List from fastapi import APIRouter, Depends, HTTPException, status, Query from sqlalchemy.orm import Session from app.core.bx_auth import BxUserContext, get_bx_current_user from app.core.database import get_db from app.core.tenant_context import get_tenant_no from app.schemas.bx.common import ApiResponse, PagedData from app.schemas.bx.workflow import ( WorkflowDefCreate, WorkflowDefOut, WorkflowDefUpdate, WorkflowNodeCreate, ) from app.services.bx.workflow import WorkflowService router = APIRouter(prefix="/workflows", tags=["工作流配置"]) @router.get("/", response_model=ApiResponse[PagedData[WorkflowDefOut]]) def list_workflows( page: int = 1, pageSize: int = Query(10, ge=1, le=500), db: Session = Depends(get_db), user: BxUserContext = Depends(get_bx_current_user), ): tenant_no = get_tenant_no(db, user.to_tenant_user_dict()) rows, total = WorkflowService.get_paged(db, tenant_no, page=page, page_size=pageSize, user=user) out_rows = [WorkflowDefOut.model_validate(r) for r in rows] paged_data = PagedData(rows=out_rows, total=total, page=page, page_size=pageSize) return ApiResponse(data=paged_data) @router.get("/biz/{biz_type}", response_model=ApiResponse[WorkflowDefOut]) def get_workflow_by_biz_type( biz_type: str, db: Session = Depends(get_db), user: BxUserContext = Depends(get_bx_current_user), ): workflow = WorkflowService.ensure_by_biz_type(db, biz_type, user=user) if not workflow: return ApiResponse(data=None) return ApiResponse(data=WorkflowDefOut.model_validate(workflow)) @router.get("/{workflow_id}", response_model=ApiResponse[WorkflowDefOut]) def get_workflow( workflow_id: str, db: Session = Depends(get_db), user: BxUserContext = Depends(get_bx_current_user), ): tenant_no = get_tenant_no(db, user.to_tenant_user_dict()) workflow = WorkflowService.get_by_id(db, workflow_id, tenant_no, user=user) if not workflow: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="工作流不存在") return ApiResponse(data=WorkflowDefOut.model_validate(workflow)) @router.post("/", response_model=ApiResponse[WorkflowDefOut]) def create_workflow( body: WorkflowDefCreate, db: Session = Depends(get_db), user: BxUserContext = Depends(get_bx_current_user), ): data = body.model_dump(exclude_unset=True) nodes_data = data.pop("nodes", []) or [] workflow = WorkflowService.create(db, data, user=user) if nodes_data: try: WorkflowService.save_nodes(db, workflow.id, nodes_data, user=user) except ValueError as exc: db.rollback() code = ( status.HTTP_400_BAD_REQUEST if "发放登记" in str(exc) else status.HTTP_404_NOT_FOUND ) raise HTTPException(status_code=code, detail=str(exc)) from exc db.commit() db.refresh(workflow) return ApiResponse(data=WorkflowDefOut.model_validate(workflow)) @router.put("/{workflow_id}", response_model=ApiResponse[WorkflowDefOut]) def update_workflow( workflow_id: str, body: WorkflowDefUpdate, db: Session = Depends(get_db), user: BxUserContext = Depends(get_bx_current_user), ): tenant_no = get_tenant_no(db, user.to_tenant_user_dict()) data = body.model_dump(exclude_unset=True) nodes_data = data.pop("nodes", None) workflow = WorkflowService.update(db, workflow_id, data, user=user) if not workflow: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="工作流不存在") if nodes_data is not None: try: WorkflowService.save_nodes(db, workflow_id, nodes_data, user=user) except ValueError as exc: db.rollback() code = ( status.HTTP_400_BAD_REQUEST if "发放登记" in str(exc) else status.HTTP_404_NOT_FOUND ) raise HTTPException(status_code=code, detail=str(exc)) from exc db.commit() db.refresh(workflow) return ApiResponse(data=WorkflowDefOut.model_validate(workflow)) @router.put("/{workflow_id}/nodes", response_model=ApiResponse[WorkflowDefOut]) def save_workflow_nodes( workflow_id: str, body: List[WorkflowNodeCreate], db: Session = Depends(get_db), user: BxUserContext = Depends(get_bx_current_user), ): tenant_no = get_tenant_no(db, user.to_tenant_user_dict()) nodes_data = [n.model_dump(exclude_unset=True) for n in body] try: WorkflowService.save_nodes(db, workflow_id, nodes_data, user=user) except ValueError as exc: db.rollback() code = ( status.HTTP_400_BAD_REQUEST if "发放登记" in str(exc) else status.HTTP_404_NOT_FOUND ) raise HTTPException(status_code=code, detail=str(exc)) from exc workflow = WorkflowService.get_by_id(db, workflow_id, tenant_no, user=user) if not workflow: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="工作流不存在") db.commit() db.refresh(workflow) return ApiResponse(data=WorkflowDefOut.model_validate(workflow)) @router.delete("/{workflow_id}", response_model=ApiResponse[None]) def delete_workflow( workflow_id: str, db: Session = Depends(get_db), user: BxUserContext = Depends(get_bx_current_user), ): tenant_no = get_tenant_no(db, user.to_tenant_user_dict()) workflow = WorkflowService.get_by_id(db, workflow_id, tenant_no, user=user) if not workflow: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="工作流不存在") WorkflowService.soft_delete(db, workflow_id, user=user) db.commit() return ApiResponse(data=None)