Un projet Odoo finit toujours par la même conversation. « Et les données, on fait comment ? » On en parle au cadrage, on rassure tout le monde, on passe à la suite. Puis ça revient trois semaines avant le Go Live. À ce moment-là, ça déborde sur tous les autres lots et le calendrier prend cher.
Dans l'article de mars sur la migration, on parlait du pilotage projet : périmètre, équipes, décisions. Cette fois je voudrais descendre d'un cran. Là où ça coince vraiment quand on charge des CSV à 2h du matin pour rattraper le retard.
Les External IDs sont la pièce qu'on oublie
Première erreur qu'on voit dans neuf projets sur dix. La doc Odoo le dit clairement : pour gérer les relations entre tables, on passe par les External IDs. C'est l'identifiant unique d'un enregistrement, celui qui permet de lier une facture à un client, une ligne de commande à un produit, un mouvement de stock à un emplacement. La doc va même jusqu'à recommander de préfixer l'External ID avec le nom de l'application source pour éviter les collisions.
En pratique, ce qu'on voit c'est l'inverse. Quelqu'un exporte les clients depuis le vieil ERP avec leur code interne « C00123 », importe ça tel quel dans Odoo, puis se rend compte au moment d'importer les factures que rien ne se rattache. Pourquoi ? Parce qu'à l'import des clients, la colonne External ID n'a pas été remplie, ou pas dans le bon format. Odoo a créé les clients, leur a attribué un ID interne aléatoire, et le fichier de factures ne sait plus comment retrouver ces clients.
On refait l'import, en nettoyant les doublons au passage. Une journée de perdue.
Cas particulier qui mérite qu'on s'y attarde : les External IDs des données standard d'Odoo (taxes, comptes de plan comptable français, unités de mesure) sont fixés par les modules core. Si vous importez une facture avec une référence à account.tax_15, alors qu'Odoo nomme cette taxe l10n_fr.tax_normale_20, l'import passe en erreur ou pire, lie à la mauvaise taxe et personne ne s'en rend compte tout de suite. Il faut prendre trente minutes pour exporter les External IDs d'Odoo (taxes, comptes, devises, journaux) et les mapper proprement vers les codes du système source. Trente minutes au début du projet qui en font gagner trois jours à la fin.
Bref, si on vous présente un plan de migration Odoo sans jamais évoquer ce mécanisme, il y a un problème.
L'ordre est plus important que le contenu
On peut avoir le fichier le plus propre du monde. Si on l'importe au mauvais moment, on se retrouve avec des relations cassées partout.
L'ordre minimal qu'on applique sur un projet standard :
- Plan comptable, taxes, journaux (s'ils ne sont pas déjà en place via l10n_fr)
- Sociétés et utilisateurs
- Partners : clients, fournisseurs, contacts, avec toutes leurs adresses
- Partners : contacts des Partners ci-dessus
- Produits
- Nomenclatures
Cette liste a l'air évidente. Elle l'est. Le piège, c'est qu'en pratique les équipes côté client veulent commencer par ce qui les intéresse. Le commercial veut ses prospects dans le CRM. La compta veut ses balances pour pouvoir lancer ses tests. Le magasinier veut ses stocks pour vérifier ses emplacements. Quand tout part en parallèle sans ordre maître, on découvre les dépendances en cours de route et on refait des imports.
Un détail qui change tout : on importe d'abord en environnement de test, jamais directement en production. Et on documente l'ordre exact des fichiers chargés, avec leur version, leur date, leur résultat. Sans ça, le jour du vrai Go Live, on improvise. Et improviser sur une bascule ERP c'est exactement ce qu'on ne voudrait jamais faire.
Les écritures comptables, ce que les fichiers Excel ne disent pas
C'est probablement la partie qui pose le plus de problèmes. Pas parce que c'est techniquement compliqué : c'est juste de la saisie comptable. Mais parce que les soldes ouverts dépendent de tellement de choses qu'on découvre au dernier moment.
Quelques exemples qu'on retrouve à chaque projet.
Les écritures de lettrage. Côté client comme côté fournisseur, on importe des factures non soldées et des règlements partiels. Si on ne reconstitue pas le lettrage en comptabilité auxiliaire, on se retrouve avec des soldes globalement justes mais des relances client incompréhensibles. Le client B doit 12 000 € : six factures, trois règlements, des avoirs, et personne ne sait dire ce qui solde quoi. Le service comptable se retrouve à devoir relire l'historique papier pour reconstituer ce qui aurait dû être migré proprement.
La devise des écritures. Sur les comptes en devise, on importe le montant en devise originale ET le montant en euros. Si on ne le fait pas, Odoo recalcule au taux du jour et casse tout l'historique des écarts de change. La compta se retrouve avec un bilan qui ne ressemble à rien comparé au bilan validé avant migration.
L'année N-1, parfois N-2. Question quasi systématique en réunion : « on veut comparer N à N-1 ». Pour avoir des comparatifs propres dès la première année, il faut importer les écritures cumulées mensuelles de N-1 par compte. C'est de la donnée en plus qui ne sert qu'au reporting, et qui n'est presque jamais prévue au cadrage. À chiffrer dès le début.
Et les unités, on en fait quoi ?
Petite parenthèse, parce que c'est un sujet qui n'a l'air de rien et qui dévore plus de temps qu'on imagine.
Sur l'ancien système, le produit « Farine T65 » se vend au sac de 25 kg. À l'achat, il se commande à la tonne. En stock, on suit le kilo. Ça fait trois unités pour un même article. Odoo gère ça via les UoM (units of measure) avec catégories et facteurs de conversion. Mais ça suppose que la catégorie « Poids » soit bien configurée, et surtout que chaque écriture importée référence la bonne unité.
Le piège, c'est l'import des commandes ouvertes. Si dans le fichier source la quantité est en kg mais que l'unité par défaut du produit dans Odoo est le sac, le stock part en sucette dès le Go Live. On a vu un cas concret là-dessus sur un multi-sites : un import qui mélangeait kg et sacs sur la même colonne pour un produit pivot. Il a fallu détecter, corriger, et réimporter. Vingt-quatre heures de perdues sur un Go Live qui en avait déjà soixante-douze de retard.
Mention spéciale aux articles vendus en lot (le carton de 12, la palette de 80) où la quantité commandée peut être exprimée soit en unité élémentaire, soit en unité d'emballage. Le client final, lui, voit toujours la même ligne sur sa facture. Mais derrière, le stock se comporte différemment selon ce qui a été importé.
Les imports qui passent en silence
Le truc le plus piégeux d'Odoo en import : un fichier qui passe en succès alors qu'il y a un problème.
Exemple vécu. On importe 4 000 contacts depuis un fichier Excel. Odoo annonce « 4 000 enregistrements importés ». On ferme l'écran, on valide. Trois mois plus tard, le commercial signale qu'il manque des emails dans le CRM. On vérifie : sur 4 000 contacts, 1 200 n'ont pas d'email. Pourquoi ? Parce que la colonne email du fichier contenait des sauts de ligne dans certaines cellules, et Odoo a interprété ces sauts comme des séparateurs de champs. Aucune erreur, juste des valeurs vides.
Ce genre de truc arrive plus souvent qu'on voudrait. Les imports CSV souffrent d'un nombre incroyable de petits problèmes silencieux. Encodage non-UTF-8 qui transforme « é » en « ?? ». Virgules dans les noms d'entreprise qui décalent les colonnes. Dates en format anglo-saxon qui se chargent comme du texte au lieu de date. Champs booléens qui prennent « OUI » alors qu'Odoo attend « True ». La liste est longue, et chaque problème peut passer sans déclencher d'erreur visible.
La règle pratique qu'on s'impose : tout import volumineux est suivi d'un audit. On compte les lignes importées par rapport aux lignes du fichier, on échantillonne cinquante enregistrements au hasard, on vérifie que les valeurs sont bien celles attendues. C'est tatillon, c'est lent, mais c'est le seul moyen de ne pas découvrir un problème six mois plus tard.
Quand l'import-CSV de l'interface ne suffit plus
L'interface d'import d'Odoo est très bien pour ce qu'elle fait : recharger des données structurées dans une table. Mais elle a deux limites pratiques.
D'abord, la performance. Au-delà de 50 000 lignes, on commence à voir des timeouts et des coupures pénibles à reprendre. Pour ce genre de volumes, on passe par l'API XML-RPC ou JSON-RPC (la nouvelle API JSON2 annoncée sur la roadmap Odoo 20 va simplifier ce travail, mais on n'y est pas encore en mai 2026, et il faudra attendre les premiers retours pour savoir si elle change vraiment la donne sur les imports massifs).
Ensuite, la logique métier. Si on doit importer 10 000 factures et appliquer un workflow particulier (affecter une analytique selon le code projet, déclencher une validation automatique, recalculer un champ stocké), l'import CSV ne le fera pas. C'est un script Python via la méthode load() de l'ORM, ou un script qui s'attache à un cron temporaire, qui prendra le relais.
Beaucoup d'intégrateurs vendent du script comme la solution miracle. C'est plus puissant, oui. C'est aussi plus long à développer, à tester, à maintenir, et à débugger quand quelque chose passe mal. Pour des données simples et bien structurées, l'interface fait largement le job. Pas besoin d'aller chercher du Python si un CSV propre suffit.
Sur les outils, et sur ce qu'on fait pour nos clients
Un dernier point sur les outils, parce qu'on nous pose souvent la question.
« Est-ce que vous avez un outil maison pour automatiser tout ça ? » Réponse : non, et c'est volontaire. Chaque migration a sa logique, ses contraintes, ses cas particuliers. Un outil qui marcherait pour 80 % des cas serait dangereux pour les 20 % qui restent, ceux qui nous appellent. On préfère un kit de scripts et de templates qu'on adapte projet par projet, plutôt qu'une solution boîte noire qui passe à côté du vrai problème métier.
Ce qu'on a en revanche, c'est ce kit interne. Il contient principalement : un extracteur d'External IDs Odoo standard pour récupérer les références natives (taxes, plans comptables, devises, journaux) ; un générateur de templates d'import par modèle, déjà mappé avec les colonnes obligatoires et les pièges connus ; un script d'audit post-import qui compare lignes attendues et lignes effectivement créées. Ça mâche le travail, ça ne le fait pas à notre place.
Si vous êtes en phase d'analyse pour une migration ERP, ou si vous avez un Go Live qui s'approche et que la donnée vous inquiète, venez nous en parler.Le formulaire est ici, et on regarde votre cas avant de chiffrer quoi que ce soit.
Sources
1. Export and import data (Odoo 19.0 documentation) « To manage relations between tables, use the External ID facilities of Odoo. » Lire la doc officielle
2. Migrer vers Odoo : ce que personne ne vous dit avant de signer (Nexelans, 13 mars 2026) « La reprise de données est systématiquement sous-estimée. » Lire l'article