controller.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. from datetime import datetime, timedelta
  2. import io
  3. from typing import Annotated, Any, Optional, Dict
  4. from fastapi import APIRouter, Body, Depends, Path, Query
  5. from fastapi.responses import JSONResponse, StreamingResponse
  6. from redis.asyncio import Redis
  7. from app.api.v1.module_system.auth.schema import AuthSchema
  8. from app.common.response import ResponseSchema, SuccessResponse
  9. from app.core.dependencies import AuthPermission
  10. from app.core.logger import log
  11. from app.core.router_class import OperationLogRoute
  12. from app.core.base_params import PaginationQueryParam
  13. from app.core.dependencies import redis_getter
  14. from .schema import (
  15. AccountAuthorizeApplySchema,
  16. AccountAuthorizeApplyOutSchema,
  17. AccountCreateSchema,
  18. AccountDepositSchema,
  19. AccountDepositOutSchema,
  20. AccountOperationOutSchema,
  21. AccountQuerySchema,
  22. AccountTransferSchema,
  23. AccountWithdrawSchema,
  24. ReceiptApplySchema,
  25. ReceiptApplyOutSchema,
  26. ReceiptQueryOutSchema,
  27. TransferListOutSchema,
  28. TransferOutSchema,
  29. TransferSyncStatusSchema,
  30. TransferTaskOutSchema,
  31. ConsumeDetailOutSchema,
  32. )
  33. from .service import AccountService
  34. AccountRouter = APIRouter(
  35. route_class=OperationLogRoute,
  36. prefix="/account",
  37. tags=["资金专户"],
  38. )
  39. # 转账金额统计
  40. @AccountRouter.get(
  41. "/stat/transfer/amount",
  42. summary="统计转账金额",
  43. description="统计企业在指定时间范围内的转账总金额以及每天的转账金额",
  44. response_model=ResponseSchema[Dict],
  45. )
  46. async def stat_transfer_amount_controller(
  47. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:transfer"]))],
  48. tenant_id: Annotated[Optional[int], Query(description="租户ID")] = None,
  49. enterprise_id: Annotated[Optional[str], Query(description="企业ID")] = None,
  50. payee_type: Annotated[Optional[str], Query(description="收款方类型: ALIPAY_ACCOUNT/BANK_CARD")] = None,
  51. ) -> JSONResponse:
  52. """统计转账金额"""
  53. from datetime import datetime, timedelta, date
  54. # 1. 获取当前时间(建议统一使用 UTC 或指定时区)
  55. now = datetime.now()
  56. today = date.today()
  57. # --- 1:统计当天转账金额 ---
  58. # 目标:今天 00:00:00 到 明天 00:00:00 (不包含明天0点,即覆盖全天)
  59. start_of_today = datetime.combine(today, datetime.min.time()) # 今天凌晨 00:00:00
  60. end_of_today = start_of_today + timedelta(days=1) # 明天凌晨 00:00:00
  61. amount_of_today = await AccountService.stat_transfer_amount_service(
  62. auth=auth,
  63. tenant_id=tenant_id,
  64. enterprise_id=enterprise_id,
  65. start_date=start_of_today,
  66. end_date=end_of_today,
  67. payee_type=payee_type,
  68. )
  69. start_of_7days_ago = datetime.combine(today - timedelta(days=7), datetime.min.time())
  70. amount_of_7days = await AccountService.stat_transfer_amount_service(
  71. auth=auth,
  72. tenant_id=tenant_id,
  73. enterprise_id=enterprise_id,
  74. start_date=start_of_7days_ago,
  75. end_date=now,
  76. payee_type=payee_type,
  77. )
  78. amount_of_all = await AccountService.stat_transfer_amount_service(
  79. auth=auth,
  80. tenant_id=tenant_id,
  81. enterprise_id=enterprise_id,
  82. start_date=None,
  83. end_date=None,
  84. payee_type=payee_type,
  85. )
  86. return SuccessResponse(data={
  87. "amount_of_today": amount_of_today,
  88. "amount_of_7days": amount_of_7days,
  89. "amount_of_all": amount_of_all,
  90. }, msg="统计转账金额成功")
  91. @AccountRouter.get(
  92. "/stat/consume/amount",
  93. summary="统计消费金额",
  94. description="统计企业在指定时间范围内的消费总金额",
  95. response_model=ResponseSchema[Dict],
  96. )
  97. async def stat_consume_amount_controller(
  98. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:transfer"]))],
  99. tenant_id: Annotated[Optional[int], Query(description="租户ID")] = None,
  100. enterprise_id: Annotated[Optional[str], Query(description="企业ID")] = None,
  101. ) -> JSONResponse:
  102. """统计消费金额"""
  103. from datetime import datetime, timedelta, date
  104. now = datetime.now()
  105. today = date.today()
  106. # 今天
  107. start_of_today = datetime.combine(today, datetime.min.time())
  108. end_of_today = start_of_today + timedelta(days=1)
  109. amount_of_today = await AccountService.stat_consume_amount_service(
  110. auth=auth, tenant_id=tenant_id, enterprise_id=enterprise_id,
  111. start_date=start_of_today, end_date=end_of_today,
  112. )
  113. # 近7天
  114. start_of_7days_ago = datetime.combine(today - timedelta(days=7), datetime.min.time())
  115. amount_of_7days = await AccountService.stat_consume_amount_service(
  116. auth=auth, tenant_id=tenant_id, enterprise_id=enterprise_id,
  117. start_date=start_of_7days_ago, end_date=now,
  118. )
  119. # 全部
  120. amount_of_all = await AccountService.stat_consume_amount_service(
  121. auth=auth, tenant_id=tenant_id, enterprise_id=enterprise_id,
  122. start_date=None, end_date=None,
  123. )
  124. return SuccessResponse(data={
  125. "amount_of_today": amount_of_today,
  126. "amount_of_7days": amount_of_7days,
  127. "amount_of_all": amount_of_all,
  128. }, msg="统计消费金额成功")
  129. @AccountRouter.get(
  130. "/stat/summary/amount",
  131. summary="汇总统计金额",
  132. description="统计企业在指定时间范围内的汇总金额(消费+转账)",
  133. response_model=ResponseSchema[Dict],
  134. )
  135. async def stat_summary_amount_controller(
  136. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:transfer"]))],
  137. tenant_id: Annotated[Optional[int], Query(description="租户ID")] = None,
  138. enterprise_id: Annotated[Optional[str], Query(description="企业ID")] = None,
  139. payee_type: Annotated[Optional[str], Query(description="收款方类型: ALIPAY_ACCOUNT/BANK_CARD")] = None,
  140. ) -> JSONResponse:
  141. """汇总统计金额(消费+转账),payee_type 仅过滤转账部分"""
  142. from datetime import datetime, timedelta, date
  143. now = datetime.now()
  144. today = date.today()
  145. start_of_today = datetime.combine(today, datetime.min.time())
  146. end_of_today = start_of_today + timedelta(days=1)
  147. amount_of_today = await AccountService.stat_summary_amount_service(
  148. auth=auth, tenant_id=tenant_id, enterprise_id=enterprise_id,
  149. start_date=start_of_today, end_date=end_of_today, payee_type=payee_type,
  150. )
  151. start_of_7days_ago = datetime.combine(today - timedelta(days=7), datetime.min.time())
  152. amount_of_7days = await AccountService.stat_summary_amount_service(
  153. auth=auth, tenant_id=tenant_id, enterprise_id=enterprise_id,
  154. start_date=start_of_7days_ago, end_date=now, payee_type=payee_type,
  155. )
  156. amount_of_all = await AccountService.stat_summary_amount_service(
  157. auth=auth, tenant_id=tenant_id, enterprise_id=enterprise_id,
  158. start_date=None, end_date=None, payee_type=payee_type,
  159. )
  160. return SuccessResponse(data={
  161. "amount_of_today": amount_of_today,
  162. "amount_of_7days": amount_of_7days,
  163. "amount_of_all": amount_of_all,
  164. }, msg="统计汇总金额成功")
  165. @AccountRouter.post(
  166. "/authorize/apply",
  167. summary="申请转账授权签约",
  168. description="申请转账授权签约",
  169. response_model=ResponseSchema[AccountAuthorizeApplyOutSchema],
  170. )
  171. async def authorize_apply_controller(
  172. data: AccountAuthorizeApplySchema,
  173. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:authorize"]))],
  174. ) -> JSONResponse:
  175. """申请转账授权签约"""
  176. result = await AccountService.authorize_apply_service(auth=auth, data=data)
  177. log.info(f"申请转账授权签约成功: {data.enterprise_id}")
  178. return SuccessResponse(data=result, msg="申请转账授权签约成功")
  179. @AccountRouter.post(
  180. "",
  181. summary="开通资金专户",
  182. description="开通资金专户",
  183. response_model=ResponseSchema[AccountOperationOutSchema],
  184. )
  185. async def create_account_controller(
  186. data: AccountCreateSchema,
  187. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:create"]))],
  188. ) -> JSONResponse:
  189. """开通资金专户"""
  190. result = await AccountService.create_account_service(auth=auth, data=data)
  191. log.info(f"开通资金专户成功: {data.enterprise_id}")
  192. return SuccessResponse(data=result, msg="开通资金专户成功")
  193. @AccountRouter.get(
  194. "/query/{enterprise_id}",
  195. summary="查询资金专户",
  196. description="根据企业ID查询资金专户(调用支付宝接口)",
  197. response_model=ResponseSchema[list[Any]],
  198. )
  199. async def query_account_controller(
  200. # data: AccountQuerySchema,
  201. enterprise_id: Annotated[str, Path(description="企业ID")],
  202. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:detail"]))],
  203. ) -> JSONResponse:
  204. """查询资金专户"""
  205. result = await AccountService.query_account_service(auth=auth, data=AccountQuerySchema(enterprise_id=enterprise_id))
  206. log.info(f"查询资金专户成功: {enterprise_id}")
  207. return SuccessResponse(data=result, msg="查询资金专户成功")
  208. @AccountRouter.post(
  209. "/deposit",
  210. summary="资金专户充值",
  211. description="从支付宝余额向资金专户充值",
  212. response_model=ResponseSchema[AccountDepositOutSchema],
  213. )
  214. async def deposit_controller(
  215. data: AccountDepositSchema,
  216. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:deposit"]))],
  217. ) -> JSONResponse:
  218. """资金专户充值"""
  219. result = await AccountService.deposit_service(auth=auth, data=data)
  220. log.info(f"资金专户充值发起成功: {data.enterprise_id} -> {str(data.amount)}")
  221. return SuccessResponse(data=result, msg="充值页面获取成功,请跳转完成支付")
  222. @AccountRouter.post(
  223. "/transfer",
  224. summary="资金专户转账",
  225. description="从资金专户转账到支付宝账户/银行卡/资金专户",
  226. response_model=ResponseSchema[TransferTaskOutSchema],
  227. )
  228. async def transfer_controller(
  229. data: AccountTransferSchema,
  230. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:transfer"]))],
  231. ) -> JSONResponse:
  232. """资金专户转账"""
  233. result = await AccountService.transfer_service(auth=auth, data=data)
  234. log.info(f"资金专户转账发起成功: 企业: {data.enterprise_id}, 金额: {data.amount}")
  235. return SuccessResponse(data=result, msg="转账申请已提交")
  236. @AccountRouter.post(
  237. "/withdraw",
  238. summary="资金专户提现",
  239. description="从资金专户向支付宝余额提现。调用支付宝接口: alipay.commerce.ec.trans.account.withdraw",
  240. response_model=ResponseSchema[AccountOperationOutSchema],
  241. )
  242. async def withdraw_controller(
  243. data: AccountWithdrawSchema,
  244. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:withdraw"]))],
  245. ) -> JSONResponse:
  246. """
  247. 资金专户提现
  248. 接口文档: https://opendocs.alipay.com/pre-open/d651859b_alipay.commerce.ec.trans.account.withdraw
  249. 参数说明:
  250. - enterprise_id: 企业ID
  251. - account_book_id: 资金专户号
  252. - amount: 提现金额(大于0)
  253. - out_biz_no: 商家侧订单号(唯一)
  254. 返回:
  255. - enterprise_id: 企业ID
  256. - account_book_id: 资金专户号
  257. """
  258. result = await AccountService.withdraw_service(auth=auth, data=data)
  259. log.info(f"资金专户提现发起成功: 企业: {data.enterprise_id}, 金额: {data.amount}")
  260. return SuccessResponse(data=result, msg="提现申请已提交")
  261. @AccountRouter.get(
  262. "/transfer/{out_biz_no}",
  263. summary="查询转账记录详情",
  264. description="根据订单号查询转账记录",
  265. response_model=ResponseSchema[TransferOutSchema],
  266. )
  267. async def transfer_detail_controller(
  268. out_biz_no: Annotated[str, Path(description="商家侧订单号")],
  269. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:transfer:detail"]))],
  270. ) -> JSONResponse:
  271. """查询转账记录详情"""
  272. result = await AccountService.transfer_detail_service(auth=auth, out_biz_no=out_biz_no)
  273. log.info(f"查询转账记录详情成功: {out_biz_no}")
  274. return SuccessResponse(data=result, msg="查询转账记录详情成功")
  275. @AccountRouter.get(
  276. "/transfer",
  277. summary="查询转账记录列表",
  278. description="分页查询转账记录列表",
  279. response_model=ResponseSchema[TransferListOutSchema],
  280. )
  281. async def transfer_list_controller(
  282. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:transfer:list"]))],
  283. page_no: Annotated[int, Query(description="页码")] = 1,
  284. page_size: Annotated[int, Query(description="每页数量")] = 20,
  285. out_biz_no: Annotated[str | None, Query(description="订单号")] = None,
  286. status: Annotated[str | None, Query(description="状态")] = None,
  287. ) -> JSONResponse:
  288. """查询转账记录列表"""
  289. search = {}
  290. if out_biz_no:
  291. search["out_biz_no"] = out_biz_no
  292. if status:
  293. search["status"] = status
  294. result = await AccountService.transfer_list_service(
  295. auth=auth, page_no=page_no, page_size=page_size, search=search
  296. )
  297. return SuccessResponse(data=result, msg="查询转账记录列表成功")
  298. @AccountRouter.post(
  299. "/transfer/sync-status",
  300. summary="手动同步转账状态",
  301. description="手动修复卡在 DEALING 的转账记录状态(管理员在支付宝核实后使用)",
  302. response_model=ResponseSchema[dict],
  303. )
  304. async def transfer_sync_status_controller(
  305. data: TransferSyncStatusSchema,
  306. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:transfer:update"]))],
  307. ) -> JSONResponse:
  308. """手动同步转账状态"""
  309. result = await AccountService.transfer_sync_status_service(auth=auth, data=data)
  310. log.info(f"手动同步转账状态成功: out_biz_no={data.out_biz_no}, status={data.status}")
  311. return SuccessResponse(data=result, msg="同步转账状态成功")
  312. @AccountRouter.post(
  313. "/transfer/sync-all",
  314. summary="全量同步转账状态",
  315. description="自动查询所有企业卡在 DEALING 的转账,调用支付宝核实状态并更新",
  316. response_model=ResponseSchema[dict],
  317. )
  318. async def transfer_sync_all_controller(
  319. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:transfer:update"]))],
  320. ) -> JSONResponse:
  321. """全量同步转账状态"""
  322. result = await AccountService.transfer_sync_all_service(auth=auth)
  323. log.info(f"全量同步转账状态完成: {result}")
  324. return SuccessResponse(data=result, msg="全量同步完成")
  325. @AccountRouter.get(
  326. "/consume-detail",
  327. summary="账单详情查询",
  328. description="查询企业码账单详情,支持查询关联退款、订单、票据等信息",
  329. response_model=ResponseSchema[ConsumeDetailOutSchema],
  330. )
  331. async def consume_detail_query_controller(
  332. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:consume:detail"]))],
  333. pay_no: Annotated[str, Query(description="支付宝账单号")],
  334. enterprise_id: Annotated[str | None, Query(description="企业ID(2.0接口签约企业必填)")] = None,
  335. ant_shop_id: Annotated[str | None, Query(description="蚂蚁门店ID(商户服务商必填)")] = None,
  336. query_options: Annotated[str | None, Query(description="查询选项,多个用逗号分隔")] = None,
  337. ) -> JSONResponse:
  338. """
  339. 账单详情查询
  340. 调用: alipay.commerce.ec.consume.detail.query
  341. 用于查询企业码账单详情,支持查询关联退款、订单、票据等信息。
  342. - pay_no: 支付宝账单号(必填)
  343. - enterprise_id: 企业ID(2.0接口签约企业必填)
  344. - ant_shop_id: 蚂蚁门店ID(商户服务商必填)
  345. - query_options: 查询选项,支持 Refund/Order/Ticket,多个用逗号分隔
  346. """
  347. options_list = None
  348. if query_options:
  349. options_list = [opt.strip() for opt in query_options.split(",") if opt.strip()]
  350. result = await AccountService.consume_detail_query_service(
  351. auth=auth,
  352. pay_no=pay_no,
  353. enterprise_id=enterprise_id,
  354. ant_shop_id=ant_shop_id,
  355. query_options=options_list,
  356. )
  357. log.info(f"账单详情查询成功: {pay_no}")
  358. return SuccessResponse(data=result, msg="账单详情查询成功")
  359. @AccountRouter.get(
  360. "/transfer/export",
  361. summary="导出转账记录报表",
  362. description="导出指定时间范围内的转账记录为Excel文件",
  363. responses={
  364. 200: {
  365. "description": "Excel文件下载",
  366. "content": {
  367. "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": {}
  368. }
  369. }
  370. },
  371. )
  372. async def transfer_export_controller(
  373. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:transfer:list"]))],
  374. start_time: Annotated[str, Query(description="开始时间,格式:YYYY-MM-DD HH:MM:SS")],
  375. end_time: Annotated[str, Query(description="结束时间,格式:YYYY-MM-DD HH:MM:SS")],
  376. enterprise_id: Annotated[str | None, Query(description="企业ID(2.0接口签约企业必填)")] = None,
  377. ) -> StreamingResponse:
  378. """导出转账记录报表"""
  379. result = await AccountService.transfer_export_service(
  380. auth=auth, start_time=start_time, end_time=end_time, enterprise_id=enterprise_id
  381. )
  382. log.info(f"导出转账记录报表成功: {start_time} -> {end_time}")
  383. return StreamingResponse(
  384. io.BytesIO(result),
  385. media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  386. headers={
  387. "Content-Disposition": f"attachment; filename=transfer_report_{start_time}_{end_time}.xlsx"
  388. }
  389. )
  390. # @AccountRouter.post(
  391. # "/receipt/apply",
  392. # summary="申请资金回单",
  393. # description="申请资金业务回单",
  394. # response_model=ResponseSchema[ReceiptApplyOutSchema],
  395. # )
  396. # async def receipt_apply_controller(
  397. # data: ReceiptApplySchema,
  398. # auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:receipt"]))],
  399. # ) -> JSONResponse:
  400. # """申请资金回单"""
  401. # result = await AccountService.receipt_apply_service(auth=auth, data=data)
  402. # log.info(f"申请资金回单成功: {data.order_no}")
  403. # return SuccessResponse(data=result, msg="申请资金回单成功")
  404. @AccountRouter.post(
  405. "/receipt/apply",
  406. summary="申请转账业务回单",
  407. description="申请指定转账单号的业务回单,返回 file_id 用于查询状态",
  408. response_model=ResponseSchema[ReceiptApplyOutSchema],
  409. )
  410. async def receipt_apply_controller(
  411. data: ReceiptApplySchema,
  412. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:receipt"]))],
  413. redis: Annotated[Redis, Depends(redis_getter)],
  414. ) -> JSONResponse:
  415. """
  416. 申请转账业务回单
  417. 调用: alipay.commerce.ec.trans.receipt.apply
  418. 参数:
  419. - enterprise_id: 企业ID
  420. - order_no: 支付宝转账单号
  421. """
  422. file_id = await AccountService.apply_receipt_service(
  423. auth=auth,
  424. redis=redis,
  425. data=data,
  426. )
  427. log.info(f"申请转账业务回单成功: order_no={data.order_no}, file_id={file_id}")
  428. return SuccessResponse(data={"file_id": file_id}, msg="申请成功")
  429. @AccountRouter.get(
  430. "/receipt/{enterprise_id}/{file_id}",
  431. summary="查询回单状态",
  432. description="查询转账回单的处理状态和下载链接",
  433. response_model=ResponseSchema[ReceiptQueryOutSchema],
  434. )
  435. async def receipt_query_controller(
  436. enterprise_id: Annotated[str, Path(description="企业ID")],
  437. file_id: Annotated[str, Path(description="文件申请号")],
  438. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:receipt"]))],
  439. ) -> JSONResponse:
  440. """
  441. 查询回单状态
  442. 调用: alipay.commerce.ec.trans.receipt.query
  443. 参数:
  444. - file_id: 文件申请号(有效期2天)
  445. """
  446. result = await AccountService.query_receipt_service(
  447. enterprise_id=enterprise_id,
  448. file_id=file_id,
  449. )
  450. log.info(f"查询回单状态成功: file_id={file_id}, status={result['status']}")
  451. return SuccessResponse(data=result, msg="查询成功")
  452. @AccountRouter.get(
  453. "/receipt/download",
  454. summary="获取回单下载链接",
  455. description="获取回单下载链接(封装申请+查询,PROCESS状态直接返回,由前端轮询)",
  456. response_model=ResponseSchema[ReceiptQueryOutSchema],
  457. )
  458. async def receipt_download_controller(
  459. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:receipt"]))],
  460. redis: Annotated[Redis, Depends(redis_getter)],
  461. enterprise_id: Annotated[str, Query(description="企业ID")],
  462. order_no: Annotated[str, Query(description="支付宝转账单号")],
  463. ) -> JSONResponse:
  464. """
  465. 获取回单下载链接
  466. 封装完整流程:
  467. 1. 申请/获取 file_id(自动缓存)
  468. 2. 查询回单状态
  469. 3. 直接返回状态(PROCESS状态由前端主动查询)
  470. """
  471. file_id = await AccountService.apply_receipt_service(
  472. auth=auth,
  473. redis=redis,
  474. data=ReceiptApplySchema(enterprise_id=enterprise_id, order_no=order_no),
  475. )
  476. result = await AccountService.query_receipt_service(
  477. enterprise_id=enterprise_id,
  478. file_id=file_id,
  479. )
  480. log.info(f"获取回单下载链接: file_id={file_id}, status={result['status']}")
  481. return SuccessResponse(data=result, msg="操作成功")
  482. # @AccountRouter.post(
  483. # "/transfer/batch",
  484. # summary="批量资金专户转账",
  485. # description="异步批量转账,先放入队列,后台处理",
  486. # response_model=ResponseSchema[AccountTransferBatchOutSchema],
  487. # )
  488. # async def batch_transfer_controller(
  489. # data: AccountTransferBatchSchema,
  490. # auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:transfer"]))],
  491. # ) -> JSONResponse:
  492. # """批量资金专户转账(异步)"""
  493. # result = await AccountService.batch_transfer_service(auth=auth, data=data)
  494. # log.info(f"批量转账任务已提交: {result.batch_id}, 总笔数: {result.total}")
  495. # return SuccessResponse(data=result, msg="批量转账任务已提交,正在处理中")
  496. # @AccountRouter.get(
  497. # "/transfer/batch/{batch_id}",
  498. # summary="查询批量转账结果",
  499. # description="查询批量转账的处理状态和结果",
  500. # response_model=ResponseSchema[dict],
  501. # )
  502. # async def get_batch_result_controller(
  503. # batch_id: Annotated[str, Path(description="批次ID")],
  504. # auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:transfer"]))],
  505. # ) -> JSONResponse:
  506. # """查询批量转账结果"""
  507. # result = await AccountService.get_batch_result_service(auth=auth, batch_id=batch_id)
  508. # log.info(f"查询批量转账结果成功: {batch_id}")
  509. # return SuccessResponse(data=result, msg="查询批量转账结果成功")