""" Fleet-wide deployment-history calendar — Phase 2 of the deployment-history visualisation work (Phase 1 is the per-unit Gantt on /unit/{id}). Renders all UnitAssignment windows across all projects on a 12-month calendar grid styled like the Job Planner. Each day cell shows one mini-bar per project that had ≥1 active assignment that day. Click a day → side panel with the (unit, location) pairs active. Routes: GET /tools/deployment-history — HTML page GET /api/admin/deployment-history/day — JSON list of deployments on a specific date (used by the day-detail panel) """ from __future__ import annotations from datetime import date, datetime from typing import Optional from fastapi import APIRouter, Depends, Query, Request from fastapi.responses import HTMLResponse, JSONResponse from sqlalchemy.orm import Session from backend.database import get_db from backend.services.deployment_history import ( get_deployment_history_data, get_deployments_on_day, ) from backend.templates_config import templates router = APIRouter() @router.get("/tools/deployment-history", response_class=HTMLResponse) def deployment_history_page( request: Request, year: Optional[int] = Query(None), month: Optional[int] = Query(None), db: Session = Depends(get_db), ): """Fleet-wide deployment history calendar. Defaults to a 12-month window ending in the current month (so the operator sees the recent past, not the future). ?year=&month= can override the START of the window to scroll backward or forward. """ today = date.today() # Default: 12-month window ending this month → start = 11 months back. if year is None or month is None: # 11 months back from current month. m = today.month - 11 y = today.year while m < 1: m += 12 y -= 1 start_year, start_month = y, m else: start_year, start_month = year, month calendar = get_deployment_history_data(db, start_year, start_month) # Build prev/next navigation values. prev_y, prev_m = (start_year - 1, 12) if start_month == 1 else (start_year, start_month - 1) next_y, next_m = (start_year + 1, 1) if start_month == 12 else (start_year, start_month + 1) return templates.TemplateResponse("admin/deployment_history.html", { "request": request, "calendar": calendar, "today": today.isoformat(), "prev_year": prev_y, "prev_month": prev_m, "next_year": next_y, "next_month": next_m, }) @router.get("/api/admin/deployment-history/day") def deployment_history_day( target_date: str = Query(..., description="YYYY-MM-DD"), db: Session = Depends(get_db), ): """Return assignments active on a specific calendar day.""" try: d = date.fromisoformat(target_date) except ValueError: return JSONResponse( {"error": f"Invalid date: {target_date!r}"}, status_code=400, ) deployments = get_deployments_on_day(db, d) return JSONResponse({ "date": target_date, "count": len(deployments), "deployments": deployments, })