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.
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).
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.
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.
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 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.
procurement.group vs. stock.reference : ce qui change dans le MTO Odoo 19
| Aspect | Odoo 18 (procurement.group) | Odoo 19 (stock.reference) |
|---|---|---|
| Modèle | procurement.group | stock.reference |
| Champ de liaison sur stock.move | group_id (Many2one) | reference_id (Many2one) |
| Traçabilité commande de vente | Via group_id.sale_id (indirect) | Via reference_id.sale_id ou reference_id.get_source_document() |
| Lien OF → CV | procurement.group partagé entre CV et OF | stock.reference explicite avec res_model='sale.order' |
| Routage d'approvisionnement | Inté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 values | Reçoit reference_id dans le dict values |
| Custom _run_manufacture() | Crée un OF lié via procurement_group_id | Crée un OF lié via reference_id |
| Routes multi-étapes | Tous les mouvements partagent un group_id | Chaque mouvement porte son propre reference_id ; la chaîne est explicite |
| Extensibilité | Surchargé ; ajouter des champs risque des effets secondaires | Propre ; étendre stock.reference sans effets secondaires d'approvisionnement |
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.
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)
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)
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
group_id sur stock.move et stock.rule dans votre code—remplacer par reference_idprocurement.group par stock.referenceprocurement.group vers stock.reference via un script pre-migrategroup_idsearch() qui filtrent sur les champs de procurement.group3 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.
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.production où reference_id est nul mais origin contient une référence CV. Cela attrape les orphelins avant qu'ils n'arrivent en atelier.
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.
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.
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 :
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 ? »
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.
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.
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.
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