import enum import uuid from sqlalchemy import ( Boolean, Enum, ForeignKey, Integer, String, Text, UniqueConstraint, ) from sqlalchemy.orm import Mapped, mapped_column, relationship from app.db.base import Base class NutrientDemand(str, enum.Enum): SCHWACH = "schwach" MITTEL = "mittel" STARK = "stark" class WaterDemand(str, enum.Enum): WENIG = "wenig" MITTEL = "mittel" VIEL = "viel" class CompatibilityRating(str, enum.Enum): GUT = "gut" NEUTRAL = "neutral" SCHLECHT = "schlecht" class PlantFamily(Base): __tablename__ = "plant_families" id: Mapped[uuid.UUID] = mapped_column( primary_key=True, default=uuid.uuid4, index=True ) name: Mapped[str] = mapped_column(String(255), nullable=False, unique=True) latin_name: Mapped[str] = mapped_column(String(255), nullable=False, unique=True) # Relationships plants: Mapped[list["Plant"]] = relationship("Plant", back_populates="family") class Plant(Base): __tablename__ = "plants" id: Mapped[uuid.UUID] = mapped_column( primary_key=True, default=uuid.uuid4, index=True ) tenant_id: Mapped[uuid.UUID | None] = mapped_column( ForeignKey("tenants.id", ondelete="CASCADE"), nullable=True, index=True, ) family_id: Mapped[uuid.UUID] = mapped_column( ForeignKey("plant_families.id", ondelete="RESTRICT"), nullable=False, index=True, ) name: Mapped[str] = mapped_column(String(255), nullable=False) latin_name: Mapped[str | None] = mapped_column(String(255), nullable=True) nutrient_demand: Mapped[NutrientDemand] = mapped_column( Enum(NutrientDemand, name="nutrient_demand"), nullable=False, ) water_demand: Mapped[WaterDemand] = mapped_column( Enum(WaterDemand, name="water_demand"), nullable=False, ) spacing_cm: Mapped[int] = mapped_column(Integer, nullable=False) sowing_start_month: Mapped[int] = mapped_column(Integer, nullable=False) sowing_end_month: Mapped[int] = mapped_column(Integer, nullable=False) rest_years: Mapped[int] = mapped_column(Integer, nullable=False, default=0) notes: Mapped[str | None] = mapped_column(Text, nullable=True) is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False) # Relationships tenant: Mapped["Tenant | None"] = relationship( # noqa: F821 "Tenant", back_populates="plants" ) family: Mapped["PlantFamily"] = relationship("PlantFamily", back_populates="plants") plantings: Mapped[list["BedPlanting"]] = relationship( # noqa: F821 "BedPlanting", back_populates="plant" ) compatibility_a: Mapped[list["PlantCompatibility"]] = relationship( "PlantCompatibility", foreign_keys="PlantCompatibility.plant_id_a", back_populates="plant_a", cascade="all, delete-orphan", ) compatibility_b: Mapped[list["PlantCompatibility"]] = relationship( "PlantCompatibility", foreign_keys="PlantCompatibility.plant_id_b", back_populates="plant_b", cascade="all, delete-orphan", ) class PlantCompatibility(Base): __tablename__ = "plant_compatibilities" __table_args__ = ( UniqueConstraint("plant_id_a", "plant_id_b", name="uq_plant_compatibility"), ) id: Mapped[uuid.UUID] = mapped_column( primary_key=True, default=uuid.uuid4, index=True ) plant_id_a: Mapped[uuid.UUID] = mapped_column( ForeignKey("plants.id", ondelete="CASCADE"), nullable=False, ) plant_id_b: Mapped[uuid.UUID] = mapped_column( ForeignKey("plants.id", ondelete="CASCADE"), nullable=False, ) rating: Mapped[CompatibilityRating] = mapped_column( Enum(CompatibilityRating, name="compatibility_rating"), nullable=False, ) reason: Mapped[str | None] = mapped_column(Text, nullable=True) # Relationships plant_a: Mapped["Plant"] = relationship( "Plant", foreign_keys=[plant_id_a], back_populates="compatibility_a" ) plant_b: Mapped["Plant"] = relationship( "Plant", foreign_keys=[plant_id_b], back_populates="compatibility_b" )