from typing import TYPE_CHECKING, List, Optional from pydantic import field_validator from sqlalchemy import UniqueConstraint from sqlmodel import Field, Relationship, SQLModel if TYPE_CHECKING: from app.models.mail_log import MailLog from app.models.order import Order from app.models.route import Route def _normalize_email(value: str) -> str: return value.strip().lower() class ParticipantBase(SQLModel): name: str email: str phone: Optional[str] = Field(default=None) is_active: bool = Field(default=True) @field_validator("email") @classmethod def _validate_email(cls, v: str) -> str: return _normalize_email(v) class Participant(ParticipantBase, table=True): __tablename__ = "participant" __table_args__ = (UniqueConstraint("route_id", "email", name="uq_participant_route_email"),) id: Optional[int] = Field(default=None, primary_key=True) route_id: int = Field(foreign_key="route.id", ondelete="CASCADE") route: "Route" = Relationship(back_populates="participants") orders: List["Order"] = Relationship( back_populates="participant", sa_relationship_kwargs={"cascade": "all, delete-orphan"} ) mail_logs: List["MailLog"] = Relationship( back_populates="participant", sa_relationship_kwargs={"cascade": "all, delete-orphan"} ) class ParticipantCreate(ParticipantBase): route_id: int phone: str # påkrævet ved oprettelse, selvom det er Optional i basen/DB'en class ParticipantUpdate(SQLModel): name: Optional[str] = None email: Optional[str] = None phone: Optional[str] = None is_active: Optional[bool] = None @field_validator("email") @classmethod def _validate_email(cls, v: Optional[str]) -> Optional[str]: return _normalize_email(v) if v is not None else v class ParticipantPublic(ParticipantBase): id: int route_id: int