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

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")