From 0402f797c08a1da07af4b4048d63b7ae8a7c2b49 Mon Sep 17 00:00:00 2001 From: zlwu <704541015@qq.com> Date: Fri, 16 Oct 2026 16:58:24 +0800 Subject: [PATCH] feat(oa): expose bank-receipts GET/PUT with menu permission Gate instance bank receipt APIs behind oa:done:bank-receipt. Co-authored-by: Cursor --- backend/app/api/oa_approval.py | 65 ++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/backend/app/api/oa_approval.py b/backend/app/api/oa_approval.py index 969a174f..c67e7533 100644 --- a/backend/app/api/oa_approval.py +++ b/backend/app/api/oa_approval.py @@ -19,6 +19,7 @@ from app.services.oa_receive_account import normalize_account_fields router = APIRouter(prefix="/web/admin/oa-approval", tags=["OA审批"]) OA_START_HISTORY_ALL_PERM = "oa:start:history:all" +OA_DONE_BANK_RECEIPT_PERM = "oa:done:bank-receipt" def _get_tenant_no(db: Session, user: dict) -> str: @@ -773,6 +774,19 @@ class OaCommentCreateBody(BaseModel): mention_user_ids: Optional[List[str]] = Field(None, alias="mentionUserIds") +class OaBankReceiptItemBody(BaseModel): + model_config = ConfigDict(populate_by_name=True) + file_url: str = Field(..., alias="fileUrl") + file_name: Optional[str] = Field(None, alias="fileName") + file_type: Optional[str] = Field(None, alias="fileType") + file_size: Optional[int] = Field(None, alias="fileSize") + + +class OaBankReceiptReplaceBody(BaseModel): + model_config = ConfigDict(populate_by_name=True) + items: List[OaBankReceiptItemBody] = Field(default_factory=list) + + class OaResubmitBody(BaseModel): model_config = ConfigDict(populate_by_name=True) form_data: Optional[Dict[str, Any]] = Field(None, alias="formData") @@ -1032,6 +1046,57 @@ async def list_oa_instance_form_attachments( return error_response(400, str(e)) +@router.get("/instances/{instance_id}/bank-receipts") +async def list_oa_bank_receipts( + instance_id: str, + user: dict = Depends(require_admin_or_super_admin), + db: Session = Depends(get_db), +): + from app.core.menu_guard import user_has_menu_perm + from app.services import oa_bank_receipt as br + + if not user_has_menu_perm(db, user, OA_DONE_BANK_RECEIPT_PERM): + return error_response(403, "无权上传银行回执单") + try: + tenant_no = _get_tenant_no(db, user) + items = br.list_bank_receipts(db, instance_id=instance_id, tenant_no=tenant_no) + return success_response({"items": items}) + except br.OaBankReceiptError as e: + return error_response(400, str(e)) + + +@router.put("/instances/{instance_id}/bank-receipts") +async def replace_oa_bank_receipts( + instance_id: str, + body: OaBankReceiptReplaceBody, + user: dict = Depends(require_admin_or_super_admin), + db: Session = Depends(get_db), +): + from app.core.menu_guard import user_has_menu_perm + from app.services import oa_bank_receipt as br + + if not user_has_menu_perm(db, user, OA_DONE_BANK_RECEIPT_PERM): + return error_response(403, "无权上传银行回执单") + try: + tenant_no = _get_tenant_no(db, user) + items = br.replace_bank_receipts( + db, + instance_id=instance_id, + tenant_no=tenant_no, + items=[it.model_dump(by_alias=True) for it in (body.items or [])], + user_id=user.get("user_id") or "", + dept_id=user.get("dept_id") or "", + ) + db.commit() + return success_response({"items": items}) + except br.OaBankReceiptError as e: + db.rollback() + return error_response(400, str(e)) + except Exception: + db.rollback() + raise + + @router.get("/instances/{instance_id}/comments") async def list_oa_instance_comments( instance_id: str,