from typing import TYPE_CHECKING, Optional from sqlalchemy import ForeignKey, Table, Column from sqlalchemy.dialects.postgresql import JSONB from sqlalchemy.orm import Mapped, mapped_column, relationship from models.base import BaseModel from models.mixins import IdMixin, SoftDeleteMixin if TYPE_CHECKING: from models import Module, Deal, AttributeSelect module_attribute = Table( "module_attribute", BaseModel.metadata, Column("module_id", ForeignKey("modules.id"), primary_key=True), Column("attribute_id", ForeignKey("attributes.id"), primary_key=True), ) class AttributeType(BaseModel, IdMixin, SoftDeleteMixin): __tablename__ = "attribute_types" type: Mapped[str] = mapped_column(unique=True) name: Mapped[str] = mapped_column(unique=True) attributes: Mapped["Attribute"] = relationship( back_populates="type", lazy="noload", ) class Attribute(BaseModel, IdMixin, SoftDeleteMixin): __tablename__ = "attributes" label: Mapped[str] = mapped_column() is_applicable_to_group: Mapped[bool] = mapped_column( default=False, comment="Применять ли изменения атрибута карточки ко всем карточкам в группе", ) is_nullable: Mapped[bool] = mapped_column(default=False) default_value: Mapped[Optional[dict[str, any]]] = mapped_column(JSONB) description: Mapped[str] = mapped_column(default="") is_built_in: Mapped[bool] = mapped_column(default=False) type_id: Mapped[int] = mapped_column(ForeignKey("attribute_types.id")) type: Mapped[AttributeType] = relationship( back_populates="attributes", lazy="joined", ) select_id: Mapped[Optional[int]] = mapped_column(ForeignKey("attribute_selects.id")) select: Mapped[Optional["AttributeSelect"]] = relationship( back_populates="attributes", lazy="joined", ) modules: Mapped[list["Module"]] = relationship( secondary=module_attribute, back_populates="attributes", lazy="noload", ) values: Mapped[list["AttributeValue"]] = relationship( uselist=True, back_populates="attribute", lazy="noload", ) class AttributeValue(BaseModel): __tablename__ = "attribute_values" id: Mapped[int] = mapped_column( primary_key=True, autoincrement=True, ) value: Mapped[Optional[dict[str, any]]] = mapped_column(JSONB) deal_id: Mapped[int] = mapped_column( ForeignKey("deals.id"), primary_key=True, ) deal: Mapped["Deal"] = relationship( back_populates="attributes_values", lazy="noload", ) module_id: Mapped[int] = mapped_column( ForeignKey("modules.id"), primary_key=True, ) module: Mapped["Module"] = relationship( back_populates="attribute_values", lazy="noload", ) attribute_id: Mapped[int] = mapped_column( ForeignKey("attributes.id"), primary_key=True, ) attribute: Mapped[Attribute] = relationship( back_populates="values", lazy="noload", ) class AttributeLabel(BaseModel): __tablename__ = "attribute_labels" label: Mapped[str] = mapped_column() module_id: Mapped[int] = mapped_column( ForeignKey("modules.id"), primary_key=True, ) module: Mapped["Module"] = relationship( backref="attribute_labels", lazy="noload", ) attribute_id: Mapped[int] = mapped_column( ForeignKey("attributes.id"), primary_key=True, ) attribute: Mapped[Attribute] = relationship( backref="attribute_labels", lazy="noload", )