BE-CAL-004: implement MinimumWorkload storage
- New model: minimum_workloads table with JSON config column (per-user) - Schemas: MinimumWorkloadConfig, MinimumWorkloadUpdate, MinimumWorkloadResponse - Service: CRUD operations + check_workload_warnings() entry point for BE-CAL-007 - API: GET/PUT/PATCH /calendar/workload-config (self + admin routes) - Migration: auto-create minimum_workloads table on startup - Registered calendar router in main.py
This commit is contained in:
147
app/api/routers/calendar.py
Normal file
147
app/api/routers/calendar.py
Normal file
@@ -0,0 +1,147 @@
|
||||
"""Calendar API router.
|
||||
|
||||
BE-CAL-004: MinimumWorkload CRUD endpoints.
|
||||
Future tasks (BE-CAL-API-*) will add slot/plan endpoints here.
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.api.deps import get_current_user
|
||||
from app.core.config import get_db
|
||||
from app.models.models import User
|
||||
from app.schemas.calendar import (
|
||||
MinimumWorkloadConfig,
|
||||
MinimumWorkloadResponse,
|
||||
MinimumWorkloadUpdate,
|
||||
)
|
||||
from app.services.minimum_workload import (
|
||||
get_workload_config,
|
||||
replace_workload_config,
|
||||
upsert_workload_config,
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/calendar", tags=["Calendar"])
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# MinimumWorkload
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@router.get(
|
||||
"/workload-config",
|
||||
response_model=MinimumWorkloadResponse,
|
||||
summary="Get current user's minimum workload configuration",
|
||||
)
|
||||
def get_my_workload_config(
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
"""Return the workload thresholds for the authenticated user.
|
||||
|
||||
If no configuration has been saved yet, returns default (all-zero)
|
||||
thresholds.
|
||||
"""
|
||||
cfg = get_workload_config(db, current_user.id)
|
||||
return MinimumWorkloadResponse(user_id=current_user.id, config=cfg)
|
||||
|
||||
|
||||
@router.put(
|
||||
"/workload-config",
|
||||
response_model=MinimumWorkloadResponse,
|
||||
summary="Replace the current user's minimum workload configuration",
|
||||
)
|
||||
def put_my_workload_config(
|
||||
payload: MinimumWorkloadConfig,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
"""Full replacement of the workload configuration."""
|
||||
row = replace_workload_config(db, current_user.id, payload)
|
||||
db.commit()
|
||||
db.refresh(row)
|
||||
return MinimumWorkloadResponse(user_id=current_user.id, config=row.config)
|
||||
|
||||
|
||||
@router.patch(
|
||||
"/workload-config",
|
||||
response_model=MinimumWorkloadResponse,
|
||||
summary="Partially update the current user's minimum workload configuration",
|
||||
)
|
||||
def patch_my_workload_config(
|
||||
payload: MinimumWorkloadUpdate,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
"""Partial update — only the provided periods are overwritten."""
|
||||
row = upsert_workload_config(db, current_user.id, payload)
|
||||
db.commit()
|
||||
db.refresh(row)
|
||||
return MinimumWorkloadResponse(user_id=current_user.id, config=row.config)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Admin: manage another user's workload config
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _require_admin(current_user: User = Depends(get_current_user)):
|
||||
if not current_user.is_admin:
|
||||
raise HTTPException(status_code=403, detail="Admin required")
|
||||
return current_user
|
||||
|
||||
|
||||
@router.get(
|
||||
"/workload-config/{user_id}",
|
||||
response_model=MinimumWorkloadResponse,
|
||||
summary="[Admin] Get a specific user's minimum workload configuration",
|
||||
)
|
||||
def get_user_workload_config(
|
||||
user_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
_admin: User = Depends(_require_admin),
|
||||
):
|
||||
user = db.query(User).filter(User.id == user_id).first()
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
cfg = get_workload_config(db, user_id)
|
||||
return MinimumWorkloadResponse(user_id=user_id, config=cfg)
|
||||
|
||||
|
||||
@router.put(
|
||||
"/workload-config/{user_id}",
|
||||
response_model=MinimumWorkloadResponse,
|
||||
summary="[Admin] Replace a specific user's minimum workload configuration",
|
||||
)
|
||||
def put_user_workload_config(
|
||||
user_id: int,
|
||||
payload: MinimumWorkloadConfig,
|
||||
db: Session = Depends(get_db),
|
||||
_admin: User = Depends(_require_admin),
|
||||
):
|
||||
user = db.query(User).filter(User.id == user_id).first()
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
row = replace_workload_config(db, user_id, payload)
|
||||
db.commit()
|
||||
db.refresh(row)
|
||||
return MinimumWorkloadResponse(user_id=user_id, config=row.config)
|
||||
|
||||
|
||||
@router.patch(
|
||||
"/workload-config/{user_id}",
|
||||
response_model=MinimumWorkloadResponse,
|
||||
summary="[Admin] Partially update a specific user's minimum workload configuration",
|
||||
)
|
||||
def patch_user_workload_config(
|
||||
user_id: int,
|
||||
payload: MinimumWorkloadUpdate,
|
||||
db: Session = Depends(get_db),
|
||||
_admin: User = Depends(_require_admin),
|
||||
):
|
||||
user = db.query(User).filter(User.id == user_id).first()
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
row = upsert_workload_config(db, user_id, payload)
|
||||
db.commit()
|
||||
db.refresh(row)
|
||||
return MinimumWorkloadResponse(user_id=user_id, config=row.config)
|
||||
Reference in New Issue
Block a user