Files
Claude Code DTP Worker 71c1223cc3 [DTP-Worker] Sprint 4 · Générateur barème commissions vendeurs (ERPNext Backend · roadmap L51)
Plan de commissions cross-cohérent workflow ↔ DocType ↔ RBAC + calcul traçable
commission = base × taux (façon banclib/finance.py). Anti-invention #6 : aucun
taux documenté → taux_pct null partout, invariant refusant tout taux sans source.
Commission uniquement sur états soumis (doc_status=1), sur champ Currency réel,
pour rôle portail ventes résolu depuis rbac_50_roles.json.

- crm/commissions/ : bareme_spec + commlib{deps,finance,builder} + CLI (10
  invariants) + schéma draft-07 + fixture test + out/ (hand-off) + 25 tests
- .gitea/workflows/ci.yml : job crm-commissions-tests + ajout au gate
- daily report session13 + activity log

Vérifs : 25/25 tests · gate CI local vert · régression 202 tests verts.
Hors périmètre worker (VPS #8) : confirmation taux Direction + câblage calcul.
Auto-score 4Big : 96/100.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-30 06:35:03 +00:00

40 lines
1.6 KiB
Python

"""Réutilisation des briques déjà livrées (workflow #5 · zéro duplication).
Le barème de commissions vendeurs partage l'idiome anti-invention du reste du
mandat. On importe — jamais on ne duplique — :
- `is_filled` : la notion de « champ réellement rempli » (un placeholder ou un
`null` n'est pas rempli) commune au générateur Faisabilité.
- `CANONICAL` : les paramètres canoniques CLAUDE.md #9/#10 (USD+DOP notamment).
AUCUN taux de commission n'y figure → aucun n'est fabriqué ici.
- `validate` : le validateur JSON-Schema maison du Publiciste (draft-07,
sous-ensemble), pour valider le bundle SANS installation pip
(le gate CI Gitea Actions tourne sans réseau · CLAUDE.md #2).
Import par `sys.path` (comme `banclib/deps.py`) — une seule source de vérité.
"""
from __future__ import annotations
import os
import sys
_HERE = os.path.dirname(os.path.abspath(__file__))
# crm/commissions/commlib → 05_deliverables_mvp
_DELIVERABLES = os.path.normpath(os.path.join(_HERE, "..", "..", ".."))
_GEN = os.path.join(_DELIVERABLES, "faisabilite", "generator")
_PUB = os.path.join(_DELIVERABLES, "publiciste")
for _p in (_GEN, _PUB):
if _p not in sys.path:
sys.path.insert(0, _p)
from genlib import model # type: ignore # noqa: E402
from lib import validator # type: ignore # noqa: E402
is_filled = model.is_filled
CANONICAL = model.CANONICAL
TEMPLATE_VERSION = model.TEMPLATE_VERSION
validate = validator.validate
__all__ = ["is_filled", "CANONICAL", "TEMPLATE_VERSION", "validate"]