import uuid from datetime import date, datetime from typing import Optional from enum import Enum from pydantic import BaseModel, ConfigDict, field_validator class AESeriousness(str, Enum): I = "I" II = "II" III = "III" IV = "IV" V = "V" class AECreate(BaseModel): site_id: Optional[uuid.UUID] = None subject_id: Optional[uuid.UUID] = None visit_id: Optional[uuid.UUID] = None term: str onset_date: Optional[date] = None seriousness: AESeriousness causality: Optional[str] = None description: Optional[str] = None outcome: Optional[str] = None class AEUpdate(BaseModel): subject_id: Optional[uuid.UUID] = None term: Optional[str] = None onset_date: Optional[date] = None resolution_date: Optional[date] = None seriousness: Optional[AESeriousness] = None causality: Optional[str] = None action_taken: Optional[str] = None outcome: Optional[str] = None reported_to_sponsor: Optional[bool] = None status: Optional[str] = None description: Optional[str] = None class AERead(BaseModel): id: uuid.UUID study_id: uuid.UUID site_id: Optional[uuid.UUID] subject_id: Optional[uuid.UUID] visit_id: Optional[uuid.UUID] term: str onset_date: Optional[date] resolution_date: Optional[date] seriousness: AESeriousness causality: Optional[str] action_taken: Optional[str] outcome: Optional[str] reported_to_sponsor: bool report_due_date: Optional[date] status: str description: Optional[str] created_by: uuid.UUID created_at: datetime updated_at: datetime is_overdue: bool | None = None model_config = ConfigDict(from_attributes=True) @field_validator("seriousness", mode="before") @classmethod def normalize_seriousness(cls, value): if value is None: return AESeriousness.I normalized = str(value).strip().upper() digit_map = { "1": "I", "2": "II", "3": "III", "4": "IV", "5": "V", } legacy_map = { "SERIOUS": "IV", "NON_SERIOUS": "II", } if normalized in digit_map: return digit_map[normalized] if normalized in legacy_map: return legacy_map[normalized] return normalized