import uuid import enum from datetime import datetime, timezone from sqlalchemy import String, Boolean, DateTime, Enum as SAEnum, ForeignKey, Text, Integer from sqlalchemy.orm import Mapped, mapped_column, relationship from app.database import Base class TicketStatus(str, enum.Enum): open = "open" in_progress = "in_progress" resolved = "resolved" closed = "closed" class TicketPriority(str, enum.Enum): low = "low" medium = "medium" high = "high" urgent = "urgent" class TicketCategory(str, enum.Enum): billing = "billing" technical = "technical" sms = "sms" license = "license" general = "general" class SupportTicket(Base): __tablename__ = "support_tickets" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) school_id: Mapped[str] = mapped_column(String(36), ForeignKey("schools.id", ondelete="CASCADE"), nullable=False, index=True) submitted_by: Mapped[str] = mapped_column(String(36), ForeignKey("hub_users.id", ondelete="SET NULL"), nullable=True) ticket_number: Mapped[str] = mapped_column(String(20), unique=True, nullable=False) subject: Mapped[str] = mapped_column(String(255), nullable=False) body: Mapped[str] = mapped_column(Text, nullable=False) category: Mapped[TicketCategory] = mapped_column(SAEnum(TicketCategory), default=TicketCategory.general, nullable=False) status: Mapped[TicketStatus] = mapped_column(SAEnum(TicketStatus), default=TicketStatus.open, nullable=False) priority: Mapped[TicketPriority] = mapped_column(SAEnum(TicketPriority), default=TicketPriority.medium, nullable=False) assigned_to: Mapped[str | None] = mapped_column(String(36), ForeignKey("hub_users.id", ondelete="SET NULL"), nullable=True) first_response_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) resolved_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)) updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) school: Mapped["School"] = relationship("School", back_populates="tickets") replies: Mapped[list["TicketReply"]] = relationship("TicketReply", back_populates="ticket", cascade="all, delete-orphan") class TicketReply(Base): __tablename__ = "ticket_replies" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) ticket_id: Mapped[str] = mapped_column(String(36), ForeignKey("support_tickets.id", ondelete="CASCADE"), nullable=False) author_id: Mapped[str] = mapped_column(String(36), ForeignKey("hub_users.id", ondelete="SET NULL"), nullable=True) body: Mapped[str] = mapped_column(Text, nullable=False) is_internal: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)) ticket: Mapped[SupportTicket] = relationship("SupportTicket", back_populates="replies")