import enum from sqlalchemy import Column, Integer, String, Date, Boolean, Text, DateTime, Enum, ForeignKey from sqlalchemy.orm import relationship from sqlalchemy.sql import func from database import Base class Category(str, enum.Enum): vegetable = "vegetable" herb = "herb" flower = "flower" fruit = "fruit" class SunRequirement(str, enum.Enum): full_sun = "full_sun" part_shade = "part_shade" full_shade = "full_shade" class WaterNeeds(str, enum.Enum): low = "low" medium = "medium" high = "high" class BatchStatus(str, enum.Enum): planned = "planned" germinating = "germinating" seedling = "seedling" potted_up = "potted_up" hardening = "hardening" garden = "garden" harvested = "harvested" failed = "failed" class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, autoincrement=True) email = Column(String(255), unique=True, nullable=False) hashed_password = Column(String(255), nullable=False) is_admin = Column(Boolean, default=False, nullable=False) is_disabled = Column(Boolean, default=False, nullable=False) created_at = Column(DateTime, server_default=func.now()) last_login_at = Column(DateTime, nullable=True) varieties = relationship("Variety", back_populates="user", cascade="all, delete-orphan") batches = relationship("Batch", back_populates="user", cascade="all, delete-orphan") settings = relationship("Settings", back_populates="user", uselist=False, cascade="all, delete-orphan") notification_logs = relationship("NotificationLog", back_populates="user", cascade="all, delete-orphan") class Variety(Base): __tablename__ = "varieties" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True) name = Column(String(100), nullable=False) variety_name = Column(String(100)) category = Column(Enum(Category), default=Category.vegetable) weeks_to_start = Column(Integer) weeks_to_greenhouse = Column(Integer) weeks_to_garden = Column(Integer) days_to_germinate = Column(Integer, default=7) direct_sow_ok = Column(Boolean, default=False) frost_tolerant = Column(Boolean, default=False) sun_requirement = Column(Enum(SunRequirement), default=SunRequirement.full_sun) water_needs = Column(Enum(WaterNeeds), default=WaterNeeds.medium) color = Column(String(7), default="#52b788") notes = Column(Text) created_at = Column(DateTime, server_default=func.now()) user = relationship("User", back_populates="varieties") batches = relationship("Batch", back_populates="variety", cascade="all, delete-orphan") class Batch(Base): __tablename__ = "batches" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True) variety_id = Column(Integer, ForeignKey("varieties.id"), nullable=False) label = Column(String(100)) quantity = Column(Integer, default=1) sow_date = Column(Date) germination_date = Column(Date) greenhouse_date = Column(Date) garden_date = Column(Date) status = Column(Enum(BatchStatus), default=BatchStatus.planned) notes = Column(Text) created_at = Column(DateTime, server_default=func.now()) user = relationship("User", back_populates="batches") variety = relationship("Variety", back_populates="batches") class Settings(Base): __tablename__ = "settings" id = Column(Integer, primary_key=True, autoincrement=True) user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), unique=True, nullable=False) last_frost_date = Column(Date) first_frost_fall_date = Column(Date) ntfy_topic = Column(String(200)) ntfy_server = Column(String(200), default="https://ntfy.sh") notification_time = Column(String(5), default="07:00") timezone = Column(String(50), default="UTC") location_name = Column(String(100)) ntfy_username = Column(String(200)) ntfy_password = Column(String(200)) ntfy_api_key = Column(String(200)) user = relationship("User", back_populates="settings") class NotificationLog(Base): __tablename__ = "notification_log" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=True) sent_at = Column(DateTime, server_default=func.now()) message = Column(Text) status = Column(String(20)) error = Column(Text) user = relationship("User", back_populates="notification_logs")