settlement_reports.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. """结算报表导出数据 API(01–06 独立查询,前端再生成 Excel)。"""
  2. from __future__ import annotations
  3. from typing import Optional
  4. from fastapi import APIRouter, Depends, Query
  5. from sqlalchemy.orm import Session
  6. from app.api.admin import (
  7. _effective_settlement_region_id,
  8. get_admin_allowed_region_ids,
  9. get_admin_region_filter,
  10. require_admin,
  11. )
  12. from app.core.database import get_db
  13. from app.core.response import error_response, success_response
  14. from app.services import settlement_reports as svc
  15. router = APIRouter(prefix="/web/admin/settlement-reports", tags=["结算报表导出"])
  16. def _resolve_eff_region(
  17. db: Session,
  18. current_user: dict,
  19. region_id: Optional[str],
  20. ):
  21. allowed_region_ids = get_admin_allowed_region_ids(db, current_user)
  22. if allowed_region_ids is not None and region_id and region_id not in allowed_region_ids:
  23. return None, error_response(403, "无权访问该区域数据")
  24. admin_region_id = get_admin_region_filter(db, current_user)
  25. # 多区域运营:允许按 Tab 的 regionId 筛选(在权限集合内)
  26. if allowed_region_ids is not None and len(allowed_region_ids) > 1 and region_id:
  27. eff = region_id
  28. else:
  29. eff = _effective_settlement_region_id(admin_region_id, region_id)
  30. return eff, None
  31. def _split_ids(raw: Optional[str]) -> Optional[list]:
  32. ids = [x.strip() for x in (raw or "").split(",") if x.strip()]
  33. return ids or None
  34. @router.get("/client-order-lines")
  35. def export_client_order_lines(
  36. regionId: Optional[str] = Query(None),
  37. clientId: Optional[str] = Query(None),
  38. keyword: Optional[str] = Query(None),
  39. startDate: Optional[str] = Query(None),
  40. endDate: Optional[str] = Query(None),
  41. orderIds: Optional[str] = Query(None, description="逗号分隔订单ID,优先于日期筛选"),
  42. yearMonth: Optional[str] = Query(None, description="YYYY-MM;单月兼容"),
  43. yearMonthStart: Optional[str] = Query(None, description="YYYY-MM 起始月"),
  44. yearMonthEnd: Optional[str] = Query(None, description="YYYY-MM 结束月"),
  45. db: Session = Depends(get_db),
  46. current_user: dict = Depends(require_admin),
  47. ):
  48. eff, err = _resolve_eff_region(db, current_user, regionId)
  49. if err is not None:
  50. return err
  51. try:
  52. rows = svc.build_client_order_lines(
  53. db,
  54. region_id=eff,
  55. client_id=clientId,
  56. keyword=keyword,
  57. start=startDate,
  58. end=endDate,
  59. order_ids=_split_ids(orderIds),
  60. year_month=yearMonth,
  61. year_month_start=yearMonthStart,
  62. year_month_end=yearMonthEnd,
  63. )
  64. return success_response({"list": rows, "total": len(rows)})
  65. except ValueError as e:
  66. return error_response(400, str(e))
  67. @router.get("/client-monthly")
  68. def export_client_monthly(
  69. yearMonth: Optional[str] = Query(None, description="YYYY-MM;单月兼容"),
  70. yearMonthStart: Optional[str] = Query(None, description="YYYY-MM 起始月"),
  71. yearMonthEnd: Optional[str] = Query(None, description="YYYY-MM 结束月"),
  72. regionId: Optional[str] = Query(None),
  73. db: Session = Depends(get_db),
  74. current_user: dict = Depends(require_admin),
  75. ):
  76. eff, err = _resolve_eff_region(db, current_user, regionId)
  77. if err is not None:
  78. return err
  79. try:
  80. rows = svc.build_client_monthly_summary(
  81. db,
  82. region_id=eff,
  83. year_month=yearMonth,
  84. year_month_start=yearMonthStart,
  85. year_month_end=yearMonthEnd,
  86. )
  87. return success_response({"list": rows, "total": len(rows)})
  88. except ValueError as e:
  89. return error_response(400, str(e))
  90. @router.get("/supplier-supply-lines")
  91. def export_supplier_supply_lines(
  92. regionId: Optional[str] = Query(None),
  93. supplierId: Optional[str] = Query(None),
  94. keyword: Optional[str] = Query(None),
  95. startDate: Optional[str] = Query(None),
  96. endDate: Optional[str] = Query(None),
  97. orderIds: Optional[str] = Query(None, description="逗号分隔订单ID,优先于日期筛选"),
  98. yearMonth: Optional[str] = Query(None, description="YYYY-MM;单月兼容"),
  99. yearMonthStart: Optional[str] = Query(None, description="YYYY-MM 起始月"),
  100. yearMonthEnd: Optional[str] = Query(None, description="YYYY-MM 结束月"),
  101. db: Session = Depends(get_db),
  102. current_user: dict = Depends(require_admin),
  103. ):
  104. eff, err = _resolve_eff_region(db, current_user, regionId)
  105. if err is not None:
  106. return err
  107. try:
  108. rows = svc.build_supplier_supply_lines(
  109. db,
  110. region_id=eff,
  111. supplier_id=supplierId,
  112. keyword=keyword,
  113. start=startDate,
  114. end=endDate,
  115. order_ids=_split_ids(orderIds),
  116. year_month=yearMonth,
  117. year_month_start=yearMonthStart,
  118. year_month_end=yearMonthEnd,
  119. )
  120. return success_response({"list": rows, "total": len(rows)})
  121. except ValueError as e:
  122. return error_response(400, str(e))
  123. @router.get("/supplier-monthly")
  124. def export_supplier_monthly(
  125. yearMonth: Optional[str] = Query(None, description="YYYY-MM;单月兼容"),
  126. yearMonthStart: Optional[str] = Query(None, description="YYYY-MM 起始月"),
  127. yearMonthEnd: Optional[str] = Query(None, description="YYYY-MM 结束月"),
  128. regionId: Optional[str] = Query(None),
  129. db: Session = Depends(get_db),
  130. current_user: dict = Depends(require_admin),
  131. ):
  132. eff, err = _resolve_eff_region(db, current_user, regionId)
  133. if err is not None:
  134. return err
  135. try:
  136. rows = svc.build_supplier_monthly_summary(
  137. db,
  138. region_id=eff,
  139. year_month=yearMonth,
  140. year_month_start=yearMonthStart,
  141. year_month_end=yearMonthEnd,
  142. )
  143. return success_response({"list": rows, "total": len(rows)})
  144. except ValueError as e:
  145. return error_response(400, str(e))
  146. @router.get("/delivery-lines")
  147. def export_delivery_lines(
  148. regionId: Optional[str] = Query(None),
  149. keyword: Optional[str] = Query(None),
  150. status: Optional[str] = Query(None),
  151. deliverId: Optional[str] = Query(None),
  152. startDate: Optional[str] = Query(None),
  153. endDate: Optional[str] = Query(None),
  154. yearMonth: Optional[str] = Query(None, description="YYYY-MM;单月兼容"),
  155. yearMonthStart: Optional[str] = Query(None, description="YYYY-MM 起始月"),
  156. yearMonthEnd: Optional[str] = Query(None, description="YYYY-MM 结束月"),
  157. db: Session = Depends(get_db),
  158. current_user: dict = Depends(require_admin),
  159. ):
  160. eff, err = _resolve_eff_region(db, current_user, regionId)
  161. if err is not None:
  162. return err
  163. try:
  164. rows = svc.build_delivery_lines(
  165. db,
  166. region_id=eff,
  167. keyword=keyword,
  168. status=status,
  169. deliver_id=deliverId,
  170. start=startDate,
  171. end=endDate,
  172. year_month=yearMonth,
  173. year_month_start=yearMonthStart,
  174. year_month_end=yearMonthEnd,
  175. )
  176. return success_response({"list": rows, "total": len(rows)})
  177. except ValueError as e:
  178. return error_response(400, str(e))
  179. @router.get("/delivery-monthly")
  180. def export_delivery_monthly(
  181. yearMonth: Optional[str] = Query(None, description="YYYY-MM;单月兼容"),
  182. yearMonthStart: Optional[str] = Query(None, description="YYYY-MM 起始月"),
  183. yearMonthEnd: Optional[str] = Query(None, description="YYYY-MM 结束月"),
  184. regionId: Optional[str] = Query(None),
  185. db: Session = Depends(get_db),
  186. current_user: dict = Depends(require_admin),
  187. ):
  188. eff, err = _resolve_eff_region(db, current_user, regionId)
  189. if err is not None:
  190. return err
  191. try:
  192. rows = svc.build_delivery_monthly_summary(
  193. db,
  194. region_id=eff,
  195. year_month=yearMonth,
  196. year_month_start=yearMonthStart,
  197. year_month_end=yearMonthEnd,
  198. )
  199. return success_response({"list": rows, "total": len(rows)})
  200. except ValueError as e:
  201. return error_response(400, str(e))