You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

284 lines
13 KiB

7 months ago
8 months ago
8 months ago
7 months ago
8 months ago
7 months ago
8 months ago
7 months ago
8 months ago
7 months ago
8 months ago
8 months ago
7 months ago
8 months ago
7 months ago
8 months ago
8 months ago
8 months ago
  1. from fastapi import Depends, APIRouter, status, Query, Path, HTTPException,Request
  2. from internal.models import *
  3. from internal.database import fetch_one, fetch_all, execute_query, response_success, raise_if_exists, raise_if_not_found
  4. from dependencies import get_current_active_user
  5. from datetime import datetime
  6. from limiter_config import limiter
  7. router = APIRouter(
  8. prefix="/disburses",
  9. tags=['支出管理']
  10. )
  11. @router.get("/line/nighweek")
  12. @limiter.limit("10/minute")
  13. async def disburse_list(request: Request,):
  14. select_query = """
  15. -- Generate dates for the current week (Monday to Sunday)
  16. SELECT
  17. dates.selected_date AS create_date,
  18. COALESCE(SUM(d.disburseprice), 0) AS total_disburseprice
  19. FROM (
  20. SELECT CURDATE() - INTERVAL (WEEKDAY(CURDATE()) - x.a) DAY AS selected_date
  21. FROM (
  22. SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2
  23. UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5
  24. UNION ALL SELECT 6
  25. ) x
  26. ) AS dates
  27. LEFT JOIN disburses d ON DATE(d.create_at) = dates.selected_date
  28. WHERE dates.selected_date BETWEEN CURDATE() - INTERVAL WEEKDAY(CURDATE()) DAY
  29. AND CURDATE() + INTERVAL (6 - WEEKDAY(CURDATE())) DAY
  30. GROUP BY dates.selected_date
  31. ORDER BY dates.selected_date ASC;
  32. """
  33. disburse_list = fetch_all(select_query)
  34. return response_success(disburse_list, "disburse get list success")
  35. @router.get("/line/nighmonth")
  36. @limiter.limit("10/minute")
  37. async def disburse_list(request: Request,):
  38. select_query = """
  39. -- Generate dates for the current month (1st to last day)
  40. SELECT
  41. dates.selected_date AS create_date,
  42. COALESCE(SUM(d.disburseprice), 0) AS total_disburseprice
  43. FROM (
  44. SELECT DATE_FORMAT(CURDATE() - INTERVAL (DAY(CURDATE()) - 1) DAY + INTERVAL x.a DAY, '%Y-%m-%d') AS selected_date
  45. FROM (
  46. SELECT @rownum := @rownum + 1 AS a
  47. FROM (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
  48. UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11
  49. UNION ALL SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15 UNION ALL SELECT 16
  50. UNION ALL SELECT 17 UNION ALL SELECT 18 UNION ALL SELECT 19 UNION ALL SELECT 20 UNION ALL SELECT 21
  51. UNION ALL SELECT 22 UNION ALL SELECT 23 UNION ALL SELECT 24 UNION ALL SELECT 25 UNION ALL SELECT 26
  52. UNION ALL SELECT 27 UNION ALL SELECT 28 UNION ALL SELECT 29 UNION ALL SELECT 30 UNION ALL SELECT 31) t1,
  53. (SELECT @rownum := -1) t2
  54. ) x
  55. WHERE DATE_FORMAT(CURDATE() - INTERVAL (DAY(CURDATE()) - 1) DAY + INTERVAL x.a DAY, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m')
  56. ) AS dates
  57. LEFT JOIN disburses d ON DATE(d.create_at) = dates.selected_date
  58. GROUP BY dates.selected_date
  59. ORDER BY dates.selected_date ASC;
  60. """
  61. disburse_list = fetch_all(select_query)
  62. return response_success(disburse_list, "disburse get list success")
  63. @router.get("/line/nighyear")
  64. @limiter.limit("10/minute")
  65. async def disburse_list(request: Request,):
  66. select_query = """
  67. -- Generate months for the current year (January to December)
  68. SELECT
  69. DATE_FORMAT(months.selected_month, '%Y-%m') AS create_date, -- Only keep the year and month
  70. COALESCE(SUM(d.disburseprice), 0) AS total_disburseprice
  71. FROM (
  72. -- Generate months from January to December of the current year
  73. SELECT DATE_FORMAT(CONCAT(YEAR(CURDATE()), '-', LPAD(x.a, 2, '0'), '-01'), '%Y-%m-01') AS selected_month
  74. FROM (
  75. SELECT 1 AS a UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
  76. UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11
  77. UNION ALL SELECT 12
  78. ) x
  79. ) AS months
  80. LEFT JOIN disburses d ON DATE_FORMAT(d.create_at, '%Y-%m') = DATE_FORMAT(months.selected_month, '%Y-%m') -- Match by year and month only
  81. AND d.create_at >= DATE_FORMAT(CURDATE(), '%Y-01-01')
  82. AND d.create_at < DATE_FORMAT(CURDATE() + INTERVAL 1 YEAR, '%Y-01-01')
  83. GROUP BY DATE_FORMAT(months.selected_month, '%Y-%m') -- Group by year and month only
  84. ORDER BY create_date ASC;
  85. """
  86. disburse_list = fetch_all(select_query)
  87. return response_success(disburse_list, "disburse get list success")
  88. @router.get("/pie/nighweek")
  89. @limiter.limit("10/minute")
  90. async def classified_list(request: Request,):
  91. select_query = """
  92. -- Generate classified data for the current week (Monday to Sunday)
  93. SELECT
  94. t.typename AS name,
  95. COALESCE(SUM(daily_totals.value), 0) AS value
  96. FROM (
  97. -- Generate dates for the current week
  98. SELECT CURDATE() - INTERVAL (WEEKDAY(CURDATE()) - x.a) DAY AS selected_date
  99. FROM (
  100. SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2
  101. UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5
  102. UNION ALL SELECT 6
  103. ) x
  104. ) AS dates
  105. CROSS JOIN disbursetypes t -- Cross join to combine all dates with all typenames
  106. LEFT JOIN (
  107. -- Subquery to aggregate daily totals per type
  108. SELECT
  109. DATE(d.create_at) AS create_date,
  110. t.typename AS name,
  111. SUM(d.disburseprice) AS value
  112. FROM disburses d
  113. JOIN disbursetypes t ON d.typeid = t.id
  114. WHERE DATE(d.create_at) BETWEEN CURDATE() - INTERVAL WEEKDAY(CURDATE()) DAY
  115. AND CURDATE() + INTERVAL (6 - WEEKDAY(CURDATE())) DAY
  116. GROUP BY DATE(d.create_at), t.typename
  117. ) AS daily_totals ON daily_totals.create_date = dates.selected_date AND daily_totals.name = t.typename
  118. GROUP BY t.typename
  119. ORDER BY t.typename ASC;
  120. """
  121. classified_list = fetch_all(select_query)
  122. return response_success(classified_list, "disburse get list success")
  123. @router.get("/pie/nighmonth")
  124. @limiter.limit("10/minute")
  125. async def classified_list(request: Request,):
  126. select_query = """
  127. -- Generate classified data for the current month (1st to last day of the month)
  128. SELECT
  129. t.typename AS name,
  130. COALESCE(SUM(daily_totals.value), 0) AS value
  131. FROM (
  132. -- Generate dates for the current month
  133. SELECT DATE_FORMAT(CURDATE() - INTERVAL (DAY(CURDATE()) - 1) DAY + INTERVAL x.a DAY, '%Y-%m-%d') AS selected_date
  134. FROM (
  135. SELECT @rownum := @rownum + 1 AS a
  136. FROM (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
  137. UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11
  138. UNION ALL SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15 UNION ALL SELECT 16
  139. UNION ALL SELECT 17 UNION ALL SELECT 18 UNION ALL SELECT 19 UNION ALL SELECT 20 UNION ALL SELECT 21
  140. UNION ALL SELECT 22 UNION ALL SELECT 23 UNION ALL SELECT 24 UNION ALL SELECT 25 UNION ALL SELECT 26
  141. UNION ALL SELECT 27 UNION ALL SELECT 28 UNION ALL SELECT 29 UNION ALL SELECT 30 UNION ALL SELECT 31) t1,
  142. (SELECT @rownum := -1) t2
  143. ) x
  144. WHERE DATE_FORMAT(CURDATE() - INTERVAL (DAY(CURDATE()) - 1) DAY + INTERVAL x.a DAY, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m')
  145. ) AS dates
  146. CROSS JOIN disbursetypes t -- Cross join to combine all dates with all typenames
  147. LEFT JOIN (
  148. -- Subquery to aggregate daily totals per type
  149. SELECT
  150. DATE(d.create_at) AS create_date,
  151. t.typename AS name,
  152. SUM(d.disburseprice) AS value
  153. FROM disburses d
  154. JOIN disbursetypes t ON d.typeid = t.id
  155. WHERE DATE(d.create_at) BETWEEN DATE_FORMAT(CURDATE() - INTERVAL (DAY(CURDATE()) - 1) DAY, '%Y-%m-%d')
  156. AND LAST_DAY(CURDATE())
  157. GROUP BY DATE(d.create_at), t.typename
  158. ) AS daily_totals ON daily_totals.create_date = dates.selected_date AND daily_totals.name = t.typename
  159. GROUP BY t.typename
  160. ORDER BY t.typename ASC;
  161. """
  162. classified_list = fetch_all(select_query)
  163. return response_success(classified_list, "disburse get list success")
  164. @router.get("/pie/nighyear")
  165. @limiter.limit("10/minute")
  166. async def classified_list(request: Request,):
  167. select_query = """
  168. -- Generate classified data for the current year (January to December)
  169. SELECT
  170. t.typename AS name,
  171. COALESCE(SUM(monthly_totals.value), 0) AS value
  172. FROM (
  173. -- Generate months for the current year
  174. SELECT DATE_FORMAT(CONCAT(YEAR(CURDATE()), '-', LPAD(x.a, 2, '0'), '-01'), '%Y-%m-01') AS selected_month
  175. FROM (
  176. SELECT 1 AS a UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
  177. UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11
  178. UNION ALL SELECT 12
  179. ) x
  180. ) AS months
  181. CROSS JOIN disbursetypes t -- Cross join to combine all months with all typenames
  182. LEFT JOIN (
  183. -- Subquery to aggregate monthly totals per type
  184. SELECT
  185. DATE_FORMAT(d.create_at, '%Y-%m-01') AS create_month,
  186. t.typename AS name,
  187. SUM(d.disburseprice) AS value
  188. FROM disburses d
  189. JOIN disbursetypes t ON d.typeid = t.id
  190. WHERE DATE_FORMAT(d.create_at, '%Y-%m') BETWEEN DATE_FORMAT(CURDATE() - INTERVAL (YEAR(CURDATE()) - YEAR(d.create_at)) YEAR, '%Y-01')
  191. AND DATE_FORMAT(CURDATE(), '%Y-12')
  192. GROUP BY DATE_FORMAT(d.create_at, '%Y-%m-01'), t.typename
  193. ) AS monthly_totals ON monthly_totals.create_month = months.selected_month AND monthly_totals.name = t.typename
  194. GROUP BY t.typename
  195. ORDER BY t.typename ASC;
  196. """
  197. classified_list = fetch_all(select_query)
  198. return response_success(classified_list, "disburse get list success")
  199. @router.get("/list/consume")
  200. @limiter.limit("10/minute")
  201. async def consume_list(request: Request,days: int):
  202. current_year = datetime.now().year
  203. target_year = current_year - days
  204. select_query = f"""
  205. SELECT SUM(d.disburseprice) AS data, t.typename AS name, DATE_FORMAT(d.create_at, '%Y-%m') AS date
  206. FROM disburses d JOIN disbursetypes t ON d.typeid = t.id
  207. WHERE YEAR(d.create_at) = {target_year}
  208. GROUP BY t.typename, DATE_FORMAT(d.create_at, '%Y-%m')
  209. ORDER BY DATE_FORMAT(d.create_at, '%Y-%m');
  210. """
  211. consume_list = fetch_all(select_query)
  212. result = {}
  213. for entry in consume_list:
  214. name = entry['name']
  215. date = entry['date']
  216. data = entry['data']
  217. if name not in result:
  218. result[name] = [0] * 12
  219. month_index = int(date.split('-')[1]) - 1
  220. result[name][month_index] = data
  221. final_result = [{"name": name, "data": data}
  222. for name, data in result.items()]
  223. return response_success(final_result, "disburse get list success")
  224. @router.get("/list/calendar")
  225. @limiter.limit("10/minute")
  226. async def calendar_list(request: Request,):
  227. select_query = """
  228. SELECT t.typename AS NAME, YEAR(d.create_at) AS YEAR, SUM(d.disburseprice) AS total_amount
  229. FROM disburses d
  230. JOIN disbursetypes t ON d.typeid = t.id
  231. GROUP BY t.typename, YEAR(d.create_at)
  232. ORDER BY t.typename, YEAR(d.create_at);
  233. """
  234. calendar_list = fetch_all(select_query)
  235. # Initialize dictionaries to store the transformed data
  236. transformed_data = {}
  237. years = set()
  238. # Process each row from the query result
  239. for row in calendar_list:
  240. name = row['NAME']
  241. year = row['YEAR']
  242. total_amount = row['total_amount']
  243. if name not in transformed_data:
  244. transformed_data[name] = {}
  245. transformed_data[name][year] = total_amount
  246. years.add(year)
  247. # Prepare the final result in the desired format
  248. sorted_years = sorted(years) # Sort years in ascending order
  249. headers = ['name'] + [str(year) for year in sorted_years] # Create headers
  250. final_result = [headers] # Initialize with headers
  251. for name, year_data in transformed_data.items():
  252. row = [name]
  253. for year in sorted_years:
  254. row.append(year_data.get(year, 0)) # Append data or 0 if not available
  255. final_result.append(row)
  256. return response_success(final_result, "disburse get list success")