from datetime import datetime from decimal import Decimal from enum import Enum from typing import TYPE_CHECKING, List, Optional from sqlalchemy import CheckConstraint, Column from sqlalchemy import Enum as SAEnum from sqlmodel import Field, Relationship, SQLModel if TYPE_CHECKING: from app.models.order import Order from app.models.route import Route from app.models.wine_offering import WineOffering class PurchaseRoundStatus(str, Enum): DRAFT = "draft" OPEN = "open" CLOSED = "closed" class PurchaseRoundBase(SQLModel): name: str status: PurchaseRoundStatus = Field( default=PurchaseRoundStatus.DRAFT, sa_column=Column( SAEnum( PurchaseRoundStatus, name="purchase_round_status", native_enum=False, values_callable=lambda enum_cls: [member.value for member in enum_cls], ), nullable=False, ), ) opens_at: Optional[datetime] = Field(default=None) order_deadline_at: Optional[datetime] = Field(default=None) pickup_at: Optional[datetime] = Field(default=None) eur_dkk_rate: Optional[Decimal] = Field(default=None, max_digits=10, decimal_places=4) intro_text: Optional[str] = Field(default=None) pickup_info_text: Optional[str] = Field(default=None) class PurchaseRound(PurchaseRoundBase, table=True): __tablename__ = "purchase_round" __table_args__ = ( CheckConstraint( "status = 'draft' OR " "(opens_at IS NOT NULL AND order_deadline_at IS NOT NULL AND pickup_at IS NOT NULL)", name="ck_purchase_round_dates_required_unless_draft", ), ) id: Optional[int] = Field(default=None, primary_key=True) route_id: int = Field(foreign_key="route.id", ondelete="CASCADE") route: "Route" = Relationship(back_populates="purchase_rounds") wine_offerings: List["WineOffering"] = Relationship( back_populates="purchase_round", sa_relationship_kwargs={"cascade": "all, delete-orphan"} ) orders: List["Order"] = Relationship( back_populates="purchase_round", sa_relationship_kwargs={"cascade": "all, delete-orphan"} )