diff --git a/backend/destinations.py b/backend/destinations.py index 1a1775c..8242561 100644 --- a/backend/destinations.py +++ b/backend/destinations.py @@ -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}) diff --git a/backend/main.py b/backend/main.py index 09634e0..c7f5431 100644 --- a/backend/main.py +++ b/backend/main.py @@ -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") diff --git a/frontend/css/style.css b/frontend/css/style.css index 1cfa957..c8a517b 100644 --- a/frontend/css/style.css +++ b/frontend/css/style.css @@ -935,6 +935,42 @@ html, body { } .admin-onglets.cache { display: none; } +.conso-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 1rem; + margin-bottom: 1.5rem; +} +.conso-card { + background: rgba(255,255,255,0.04); + border-radius: 12px; + padding: 1.2rem; + text-align: center; +} +.conso-icon { font-size: 2rem; margin-bottom: 0.3rem; } +.conso-titre { font-weight: 600; margin-bottom: 0.8rem; font-size: 0.95rem; } +.conso-barre-fond { + height: 12px; + background: rgba(255,255,255,0.08); + border-radius: 6px; + overflow: hidden; + margin-bottom: 0.5rem; +} +.conso-barre { + height: 100%; + border-radius: 6px; + transition: width 0.5s ease, background 0.5s ease; +} +.conso-chiffres { font-size: 0.85rem; color: var(--texte-secondaire); margin-bottom: 0.8rem; } +.conso-gros { font-size: 2.5rem; font-weight: 800; margin: 0.5rem 0; } +.conso-diag { + background: rgba(255,255,255,0.03); + border-radius: 8px; + padding: 1rem; + font-size: 0.85rem; + line-height: 1.6; +} + .video-situation-bloc { background: rgba(255,255,255,0.03); border-radius: 8px; diff --git a/frontend/index.html b/frontend/index.html index f68f66e..376a9b6 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -7,7 +7,7 @@ - +
@@ -379,6 +379,7 @@Suivez l'usure du papier et du ruban. Reinitalisez quand vous changez une bobine.
+ +