solorpower_server/app/routers/stats.py

120 lines
3.8 KiB
Python

"""
통계 조회 API
- 일별/월별/연도별 발전량 통계
"""
from fastapi import APIRouter, HTTPException, Depends, Query
from supabase import Client
from typing import List, Literal
from datetime import datetime, timedelta
from app.core.database import get_db
router = APIRouter(
prefix="/plants",
tags=["Stats"]
)
@router.get("/{plant_id}/stats")
async def get_plant_stats(
plant_id: str,
period: Literal["day", "month", "year"] = Query("day", description="통계 기간"),
db: Client = Depends(get_db)
) -> dict:
"""
발전소 통계 조회
Args:
plant_id: 발전소 ID
period: 'day' (최근 30일), 'month' (최근 12개월), 'year' (최근 5년)
Returns:
차트 라이브러리 친화적 포맷 [{"label": "...", "value": ...}, ...]
"""
try:
today = datetime.now().date()
if period == "day":
# 최근 30일
start_date = today - timedelta(days=30)
result = db.table("daily_stats") \
.select("date, total_generation") \
.eq("plant_id", plant_id) \
.gte("date", start_date.isoformat()) \
.lte("date", today.isoformat()) \
.order("date", desc=False) \
.execute()
data = [
{"label": row["date"], "value": row["total_generation"] or 0}
for row in result.data
]
elif period == "month":
# 최근 12개월 - 월별 합계
start_date = today.replace(day=1) - timedelta(days=365)
result = db.table("daily_stats") \
.select("date, total_generation") \
.eq("plant_id", plant_id) \
.gte("date", start_date.isoformat()) \
.lte("date", today.isoformat()) \
.execute()
# 월별 집계
monthly = {}
for row in result.data:
date_str = row["date"]
month_key = date_str[:7] # YYYY-MM
generation = row["total_generation"] or 0
monthly[month_key] = monthly.get(month_key, 0) + generation
data = [
{"label": month, "value": round(value, 2)}
for month, value in sorted(monthly.items())
][-12:] # 최근 12개월만
elif period == "year":
# 최근 5년 - 연도별 합계
start_year = today.year - 5
result = db.table("daily_stats") \
.select("date, total_generation") \
.eq("plant_id", plant_id) \
.gte("date", f"{start_year}-01-01") \
.lte("date", today.isoformat()) \
.execute()
# 연도별 집계
yearly = {}
for row in result.data:
date_str = row["date"]
year_key = date_str[:4] # YYYY
generation = row["total_generation"] or 0
yearly[year_key] = yearly.get(year_key, 0) + generation
data = [
{"label": year, "value": round(value, 2)}
for year, value in sorted(yearly.items())
]
else:
raise HTTPException(status_code=400, detail="Invalid period parameter")
return {
"status": "success",
"plant_id": plant_id,
"period": period,
"data": data,
"count": len(data)
}
except HTTPException:
raise
except Exception as e:
raise HTTPException(
status_code=500,
detail=f"통계 조회 실패: {str(e)}"
)