generated from gilles/template-webapp
claude code
This commit is contained in:
97
backend/app/models/location.py
Normal file
97
backend/app/models/location.py
Normal file
@@ -0,0 +1,97 @@
|
||||
"""Modèle SQLAlchemy pour les emplacements de stockage.
|
||||
|
||||
Les emplacements sont organisés de manière hiérarchique :
|
||||
pièce → meuble → tiroir → boîte
|
||||
Exemple : Garage → Étagère A → Tiroir 2 → Boîte visserie
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from sqlalchemy import DateTime, Enum, ForeignKey, Integer, String
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
from app.core.database import Base
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from app.models.item import Item
|
||||
|
||||
import enum
|
||||
|
||||
|
||||
class LocationType(str, enum.Enum):
|
||||
"""Type d'emplacement dans la hiérarchie."""
|
||||
|
||||
ROOM = "room" # Pièce (ex: Garage, Cuisine)
|
||||
FURNITURE = "furniture" # Meuble (ex: Étagère, Armoire)
|
||||
DRAWER = "drawer" # Tiroir
|
||||
BOX = "box" # Boîte/Bac de rangement
|
||||
|
||||
|
||||
class Location(Base):
|
||||
"""Emplacement de stockage hiérarchique.
|
||||
|
||||
Attributes:
|
||||
id: Identifiant unique auto-incrémenté
|
||||
name: Nom de l'emplacement (ex: "Garage", "Étagère A")
|
||||
type: Type d'emplacement (room/furniture/drawer/box)
|
||||
parent_id: ID du parent (None si racine)
|
||||
path: Chemin complet calculé (ex: "Garage > Étagère A > Tiroir 2")
|
||||
description: Description optionnelle
|
||||
created_at: Date/heure de création (auto)
|
||||
updated_at: Date/heure de dernière modification (auto)
|
||||
parent: Relation vers le parent
|
||||
children: Relation vers les enfants
|
||||
items: Relation vers les objets à cet emplacement
|
||||
"""
|
||||
|
||||
__tablename__ = "locations"
|
||||
|
||||
# Colonnes
|
||||
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
||||
name: Mapped[str] = mapped_column(String(100), nullable=False, index=True)
|
||||
type: Mapped[LocationType] = mapped_column(
|
||||
Enum(LocationType, native_enum=False, length=20), nullable=False
|
||||
)
|
||||
parent_id: Mapped[int | None] = mapped_column(
|
||||
Integer, ForeignKey("locations.id", ondelete="CASCADE"), nullable=True, index=True
|
||||
)
|
||||
path: Mapped[str] = mapped_column(String(500), nullable=False, index=True)
|
||||
description: Mapped[str | None] = mapped_column(String(500), nullable=True)
|
||||
|
||||
# Timestamps
|
||||
created_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), server_default=func.now(), nullable=False
|
||||
)
|
||||
updated_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True),
|
||||
server_default=func.now(),
|
||||
onupdate=func.now(),
|
||||
nullable=False,
|
||||
)
|
||||
|
||||
# Relations
|
||||
parent: Mapped["Location | None"] = relationship(
|
||||
"Location", remote_side=[id], back_populates="children"
|
||||
)
|
||||
children: Mapped[list["Location"]] = relationship(
|
||||
"Location", back_populates="parent", cascade="all, delete-orphan"
|
||||
)
|
||||
items: Mapped[list["Item"]] = relationship(
|
||||
"Item", back_populates="location", cascade="all, delete-orphan"
|
||||
)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""Représentation string de l'emplacement."""
|
||||
return f"<Location(id={self.id}, name='{self.name}', type={self.type.value})>"
|
||||
|
||||
def calculate_path(self) -> str:
|
||||
"""Calcule le chemin complet de l'emplacement.
|
||||
|
||||
Returns:
|
||||
Chemin complet (ex: "Garage > Étagère A > Tiroir 2")
|
||||
"""
|
||||
if self.parent is None:
|
||||
return self.name
|
||||
return f"{self.parent.calculate_path()} > {self.name}"
|
||||
Reference in New Issue
Block a user