Un acheteur se connecte au compte du groupe, choisit un site de livraison et voit une remise de 18 %. Son collègue, rattaché à une filiale, obtient 12 % sur le même produit. Au checkout, le système rattache l’adresse au mauvais payeur et applique le contrat groupe. La commande passe, mais la marge, la facture et le reporting commercial portent trois lectures incompatibles.
Le problème devient visible lorsque le prix est réduit à une colonne par client. En B2B, l’identité connectée, l’organisation acheteuse, le compte facturé, le site livré, le contrat, la quantité, la devise et la date peuvent tous modifier la décision. Une règle correcte isolément devient fausse lorsqu’elle reçoit le mauvais périmètre.
Le vrai enjeu est de produire un prix dont l’éligibilité, le calcul, la durée et le passage à l’engagement restent prouvables. Contre-intuitivement, centraliser toutes les remises dans un moteur unique ne suffit pas : si les identités et contrats sont ambigus, le moteur accélère une mauvaise décision avec beaucoup de cohérence technique.
Dans une démarche de développement web sur mesure, la tarification relie domaine client, catalogue, devis, commande et finance. Le modèle proposé associe un cas multi-comptes, des seuils locaux et une mise en œuvre qui protège le prix sans rendre chaque évolution dépendante d’un expert.
Traiter le prix comme une décision
Décrire les entrées déterminantes
Le moteur reçoit une intention complète : acteur, organisation acheteuse, compte facturé, bénéficiaire, canal, lignes, quantités, date, devise et contexte de livraison. Il ne déduit pas le client depuis le dernier choix en session. Chaque identifiant possède une source et un périmètre.
La sortie ne contient pas seulement un montant. Elle porte prix unitaire, total, taxe ou frais selon le domaine compétent, devise, version, règles appliquées, échéance et éventuelles conditions. Une réponse partielle est signalée. Zéro n’est pas la même chose qu’indisponible ou à approuver.
Nommer le propriétaire du verdict
Commerce décide la politique, finance valide les conséquences, produit organise l’usage et la plateforme garantit l’exécution. Les responsabilités sont écrites. Un administrateur technique ne crée pas une remise pour débloquer une commande. Une exception suit une commande autorisée avec motif, portée et date de fin.
Modéliser organisation, compte et mandat
Une personne peut acheter pour plusieurs organisations. Une organisation peut posséder plusieurs comptes de facturation et sites. Un contrat peut couvrir le groupe ou seulement une filiale. Le produit affiche le contexte actif et le revalide à chaque calcul. Changer de site invalide les données dépendantes au lieu de conserver silencieusement le prix précédent.
Le mandat relie utilisateur, capacité, organisation et durée. Il ne suffit pas d’être authentifié. Le contrôle suit les principes de validation à chaque requête de l’OWASP Authorization Cheat Sheet. Les prix, exports, paniers, devis et caches appliquent le même périmètre.
Séparer acheteur, facturé et livré
Ces rôles sont des relations, pas trois champs libres. La commande conserve qui a agi, pour quelle organisation, quel compte porte l’engagement et où l’exécution a lieu. La règle peut dépendre de l’un ou l’autre, mais elle le déclare. Le support ne corrige pas l’adresse pour modifier indirectement le prix.
Versionner les contrats et leurs périodes
Un contrat possède identifiant, version, dates d’effet, périmètre de produits, comptes, sites, devises, quantités, exclusions et mode de cumul. La publication est atomique pour les éléments qui doivent être cohérents. Une modification future n’altère pas les devis et commandes déjà engagés.
Les périodes sont validées. Deux versions actives sur la même population ouvrent un conflit ou suivent une priorité explicitement modélisée. Les contraintes d’exclusion de PostgreSQL peuvent aider à empêcher certains chevauchements ; la documentation des contraintes rappelle toutefois que le modèle métier doit définir précisément ce qui est incompatible.
Préparer renouvellement et fin
Avant expiration, le propriétaire reçoit une file avec contrats et populations touchées. La fin ne bascule pas automatiquement vers un tarif public si cette conséquence serait dangereuse. Le produit peut bloquer, prolonger avec autorité ou demander une revue. La décision et sa date sont visibles au client avant engagement.
Composer les règles sans ordre implicite
Tarif de base, remise de compte, palier de quantité, promotion, frais et dérogation forment une politique. L’équipe définit exclusivité, cumul, priorité et arrondi. L’ordre d’une liste de plugins ne devient pas la règle métier. Chaque composant explique sa contribution et les conditions non satisfaites.
Les montants utilisent une représentation décimale adaptée et des règles d’arrondi validées par devise et étape. Le front ne recalcule pas un total avec des nombres flottants différents. Le domaine décide quand arrondir : ligne, taux, taxe ou total. Les tests portent les écarts d’unité minimale qui révèlent les divergences.
Borner les promotions
Une promotion grand public ne traverse pas un contrat B2B sans politique explicite. Le moteur indique pourquoi elle ne s’applique pas. Une nouvelle campagne est testée contre un portefeuille de comptes. Si elle efface une marge ou un prix négocié, alors sa publication est suspendue plutôt que corrigée après les commandes.
Distinguer simulation, devis et engagement
La simulation informe à un instant donné. Le devis porte une durée et des hypothèses. La commande engage selon des préconditions. Transformer une simulation en commande sans revalidation fait passer un cache au rang de contrat. À l’inverse, recalculer silencieusement un devis enlève toute valeur à son acceptation.
Le panier conserve une référence de calcul et affiche son échéance. À l’engagement, le serveur vérifie compte, contrat, lignes et quantité. Si une différence apparaît, il la présente avant la confirmation. Un petit écart n’est pas automatiquement accepté : le métier décide les tolérances autorisées et les populations concernées.
Figer ce qui fonde la commande
La commande garde version de contrat, règle, prix, devise et contexte. Elle ne dépend pas du moteur courant pour être relue. Une facture ou un retour se fonde sur cet instant, avec les corrections prévues par leurs domaines. Cette trace évite de reconstruire l’histoire depuis des tables qui ont évolué.
Gérer chevauchements et changements tardifs
Deux commerciaux peuvent modifier un contrat pendant qu’un client commande. La version optimiste détecte le changement. Le moteur retourne un conflit expliqué. Le client choisit sur la nouvelle proposition ; le système ne remplace pas le prix entre affichage et clic sans lui rendre la décision.
Une demande rejouée utilise la même clé et retrouve son verdict. Même clé avec contenu différent est refusée. Les caches et projections portent la version de politique. Une réponse ancienne après changement de compte est ignorée. Les tâches asynchrones rechargent leur périmètre au moment d’émettre document ou export.
Prévoir l’indisponibilité
Le mode dégradé dépend du parcours. Le catalogue peut masquer le prix et proposer un devis ; le checkout peut attendre ou refuser ; un client disposant d’un prix figé peut continuer si la politique l’autorise. Le système n’invente pas une remise moyenne. La reprise rapproche les commandes laissées en attente avant réouverture.
Cas concret : groupe, filiales et sites livrés
Cas hypothétique : un groupe possède trois filiales et douze sites. Le contrat groupe couvre les consommables, mais les machines suivent des contrats de filiale. Deux sites bénéficient d’un palier logistique. Un acheteur central peut commander pour les sites, tandis que les acheteurs locaux ne voient que leur filiale.
La cible demande contexte d’achat avant le catalogue privé. Le moteur sélectionne les contrats éligibles, explique leur portée et calcule. Le panier garde organisation acheteuse, facturé et livré. Changer de site relance le calcul des lignes dépendantes. Les machines sans contrat actif proposent un devis plutôt qu’un prix public.
Le pilote couvre quatre acheteurs, trois cents produits et soixante commandes sur quatre semaines. Les seuils locaux exigent zéro prix visible hors périmètre, zéro contrat expiré engagé et toute différence supérieure à l’unité minimale de devise expliquée. Une fuite suspend immédiatement le pilote ; un refus explicable rejoint une correction qualifiée.
Tester un contrat qui expire
Par exemple, si le contrat filiale expire entre panier et validation, alors le checkout refuse la version et propose la voie de devis avec les lignes conservées. Si la réponse de commande se perd, le retry retrouve le même engagement. Le support reconstitue acteur, mandat, contrat, règle et total depuis l’identifiant.
Expliquer le prix sans exposer les marges
L’acheteur voit contrat, palier, remise commerciale et échéance utiles à sa décision. Il ne voit pas coût d’achat, marge ou règles réservées. Le commercial dispose d’un niveau complémentaire selon ses droits. Le support obtient codes et version pour diagnostiquer sans un rôle global.
Un refus indique la précondition : compte non éligible, contrat expiré, quantité insuffisante ou approbation nécessaire. Il ne confirme pas l’existence d’un contrat voisin. Les libellés sont stables. Une correction conserve le panier et le contexte. L’explication réduit les exports parallèles et les dérogations orales.
Rendre les exceptions visibles
Une dérogation porte demandeur, approbateur, motif, montant, population et expiration. Elle n’est pas une règle cachée dans le compte. Le tableau distingue usage ponctuel et exception récurrente. Cette dernière déclenche une revue de politique ou de données, pas une reconduction automatique.
Mettre en œuvre un moteur reprenable
Contractualiser calcul et engagement
Les entrées sont mandat, organisation, compte, lignes, date et version ; les sorties sont montant, explication, échéance et erreurs. Les dépendances sont explicites. Logging et instrumentation relient page, calcul, devis et commande. Le monitoring suit conflits, refus, latence, caches périmés, dérogations et écarts de balance.
Dans un backend PHP et Symfony, l’API reçoit un objet valeur immuable. Doctrine charge les contrats applicables et persiste devis ou engagement avec version. Les voters contrôlent action et périmètre. Un worker publie la commande. Les tests unitaires couvrent règles et arrondis ; les tests d’intégration couvrent droits, concurrence et retry. La CI rejoue un portefeuille de contrats.
Déployer sans basculer tous les comptes
Le déploiement active le moteur par organisation et famille. Une double lecture compare sans créer deux engagements. Le rollback renvoie les nouveaux calculs vers l’ancien chemin mais conserve les commandes déjà créées dans leur source. Le runbook répartit commerce, finance, support et exploitation et précise la reprise d’un contrat ou cache défaillant.
Piloter fuites, écarts et coût de correction
Le tableau suit calculs, devis, transformations, conflits, refus, dérogations, corrections et tickets. Il segmente par compte, contrat, produit, devise et version. Une marge moyenne peut masquer une fuite sur un compte. Un taux de succès peut masquer les clients envoyés vers un devis faute de données.
Chaque mesure déclenche une action : corriger un rattachement, renouveler un contrat, revoir un cumul ou retirer une exception. Les signaux faibles sont changements de compte répétés, exports pour vérifier un prix et approbations accordées après commande. Le comité observe coût complet et impact commercial avant d’industrialiser.
Une balance rapproche prix simulés, devis acceptés, commandes et documents financiers. Elle n’exige pas une égalité naïve si quantité ou exécution change, mais chaque différence possède une décision. Un écart sans cause reste ouvert et propriétaire jusqu’à réconciliation.
Une revue mensuelle tire dix prix élevés, dix remises récentes et dix refus. Commerce explique l’éligibilité, finance vérifie arrondis et conséquences, support reconstruit le contexte. Les écarts sont classés entre rattachement, contrat, cumul, donnée et concurrence. Si une cause se répète sur trois dossiers du portefeuille pilote, alors l’équipe corrige le modèle avant d’ajouter une dérogation. Ce seuil d’enquête est local et évolue avec le nombre de comptes.
Pour qui ce modèle devient-il nécessaire ?
Il concerne B2B, réseaux, franchises, centrales d’achat, multi-entités et portails avec devis ou prix négociés. Commerce, finance, produit, sécurité, développement, support et exploitation participent. Les responsables de compte apportent les contrats réels ; la finance protège arrondis et documents.
Un tarif unique par compte peut rester simple si identité et durée sont stables. Dès que plusieurs rôles, sites, paliers ou dérogations apparaissent, un modèle explicite devient prioritaire. Le nombre de remises n’est pas le déclencheur : la portée d’un prix faux et sa capacité à se propager le sont.
Erreurs fréquentes de tarification B2B
La première erreur stocke un pourcentage sur le client. La deuxième confond utilisateur et compte. La troisième ordonne les règles par plugin. La quatrième recalcule un devis accepté. La cinquième fait confiance au prix du navigateur. La sixième oublie devise et arrondi.
Autres pièges : contrat sans date, dérogation permanente, cache partagé, export plus permissif, promotion cumulée sans politique ou support qui corrige le total. Enfin, centraliser le calcul sans centraliser l’explication crée un moteur exact que personne ne peut contester ni reprendre.
Décider entre règle, table et approbation
Bloc de décision. Utilisez une table pour une correspondance stable et administrable. Écrivez une règle lorsque plusieurs faits produisent un verdict déterministe. Demandez une approbation lorsque le jugement et l’autorité restent nécessaires. Dans ce cas, conservez la proposition et son échéance. En revanche, n’utilisez pas une approbation humaine pour compenser chaque donnée manquante.
- Fermer identité et périmètre avant le calcul.
- Versionner contrat, cumul et arrondi.
- Distinguer simulation, devis et engagement.
- Tester fuite, conflit, expiration et reprise.
L’option la plus flexible n’est pas toujours la meilleure. Un langage de règles accélère les variations mais augmente validation et gouvernance ; du code explicite est plus lent à éditer mais mieux contrôlé. Le choix dépend de la fréquence, du risque et de l’équipe qui assumera le run.
Plan d’action sur huit semaines
Semaines 1 et 2 : inventorier
Rejouez trente commandes et dix devis. Cartographiez utilisateurs, organisations, comptes, sites, contrats et exceptions. Notez les corrections manuelles, les expirations et les calculs parallèles. Définissez les populations sensibles et les seuils de fuite, conflit et arrondi.
Semaines 3 à 5 : modéliser et construire
Créez les identités, versions de contrat et politique de cumul. Implémentez calcul expliqué, devis figé et engagement idempotent. Branchez droits, cache partitionné, journalisation, instrumentation et balance. Rejouez le portefeuille de contrats dans la CI avec les cas d’unité minimale.
Semaines 6 à 8 : ouvrir et perturber
Pilotez deux comptes. Provoquez contrat expiré, changement de site, promotion concurrente, réponse perdue et cache ancien. Exécutez rollback et reprise. Commerce et support expliquent cinq prix sans intervention développeur.
La revue finale compare soixante commandes, leurs devis et documents. D’abord, fermer le périmètre ; ensuite, stabiliser les versions ; puis étendre. Toute fuite, double engagement ou écart monétaire inexpliqué suspend le compte suivant. Les seuils restent locaux au portefeuille et sont requalifiés lors d’un changement de modèle.
Gouverner la première semaine d’ouverture
La première semaine d’ouverture ajoute une balance quotidienne par compte et contrat. Elle rapproche demande de calcul, version servie, devis éventuel, commande et montant transmis à la finance. Chaque différence cite l’événement qui l’explique. Le support exécute une reprise de cache ancien et une réponse perdue, tandis que le commerce joue expiration et nouvelle dérogation. Le compte suivant reste fermé tant que l’une de ces procédures dépend d’une correction SQL ou d’une connaissance orale.
Le bilan consigne également le coût de gouvernance : nombre de règles, temps de validation, contrats sans owner et exceptions proches de leur fin. Une plateforme tarifaire n’est pas déclarée réussie parce qu’elle calcule vite. Elle doit permettre à une équipe autorisée de publier, expliquer, retirer et auditer une politique sans provoquer une fuite. Les règles inutilisées sont dépréciées avec une période d’observation, puis retirées des tests et des interfaces.
Ce retrait contrôlé réduit aussi le portefeuille de cas que finance et support devront vérifier au prochain changement.
- Nommer qui achète, paie et reçoit.
- Versionner la décision tarifaire.
- Tester cumul, conflit et expiration.
- Étendre depuis des prix expliqués.
Guides complémentaires pour le B2B
Relier le prix à la commande
La cohérence e-commerce et ERP relie le prix versionné aux réservations, commandes et documents.
Protéger le prix dans le front
La performance e-commerce sépare rendu rapide, cache privé et revalidation à l’engagement.
- Une identité qualifiée.
- Un contrat versionné.
- Un prix expliqué jusqu’à la commande.
Conclusion : rendre le prix opposable et explicable
La tarification contractuelle n’est pas un pourcentage attaché à un client. Elle relie mandat, organisation, compte, contrat, produit, quantité, date et devise. Chacun conserve une identité et un propriétaire.
Versionner les contrats, distinguer simulation et engagement, contrôler les cumuls et expliquer le verdict protègent marge et confiance. Les caches et retries respectent le périmètre. Une exception porte toujours une fin.
Dawap peut accompagner ce modèle et sa mise en œuvre dans une démarche de développement web sur mesure. Le résultat attendu est un prix juste pour le bon compte, compréhensible par le client et reconstructible par le support jusqu’au document financier.