state-hub/api/routers/legacy_meter.py

130 lines
4.4 KiB
Python
Raw Normal View History

import uuid
from datetime import datetime, timedelta, timezone
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.ext.asyncio import AsyncSession
from api.database import get_session
from api.models.legacy_meter import LegacyInterface
from api.schemas.legacy_meter import (
LegacyInterfacePatch,
LegacyInterfaceRead,
LegacyInterfaceRegister,
LegacyUsageRecord,
LegacyUsageSummary,
LegacyWeeklyReview,
)
from api.services.legacy_meter import (
LegacyUsageIdentity,
get_legacy_interface_by_key,
legacy_usage_summary,
legacy_weekly_review,
list_legacy_interfaces,
patch_legacy_interface,
record_legacy_usage,
register_legacy_interface,
)
router = APIRouter(prefix="/legacy-meter", tags=["legacy-meter"])
@router.post(
"/interfaces",
response_model=LegacyInterfaceRead,
status_code=status.HTTP_201_CREATED,
)
async def register_interface(
body: LegacyInterfaceRegister,
session: AsyncSession = Depends(get_session),
) -> LegacyInterface:
try:
return await register_legacy_interface(session, **body.model_dump())
except ValueError as exc:
raise HTTPException(status_code=422, detail=str(exc)) from exc
@router.get("/interfaces", response_model=list[LegacyInterfaceRead])
async def list_interfaces(
session: AsyncSession = Depends(get_session),
) -> list[LegacyInterface]:
return await list_legacy_interfaces(session)
@router.get("/interfaces/by-key", response_model=LegacyInterfaceRead)
async def get_interface_by_key(
interface_key: str = Query(...),
session: AsyncSession = Depends(get_session),
) -> LegacyInterface:
interface = await get_legacy_interface_by_key(session, interface_key)
if interface is None:
raise HTTPException(status_code=404, detail=f"Legacy interface '{interface_key}' not found")
return interface
@router.patch("/interfaces/{interface_id}", response_model=LegacyInterfaceRead)
async def patch_interface(
interface_id: uuid.UUID,
body: LegacyInterfacePatch,
session: AsyncSession = Depends(get_session),
) -> LegacyInterface:
interface = await session.get(LegacyInterface, interface_id)
if interface is None:
raise HTTPException(status_code=404, detail=f"Legacy interface '{interface_id}' not found")
try:
return await patch_legacy_interface(
session,
interface,
body.model_dump(exclude_unset=True),
)
except ValueError as exc:
raise HTTPException(status_code=422, detail=str(exc)) from exc
@router.post("/usage", response_model=LegacyInterfaceRead, status_code=status.HTTP_201_CREATED)
async def record_usage(
body: LegacyUsageRecord,
session: AsyncSession = Depends(get_session),
) -> LegacyInterface:
try:
return await record_legacy_usage(
session,
interface_key=body.interface_key,
interface_kind=body.interface_kind,
replacement_ref=body.replacement_ref,
owner_component=body.owner_component,
replacement_verified=body.replacement_verified,
identity=LegacyUsageIdentity(
tenant_key=body.tenant_key or "unknown",
user_key=body.user_key or "unknown",
component_key=body.component_key or "unknown",
),
observed_at=body.observed_at,
call_count=body.call_count,
)
except ValueError as exc:
raise HTTPException(status_code=422, detail=str(exc)) from exc
@router.get("/summary", response_model=LegacyUsageSummary)
async def usage_summary(
days: int = Query(7, ge=1, le=366),
window_start: datetime | None = None,
window_end: datetime | None = None,
session: AsyncSession = Depends(get_session),
) -> LegacyUsageSummary:
end = window_end or datetime.now(tz=timezone.utc)
start = window_start or (end - timedelta(days=days))
return await legacy_usage_summary(session, window_start=start, window_end=end)
@router.get("/weekly-review", response_model=LegacyWeeklyReview)
async def weekly_review(
days: int = Query(7, ge=1, le=366),
window_start: datetime | None = None,
window_end: datetime | None = None,
session: AsyncSession = Depends(get_session),
) -> LegacyWeeklyReview:
end = window_end or datetime.now(tz=timezone.utc)
start = window_start or (end - timedelta(days=days))
return await legacy_weekly_review(session, window_start=start, window_end=end)