Blog
Odoo Data Migration Checklist: Clean, Map, Validate Before Go-Live
A practical Odoo data migration checklist for SMBs: what to clean, how to map fields and external IDs, and how to reconcile balances before go-live.
- mid
- odoo
Most Odoo go-lives that go badly fail on data, not software. The short answer: decide what moves, clean it in the source, map it field by field with stable External IDs, rehearse the load in a test database until it repeats cleanly, and reconcile balances to the cent before anyone signs off.
This checklist follows that order. It applies to Odoo 17, 18 and 19, though menu names shift slightly between versions, so confirm against your own instance.
1. Decide what actually moves
Not everything deserves to come across. Before you touch a spreadsheet, sort your data into three piles:
- Migrate: active customers, vendors, products, open orders, open invoices and bills, opening balances.
- Archive: old transactions you only need for reference or audit. Keep them in the legacy system or a read-only export.
- Drop: dead contacts, discontinued products, test records.
Assign a business owner to each pile. Rand Group’s ERP migration checklist makes the same point: scope, data owners and retention needs come first, and the business, not IT alone, approves the decisions.
Be careful about over-cleaning. Deleting records that other history refers to creates orphans. Archive rather than delete when in doubt.
2. Clean in the source, not during the load
Fixing data mid-import produces files nobody can reproduce. Clean in the legacy system or a working copy, and write the rules down. A typical pass covers:
- Duplicate customers and vendors (same company, three spellings).
- Missing required fields: country, tax ID or VAT number where relevant, payment terms, units of measure.
- Inconsistent formats: phone numbers, country names versus ISO codes, product categories.
- Products with no cost, no unit, or conflicting variants.
- Orphaned records, such as contacts with no company or invoices pointing to deleted partners.
Treat customers, vendors and products as your master data. Every later transaction depends on them, so errors there multiply.
3. Map source to target, with External IDs
Create a mapping sheet: one row per source field, with the target Odoo field, any value translation, and the owner who approved it. Align it with how you will run Odoo, not with how the old system was structured. Chart of accounts, tax codes, payment terms and units of measure usually need translation tables.
Odoo’s export and import documentation gives the mechanics worth building around:
- External IDs. Give every record a unique External ID (the
idcolumn). It lets you re-import a corrected file without creating duplicates, and it lets related records point at each other. Two records sharing an External ID cause conflicts. - Relations. For fields like country or partner, reference the related record by name, Database ID or External ID, and use only one mechanism per field. Names break when two records share one, so prefer External IDs for anything ambiguous.
- Load order. Import the referenced records first (partners before invoices, products before stock).
- Dates and numbers. Use ISO 8601 dates (
YYYY-MM-DD) to avoid day-month swaps. Unrecognized currency symbols in number cells can break an import. - File format. Odoo accepts CSV, XLS and XLSX. If you save CSV from Excel, check the encoding.
- Templates. Where Odoo offers an import template, start from it. Otherwise export a few existing records and reuse those column names.
A small example of a partner file with External IDs:
id,name,is_company,country_id,vat
legacy_cust_0001,Northwind Supplies Ltd,TRUE,United Kingdom,GB123456789
legacy_cust_0002,Harbor Foods GmbH,TRUE,Germany,DE123456789
Prefix External IDs with the source system name so you can tell migrated records from native ones later.
4. Handle finance separately
Accounting is where mistakes are most expensive. Odoo’s accounting getting-started guide has a dedicated section on opening entries, covering when to transition, open invoices and bills, opening inventory, the opening trial balance, opening bank and credit card transactions, and a final validation. Each follows a prepare, validate, import pattern.
Practical points:
- Pick a clean cut-off date, typically a period end, and freeze legacy postings for that period.
- Open items, not history. Load open customer invoices and vendor bills individually, so ageing reports and payments work from day one.
- Make subledgers tie to the ledger. Receivables, payables and inventory totals should match the trial balance lines they feed.
- Test in a separate database while your existing accounting keeps running. Odoo’s guide recommends practicing the migration this way.
Involve your accountant before the final load. Tax treatment of opening balances differs by country, and that is their call, not ours.
5. Rehearse, then rehearse again
A single successful test import proves little. Plan at least two or three full mock migrations:
- Sample load. A few hundred records per object to catch mapping errors.
- Full load in a sandbox. Time it. Odoo’s docs warn that large files can time out and advise smaller batches, so find your batch size now, not on cutover night.
- Full load plus user testing. Real people run real flows: quote to cash, purchase to pay, a stock transfer, month-end reports.
Use Odoo’s import test step before each load, and note that imports are permanent. Filtering by creation date helps you find what an import touched if you need to unwind it.
Repeat until the process is scripted and gives the same result twice. Rand Group’s guidance is the same: repeat full mock migrations until the process is repeatable.
6. Validate and reconcile
Records that load are not necessarily records that are right. Reconcile against agreed tolerances, and write down every variance:
| Check | What to compare |
|---|---|
| Record counts | Source versus Odoo, per object |
| Trial balance | Debits equal credits; account totals match legacy |
| Receivables and payables | Open item totals versus ledger balances |
| Inventory | Quantity and value per product or location versus the count |
| Relationships | Spot-check partners, products, prices, tax mappings |
| Reports | Run the same report in both systems and compare |
Have the data owners sign off, not just the project lead.
7. Cutover day
Keep it boring:
- Back up the legacy system and agree go/no-go criteria in advance.
- Freeze legacy transactions.
- Load the final data in the rehearsed order.
- Reconcile again.
- Run smoke tests on the critical flows.
- Release to users, then monitor closely for the first weeks.
Keep the legacy system read-only for a defined period. You will need it for questions you did not anticipate.
Common mistakes
- Treating migration as a final-week task instead of a workstream from the start.
- Cleaning inside the import file, so the next attempt starts over.
- Using names instead of External IDs for relations.
- Migrating years of closed transactions nobody will read.
- Skipping the accountant’s review of opening balances.
- Only one rehearsal.
If you would like a second pair of eyes on your migration plan or a rehearsal run, we are happy to talk it through. No charge, no obligation: get in touch with Teknologia Solutions.
Sources: Odoo documentation, Export and import data (18.0); Odoo documentation, Accounting get started (19.0); Rand Group, ERP data migration checklist. Menu names and features change between Odoo versions and editions, and tax and accounting rules vary by country. Verify details against the primary sources and your own accountant before acting.