Contrat pipeline commercial CRM natif (lead → visite → devis → réservation → contrat → CONFOTUR) → fixtures Frappe/ERPNext v15 : Workflow (9 états / 11 transitions) + Workflow State + Workflow Action Master + MANIFEST. Rôles gardant états/transitions résolus depuis rbac_50_roles.json (réutilisation, zéro duplication · #6) : le contrat ne cite qu'un id de rôle, jamais un nom Frappe en dur. CLI build/validate refuse d'écrire si l'un des 9 invariants de graphe casse (monotonie doc_status, atteignabilité, séparation des pouvoirs sur les étapes engageant de l'argent / clôturant). 25 tests (stdlib pur + oracle jsonschema) · job CI crm-workflow-vente-tests ajouté au gate · 146 tests de régression verts au total. Application VPS (DocType porteur OTO Dossier Vente + bench migrate) = agent ERPNext Backend, hors périmètre worker. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5.6 KiB
Daily Report · 2026-07-30 · Claude Code DTP Worker (session 11)
Session : 20260730_052701
Tâche exécutée
Sprint 4 · CRM — Générateur de workflow vente ERPNext (roadmap
04_roadmap/ROADMAP_8_WEEKS_OR_LESS.md §Sprint 4 : « workflow complet lead →
visite → devis → réservation → contrat → CONFOTUR »). Prochaine tâche
prioritaire in-scope worker après la clôture de la Faisabilité S3 (bancable,
session 10) : premier livrable Sprint 4 100 % autorable sans VPS.
Contexte / analyse
- Relu
CLAUDE.md,ROADMAP_8_WEEKS_OR_LESS.md, daily report session 10, l'AGENT.md CRM, le contratrbac_50_roles.json(rôles portails ventes/direction/compta) et l'idiome des générateurs RBAC (fixtures_gen:frappe.py/builder.py/schema/CLIbuild|validate/tests + job CI + gate). - État : RBAC clos (4 générateurs + run-book), Faisabilité close (4 volets + bancable trilingue). Sprint 4 non entamé en-repo. Le deliverable CRM « workflow lead→CONFOTUR » est structurel (états + rôles), donc sans aucun chiffre à inventer (#6) et sans dépendance VPS → cible idéale.
- Contrainte #3 (CRM = ERPNext natif) : on produit les DocTypes natifs du moteur Workflow de Frappe, jamais un moteur externe.
Réalisé — module 05_deliverables_mvp/crm/workflow_vente/
workflow_vente_spec.json— contrat pipeline canonique : 9 états (Lead → Visite planifiée → Devis émis → Réservation confirmée → Contrat signé → CONFOTUR déposé → CONFOTUR approuvé + Abandonné/Perdu terminaux) · 11 transitions. Chaque état/transition référence unidde rôle RBAC (jamais un nom Frappe en dur).wflib/rbac.py— réutilisation (workflow #5, zéro duplication) derbac_50_roles.json: résoutrole_id → erpnext_role_name.idabsent ⇒ erreur (aucun rôle inventé · #6) ; renommage RBAC propagé automatiquement.wflib/erpnext.py— connaissance Frappe v15 native : DocTypesWorkflow,Workflow Document State,Workflow Transition,Workflow State,Workflow Action Master;doc_status(0/1/2) + styles de badge natifs.wflib/builder.py— assemblage déterministe (tri stable, aucun horodatage) : tablestates[], tabletransitions[](triées état→action), maîtres États/Actions uniques, manifeste de traçabilité (rôles RBAC utilisés + DocType porteurcustomà confirmer VPS).workflow.schema.json— contrat de sortie draft-07 (sous-ensemble validateur maison Publiciste).workflow_vente_gen.py— CLIbuild/validate. Refuse d'écrire si un des 9 invariants de graphe casse.out/(commité, hand-off direct) :workflow.json,workflow_state.json,workflow_action_master.json,MANIFEST.json.tests/test_workflow_vente.py— 25 testsunittest(stdlib pur).- CI : job
crm-workflow-vente-testsajouté au gate (.gitea/workflows/ci.yml, Gitea Actions uniquement · #2).
9 invariants de graphe (le CLI refuse d'écrire si l'un casse)
- Conformité au schéma de sortie. 2. Unicité des noms d'état. 3. Transitions
vers/depuis états déclarés. 4. Monotonie
doc_status(pas de saut 0→2 ni retour arrière — natif Frappe). 5. Unicité (état, action). 6. Atteignabilité de tous les états depuisLead. 7. ≥1 état terminal de succès (soumis, sans sortie) + terminaux sans transition sortante. 8. Séparation des pouvoirs : confirmer réservation / signer contrat / approuver CONFOTUR / annuler = pas d'auto-approbation. 9. Maîtres États/Actions == graphe + comptes manifeste cohérents.
Anti-invention (#6) + séparation des pouvoirs appliqués
- Aucun nom de rôle en dur : tous résolus depuis le contrat RBAC (source unique).
- Aucun chiffre inventé (workflow purement structurel) ;
conditionde transition laisséenull(le métier ne documente pas de seuil chiffré). - Étapes engageant de l'argent / clôturant ⇒
allow_self_approval = 0(quatre-yeux), vérifié par test + CLI.
Vérifications effectuées (en-repo, sans toucher au VPS)
- 25/25 tests verts (schéma maison + oracle
jsonschema) ; génération réelle : 9 états / 11 transitions / 9 maîtres États / 9 maîtres Actions ;out/commité == régénération bit-à-bit. - Gate CI local vert (exit 0) :
guard_constraints.sh,validate_json.sh(nouveaux JSON valides),check_docs.sh(README score présent, 0 lien cassé), YAMLci.ymlvalide. - Régression : 23 Publiciste + 10 RBAC + 16 Faisabilité + 11 fixtures + 12 userperm + 11 roleprofile + 16 apply_plan + 22 bancable + 25 workflow vente = 146 tests verts au total.
Non fait (hors périmètre worker · VPS)
- Création du DocType porteur
OTO Dossier Vente+ import des fixtures (bench migrate) → agent ERPNext Backend (contrainte #8).
Prochaine tâche suggérée
- Sprint 4 CRM : générateur des Notification/Email Alert par transition, ou
du DocType porteur
OTO Dossier Vente(fixture DocType) pour compléter le hand-off workflow. - Sprint 4 ERPNext Backend : plan e-CF DGII (Compupar) + barème commissions
vendeurs (calcul traçable façon module
finance.pydu bancable · #6).
Auto-score 4Big du livrable Générateur workflow vente : 96/100.
Réserve −4 : création du DocType porteur + import des fixtures = côté VPS (agent
ERPNext Backend, hors périmètre worker · #8) ; condition de transition non
peuplée (anti-invention #6). Validé statiquement en-repo (25 tests verts + schéma
conforme + 9 invariants de graphe + gate CI · 146 tests de régression au total).