from datetime import datetime from typing import Any from sqlalchemy import JSON, BigInteger, DateTime, Integer, String, Text, UniqueConstraint from sqlalchemy.orm import Mapped, mapped_column from app.model.base import Base class RequestIdempotency(Base): __tablename__ = "request_idempotency" id: Mapped[int] = mapped_column(BigInteger, primary_key=True) user_id: Mapped[int] = mapped_column(BigInteger, nullable=False) session_id: Mapped[str] = mapped_column(String(64), nullable=False) agent_type: Mapped[str] = mapped_column(String(32), nullable=False) idempotency_key: Mapped[str] = mapped_column(String(64), nullable=False) request_hash: Mapped[str] = mapped_column(String(64), nullable=False) trace_id: Mapped[str] = mapped_column(String(64), nullable=False) status: Mapped[str] = mapped_column(String(16), nullable=False, default="processing") result_message_id: Mapped[int | None] = mapped_column(BigInteger) error_code: Mapped[str | None] = mapped_column(String(64)) locked_until: Mapped[datetime | None] = mapped_column(DateTime) expire_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) __table_args__ = (UniqueConstraint("user_id", "agent_type", "idempotency_key"),) class AgentRun(Base): __tablename__ = "agent_run" id: Mapped[int] = mapped_column(BigInteger, primary_key=True) run_id: Mapped[str] = mapped_column(String(36), unique=True, nullable=False) idempotency_id: Mapped[int] = mapped_column(BigInteger, unique=True, nullable=False) session_id: Mapped[str] = mapped_column(String(64), nullable=False) user_id: Mapped[int] = mapped_column(BigInteger, nullable=False) agent_type: Mapped[str] = mapped_column(String(32), nullable=False) trace_id: Mapped[str] = mapped_column(String(64), unique=True, nullable=False) request_message_id: Mapped[int] = mapped_column(BigInteger, nullable=False) result_message_id: Mapped[int | None] = mapped_column(BigInteger) status: Mapped[str] = mapped_column(String(24), nullable=False, default="queued") attempt_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0) worker_id: Mapped[str | None] = mapped_column(String(128)) locked_until: Mapped[datetime | None] = mapped_column(DateTime) error_code: Mapped[str | None] = mapped_column(String(64)) result_version: Mapped[int | None] = mapped_column(Integer) cancel_requested_at: Mapped[datetime | None] = mapped_column(DateTime) started_at: Mapped[datetime | None] = mapped_column(DateTime) completed_at: Mapped[datetime | None] = mapped_column(DateTime) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) class DomainEventOutbox(Base): __tablename__ = "domain_event_outbox" id: Mapped[int] = mapped_column(BigInteger, primary_key=True) event_id: Mapped[str] = mapped_column(String(36), unique=True, nullable=False) event_type: Mapped[str] = mapped_column(String(64), nullable=False) aggregate_type: Mapped[str] = mapped_column(String(32), nullable=False) aggregate_id: Mapped[str] = mapped_column(String(64), nullable=False) trace_id: Mapped[str] = mapped_column(String(64), nullable=False) payload: Mapped[dict[str, Any]] = mapped_column(JSON, nullable=False) status: Mapped[str] = mapped_column(String(16), nullable=False, default="pending") retry_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0) next_retry_at: Mapped[datetime | None] = mapped_column(DateTime) last_error: Mapped[str | None] = mapped_column(Text) occurred_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) published_at: Mapped[datetime | None] = mapped_column(DateTime) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) class OutboxDelivery(Base): __tablename__ = "outbox_delivery" __table_args__ = ( UniqueConstraint("event_id", "consumer_name", name="uk_outbox_delivery_event_consumer"), ) id: Mapped[int] = mapped_column(BigInteger, primary_key=True) event_id: Mapped[str] = mapped_column(String(36), nullable=False) consumer_name: Mapped[str] = mapped_column(String(64), nullable=False) delivered_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) class HandoverTicket(Base): __tablename__ = "svc_handover_ticket" id: Mapped[int] = mapped_column(BigInteger, primary_key=True) ticket_no: Mapped[str] = mapped_column(String(32), unique=True, nullable=False) session_id: Mapped[str] = mapped_column(String(64), nullable=False) customer_id: Mapped[int | None] = mapped_column(BigInteger) source_agent: Mapped[str] = mapped_column(String(32), nullable=False) source_message_id: Mapped[int | None] = mapped_column(BigInteger) reason_code: Mapped[str] = mapped_column(String(64), nullable=False) reason_detail: Mapped[str | None] = mapped_column(String(500)) status: Mapped[str] = mapped_column(String(16), nullable=False, default="pending") created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)