Introduction
Dans Odoo, les modèles déterminent la forme et l'organisation des données en base. Toute information métier — des demandes d'achat aux factures en passant par les mouvements de stock — est représentée par un modèle qui définit ses champs et ses relations.
Maîtriser les modèles Odoo est indispensable aussi bien pour les développeurs que pour les consultants fonctionnels. Ce sont eux qui matérialisent la logique métier, les contraintes et les dépendances entre données au sein de l'ERP.
Ici, nous nous intéressons au modèle purchase.order, un pilier du module Achats. Que vous développiez des modules, connectiez des systèmes externes ou paramétriez des flux d'approvisionnement, ce modèle fait souvent partie du cœur de la solution.
Qu'est-ce que le modèle purchase.order
Le modèle purchase.order représente les demandes de prix (RFQ) et les commandes d'achat. C'est l'entité centrale où l'on enregistre les besoins d'approvisionnement avant qu'ils ne deviennent des réceptions de marchandises ou des factures fournisseurs.
Dans le flux standard du module Achats, la création d'une RFQ génère un enregistrement purchase.order en brouillon. Après confirmation par le fournisseur ou approbation interne, l'enregistrement passe en état confirmé. Le même modèle gère donc aussi bien les RFQ que les commandes validées, grâce à un champ d'état qui pilote leur cycle de vie.
D'autres modules enrichissent ce modèle via l'héritage d'objets Odoo : l'inventaire ajoute la logique de réceptions et de pickings, la comptabilité rattache les factures fournisseurs, le module MRP peut générer des commandes depuis une nomenclature. Chaque module complète la structure sans dupliquer l'ossature centrale.
Champs clés du modèle
Voici les champs essentiels du modèle purchase.order. Les connaître facilite la personnalisation, le reporting et les intégrations.
1. name
Type : Char. Référence de commande (ex. PO00042). Généralement générée automatiquement et utilisée comme identifiant principal dans les listes et documents.
2. state
Type : Selection. Indique l'étape du cycle : draft (RFQ), sent, to approve, purchase (confirmée), done (réceptionnée/facturée), cancel. Ce champ conditionne les actions disponibles et les contrôles.
3. partner_id
Type : Many2one (res.partner). Le fournisseur/partenaire. Champ obligatoire servant de lien principal pour la facturation, les livraisons et les rapports fournisseurs.
4. partner_ref
Type : Char. Référence fournie par le fournisseur (numéro de commande fournisseur). Utile pour la correspondance entre docs et la réconciliation des réceptions et factures.
5. date_order
Type : Datetime. Date de la commande : date de création pour un brouillon, date de confirmation pour une commande validée. Sert au tri, aux rapports et comme base des dates de livraison attendues.
6. date_approve
Type : Datetime. Date d'approbation/confirmation. Positionnée lors du passage en état 'purchase'. Champ en lecture seule utilisé pour l'audit et le suivi.
7. order_line
Type : One2many (purchase.order.line). Les lignes de commande contenant produit, quantité, prix, et taxes. C'est le détail opérationnel de la commande.
8. amount_untaxed
Type : Float. Sous-total hors taxes, calculé depuis les lignes. Utilisé pour l'affichage et les exports financiers.
9. amount_tax
Type : Float. Montant total des taxes, calculé selon la configuration fiscale des lignes. Affiché sur la commande et reporté sur la facture fournisseur.
10. amount_total
Type : Float. Total TTC de la commande. Champ central pour la facturation et les rapports financiers.
11. currency_id
Type : Many2one (res.currency). Devise de la commande, héritée du fournisseur ou de la société. Tous les montants monétaires s'appuient sur cette devise.
12. origin
Type : Char. Document source (ex. commande de vente ou ordre de fabrication). Sert à tracer l'origine d'une commande et à comprendre les liens inter-modules.
13. dest_address_id
Type : Many2one (res.partner). Adresse de livraison. Par défaut l'adresse de la société si non renseignée. Importante pour le dropshipping lorsque les marchandises sont expédiées directement au client.
14. priority
Type : Selection. Priorité de la commande : Normal ou Urgent. Permet de trier et de faire remonter les commandes nécessitant un traitement prioritaire.
15. invoice_status
Type : Selection. État de facturation : no, to invoice, invoiced. Contrôle la visibilité de l'action « Créer la facture » et guide le suivi comptable.
16. invoice_count
Type : Integer. Nombre de factures fournisseurs liées. Champ calculé pour permettre un accès rapide aux factures associées.
17. invoice_ids
Type : One2many (account.move). Liens vers les factures fournisseurs. Permet le rapprochement trois-points (commande, réception, facture) et le suivi des paiements.
18. picking_ids
Type : One2many (stock.picking). Réceptions et mouvements logistiques associés. Apparent lorsque le module Inventaire est actif.
19. picking_count
Type : Integer. Nombre de pickings liés. Champ calculé pour l'affichage et l'ouverture rapide des réceptions.
20. create_date
Type : Datetime. Date/heure de création de l'enregistrement, gérée automatiquement par Odoo. Utile pour l'historique et les rapports.
21. write_date
Type : Datetime. Date/heure de la dernière modification, également automatique. Permet de savoir quand la commande a été mise à jour pour la dernière fois.
22. notes
Type : Text. Mentions légales, conditions ou instructions internes. Peut être imprimé sur les documents destinés au fournisseur.
23. company_id
Type : Many2one (res.company). Dans un environnement multi-sociétés, indique à quelle société appartient la commande et contrôle la visibilité et les règles d'accès.
24. user_id
Type : Many2one (res.users). L'acheteur ou l'utilisateur responsable. Servira dans les workflows d'approbation et l'attribution d'activités.
25. fiscal_position_id
Type : Many2one (account.fiscal.position). Position fiscale utilisée pour adapter la taxation en fonction du pays ou du régime particulier du fournisseur.
26. payment_term_id
Type : Many2one (account.payment.term). Conditions de paiement (ex. Net 30). Reportées lors de la création des factures fournisseurs.
27. display_name
Type : Char. Nom affiché calculé, souvent combinaison de la référence et du fournisseur. Utilisé dans les listes déroulantes many2one.
28. active
Type : Boolean. Indicateur d'archivage. À false, la commande est masquée des vues par défaut pour préserver l'historique sans suppression physique.
Utilisation du modèle dans les processus métier
1. De la RFQ à la commande d'achat
Le cycle typique démarre par une RFQ en brouillon : ajout de lignes, envoi au fournisseur et confirmation par ce dernier ou validation interne. Une fois confirmée, la RFQ devient une commande prête pour réceptions et facturation.
2. Réception fournisseur
À l'arrivée des marchandises, on crée une réception liée à la commande. Les pickings se rattachent automatiquement et les quantités réceptionnées mettent à jour le stock ; le coût du produit peut être actualisé depuis le prix d'achat.
3. Facture fournisseur
Depuis une commande confirmée, on génère les factures fournisseurs. Les lignes sont reprises depuis la commande et les conditions de paiement ainsi que la position fiscale sont transférées pour assurer cohérence comptable.
4. Dropshipping
Quand une commande client engendre un achat, le champ origin conserve le lien vers la vente et dest_address_id est réglé sur l'adresse du client afin que le fournisseur expédie directement au destinataire final.
5. Fabrication et MRP
Le module de fabrication peut déclencher des commandes d'achat pour approvisionner les composants nécessaires. L'origine relie la commande au bon de fabrication, intégrant le modèle purchase.order dans le cycle procure-to-pay.
Comment les développeurs étendent ce modèle
Les développeurs étendent purchase.order via plusieurs approches, l'héritage de modèle étant la plus courante.
Héritage de modèle
Déclarez _inherit = 'purchase.order' pour ajouter des champs, surcharger des méthodes ou ajouter des contraintes. L'héritage permet d'apporter des modifications encapsulées dans votre module sans toucher au cœur, facilitant les mises à jour.
Ajout de champs
Définissez des champs supplémentaires dans votre modèle hérité en choisissant le type adapté : Char, Many2one, Boolean, Integer, Text, Selection. Pensez aux champs dépendants de la société pour les contextes multi-company.
Extensions Python
Surchargez des méthodes comme button_confirm, create ou write pour insérer de la logique métier. Appelez super() pour préserver le comportement existant et faites attention aux champs calculés et à leurs dépendances.
Odoo Studio
Odoo Studio permet d'ajouter des champs sans écrire de code, pratique pour des ajustements rapides. Pour des logiques complexes ou une maintenance à long terme, préférez des modules personnalisés. Le modèle purchase.order est aussi accessible via XML-RPC et JSON-RPC pour les intégrations.
Bonnes pratiques
- Respectez l'état de la commande à chaque étape : ne sautez pas les transitions ni les contrôles d'activation.
- Enregistrez partner_ref lorsque le fournisseur communique sa référence : cela facilite le rapprochement des réceptions et des factures.
- Conservez le champ origin pour tracer l'origine des commandes — indispensable en dropshipping et pour la traçabilité des flux MRP.
- Pour les intégrations API, utilisez XML-RPC ou JSON-RPC et mappez soigneusement les identifiants externes avec purchase.order pour éviter les doublons.
- Pour les champs personnalisés, préfixez-les par
x_ou avec le nom de votre module afin de minimiser les risques de conflit lors des montées de version Odoo.
Erreurs fréquentes
- Modifier une commande confirmée sans vérifier l'état peut provoquer des incohérences. Respectez les règles métier : créez une nouvelle commande ou utilisez le workflow prévu.
- Ne pas confondre partner_id et dest_address_id : le premier désigne le fournisseur, le second l'adresse de livraison (utile en dropshipping).
- Surcharger
button_confirmsans appelersuper()peut casser des comportements attendus et compliquer les mises à jour futures. - Ajouter des champs obligatoires sans valeur par défaut provoquera des erreurs lors d'upgrades sur des commandes existantes : fournissez des valeurs ou des scripts de migration.
- Oublier de définir currency_id pour les fournisseurs multi-devises entraîne des montants erronés et des problèmes de facturation : vérifiez la devise dès la création.
Conclusion
Le modèle purchase.order est au cœur du module Achats. Il centralise RFQ et commandes confirmées ; connaître ses champs et son extensibilité facilite la configuration, la personnalisation et l'intégration d'Odoo.
Que vous cartographiez des processus d'achats ou développiez des modules, une bonne compréhension de purchase.order vous évitera bien des erreurs et des retards.
Besoin d'aide pour votre implémentation Odoo ?
Dasolo accompagne les entreprises pour implémenter, personnaliser et optimiser Odoo. Nous sommes spécialisés en intégrations API et développement Odoo, avec une solide expérience des modèles comme purchase.order.
Si vous avez besoin d'aide pour votre implémentation Odoo, vos modules personnalisés ou vos intégrations, nous pouvons vous accompagner. Demandez une démonstration pour discuter de votre projet.