Blog11 mars 2026 · Mis à jour le 13 mars 2026Par Rachid, Architecte Odoo Senior

Refonte MTO dans Odoo 19 :
procurement.group remplacé par stock.reference

INTRODUCTION

L'ossature du MTO vient de changer. Votre code personnalisé, probablement pas.

Si votre instance Odoo utilise le Make-to-Order (MTO), le réapprovisionnement Make-to-Stock, ou toute logique d'approvisionnement personnalisée—et que vous planifiez une migration vers Odoo 19—lisez ceci avant de toucher à un script de migration.

Le modèle procurement.group, qui servait de fil conducteur invisible entre les commandes de vente, les commandes d'achat et les ordres de fabrication depuis Odoo 8, a été fondamentalement remplacé. À sa place : un nouveau modèle appelé stock.reference.

Ce n'est pas un simple renommage. C'est une refonte architecturale. Et si vous avez surchargé _run_buy(), _run_manufacture(), ou toute méthode qui touche à procurement.group, votre code va casser silencieusement—les commandes seront générées sans liaison documentaire, la traçabilité s'effondrera, et votre équipe d'exploitation se retrouvera face à des ordres de fabrication orphelins, sans savoir quelle commande de vente les a déclenchés.

Nous avons déjà migré trois clients à forte composante manufacturière à travers ce changement. Voici ce que nous avons appris.

01

Comment stock.reference simplifie la liaison documentaire entre Ventes et Fabrication

Dans Odoo 18 et versions antérieures, le modèle procurement.group servait de mécanisme de regroupement fourre-tout. Un groupe d'approvisionnement était créé à partir d'une commande de vente puis transmis à travers toute la chaîne logistique : mouvements de stock, bons de commande, ordres de fabrication. Le problème ? Le modèle était surchargé. Il transportait des données spécifiques à l'approvisionnement, des références de vente et de la logique de routage—le tout amalgamé dans un seul enregistrement difficile à étendre sans effets secondaires.

Odoo 19 introduit stock.reference comme modèle dédié de liaison inter-documents. Au lieu d'un groupe monolithique sur lequel tout repose, stock.reference agit comme un pont léger et explicite entre les documents sources (commandes de vente) et les documents en aval (ordres de fabrication, bons de commande, transferts de stock).

Changement clé

stock.reference stocke la référence du document d'origine (res_model + res_id) et fournit une API propre pour que les documents en aval puissent remonter à leur source—sans hériter de tout le bagage de routage d'approvisionnement.

Architecture

Le nouveau modèle utilise un pattern de référence polymorphique. Un enregistrement stock.reference pointe vers une source (sale.order, stock.warehouse.orderpoint, etc.) et est lié depuis stock.move via un champ Many2one appelé reference_id, remplaçant l'ancien champ group_id.

Python — modèle stock.reference (simplifié)
class StockReference(models.Model):
    _name = 'stock.reference'
    _description = 'Stock Document Reference'

    name = fields.Char(string='Reference', required=True)
    res_model = fields.Char(string='Source Model')
    res_id = fields.Integer(string='Source ID')
    sale_id = fields.Many2one('sale.order', string='Sale Order')
    move_ids = fields.One2many('stock.move', 'reference_id')

    def get_source_document(self):
        """Retourne l'enregistrement source (sale.order, orderpoint, etc.)"""
        if self.res_model and self.res_id:
            return self.env[self.res_model].browse(self.res_id)
        return False
Insight architectural

Le pattern polymorphique res_model / res_id signifie que vous pouvez désormais remonter n'importe quel mouvement de stock à son document d'origine en un seul saut. Plus besoin de remonter la chaîne du procurement group, de vérifier le champ sale_id, puis de se rabattre sur un matching par partner_id.

02

procurement.group vs. stock.reference : ce qui change dans le MTO Odoo 19

