Le module Achats standard d'Odoo suppose que toutes les commandes se ressemblent et qu'un humain vérifie chacune. Dès qu'une entreprise distingue les achats ponctuels des contrats-cadres, ou qu'elle importe des commandes en masse, les deux hypothèses tombent.
Six modules du dépôt purchase-workflow — le deuxième plus fourni de l'écosystème avec 106 modules documentés — traitent ces cas : la typologie, le blocage, les remises en chaîne et le suivi des encours.
Résumé
Six modules complètent les achats : un type de commande qui porte des valeurs par défaut et sa propre séquence, des règles de blocage avant confirmation, les remises en cascade côté fournisseur, le dernier prix d'achat sur la fiche produit, les conditions générales par défaut, et le suivi des quantités restant à recevoir ou à facturer.
Les deux plus utiles répondent à deux questions opposées : purchase_exception empêche une commande anormale d'être confirmée — son intérêt est maximal lors d'imports massifs, où les erreurs de données sont fréquentes — et purchase_open_qty répond à « qu'est-ce qui reste à recevoir », ce qu'Odoo ne dit pas d'un coup d'œil.
L'essentiel
purchase_order_type: Regular, Blanket, Contract, Planned — avec conditions de paiement, incoterm et séquence de numérotation par type.purchase_exception: règles de détection avant confirmation, bloquantes ou non, ignorables par un utilisateur habilité.purchase_triple_discount: trois remises en cascade par ligne, étendues aux tarifs fournisseurs et avec des remises par défaut par fournisseur.purchase_open_qty: les commandes et lignes qui ont encore des quantités en attente de réception ou de facturation.purchase_last_price_info: fournisseur, date et prix du dernier achat confirmé, directement sur la fiche produit.purchase_default_terms_conditions: des conditions générales d'achat par défaut, par société et par fournisseur.
Ce que ces modules ajoutent à l'instance
| Module | Modèles étendus | Champs | Menus | Version |
|---|---|---|---|---|
purchase_order_type | 3 | 20 | 1 | 18.0.1.1.2 |
purchase_last_price_info | 2 | 20 | 0 | 18.0.2.0.0 |
purchase_exception | 4 | 16 | 1 | 18.0.1.1.0 |
purchase_default_terms_conditions | 4 | 8 | 0 | 18.0.1.0.0 |
purchase_open_qty | 2 | 5 | 0 | 18.0.1.0.1 |
purchase_triple_discount | — | — | 0 | — |
Aucun ne crée de modèle : ce sont tous des enrichissements de la commande d'achat et de la fiche produit. Ils s'installent et se retirent sans laisser de structure derrière eux — à l'exception des séquences créées par le module de types.
purchase_order_type : distinguer les natures d'achat
Le module ajoute un type sur la commande d'achat, et le dépôt en donne les exemples : Regular, Blanket (contrat-cadre), Contract, Planned.
| Ce que le type porte | Ce que cela règle |
|---|---|
| Conditions de paiement par défaut | Un contrat-cadre et un achat ponctuel n'ont pas les mêmes délais |
| Incoterm par défaut | Lever l'ambiguïté sur qui paie le transport, par nature d'achat |
| Séquence de numérotation dédiée | Des séries distinctes, lisibles dans la comptabilité |
| Filtrage et regroupement | Savoir ce que pèse chaque nature d'achat |

La séquence par type est le point qui compte le plus en comptabilité : des contrats-cadres numérotés dans leur propre série se retrouvent au contrôle, alors que mélangés à l'ensemble ils sont indistinguables.
Limite répertoriée : le dépôt suggère lui-même d'ajouter une configuration par défaut rattachée aux types. Aujourd'hui, les valeurs par défaut sont celles listées ci-dessus, pas une configuration complète.
Le pendant côté vente existe et fonctionne de la même manière — voir les types de commande de vente.
purchase_exception : le module des imports massifs
C'est l'implémentation de base_exception pour les achats, et le dépôt précise son terrain de prédilection : les imports massifs de commandes d'achat, où les erreurs de données sont fréquentes.
Le mécanisme : des règles écrites en domaine ou en code Python, évaluées automatiquement sur les commandes et leurs lignes, avant ou pendant la confirmation. Les anomalies s'affichent à l'écran, et la confirmation est bloquée — ou autorisée exceptionnellement selon les droits de l'utilisateur.

