from __future__ import annotations import uuid from datetime import datetime from typing import Any 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 OrganizationUnit(Base, TimestampMixin): __tablename__ = "organizations_units" __table_args__ = (UniqueConstraint("tenant_id", "slug", name="uq_organizations_units_tenant_slug"),) 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) unit_type_id: Mapped[str | None] = mapped_column(ForeignKey("organizations_unit_types.id", ondelete="SET NULL"), nullable=True, index=True) parent_id: Mapped[str | None] = mapped_column(ForeignKey("organizations_units.id", ondelete="SET NULL"), nullable=True, index=True) slug: Mapped[str] = mapped_column(String(100), nullable=False) name: Mapped[str] = mapped_column(String(255), nullable=False) description: Mapped[str | None] = mapped_column(Text) is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False) settings: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False) class OrganizationUnitType(Base, TimestampMixin): __tablename__ = "organizations_unit_types" __table_args__ = (UniqueConstraint("tenant_id", "slug", name="uq_organizations_unit_types_tenant_slug"),) 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) slug: Mapped[str] = mapped_column(String(100), nullable=False) name: Mapped[str] = mapped_column(String(255), nullable=False) description: Mapped[str | None] = mapped_column(Text) is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False) settings: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False) class OrganizationTenantSettings(Base, TimestampMixin): __tablename__ = "organizations_tenant_settings" __table_args__ = (UniqueConstraint("tenant_id", name="uq_organizations_tenant_settings_tenant"),) 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) allow_tenant_model_customization: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False) require_model_change_requests: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False) audit_detail_level: Mapped[str] = mapped_column(String(30), default="standard", nullable=False) change_retention_days: Mapped[int | None] = mapped_column(Integer, nullable=True) settings: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False) class OrganizationStructure(Base, TimestampMixin): __tablename__ = "organizations_structures" __table_args__ = (UniqueConstraint("tenant_id", "slug", name="uq_organizations_structures_tenant_slug"),) 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) slug: Mapped[str] = mapped_column(String(100), nullable=False) name: Mapped[str] = mapped_column(String(255), nullable=False) description: Mapped[str | None] = mapped_column(Text) structure_kind: Mapped[str] = mapped_column(String(30), default="hierarchy", nullable=False) is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False) settings: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False) class OrganizationRelationType(Base, TimestampMixin): __tablename__ = "organizations_relation_types" __table_args__ = ( UniqueConstraint("tenant_id", "slug", name="uq_organizations_relation_types_tenant_slug"), Index("ix_organizations_relation_types_structure", "tenant_id", "structure_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) structure_id: Mapped[str | None] = mapped_column(ForeignKey("organizations_structures.id", ondelete="SET NULL"), nullable=True, index=True) slug: Mapped[str] = mapped_column(String(100), nullable=False) name: Mapped[str] = mapped_column(String(255), nullable=False) description: Mapped[str | None] = mapped_column(Text) source_unit_type_id: Mapped[str | None] = mapped_column(ForeignKey("organizations_unit_types.id", ondelete="SET NULL"), nullable=True, index=True) target_unit_type_id: Mapped[str | None] = mapped_column(ForeignKey("organizations_unit_types.id", ondelete="SET NULL"), nullable=True, index=True) is_hierarchical: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False) allow_cycles: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False) is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False) settings: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False) class OrganizationRelation(Base, TimestampMixin): __tablename__ = "organizations_relations" __table_args__ = ( UniqueConstraint( "tenant_id", "structure_id", "relation_type_id", "source_unit_id", "target_unit_id", name="uq_organizations_relations_edge", ), Index("ix_organizations_relations_structure_source", "tenant_id", "structure_id", "source_unit_id"), Index("ix_organizations_relations_structure_target", "tenant_id", "structure_id", "target_unit_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) structure_id: Mapped[str] = mapped_column(ForeignKey("organizations_structures.id", ondelete="CASCADE"), nullable=False, index=True) relation_type_id: Mapped[str] = mapped_column(ForeignKey("organizations_relation_types.id", ondelete="CASCADE"), nullable=False, index=True) source_unit_id: Mapped[str] = mapped_column(ForeignKey("organizations_units.id", ondelete="CASCADE"), nullable=False, index=True) target_unit_id: Mapped[str] = mapped_column(ForeignKey("organizations_units.id", ondelete="CASCADE"), nullable=False, index=True) valid_from: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) valid_until: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False) settings: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False) class OrganizationFunctionType(Base, TimestampMixin): __tablename__ = "organizations_function_types" __table_args__ = (UniqueConstraint("tenant_id", "slug", name="uq_organizations_function_types_tenant_slug"),) 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) slug: Mapped[str] = mapped_column(String(100), nullable=False) name: Mapped[str] = mapped_column(String(255), nullable=False) description: Mapped[str | None] = mapped_column(Text) organization_unit_type_id: Mapped[str | None] = mapped_column(ForeignKey("organizations_unit_types.id", ondelete="SET NULL"), nullable=True, index=True) delegable: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False) act_in_place_allowed: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False) is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False) settings: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False) class OrganizationFunction(Base, TimestampMixin): __tablename__ = "organizations_functions" __table_args__ = (UniqueConstraint("tenant_id", "organization_unit_id", "slug", name="uq_organizations_functions_tenant_unit_slug"),) 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) function_type_id: Mapped[str | None] = mapped_column(ForeignKey("organizations_function_types.id", ondelete="SET NULL"), nullable=True, index=True) organization_unit_id: Mapped[str] = mapped_column(ForeignKey("organizations_units.id", ondelete="CASCADE"), nullable=False, index=True) slug: Mapped[str] = mapped_column(String(100), nullable=False) name: Mapped[str] = mapped_column(String(255), nullable=False) description: Mapped[str | None] = mapped_column(Text) delegable: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False) act_in_place_allowed: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False) is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False) settings: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False) class OrganizationFunctionAssignment(Base, TimestampMixin): __tablename__ = "organizations_function_assignments" __table_args__ = ( UniqueConstraint( "tenant_id", "identity_id", "function_id", "organization_unit_id", name="uq_organizations_function_assignments_identity_scope", ), ) 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(String(36), nullable=False, index=True) account_id: Mapped[str | None] = mapped_column(String(36), nullable=True, index=True) function_id: Mapped[str] = mapped_column(ForeignKey("organizations_functions.id", ondelete="CASCADE"), nullable=False, index=True) organization_unit_id: Mapped[str] = mapped_column(ForeignKey("organizations_units.id", ondelete="CASCADE"), nullable=False, index=True) applies_to_subunits: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False) source: Mapped[str] = mapped_column(String(50), default="direct", nullable=False) delegated_from_assignment_id: Mapped[str | None] = mapped_column(ForeignKey("organizations_function_assignments.id", ondelete="SET NULL"), nullable=True, index=True) acting_for_account_id: Mapped[str | None] = mapped_column(String(36), nullable=True, index=True) valid_from: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) valid_until: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False) settings: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False) __all__ = [ "OrganizationFunction", "OrganizationFunctionAssignment", "OrganizationFunctionType", "OrganizationRelation", "OrganizationRelationType", "OrganizationStructure", "OrganizationTenantSettings", "OrganizationUnit", "OrganizationUnitType", "new_uuid", ]