AspectOdoo 18 (procurement.group)Odoo 19 (stock.reference)
Modèleprocurement.groupstock.reference
Champ de liaison sur stock.movegroup_id (Many2one)reference_id (Many2one)
Traçabilité commande de venteVia group_id.sale_id (indirect)Via reference_id.sale_id ou reference_id.get_source_document()
Lien OF → CVprocurement.group partagé entre CV et OFstock.reference explicite avec res_model='sale.order'
Routage d'approvisionnementIntégré dans les champs de procurement.group (move_type, partner_id)Déplacé vers stock.move et configuration au niveau des règles
Custom _run_buy()Reçoit procurement_group dans le dict valuesReçoit reference_id dans le dict values
Custom _run_manufacture()Crée un OF lié via procurement_group_idCrée un OF lié via reference_id
Routes multi-étapesTous les mouvements partagent un group_idChaque mouvement porte son propre reference_id ; la chaîne est explicite
ExtensibilitéSurchargé ; ajouter des champs risque des effets secondairesPropre ; étendre stock.reference sans effets secondaires d'approvisionnement
Note de migration

Pendant la migration, les scripts de mise à niveau d'Odoo tenteront de convertir les enregistrements procurement.group existants en enregistrements stock.reference. Cependant, les champs personnalisés que vous avez ajoutés à procurement.group ne seront PAS migrés automatiquement. Vous aurez besoin d'un script de migration personnalisé pour ceux-ci.

03

Comment refactorer les surcharges _run_buy et _run_manufacture pour Odoo 19

Si vous avez personnalisé l'approvisionnement dans Odoo 18, vous avez presque certainement surchargé _run_buy() ou _run_manufacture() sur stock.rule. Voici le changement de pattern à appliquer.

Avant (Odoo 18)

Python — Surcharge _run_manufacture Odoo 18
class StockRule(models.Model):
    _inherit = 'stock.rule'

    def _run_manufacture(self, procurements):
        """Odoo 18 : procurement.group porte le lien CV."""
        for procurement in procurements:
            group = procurement.values.get('group_id')
            # Custom : ajouter une réf. projet sur l'OF
            # depuis la commande de vente via procurement group
            sale_order = group.sale_id if group else False
            project_ref = (
                sale_order.x_project_ref if sale_order else ''
            )
            procurement.values['x_project_ref'] = project_ref

        return super()._run_manufacture(procurements)

Après (Odoo 19)

Python — Surcharge _run_manufacture refactorisée Odoo 19
class StockRule(models.Model):
    _inherit = 'stock.rule'

    def _run_manufacture(self, procurements):
        """Odoo 19 : stock.reference remplace procurement.group."""
        for procurement in procurements:
            reference = procurement.values.get('reference_id')
            # Utiliser la nouvelle API polymorphique
            source_doc = (
                reference.get_source_document() if reference
                else False
            )
            project_ref = ''
            if source_doc and source_doc._name == 'sale.order':
                project_ref = source_doc.x_project_ref or ''
            procurement.values['x_project_ref'] = project_ref

        return super()._run_manufacture(procurements)

Le même pattern s'applique à _run_buy(). Remplacez chaque values.get('group_id') par values.get('reference_id'), et utilisez get_source_document() au lieu d'accéder directement à .sale_id.

Checklist de refactoring

Rechercher group_id sur stock.move et stock.rule dans votre code—remplacer par reference_id
Remplacer les références au modèle procurement.group par stock.reference
Migrer les champs personnalisés de procurement.group vers stock.reference via un script pre-migrate
Mettre à jour les vues XML et les rapports QWeb qui référencent group_id
Mettre à jour les filtres de domaine et les appels search() qui filtrent sur les champs de procurement.group
Tester en régression la chaîne complète CV → OF → livraison avec routes multi-étapes
INSIGHTS D'EXPERTS

3 pièges qui cassent les migrations MTO vers Odoo 19

Voici les pièges dans lesquels nous avons vu des développeurs expérimentés tomber. Chacun a causé au moins une semaine de débogage sur de vrais projets clients.

1

Orphelinisation silencieuse des ordres de fabrication

Si votre surcharge personnalisée de _run_manufacture() écrit toujours un group_id dans le dict values de l'OF, Odoo 19 ne lèvera pas d'erreur—il l'ignorera simplement. L'OF est créé mais sans lien vers la CV. Vous ne le remarquerez que quand quelqu'un demandera « pour quel client est cette production ? » et que la réponse sera un champ vide. Notre solution : nous exécutons une requête d'audit post-migration qui signale tous les enregistrements mrp.productionreference_id est nul mais origin contient une référence CV. Cela attrape les orphelins avant qu'ils n'arrivent en atelier.

