Files
Claude Code DTP Worker e7cc3c4a3c [DTP-Worker 20260812_080104] fix correctness · commissions vendeurs — la formule traçable base×taux cassait sur montants réels
Bug latent réel (crm/commissions/commlib/finance.py:75) : le libellé de base de
la formule traçable « commission = base × taux » utilisait f"{base:g}", qui casse
deux fois sur des montants immobiliers réels en RD (une unité USD 300k ≈ 18M DOP) :
(1) notation exponentielle dès 1e6 (18000000 → 1.8e+07, illisible/non auditable) ;
(2) arrondi silencieux à 6 chiffres significatifs (123456.78 → 123457) = une base
FABRIQUÉE ≠ de la réelle, l'invention interdite par #6 dans le module même qui
proclame l'anti-invention.

Fix : helper _amount_label (f"{x:f}" jamais exponentiel + strip zéros) → décimal
fidèle, identique à l'ancien pour tous les montants simples (200000 reste 200000) ;
seuls les cas buggés changent. 2 tests à dents (millions non-exponentiel + décimales
préservées) — teeth prouvé : les DEUX échouent sans le fix.

Byte-repro : 0 impact d'artefact du module (compute_line est runtime, jamais appelé
par le générateur). Cascade compteur-de-suite seule : matrice 631/614 → 633/616,
regression×3 + quality_report régénérés, fiches qa/erpnext/crm + README réalignés
(commissions 25→27, Total CRM 81→83). run_ci 33/0/0. 0 code moteur V18 (bloqué D-06).
0 gate ajouté (#5). 0 commande VPS (#8).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-12 08:11:32 +00:00

94 lines
4.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 # 27 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 (27 tests verts + schéma + 10 invariants de cross-cohérence
+ gate CI).