EV 충전 플랫폼 초기 백업
This commit is contained in:
131
app/routers/dashboard.py
Normal file
131
app/routers/dashboard.py
Normal file
@@ -0,0 +1,131 @@
|
||||
"""대시보드 API — 관리자 모니터링"""
|
||||
|
||||
from datetime import datetime, timezone, timedelta
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy import select, func, and_, extract
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.database import get_db
|
||||
from app.models import Charger, ChargingSession, ChargerStatus, SessionStatus
|
||||
from app.schemas import DashboardSummary
|
||||
|
||||
router = APIRouter(prefix="/dashboard", tags=["대시보드"])
|
||||
|
||||
|
||||
@router.get("/summary", response_model=DashboardSummary)
|
||||
async def get_summary(db: AsyncSession = Depends(get_db)):
|
||||
"""대시보드 요약 — 오늘/이번달 충전 현황"""
|
||||
now = datetime.now(timezone.utc)
|
||||
today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
month_start = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
|
||||
|
||||
# 충전기 통계
|
||||
chargers = await db.execute(select(Charger).where(Charger.is_active == True))
|
||||
charger_list = chargers.scalars().all()
|
||||
total = len(charger_list)
|
||||
active = sum(1 for c in charger_list if c.status != ChargerStatus.UNAVAILABLE)
|
||||
charging = sum(1 for c in charger_list if c.status == ChargerStatus.CHARGING)
|
||||
|
||||
# 오늘 세션
|
||||
today_q = await db.execute(
|
||||
select(
|
||||
func.count(ChargingSession.id),
|
||||
func.coalesce(func.sum(ChargingSession.total_bill), 0),
|
||||
func.coalesce(func.sum(ChargingSession.charged_wh), 0),
|
||||
).where(
|
||||
and_(
|
||||
ChargingSession.status == SessionStatus.COMPLETED,
|
||||
ChargingSession.created_at >= today_start,
|
||||
)
|
||||
)
|
||||
)
|
||||
today_row = today_q.one()
|
||||
|
||||
# 이번달 세션
|
||||
month_q = await db.execute(
|
||||
select(
|
||||
func.coalesce(func.sum(ChargingSession.total_bill), 0),
|
||||
func.coalesce(func.sum(ChargingSession.charged_wh), 0),
|
||||
).where(
|
||||
and_(
|
||||
ChargingSession.status == SessionStatus.COMPLETED,
|
||||
ChargingSession.created_at >= month_start,
|
||||
)
|
||||
)
|
||||
)
|
||||
month_row = month_q.one()
|
||||
|
||||
return DashboardSummary(
|
||||
total_chargers=total,
|
||||
active_chargers=active,
|
||||
charging_now=charging,
|
||||
today_sessions=today_row[0],
|
||||
today_revenue=today_row[1],
|
||||
today_kwh=round(today_row[2] / 1000, 2),
|
||||
month_revenue=month_row[0],
|
||||
month_kwh=round(month_row[1] / 1000, 2),
|
||||
)
|
||||
|
||||
|
||||
@router.get("/recent-sessions")
|
||||
async def recent_sessions(
|
||||
limit: int = 20,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""최근 충전 세션 목록"""
|
||||
result = await db.execute(
|
||||
select(ChargingSession)
|
||||
.order_by(ChargingSession.created_at.desc())
|
||||
.limit(limit)
|
||||
)
|
||||
sessions = result.scalars().all()
|
||||
|
||||
return [
|
||||
{
|
||||
"session_uid": s.session_uid,
|
||||
"charger_id": s.charger_id,
|
||||
"status": s.status,
|
||||
"charged_kwh": round(s.charged_wh / 1000, 2) if s.charged_wh else 0,
|
||||
"total_bill": s.total_bill,
|
||||
"started_at": s.started_at,
|
||||
"stopped_at": s.stopped_at,
|
||||
}
|
||||
for s in sessions
|
||||
]
|
||||
|
||||
|
||||
@router.get("/daily-stats")
|
||||
async def daily_stats(
|
||||
days: int = 30,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""일별 충전 통계 (최근 N일)"""
|
||||
cutoff = datetime.now(timezone.utc) - timedelta(days=days)
|
||||
|
||||
result = await db.execute(
|
||||
select(
|
||||
func.date(ChargingSession.created_at).label("date"),
|
||||
func.count(ChargingSession.id).label("sessions"),
|
||||
func.coalesce(func.sum(ChargingSession.total_bill), 0).label("revenue"),
|
||||
func.coalesce(func.sum(ChargingSession.charged_wh), 0).label("wh"),
|
||||
)
|
||||
.where(
|
||||
and_(
|
||||
ChargingSession.status == SessionStatus.COMPLETED,
|
||||
ChargingSession.created_at >= cutoff,
|
||||
)
|
||||
)
|
||||
.group_by(func.date(ChargingSession.created_at))
|
||||
.order_by(func.date(ChargingSession.created_at))
|
||||
)
|
||||
|
||||
return [
|
||||
{
|
||||
"date": str(row.date),
|
||||
"sessions": row.sessions,
|
||||
"revenue": row.revenue,
|
||||
"kwh": round(row.wh / 1000, 2),
|
||||
}
|
||||
for row in result.all()
|
||||
]
|
||||
Reference in New Issue
Block a user