import uuid from datetime import datetime, timezone from sqlalchemy import Column, String, Text, DateTime, Boolean, ForeignKey from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import relationship from database.postgres import Base def _now(): return datetime.now(timezone.utc) class SupportTicket(Base): __tablename__ = "support_tickets" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) customer_id = Column(String(128), nullable=False) # Firestore ID (moves to UUID when customers migrate) customer_name = Column(String(255), nullable=True) # denormalized snapshot device_id = Column(String(128), nullable=True) # Firestore ID device_serial = Column(String(64), nullable=True) # denormalized snapshot subject = Column(String(500), nullable=False) status = Column(String(30), nullable=False, default="open") # open | waiting_on_customer | waiting_on_staff | resolved | closed priority = Column(String(10), nullable=True) # low | medium | high | urgent opened_via = Column(String(20), nullable=True) # app | email | phone | staff linked_entry_id = Column(UUID(as_uuid=True), ForeignKey("crm_entries.id", ondelete="SET NULL"), nullable=True) created_at = Column(DateTime(timezone=True), nullable=False, default=_now) updated_at = Column(DateTime(timezone=True), nullable=False, default=_now, onupdate=_now) messages = relationship("TicketMessage", back_populates="ticket", cascade="all, delete-orphan", order_by="TicketMessage.created_at", lazy="noload") class TicketMessage(Base): __tablename__ = "ticket_messages" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) ticket_id = Column(UUID(as_uuid=True), ForeignKey("support_tickets.id", ondelete="CASCADE"), nullable=False) sender_type = Column(String(10), nullable=False) # 'staff' | 'customer' sender_id = Column(String(128), nullable=False) sender_name = Column(String(255), nullable=True) body = Column(Text, nullable=False) is_internal = Column(Boolean, nullable=False, default=False) created_at = Column(DateTime(timezone=True), nullable=False, default=_now) ticket = relationship("SupportTicket", back_populates="messages")