La remise est le seul endroit d'un ERP où une négociation se matérialise. Elle se discute en euros, se décide en pourcentage, s'applique parfois à toute la commande, et finit souvent écrasée par un recalcul automatique.
Quinze modules communautaires couvrent ces cas. Trois types de remise, deux façons de protéger un prix, un historique, et une mécanique de tarifs nettement plus riche que le standard.
Résumé
Trois modules ajoutent des types de remise : en montant fixe (sale_fixed_discount), globale sur toute la commande et cumulable en cascade (sale_global_discount), ou globale répercutée sur le champ de remise de chaque ligne avec exclusions produit par produit (sale_order_general_discount). sale_discount_display_amount affiche le montant remisé et le total avant remise, sur la ligne et dans les totaux — ce qu'un client demande systématiquement.
Deux modules protègent un prix : sale_order_line_final_price verrouille prix unitaire et remise pour les non-responsables, sale_order_line_price_lock_by_pricelist verrouille le prix unitaire quand il vient d'une règle de tarif d'une portée donnée. Deux autres aident à le fixer : l'historique des prix pratiqués chez ce client, et deux boutons de recalcul des prix et des descriptions.
Côté tarifs enfin : une règle de tarif par conditionnement, une catégorie de prix indépendante de la catégorie produit, le prix déterminé par la date de livraison plutôt que par la date de commande, l'affichage d'une majoration (et non seulement d'une remise), le choix de la méthode d'arrondi de TVA par client, et un cache de prix pour sortir un catalogue client complet sans relancer le moteur de calcul.
L'essentiel
- Remise en euros sur la ligne, remise globale en cascade sur la commande, ou remise uniforme répercutée ligne à ligne avec exclusions.
- Le montant de la remise affiché — sur la ligne et dans les totaux, en HT ou en TTC selon un paramètre.
- Deux verrouillages de prix : par rôle, ou selon la portée de la règle de tarif qui a fixé le prix.
- L'historique des prix pratiqués pour ce produit chez ce client, réappliquable en un clic.
- Le prix calculé à la date de livraison plutôt qu'à la date de commande — décisif quand les tarifs changent au 1ᵉʳ janvier.
- Un tarif par conditionnement : unité, carton, palette — le même article à trois prix.
- Une catégorie de prix indépendante de la catégorie produit, pour des règles transversales.
- Un cache de prix pour produire un catalogue client complet sans recalcul, avec file d'attente de traitement.
Ce que ces modules ajoutent à l'instance
| Module | Ce qu'il apporte | Version | Dépend de |
|---|---|---|---|
sale_fixed_discount | Remise en montant fixe sur la ligne | 18.0.1.0.0 | account_invoice_fixed_discount |
sale_global_discount | Remises globales cumulables en cascade | 18.0.1.0.0 | account_global_discount |
sale_order_general_discount | Remise uniforme répercutée sur les lignes | 18.0.1.0.2 | sale |
sale_discount_display_amount | Le montant de la remise, enfin visible | 18.0.1.0.0 | sale_management |
sale_order_line_final_price | Prix et remise verrouillés hors responsables | 18.0.1.0.2 | sale |
sale_order_line_price_lock_by_pricelist | Prix verrouillé selon la portée de la règle | 18.0.1.0.1 | sale |
sale_order_line_price_history | Historique des prix pour ce produit | 18.0.1.0.1 | sale |
sale_order_price_recalculation | Recalcul manuel des prix et descriptions | 18.0.1.0.0 | sale |
sale_last_price_info | Dernier prix pratiqué, accessible à la saisie | 18.0.1.0.0 | sale_management |
sale_pricelist_packaging | Règle de tarif par conditionnement | 18.0.1.0.0 | sale_management |
product_price_category | Catégorie de prix indépendante | 18.0.1.0.0 | sale_stock |
sale_pricelist_from_commitment_date | Prix calculé à la date de livraison | 18.0.1.0.0 | sale |
sale_pricelist_display_surcharge | Affichage des majorations | 18.0.1.0.0 | sale |
sale_custom_rounding | Méthode d'arrondi de TVA par client | 18.0.1.0.0 | account_invoice_custom_rounding |
pricelist_cache | Cache de prix pour catalogue client | 18.0.1.0.0 | product, queue_job, partner_pricelist_search |
Un seul menu ajouté, par le dernier : Ventes ▸ Configuration ▸ Produits ▸ Pricelist Cache. Tous les autres enrichissent le devis, la ligne, la fiche produit ou la liste de prix.
Trois remises, trois logiques commerciales
| Module | Où s'applique la remise | Pour qui |
|---|---|---|
sale_fixed_discount | Sur la ligne, en euros | Le commercial qui négocie « je vous fais 500 € » |
sale_global_discount | Sur la commande entière, en cascade | Les remises financières successives — volume, puis fin d'année |
sale_order_general_discount | Sur la commande, répercutée ligne à ligne | La remise uniforme avec exclusions produit |
La différence entre les deux derniers est structurante. La remise globale reste une ligne de remise au niveau de la commande, transmise telle quelle à la facture ; la remise générale modifie le champ de remise de chaque ligne, donc change le prix net de chaque ligne.
Le choix se fait sur une question simple : votre client doit-il voir une remise par ligne, ou une remise en pied de document ? Un distributeur veut la première, un donneur d'ordre industriel souvent la seconde.
Le quatrième module du lot est celui qu'on finit toujours par installer. En standard, Odoo n'affiche que le taux de remise : jamais le montant. sale_discount_display_amount calcule et affiche ce montant, en HT ou en TTC selon un paramètre, sur chaque ligne et dans la zone des totaux, avec le total avant remise.
C'est exactement ce que le client demande au téléphone — « ça me fait combien de remise ? » — et ce qu'un vendeur calculait jusque-là à la main.
Protéger un prix négocié
Deux verrouillages, deux logiques, et ils se complètent plus qu'ils ne se concurrencent.
- Par rôle :
sale_order_line_final_pricepermet de poser un prix final et de verrouiller prix unitaire et remise pour les utilisateurs qui ne sont pas responsables des ventes. Le prix décidé par le responsable ne bouge plus. - Par origine du prix :
sale_order_line_price_lock_by_pricelistverrouille le prix unitaire quand il provient d'une règle de tarif dont la portée — produit, variante, catégorie, tous produits — correspond à un niveau de verrouillage défini sur la liste de prix.
Le second est le plus fin, et le plus adapté aux entreprises qui ont une vraie politique tarifaire : un prix catalogue négocié au niveau d'un contrat client ne doit pas pouvoir être modifié à la main, tandis qu'un prix issu d'une règle générique peut rester ajustable.
Il complète utilement le verrouillage par la liste de prix côté achats, et les deux reposent sur le même principe : c'est l'origine du prix qui décide de sa modifiabilité, pas le rôle de celui qui regarde l'écran.
Et quand il faut au contraire recalculer
sale_order_price_recalculation ajoute deux boutons sur le devis : recalculer les prix selon la liste de prix courante, et réinitialiser les descriptions des lignes depuis la fiche produit.
Le cas d'usage est le devis ancien qu'on réactive : les tarifs ont changé, les libellés aussi, et tout reprendre à la main prend un quart d'heure. Deux boutons, et le devis est à jour — en assumant qu'il faut ensuite le relire.
Retrouver le bon prix : historique et dernier prix
Un vendeur au téléphone a une question récurrente : à quel prix lui avons-nous vendu ça la dernière fois ? Deux modules y répondent, avec deux niveaux de profondeur.
| Module | Ce qu'il montre | Geste |
|---|---|---|
sale_order_line_price_history | L'historique des prix pratiqués pour le produit, chez ce client ou tous clients confondus | Réappliquer un prix passé en un clic |
sale_last_price_info | Le dernier prix pratiqué, accessible pendant la saisie | Information, sans ressaisie |
Ce détail décide souvent de la cohérence tarifaire d'une entreprise. Sans historique accessible, chaque vendeur refait son prix — et le client finit par connaître l'écart entre deux commerciaux mieux que vous.
Le premier est le plus complet : il distingue l'historique chez ce client de l'historique général, ce qui est la bonne distinction pour une négociation.
Le symétrique existe côté achats, où il sert à ne pas payer plus cher que la dernière fois : voir la fiche des achats.
Des tarifs plus fins que le standard
Par conditionnement, par catégorie de prix
sale_pricelist_packagingpermet des règles de tarif par conditionnement : le même article vendu à l'unité, au carton ou à la palette n'a pas le même prix unitaire. C'est la base du négoce, et c'est absent du standard.product_price_categoryajoute une catégorie de prix sur le produit, indépendante de la catégorie produit — qui, elle, porte la comptabilité et la logistique. On peut alors écrire des règles transversales sans tordre son arborescence comptable.
Le second résout un conflit classique : la catégorie produit sert déjà à la comptabilité analytique et au stock. Y greffer la logique tarifaire finit par produire une arborescence que plus personne ne comprend.
Quelle date fait le prix ?
sale_pricelist_from_commitment_dateutilise la date d'engagement — la date de livraison — plutôt que la date de commande pour déterminer la règle de tarif applicable. Deux options permettent de rendre cette date plus visible, voire obligatoire, sur le formulaire.
Le cas se présente chaque 1ᵉʳ janvier : une commande prise en décembre pour une livraison en février doit-elle appliquer l'ancien tarif ou le nouveau ? La réponse dépend de vos conditions générales — et jusqu'ici, Odoo n'offrait qu'une seule réponse.
Majorations, arrondis et catalogue
sale_pricelist_display_surchargeaffiche une majoration calculée par une règle de tarif. Par défaut, Odoo masque les « remises négatives » : le surcoût s'applique sans se voir, ce qui est le meilleur moyen de perdre la confiance du client.sale_custom_roundingpermet de choisir la méthode d'arrondi de TVA — par ligne ou globale — au niveau d'un contact ou d'une commande, plutôt que d'appliquer celle de la société. C'est une exigence de certains clients et de certains pays.pricelist_cacheprécalcule le prix de chaque produit pour chaque tarif, afin de générer un catalogue client complet sans relancer le moteur de prix. Il s'appuie sur une file d'attente de traitement, donc sur une infrastructure de travaux de fond.
Le dernier n'est pas un module de confort : sur un catalogue de dizaines de milliers de références, produire la liste de prix d'un client est une opération qui met un serveur à genoux. Le cache la rend instantanée, au prix d'un mécanisme de rafraîchissement à surveiller.
Limites connues
- Trois modules de remise qui se chevauchent : choisir selon ce que le client doit voir — remise par ligne ou en pied de document — et ne pas les empiler.
sale_fixed_discountetsale_global_discountdépendent de modules comptables correspondants : la remise doit exister sur la facture, pas seulement sur la commande.- Le verrouillage par règle de tarif suppose une politique tarifaire réelle : sans règles structurées, il n'a rien à verrouiller.
- Le recalcul des prix écrase les ajustements manuels : c'est son rôle, et c'est à dire avant de donner le bouton.
pricelist_cachedépend d'une file de travaux de fond (queue_job) : c'est un composant d'infrastructure à exploiter, pas une case à cocher.- Le cache doit être rafraîchi : un prix modifié et un cache périmé produisent un catalogue faux, ce qui est pire que lent.
Identité technique
Les quinze modules viennent du dépôt OCA sale-workflow, branche 18.0, en licence AGPL-3 sauf sale_order_line_price_lock_by_pricelist (LGPL-3). Quatre dépendent d'un module comptable du dépôt account-invoicing — remise fixe, remise globale, arrondi personnalisé — parce que la remise doit vivre jusqu'à la facture.
Les autres familles de ce dépôt sont traitées dans la présentation des lignes et les dates et reliquats.
Questions fréquentes
Peut-on faire une remise en euros dans Odoo ?
Pas en standard : la remise d'une ligne est un pourcentage. sale_fixed_discount ajoute la remise en montant fixe, en s'appuyant sur le module comptable qui apporte déjà cette capacité aux factures — la remise doit en effet exister jusque sur la facture, pas seulement sur la commande.
Pourquoi Odoo n'affiche-t-il pas le montant de la remise ?
Parce qu'il n'affiche que le taux. sale_discount_display_amount calcule et affiche le montant remisé et le total avant remise, en HT ou en TTC selon un paramètre, sur chaque ligne et dans la zone des totaux. C'est la question que pose tout client au téléphone.
Comment empêcher un vendeur de modifier un prix négocié ?
Deux approches. sale_order_line_final_price verrouille prix et remise pour les utilisateurs non responsables des ventes. sale_order_line_price_lock_by_pricelist verrouille le prix selon l'origine : si le prix vient d'une règle de tarif dont la portée correspond au niveau de verrouillage de la liste de prix, il n'est plus modifiable à la main.
Quel tarif s'applique pour une commande prise avant un changement de prix ?
En standard, celui de la date de commande. sale_pricelist_from_commitment_date fait appliquer le tarif en vigueur à la date de livraison — ce qui change tout pour une commande de décembre livrée en février. Deux options rendent cette date plus visible, voire obligatoire sur le formulaire.
Peut-on vendre le même produit à des prix différents selon le conditionnement ?
Oui, avec sale_pricelist_packaging : les règles de tarif peuvent viser un conditionnement — unité, carton, palette. C'est la base du négoce et c'est absent du standard, où le prix est attaché au produit et à son unité de mesure.
Se faire accompagner
La politique tarifaire est le sujet où l'empilement de modules coûte le plus cher : trois types de remise installés en même temps produisent trois façons de faire la même chose, et des documents clients incohérents d'un vendeur à l'autre.
Nous commençons donc par écrire la politique — qui accorde quoi, jusqu'où, et ce que le client doit lire sur son devis — puis nous installons les deux ou trois modules qui la servent. Le reste n'a pas de raison d'exister sur votre instance. Voir les prestations d'Atalios Consulting, notre méthode ou demander un rappel.
Pour aller plus loin
- Lignes de commande : présentation et documents
- Achats : types, remises et blocages
- Ventes : types de commande, workflows et blocages
En résumé
Trois formes de remise, deux verrouillages de prix, un historique client, et des tarifs enfin capables de distinguer un carton d'une palette ou une livraison de janvier d'une livraison de février. À choisir selon la politique commerciale écrite, pas selon la liste des modules disponibles. Parlons de votre politique tarifaire.