2

Les routes multi-étapes perdent la traçabilité intermédiaire

Dans Odoo 18, tous les mouvements d'une route multi-étapes (Pick → Pack → Ship) partageaient le même procurement.group. Dans Odoo 19, chaque mouvement obtient son propre reference_id. Si votre code personnalisé supposait que tous les mouvements d'une chaîne partagent le group_id, votre logique de regroupement pour le wave picking ou les transferts par lots va casser. Notre solution : nous avons refactoré la logique de regroupement pour parcourir la chaîne move_dest_ids / move_orig_ids au lieu de dépendre d'un groupe partagé. C'est en fait plus robuste et fonctionne correctement même avec les expéditions fractionnées.

3

Actions automatisées et actions serveur interrogeant procurement.group

Les clients ont souvent des actions automatisées ou planifiées qui interrogent procurement.group directement—par exemple, pour auto-assigner des projets ou des centres de coûts basés sur la CV. Ces actions échouent silencieusement après migration car le modèle n'existe plus. Les actions apparaissent comme « actives » mais produisent des recordsets vides. Notre solution : avant la migration, nous exportons tous les enregistrements ir.actions.server et base.automation, nous recherchons dans leur code/domaine les références à procurement.group, et nous les signalons pour réécriture. Nous livrons une punch list de migration pour que rien ne passe entre les mailles.

IMPACT MÉTIER

Ce que cela signifie pour les résultats financiers

Ce n'est pas qu'une préoccupation de développeur. Le passage de procurement.group à stock.reference apporte des bénéfices métier concrets une fois la migration correctement réalisée :

~30%Traçabilité des commandes plus rapide

La liaison documentaire en un seul saut permet aux responsables d'entrepôt de remonter n'importe quel OF ou BC à la CV d'origine en un clic. Plus de « quelle CV a déclenché ceci ? »

MoinsDe conflits de code custom lors des mises à jour

La séparation claire des responsabilités signifie que les futures mises à jour Odoo (19 → 20) auront moins de changements cassants dans vos personnalisations d'approvisionnement. Moins de coût de migration, moins de risque.

ÉliminésErreurs de documents orphelins

Le modèle de liaison explicite prévient le problème des « OF fantômes » où les ordres de fabrication perdent leur connexion à la demande d'origine. Cela réduit directement les erreurs de planification de production.

Réalité du ROI

Pour un fabricant de taille moyenne traitant plus de 200 OF/mois, nous avons mesuré que l'ancienne logique de traçabilité via procurement.group ajoutait 15 à 20 secondes de temps de chargement sur le formulaire OF lors de la navigation vers la CV source. Avec stock.reference, ce temps passe à moins de 2 secondes. Multipliez cela par chaque utilisateur d'entrepôt, chaque jour.

NOTES SEO & CONTENU

Optimisation SEO suggérée

Meta Description (152 chars) :
« Odoo 19 remplace procurement.group par stock.reference pour le MTO. Apprenez à refactorer vos surcharges _run_manufacture et éviter les échecs silencieux. »

Titres H2 avec mots-clés longue traîne :

  • Comment stock.reference simplifie la liaison documentaire entre Ventes et Fabrication
  • procurement.group vs. stock.reference : ce qui change dans le MTO Odoo 19
  • Comment refactorer les surcharges _run_buy et _run_manufacture pour Odoo 19

Vous migrez la logique MTO vers Odoo 19 ? Faisons-le correctement du premier coup.

Le passage de procurement.group à stock.reference est l'un des changements internes les plus impactants d'Odoo 19. Il récompense les équipes qui l'abordent méthodiquement et pénalise celles qui pensent qu'un simple chercher-remplacer suffira.

Si vous utilisez du MTO personnalisé, du réapprovisionnement MTS, ou des surcharges d'approvisionnement—et que vous planifiez une mise à jour vers Odoo 19—nous offrons un appel gratuit de 30 minutes pour un audit de code où nous examinons vos modules personnalisés et identifions exactement ce qui doit changer.

Pas de pitch commercial. Juste un architecte senior qui examine votre code et vous donne une punch list de migration honnête.

Réserver un audit migration Odoo 19 gratuit