IT-Stock/app/routers/categories.py
maxsoch 7ce6540924 Refonte des listings et arborescence de catégories à profondeur illimitée
Catégorie/SousCategorie fusionnées en un seul modèle auto-référencé
(parent_id), pour permettre une imbrication sans limite de niveaux. Les
listings matériels/catégories/destinataires passent en lignes repliées
(<details>) avec recherche côté serveur, ce qui corrige le débordement
horizontal du tableau tout-en-input et reste utilisable sur de longues
listes. Style de l'écran de scan également retravaillé (frontend-design).
2026-07-14 19:06:37 +02:00

66 lines
2.6 KiB
Python

"""
Routes pour la gestion de l'arborescence de catégories : profondeur
illimitée, une catégorie peut avoir des sous-catégories qui peuvent
elles-mêmes en avoir, etc. (Categorie.parent_id auto-référencé).
"""
from fastapi import APIRouter, Depends, Form
from fastapi.requests import Request
from fastapi.responses import RedirectResponse
from sqlmodel import Session, select
from app.categories_arbre import categories_racines
from app.database import get_session
from app.models import Categorie
from app.templates_engine import templates
router = APIRouter()
@router.get("/categories")
def lister_categories(request: Request, q: str = "", session: Session = Depends(get_session)):
"""Sans recherche : affiche l'arborescence complète, repliable.
Avec ?q=..., bascule sur une liste plate des catégories dont le nom
correspond, chacune affichée avec son chemin complet (ex: "Réseau /
Câbles") — plus rapide pour retrouver une catégorie précise que de
déplier un arbre profond ou une longue liste de racines.
"""
if q:
toutes = session.exec(select(Categorie)).all()
q_normalise = q.lower()
resultats = [c for c in toutes if q_normalise in c.nom.lower()]
return templates.TemplateResponse(
request, "categories.html", {"q": q, "resultats": resultats, "racines": []}
)
racines = categories_racines(session)
return templates.TemplateResponse(
request, "categories.html", {"q": "", "resultats": [], "racines": racines}
)
@router.post("/categories")
def creer_categorie(
nom: str = Form(...), parent_id: str = Form(""), session: Session = Depends(get_session)
):
"""Crée une catégorie : racine si parent_id est vide, sous-catégorie
(à n'importe quelle profondeur) sinon. Un seul endpoint pour les deux
cas, le formulaire d'ajout de chaque nœud de l'arbre poste juste son
propre id comme parent_id."""
session.add(Categorie(nom=nom, parent_id=int(parent_id) if parent_id else None))
session.commit()
return RedirectResponse(url="/categories", status_code=303)
@router.post("/categories/{categorie_id}/supprimer")
def supprimer_categorie(categorie_id: int, session: Session = Depends(get_session)):
"""Supprime une catégorie. Refuse silencieusement si elle a encore des
sous-catégories ou des matériels rattachés, pour éviter de perdre des
données par erreur en un clic."""
categorie = session.get(Categorie, categorie_id)
if categorie and not categorie.enfants and not categorie.materiels:
session.delete(categorie)
session.commit()
return RedirectResponse(url="/categories", status_code=303)