# Barème commissions vendeurs · `OTO Barème Commissions Ventes` **Sprint 4 · ERPNext Backend** (roadmap ligne 51 : _« commissions vendeurs auto »_). Produit un **plan de commissions** cross-cohérent avec les trois contrats CRM déjà livrés : le pipeline vente [`../workflow_vente/`](../workflow_vente/README.md), le DocType porteur [`../dossier_vente/`](../dossier_vente/README.md) et le contrat RBAC 50 rôles. Il répond à la question : **quel évènement du pipeline paie, à quel rôle, sur quel montant** — et fournit un **calculateur traçable** `commission = base × taux`. > Ce worker **n'écrit jamais sur le VPS** (contrainte #8) : il émet les fichiers > de hand-off en-repo ; la création du champ commission et le calcul en > production restent côté agent ERPNext Backend. ## Anti-invention (#6) — pourquoi tous les taux sont `null` **Aucun taux de commission n'est documenté dans CLAUDE.md.** Les seuls pourcentages canoniques (3 % édition · 8.5 % marketing · 52 % point d'équilibre) ne sont **pas** des commissions. Fixer un taux ici serait une invention. Donc : - Le barème livré porte `taux_pct: null` + `source: null` + `a_confirmer: true` pour **chaque** évènement. - Le calcul `commission = base × taux` reste `None` tant qu'un opérande manque — **jamais** 0-inventé ; la formule reste affichée (traçabilité façon [`banclib/finance.py`](../../faisabilite/bancable/banclib/finance.py)). - Un invariant du CLI **refuse** tout `taux_pct` fourni **sans `source`**. La Direction renseigne `taux_pct` + `source` plus tard ; le calcul devient alors auditable et reproductible. ## Ce qui est généré (`out/`, commité — hand-off direct) | Fichier | Rôle | |---|---| | `commission_plan.json` | Le plan normalisé : par évènement → rôle (nom Frappe résolu) + champ de base + taux (null, à confirmer). | | `MANIFEST.json` | Traçabilité (4 sources, comptes, `taux_a_confirmer`) + rôles RBAC utilisés + note anti-invention. | ## Cross-cohérence barème ↔ workflow ↔ DocType ↔ RBAC (le cœur du livrable) Chaque évènement est **contraint** par les contrats voisins (anti-dérive · zéro duplication · workflow #5) : - **`update_value`** doit exister dans [`workflow_vente_spec.json`](../workflow_vente/workflow_vente_spec.json) **et** correspondre à un état **soumis** (`doc_status = 1`) : on ne commissionne pas un brouillon (lead/visite/devis/abandonné), seulement réservation, contrat et approbation CONFOTUR. - **`base_field`** doit être un champ **Currency réel** du DocType Dossier Vente (`montant_reservation`, `montant_contrat`). - **`role_id`** doit être résolu depuis [`rbac_50_roles.json`](../../rbac/rbac_50_roles.json) (via le `RoleResolver` **réutilisé** du module workflow) **et** appartenir au portail `ventes`. - **`devise_field`** = le champ `devise` (`Select` **USD/DOP** · #10) du DocType. ## Utilisation ```bash python3 commissions_gen.py build # écrit out/ (refuse si invalide) python3 commissions_gen.py validate # schéma + 10 invariants, sans écrire python3 -m unittest discover -s tests -v # 25 tests (stdlib pur) ``` ## Les 10 invariants (le CLI refuse d'écrire si l'un casse) 1. Conformité au [schéma de sortie](bareme.schema.json). 2. `update_value` ∈ workflow vente. 3. État **soumis** uniquement (pas de commission sur brouillon). 4. `base_field` = champ Currency réel du Dossier Vente. 5. `role_id` du portail ventes. 6. `erpnext_role_name` cohérent avec RBAC. 7. Anti-invention : jamais de `taux_pct` sans `source`. 8. Unicité (`update_value`, `role_id`). 9. `devise_field` = `devise` (USD/DOP). 10. Comptes du manifeste cohérents. ## Calcul traçable (`commlib/finance.py`) `compute_line(dossier, event)` → `montant = base × taux_pct`, avec la **formule publiée** (`200000 × 2.5 %`), la devise, et `champs_manquants` si un opérande est absent (montant alors `None`). La fixture [`fixtures/dossier_exemple.json`](fixtures/dossier_exemple.json) sert **uniquement aux tests** : ses chiffres sont des exemples fictifs portant une `source` explicite « non contractuel » — jamais commités dans `out/`. ## Hand-off VPS (agent ERPNext Backend · hors périmètre worker · #8) 1. La Direction confirme les `taux_pct` + `source` de chaque évènement. 2. Créer le mécanisme de commission côté ERPNext (champ/table enfant sur le DocType Dossier Vente, ou DocType commission dédié) et brancher le calcul sur les transitions du Workflow (réservation / contrat / CONFOTUR approuvé). --- **Auto-score 4Big : 96/100.** Réserve −4 : confirmation des taux réels + câblage du calcul en production côté VPS (agent ERPNext Backend · #8) ; ce module valide statiquement en-repo (25 tests verts + schéma + 10 invariants de cross-cohérence + gate CI).