import enum from typing import TYPE_CHECKING, Optional from sqlalchemy import Table, Column, ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship from models import AttributeValue, Attribute from models.base import BaseModel if TYPE_CHECKING: from models import Project project_module = Table( "project_module", BaseModel.metadata, Column("project_id", ForeignKey("projects.id"), primary_key=True), Column("module_id", ForeignKey("modules.id"), primary_key=True), ) module_dependencies = Table( "module_dependencies", BaseModel.metadata, Column("module_id", ForeignKey("modules.id"), primary_key=True), Column("depends_on_id", ForeignKey("modules.id"), primary_key=True), ) class Module(BaseModel): __tablename__ = "modules" id: Mapped[int] = mapped_column(primary_key=True) key: Mapped[str] = mapped_column(unique=True) label: Mapped[str] = mapped_column() description: Mapped[Optional[str]] = mapped_column() is_deleted: Mapped[bool] = mapped_column(default=False) is_built_in: Mapped[bool] = mapped_column(default=False, server_default="0") depends_on: Mapped[list["Module"]] = relationship( secondary=module_dependencies, primaryjoin="Module.id == module_dependencies.c.module_id", secondaryjoin="Module.id == module_dependencies.c.depends_on_id", back_populates="depended_on_by", lazy="immediate", ) depended_on_by: Mapped[list["Module"]] = relationship( secondary="module_dependencies", primaryjoin="Module.id == module_dependencies.c.depends_on_id", secondaryjoin="Module.id == module_dependencies.c.module_id", back_populates="depends_on", lazy="noload", ) projects: Mapped[list["Project"]] = relationship( uselist=True, secondary="project_module", back_populates="modules", lazy="noload", ) tabs: Mapped[list["ModuleTab"]] = relationship( lazy="immediate", backref="module", cascade="all, delete-orphan" ) attributes: Mapped[list["Attribute"]] = relationship( secondary="module_attribute", back_populates="modules", lazy="noload" ) attribute_values: Mapped[list["AttributeValue"]] = relationship( lazy="noload", back_populates="module" ) class DeviceType(enum.StrEnum): MOBILE = "mobile" DESKTOP = "desktop" BOTH = "both" class ModuleTab(BaseModel): __tablename__ = "module_tab" id: Mapped[int] = mapped_column(primary_key=True) key: Mapped[str] = mapped_column(unique=True) label: Mapped[str] = mapped_column() icon_name: Mapped[Optional[str]] = mapped_column() module_id: Mapped[int] = mapped_column(ForeignKey("modules.id")) device: Mapped[DeviceType] = mapped_column(default=DeviceType.BOTH)