from __future__ import annotations from datetime import datetime from typing import Optional from sqlalchemy import ( Boolean, DateTime, Float, ForeignKey, Integer, String, Text, UniqueConstraint, func, ) from sqlalchemy.orm import Mapped, mapped_column, relationship from app.core.database import Base class Project(Base): __tablename__ = "projects" id: Mapped[int] = mapped_column(Integer, primary_key=True) name: Mapped[str] = mapped_column(String(255), nullable=False) status: Mapped[str] = mapped_column(String(64), default="created") current_variant: Mapped[str] = mapped_column(String(255), default="No Variations") zip_path: Mapped[Optional[str]] = mapped_column(String(1024), nullable=True) extract_path: Mapped[Optional[str]] = mapped_column(String(1024), nullable=True) pcb_doc_name: Mapped[Optional[str]] = mapped_column(String(512), nullable=True) decimal_number: Mapped[str] = mapped_column(String(255), default="") board_name: Mapped[str] = mapped_column(String(255), default="") error_message: Mapped[Optional[str]] = mapped_column(Text, nullable=True) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), onupdate=func.now() ) variants: Mapped[list[Variant]] = relationship(back_populates="project", cascade="all, delete-orphan") components: Mapped[list[Component]] = relationship(back_populates="project", cascade="all, delete-orphan") project_params: Mapped[list[ProjectParam]] = relationship( back_populates="project", cascade="all, delete-orphan" ) pcb_data: Mapped[Optional[PcbData]] = relationship( back_populates="project", uselist=False, cascade="all, delete-orphan" ) settings: Mapped[list[ProjectSetting]] = relationship( back_populates="project", cascade="all, delete-orphan" ) inscriptions: Mapped[list[TitleInscription]] = relationship( back_populates="project", cascade="all, delete-orphan" ) designator_mappings: Mapped[list[DesignatorMapping]] = relationship( back_populates="project", cascade="all, delete-orphan" ) llm_messages: Mapped[list[LlmMessage]] = relationship( back_populates="project", cascade="all, delete-orphan" ) class Variant(Base): __tablename__ = "variants" __table_args__ = (UniqueConstraint("project_id", "name", name="uq_variant_project_name"),) id: Mapped[int] = mapped_column(Integer, primary_key=True) project_id: Mapped[int] = mapped_column(ForeignKey("projects.id", ondelete="CASCADE"), index=True) name: Mapped[str] = mapped_column(String(255), nullable=False) project: Mapped[Project] = relationship(back_populates="variants") class Component(Base): __tablename__ = "components" __table_args__ = (UniqueConstraint("project_id", "designator", name="uq_component_designator"),) id: Mapped[int] = mapped_column(Integer, primary_key=True) project_id: Mapped[int] = mapped_column(ForeignKey("projects.id", ondelete="CASCADE"), index=True) designator: Mapped[str] = mapped_column(String(128), nullable=False) project: Mapped[Project] = relationship(back_populates="components") properties: Mapped[list[ComponentProperty]] = relationship( back_populates="component", cascade="all, delete-orphan" ) variant_links: Mapped[list[ComponentVariant]] = relationship( back_populates="component", cascade="all, delete-orphan" ) variant_properties: Mapped[list[VariantProperty]] = relationship( back_populates="component", cascade="all, delete-orphan" ) class ComponentProperty(Base): __tablename__ = "component_properties" id: Mapped[int] = mapped_column(Integer, primary_key=True) component_id: Mapped[int] = mapped_column(ForeignKey("components.id", ondelete="CASCADE"), index=True) key: Mapped[str] = mapped_column(String(255), nullable=False) value: Mapped[str] = mapped_column(Text, default="") component: Mapped[Component] = relationship(back_populates="properties") class ComponentVariant(Base): __tablename__ = "component_variants" __table_args__ = ( UniqueConstraint("component_id", "variant_id", name="uq_component_variant"), ) id: Mapped[int] = mapped_column(Integer, primary_key=True) component_id: Mapped[int] = mapped_column(ForeignKey("components.id", ondelete="CASCADE"), index=True) variant_id: Mapped[int] = mapped_column(ForeignKey("variants.id", ondelete="CASCADE"), index=True) is_fitted: Mapped[bool] = mapped_column(Boolean, default=True) component: Mapped[Component] = relationship(back_populates="variant_links") variant: Mapped[Variant] = relationship() class VariantProperty(Base): __tablename__ = "variant_properties" id: Mapped[int] = mapped_column(Integer, primary_key=True) component_id: Mapped[int] = mapped_column(ForeignKey("components.id", ondelete="CASCADE"), index=True) variant_id: Mapped[int] = mapped_column(ForeignKey("variants.id", ondelete="CASCADE"), index=True) key: Mapped[str] = mapped_column(String(255), nullable=False) value: Mapped[str] = mapped_column(Text, default="") component: Mapped[Component] = relationship(back_populates="variant_properties") variant: Mapped[Variant] = relationship() class ProjectParam(Base): __tablename__ = "project_params" id: Mapped[int] = mapped_column(Integer, primary_key=True) project_id: Mapped[int] = mapped_column(ForeignKey("projects.id", ondelete="CASCADE"), index=True) name: Mapped[str] = mapped_column(String(255), nullable=False) value: Mapped[str] = mapped_column(Text, default="") variant_name: Mapped[str] = mapped_column(String(255), default="") project: Mapped[Project] = relationship(back_populates="project_params") class ProjectSetting(Base): __tablename__ = "project_settings" __table_args__ = (UniqueConstraint("project_id", "key", name="uq_project_setting"),) id: Mapped[int] = mapped_column(Integer, primary_key=True) project_id: Mapped[int] = mapped_column(ForeignKey("projects.id", ondelete="CASCADE"), index=True) key: Mapped[str] = mapped_column(String(255), nullable=False) value: Mapped[str] = mapped_column(Text, default="") project: Mapped[Project] = relationship(back_populates="settings") class DesignatorMapping(Base): __tablename__ = "designator_mappings" __table_args__ = (UniqueConstraint("project_id", "prefix", name="uq_designator_prefix"),) id: Mapped[int] = mapped_column(Integer, primary_key=True) project_id: Mapped[int] = mapped_column(ForeignKey("projects.id", ondelete="CASCADE"), index=True) prefix: Mapped[str] = mapped_column(String(16), nullable=False) singular_name: Mapped[str] = mapped_column(String(255), default="") plural_name: Mapped[str] = mapped_column(String(255), default="") project: Mapped[Project] = relationship(back_populates="designator_mappings") class TitleInscription(Base): __tablename__ = "title_inscriptions" __table_args__ = (UniqueConstraint("project_id", "field_number", name="uq_inscription_field"),) id: Mapped[int] = mapped_column(Integer, primary_key=True) project_id: Mapped[int] = mapped_column(ForeignKey("projects.id", ondelete="CASCADE"), index=True) field_number: Mapped[int] = mapped_column(Integer, nullable=False) field_value: Mapped[str] = mapped_column(Text, default="") project: Mapped[Project] = relationship(back_populates="inscriptions") class PcbData(Base): __tablename__ = "pcb_data" id: Mapped[int] = mapped_column(Integer, primary_key=True) project_id: Mapped[int] = mapped_column( ForeignKey("projects.id", ondelete="CASCADE"), unique=True, index=True ) layer_count: Mapped[int] = mapped_column(Integer, default=0) project: Mapped[Project] = relationship(back_populates="pcb_data") diel_materials: Mapped[list[DielMaterial]] = relationship( back_populates="pcb_data", cascade="all, delete-orphan" ) class DielMaterial(Base): __tablename__ = "diel_materials" id: Mapped[int] = mapped_column(Integer, primary_key=True) pcb_data_id: Mapped[int] = mapped_column(ForeignKey("pcb_data.id", ondelete="CASCADE"), index=True) name: Mapped[str] = mapped_column(String(255), default="DielMaterial") value: Mapped[str] = mapped_column(String(255), default="") height: Mapped[float] = mapped_column(Float, default=0.0) diel_type: Mapped[int] = mapped_column(Integer, default=1) layer_number: Mapped[int] = mapped_column(Integer, default=0) pcb_data: Mapped[PcbData] = relationship(back_populates="diel_materials") class PerechenRow(Base): __tablename__ = "perechen_rows" id: Mapped[int] = mapped_column(Integer, primary_key=True) project_id: Mapped[int] = mapped_column(ForeignKey("projects.id", ondelete="CASCADE"), index=True) row_index: Mapped[int] = mapped_column(Integer, default=0) page_number: Mapped[int] = mapped_column(Integer, default=1) position: Mapped[str] = mapped_column(Text, default="") designation: Mapped[str] = mapped_column(Text, default="") quantity: Mapped[str] = mapped_column(String(64), default="") note: Mapped[str] = mapped_column(Text, default="") is_header: Mapped[bool] = mapped_column(Boolean, default=False) is_empty: Mapped[bool] = mapped_column(Boolean, default=False) is_auto_generated: Mapped[bool] = mapped_column(Boolean, default=True) stretch: Mapped[bool] = mapped_column(Boolean, default=False) is_underline: Mapped[bool] = mapped_column(Boolean, default=False) class SpecificationPcbRow(Base): __tablename__ = "specification_pcb_rows" id: Mapped[int] = mapped_column(Integer, primary_key=True) project_id: Mapped[int] = mapped_column(ForeignKey("projects.id", ondelete="CASCADE"), index=True) row_index: Mapped[int] = mapped_column(Integer, default=0) page_number: Mapped[int] = mapped_column(Integer, default=1) format: Mapped[str] = mapped_column(String(64), default="") zone: Mapped[str] = mapped_column(String(64), default="") position: Mapped[str] = mapped_column(String(64), default="") designation: Mapped[str] = mapped_column(Text, default="") name: Mapped[str] = mapped_column(Text, default="") quantity: Mapped[str] = mapped_column(String(64), default="") note: Mapped[str] = mapped_column(Text, default="") is_header: Mapped[bool] = mapped_column(Boolean, default=False) is_empty: Mapped[bool] = mapped_column(Boolean, default=False) is_auto_generated: Mapped[bool] = mapped_column(Boolean, default=True) stretch: Mapped[bool] = mapped_column(Boolean, default=False) is_underline: Mapped[bool] = mapped_column(Boolean, default=False) class SpecificationRow(Base): __tablename__ = "specification_rows" id: Mapped[int] = mapped_column(Integer, primary_key=True) project_id: Mapped[int] = mapped_column(ForeignKey("projects.id", ondelete="CASCADE"), index=True) row_index: Mapped[int] = mapped_column(Integer, default=0) page_number: Mapped[int] = mapped_column(Integer, default=1) format: Mapped[str] = mapped_column(String(64), default="") zone: Mapped[str] = mapped_column(String(64), default="") position: Mapped[str] = mapped_column(String(64), default="") designation: Mapped[str] = mapped_column(Text, default="") name: Mapped[str] = mapped_column(Text, default="") quantity: Mapped[str] = mapped_column(String(64), default="") note: Mapped[str] = mapped_column(Text, default="") is_header: Mapped[bool] = mapped_column(Boolean, default=False) is_empty: Mapped[bool] = mapped_column(Boolean, default=False) is_auto_generated: Mapped[bool] = mapped_column(Boolean, default=True) stretch: Mapped[bool] = mapped_column(Boolean, default=False) is_underline: Mapped[bool] = mapped_column(Boolean, default=False) class VedomostRow(Base): __tablename__ = "vedomost_rows" id: Mapped[int] = mapped_column(Integer, primary_key=True) project_id: Mapped[int] = mapped_column(ForeignKey("projects.id", ondelete="CASCADE"), index=True) row_index: Mapped[int] = mapped_column(Integer, default=0) page_number: Mapped[int] = mapped_column(Integer, default=1) name: Mapped[str] = mapped_column(Text, default="") product_code: Mapped[str] = mapped_column(Text, default="") document_code: Mapped[str] = mapped_column(Text, default="") supplier: Mapped[str] = mapped_column(Text, default="") where_used: Mapped[str] = mapped_column(Text, default="") quantity_per_item: Mapped[str] = mapped_column(String(64), default="") quantity_in_set: Mapped[str] = mapped_column(String(64), default="") quantity_for_reg: Mapped[str] = mapped_column(String(64), default="") total_quantity: Mapped[str] = mapped_column(String(64), default="") note: Mapped[str] = mapped_column(Text, default="") is_header: Mapped[bool] = mapped_column(Boolean, default=False) is_empty: Mapped[bool] = mapped_column(Boolean, default=False) is_auto_generated: Mapped[bool] = mapped_column(Boolean, default=True) stretch: Mapped[bool] = mapped_column(Boolean, default=False) is_underline: Mapped[bool] = mapped_column(Boolean, default=False) class SimpleListRow(Base): __tablename__ = "simple_list_rows" id: Mapped[int] = mapped_column(Integer, primary_key=True) project_id: Mapped[int] = mapped_column(ForeignKey("projects.id", ondelete="CASCADE"), index=True) row_index: Mapped[int] = mapped_column(Integer, default=0) designator: Mapped[str] = mapped_column(Text, default="") name: Mapped[str] = mapped_column(Text, default="") quantity: Mapped[str] = mapped_column(String(64), default="") is_auto_generated: Mapped[bool] = mapped_column(Boolean, default=True) is_empty: Mapped[bool] = mapped_column(Boolean, default=False) class LlmMessage(Base): __tablename__ = "llm_messages" id: Mapped[int] = mapped_column(Integer, primary_key=True) project_id: Mapped[int] = mapped_column(ForeignKey("projects.id", ondelete="CASCADE"), index=True) role: Mapped[str] = mapped_column(String(32), nullable=False) content: Mapped[str] = mapped_column(Text, default="") table_type: Mapped[Optional[str]] = mapped_column(String(64), nullable=True) proposed_edits: Mapped[Optional[str]] = mapped_column(Text, nullable=True) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) project: Mapped[Project] = relationship(back_populates="llm_messages")