from pydantic import BaseModel, EmailStr, validator from datetime import datetime from typing import Optional from enum import Enum class PPRStatus(str, Enum): NEW = "NEW" CONFIRMED = "CONFIRMED" CANCELED = "CANCELED" LANDED = "LANDED" DELETED = "DELETED" DEPARTED = "DEPARTED" class UserRole(str, Enum): ADMINISTRATOR = "ADMINISTRATOR" OPERATOR = "OPERATOR" READ_ONLY = "READ_ONLY" class PPRBase(BaseModel): ac_reg: str ac_type: str ac_call: Optional[str] = None captain: str fuel: Optional[str] = None in_from: str eta: datetime pob_in: int out_to: Optional[str] = None etd: Optional[datetime] = None pob_out: Optional[int] = None email: Optional[EmailStr] = None phone: Optional[str] = None notes: Optional[str] = None @validator('ac_reg') def validate_registration(cls, v): if not v or len(v.strip()) == 0: raise ValueError('Aircraft registration is required') return v.strip().upper() @validator('pob_in') def validate_pob_in(cls, v): if v is not None and v < 0: raise ValueError('POB inbound must be non-negative') return v @validator('pob_out') def validate_pob_out(cls, v): if v is not None and v < 0: raise ValueError('POB outbound must be non-negative') return v class PPRCreate(PPRBase): pass class PPRUpdate(BaseModel): ac_reg: Optional[str] = None ac_type: Optional[str] = None ac_call: Optional[str] = None captain: Optional[str] = None fuel: Optional[str] = None in_from: Optional[str] = None eta: Optional[datetime] = None pob_in: Optional[int] = None out_to: Optional[str] = None etd: Optional[datetime] = None pob_out: Optional[int] = None email: Optional[EmailStr] = None phone: Optional[str] = None notes: Optional[str] = None class PPRStatusUpdate(BaseModel): status: PPRStatus timestamp: Optional[datetime] = None class PPRInDBBase(PPRBase): id: int status: PPRStatus landed_dt: Optional[datetime] = None departed_dt: Optional[datetime] = None created_by: Optional[str] = None submitted_dt: datetime class Config: from_attributes = True class PPR(PPRInDBBase): pass class PPRInDB(PPRInDBBase): pass # User schemas class UserBase(BaseModel): username: str role: UserRole = UserRole.READ_ONLY class UserCreate(UserBase): password: str class UserUpdate(BaseModel): username: Optional[str] = None password: Optional[str] = None role: Optional[UserRole] = None class UserInDBBase(UserBase): id: int class Config: from_attributes = True class User(UserInDBBase): pass class UserInDB(UserInDBBase): password: str # Authentication schemas class Token(BaseModel): access_token: str token_type: str class TokenData(BaseModel): username: Optional[str] = None # Journal schemas class JournalBase(BaseModel): ppr_id: int entry: str user: str ip: str class JournalCreate(JournalBase): pass class Journal(JournalBase): id: int entry_dt: datetime class Config: from_attributes = True # Airport schemas class AirportBase(BaseModel): icao: str iata: Optional[str] = None name: str country: str class Airport(AirportBase): class Config: from_attributes = True # Aircraft schemas class AircraftBase(BaseModel): icao24: Optional[str] = None registration: Optional[str] = None manufacturer_icao: Optional[str] = None type_code: Optional[str] = None manufacturer_name: Optional[str] = None model: Optional[str] = None clean_reg: Optional[str] = None class Aircraft(AircraftBase): id: int class Config: from_attributes = True