Suivi consommables : compteur papier, ruban et photos avec diagnostic ratio

- Onglet Consommables dans General : barres de progression papier/ruban, compteur photos
- Capacites configurables (feuilles par bobine / poses par bobine)
- Reset individuel papier/ruban (quand on change la bobine)
- Diagnostic ratio ruban/papier pour verifier que le rembobinage fonctionne
- Tracking automatique a chaque impression (format-aware)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-12 15:23:17 +02:00
parent 44a9992557
commit 3b6f376ded
5 changed files with 239 additions and 5 deletions

View File

@@ -11,7 +11,7 @@ from backend.config import charger_config, mettre_a_jour_config
log = logging.getLogger("photobooth.destinations")
def distribuer_photo(chemin_photo: Path, imprimee: bool = False, copies: int = 1):
def distribuer_photo(chemin_photo: Path, imprimee: bool = False, copies: int = 1, format_papier: str | None = None):
"""Copie la photo vers toutes les destinations activees."""
config = charger_config()
dest = config.get("destinations", {})
@@ -43,6 +43,7 @@ def distribuer_photo(chemin_photo: Path, imprimee: bool = False, copies: int = 1
if compteur.get("actif", False):
compteur["photos_prises"] = compteur.get("photos_prises", 0) + copies
mettre_a_jour_config({"compteur": compteur})
maj_consommables(config, copies, format_papier)
def copier_usb(chemin_photo: Path, chemin_usb: str, sous_dossier: str | None = None):
@@ -218,3 +219,65 @@ def compteur_restant() -> dict:
def reset_compteur():
"""Remet le compteur a zero."""
mettre_a_jour_config({"compteur": {"photos_prises": 0}})
# --- Suivi consommables ---
TAILLE_RUBAN = {
"15x20": 1.0,
"10x15": 0.667,
"10x15-2up": 1.0,
"15x20-2up": 1.0,
}
def maj_consommables(config: dict, copies: int, format_papier: str | None):
"""Met a jour le suivi consommables (papier, ruban, photos)."""
conso = config.get("consommables", {})
fmt = format_papier or config.get("impression", {}).get("format", "15x20")
rembobinage = config.get("impression", {}).get("rembobinage_ruban", False)
is_2up = "-2up" in fmt
feuilles = copies if not is_2up else (copies + 1) // 2
conso["papier_utilise"] = conso.get("papier_utilise", 0) + feuilles
conso["photos_imprimees"] = conso.get("photos_imprimees", 0) + copies
if rembobinage:
ruban_par_feuille = TAILLE_RUBAN.get(fmt, 1.0)
else:
ruban_par_feuille = 1.0
conso["ruban_utilise"] = round(conso.get("ruban_utilise", 0) + feuilles * ruban_par_feuille, 1)
mettre_a_jour_config({"consommables": conso})
def consommables_etat() -> dict:
"""Retourne l'etat des consommables."""
config = charger_config()
conso = config.get("consommables", {})
papier_cap = conso.get("papier_capacite", 400)
ruban_cap = conso.get("ruban_capacite", 400)
papier_used = conso.get("papier_utilise", 0)
ruban_used = conso.get("ruban_utilise", 0)
photos = conso.get("photos_imprimees", 0)
return {
"papier_capacite": papier_cap,
"papier_utilise": papier_used,
"papier_restant": max(0, papier_cap - papier_used),
"ruban_capacite": ruban_cap,
"ruban_utilise": ruban_used,
"ruban_restant": max(0, round(ruban_cap - ruban_used, 1)),
"photos_imprimees": photos,
}
def reset_consommables(quoi: str):
"""Reinitialise papier, ruban ou tout."""
config = charger_config()
conso = config.get("consommables", {})
if quoi in ("papier", "tout"):
conso["papier_utilise"] = 0
if quoi in ("ruban", "tout"):
conso["ruban_utilise"] = 0
if quoi == "tout":
conso["photos_imprimees"] = 0
mettre_a_jour_config({"consommables": conso})

View File

@@ -27,7 +27,7 @@ except ImportError:
from backend.gallery import lister_photos, compter_photos, supprimer_photo, vider_galerie
from backend.effects import appliquer_filtre, appliquer_overlay, chroma_key, lister_overlays, lister_fonds, lister_cadres, FILTRES
from backend.collage import creer_strip, creer_collage
from backend.destinations import distribuer_photo, detecter_usb, compteur_restant, reset_compteur, recuperer_booth_password
from backend.destinations import distribuer_photo, detecter_usb, compteur_restant, reset_compteur, recuperer_booth_password, consommables_etat, reset_consommables
from backend.printer import lister_imprimantes, imprimer
from backend.mailer import envoyer_photo, charger_emails_historique, effacer_emails_historique, ajouter_au_spool, taille_spool, tache_spool_demarrage
from backend.qrcode_gen import generer_qr, qr_galerie
@@ -903,10 +903,41 @@ async def api_imprimer(donnees: dict):
format_papier = donnees.get("format_papier") or None
resultat = imprimer(chemin, copies=copies, cadre_override=cadre_override, format_papier=format_papier)
if resultat.get("succes"):
distribuer_photo(chemin, imprimee=True, copies=copies)
distribuer_photo(chemin, imprimee=True, copies=copies, format_papier=format_papier)
return resultat
# --- API Consommables ---
@app.get("/api/consommables")
async def api_consommables():
return consommables_etat()
@app.post("/api/consommables/reset")
async def api_reset_consommables(request: Request):
body = await request.json()
quoi = body.get("quoi", "tout")
reset_consommables(quoi)
return consommables_etat()
@app.post("/api/consommables/capacite")
async def api_consommables_capacite(request: Request):
body = await request.json()
updates = {}
if "papier_capacite" in body:
updates["papier_capacite"] = int(body["papier_capacite"])
if "ruban_capacite" in body:
updates["ruban_capacite"] = int(body["ruban_capacite"])
if updates:
config = charger_config()
conso = config.get("consommables", {})
conso.update(updates)
mettre_a_jour_config({"consommables": conso})
return consommables_etat()
# --- API Booth (galerie live) ---
@app.get("/api/booth/info")