ERP migration checklist

Migration Checklist: Moving to Odoo ERP

An exhaustive 8-phase punch list for moving chart of accounts, opening balances, stock, BOMs, multi-currency, and AP/AR into Odoo ERP via base_import.import, XML-RPC, and the ORM load() method.

152 tasks 8–24 weeks typical Updated May 27, 2026
Odoo ERP
Chart of Accounts
Customers
Vendors
Items
Transactions
Inventory
0 of 152 tasks complete

Phase 0

Decide & Plan

Lock scope, deployment shape, edition, and localization before any data moves.

  • Risk if skipped: Picking Odoo Online and then discovering you need a custom localization module or server action forces a re-platform mid-project.

  • Risk if skipped: Restoring an Enterprise database into a Community container marks Enterprise modules as 'not installable, skipped' and breaks the Accounting app entirely on Community.

  • Risk if skipped: Mapping against the wrong major produces import files referencing fields that have been renamed or removed.

  • Risk if skipped: Switching localizations post-load forces a database rebuild because the chart-of-accounts template is one-shot.

  • Risk if skipped: Migrating five years of posted journals when only opening balances are needed inflates database size by an order of magnitude and slows every report.

  • Risk if skipped: Discovering a residency conflict after go-live forces a database export, region re-provision, and re-import.

  • Risk if skipped: Without explicit success criteria the project never formally closes and finance refuses sign-off.

Phase 1

Pre-Migration Prep

Everything that must be true before the first byte leaves the source.

1a. Source-system audit and cleansing

  • Risk if skipped: Without a baseline count you cannot prove completeness at reconciliation.

  • Risk if skipped: Without a frozen source trial balance the reconciliation in Phase 6 has no anchor and finance cannot sign off.

  • Risk if skipped: Duplicate vendors in res.partner inflate AP aging and split payment history across two records.

  • Risk if skipped: Mismatched country strings either fail the import row or silently leave country blank.

  • Risk if skipped: Products with missing required fields fail row-by-row and force a partial re-import.

  • Risk if skipped: AR/AP that does not tie to the GL in the source will never tie in Odoo no matter how careful the load is.

1b. Destination Odoo tenant setup

  • Risk if skipped: Skipping the sandbox forces every test against production and contaminates real financial data with test rows.

  • Risk if skipped: An incorrect chart-of-accounts template at install time cannot be swapped without rebuilding the database.

  • Risk if skipped: Changing res.company.currency_id or timezone after data exists requires reposting every journal and shifts every imported datetime.

  • Risk if skipped: Importing posted journal entries without journals pre-created produces a hard foreign-key error on every row.

  • Risk if skipped: Posting journals without a fiscal year defined throws 'no open fiscal year' errors and blocks the opening-balance entry.

  • Risk if skipped: FIFO retroactively applied to AVCO inventory produces non-deterministic valuation that finance cannot tie back.

  • Risk if skipped: Missing stock.location records cause every stock.quant row to fail and leave on-hand at zero.

  • Risk if skipped: Importing a product against a uom that does not exist defaults it to 'Units' and silently corrupts every subsequent stock movement quantity.

  • Risk if skipped: Missing res.currency.rate rows block every multi-currency document and force a re-load after rates are seeded.

  • Risk if skipped: Discovering a missing custom field after a 100k-row load forces a transform rebuild and re-import.

  • Risk if skipped: Files over the cap fail silently in batch imports and leave records with broken document references.

1c. People prep

  • Risk if skipped: Without named responders the inevitable cutover-day questions land in random inboxes and lose audit trail.

Phase 2

Source Export

Pull a complete, timestamped snapshot of master data, transactions, and configuration.

  • Risk if skipped: Forgetting the source ID column makes idempotent re-runs impossible and forces full re-imports.

  • Risk if skipped: An unsigned or untimed trial balance produces an opening journal that finance cannot trace back to a source document.

  • Risk if skipped: Missing the lot/serial column on a serial-tracked product forces individual quant rows to be split manually post-load.

  • Risk if skipped: Skipping historical rate export forces a fallback to today's rate and misstates every multi-currency open balance.

  • Risk if skipped: Files without a manifest cannot be re-linked to their parent records and become orphaned uploads.

  • Risk if skipped: Without an export timestamp you cannot compute the delta and risk losing every change made between export and cutover.

