Full-stack energy management system for Tianpu Daxing campus. - Frontend: React 19 + TypeScript + Ant Design + ECharts - Backend: FastAPI + SQLAlchemy + PostgreSQL/TimescaleDB - Features: PV monitoring, heat pump management, carbon tracking, alarms, reports Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
76 lines
2.8 KiB
Python
76 lines
2.8 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy import select
|
|
from pydantic import BaseModel
|
|
from app.core.database import get_db
|
|
from app.core.deps import get_current_user
|
|
from app.models.report import ReportTemplate, ReportTask
|
|
from app.models.user import User
|
|
|
|
router = APIRouter(prefix="/reports", tags=["报表管理"])
|
|
|
|
|
|
class TemplateCreate(BaseModel):
|
|
name: str
|
|
report_type: str
|
|
description: str | None = None
|
|
fields: list[dict]
|
|
filters: dict | None = None
|
|
aggregation: str = "sum"
|
|
time_granularity: str = "hour"
|
|
|
|
|
|
class TaskCreate(BaseModel):
|
|
template_id: int
|
|
name: str | None = None
|
|
schedule: str | None = None
|
|
recipients: list[str] | None = None
|
|
export_format: str = "xlsx"
|
|
|
|
|
|
@router.get("/templates")
|
|
async def list_templates(db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
|
|
result = await db.execute(select(ReportTemplate).order_by(ReportTemplate.id))
|
|
return [{
|
|
"id": t.id, "name": t.name, "report_type": t.report_type, "description": t.description,
|
|
"fields": t.fields, "is_system": t.is_system, "aggregation": t.aggregation,
|
|
"time_granularity": t.time_granularity,
|
|
} for t in result.scalars().all()]
|
|
|
|
|
|
@router.post("/templates")
|
|
async def create_template(data: TemplateCreate, db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
|
|
template = ReportTemplate(**data.model_dump(), created_by=user.id)
|
|
db.add(template)
|
|
await db.flush()
|
|
return {"id": template.id, "name": template.name}
|
|
|
|
|
|
@router.get("/tasks")
|
|
async def list_tasks(db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
|
|
result = await db.execute(select(ReportTask).order_by(ReportTask.id.desc()))
|
|
return [{
|
|
"id": t.id, "template_id": t.template_id, "name": t.name, "schedule": t.schedule,
|
|
"status": t.status, "export_format": t.export_format, "file_path": t.file_path,
|
|
"last_run": str(t.last_run) if t.last_run else None,
|
|
} for t in result.scalars().all()]
|
|
|
|
|
|
@router.post("/tasks")
|
|
async def create_task(data: TaskCreate, db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
|
|
task = ReportTask(**data.model_dump(), created_by=user.id)
|
|
db.add(task)
|
|
await db.flush()
|
|
return {"id": task.id}
|
|
|
|
|
|
@router.post("/tasks/{task_id}/run")
|
|
async def run_task(task_id: int, db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
|
|
result = await db.execute(select(ReportTask).where(ReportTask.id == task_id))
|
|
task = result.scalar_one_or_none()
|
|
if not task:
|
|
raise HTTPException(status_code=404, detail="任务不存在")
|
|
task.status = "running"
|
|
# TODO: trigger Celery task
|
|
return {"message": "报表生成中", "task_id": task.id}
|