clinical_payment.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. from typing import List, Optional
  2. from fastapi import APIRouter, Depends, Query
  3. from pydantic import BaseModel, ConfigDict, Field
  4. from sqlalchemy.orm import Session
  5. from app.core.database import get_db
  6. from app.core.menu_guard import require_admin_or_super_admin
  7. from app.core.response import error_response, success_response
  8. from app.crud import clinical_payment
  9. from app.models.models import SysUser
  10. router = APIRouter(prefix="/web/admin", tags=["临床应用缴费管理"])
  11. def _get_tenant_no(db: Session, user: dict) -> str:
  12. user_id = user.get("user_id")
  13. if not user_id:
  14. raise PermissionError("用户身份信息缺失,无法确定租户")
  15. sys_user = db.query(SysUser).filter(SysUser.id == user_id).first()
  16. if not sys_user or not sys_user.tenant_no:
  17. raise PermissionError("用户租户信息缺失")
  18. return sys_user.tenant_no
  19. class PaymentIdBody(BaseModel):
  20. model_config = ConfigDict(populate_by_name=True)
  21. id: str
  22. class BatchPaymentIdsBody(BaseModel):
  23. model_config = ConfigDict(populate_by_name=True)
  24. payment_ids: List[str] = Field(..., alias="paymentIds")
  25. class SubmitReceiptBody(BaseModel):
  26. model_config = ConfigDict(populate_by_name=True)
  27. transfer_amount: Optional[float] = Field(None, alias="transferAmount")
  28. transfer_type: Optional[str] = Field(None, alias="transferType")
  29. remark: Optional[str] = None
  30. transfer_attachments: Optional[str] = Field(None, alias="transferAttachments")
  31. class BatchSubmitReceiptBody(BaseModel):
  32. model_config = ConfigDict(populate_by_name=True)
  33. payment_ids: List[str] = Field(..., alias="paymentIds")
  34. remark: Optional[str] = None
  35. transfer_attachments: Optional[str] = Field(None, alias="transferAttachments")
  36. class ConfirmReceiptBody(BaseModel):
  37. model_config = ConfigDict(populate_by_name=True)
  38. finance_confirm_attachments: Optional[str] = Field(None, alias="financeConfirmAttachments")
  39. finance_remark: Optional[str] = Field(None, alias="financeRemark")
  40. class SubmitRefundBody(BaseModel):
  41. model_config = ConfigDict(populate_by_name=True)
  42. refund_amount: float = Field(..., alias="refundAmount")
  43. refund_remark: Optional[str] = Field(None, alias="refundRemark")
  44. refund_attachments: Optional[str] = Field(None, alias="refundAttachments")
  45. class BatchSubmitRefundBody(BaseModel):
  46. model_config = ConfigDict(populate_by_name=True)
  47. payment_ids: List[str] = Field(..., alias="paymentIds")
  48. refund_amount: float = Field(..., alias="refundAmount")
  49. refund_remark: Optional[str] = Field(None, alias="refundRemark")
  50. refund_attachments: Optional[str] = Field(None, alias="refundAttachments")
  51. class ConfirmRefundBody(BaseModel):
  52. model_config = ConfigDict(populate_by_name=True)
  53. refund_finance_confirm_attachments: Optional[str] = Field(
  54. None, alias="refundFinanceConfirmAttachments"
  55. )
  56. refund_finance_remark: Optional[str] = Field(None, alias="refundFinanceRemark")
  57. @router.get("/clinical-payments")
  58. async def api_list_payments(
  59. page: int = Query(1, ge=1),
  60. pageSize: int = Query(10, ge=1, le=100, alias="pageSize"),
  61. payStatus: Optional[str] = Query(None, alias="payStatus"),
  62. keyword: Optional[str] = Query(None, alias="keyword"),
  63. bizType: Optional[str] = Query(None, alias="bizType"),
  64. user: dict = Depends(require_admin_or_super_admin),
  65. db: Session = Depends(get_db),
  66. ):
  67. tenant_no = _get_tenant_no(db, user)
  68. try:
  69. rows, total = clinical_payment.list_payments(
  70. db,
  71. page=page,
  72. page_size=pageSize,
  73. pay_status=payStatus,
  74. keyword=keyword,
  75. biz_type=bizType,
  76. tenant_no=tenant_no,
  77. user_info=user,
  78. )
  79. return success_response({"list": rows, "total": total})
  80. except Exception as e:
  81. return error_response(500, str(e))
  82. @router.get("/clinical-payments/receipt-pending")
  83. async def api_receipt_pending(
  84. page: int = Query(1, ge=1),
  85. pageSize: int = Query(10, ge=1, le=100, alias="pageSize"),
  86. keyword: Optional[str] = Query(None, alias="keyword"),
  87. bizType: Optional[str] = Query(None, alias="bizType"),
  88. user: dict = Depends(require_admin_or_super_admin),
  89. db: Session = Depends(get_db),
  90. ):
  91. tenant_no = _get_tenant_no(db, user)
  92. try:
  93. rows, total = clinical_payment.list_payments(
  94. db,
  95. page=page,
  96. page_size=pageSize,
  97. pay_status="jfqrz",
  98. keyword=keyword,
  99. biz_type=bizType,
  100. tenant_no=tenant_no,
  101. user_info=user,
  102. )
  103. return success_response({"list": rows, "total": total})
  104. except Exception as e:
  105. return error_response(500, str(e))
  106. @router.get("/clinical-payments/receipt-confirmed")
  107. async def api_receipt_confirmed(
  108. page: int = Query(1, ge=1),
  109. pageSize: int = Query(10, ge=1, le=100, alias="pageSize"),
  110. keyword: Optional[str] = Query(None, alias="keyword"),
  111. bizType: Optional[str] = Query(None, alias="bizType"),
  112. user: dict = Depends(require_admin_or_super_admin),
  113. db: Session = Depends(get_db),
  114. ):
  115. tenant_no = _get_tenant_no(db, user)
  116. try:
  117. rows, total = clinical_payment.list_payments(
  118. db,
  119. page=page,
  120. page_size=pageSize,
  121. pay_status="yjf",
  122. keyword=keyword,
  123. biz_type=bizType,
  124. tenant_no=tenant_no,
  125. user_info=user,
  126. )
  127. return success_response({"list": rows, "total": total})
  128. except Exception as e:
  129. return error_response(500, str(e))
  130. @router.get("/clinical-payments/refund-pending")
  131. async def api_refund_pending(
  132. page: int = Query(1, ge=1),
  133. pageSize: int = Query(10, ge=1, le=100, alias="pageSize"),
  134. keyword: Optional[str] = Query(None, alias="keyword"),
  135. bizType: Optional[str] = Query(None, alias="bizType"),
  136. user: dict = Depends(require_admin_or_super_admin),
  137. db: Session = Depends(get_db),
  138. ):
  139. tenant_no = _get_tenant_no(db, user)
  140. try:
  141. rows, total = clinical_payment.list_payments(
  142. db,
  143. page=page,
  144. page_size=pageSize,
  145. pay_status="tfqrz",
  146. keyword=keyword,
  147. biz_type=bizType,
  148. tenant_no=tenant_no,
  149. user_info=user,
  150. )
  151. return success_response({"list": rows, "total": total})
  152. except Exception as e:
  153. return error_response(500, str(e))
  154. @router.get("/clinical-payments/refund-confirmed")
  155. async def api_refund_confirmed(
  156. page: int = Query(1, ge=1),
  157. pageSize: int = Query(10, ge=1, le=100, alias="pageSize"),
  158. keyword: Optional[str] = Query(None, alias="keyword"),
  159. bizType: Optional[str] = Query(None, alias="bizType"),
  160. user: dict = Depends(require_admin_or_super_admin),
  161. db: Session = Depends(get_db),
  162. ):
  163. tenant_no = _get_tenant_no(db, user)
  164. try:
  165. rows, total = clinical_payment.list_payments(
  166. db,
  167. page=page,
  168. page_size=pageSize,
  169. pay_status="ytf",
  170. keyword=keyword,
  171. biz_type=bizType,
  172. tenant_no=tenant_no,
  173. user_info=user,
  174. )
  175. return success_response({"list": rows, "total": total})
  176. except Exception as e:
  177. return error_response(500, str(e))
  178. @router.get("/clinical-payments/{payment_id}")
  179. async def api_get_payment_detail(
  180. payment_id: str,
  181. user: dict = Depends(require_admin_or_super_admin),
  182. db: Session = Depends(get_db),
  183. ):
  184. tenant_no = _get_tenant_no(db, user)
  185. try:
  186. result = clinical_payment.get_payment_detail(
  187. db, payment_id=payment_id, tenant_no=tenant_no
  188. )
  189. if result is None:
  190. return error_response(404, "缴费记录不存在")
  191. return success_response(result)
  192. except ValueError as e:
  193. return error_response(404, str(e))
  194. @router.post("/clinical-payments/{payment_id}/submit-receipt")
  195. async def api_submit_receipt(
  196. payment_id: str,
  197. body: SubmitReceiptBody = SubmitReceiptBody(),
  198. user: dict = Depends(require_admin_or_super_admin),
  199. db: Session = Depends(get_db),
  200. ):
  201. tenant_no = _get_tenant_no(db, user)
  202. try:
  203. clinical_payment.submit_receipt(
  204. db,
  205. payment_id=payment_id,
  206. tenant_no=tenant_no,
  207. user_id=user.get("user_id"),
  208. remark=body.remark,
  209. transfer_attachments=body.transfer_attachments,
  210. transfer_amount=body.transfer_amount,
  211. transfer_type=body.transfer_type,
  212. )
  213. return success_response(None, message="提交缴费确认成功")
  214. except ValueError as e:
  215. return error_response(400, str(e))
  216. @router.post("/clinical-payments/submit-receipt-batch")
  217. async def api_batch_submit_receipt(
  218. body: BatchSubmitReceiptBody,
  219. user: dict = Depends(require_admin_or_super_admin),
  220. db: Session = Depends(get_db),
  221. ):
  222. tenant_no = _get_tenant_no(db, user)
  223. try:
  224. count = clinical_payment.batch_submit_receipt(
  225. db,
  226. payment_ids=body.payment_ids,
  227. tenant_no=tenant_no,
  228. user_id=user.get("user_id"),
  229. remark=body.remark,
  230. transfer_attachments=body.transfer_attachments,
  231. )
  232. return success_response({"count": count}, message=f"批量提交成功,共{count}条")
  233. except ValueError as e:
  234. return error_response(400, str(e))
  235. @router.post("/clinical-payments/{payment_id}/confirm-receipt")
  236. async def api_confirm_receipt(
  237. payment_id: str,
  238. body: ConfirmReceiptBody,
  239. user: dict = Depends(require_admin_or_super_admin),
  240. db: Session = Depends(get_db),
  241. ):
  242. tenant_no = _get_tenant_no(db, user)
  243. try:
  244. clinical_payment.confirm_receipt(
  245. db,
  246. payment_id=payment_id,
  247. tenant_no=tenant_no,
  248. user_id=user.get("user_id"),
  249. finance_confirm_attachments=body.finance_confirm_attachments,
  250. finance_remark=body.finance_remark,
  251. )
  252. return success_response(None, message="确认收款成功")
  253. except ValueError as e:
  254. return error_response(400, str(e))
  255. @router.post("/clinical-payments/{payment_id}/reject-receipt")
  256. async def api_reject_receipt(
  257. payment_id: str,
  258. user: dict = Depends(require_admin_or_super_admin),
  259. db: Session = Depends(get_db),
  260. ):
  261. tenant_no = _get_tenant_no(db, user)
  262. try:
  263. clinical_payment.reject_receipt(
  264. db,
  265. payment_id=payment_id,
  266. tenant_no=tenant_no,
  267. user_id=user.get("user_id"),
  268. )
  269. return success_response(None, message="退回成功")
  270. except ValueError as e:
  271. return error_response(400, str(e))
  272. @router.post("/clinical-payments/{payment_id}/submit-refund")
  273. async def api_submit_refund(
  274. payment_id: str,
  275. body: SubmitRefundBody,
  276. user: dict = Depends(require_admin_or_super_admin),
  277. db: Session = Depends(get_db),
  278. ):
  279. tenant_no = _get_tenant_no(db, user)
  280. try:
  281. clinical_payment.submit_refund(
  282. db,
  283. payment_id=payment_id,
  284. tenant_no=tenant_no,
  285. user_id=user.get("user_id"),
  286. refund_amount=body.refund_amount,
  287. refund_remark=body.refund_remark,
  288. refund_attachments=body.refund_attachments,
  289. )
  290. return success_response(None, message="提交退费申请成功")
  291. except ValueError as e:
  292. return error_response(400, str(e))
  293. @router.post("/clinical-payments/submit-refund-batch")
  294. async def api_batch_submit_refund(
  295. body: BatchSubmitRefundBody,
  296. user: dict = Depends(require_admin_or_super_admin),
  297. db: Session = Depends(get_db),
  298. ):
  299. tenant_no = _get_tenant_no(db, user)
  300. try:
  301. count = clinical_payment.batch_submit_refund(
  302. db,
  303. payment_ids=body.payment_ids,
  304. tenant_no=tenant_no,
  305. user_id=user.get("user_id"),
  306. refund_amount=body.refund_amount,
  307. refund_remark=body.refund_remark,
  308. refund_attachments=body.refund_attachments,
  309. )
  310. return success_response({"count": count}, message=f"批量提交退费成功,共{count}条")
  311. except ValueError as e:
  312. return error_response(400, str(e))
  313. @router.post("/clinical-payments/{payment_id}/confirm-refund")
  314. async def api_confirm_refund(
  315. payment_id: str,
  316. body: ConfirmRefundBody,
  317. user: dict = Depends(require_admin_or_super_admin),
  318. db: Session = Depends(get_db),
  319. ):
  320. tenant_no = _get_tenant_no(db, user)
  321. try:
  322. clinical_payment.confirm_refund(
  323. db,
  324. payment_id=payment_id,
  325. tenant_no=tenant_no,
  326. user_id=user.get("user_id"),
  327. refund_finance_confirm_attachments=body.refund_finance_confirm_attachments,
  328. refund_finance_remark=body.refund_finance_remark,
  329. )
  330. return success_response(None, message="确认退费成功")
  331. except ValueError as e:
  332. return error_response(400, str(e))
  333. @router.post("/clinical-payments/{payment_id}/reject-refund")
  334. async def api_reject_refund(
  335. payment_id: str,
  336. user: dict = Depends(require_admin_or_super_admin),
  337. db: Session = Depends(get_db),
  338. ):
  339. tenant_no = _get_tenant_no(db, user)
  340. try:
  341. clinical_payment.reject_refund(
  342. db,
  343. payment_id=payment_id,
  344. tenant_no=tenant_no,
  345. user_id=user.get("user_id"),
  346. )
  347. return success_response(None, message="退回成功")
  348. except ValueError as e:
  349. return error_response(400, str(e))