Files
calminer/routes/reporting.py

74 lines
2.3 KiB
Python

from typing import Any, Dict, List, cast
from fastapi import APIRouter, HTTPException, Request, status
from pydantic import BaseModel
from services.reporting import generate_report
router = APIRouter(prefix="/api/reporting", tags=["Reporting"])
def _validate_payload(payload: Any) -> List[Dict[str, float]]:
if not isinstance(payload, list):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid input format",
)
typed_payload = cast(List[Any], payload)
validated: List[Dict[str, float]] = []
for index, item in enumerate(typed_payload):
if not isinstance(item, dict):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Entry at index {index} must be an object",
)
value = cast(Dict[str, Any], item).get("result")
if not isinstance(value, (int, float)):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Entry at index {index} must include numeric 'result'",
)
validated.append({"result": float(value)})
return validated
class ReportSummary(BaseModel):
count: int
mean: float
median: float
min: float
max: float
std_dev: float
variance: float
percentile_10: float
percentile_90: float
percentile_5: float
percentile_95: float
value_at_risk_95: float
expected_shortfall_95: float
@router.post("/summary", response_model=ReportSummary)
async def summary_report(request: Request):
payload = await request.json()
validated_payload = _validate_payload(payload)
summary = generate_report(validated_payload)
return ReportSummary(
count=int(summary["count"]),
mean=float(summary["mean"]),
median=float(summary["median"]),
min=float(summary["min"]),
max=float(summary["max"]),
std_dev=float(summary["std_dev"]),
variance=float(summary["variance"]),
percentile_10=float(summary["percentile_10"]),
percentile_90=float(summary["percentile_90"]),
percentile_5=float(summary["percentile_5"]),
percentile_95=float(summary["percentile_95"]),
value_at_risk_95=float(summary["value_at_risk_95"]),
expected_shortfall_95=float(summary["expected_shortfall_95"]),
)