quote → cash
FR/EN Contact

Pricing·Avancé·12 min·Mis à jour le 05/10/2026

Guide · Pricing

Renouvellement au prix catalogue : quand la pricing procedure ignore vos lignes Renew

Un renouvellement natif qui sort au prix catalogue, sans remise de bundle, sans composants inclus, sans indexation. Quatre causes empilées dans la procédure, et l’outil qui les rend visibles.

D’où vient chaque affirmation
Salesforce docsdocumenté par SalesforceTerrainconstaté sur une vraie orgRecommandéce que nous recommandonsÀ vérifiernon vérifié
Architecture du pricing contexte → procédure → prix
ENTRÉE DÉCIDER EXÉCUTER SORTIE ContextDefinition ce que le pricing voit DecisionTable si conditionnel Barème d’ajustement paliers et franchises PricebookEntry si sans condition Pricing procedure ExpressionSet Prix net sur la ligne

Scroll the diagram sideways

La règle qui garde un catalogue maintenable : une decision table seulement s’il y a une condition ou un palier. Un prix fixe vit sur le PricebookEntry. Les decision tables ajoutées par réflexe sont ce qui remplit une procédure jusqu’à son plafond.

Et la procédure qui s’exécute est la version compilée _Auto, pas la source que vous éditez.

Un renouvellement doit coûter ce que le client paie aujourd’hui, plus l’indexation. Le nôtre sortait 37 % plus cher : prix catalogue plein, remise de bundle perdue, composants inclus facturés, et pas une trace de l’indexation pourtant posée sur la ligne.

Personne ne s’en serait aperçu sur une démo. Sur un vrai parc, c’est une facture fausse à chaque date anniversaire.

Le symptôme

Un bundle vendu 5 licences à 3 600, avec 10 % de remise de bundle (3 240 net) et une dizaine de composants inclus à 0. On pose 1,58 % d’indexation sur l’actif, on clique sur Renouveler.

LigneVente d’origineRenouvellement obtenu Attendu
Licences ×516 20018 00016 455,96
Composants inclus04 2520
Total16 200 22 25216 455,96

Le taux d’indexation est bien sur la ligne. Le prix l’ignore, comme il ignore tout le reste. Terrain

Première erreur : corriger la mauvaise procédure

On avait un procedure plan actif sur Quote, qui pointait vers une procédure maison. Toutes nos corrections allaient dedans. Cinq versions plus tard, rien ne bougeait.

La procédure qui calcule un devis via l’API — et donc les renouvellements — n’était pas celle du plan. C’était la procédure par défaut de la pricing recipe. Le plan n’intervenait pas sur ce chemin. Terrain Le périmètre exact des procedure plans selon le point d’entrée reste À vérifier

Deux pièges ont rendu ça invisible longtemps.

  • Une nouvelle version avec la même date de début que la précédente n’est pas sélectionnée. Si vous copiez une version pour la modifier, avancez sa date de début.
  • Le moteur garde la procédure en cache une à deux minutes après un déploiement. Un test lancé juste après tourne sur l’ancienne version. Testez en boucle jusqu’à voir le changement.

Le réflexe à prendre : marquer chaque version. Changez le libellé d’une étape — Get base prices from price book V7 — et vérifiez qu’il apparaît à l’exécution. Sans ce marqueur, vous ne savez pas ce que vous testez. Recommandé

L’outil qui change tout : la cascade de prix

Les logs de pricing disent seulement qu’une ligne a réussi ou échoué, sans message. La cascade de prix, elle, donne chaque étape exécutée, avec ses entrées et ses sorties.

L’identifiant d’exécution attendu est la partie qui précède le _ dans la clé de type d’exécution de l’exécution de ligne, pas la clé globale. Avec le mauvais identifiant, l’API répond « vérifiez vos réglages de Price Waterfall », ce qui oriente vers une fausse piste. Terrain

C’est cette cascade qui a révélé les quatre causes suivantes, en une lecture.

Les quatre causes, empilées

Les lignes créées par le renouvellement arrivent avec deux particularités : elles sont marquées « prix de la dernière transaction », et leur attribut de pricing dérivé est vide. Une ligne de vente neuve a cet attribut à false. Terrain

