""" Ticket Link model for connecting sessions to external ticketing systems. This model creates relationships between ClaudeTools sessions and tickets in external systems like SyncroMSP, Autotask, ConnectWise, etc. """ from datetime import datetime from typing import Optional from sqlalchemy import CHAR, ForeignKey, Index, String from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql import func from .base import Base, UUIDMixin class TicketLink(Base, UUIDMixin): """ Links between sessions and external ticketing system tickets. Creates associations between ClaudeTools work sessions and tickets in external MSP platforms. Enables automatic time tracking, status updates, and work documentation in ticketing systems. Attributes: id: Unique identifier session_id: Reference to the ClaudeTools session client_id: Reference to the client integration_type: Type of ticketing system (syncro, autotask, connectwise) ticket_id: External ticket identifier ticket_number: Human-readable ticket number (e.g., "T12345") ticket_subject: Subject/title of the ticket ticket_url: Direct URL to view the ticket ticket_status: Current status of the ticket link_type: Type of relationship (related, resolves, documents) created_at: When the link was created """ __tablename__ = "ticket_links" # Foreign keys session_id: Mapped[Optional[str]] = mapped_column( CHAR(36), ForeignKey("sessions.id", ondelete="CASCADE"), nullable=True, doc="ClaudeTools session linked to this ticket", ) client_id: Mapped[Optional[str]] = mapped_column( CHAR(36), ForeignKey("clients.id", ondelete="CASCADE"), nullable=True, doc="Client this ticket belongs to", ) # Ticket information integration_type: Mapped[str] = mapped_column( String(100), nullable=False, doc="Ticketing system type (syncro, autotask, connectwise)", ) ticket_id: Mapped[str] = mapped_column( String(255), nullable=False, doc="External ticket identifier", ) ticket_number: Mapped[Optional[str]] = mapped_column( String(100), nullable=True, doc="Human-readable ticket number (T12345)", ) ticket_subject: Mapped[Optional[str]] = mapped_column( String(500), nullable=True, doc="Subject/title of the ticket", ) ticket_url: Mapped[Optional[str]] = mapped_column( String(500), nullable=True, doc="Direct URL to view the ticket", ) ticket_status: Mapped[Optional[str]] = mapped_column( String(100), nullable=True, doc="Current status of the ticket", ) # Link metadata link_type: Mapped[Optional[str]] = mapped_column( String(50), nullable=True, doc="Type of relationship (related, resolves, documents)", ) created_at: Mapped[datetime] = mapped_column( nullable=False, server_default=func.now(), doc="When the link was created", ) # Indexes __table_args__ = ( Index("idx_ticket_session", "session_id"), Index("idx_ticket_client", "client_id"), Index("idx_ticket_external", "integration_type", "ticket_id"), ) # Relationships # session = relationship("Session", back_populates="ticket_links") # client = relationship("Client", back_populates="ticket_links") def __repr__(self) -> str: """String representation of the ticket link.""" return ( f"" )