from sqlalchemy import String, Text, Boolean, Integer, ForeignKey, func from sqlalchemy.orm import Mapped, mapped_column, relationship from datetime import datetime from typing import Optional from app.database import Base class CalendarEvent(Base): __tablename__ = "calendar_events" id: Mapped[int] = mapped_column(primary_key=True, index=True) title: Mapped[str] = mapped_column(String(255), nullable=False) description: Mapped[Optional[str]] = mapped_column(Text, nullable=True) start_datetime: Mapped[datetime] = mapped_column(nullable=False) end_datetime: Mapped[datetime] = mapped_column(nullable=False) all_day: Mapped[bool] = mapped_column(Boolean, default=False) color: Mapped[Optional[str]] = mapped_column(String(20), nullable=True) location_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("locations.id"), nullable=True) recurrence_rule: Mapped[Optional[str]] = mapped_column(String(255), nullable=True) is_starred: Mapped[bool] = mapped_column(Boolean, default=False, server_default="false") calendar_id: Mapped[int] = mapped_column(Integer, ForeignKey("calendars.id"), nullable=False) # Recurrence fields # parent_event_id: set on child events; NULL on the parent template row parent_event_id: Mapped[Optional[int]] = mapped_column( Integer, ForeignKey("calendar_events.id", ondelete="CASCADE"), nullable=True, ) # is_recurring: True on both the parent template and all generated children is_recurring: Mapped[bool] = mapped_column(Boolean, default=False, server_default="false") # original_start: the originally computed occurrence datetime (children only) original_start: Mapped[Optional[datetime]] = mapped_column(nullable=True) created_at: Mapped[datetime] = mapped_column(default=func.now()) updated_at: Mapped[datetime] = mapped_column(default=func.now(), onupdate=func.now()) location: Mapped[Optional["Location"]] = relationship(back_populates="events") calendar: Mapped["Calendar"] = relationship(back_populates="events") @property def calendar_name(self) -> str: return self.calendar.name if self.calendar else "" @property def calendar_color(self) -> str: return self.calendar.color if self.calendar else ""