1. Les lignes échouent en silence

Plusieurs groupes de la procédure standard filtrent sur « attribut dérivé non nul ET égal à false ». Une valeur vide ne passe ni l’un ni l’autre. Ces lignes sautent le calcul du prix net et finissent en échec. Le moteur garde alors le prix catalogue, sans message d’erreur.

Correctif : « attribut dérivé nul OU égal à false » dans ces groupes.

2. Une étape « dernière transaction » écrase le résultat

La branche dernière transaction se termine par une affectation du prix unitaire d’entrée vers le prix net. Elle tourne après les remises et l’indexation, et remet le prix net au prix unitaire d’origine avant remise. Dans la cascade, on voit l’indexation calculer le bon montant, puis cette étape l’effacer.

Correctif : exclure les lignes de type Renew de cette branche.

3. Les remises excluent les renouvellements

Remise de bundle, remises au volume, remises en montant ou en pourcentage, prix par attribut : chaque groupe porte un filtre qui écarte les lignes « dernière transaction ». Pour un avenant, ça se défend. Pour un renouvellement, ça supprime la remise de bundle et le prix à 0 des composants inclus.

Correctif : ajouter une exception pour le type Renew sur ces filtres. Recommandé Nous avons choisi de renouveler au prix catalogue courant, remise de bundle réappliquée, puis indexé. Si votre politique est de repartir du net payé, c’est un autre chantier.

4. L’indexation n’a nulle part où s’appliquer

L’étape native de révision de prix exige une politique de révision sur la ligne et la branche dernière transaction. Sans politique, elle ne fait rien. Nous avons ajouté une étape de pricing par formule : le prix net, plus le prix net multiplié par le taux d’indexation de la ligne, filtrée sur un taux non nul et une quantité positive, et placée après les remises.

Le pourcentage stocké en 1,58 arrive dans le contexte en 0,0158. Terrain

Ce qu’on a écarté

  • Un hook Apex dans le procedure plan. On l’avait déjà mesuré : la section pricing suivante relit les enregistrements et écrase ce que le hook a écrit. Et le plan n’était même pas sur le chemin.
  • Forcer le prix par l’API. Poser un prix unitaire différent du catalogue déclenche bien le calcul complet — même 3 600,01 au lieu de 3 600. Un prix égal au catalogue est ignoré, ce qui est justement le cas normal d’un renouvellement. C’est une béquille, pas une solution.
  • Écrire le prix sur la ligne par DML. Refusé dès que la ligne a un détail : « You can’t edit the Sales Price because the Quote Line Item has related Quote Line Detail records ».

Résultat

Un renouvellement créé au bouton, sans aucune manipulation : 16 455,96, soit 3 600, moins 10 % de remise de bundle, plus 1,58 % d’indexation, avec les composants inclus à 0.

Deux contrôles avant de passer en production : une vente neuve calcule toujours le même prix, et un avenant négatif garde son montant au prorata.

Ce que ça coûte

  • Une version de procédure en plus. Avec des filtres qui s’écartent du standard. À chaque montée de version Salesforce, il faut relire ces groupes.
  • Huit filtres modifiés. Dont la logique doit être documentée, sinon le prochain administrateur les « répare ».
  • Un choix métier assumé : Le renouvellement repart du prix catalogue courant. Une hausse de catalogue s’ajoute alors à l’indexation.

Composants Salesforce

Sélectionnez-en un pour ouvrir son détail.

Sur quoi ça repose

  • Org en Advanced Transaction Detail Line Pricing, avec l’étape de mapping de ligne en place. Sans elle, les lignes d’avenant négatif sortent à 0 : c’est le sujet de l’avenant négatif à 0 €.
  • Le comportement « attribut dérivé vide sur les lignes Renew » et la sélection de version par date de début sont observés, pas documentés. Ils peuvent changer avec une release.
  • Le choix de la procédure selon le point d’entrée — API, écran, plan — reste à vérifier sur votre org. Marquez vos versions avant de conclure quoi que ce soit.
  • Constaté sur une org en Summer ’26 / Winter ’27.

Ressources Salesforce