from __future__ import annotations from datetime import datetime from typing import Any import uuid from sqlalchemy import DateTime, ForeignKey, Index, Integer, JSON, String, Text, UniqueConstraint from sqlalchemy.orm import Mapped, mapped_column from govoplan_core.db.base import Base, TimestampMixin def new_uuid() -> str: return str(uuid.uuid4()) class CommitteeWorkspaceRevision(Base, TimestampMixin): __tablename__ = "committee_workspace_revisions" __table_args__ = ( UniqueConstraint( "tenant_id", "object_kind", "object_id", "revision", name="uq_committee_workspace_revision", ), Index( "ix_committee_workspace_current", "tenant_id", "object_kind", "object_id", "superseded_at", ), Index( "ix_committee_workspace_parent", "tenant_id", "parent_kind", "parent_id", "object_kind", "state", ), ) id: Mapped[str] = mapped_column(String(36), primary_key=True, default=new_uuid) tenant_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True) object_kind: Mapped[str] = mapped_column(String(30), nullable=False, index=True) object_id: Mapped[str] = mapped_column(String(255), nullable=False, index=True) revision: Mapped[int] = mapped_column(Integer, nullable=False) previous_revision_id: Mapped[str | None] = mapped_column( ForeignKey("committee_workspace_revisions.id", ondelete="RESTRICT"), nullable=True, index=True, ) parent_kind: Mapped[str | None] = mapped_column(String(30), nullable=True, index=True) parent_id: Mapped[str | None] = mapped_column(String(255), nullable=True, index=True) state: Mapped[str] = mapped_column(String(30), nullable=False, index=True) title: Mapped[str] = mapped_column(String(500), nullable=False) search_text: Mapped[str] = mapped_column(Text, nullable=False) recorded_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, index=True) superseded_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True, index=True) payload: Mapped[dict[str, Any]] = mapped_column(JSON, nullable=False) changed_by: Mapped[str | None] = mapped_column(String(255), nullable=True, index=True) class CommitteeWorkspaceEvent(Base, TimestampMixin): __tablename__ = "committee_workspace_events" __table_args__ = ( UniqueConstraint("tenant_id", "event_id", name="uq_committee_workspace_event"), UniqueConstraint("tenant_id", "idempotency_key", name="uq_committee_workspace_idempotency"), Index( "ix_committee_workspace_event_object", "tenant_id", "object_kind", "object_id", "occurred_at", ), ) id: Mapped[str] = mapped_column(String(36), primary_key=True, default=new_uuid) tenant_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True) object_kind: Mapped[str] = mapped_column(String(30), nullable=False, index=True) object_id: Mapped[str] = mapped_column(String(255), nullable=False, index=True) object_revision: Mapped[int] = mapped_column(Integer, nullable=False) event_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True) event_type: Mapped[str] = mapped_column(String(120), nullable=False, index=True) occurred_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, index=True) actor_id: Mapped[str | None] = mapped_column(String(255), nullable=True, index=True) idempotency_key: Mapped[str] = mapped_column(String(255), nullable=False) request_sha256: Mapped[str] = mapped_column(String(64), nullable=False) payload: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False) class CommitteeDecisionProjection(Base, TimestampMixin): __tablename__ = "committee_decision_projections" __table_args__ = ( UniqueConstraint( "tenant_id", "decision_id", "revision", name="uq_committee_decision_projection_revision", ), Index( "ix_committee_decision_projection_current", "tenant_id", "decision_id", "superseded_at", ), ) id: Mapped[str] = mapped_column(String(36), primary_key=True, default=new_uuid) tenant_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True) decision_id: Mapped[str] = mapped_column(String(255), nullable=False, index=True) revision: Mapped[str] = mapped_column(String(120), nullable=False) previous_revision_id: Mapped[str | None] = mapped_column( ForeignKey("committee_decision_projections.id", ondelete="RESTRICT"), nullable=True, index=True, ) meeting_id: Mapped[str] = mapped_column(String(255), nullable=False, index=True) agenda_item_id: Mapped[str] = mapped_column(String(255), nullable=False, index=True) state: Mapped[str] = mapped_column(String(30), nullable=False, index=True) recorded_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, index=True) superseded_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True, index=True) payload: Mapped[dict[str, Any]] = mapped_column(JSON, nullable=False) changed_by: Mapped[str | None] = mapped_column(String(255), nullable=True, index=True) __all__ = [ "CommitteeDecisionProjection", "CommitteeWorkspaceEvent", "CommitteeWorkspaceRevision", ]