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:
63
app/schemas/calendar.py
Normal file
63
app/schemas/calendar.py
Normal file
@@ -0,0 +1,63 @@
|
||||
"""Calendar-related Pydantic schemas.
|
||||
|
||||
BE-CAL-004: MinimumWorkload read/write schemas.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pydantic import BaseModel, Field, model_validator
|
||||
from typing import Optional
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# MinimumWorkload
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class WorkloadCategoryThresholds(BaseModel):
|
||||
"""Minutes thresholds per slot category within a single period."""
|
||||
work: int = Field(0, ge=0, le=65535, description="Minutes of work-type slots")
|
||||
on_call: int = Field(0, ge=0, le=65535, description="Minutes of on-call-type slots")
|
||||
entertainment: int = Field(0, ge=0, le=65535, description="Minutes of entertainment-type slots")
|
||||
|
||||
|
||||
class MinimumWorkloadConfig(BaseModel):
|
||||
"""Full workload configuration across all four periods."""
|
||||
daily: WorkloadCategoryThresholds = Field(default_factory=WorkloadCategoryThresholds)
|
||||
weekly: WorkloadCategoryThresholds = Field(default_factory=WorkloadCategoryThresholds)
|
||||
monthly: WorkloadCategoryThresholds = Field(default_factory=WorkloadCategoryThresholds)
|
||||
yearly: WorkloadCategoryThresholds = Field(default_factory=WorkloadCategoryThresholds)
|
||||
|
||||
|
||||
class MinimumWorkloadUpdate(BaseModel):
|
||||
"""Partial update — only provided periods/categories are overwritten.
|
||||
|
||||
Accepts the same shape as ``MinimumWorkloadConfig`` but every field
|
||||
is optional so callers can PATCH individual periods.
|
||||
"""
|
||||
daily: Optional[WorkloadCategoryThresholds] = None
|
||||
weekly: Optional[WorkloadCategoryThresholds] = None
|
||||
monthly: Optional[WorkloadCategoryThresholds] = None
|
||||
yearly: Optional[WorkloadCategoryThresholds] = None
|
||||
|
||||
|
||||
class MinimumWorkloadResponse(BaseModel):
|
||||
"""API response for workload configuration."""
|
||||
user_id: int
|
||||
config: MinimumWorkloadConfig
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Workload warning (used by future calendar validation endpoints)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class WorkloadWarningItem(BaseModel):
|
||||
"""A single workload warning returned alongside a calendar mutation."""
|
||||
period: str = Field(..., description="daily | weekly | monthly | yearly")
|
||||
category: str = Field(..., description="work | on_call | entertainment")
|
||||
current_minutes: int = Field(..., ge=0, description="Current scheduled minutes in the period")
|
||||
minimum_minutes: int = Field(..., ge=0, description="Configured minimum threshold")
|
||||
shortfall_minutes: int = Field(..., ge=0, description="How many minutes below threshold")
|
||||
message: str = Field(..., description="Human-readable warning")
|
||||
Reference in New Issue
Block a user