9.4 KiB
Guide — 3D Pricing App
Application web Flask/SQLite de gestion du pricing et de la planification pour un atelier d'impression 3D.
Architecture technique
Flask (Python) ──► SQLite (WAL mode)
│
├── Templates Jinja2 (Bootstrap 5 + vis.js)
├── Thread arrière-plan : sync Home Assistant
└── Docker : /data/pricing.db (persistant)
Stack :
- Python 3.12 + Flask
- SQLite avec WAL (pas de blocage lecture/écriture simultanée)
- Bootstrap 5 + Bootstrap Icons
- vis.js Timeline (Gantt planning)
- Authelia OIDC (optionnel, activé via variables d'env)
- Home Assistant REST API (optionnel)
- Nextcloud WebDAV (optionnel)
Schéma de base de données
| Table | Rôle |
|---|---|
settings |
Clés/valeurs de configuration globale |
clients |
Clients avec profils par défaut |
projects |
Projets regroupant plusieurs commandes |
jobs |
Commandes / calculs de prix (1 plateau = 1 job) |
materials |
Filaments avec stock et historique de prix |
material_price_history |
Historique des changements de prix filament |
machine_profiles |
Profils machine (usure, électricité) |
handling_profiles |
Profils manutention (taux horaire, minutes/plateau) |
material_profiles |
Profils marge matière |
pricing_profiles |
Profils multiplicateur design + marge brute |
printers |
Imprimantes physiques avec préfixe HA |
print_slots |
Créneaux d'impression planifiés |
working_schedule |
Planning hebdomadaire (TT / sur site / off) |
calendar_blocks |
Indisponibilités ponctuelles (plage de dates) |
Moteur de calcul (calc())
Tout se calcule par pièce à partir des données du plateau Bambu.
Coût fixe = matière + marge_matière + usure_machine + électricité
(divisé par pièces/plateau)
Sous-total = coût_fixe + manutention + design
Marge brute = sous-total × gross_margin_pct / 100
Total marge = manutention + design + marge_brute
Prix HT = coût_fixe + total_marge
Prix HT net = prix_ht / (1 - cotisations - VFL - autres_taxes)
└─ les charges fiscales sont "self-contained" dans le prix
Prix TTC = prix_ht_net × (1 + TVA)
Prix final = prix_ttc × (1 - remise)
Multiplicateur design : coefficient appliqué au coût matière pour valoriser le temps de modélisation. ×0.8 = design simple, ×1.8 = design complexe.
Pages et fonctionnalités
Dashboard (/)
Vue d'ensemble : 10 dernières commandes, CA total, CA du mois, alertes stock bas.
Commandes (/jobs)
Liste de toutes les commandes avec réf. plateau, poids, durée, marge, remise, prix final.
- Nouveau job : saisie manuelle ou import
.gcode.3mfdepuis Nextcloud - Import Bambu : parse
slice_info.config→ détecte les plateaux, poids, durée, filaments - Duplication (
?clone_from=ID) : copie les paramètres + re-parse automatiquement le fichier Nextcloud sisource_nc_pathest renseigné - Export CSV : toutes les commandes en CSV
Détail commande (/jobs/<id>)
- Décomposition du prix (coût fixe, variable, fiscal)
- Section Plateaux d'impression : liste des slots avec statut, pièces, avancement HA
- Portail client : génération d'un lien de partage tokenisé
Projets (/projects)
Regroupe plusieurs commandes sous un même projet client. Affiche total pièces et CA.
Clients (/clients)
Clients avec profils par défaut (machine, manutention, matière, tarif). Ces profils se chargent automatiquement à la création d'un job pour ce client.
Matières (/materials)
- Stock en grammes avec alerte seuil bas
- Historique des prix
- Déduction automatique du stock à la création d'un job
- Suivi du gaspillage (impressions ratées)
Profils (/profiles)
4 types de profils réutilisables :
- Machine : prix imprimante, durée de vie, nozzle, plateau, puissance, électricité
- Manutention : taux horaire, minutes par plateau
- Matière : marge matière en %
- Tarif : multiplicateur design + marge brute
Planning (/planning)
Gantt vis.js sur 14 jours (démarre 12h avant maintenant pour voir les impressions en cours).
- Gantt : slots par imprimante, codes couleur par statut, bandes rouges si capacité saturée
- À planifier : jobs dont tous les plateaux ne sont pas encore planifiés
- Overlay HA live : rafraîchissement automatique (intervalle configurable) des statuts depuis Home Assistant
- Badges compensation : si HA signale des pièces ignorées sur un plateau, les autres plateaux du même job proposent d'augmenter leur quantité
Planifier un slot :
- Cliquer sur un job "À planifier"
- Choisir imprimante + date/heure de lancement
- Option "Déjà imprimé" pour enregistrer rétroactivement sans vérification de capacité
Statuts des slots :
| Statut | Couleur | Signification |
|---|---|---|
planned |
bleu | Planifié, pas encore lancé |
running |
orange | En cours (mis à jour par HA sync) |
done |
vert | Terminé |
failed |
rouge | Raté (gaspillage logué) |
cancelled |
gris | Annulé |
Imprimantes (/printers)
- Activer/désactiver des imprimantes
- Configurer le préfixe HA (
a1_1→ surveillesensor.a1_1_etat_de_l_impression) - Modifier nom, préfixe HA, notes
Planning horaire (/working-schedule)
Configuré par jour de la semaine :
- TT (télétravail) : fenêtre horaire avec nb de lancements calculé automatiquement
- Onsite : 2 créneaux fixes (ex: 07h00 + 18h30)
- Off : aucun lancement possible
Indisponibilités (/calendar-blocks)
Bloquer une période (date début → date fin optionnelle) pour une ou toutes les imprimantes. Types : Off / Télétravail / Sur site / Maintenance machine.
Page mobile (/mobile)
Interface simplifiée pour saisie rapide sur smartphone :
- Ajouter une indisponibilité
- Décaler un créneau
- Marquer une impression comme ratée ou terminée
Statistiques (/stats)
CA par période, matières les plus utilisées, gaspillage, top clients.
Paramètres (/settings)
- Taux fiscaux (cotisations, VFL, TVA, autres taxes)
- Paramètres machine par défaut
- Configuration Nextcloud (URL, user, mot de passe d'app, dossier racine)
- Configuration Home Assistant (URL, token, intervalle de sync)
- Nombre max d'imprimantes simultanées
- Cooldown entre impressions (minutes)
Home Assistant Sync
Le thread HA tourne en arrière-plan et poll toutes les N secondes (configurable, défaut 60s).
Entités surveillées (par imprimante avec préfixe {prefix}) :
sensor.{prefix}_etat_de_l_impression→running/finish/unknownbinary_sensor.{prefix}_erreur_d_impression→on/offsensor.{prefix}_objets_ignores→ nombre de pièces ignorées (compensation multi-plateau)sensor.{prefix}_avancement_de_l_impression→ % d'avancement
Logique de sync :
- Cherche un slot
plannedourunningqui chevauche la fenêtre actuelle (±30 min) running→ passe le slot àrunningfinish→ passe le slot àdonebinary_sensor erreur = on→ passe le slot àfailedobjets_ignores > 0→ met à jourpieces_ignoredsur le slot
Important : le sync utilise des connexions courtes par imprimante (autocommit) pour ne pas bloquer les requêtes Flask.
Nextcloud
Utilisé comme bibliothèque de fichiers .gcode.3mf.
- Navigation WebDAV via le picker modal dans "Nouveau job"
- Téléchargement + parsing du
.3mfcôté serveur (/api/nextcloud/parse) - Chemin stocké dans
source_nc_pathpour permettre la duplication sans re-sélection
Portail client
Chaque commande peut générer un lien tokenisé (/portal/<token>) donnant accès à :
- Décomposition du prix en lecture seule
- Sans authentification requise
Variables d'environnement (Docker)
| Variable | Défaut | Rôle |
|---|---|---|
SECRET_KEY |
généré aléatoirement | Clé session Flask |
DATABASE_PATH |
/data/pricing.db |
Chemin SQLite |
OIDC_CLIENT_ID |
— | Active l'auth OIDC si défini |
OIDC_CLIENT_SECRET |
— | Secret OIDC |
OIDC_DISCOVERY_URL |
— | URL metadata OIDC (Authelia) |
OIDC_END_SESSION_URL |
— | URL déconnexion OIDC |
Calendrier iCal (/calendar.ics)
Export iCal des créneaux planifiés. Protégé par token (ical_token dans settings).
URL : http://host/calendar.ics?token=<ical_token>
API JSON principales
| Endpoint | Méthode | Rôle |
|---|---|---|
/api/calculate |
POST | Calcul de prix live (formulaire new_job) |
/api/slots |
GET | Liste des slots pour le Gantt (7 derniers jours → +) |
/api/slots/new |
POST | Créer un slot planifié |
/api/slots/<id>/move |
POST | Déplacer un slot |
/api/slots/<id>/fail |
POST | Marquer comme raté |
/api/slots/<id>/done |
POST | Marquer comme terminé |
/api/slots/<id>/status |
POST | Changer le statut |
/api/slots/<id>/pieces_override |
POST | Override nb pièces (compensation) |
/api/suggest-slot |
POST | Suggérer le prochain créneau libre |
/api/capacity |
POST | Calculer la capacité de production |
/api/ha/status |
GET | Statuts HA de toutes les imprimantes |
/api/parse-3mf |
POST | Parser un fichier .3mf uploadé |
/api/nextcloud/browse |
GET | Lister un dossier Nextcloud |
/api/nextcloud/parse |
GET | Fetch + parser un .3mf Nextcloud |
/api/nextcloud/file |
GET | Proxy téléchargement fichier Nextcloud |
/api/client/<id>/defaults |
GET | Profils par défaut d'un client |