from __future__ import annotations from datetime import datetime from typing import Any import uuid from sqlalchemy import ( Boolean, 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 ReportingDefinitionIdentity(Base, TimestampMixin): __tablename__ = "reporting_definition_identities" __table_args__ = ( UniqueConstraint( "tenant_id", "definition_kind", "definition_id", name="uq_reporting_definition_identity", ), UniqueConstraint( "tenant_id", "definition_kind", "definition_key", name="uq_reporting_definition_key", ), Index( "ix_reporting_definition_catalog", "tenant_id", "definition_kind", "definition_key", ), ) 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) definition_kind: Mapped[str] = mapped_column(String(40), nullable=False, index=True) definition_id: Mapped[str] = mapped_column(String(255), nullable=False, index=True) definition_key: Mapped[str] = mapped_column(String(120), nullable=False, index=True) created_by: Mapped[str | None] = mapped_column( String(255), nullable=True, index=True ) class ReportingDefinitionRevision(Base, TimestampMixin): __tablename__ = "reporting_definition_revisions" __table_args__ = ( UniqueConstraint( "tenant_id", "definition_kind", "definition_id", "revision", name="uq_reporting_definition_revision", ), UniqueConstraint( "tenant_id", "idempotency_key", name="uq_reporting_definition_idempotency", ), UniqueConstraint( "tenant_id", "event_id", name="uq_reporting_definition_event", ), Index( "ix_reporting_definition_current", "tenant_id", "definition_kind", "definition_id", "superseded_at", ), Index( "ix_reporting_definition_parent", "tenant_id", "parent_kind", "parent_id", "parent_revision", ), Index( "ix_reporting_definition_list", "tenant_id", "definition_kind", "status", "recorded_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) identity_id: Mapped[str] = mapped_column( ForeignKey("reporting_definition_identities.id", ondelete="RESTRICT"), nullable=False, index=True, ) definition_kind: Mapped[str] = mapped_column(String(40), nullable=False, index=True) definition_id: Mapped[str] = mapped_column(String(255), nullable=False, index=True) definition_key: Mapped[str] = mapped_column(String(120), nullable=False, index=True) revision: Mapped[int] = mapped_column(Integer, nullable=False) previous_revision_id: Mapped[str | None] = mapped_column( ForeignKey("reporting_definition_revisions.id", ondelete="RESTRICT"), nullable=True, index=True, ) parent_kind: Mapped[str | None] = mapped_column( String(40), nullable=True, index=True ) parent_id: Mapped[str | None] = mapped_column( String(255), nullable=True, index=True ) parent_revision: Mapped[int | None] = mapped_column(Integer, nullable=True) name: Mapped[str] = mapped_column(String(500), nullable=False) description: Mapped[str | None] = mapped_column(Text, nullable=True) status: Mapped[str] = mapped_column(String(30), nullable=False, index=True) visibility: Mapped[str] = mapped_column(String(30), nullable=False, index=True) content_hash: Mapped[str] = mapped_column(String(64), nullable=False, index=True) change_reason: Mapped[str] = mapped_column(String(1000), nullable=False) idempotency_key: Mapped[str] = mapped_column(String(255), nullable=False) request_sha256: Mapped[str] = mapped_column(String(64), nullable=False) event_id: Mapped[str] = mapped_column(String(36), 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 ) class ReportingExecution(Base, TimestampMixin): __tablename__ = "reporting_executions" __table_args__ = ( UniqueConstraint("tenant_id", "execution_id", name="uq_reporting_execution"), UniqueConstraint( "tenant_id", "idempotency_key", name="uq_reporting_execution_idempotency", ), Index( "ix_reporting_execution_history", "tenant_id", "report_id", "started_at", ), Index( "ix_reporting_execution_status", "tenant_id", "status", "started_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) execution_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True) report_id: Mapped[str] = mapped_column(String(255), nullable=False, index=True) report_revision: Mapped[int] = mapped_column(Integer, nullable=False) semantic_model_id: Mapped[str] = mapped_column( String(255), nullable=False, index=True ) semantic_model_revision: Mapped[int] = mapped_column(Integer, nullable=False) dataset_id: Mapped[str] = mapped_column(String(255), nullable=False, index=True) dataset_revision: Mapped[int] = mapped_column(Integer, nullable=False) status: Mapped[str] = mapped_column(String(30), nullable=False, index=True) idempotency_key: Mapped[str] = mapped_column(String(255), nullable=False) request_sha256: Mapped[str] = mapped_column(String(64), nullable=False) parameters: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False ) query: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False) source_fingerprints: Mapped[list[dict[str, Any]]] = mapped_column( JSON, default=list, nullable=False ) definition_hashes: Mapped[dict[str, str]] = mapped_column( JSON, default=dict, nullable=False ) output_hash: Mapped[str | None] = mapped_column( String(64), nullable=True, index=True ) executor_version: Mapped[str | None] = mapped_column(String(255), nullable=True) result_schema: Mapped[list[dict[str, Any]]] = mapped_column( JSON, default=list, nullable=False ) result_rows: Mapped[list[dict[str, Any]]] = mapped_column( JSON, default=list, nullable=False ) total_rows: Mapped[int] = mapped_column(Integer, default=0, nullable=False) truncated: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False) diagnostics: Mapped[list[dict[str, Any]]] = mapped_column( JSON, default=list, nullable=False ) provenance: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False ) started_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, index=True ) finished_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, index=True ) actor_id: Mapped[str | None] = mapped_column(String(255), nullable=True, index=True) class ReportingProviderExecution(Base, TimestampMixin): __tablename__ = "reporting_provider_executions" __table_args__ = ( UniqueConstraint( "tenant_id", "execution_id", name="uq_reporting_provider_execution", ), UniqueConstraint( "tenant_id", "idempotency_key", name="uq_reporting_provider_execution_idempotency", ), Index( "ix_reporting_provider_execution_history", "tenant_id", "provider_id", "report_id", "generated_at", ), Index( "ix_reporting_provider_execution_retention", "tenant_id", "expires_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) execution_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True) provider_id: Mapped[str] = mapped_column(String(120), nullable=False, index=True) report_id: Mapped[str] = mapped_column(String(255), nullable=False, index=True) report_revision: Mapped[str] = mapped_column(String(255), nullable=False) contract_version: Mapped[str] = mapped_column(String(30), nullable=False) idempotency_key: Mapped[str] = mapped_column(String(255), nullable=False) request_sha256: Mapped[str] = mapped_column(String(64), nullable=False) purpose: Mapped[str] = mapped_column(Text, nullable=False) audience_scope: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False ) parameters: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False ) result_schema: Mapped[list[dict[str, Any]]] = mapped_column( JSON, default=list, nullable=False ) result_payload: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False ) source_revisions: Mapped[list[dict[str, Any]]] = mapped_column( JSON, default=list, nullable=False ) effective_scope: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False ) privacy_transforms: Mapped[list[str]] = mapped_column( JSON, default=list, nullable=False ) provenance: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False ) governance_provenance: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False ) retention_class: Mapped[str] = mapped_column(String(120), nullable=False) retention_days: Mapped[int | None] = mapped_column(Integer, nullable=True) expires_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, index=True ) retention_redacted_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, index=True ) output_hash: Mapped[str] = mapped_column(String(64), nullable=False, index=True) generated_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) class ReportingProviderExport(Base, TimestampMixin): __tablename__ = "reporting_provider_exports" __table_args__ = ( UniqueConstraint( "tenant_id", "export_id", name="uq_reporting_provider_export", ), Index( "ix_reporting_provider_export_history", "tenant_id", "provider_execution_id", "exported_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) export_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True) provider_execution_id: Mapped[str] = mapped_column( ForeignKey( "reporting_provider_executions.id", ondelete="RESTRICT", ), nullable=False, index=True, ) execution_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True) format: Mapped[str] = mapped_column(String(30), nullable=False) purpose: Mapped[str] = mapped_column(Text, nullable=False) audience_scope: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False ) output_hash: Mapped[str] = mapped_column(String(64), nullable=False, index=True) exported_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) class ReportingDefinitionGrant(Base, TimestampMixin): __tablename__ = "reporting_definition_grants" __table_args__ = ( UniqueConstraint( "tenant_id", "definition_kind", "definition_id", "subject_kind", "subject_id", name="uq_reporting_definition_grant", ), Index( "ix_reporting_definition_grant_subject", "tenant_id", "subject_kind", "subject_id", "active", ), Index( "ix_reporting_definition_grant_object", "tenant_id", "definition_kind", "definition_id", "active", ), ) 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) definition_kind: Mapped[str] = mapped_column(String(40), nullable=False, index=True) definition_id: Mapped[str] = mapped_column(String(255), nullable=False, index=True) subject_kind: Mapped[str] = mapped_column(String(40), nullable=False, index=True) subject_id: Mapped[str] = mapped_column(String(255), nullable=False, index=True) permissions: Mapped[list[str]] = mapped_column(JSON, default=list, nullable=False) active: Mapped[bool] = mapped_column( Boolean, default=True, nullable=False, index=True ) source_revision: Mapped[int] = mapped_column(Integer, nullable=False) class ReportingSavedView(Base, TimestampMixin): __tablename__ = "reporting_saved_views" __table_args__ = ( UniqueConstraint("tenant_id", "view_id", name="uq_reporting_saved_view"), Index( "ix_reporting_saved_view_catalog", "tenant_id", "report_id", "owner_id", "shared", ), ) 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) view_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True) report_id: Mapped[str] = mapped_column(String(255), nullable=False, index=True) report_revision: Mapped[int] = mapped_column(Integer, nullable=False) owner_kind: Mapped[str] = mapped_column(String(40), nullable=False, index=True) owner_id: Mapped[str] = mapped_column(String(255), nullable=False, index=True) name: Mapped[str] = mapped_column(String(500), nullable=False) revision: Mapped[int] = mapped_column(Integer, default=1, nullable=False) state: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False) shared: Mapped[bool] = mapped_column( Boolean, default=False, nullable=False, index=True ) access: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False) class ReportingSchedule(Base, TimestampMixin): __tablename__ = "reporting_schedules" __table_args__ = ( UniqueConstraint("tenant_id", "schedule_id", name="uq_reporting_schedule"), Index( "ix_reporting_schedule_due", "enabled", "next_run_at", "tenant_id", ), ) 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) schedule_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True) report_id: Mapped[str] = mapped_column(String(255), nullable=False, index=True) report_revision: Mapped[int] = mapped_column(Integer, nullable=False) name: Mapped[str] = mapped_column(String(500), nullable=False) revision: Mapped[int] = mapped_column(Integer, default=1, nullable=False) trigger_kind: Mapped[str] = mapped_column(String(30), nullable=False) trigger_config: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False ) parameters: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False ) query: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False) publication_target: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False ) enabled: Mapped[bool] = mapped_column( Boolean, default=True, nullable=False, index=True ) next_run_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, index=True ) last_run_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True ) last_execution_id: Mapped[str | None] = mapped_column(String(36), nullable=True) created_by: Mapped[str | None] = mapped_column(String(255), nullable=True) class ReportingPublication(Base, TimestampMixin): __tablename__ = "reporting_publications" __table_args__ = ( UniqueConstraint( "tenant_id", "publication_id", name="uq_reporting_publication" ), UniqueConstraint( "tenant_id", "idempotency_key", name="uq_reporting_publication_idempotency", ), Index( "ix_reporting_publication_history", "tenant_id", "execution_id", "created_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) publication_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True) execution_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True) target_capability: Mapped[str] = mapped_column(String(255), nullable=False) target_ref: Mapped[str | None] = mapped_column(String(1000), nullable=True) format: Mapped[str] = mapped_column(String(30), nullable=False) status: Mapped[str] = mapped_column(String(30), nullable=False, index=True) idempotency_key: Mapped[str] = mapped_column(String(255), nullable=False) evidence: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False) error: Mapped[str | None] = mapped_column(Text, nullable=True) completed_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True ) class ReportingDrillContext(Base, TimestampMixin): __tablename__ = "reporting_drill_contexts" __table_args__ = ( UniqueConstraint( "tenant_id", "drill_context_id", name="uq_reporting_drill_context" ), Index( "ix_reporting_drill_context_expiry", "tenant_id", "expires_at", ), Index( "ix_reporting_drill_context_execution", "tenant_id", "execution_id", ), ) 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) drill_context_id: Mapped[str] = mapped_column( String(36), nullable=False, index=True ) execution_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True) token_sha256: Mapped[str] = mapped_column(String(64), nullable=False) context_sha256: Mapped[str] = mapped_column(String(64), nullable=False) actor_id: Mapped[str] = mapped_column(String(255), nullable=False, index=True) dimension_path: Mapped[list[dict[str, Any]]] = mapped_column( JSON, default=list, nullable=False ) source_fingerprints: Mapped[list[dict[str, Any]]] = mapped_column( JSON, default=list, nullable=False ) policy_provenance: Mapped[dict[str, Any]] = mapped_column( JSON, default=dict, nullable=False ) expires_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, index=True ) last_accessed_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True ) class ReportingQualityResult(Base, TimestampMixin): __tablename__ = "reporting_quality_results" __table_args__ = ( UniqueConstraint("tenant_id", "result_id", name="uq_reporting_quality_result"), Index( "ix_reporting_quality_history", "tenant_id", "quality_plan_id", "evaluated_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) result_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True) quality_plan_id: Mapped[str] = mapped_column( String(255), nullable=False, index=True ) quality_plan_revision: Mapped[int] = mapped_column(Integer, nullable=False) dataset_id: Mapped[str] = mapped_column(String(255), nullable=False, index=True) dataset_revision: Mapped[int] = mapped_column(Integer, nullable=False) status: Mapped[str] = mapped_column(String(30), nullable=False, index=True) output_hash: Mapped[str] = mapped_column(String(64), nullable=False, index=True) assertions: Mapped[list[dict[str, Any]]] = mapped_column( JSON, default=list, nullable=False ) source_fingerprints: Mapped[list[dict[str, Any]]] = mapped_column( JSON, default=list, nullable=False ) evaluated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, index=True ) actor_id: Mapped[str | None] = mapped_column(String(255), nullable=True) class ReportingImportAssessment(Base, TimestampMixin): __tablename__ = "reporting_import_assessments" __table_args__ = ( UniqueConstraint( "tenant_id", "assessment_id", name="uq_reporting_import_assessment" ), Index( "ix_reporting_import_history", "tenant_id", "source_system", "created_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) assessment_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True) source_system: Mapped[str] = mapped_column(String(255), nullable=False, index=True) source_id: Mapped[str] = mapped_column(String(500), nullable=False) source_fingerprint: Mapped[str] = mapped_column(String(64), nullable=False) mapping_report: Mapped[dict[str, Any]] = mapped_column(JSON, nullable=False) status: Mapped[str] = mapped_column(String(30), nullable=False, index=True) accepted_approximations: Mapped[list[str]] = mapped_column( JSON, default=list, nullable=False ) assessed_by: Mapped[str | None] = mapped_column(String(255), nullable=True) __all__ = [ "ReportingDefinitionGrant", "ReportingDefinitionIdentity", "ReportingDefinitionRevision", "ReportingDrillContext", "ReportingExecution", "ReportingImportAssessment", "ReportingPublication", "ReportingProviderExecution", "ReportingProviderExport", "ReportingQualityResult", "ReportingSavedView", "ReportingSchedule", ]