Files
tianpu-ems/backend/app/api/v1/reports.py
Du Wenbo f53a610a19 Initial commit: Tianpu Zero-Carbon EMS Platform
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>
2026-04-01 13:36:06 +08:00

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}