- Updated README.md to reflect new features and usage instructions. - Removed deprecated Dashboard.html component and integrated dashboard functionality directly into the main application. - Revised architecture documentation for clarity and added module map and request flow diagrams. - Enhanced maintenance model to include equipment association and cost tracking. - Updated requirements.txt to include new dependencies (httpx, pandas, numpy). - Improved consumption, maintenance, production, and reporting routes with better validation and response handling. - Added unit tests for maintenance and production routes, ensuring proper CRUD operations and validation. - Enhanced reporting service to calculate and return detailed summary statistics. - Redesigned Dashboard.html for improved user experience and integrated Chart.js for visualizing simulation results.
71 lines
2.0 KiB
Python
71 lines
2.0 KiB
Python
from typing import Any, Dict, List
|
|
|
|
from fastapi import APIRouter, HTTPException, Request, status
|
|
from pydantic import BaseModel
|
|
|
|
from config.database import SessionLocal
|
|
from services.reporting import generate_report
|
|
|
|
|
|
router = APIRouter(prefix="/api/reporting", tags=["Reporting"])
|
|
|
|
|
|
def get_db():
|
|
db = SessionLocal()
|
|
try:
|
|
yield db
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
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",
|
|
)
|
|
|
|
validated: List[Dict[str, float]] = []
|
|
for index, item in enumerate(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 = 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
|
|
percentile_10: float
|
|
percentile_90: 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"]),
|
|
percentile_10=float(summary["percentile_10"]),
|
|
percentile_90=float(summary["percentile_90"]),
|
|
)
|