Phase 3

Transform & Map

Reshape source exports into Odoo-shaped CSVs.

3a. Mapping spreadsheet

  • Risk if skipped: A mapping kept in heads or chat threads cannot be audited and produces inconsistent transforms across re-runs.

  • Risk if skipped: Without external IDs, re-running the importer creates duplicate records instead of updating the existing ones.

3b. Data transformation

  • Risk if skipped: Day-month inversion on dates misstates posting periods and shifts entire quarters of revenue.

  • Risk if skipped: Encoding mismatches surface as mojibake on partner names that have to be reimported per row.

  • Risk if skipped: Unescaped newlines in invoice memo bodies split one row into two and shift every subsequent column.

3c. Relationship and audit-trail decisions

  • Risk if skipped: Loading raw integer IDs into Many2one columns ties imports to a specific database instance and breaks if you ever rebuild.

  • Risk if skipped: Failing to preserve historical timestamps makes age-based AR aging reports wrong for the first reporting period post-cutover.

  • Risk if skipped: Violating load order causes ondelete='restrict' foreign-key errors and leaves every dependent record with a null reference.

3d. ERP-specific transforms

  • Risk if skipped: An off-by-one in account.account.type misclassifies expenses as assets and corrupts every report rolled up from account type.

  • Risk if skipped: Posting an unbalanced opening journal throws ValidationError and blocks every subsequent posted document.

  • Risk if skipped: Direct writes to stock.quant without the inventory adjustment journal break Odoo's stock valuation reconciliation.

  • Risk if skipped: Flattening a multi-level BOM at transform breaks the master production schedule's component requirement calculations.

  • Risk if skipped: Gaps in dated rates cause Odoo to fall back to 1.0 and value foreign-currency invoices at parity, producing nonsensical residuals.

  • Risk if skipped: Without lock dates, a user can post a journal into a closed prior year and silently corrupt the opening balance.

  • Risk if skipped: Posting open AR with the wrong receivable account routes payments to the wrong GL and breaks AR aging.

  • Risk if skipped: Importing the human-readable label when the field's internal key differs causes the row to fail silently and leaves a null value.

  • Risk if skipped: Wrong uom factor multiplies or divides every stock movement quantity for that product by an order of magnitude.

  • Risk if skipped: Loading only product.template leaves the catalog technically present but unusable because stock and BOM lines reference product.product.

  • Risk if skipped: Misallocated company_id values make records invisible to users in the correct company and trigger record-rule access errors.

  • Risk if skipped: Missing stock.lot records on tracked products cause every stock.quant for that product to fail and leave on-hand at zero.

Phase 4

Sandbox Test Migration

Run the full migration against a duplicate database before touching production.

  • Risk if skipped: Loading the full file first burns hours debugging issues a 1% sample would have caught in minutes.

  • Risk if skipped: An out-of-balance opening journal blocks every subsequent posted invoice from reconciling cleanly.

  • Risk if skipped: Stock valuation that does not tie post-load forces every product category's costing method to be re-validated.

  • Risk if skipped: A flattened or partial BOM produces incorrect material requirements for every future manufacturing order.

  • Risk if skipped: Wrong rate selection misstates every foreign-currency residual and breaks AR reconciliation.

  • Risk if skipped: Bulk count matches can mask field-level corruption that only field-by-field comparison surfaces.

  • Risk if skipped: Skipping a full-volume rehearsal means cutover-day surprises around throttling, timeout behavior, and storage caps.

  • Risk if skipped: Aggressive parallel writes against Odoo Online trip throttling and stall the load mid-batch.

  • Risk if skipped: Non-idempotent imports compound every retry into duplicate journals and force a destructive cleanup.

Phase 5

Production Cutover

