Adding fits
This commit is contained in:
1 parent
8185f1f8b3
commit
ab39191af5
19 files changed
+1253
-1
No files matched your search
@@ -10,6 +10,7 @@ from app.models.attachment_point_name import AttachmentPointName
|
||||
from app.models.audit_log import AuditLog
|
||||
from app.models.augmented_part import AugmentedPart
|
||||
from app.models.clamp_connection import ClampConnection
|
||||
from app.models.fit import Fit, FitLabel, FitNote
|
||||
from app.models.imported_part import ImportedPart
|
||||
from app.models.imported_part_config import ImportedPartConfig
|
||||
from app.models.iso_thread import IsoThread
|
||||
@@ -31,6 +32,9 @@ __all__ = [
|
||||
"AuditLog",
|
||||
"AugmentedPart",
|
||||
"ClampConnection",
|
||||
"Fit",
|
||||
"FitLabel",
|
||||
"FitNote",
|
||||
"ImportedPart",
|
||||
"ImportedPartConfig",
|
||||
"IsoThread",
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
import enum
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import DateTime, Enum, ForeignKey, String, Text, UniqueConstraint, func
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class FitLabel(str, enum.Enum):
|
||||
POSSIBLE = "possible"
|
||||
EXACT = "exact"
|
||||
NONE = "none"
|
||||
|
||||
|
||||
class Fit(Base):
|
||||
"""A candidate or confirmed fit between two attachment points on different parts."""
|
||||
|
||||
__tablename__ = "fits"
|
||||
__table_args__ = (
|
||||
UniqueConstraint("attachment_point_a_id", "attachment_point_b_id"),
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
|
||||
# Canonical ordering (attachment_point_a_id < attachment_point_b_id) is enforced
|
||||
# by app.crud.fit so an unordered pair only ever has one row.
|
||||
attachment_point_a_id: Mapped[int] = mapped_column(
|
||||
ForeignKey("attachment_points.id", ondelete="CASCADE"), nullable=False
|
||||
)
|
||||
attachment_point_b_id: Mapped[int] = mapped_column(
|
||||
ForeignKey("attachment_points.id", ondelete="CASCADE"), nullable=False
|
||||
)
|
||||
|
||||
# Denormalized from the attachment points' augmented_part_id, for querying
|
||||
# "fits for this part" without joining through attachment_points.
|
||||
augmented_part_a_id: Mapped[int] = mapped_column(
|
||||
ForeignKey("augmented_parts.id", ondelete="CASCADE"), nullable=False
|
||||
)
|
||||
augmented_part_b_id: Mapped[int] = mapped_column(
|
||||
ForeignKey("augmented_parts.id", ondelete="CASCADE"), nullable=False
|
||||
)
|
||||
|
||||
label: Mapped[FitLabel] = mapped_column(
|
||||
Enum(FitLabel, values_callable=lambda enum_cls: [e.value for e in enum_cls]),
|
||||
nullable=False,
|
||||
default=FitLabel.POSSIBLE,
|
||||
)
|
||||
|
||||
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()
|
||||
)
|
||||
|
||||
attachment_point_a = relationship(
|
||||
"AttachmentPoint", foreign_keys=[attachment_point_a_id], lazy="selectin"
|
||||
)
|
||||
attachment_point_b = relationship(
|
||||
"AttachmentPoint", foreign_keys=[attachment_point_b_id], lazy="selectin"
|
||||
)
|
||||
notes: Mapped[list["FitNote"]] = relationship(
|
||||
back_populates="fit",
|
||||
lazy="selectin",
|
||||
order_by="FitNote.created_at",
|
||||
cascade="all, delete-orphan",
|
||||
)
|
||||
|
||||
|
||||
class FitNote(Base):
|
||||
__tablename__ = "fit_notes"
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
fit_id: Mapped[int] = mapped_column(
|
||||
ForeignKey("fits.id", ondelete="CASCADE"), nullable=False
|
||||
)
|
||||
user_id: Mapped[int | None] = mapped_column(
|
||||
ForeignKey("users.id", ondelete="SET NULL"), nullable=True
|
||||
)
|
||||
# Denormalized snapshot of who wrote the note (mirrors AuditLog.user_email),
|
||||
# so the note stays attributable even if the user is later deleted.
|
||||
username: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||
body: Mapped[str] = mapped_column(Text, nullable=False)
|
||||
created_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), server_default=func.now()
|
||||
)
|
||||
|
||||
fit: Mapped[Fit] = relationship(back_populates="notes")
|
||||
Reference in new issue
Block a user