|
|
@@ -0,0 +1,205 @@
|
|
|
+"""协议级退费登记 API"""
|
|
|
+
|
|
|
+from __future__ import annotations
|
|
|
+
|
|
|
+from typing import Optional
|
|
|
+
|
|
|
+from fastapi import APIRouter, Depends
|
|
|
+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
|
|
|
+from app.core.response import error_response, success_response
|
|
|
+from app.crud import protocol_refund_record as rr_svc
|
|
|
+from app.models.models import (
|
|
|
+ BizCollectionProtocol,
|
|
|
+ BizProtocolRefundRecord,
|
|
|
+ SysUser,
|
|
|
+)
|
|
|
+
|
|
|
+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)
|
|
|
+
|
|
|
+
|
|
|
+def _protocol_accessible(db: Session, protocol_id: str, tenant_no: str, user: dict) -> bool:
|
|
|
+ from app.core.data_scope import apply_data_scope
|
|
|
+
|
|
|
+ q = db.query(BizCollectionProtocol).filter(
|
|
|
+ BizCollectionProtocol.id == protocol_id,
|
|
|
+ BizCollectionProtocol.del_flag == 0,
|
|
|
+ BizCollectionProtocol.tenant_no == tenant_no,
|
|
|
+ )
|
|
|
+ q = apply_data_scope(q, BizCollectionProtocol, user, db, tenant_no)
|
|
|
+ return q.first() is not None
|
|
|
+
|
|
|
+
|
|
|
+class RefundRecordBody(BaseModel):
|
|
|
+ model_config = ConfigDict(extra="ignore", populate_by_name=True)
|
|
|
+
|
|
|
+ refund_amount: float = Field(..., alias="refundAmount")
|
|
|
+ refund_time: Optional[str] = Field(None, alias="refundTime")
|
|
|
+ refund_remark: Optional[str] = Field(None, alias="refundRemark")
|
|
|
+ refund_attachments: Optional[str] = Field(None, alias="refundAttachments")
|
|
|
+ workflow_instance_id: Optional[str] = Field(None, alias="workflowInstanceId")
|
|
|
+ remark: Optional[str] = None
|
|
|
+
|
|
|
+
|
|
|
+class RefundRecordUpdateBody(BaseModel):
|
|
|
+ model_config = ConfigDict(extra="ignore", populate_by_name=True)
|
|
|
+
|
|
|
+ refund_amount: Optional[float] = Field(None, alias="refundAmount")
|
|
|
+ refund_time: Optional[str] = Field(None, alias="refundTime")
|
|
|
+ refund_remark: Optional[str] = Field(None, alias="refundRemark")
|
|
|
+ refund_attachments: Optional[str] = Field(None, alias="refundAttachments")
|
|
|
+ workflow_instance_id: Optional[str] = Field(None, alias="workflowInstanceId")
|
|
|
+ remark: Optional[str] = None
|
|
|
+
|
|
|
+
|
|
|
+@router.get("/collection-protocols/{protocol_id}/refund-records")
|
|
|
+async def list_protocol_refund_records(
|
|
|
+ protocol_id: str,
|
|
|
+ user: dict = Depends(require_admin_or_super_admin),
|
|
|
+ db: Session = Depends(get_db),
|
|
|
+):
|
|
|
+ try:
|
|
|
+ tenant_no = _get_tenant_no(db, user)
|
|
|
+ if not _protocol_accessible(db, protocol_id, tenant_no, user):
|
|
|
+ return error_response(404, "协议单不存在或无权查看")
|
|
|
+ data = rr_svc.list_refund_records(
|
|
|
+ db, collection_protocol_id=protocol_id, tenant_no=tenant_no
|
|
|
+ )
|
|
|
+ return success_response(data)
|
|
|
+ except PermissionError as e:
|
|
|
+ return error_response(403, str(e))
|
|
|
+
|
|
|
+
|
|
|
+@router.post("/collection-protocols/{protocol_id}/refund-records")
|
|
|
+async def create_protocol_refund_record(
|
|
|
+ protocol_id: str,
|
|
|
+ body: RefundRecordBody,
|
|
|
+ user: dict = Depends(require_admin_or_super_admin),
|
|
|
+ db: Session = Depends(get_db),
|
|
|
+):
|
|
|
+ try:
|
|
|
+ tenant_no = _get_tenant_no(db, user)
|
|
|
+ user_id = _get_current_user_id(user)
|
|
|
+ if not _protocol_accessible(db, protocol_id, tenant_no, user):
|
|
|
+ return error_response(404, "协议单不存在或无权操作")
|
|
|
+ obj = rr_svc.create_refund_record(
|
|
|
+ db,
|
|
|
+ collection_protocol_id=protocol_id,
|
|
|
+ tenant_no=tenant_no,
|
|
|
+ user_id=user_id,
|
|
|
+ refund_amount=body.refund_amount,
|
|
|
+ refund_time=body.refund_time,
|
|
|
+ refund_remark=body.refund_remark,
|
|
|
+ refund_attachments=body.refund_attachments,
|
|
|
+ workflow_instance_id=body.workflow_instance_id,
|
|
|
+ remark=body.remark,
|
|
|
+ )
|
|
|
+ return success_response(
|
|
|
+ rr_svc._record_to_dict(db, obj, tenant_no), message="登记成功"
|
|
|
+ )
|
|
|
+ except PermissionError as e:
|
|
|
+ return error_response(403, str(e))
|
|
|
+ except ValueError as e:
|
|
|
+ return error_response(400, str(e))
|
|
|
+
|
|
|
+
|
|
|
+@router.put("/protocol-refund-records/{record_id}")
|
|
|
+async def update_protocol_refund_record(
|
|
|
+ record_id: str,
|
|
|
+ body: RefundRecordUpdateBody,
|
|
|
+ user: dict = Depends(require_admin_or_super_admin),
|
|
|
+ db: Session = Depends(get_db),
|
|
|
+):
|
|
|
+ try:
|
|
|
+ tenant_no = _get_tenant_no(db, user)
|
|
|
+ user_id = _get_current_user_id(user)
|
|
|
+ existing = (
|
|
|
+ db.query(BizProtocolRefundRecord)
|
|
|
+ .filter(
|
|
|
+ BizProtocolRefundRecord.id == record_id,
|
|
|
+ BizProtocolRefundRecord.tenant_no == tenant_no,
|
|
|
+ BizProtocolRefundRecord.del_flag == 0,
|
|
|
+ )
|
|
|
+ .first()
|
|
|
+ )
|
|
|
+ if not existing:
|
|
|
+ return error_response(404, "退费登记不存在")
|
|
|
+ if not _protocol_accessible(
|
|
|
+ db, existing.collection_protocol_id, tenant_no, user
|
|
|
+ ):
|
|
|
+ return error_response(403, "无权操作该协议")
|
|
|
+ dumped = body.model_dump(by_alias=False, exclude_unset=True)
|
|
|
+ obj = rr_svc.update_refund_record(
|
|
|
+ db,
|
|
|
+ record_id=record_id,
|
|
|
+ tenant_no=tenant_no,
|
|
|
+ user_id=user_id,
|
|
|
+ refund_amount=dumped.get("refund_amount"),
|
|
|
+ refund_time=dumped.get("refund_time"),
|
|
|
+ refund_remark=dumped.get("refund_remark"),
|
|
|
+ refund_attachments=dumped.get("refund_attachments"),
|
|
|
+ workflow_instance_id=dumped.get("workflow_instance_id"),
|
|
|
+ remark=dumped.get("remark"),
|
|
|
+ fields_set=set(dumped.keys()),
|
|
|
+ )
|
|
|
+ return success_response(
|
|
|
+ rr_svc._record_to_dict(db, obj, tenant_no), message="保存成功"
|
|
|
+ )
|
|
|
+ except PermissionError as e:
|
|
|
+ return error_response(403, str(e))
|
|
|
+ except ValueError as e:
|
|
|
+ return error_response(400, str(e))
|
|
|
+
|
|
|
+
|
|
|
+@router.delete("/protocol-refund-records/{record_id}")
|
|
|
+async def delete_protocol_refund_record(
|
|
|
+ record_id: str,
|
|
|
+ user: dict = Depends(require_admin_or_super_admin),
|
|
|
+ db: Session = Depends(get_db),
|
|
|
+):
|
|
|
+ try:
|
|
|
+ tenant_no = _get_tenant_no(db, user)
|
|
|
+ user_id = _get_current_user_id(user)
|
|
|
+ existing = (
|
|
|
+ db.query(BizProtocolRefundRecord)
|
|
|
+ .filter(
|
|
|
+ BizProtocolRefundRecord.id == record_id,
|
|
|
+ BizProtocolRefundRecord.tenant_no == tenant_no,
|
|
|
+ BizProtocolRefundRecord.del_flag == 0,
|
|
|
+ )
|
|
|
+ .first()
|
|
|
+ )
|
|
|
+ if not existing:
|
|
|
+ return error_response(404, "退费登记不存在")
|
|
|
+ if not _protocol_accessible(
|
|
|
+ db, existing.collection_protocol_id, tenant_no, user
|
|
|
+ ):
|
|
|
+ return error_response(403, "无权操作该协议")
|
|
|
+ rr_svc.soft_delete_refund_record(
|
|
|
+ db, record_id=record_id, tenant_no=tenant_no, user_id=user_id
|
|
|
+ )
|
|
|
+ return success_response(None, message="删除成功")
|
|
|
+ except PermissionError as e:
|
|
|
+ return error_response(403, str(e))
|
|
|
+ except ValueError as e:
|
|
|
+ return error_response(400, str(e))
|