from typing import List, Optional from fastapi import APIRouter, Depends, Query 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 clinical_payment from app.models.models import 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 class PaymentIdBody(BaseModel): model_config = ConfigDict(populate_by_name=True) id: str class BatchPaymentIdsBody(BaseModel): model_config = ConfigDict(populate_by_name=True) payment_ids: List[str] = Field(..., alias="paymentIds") class SubmitReceiptBody(BaseModel): model_config = ConfigDict(populate_by_name=True) transfer_amount: Optional[float] = Field(None, alias="transferAmount") transfer_type: Optional[str] = Field(None, alias="transferType") remark: Optional[str] = None transfer_attachments: Optional[str] = Field(None, alias="transferAttachments") class BatchSubmitReceiptBody(BaseModel): model_config = ConfigDict(populate_by_name=True) payment_ids: List[str] = Field(..., alias="paymentIds") remark: Optional[str] = None transfer_attachments: Optional[str] = Field(None, alias="transferAttachments") class ConfirmReceiptBody(BaseModel): model_config = ConfigDict(populate_by_name=True) finance_confirm_attachments: Optional[str] = Field(None, alias="financeConfirmAttachments") finance_remark: Optional[str] = Field(None, alias="financeRemark") class SubmitRefundBody(BaseModel): model_config = ConfigDict(populate_by_name=True) refund_amount: float = Field(..., alias="refundAmount") refund_remark: Optional[str] = Field(None, alias="refundRemark") refund_attachments: Optional[str] = Field(None, alias="refundAttachments") class BatchSubmitRefundBody(BaseModel): model_config = ConfigDict(populate_by_name=True) payment_ids: List[str] = Field(..., alias="paymentIds") refund_amount: float = Field(..., alias="refundAmount") refund_remark: Optional[str] = Field(None, alias="refundRemark") refund_attachments: Optional[str] = Field(None, alias="refundAttachments") class ConfirmRefundBody(BaseModel): model_config = ConfigDict(populate_by_name=True) refund_finance_confirm_attachments: Optional[str] = Field( None, alias="refundFinanceConfirmAttachments" ) refund_finance_remark: Optional[str] = Field(None, alias="refundFinanceRemark") @router.get("/clinical-payments") async def api_list_payments( page: int = Query(1, ge=1), pageSize: int = Query(10, ge=1, le=100, alias="pageSize"), payStatus: Optional[str] = Query(None, alias="payStatus"), keyword: Optional[str] = Query(None, alias="keyword"), bizType: Optional[str] = Query(None, alias="bizType"), user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) try: rows, total = clinical_payment.list_payments( db, page=page, page_size=pageSize, pay_status=payStatus, keyword=keyword, biz_type=bizType, tenant_no=tenant_no, user_info=user, ) return success_response({"list": rows, "total": total}) except Exception as e: return error_response(500, str(e)) @router.get("/clinical-payments/receipt-pending") async def api_receipt_pending( page: int = Query(1, ge=1), pageSize: int = Query(10, ge=1, le=100, alias="pageSize"), keyword: Optional[str] = Query(None, alias="keyword"), bizType: Optional[str] = Query(None, alias="bizType"), user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) try: rows, total = clinical_payment.list_payments( db, page=page, page_size=pageSize, pay_status="jfqrz", keyword=keyword, biz_type=bizType, tenant_no=tenant_no, user_info=user, ) return success_response({"list": rows, "total": total}) except Exception as e: return error_response(500, str(e)) @router.get("/clinical-payments/receipt-confirmed") async def api_receipt_confirmed( page: int = Query(1, ge=1), pageSize: int = Query(10, ge=1, le=100, alias="pageSize"), keyword: Optional[str] = Query(None, alias="keyword"), bizType: Optional[str] = Query(None, alias="bizType"), user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) try: rows, total = clinical_payment.list_payments( db, page=page, page_size=pageSize, pay_status="yjf", keyword=keyword, biz_type=bizType, tenant_no=tenant_no, user_info=user, ) return success_response({"list": rows, "total": total}) except Exception as e: return error_response(500, str(e)) @router.get("/clinical-payments/refund-pending") async def api_refund_pending( page: int = Query(1, ge=1), pageSize: int = Query(10, ge=1, le=100, alias="pageSize"), keyword: Optional[str] = Query(None, alias="keyword"), bizType: Optional[str] = Query(None, alias="bizType"), user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) try: rows, total = clinical_payment.list_payments( db, page=page, page_size=pageSize, pay_status="tfqrz", keyword=keyword, biz_type=bizType, tenant_no=tenant_no, user_info=user, ) return success_response({"list": rows, "total": total}) except Exception as e: return error_response(500, str(e)) @router.get("/clinical-payments/refund-confirmed") async def api_refund_confirmed( page: int = Query(1, ge=1), pageSize: int = Query(10, ge=1, le=100, alias="pageSize"), keyword: Optional[str] = Query(None, alias="keyword"), bizType: Optional[str] = Query(None, alias="bizType"), user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) try: rows, total = clinical_payment.list_payments( db, page=page, page_size=pageSize, pay_status="ytf", keyword=keyword, biz_type=bizType, tenant_no=tenant_no, user_info=user, ) return success_response({"list": rows, "total": total}) except Exception as e: return error_response(500, str(e)) @router.get("/clinical-payments/{payment_id}") async def api_get_payment_detail( payment_id: str, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) try: result = clinical_payment.get_payment_detail( db, payment_id=payment_id, tenant_no=tenant_no ) if result is None: return error_response(404, "缴费记录不存在") return success_response(result) except ValueError as e: return error_response(404, str(e)) @router.post("/clinical-payments/{payment_id}/submit-receipt") async def api_submit_receipt( payment_id: str, body: SubmitReceiptBody = SubmitReceiptBody(), user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) try: clinical_payment.submit_receipt( db, payment_id=payment_id, tenant_no=tenant_no, user_id=user.get("user_id"), remark=body.remark, transfer_attachments=body.transfer_attachments, transfer_amount=body.transfer_amount, transfer_type=body.transfer_type, ) return success_response(None, message="提交缴费确认成功") except ValueError as e: return error_response(400, str(e)) @router.post("/clinical-payments/submit-receipt-batch") async def api_batch_submit_receipt( body: BatchSubmitReceiptBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) try: count = clinical_payment.batch_submit_receipt( db, payment_ids=body.payment_ids, tenant_no=tenant_no, user_id=user.get("user_id"), remark=body.remark, transfer_attachments=body.transfer_attachments, ) return success_response({"count": count}, message=f"批量提交成功,共{count}条") except ValueError as e: return error_response(400, str(e)) @router.post("/clinical-payments/{payment_id}/confirm-receipt") async def api_confirm_receipt( payment_id: str, body: ConfirmReceiptBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) try: clinical_payment.confirm_receipt( db, payment_id=payment_id, tenant_no=tenant_no, user_id=user.get("user_id"), finance_confirm_attachments=body.finance_confirm_attachments, finance_remark=body.finance_remark, ) return success_response(None, message="确认收款成功") except ValueError as e: return error_response(400, str(e)) @router.post("/clinical-payments/{payment_id}/reject-receipt") async def api_reject_receipt( payment_id: str, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) try: clinical_payment.reject_receipt( db, payment_id=payment_id, tenant_no=tenant_no, user_id=user.get("user_id"), ) return success_response(None, message="退回成功") except ValueError as e: return error_response(400, str(e)) @router.post("/clinical-payments/{payment_id}/submit-refund") async def api_submit_refund( payment_id: str, body: SubmitRefundBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) try: clinical_payment.submit_refund( db, payment_id=payment_id, tenant_no=tenant_no, user_id=user.get("user_id"), refund_amount=body.refund_amount, refund_remark=body.refund_remark, refund_attachments=body.refund_attachments, ) return success_response(None, message="提交退费申请成功") except ValueError as e: return error_response(400, str(e)) @router.post("/clinical-payments/submit-refund-batch") async def api_batch_submit_refund( body: BatchSubmitRefundBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) try: count = clinical_payment.batch_submit_refund( db, payment_ids=body.payment_ids, tenant_no=tenant_no, user_id=user.get("user_id"), refund_amount=body.refund_amount, refund_remark=body.refund_remark, refund_attachments=body.refund_attachments, ) return success_response({"count": count}, message=f"批量提交退费成功,共{count}条") except ValueError as e: return error_response(400, str(e)) @router.post("/clinical-payments/{payment_id}/confirm-refund") async def api_confirm_refund( payment_id: str, body: ConfirmRefundBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) try: clinical_payment.confirm_refund( db, payment_id=payment_id, tenant_no=tenant_no, user_id=user.get("user_id"), refund_finance_confirm_attachments=body.refund_finance_confirm_attachments, refund_finance_remark=body.refund_finance_remark, ) return success_response(None, message="确认退费成功") except ValueError as e: return error_response(400, str(e)) @router.post("/clinical-payments/{payment_id}/reject-refund") async def api_reject_refund( payment_id: str, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) try: clinical_payment.reject_refund( db, payment_id=payment_id, tenant_no=tenant_no, user_id=user.get("user_id"), ) return success_response(None, message="退回成功") except ValueError as e: return error_response(400, str(e))