Sequenced execution window — one shot, fully scripted.

  • Risk if skipped: Late source writes that arrive after the final export become silent data loss.

  • Risk if skipped: Active automations during bulk load fire thousands of redundant notifications and corrupt computed-field state.

  • Risk if skipped: Loading mrp.bom.line before its parent mrp.bom triggers ondelete='cascade' foreign-key violations and discards the line.

  • Risk if skipped: Posting the opening journal before BOMs and products exist leaves the GL balanced but disconnected from inventory valuation, producing reconciliation drift.

  • Risk if skipped: Direct writes break Odoo's stock valuation accounting entries and cause the inventory account to drift from physical on-hand.

  • Risk if skipped: Loading prior-year journals without re-locking afterward leaves the prior period writable and exposes the opening balance to drift.

  • Risk if skipped: Pushing attachments above the per-file cap or beyond the hosting throughput ceiling causes silent failures that orphan the parent record.

  • Risk if skipped: Cascading row-count and total drift across models compounds and becomes unprovable later.

Phase 6

Validate

Prove correctness before users get the keys.

6a. Reconciliation

  • Risk if skipped: Trial balance that does not tie is a hard fail — finance cannot sign off, and the migration is not complete.

  • Risk if skipped: Skipping count reconciliation lets multi-thousand-row drops go unnoticed until users complain.

  • Risk if skipped: AR/AP aging mismatch is the single most-noticed cutover defect by finance and collections.

  • Risk if skipped: Stock-on-hand mismatch breaks every future picking, MRP run, and inventory-valuation period close.

6b. Relationship validation

  • Risk if skipped: Broken BOM linkage produces wrong material requirements on the first manufacturing order and ripples through every PO suggestion.

6c. Audit and compliance

  • Risk if skipped: Forgotten lock dates leave closed periods writable and let a user backdate entries that corrupt the opening balance.

6d. User-acceptance check

  • Risk if skipped: Without UAT, the first day post-cutover surfaces issues that should have been caught before users got the keys.

6e. Sign-off

  • Risk if skipped: Verbal sign-off creates downstream disputes about what 'done' meant when finance has to defend the cutover at year-end audit.

Phase 7

Post-Migration Cleanup

Decommission the source, retire migration scaffolding, capture lessons.

  • Risk if skipped: Finance leadership without their reports stops trusting the migrated data even when it is correct.

  • Risk if skipped: Active migration-tier credentials become the path of least resistance for accidental or malicious bulk writes to the GL.

  • Risk if skipped: An untested first period close becomes a fire drill at month-end and undermines confidence in the migration.

Watch list

Risks to track throughout

These risks live across multiple phases — keep an eye on them from kickoff through cutover.

  • Community vs Enterprise feature gap surfacing mid-migration

    The full Accounting app, Studio, the Documents app, OCR on bills, and several l10n_* localizations only exist on Enterprise. Sandbox testing against an Enterprise database and then deploying onto Community causes views to break with 'not installable, skipped' errors and disables core ERP modules. Verify edition at every phase boundary, not just at Phase 0.

  • Annual major-version cadence and OpenUpgrade path

    Odoo ships a breaking major release every year. A migration planned against Odoo 18 that slips past the next release window inherits the upgrade burden. For migrations between Odoo majors of an existing database, plan the OpenUpgrade tooling path; for fresh imports, pin the major version at Phase 0 and freeze the sandbox against it through cutover.

  • Throughput and per-attachment ceiling compounding across runs

    Odoo Online throttles aggressively per session and caps writes at 2–3 sales orders per second per worker; per-attachment files default to 64 MiB on Odoo Online and 128 MiB elsewhere. Test runs, mapping fixes, and re-loads compound load volume; oversize attachments fail silently in batches. Track cumulative load volume and pre-flight attachment sizes from Phase 4 onward.

  • External-ID hygiene degrading after the first import

    The '__export__.<source>_<id>' convention is what makes safe re-runs possible. If any phase loads a model without external IDs (account.move via raw ORM calls, ir.attachment via ad-hoc admin imports), the next re-run creates duplicates rather than updating. Audit external-ID coverage at the end of every phase that writes data — especially after the opening journal and stock.quant loads, where duplicates corrupt the trial balance.

Pair this with the long-form guide

The complete Odoo ERP migration guide

Same research, written as prose: data model, import mechanisms, mapping strategy, pitfalls, and partner landscape.