crm_contract_sub_routes.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. """CRM 合同子模块路由 — 变更/模板/审批独立页"""
  2. from __future__ import annotations
  3. from datetime import datetime
  4. from typing import Optional
  5. from fastapi import Depends, Query
  6. from sqlalchemy.orm import Session
  7. from app.core.database import get_db
  8. from app.core.menu_guard import require_admin_or_super_admin
  9. from app.core.response import error_response, success_response
  10. from app.core.tenant_context import get_tenant_no
  11. from app.crud.crm.data_scope_helpers import crm_user_info
  12. from app.crud.crm.contract import (
  13. create_contract_change,
  14. create_contract_template,
  15. export_contract_changes,
  16. export_contract_templates,
  17. execute_change,
  18. get_contract_change_detail,
  19. get_contract_template_detail,
  20. list_contract_changes,
  21. list_contract_templates,
  22. soft_delete_contract_changes,
  23. soft_delete_contract_templates,
  24. submit_change_approval,
  25. toggle_contract_template_active,
  26. total_pages,
  27. update_contract_change,
  28. update_contract_template,
  29. withdraw_change,
  30. )
  31. from app.crud.crm.contract_approval import (
  32. approve_pass,
  33. approve_reject,
  34. approve_transfer,
  35. export_contract_approvals,
  36. get_contract_approval_detail,
  37. list_contract_approvals_page,
  38. refresh_approver_names,
  39. )
  40. from app.schemas.crm.contract import (
  41. ContractApprovalExportBody,
  42. ContractApprovalListQuery,
  43. ContractApprovalPassBody,
  44. ContractApprovalRefreshNamesBody,
  45. ContractApprovalRejectBody,
  46. ContractApprovalTransferBody,
  47. ContractChangeCreateBody,
  48. ContractChangeExportBody,
  49. ContractChangeListQuery,
  50. ContractChangeSubmitBody,
  51. ContractChangeUpdateBody,
  52. ContractTemplateCreateBody,
  53. ContractTemplateExportBody,
  54. ContractTemplateListQuery,
  55. ContractTemplateUpdateBody,
  56. )
  57. from app.utils.crm_export_columns import (
  58. CONTRACT_APPROVAL_EXPORT_COLUMNS,
  59. CONTRACT_CHANGE_EXPORT_COLUMNS,
  60. CONTRACT_TEMPLATE_EXPORT_COLUMNS,
  61. )
  62. from app.utils.excel_export import export_rows_to_xlsx_response
  63. def register_contract_sub_routes(router):
  64. # --- 合同变更 ---
  65. @router.get("/contract/change/list")
  66. async def contract_change_list(
  67. pageNum: int = Query(1, ge=1),
  68. pageSize: int = Query(10, ge=1, le=100),
  69. contractId: Optional[str] = None,
  70. contractNo: Optional[str] = None,
  71. contractName: Optional[str] = None,
  72. changeType: Optional[str] = None,
  73. approvalStatus: Optional[str] = None,
  74. beginTime: Optional[str] = None,
  75. endTime: Optional[str] = None,
  76. _user: dict = Depends(require_admin_or_super_admin),
  77. db: Session = Depends(get_db),
  78. ):
  79. try:
  80. tenant_no = get_tenant_no(db, _user)
  81. user_info = crm_user_info(_user)
  82. query = ContractChangeListQuery(
  83. pageNum=pageNum,
  84. pageSize=pageSize,
  85. contractId=contractId,
  86. contractNo=contractNo,
  87. contractName=contractName,
  88. changeType=changeType,
  89. approvalStatus=approvalStatus,
  90. beginTime=beginTime,
  91. endTime=endTime,
  92. )
  93. rows, total = list_contract_changes(
  94. db,
  95. tenant_no,
  96. user_info=user_info,
  97. page=query.pageNum,
  98. page_size=query.pageSize,
  99. filters=query.model_dump(by_alias=True, exclude={"pageNum", "pageSize"}, exclude_none=True),
  100. )
  101. return success_response(
  102. {
  103. "list": rows,
  104. "rows": rows,
  105. "total": total,
  106. "pageNum": query.pageNum,
  107. "pageSize": query.pageSize,
  108. "totalPages": total_pages(total, query.pageSize),
  109. }
  110. )
  111. except ValueError as e:
  112. return error_response(400, str(e))
  113. except Exception as e:
  114. return error_response(500, str(e))
  115. @router.get("/contract/change/{change_id}")
  116. async def contract_change_detail(
  117. change_id: str,
  118. _user: dict = Depends(require_admin_or_super_admin),
  119. db: Session = Depends(get_db),
  120. ):
  121. try:
  122. tenant_no = get_tenant_no(db, _user)
  123. user_info = crm_user_info(_user)
  124. detail = get_contract_change_detail(db, change_id, tenant_no=tenant_no, user_info=user_info)
  125. return success_response(detail)
  126. except ValueError as e:
  127. return error_response(400, str(e))
  128. except Exception as e:
  129. return error_response(500, str(e))
  130. @router.post("/contract/change")
  131. async def contract_change_add(
  132. body: ContractChangeCreateBody,
  133. _user: dict = Depends(require_admin_or_super_admin),
  134. db: Session = Depends(get_db),
  135. ):
  136. try:
  137. tenant_no = get_tenant_no(db, _user)
  138. user_info = crm_user_info(_user)
  139. user_id = _user.get("user_id", "") or _user.get("id", "")
  140. dept_id = _user.get("dept_id", "") or _user.get("create_dept_id", "") or ""
  141. detail = create_contract_change(
  142. db,
  143. tenant_no=tenant_no,
  144. data=body.model_dump(by_alias=True),
  145. user_id=user_id,
  146. dept_id=dept_id,
  147. )
  148. return success_response(detail["id"], message="新增成功")
  149. except ValueError as e:
  150. return error_response(400, str(e))
  151. except Exception as e:
  152. return error_response(500, str(e))
  153. @router.put("/contract/change")
  154. async def contract_change_edit(
  155. body: ContractChangeUpdateBody,
  156. _user: dict = Depends(require_admin_or_super_admin),
  157. db: Session = Depends(get_db),
  158. ):
  159. try:
  160. tenant_no = get_tenant_no(db, _user)
  161. user_info = crm_user_info(_user)
  162. user_id = _user.get("user_id", "") or _user.get("id", "")
  163. data = body.model_dump(by_alias=True)
  164. change_id = data.pop("id")
  165. detail = update_contract_change(
  166. db,
  167. change_id,
  168. tenant_no=tenant_no,
  169. data=data,
  170. user_id=user_id,
  171. user_info=user_info,
  172. )
  173. return success_response(detail, message="修改成功")
  174. except ValueError as e:
  175. return error_response(400, str(e))
  176. except Exception as e:
  177. return error_response(500, str(e))
  178. @router.delete("/contract/change/{ids}")
  179. async def contract_change_remove(
  180. ids: str,
  181. _user: dict = Depends(require_admin_or_super_admin),
  182. db: Session = Depends(get_db),
  183. ):
  184. try:
  185. tenant_no = get_tenant_no(db, _user)
  186. user_info = crm_user_info(_user)
  187. id_list = [x.strip() for x in ids.split(",") if x.strip()]
  188. soft_delete_contract_changes(db, id_list, tenant_no=tenant_no, user_info=user_info)
  189. return success_response(None, message="删除成功")
  190. except ValueError as e:
  191. return error_response(400, str(e))
  192. except Exception as e:
  193. return error_response(500, str(e))
  194. @router.post("/contract/change/submitApproval")
  195. async def contract_change_submit_approval(
  196. body: ContractChangeSubmitBody,
  197. _user: dict = Depends(require_admin_or_super_admin),
  198. db: Session = Depends(get_db),
  199. ):
  200. try:
  201. tenant_no = get_tenant_no(db, _user)
  202. user_info = crm_user_info(_user)
  203. user_id = _user.get("user_id", "") or _user.get("id", "")
  204. submit_change_approval(
  205. db,
  206. body.id,
  207. tenant_no=tenant_no,
  208. approver_ids=body.approverIds,
  209. remark=body.remark or "",
  210. user_id=user_id,
  211. )
  212. return success_response(None, message="提交成功")
  213. except ValueError as e:
  214. return error_response(400, str(e))
  215. except Exception as e:
  216. return error_response(500, str(e))
  217. @router.put("/contract/change/withdraw/{change_id}")
  218. async def contract_change_withdraw(
  219. change_id: str,
  220. _user: dict = Depends(require_admin_or_super_admin),
  221. db: Session = Depends(get_db),
  222. ):
  223. try:
  224. tenant_no = get_tenant_no(db, _user)
  225. user_info = crm_user_info(_user)
  226. user_id = _user.get("user_id", "") or _user.get("id", "")
  227. withdraw_change(db, change_id, tenant_no=tenant_no, user_id=user_id)
  228. return success_response(None, message="撤回成功")
  229. except ValueError as e:
  230. return error_response(400, str(e))
  231. except Exception as e:
  232. return error_response(500, str(e))
  233. @router.put("/contract/change/execute/{change_id}")
  234. async def contract_change_execute(
  235. change_id: str,
  236. _user: dict = Depends(require_admin_or_super_admin),
  237. db: Session = Depends(get_db),
  238. ):
  239. try:
  240. tenant_no = get_tenant_no(db, _user)
  241. user_info = crm_user_info(_user)
  242. user_id = _user.get("user_id", "") or _user.get("id", "")
  243. execute_change(db, change_id, tenant_no=tenant_no, user_id=user_id)
  244. return success_response(None, message="执行成功")
  245. except ValueError as e:
  246. return error_response(400, str(e))
  247. except Exception as e:
  248. return error_response(500, str(e))
  249. @router.post("/contract/change/export")
  250. async def contract_change_export(
  251. body: ContractChangeExportBody = None,
  252. _user: dict = Depends(require_admin_or_super_admin),
  253. db: Session = Depends(get_db),
  254. ):
  255. try:
  256. tenant_no = get_tenant_no(db, _user)
  257. user_info = crm_user_info(_user)
  258. list_body = body or ContractChangeExportBody()
  259. filters = list_body.model_dump(
  260. by_alias=True,
  261. exclude={"pageNum", "pageSize"},
  262. exclude_none=True,
  263. )
  264. rows = export_contract_changes(db, tenant_no, filters=filters)
  265. return export_rows_to_xlsx_response(
  266. db,
  267. tenant_no=tenant_no,
  268. sheet_title="合同变更记录",
  269. columns=CONTRACT_CHANGE_EXPORT_COLUMNS,
  270. rows=rows,
  271. filename_stem=f"合同变更_{datetime.now().strftime('%Y%m%d%H%M%S')}",
  272. include_legacy_filename=False,
  273. )
  274. except ValueError as e:
  275. return error_response(400, str(e))
  276. except Exception as e:
  277. return error_response(500, str(e))
  278. # --- 合同模板库 ---
  279. @router.get("/contract/template/list")
  280. async def contract_template_list(
  281. pageNum: int = Query(1, ge=1),
  282. pageSize: int = Query(10, ge=1, le=100),
  283. templateNo: Optional[str] = None,
  284. templateName: Optional[str] = None,
  285. templateType: Optional[str] = None,
  286. isActive: Optional[int] = None,
  287. beginTime: Optional[str] = None,
  288. endTime: Optional[str] = None,
  289. _user: dict = Depends(require_admin_or_super_admin),
  290. db: Session = Depends(get_db),
  291. ):
  292. try:
  293. tenant_no = get_tenant_no(db, _user)
  294. user_info = crm_user_info(_user)
  295. query = ContractTemplateListQuery(
  296. pageNum=pageNum,
  297. pageSize=pageSize,
  298. templateNo=templateNo,
  299. templateName=templateName,
  300. templateType=templateType,
  301. isActive=isActive,
  302. beginTime=beginTime,
  303. endTime=endTime,
  304. )
  305. rows, total = list_contract_templates(
  306. db,
  307. tenant_no,
  308. user_info=user_info,
  309. page=query.pageNum,
  310. page_size=query.pageSize,
  311. filters=query.model_dump(by_alias=True, exclude={"pageNum", "pageSize"}, exclude_none=True),
  312. )
  313. return success_response(
  314. {
  315. "list": rows,
  316. "rows": rows,
  317. "total": total,
  318. "pageNum": query.pageNum,
  319. "pageSize": query.pageSize,
  320. "totalPages": total_pages(total, query.pageSize),
  321. }
  322. )
  323. except ValueError as e:
  324. return error_response(400, str(e))
  325. except Exception as e:
  326. return error_response(500, str(e))
  327. @router.get("/contract/template/{template_id}")
  328. async def contract_template_detail(
  329. template_id: str,
  330. _user: dict = Depends(require_admin_or_super_admin),
  331. db: Session = Depends(get_db),
  332. ):
  333. try:
  334. tenant_no = get_tenant_no(db, _user)
  335. user_info = crm_user_info(_user)
  336. detail = get_contract_template_detail(db, template_id, tenant_no=tenant_no)
  337. return success_response(detail)
  338. except ValueError as e:
  339. return error_response(400, str(e))
  340. except Exception as e:
  341. return error_response(500, str(e))
  342. @router.post("/contract/template")
  343. async def contract_template_add(
  344. body: ContractTemplateCreateBody,
  345. _user: dict = Depends(require_admin_or_super_admin),
  346. db: Session = Depends(get_db),
  347. ):
  348. try:
  349. tenant_no = get_tenant_no(db, _user)
  350. user_info = crm_user_info(_user)
  351. user_id = _user.get("user_id", "") or _user.get("id", "")
  352. dept_id = _user.get("dept_id", "") or _user.get("create_dept_id", "") or ""
  353. detail = create_contract_template(
  354. db,
  355. tenant_no=tenant_no,
  356. data=body.model_dump(by_alias=True),
  357. user_id=user_id,
  358. dept_id=dept_id,
  359. )
  360. return success_response(detail["id"], message="新增成功")
  361. except ValueError as e:
  362. return error_response(400, str(e))
  363. except Exception as e:
  364. return error_response(500, str(e))
  365. @router.put("/contract/template")
  366. async def contract_template_edit(
  367. body: ContractTemplateUpdateBody,
  368. _user: dict = Depends(require_admin_or_super_admin),
  369. db: Session = Depends(get_db),
  370. ):
  371. try:
  372. tenant_no = get_tenant_no(db, _user)
  373. user_info = crm_user_info(_user)
  374. user_id = _user.get("user_id", "") or _user.get("id", "")
  375. data = body.model_dump(by_alias=True)
  376. template_id = data.pop("id")
  377. detail = update_contract_template(
  378. db,
  379. template_id,
  380. tenant_no=tenant_no,
  381. data=data,
  382. user_id=user_id,
  383. user_info=user_info,
  384. )
  385. return success_response(detail, message="修改成功")
  386. except ValueError as e:
  387. return error_response(400, str(e))
  388. except Exception as e:
  389. return error_response(500, str(e))
  390. @router.delete("/contract/template/{ids}")
  391. async def contract_template_remove(
  392. ids: str,
  393. _user: dict = Depends(require_admin_or_super_admin),
  394. db: Session = Depends(get_db),
  395. ):
  396. try:
  397. tenant_no = get_tenant_no(db, _user)
  398. user_info = crm_user_info(_user)
  399. id_list = [x.strip() for x in ids.split(",") if x.strip()]
  400. soft_delete_contract_templates(db, id_list, tenant_no=tenant_no, user_info=user_info)
  401. return success_response(None, message="删除成功")
  402. except ValueError as e:
  403. return error_response(400, str(e))
  404. except Exception as e:
  405. return error_response(500, str(e))
  406. @router.put("/contract/template/enable/{template_id}")
  407. async def contract_template_enable(
  408. template_id: str,
  409. _user: dict = Depends(require_admin_or_super_admin),
  410. db: Session = Depends(get_db),
  411. ):
  412. try:
  413. tenant_no = get_tenant_no(db, _user)
  414. user_info = crm_user_info(_user)
  415. user_id = _user.get("user_id", "") or _user.get("id", "")
  416. toggle_contract_template_active(
  417. db, template_id, tenant_no=tenant_no, is_active=1, user_id=user_id
  418. )
  419. return success_response(None, message="启用成功")
  420. except ValueError as e:
  421. return error_response(400, str(e))
  422. except Exception as e:
  423. return error_response(500, str(e))
  424. @router.put("/contract/template/disable/{template_id}")
  425. async def contract_template_disable(
  426. template_id: str,
  427. _user: dict = Depends(require_admin_or_super_admin),
  428. db: Session = Depends(get_db),
  429. ):
  430. try:
  431. tenant_no = get_tenant_no(db, _user)
  432. user_info = crm_user_info(_user)
  433. user_id = _user.get("user_id", "") or _user.get("id", "")
  434. toggle_contract_template_active(
  435. db, template_id, tenant_no=tenant_no, is_active=0, user_id=user_id
  436. )
  437. return success_response(None, message="停用成功")
  438. except ValueError as e:
  439. return error_response(400, str(e))
  440. except Exception as e:
  441. return error_response(500, str(e))
  442. @router.post("/contract/template/export")
  443. async def contract_template_export(
  444. body: ContractTemplateExportBody = None,
  445. _user: dict = Depends(require_admin_or_super_admin),
  446. db: Session = Depends(get_db),
  447. ):
  448. try:
  449. tenant_no = get_tenant_no(db, _user)
  450. user_info = crm_user_info(_user)
  451. list_body = body or ContractTemplateExportBody()
  452. filters = list_body.model_dump(
  453. by_alias=True,
  454. exclude={"pageNum", "pageSize"},
  455. exclude_none=True,
  456. )
  457. rows = export_contract_templates(db, tenant_no, filters=filters)
  458. return export_rows_to_xlsx_response(
  459. db,
  460. tenant_no=tenant_no,
  461. sheet_title="合同模板",
  462. columns=CONTRACT_TEMPLATE_EXPORT_COLUMNS,
  463. rows=rows,
  464. filename_stem=f"合同模板_{datetime.now().strftime('%Y%m%d%H%M%S')}",
  465. include_legacy_filename=False,
  466. )
  467. except ValueError as e:
  468. return error_response(400, str(e))
  469. except Exception as e:
  470. return error_response(500, str(e))
  471. # --- 审批记录独立页 ---
  472. @router.get("/contract/approval/list")
  473. async def contract_approval_list(
  474. pageNum: int = Query(1, ge=1),
  475. pageSize: int = Query(10, ge=1, le=100),
  476. contractId: Optional[str] = None,
  477. contractNo: Optional[str] = None,
  478. contractName: Optional[str] = None,
  479. approverName: Optional[str] = None,
  480. approvalResult: Optional[str] = None,
  481. beginTime: Optional[str] = None,
  482. endTime: Optional[str] = None,
  483. _user: dict = Depends(require_admin_or_super_admin),
  484. db: Session = Depends(get_db),
  485. ):
  486. try:
  487. tenant_no = get_tenant_no(db, _user)
  488. user_info = crm_user_info(_user)
  489. query = ContractApprovalListQuery(
  490. pageNum=pageNum,
  491. pageSize=pageSize,
  492. contractId=contractId,
  493. contractNo=contractNo,
  494. contractName=contractName,
  495. approverName=approverName,
  496. approvalResult=approvalResult,
  497. beginTime=beginTime,
  498. endTime=endTime,
  499. )
  500. rows, total = list_contract_approvals_page(
  501. db,
  502. tenant_no,
  503. page=query.pageNum,
  504. page_size=query.pageSize,
  505. filters=query.model_dump(by_alias=True, exclude={"pageNum", "pageSize"}, exclude_none=True),
  506. )
  507. return success_response(
  508. {
  509. "list": rows,
  510. "rows": rows,
  511. "total": total,
  512. "pageNum": query.pageNum,
  513. "pageSize": query.pageSize,
  514. "totalPages": total_pages(total, query.pageSize),
  515. }
  516. )
  517. except ValueError as e:
  518. return error_response(400, str(e))
  519. except Exception as e:
  520. return error_response(500, str(e))
  521. @router.get("/contract/approval/{approval_id}")
  522. async def contract_approval_detail(
  523. approval_id: str,
  524. _user: dict = Depends(require_admin_or_super_admin),
  525. db: Session = Depends(get_db),
  526. ):
  527. try:
  528. tenant_no = get_tenant_no(db, _user)
  529. user_info = crm_user_info(_user)
  530. detail = get_contract_approval_detail(db, approval_id, tenant_no=tenant_no)
  531. return success_response(detail)
  532. except ValueError as e:
  533. return error_response(400, str(e))
  534. except Exception as e:
  535. return error_response(500, str(e))
  536. @router.post("/contract/approval/pass")
  537. async def contract_approval_pass(
  538. body: ContractApprovalPassBody,
  539. _user: dict = Depends(require_admin_or_super_admin),
  540. db: Session = Depends(get_db),
  541. ):
  542. try:
  543. user_id = _user.get("user_id", "") or _user.get("id", "")
  544. approve_pass(db, body.id, approval_opinion=body.approvalOpinion or "", user_id=user_id)
  545. db.commit()
  546. return success_response(None, message="审批通过")
  547. except ValueError as e:
  548. return error_response(400, str(e))
  549. except Exception as e:
  550. return error_response(500, str(e))
  551. @router.post("/contract/approval/reject")
  552. async def contract_approval_reject(
  553. body: ContractApprovalRejectBody,
  554. _user: dict = Depends(require_admin_or_super_admin),
  555. db: Session = Depends(get_db),
  556. ):
  557. try:
  558. user_id = _user.get("user_id", "") or _user.get("id", "")
  559. approve_reject(db, body.id, approval_opinion=body.approvalOpinion, user_id=user_id)
  560. db.commit()
  561. return success_response(None, message="已驳回")
  562. except ValueError as e:
  563. return error_response(400, str(e))
  564. except Exception as e:
  565. return error_response(500, str(e))
  566. @router.post("/contract/approval/transfer")
  567. async def contract_approval_transfer(
  568. body: ContractApprovalTransferBody,
  569. _user: dict = Depends(require_admin_or_super_admin),
  570. db: Session = Depends(get_db),
  571. ):
  572. try:
  573. user_id = _user.get("user_id", "") or _user.get("id", "")
  574. approve_transfer(
  575. db,
  576. body.id,
  577. target_approver_id=body.targetApproverId,
  578. transfer_reason=body.transferReason,
  579. user_id=user_id,
  580. )
  581. db.commit()
  582. return success_response(None, message="转审成功")
  583. except ValueError as e:
  584. return error_response(400, str(e))
  585. except Exception as e:
  586. return error_response(500, str(e))
  587. @router.post("/contract/approval/export")
  588. async def contract_approval_export(
  589. body: ContractApprovalExportBody = None,
  590. _user: dict = Depends(require_admin_or_super_admin),
  591. db: Session = Depends(get_db),
  592. ):
  593. try:
  594. tenant_no = get_tenant_no(db, _user)
  595. user_info = crm_user_info(_user)
  596. list_body = body or ContractApprovalExportBody()
  597. filters = list_body.model_dump(
  598. by_alias=True,
  599. exclude={"pageNum", "pageSize"},
  600. exclude_none=True,
  601. )
  602. rows = export_contract_approvals(db, tenant_no, filters=filters)
  603. return export_rows_to_xlsx_response(
  604. db,
  605. tenant_no=tenant_no,
  606. sheet_title="合同审批记录",
  607. columns=CONTRACT_APPROVAL_EXPORT_COLUMNS,
  608. rows=rows,
  609. filename_stem=f"合同审批_{datetime.now().strftime('%Y%m%d%H%M%S')}",
  610. include_legacy_filename=False,
  611. )
  612. except ValueError as e:
  613. return error_response(400, str(e))
  614. except Exception as e:
  615. return error_response(500, str(e))
  616. @router.post("/contract/approval/refreshNames")
  617. async def contract_approval_refresh_names(
  618. body: ContractApprovalRefreshNamesBody = None,
  619. _user: dict = Depends(require_admin_or_super_admin),
  620. db: Session = Depends(get_db),
  621. ):
  622. try:
  623. req = body or ContractApprovalRefreshNamesBody()
  624. count = refresh_approver_names(db, contract_id=req.contractId)
  625. db.commit()
  626. return success_response(count)
  627. except ValueError as e:
  628. return error_response(400, str(e))
  629. except Exception as e:
  630. return error_response(500, str(e))