Les cas qui justifient ce module dans un négoce : un prix unitaire à zéro, une date de livraison antérieure à la commande, un fournisseur sans conditions de paiement, une quantité aberrante issue d'un fichier mal cadré.
La même mise en garde que pour le socle : les règles en code Python passent par safe_eval, avec le risque de sécurité que le dépôt de base_exception signale. Privilégiez le mode domaine, et réservez la création de règles aux administrateurs.
Les remises en cascade côté fournisseur
purchase_triple_discount applique à l'achat la logique que account_invoice_triple_discount applique à la facture : jusqu'à trois remises successives en cascade par ligne de commande.
Avec deux extensions propres à l'achat, et elles sont décisives :
- La logique s'étend aux lignes de tarif fournisseur — les remises ne sont pas à ressaisir à chaque commande.
- Des remises par défaut se définissent sur la fiche de chaque fournisseur.
Le cas d'usage que décrit le dépôt est exactement celui du négoce : un fournisseur qui pratique une remise de gamme, puis une remise quantité, puis une remise commerciale. Les trois doivent apparaître distinctement pour que la négociation annuelle soit discutable.
Rappel du calcul, qui provoque toujours la même discussion : les remises sont composées, pas additionnées. 10 % puis 10 % font 19 %. Voir les sept conforts de facturation.
Les trois modules de suivi
purchase_open_qty : qu'est-ce qui reste à recevoir ?
Cinq champs, et une réponse à une question qu'Odoo ne donne pas d'un coup d'œil : parmi toutes les commandes d'achat, lesquelles ont encore des quantités en attente de réception ou en attente de facturation ?
Le module ajoute des champs calculés et des filtres de recherche sur les commandes et sur leurs lignes. Les deux usages réels :
- Relancer les fournisseurs sur ce qui n'est pas arrivé, sans parcourir les commandes une par une.
- Rapprocher les factures : une réception sans facture est une charge non comptabilisée, donc un résultat flatté.
Le second rejoint directement le rapprochement à trois voies : c'est la quatrième anomalie, celle qui ne saute pas aux yeux parce que rien ne bloque.
purchase_last_price_info : le dernier prix, sur la fiche produit
Le module affiche sur la fiche produit le fournisseur, la date et le prix unitaire du dernier achat confirmé.
C'est vingt champs pour une information que les acheteurs cherchent plusieurs fois par jour, et qu'ils allaient chercher dans l'historique des commandes. Sur un catalogue de plusieurs milliers de références, le gain de temps est réel et quotidien.
purchase_default_terms_conditions : les mentions contractuelles
Des conditions générales d'achat par défaut, définies au niveau de la société et/ou d'un fournisseur spécifique, reportées automatiquement dans le champ Notes des commandes.
L'intérêt est de standardiser les mentions qui doivent figurer sur les bons de commande envoyés aux fournisseurs — délais, garanties, conditions de paiement. Sans lui, elles reposent sur la mémoire de celui qui saisit.
Dans quel ordre les déployer
| Priorité | Module | Déclencheur |
|---|---|---|
| 1 | purchase_order_type | Deux natures d'achat ou plus dans la même instance |
| 2 | purchase_open_qty | Dès qu'il y a des relances fournisseurs à faire |
| 3 | purchase_last_price_info | Dès qu'un acheteur consulte l'historique |
| 4 | purchase_triple_discount | Si vos fournisseurs pratiquent des remises en chaîne |
| 5 | purchase_exception | Avant tout import massif de commandes |
| 6 | purchase_default_terms_conditions | Quand les mentions contractuelles reposent sur la mémoire |
La cinquième ligne porte l'avertissement qui compte : installer les règles de blocage après un import massif ne sert à rien — les commandes fautives sont déjà confirmées. C'est le cas où l'ordre d'installation change le résultat.
Identité technique
| Module | Version | Licence | Dépend de |
|---|---|---|---|
purchase_order_type | 18.0.1.1.2 | AGPL-3 | purchase |
purchase_exception | 18.0.1.1.0 | AGPL-3 | base_exception, purchase |
purchase_triple_discount | — | AGPL-3 | purchase |
purchase_open_qty | 18.0.1.0.1 | AGPL-3 | purchase_order_line_menu, purchase_stock |
purchase_last_price_info | 18.0.2.0.0 | AGPL-3 | purchase |
purchase_default_terms_conditions | 18.0.1.0.0 | AGPL-3 | purchase |
Les six viennent du dépôt OCA purchase-workflow, branche 18.0, qui compte 106 modules documentés. Ils font partie de nos packs négoce (75 modules) et industrie (72), au-delà du socle commun.
Questions fréquentes
À quoi sert un type de commande d'achat ?
À distinguer les natures d'achat — Regular, Blanket (contrat-cadre), Contract, Planned — avec des conditions de paiement et un incoterm par défaut, et surtout une séquence de numérotation dédiée par type. C'est cette dernière qui rend les contrats-cadres identifiables en comptabilité.
Quand installer purchase_exception ?
Avant tout import massif de commandes d'achat — c'est le terrain que le dépôt cite explicitement, parce que les erreurs de données y sont fréquentes. Installé après, il ne sert à rien : les commandes fautives sont déjà confirmées.
Les trois remises d'achat sont-elles additionnées ?
Non, elles sont composées : la deuxième s'applique sur le montant déjà diminué par la première. 10 % puis 10 % donnent 19 %. Le module étend par ailleurs cette logique aux lignes de tarif fournisseur et permet des remises par défaut sur la fiche fournisseur.
Comment savoir ce qui reste à recevoir d'un fournisseur ?
Avec purchase_open_qty, qui ajoute des champs calculés et des filtres de recherche sur les commandes et leurs lignes pour les quantités en attente de réception ou de facturation. Cinq champs, et une réponse qu'Odoo ne donne pas d'un coup d'œil.
Où voir le dernier prix payé pour un produit ?
Sur la fiche produit elle-même, avec purchase_last_price_info : fournisseur, date et prix unitaire du dernier achat confirmé. C'est une information que les acheteurs allaient chercher dans l'historique des commandes plusieurs fois par jour.
Se faire accompagner
Un seul point de cette fiche est irréversible : installer purchase_exception après un import massif ne rattrape pas les commandes déjà confirmées. Et les règles en code Python posent le même risque de sécurité que le socle — à réserver aux administrateurs, en mode domaine par défaut.
Nous cadrons les types de commande avec vos natures d'achat réelles, puis nous écrivons les règles de blocage sur vos données avant tout import. Voir les prestations d'Atalios Consulting ou demander un rappel.
Pour aller plus loin
- Ventes : types de commande, workflows et blocages
- La gestion des achats et des fournisseurs dans Odoo
- base_exception : des règles de blocage métier
En résumé
Six modules pour encadrer les achats : une typologie avec séquence dédiée, des blocages avant confirmation, les remises en cascade propagées aux tarifs fournisseurs, et le suivi de ce qui reste à recevoir. Un seul ordre compte : les règles de blocage avant l'import massif. Parlons de vos achats.