You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
101 lines
4.0 KiB
101 lines
4.0 KiB
from pydantic import BaseModel, Field, validator |
|
from typing import List, Optional, Dict, Any |
|
from datetime import datetime, date |
|
from enum import Enum |
|
|
|
class TipoPasto(str, Enum): |
|
pranzo = "pranzo" |
|
cena = "cena" |
|
|
|
class PastoBase(BaseModel): |
|
data_pasto: date |
|
tipo_pasto: TipoPasto = TipoPasto.pranzo |
|
portate: Optional[Dict[str, Dict[int, int]]] = Field( |
|
default_factory=dict, |
|
description="Portate structure: {'primo': {pietanza_id: max_prenotazioni}}" |
|
) |
|
turni: Optional[Dict[str, int]] = Field( |
|
default_factory=dict, |
|
description="Turni structure: {'12:45': max_posti}" |
|
) |
|
disponibile: bool = True |
|
|
|
@validator('portate') |
|
def validate_portate(cls, v): |
|
if v is None: |
|
return {} |
|
# Validate structure: each portata should have pietanza_id -> max_count mapping |
|
valid_portate = ['primo', 'secondo', 'contorno', 'dolce', 'frutta'] |
|
for portata, pietanze in v.items(): |
|
if portata not in valid_portate: |
|
raise ValueError(f"Portata non valida: {portata}") |
|
if not isinstance(pietanze, dict): |
|
raise ValueError(f"Pietanze per {portata} deve essere un dizionario") |
|
for pietanza_id, max_count in pietanze.items(): |
|
if not isinstance(int(pietanza_id), int) or int(pietanza_id) <= 0: |
|
raise ValueError(f"ID pietanza non valido: {pietanza_id}") |
|
if not isinstance(max_count, int) or max_count < 0: |
|
raise ValueError(f"Numero massimo prenotazioni non valido per pietanza {pietanza_id}") |
|
return v |
|
|
|
@validator('turni') |
|
def validate_turni(cls, v): |
|
if v is None: |
|
return {} |
|
# Validate time format and capacity |
|
import re |
|
time_pattern = re.compile(r'^([01]\d|2[0-3]):([0-5]\d)$') |
|
for turno, capacity in v.items(): |
|
if not time_pattern.match(turno): |
|
raise ValueError(f"Formato orario non valido: {turno}. Usare HH:MM") |
|
if not isinstance(capacity, int) or capacity < 0: |
|
raise ValueError(f"Capacità non valida per turno {turno}: {capacity}") |
|
return v |
|
|
|
class PastoCreate(PastoBase): |
|
pass |
|
|
|
class PastoUpdate(BaseModel): |
|
tipo_pasto: Optional[TipoPasto] = None |
|
portate: Optional[Dict[str, Dict[int, int]]] = None |
|
turni: Optional[Dict[str, int]] = None |
|
disponibile: Optional[bool] = None |
|
|
|
# Same validators as PastoBase for optional fields |
|
@validator('portate') |
|
def validate_portate(cls, v): |
|
if v is None: |
|
return v |
|
valid_portate = ['primo', 'secondo', 'contorno', 'dolce', 'frutta'] |
|
for portata, pietanze in v.items(): |
|
if portata not in valid_portate: |
|
raise ValueError(f"Portata non valida: {portata}") |
|
if not isinstance(pietanze, dict): |
|
raise ValueError(f"Pietanze per {portata} deve essere un dizionario") |
|
for pietanza_id, max_count in pietanze.items(): |
|
if not isinstance(int(pietanza_id), int) or int(pietanza_id) <= 0: |
|
raise ValueError(f"ID pietanza non valido: {pietanza_id}") |
|
if not isinstance(max_count, int) or max_count < 0: |
|
raise ValueError(f"Numero massimo prenotazioni non valido per pietanza {pietanza_id}") |
|
return v |
|
|
|
@validator('turni') |
|
def validate_turni(cls, v): |
|
if v is None: |
|
return v |
|
import re |
|
time_pattern = re.compile(r'^([01]\d|2[0-3]):([0-5]\d)$') |
|
for turno, capacity in v.items(): |
|
if not time_pattern.match(turno): |
|
raise ValueError(f"Formato orario non valido: {turno}. Usare HH:MM") |
|
if not isinstance(capacity, int) or capacity < 0: |
|
raise ValueError(f"Capacità non valida per turno {turno}: {capacity}") |
|
return v |
|
|
|
class PastoResponse(PastoBase): |
|
id: int |
|
created_at: datetime |
|
updated_at: datetime |
|
|
|
class Config: |
|
from_attributes = True
|
|
|