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
284 lines
13 KiB
from fastapi import Depends, APIRouter, status, Query, Path, HTTPException,Request
|
|
from internal.models import *
|
|
from internal.database import fetch_one, fetch_all, execute_query, response_success, raise_if_exists, raise_if_not_found
|
|
from dependencies import get_current_active_user
|
|
from datetime import datetime
|
|
from limiter_config import limiter
|
|
router = APIRouter(
|
|
prefix="/disburses",
|
|
tags=['支出管理']
|
|
)
|
|
|
|
|
|
@router.get("/line/nighweek")
|
|
@limiter.limit("10/minute")
|
|
async def disburse_list(request: Request,):
|
|
select_query = """
|
|
-- Generate dates for the current week (Monday to Sunday)
|
|
SELECT
|
|
dates.selected_date AS create_date,
|
|
COALESCE(SUM(d.disburseprice), 0) AS total_disburseprice
|
|
FROM (
|
|
SELECT CURDATE() - INTERVAL (WEEKDAY(CURDATE()) - x.a) DAY AS selected_date
|
|
FROM (
|
|
SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2
|
|
UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5
|
|
UNION ALL SELECT 6
|
|
) x
|
|
) AS dates
|
|
LEFT JOIN disburses d ON DATE(d.create_at) = dates.selected_date
|
|
WHERE dates.selected_date BETWEEN CURDATE() - INTERVAL WEEKDAY(CURDATE()) DAY
|
|
AND CURDATE() + INTERVAL (6 - WEEKDAY(CURDATE())) DAY
|
|
GROUP BY dates.selected_date
|
|
ORDER BY dates.selected_date ASC;
|
|
"""
|
|
disburse_list = fetch_all(select_query)
|
|
return response_success(disburse_list, "disburse get list success")
|
|
|
|
|
|
@router.get("/line/nighmonth")
|
|
@limiter.limit("10/minute")
|
|
async def disburse_list(request: Request,):
|
|
select_query = """
|
|
-- Generate dates for the current month (1st to last day)
|
|
SELECT
|
|
dates.selected_date AS create_date,
|
|
COALESCE(SUM(d.disburseprice), 0) AS total_disburseprice
|
|
FROM (
|
|
SELECT DATE_FORMAT(CURDATE() - INTERVAL (DAY(CURDATE()) - 1) DAY + INTERVAL x.a DAY, '%Y-%m-%d') AS selected_date
|
|
FROM (
|
|
SELECT @rownum := @rownum + 1 AS a
|
|
FROM (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
|
|
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11
|
|
UNION ALL SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15 UNION ALL SELECT 16
|
|
UNION ALL SELECT 17 UNION ALL SELECT 18 UNION ALL SELECT 19 UNION ALL SELECT 20 UNION ALL SELECT 21
|
|
UNION ALL SELECT 22 UNION ALL SELECT 23 UNION ALL SELECT 24 UNION ALL SELECT 25 UNION ALL SELECT 26
|
|
UNION ALL SELECT 27 UNION ALL SELECT 28 UNION ALL SELECT 29 UNION ALL SELECT 30 UNION ALL SELECT 31) t1,
|
|
(SELECT @rownum := -1) t2
|
|
) x
|
|
WHERE DATE_FORMAT(CURDATE() - INTERVAL (DAY(CURDATE()) - 1) DAY + INTERVAL x.a DAY, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m')
|
|
) AS dates
|
|
LEFT JOIN disburses d ON DATE(d.create_at) = dates.selected_date
|
|
GROUP BY dates.selected_date
|
|
ORDER BY dates.selected_date ASC;
|
|
"""
|
|
disburse_list = fetch_all(select_query)
|
|
return response_success(disburse_list, "disburse get list success")
|
|
|
|
|
|
@router.get("/line/nighyear")
|
|
@limiter.limit("10/minute")
|
|
async def disburse_list(request: Request,):
|
|
select_query = """
|
|
-- Generate months for the current year (January to December)
|
|
SELECT
|
|
DATE_FORMAT(months.selected_month, '%Y-%m') AS create_date, -- Only keep the year and month
|
|
COALESCE(SUM(d.disburseprice), 0) AS total_disburseprice
|
|
FROM (
|
|
-- Generate months from January to December of the current year
|
|
SELECT DATE_FORMAT(CONCAT(YEAR(CURDATE()), '-', LPAD(x.a, 2, '0'), '-01'), '%Y-%m-01') AS selected_month
|
|
FROM (
|
|
SELECT 1 AS a UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
|
|
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11
|
|
UNION ALL SELECT 12
|
|
) x
|
|
) AS months
|
|
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
|
|
AND d.create_at >= DATE_FORMAT(CURDATE(), '%Y-01-01')
|
|
AND d.create_at < DATE_FORMAT(CURDATE() + INTERVAL 1 YEAR, '%Y-01-01')
|
|
GROUP BY DATE_FORMAT(months.selected_month, '%Y-%m') -- Group by year and month only
|
|
ORDER BY create_date ASC;
|
|
"""
|
|
disburse_list = fetch_all(select_query)
|
|
return response_success(disburse_list, "disburse get list success")
|
|
|
|
|
|
@router.get("/pie/nighweek")
|
|
@limiter.limit("10/minute")
|
|
async def classified_list(request: Request,):
|
|
select_query = """
|
|
-- Generate classified data for the current week (Monday to Sunday)
|
|
SELECT
|
|
t.typename AS name,
|
|
COALESCE(SUM(daily_totals.value), 0) AS value
|
|
FROM (
|
|
-- Generate dates for the current week
|
|
SELECT CURDATE() - INTERVAL (WEEKDAY(CURDATE()) - x.a) DAY AS selected_date
|
|
FROM (
|
|
SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2
|
|
UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5
|
|
UNION ALL SELECT 6
|
|
) x
|
|
) AS dates
|
|
CROSS JOIN disbursetypes t -- Cross join to combine all dates with all typenames
|
|
LEFT JOIN (
|
|
-- Subquery to aggregate daily totals per type
|
|
SELECT
|
|
DATE(d.create_at) AS create_date,
|
|
t.typename AS name,
|
|
SUM(d.disburseprice) AS value
|
|
FROM disburses d
|
|
JOIN disbursetypes t ON d.typeid = t.id
|
|
WHERE DATE(d.create_at) BETWEEN CURDATE() - INTERVAL WEEKDAY(CURDATE()) DAY
|
|
AND CURDATE() + INTERVAL (6 - WEEKDAY(CURDATE())) DAY
|
|
GROUP BY DATE(d.create_at), t.typename
|
|
) AS daily_totals ON daily_totals.create_date = dates.selected_date AND daily_totals.name = t.typename
|
|
GROUP BY t.typename
|
|
ORDER BY t.typename ASC;
|
|
"""
|
|
classified_list = fetch_all(select_query)
|
|
return response_success(classified_list, "disburse get list success")
|
|
|
|
|
|
@router.get("/pie/nighmonth")
|
|
@limiter.limit("10/minute")
|
|
async def classified_list(request: Request,):
|
|
select_query = """
|
|
-- Generate classified data for the current month (1st to last day of the month)
|
|
SELECT
|
|
t.typename AS name,
|
|
COALESCE(SUM(daily_totals.value), 0) AS value
|
|
FROM (
|
|
-- Generate dates for the current month
|
|
SELECT DATE_FORMAT(CURDATE() - INTERVAL (DAY(CURDATE()) - 1) DAY + INTERVAL x.a DAY, '%Y-%m-%d') AS selected_date
|
|
FROM (
|
|
SELECT @rownum := @rownum + 1 AS a
|
|
FROM (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
|
|
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11
|
|
UNION ALL SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15 UNION ALL SELECT 16
|
|
UNION ALL SELECT 17 UNION ALL SELECT 18 UNION ALL SELECT 19 UNION ALL SELECT 20 UNION ALL SELECT 21
|
|
UNION ALL SELECT 22 UNION ALL SELECT 23 UNION ALL SELECT 24 UNION ALL SELECT 25 UNION ALL SELECT 26
|
|
UNION ALL SELECT 27 UNION ALL SELECT 28 UNION ALL SELECT 29 UNION ALL SELECT 30 UNION ALL SELECT 31) t1,
|
|
(SELECT @rownum := -1) t2
|
|
) x
|
|
WHERE DATE_FORMAT(CURDATE() - INTERVAL (DAY(CURDATE()) - 1) DAY + INTERVAL x.a DAY, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m')
|
|
) AS dates
|
|
CROSS JOIN disbursetypes t -- Cross join to combine all dates with all typenames
|
|
LEFT JOIN (
|
|
-- Subquery to aggregate daily totals per type
|
|
SELECT
|
|
DATE(d.create_at) AS create_date,
|
|
t.typename AS name,
|
|
SUM(d.disburseprice) AS value
|
|
FROM disburses d
|
|
JOIN disbursetypes t ON d.typeid = t.id
|
|
WHERE DATE(d.create_at) BETWEEN DATE_FORMAT(CURDATE() - INTERVAL (DAY(CURDATE()) - 1) DAY, '%Y-%m-%d')
|
|
AND LAST_DAY(CURDATE())
|
|
GROUP BY DATE(d.create_at), t.typename
|
|
) AS daily_totals ON daily_totals.create_date = dates.selected_date AND daily_totals.name = t.typename
|
|
GROUP BY t.typename
|
|
ORDER BY t.typename ASC;
|
|
"""
|
|
classified_list = fetch_all(select_query)
|
|
return response_success(classified_list, "disburse get list success")
|
|
|
|
|
|
@router.get("/pie/nighyear")
|
|
@limiter.limit("10/minute")
|
|
async def classified_list(request: Request,):
|
|
select_query = """
|
|
-- Generate classified data for the current year (January to December)
|
|
SELECT
|
|
t.typename AS name,
|
|
COALESCE(SUM(monthly_totals.value), 0) AS value
|
|
FROM (
|
|
-- Generate months for the current year
|
|
SELECT DATE_FORMAT(CONCAT(YEAR(CURDATE()), '-', LPAD(x.a, 2, '0'), '-01'), '%Y-%m-01') AS selected_month
|
|
FROM (
|
|
SELECT 1 AS a UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
|
|
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11
|
|
UNION ALL SELECT 12
|
|
) x
|
|
) AS months
|
|
CROSS JOIN disbursetypes t -- Cross join to combine all months with all typenames
|
|
LEFT JOIN (
|
|
-- Subquery to aggregate monthly totals per type
|
|
SELECT
|
|
DATE_FORMAT(d.create_at, '%Y-%m-01') AS create_month,
|
|
t.typename AS name,
|
|
SUM(d.disburseprice) AS value
|
|
FROM disburses d
|
|
JOIN disbursetypes t ON d.typeid = t.id
|
|
WHERE DATE_FORMAT(d.create_at, '%Y-%m') BETWEEN DATE_FORMAT(CURDATE() - INTERVAL (YEAR(CURDATE()) - YEAR(d.create_at)) YEAR, '%Y-01')
|
|
AND DATE_FORMAT(CURDATE(), '%Y-12')
|
|
GROUP BY DATE_FORMAT(d.create_at, '%Y-%m-01'), t.typename
|
|
) AS monthly_totals ON monthly_totals.create_month = months.selected_month AND monthly_totals.name = t.typename
|
|
GROUP BY t.typename
|
|
ORDER BY t.typename ASC;
|
|
"""
|
|
classified_list = fetch_all(select_query)
|
|
return response_success(classified_list, "disburse get list success")
|
|
|
|
|
|
@router.get("/list/consume")
|
|
@limiter.limit("10/minute")
|
|
async def consume_list(request: Request,days: int):
|
|
current_year = datetime.now().year
|
|
target_year = current_year - days
|
|
|
|
select_query = f"""
|
|
SELECT SUM(d.disburseprice) AS data, t.typename AS name, DATE_FORMAT(d.create_at, '%Y-%m') AS date
|
|
FROM disburses d JOIN disbursetypes t ON d.typeid = t.id
|
|
WHERE YEAR(d.create_at) = {target_year}
|
|
GROUP BY t.typename, DATE_FORMAT(d.create_at, '%Y-%m')
|
|
ORDER BY DATE_FORMAT(d.create_at, '%Y-%m');
|
|
"""
|
|
consume_list = fetch_all(select_query)
|
|
result = {}
|
|
for entry in consume_list:
|
|
name = entry['name']
|
|
date = entry['date']
|
|
data = entry['data']
|
|
|
|
if name not in result:
|
|
result[name] = [0] * 12
|
|
|
|
month_index = int(date.split('-')[1]) - 1
|
|
result[name][month_index] = data
|
|
|
|
final_result = [{"name": name, "data": data}
|
|
for name, data in result.items()]
|
|
return response_success(final_result, "disburse get list success")
|
|
|
|
|
|
@router.get("/list/calendar")
|
|
@limiter.limit("10/minute")
|
|
async def calendar_list(request: Request,):
|
|
select_query = """
|
|
SELECT t.typename AS NAME, YEAR(d.create_at) AS YEAR, SUM(d.disburseprice) AS total_amount
|
|
FROM disburses d
|
|
JOIN disbursetypes t ON d.typeid = t.id
|
|
GROUP BY t.typename, YEAR(d.create_at)
|
|
ORDER BY t.typename, YEAR(d.create_at);
|
|
"""
|
|
calendar_list = fetch_all(select_query)
|
|
|
|
# Initialize dictionaries to store the transformed data
|
|
transformed_data = {}
|
|
years = set()
|
|
|
|
# Process each row from the query result
|
|
for row in calendar_list:
|
|
name = row['NAME']
|
|
year = row['YEAR']
|
|
total_amount = row['total_amount']
|
|
|
|
if name not in transformed_data:
|
|
transformed_data[name] = {}
|
|
|
|
transformed_data[name][year] = total_amount
|
|
years.add(year)
|
|
|
|
# Prepare the final result in the desired format
|
|
sorted_years = sorted(years) # Sort years in ascending order
|
|
headers = ['name'] + [str(year) for year in sorted_years] # Create headers
|
|
|
|
final_result = [headers] # Initialize with headers
|
|
|
|
for name, year_data in transformed_data.items():
|
|
row = [name]
|
|
for year in sorted_years:
|
|
row.append(year_data.get(year, 0)) # Append data or 0 if not available
|
|
final_result.append(row)
|
|
|
|
return response_success(final_result, "disburse get list success")
|