from __future__ import annotations from datetime import datetime from sqlalchemy import JSON, BigInteger, Boolean, ForeignKey, String, Text, TIMESTAMP, text from sqlalchemy.orm import Mapped, mapped_column, relationship from app.db.base import Base class Workspace(Base): __tablename__ = "workspaces" id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True) workspace_type: Mapped[str] = mapped_column(String(20)) software_app_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True) service_type_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True) workspace_code: Mapped[str] = mapped_column(String(50), unique=True) workspace_name: Mapped[str] = mapped_column(String(100)) is_active: Mapped[bool] = mapped_column(Boolean, server_default=text("1")) created_at: Mapped[datetime] = mapped_column(TIMESTAMP, server_default=text("CURRENT_TIMESTAMP")) tickets: Mapped[list[SupportTicket]] = relationship(back_populates="workspace") approval_policies: Mapped[list[WorkspaceApprovalPolicy]] = relationship(back_populates="workspace") attachments: Mapped[list[Attachment]] = relationship(back_populates="workspace") class SupportTicket(Base): __tablename__ = "support_tickets" id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True) workspace_id: Mapped[int] = mapped_column(ForeignKey("workspaces.id")) requester_id: Mapped[str] = mapped_column(String(100)) requester_tenant_id: Mapped[str] = mapped_column(String(100)) requester_contact: Mapped[str | None] = mapped_column(String(100), nullable=True) ticket_type: Mapped[str] = mapped_column(String(30)) source_system: Mapped[str] = mapped_column(String(30), server_default=text("'ABC'")) title: Mapped[str] = mapped_column(String(255)) description: Mapped[str] = mapped_column(Text) category_code: Mapped[str | None] = mapped_column(String(20), nullable=True) status_code: Mapped[str] = mapped_column(String(20)) approval_status: Mapped[str] = mapped_column(String(20), server_default=text("'NOT_REQUIRED'")) sync_status: Mapped[str] = mapped_column(String(20), server_default=text("'PENDING'")) issue_link_status: Mapped[str] = mapped_column(String(20), server_default=text("'NOT_REQUIRED'")) is_secret: Mapped[bool] = mapped_column(Boolean, server_default=text("0")) requires_approval: Mapped[bool] = mapped_column(Boolean, server_default=text("0")) current_assignee_id: Mapped[str | None] = mapped_column(String(100), nullable=True) current_assignee_tenant_id: Mapped[str | None] = mapped_column(String(100), nullable=True) requested_start_at: Mapped[datetime | None] = mapped_column(TIMESTAMP, nullable=True) requested_end_at: Mapped[datetime | None] = mapped_column(TIMESTAMP, nullable=True) priority: Mapped[str] = mapped_column(String(20), server_default=text("'NORMAL'")) extra_fields: Mapped[dict[str, str] | None] = mapped_column(JSON, nullable=True) created_at: Mapped[datetime] = mapped_column(TIMESTAMP, server_default=text("CURRENT_TIMESTAMP")) updated_at: Mapped[datetime] = mapped_column( TIMESTAMP, server_default=text("CURRENT_TIMESTAMP"), server_onupdate=text("CURRENT_TIMESTAMP"), ) workspace: Mapped[Workspace] = relationship(back_populates="tickets") feedback_mapping: Mapped[ABCFeedbackMapping | None] = relationship(back_populates="ticket", uselist=False) approvals: Mapped[list[RequestApproval]] = relationship(back_populates="ticket") comments: Mapped[list[TicketComment]] = relationship(back_populates="ticket") attachments: Mapped[list[Attachment]] = relationship(back_populates="ticket") class ABCFeedbackMapping(Base): __tablename__ = "abc_feedback_mappings" id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True) ticket_id: Mapped[int] = mapped_column(ForeignKey("support_tickets.id"), unique=True) workspace_id: Mapped[int] = mapped_column(ForeignKey("workspaces.id")) abc_channel_id: Mapped[str] = mapped_column(String(100)) abc_feedback_id: Mapped[str] = mapped_column(String(100), unique=True) abc_feedback_url: Mapped[str | None] = mapped_column(Text, nullable=True) sync_status: Mapped[str] = mapped_column(String(20), server_default=text("'SYNCED'")) last_synced_at: Mapped[datetime] = mapped_column(TIMESTAMP, server_default=text("CURRENT_TIMESTAMP")) created_at: Mapped[datetime] = mapped_column(TIMESTAMP, server_default=text("CURRENT_TIMESTAMP")) ticket: Mapped[SupportTicket] = relationship(back_populates="feedback_mapping") class RequestApproval(Base): __tablename__ = "request_approvals" id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True) ticket_id: Mapped[int] = mapped_column(ForeignKey("support_tickets.id")) workflow_policy_id: Mapped[int | None] = mapped_column(ForeignKey("workspace_approval_policies.id"), nullable=True) workflow_step_id: Mapped[int | None] = mapped_column(ForeignKey("workspace_approval_steps.id"), nullable=True) step_order: Mapped[int | None] = mapped_column(nullable=True) approver_id: Mapped[str] = mapped_column(String(100)) approver_tenant_id: Mapped[str] = mapped_column(String(100)) approval_status: Mapped[str] = mapped_column(String(20)) comment: Mapped[str | None] = mapped_column(Text, nullable=True) approved_at: Mapped[datetime | None] = mapped_column(TIMESTAMP, nullable=True) created_at: Mapped[datetime] = mapped_column(TIMESTAMP, server_default=text("CURRENT_TIMESTAMP")) ticket: Mapped[SupportTicket] = relationship(back_populates="approvals") workflow_policy: Mapped[WorkspaceApprovalPolicy | None] = relationship(back_populates="approval_history") workflow_step: Mapped[WorkspaceApprovalStep | None] = relationship(back_populates="approval_history") class WorkspaceApprovalPolicy(Base): __tablename__ = "workspace_approval_policies" id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True) workspace_id: Mapped[int] = mapped_column(ForeignKey("workspaces.id")) request_category_code: Mapped[str | None] = mapped_column(String(50), nullable=True) ticket_type: Mapped[str | None] = mapped_column(String(30), nullable=True) rule_name: Mapped[str] = mapped_column(String(100)) description: Mapped[str | None] = mapped_column(Text, nullable=True) conditions: Mapped[dict[str, str] | None] = mapped_column(JSON, nullable=True) is_active: Mapped[bool] = mapped_column(Boolean, server_default=text("1")) version: Mapped[int] = mapped_column(server_default=text("1")) created_by: Mapped[str | None] = mapped_column(String(100), nullable=True) created_at: Mapped[datetime] = mapped_column(TIMESTAMP, server_default=text("CURRENT_TIMESTAMP")) updated_at: Mapped[datetime] = mapped_column( TIMESTAMP, server_default=text("CURRENT_TIMESTAMP"), server_onupdate=text("CURRENT_TIMESTAMP"), ) workspace: Mapped[Workspace] = relationship(back_populates="approval_policies") steps: Mapped[list[WorkspaceApprovalStep]] = relationship(back_populates="policy") approval_history: Mapped[list[RequestApproval]] = relationship(back_populates="workflow_policy") class WorkspaceApprovalStep(Base): __tablename__ = "workspace_approval_steps" id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True) policy_id: Mapped[int] = mapped_column(ForeignKey("workspace_approval_policies.id")) step_order: Mapped[int] = mapped_column() approver_type: Mapped[str] = mapped_column(String(30)) approver_key: Mapped[str] = mapped_column(String(100)) approver_name: Mapped[str | None] = mapped_column(String(100), nullable=True) approval_mode: Mapped[str] = mapped_column(String(20), server_default=text("'ALL'")) is_required: Mapped[bool] = mapped_column(Boolean, server_default=text("1")) sla_hours: Mapped[int | None] = mapped_column(nullable=True) created_at: Mapped[datetime] = mapped_column(TIMESTAMP, server_default=text("CURRENT_TIMESTAMP")) policy: Mapped[WorkspaceApprovalPolicy] = relationship(back_populates="steps") approval_history: Mapped[list[RequestApproval]] = relationship(back_populates="workflow_step") class TicketComment(Base): __tablename__ = "ticket_comments" id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True) ticket_id: Mapped[int] = mapped_column(ForeignKey("support_tickets.id")) parent_comment_id: Mapped[int | None] = mapped_column(ForeignKey("ticket_comments.id"), nullable=True) author_id: Mapped[str] = mapped_column(String(100)) author_tenant_id: Mapped[str] = mapped_column(String(100)) author_name: Mapped[str | None] = mapped_column(String(100), nullable=True) comment_type: Mapped[str] = mapped_column(String(20), server_default=text("'COMMENT'")) content: Mapped[str] = mapped_column(Text) is_internal: Mapped[bool] = mapped_column(Boolean, server_default=text("0")) abc_comment_id: Mapped[str | None] = mapped_column(String(100), nullable=True) sync_status: Mapped[str] = mapped_column(String(20), server_default=text("'PENDING'")) edited_at: Mapped[datetime | None] = mapped_column(TIMESTAMP, nullable=True) created_at: Mapped[datetime] = mapped_column(TIMESTAMP, server_default=text("CURRENT_TIMESTAMP")) updated_at: Mapped[datetime] = mapped_column( TIMESTAMP, server_default=text("CURRENT_TIMESTAMP"), server_onupdate=text("CURRENT_TIMESTAMP"), ) deleted_at: Mapped[datetime | None] = mapped_column(TIMESTAMP, nullable=True) ticket: Mapped[SupportTicket] = relationship(back_populates="comments") parent_comment: Mapped[TicketComment | None] = relationship(remote_side=[id]) attachments: Mapped[list[Attachment]] = relationship(back_populates="comment") class Attachment(Base): __tablename__ = "attachments" id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True) ticket_id: Mapped[int] = mapped_column(ForeignKey("support_tickets.id")) comment_id: Mapped[int | None] = mapped_column(ForeignKey("ticket_comments.id"), nullable=True) workspace_id: Mapped[int] = mapped_column(ForeignKey("workspaces.id")) uploader_id: Mapped[str] = mapped_column(String(100)) uploader_tenant_id: Mapped[str] = mapped_column(String(100)) original_file_name: Mapped[str] = mapped_column(String(255)) stored_file_name: Mapped[str | None] = mapped_column(String(255), nullable=True) storage_provider: Mapped[str] = mapped_column(String(30), server_default=text("'LOCAL'")) storage_bucket: Mapped[str | None] = mapped_column(String(255), nullable=True) storage_key: Mapped[str] = mapped_column(String(500)) mime_type: Mapped[str | None] = mapped_column(String(100), nullable=True) file_extension: Mapped[str | None] = mapped_column(String(20), nullable=True) file_size: Mapped[int | None] = mapped_column(BigInteger, nullable=True) checksum_sha256: Mapped[str | None] = mapped_column(String(64), nullable=True) abc_attachment_id: Mapped[str | None] = mapped_column(String(100), nullable=True) attachment_status: Mapped[str] = mapped_column(String(20), server_default=text("'ACTIVE'")) created_at: Mapped[datetime] = mapped_column(TIMESTAMP, server_default=text("CURRENT_TIMESTAMP")) updated_at: Mapped[datetime] = mapped_column( TIMESTAMP, server_default=text("CURRENT_TIMESTAMP"), server_onupdate=text("CURRENT_TIMESTAMP"), ) deleted_at: Mapped[datetime | None] = mapped_column(TIMESTAMP, nullable=True) ticket: Mapped[SupportTicket] = relationship(back_populates="attachments") comment: Mapped[TicketComment | None] = relationship(back_populates="attachments") workspace: Mapped[Workspace] = relationship(back_populates="attachments")