App FastAPI + SQLite + SQLModel + Jinja2 pour gérer le stock de matériel IT (catégories/sous-catégories/matériels), avec recherche par scan de code-barres et alertes email de stock bas.
67 lines
2.4 KiB
Python
67 lines
2.4 KiB
Python
"""
|
|
Modèles de données du stock IT.
|
|
|
|
Principe volontairement simple, demandé par le département IT : on ne suit
|
|
PAS des exemplaires individuels (pas de numéro de série, pas d'historique
|
|
détaillé par unité). On suit juste, pour chaque *type* de matériel, une
|
|
quantité en stock. Ex: "PC Dell XPS 13 modèle 9310" -> quantite=5,
|
|
"Câble RJ45 2m" -> quantite=42.
|
|
|
|
Hiérarchie : Categorie -> SousCategorie -> Materiel.
|
|
"""
|
|
|
|
from typing import Optional
|
|
|
|
from sqlmodel import Field, Relationship, SQLModel
|
|
|
|
|
|
class Categorie(SQLModel, table=True):
|
|
"""Catégorie de haut niveau (ex: 'Ordinateurs', 'Réseau', 'Périphériques')."""
|
|
|
|
id: Optional[int] = Field(default=None, primary_key=True)
|
|
nom: str = Field(index=True, unique=True)
|
|
|
|
sous_categories: list["SousCategorie"] = Relationship(back_populates="categorie")
|
|
|
|
|
|
class SousCategorie(SQLModel, table=True):
|
|
"""Sous-catégorie rattachée à une catégorie (ex: 'Portables', 'Câbles')."""
|
|
|
|
id: Optional[int] = Field(default=None, primary_key=True)
|
|
nom: str
|
|
categorie_id: int = Field(foreign_key="categorie.id")
|
|
|
|
categorie: Optional[Categorie] = Relationship(back_populates="sous_categories")
|
|
materiels: list["Materiel"] = Relationship(back_populates="sous_categorie")
|
|
|
|
|
|
class Materiel(SQLModel, table=True):
|
|
"""Un type de matériel suivi en stock.
|
|
|
|
code_barre identifie le *type* de matériel (le "SKU"), pas un
|
|
exemplaire précis : scanner deux PC XPS 13 identiques renvoie le même
|
|
matériel, et chaque scan ajuste juste la quantité globale.
|
|
"""
|
|
|
|
id: Optional[int] = Field(default=None, primary_key=True)
|
|
nom: str
|
|
code_barre: Optional[str] = Field(default=None, index=True, unique=True)
|
|
quantite: int = Field(default=0)
|
|
# En dessous de ce seuil, une alerte email est envoyée (voir email_alerts.py).
|
|
# None = pas d'alerte configurée pour ce matériel.
|
|
seuil_alerte: Optional[int] = Field(default=None)
|
|
sous_categorie_id: int = Field(foreign_key="souscategorie.id")
|
|
|
|
sous_categorie: Optional[SousCategorie] = Relationship(back_populates="materiels")
|
|
|
|
|
|
class DestinataireAlerte(SQLModel, table=True):
|
|
"""Adresse email qui reçoit les alertes de stock bas.
|
|
|
|
Liste globale simple (pas de destinataires par matériel/catégorie) :
|
|
c'est suffisant pour une petite équipe IT et ça reste facile à gérer.
|
|
"""
|
|
|
|
id: Optional[int] = Field(default=None, primary_key=True)
|
|
email: str = Field(unique=True)
|