Guide · Migration
How to migrate to Odoo from CONTPAQi, Aspel, SAP Business One, NetSuite or Business Central
- Author
- Fabio Soto, Business Analyst
- Published
- Updated
- Version
- Odoo 20
In short
Migrating to Odoo from another system is not a version upgrade: the Odoo 20 documentation leaves migration from another ERP outside its upgrade service, so it is done by importing data. You bring over master data, the balances at the cut-off date —trial balance, open invoices and bills, inventory and banks— and, in Mexico, what you need to keep issuing payment complements; history stays in the previous system for reference. The migration is done when Odoo's trial balance, receivables and inventory reconcile with the previous system's at the same date.
Migrating means importing data, not upgrading a version
Switching systems and moving to a newer Odoo version are different jobs. An upgrade converts an Odoo database into a newer one; a migration from another system rebuilds in Odoo the data the company needs to keep operating. The Odoo documentation spells it out when it lists what its upgrade service does not cover:
“An upgrade does not cover: […] Migrating from another ERP to Odoo”
That is why a migration from CONTPAQi, Aspel, SAP Business One, NetSuite or Business Central is planned as part of the implementation, with its own cut-off date and reconciliation. The guide How to implement Odoo in a mid-sized company explains where it fits in the project.
If you are moving a Mexican entity, three local terms run through this guide: the SAT (Servicio de Administración Tributaria, Mexico’s tax authority), the RFC (Registro Federal de Contribuyentes, the Mexican tax ID) and the CFDI (Comprobante Fiscal Digital por Internet, Mexico’s electronic invoice, stamped through an authorized provider).
- Previous system
- The software where the company records its operation and its books today, and which stops being the source of truth on cut-off day.
- Cut-off date
- The date whose balances are carried into Odoo as the starting point.
- Opening balances
- The company’s snapshot at the cut-off date: the trial balance, what it is owed, what it owes, its inventory and its banks.
- Clearing account
- An account that temporarily holds an amount while its detail is loaded, so that nothing is recorded twice.
- External ID
- The key Odoo uses to recognize an imported record, which can be the same key it had in the previous system.
What moves and what stays
The Odoo 20 accounting documentation asks you to prepare four sets of data from the previous system: the opening account balances, the open customer invoices with their credit notes, the open vendor bills with their refunds, and the opening inventory count. Master data goes first, because everything else depends on it.
| Data | What it includes | How it goes into Odoo |
|---|---|---|
| Chart of accounts | The accounts the company uses, with their codes | Matching standard accounts are renamed and recoded; the rest are created or imported |
| Contacts | Customers and vendors with current activity | Import with the contacts template |
| Products | Current products, with their category and cost | Import, categories first |
| Trial balance at cut-off | The balance of each account at the cut-off date | One journal entry, using the miscellaneous operations template |
| Receivables and payables | Open invoices and bills, for the amount still due | Import of invoices at their open balance, against a clearing account |
| Inventory | Counted quantity by product, location and lot | Import into the physical inventory |
| Banks | The balance of each bank account | Starting balance of the first statement |
| History | Paid invoices, past journal entries and transactions | Stays in the previous system for reference |
History stays where it is. A full year of paid invoices does nothing for tomorrow’s operation and multiplies what has to be reconciled; the Odoo documentation names the end of the fiscal year as the easiest moment to switch precisely because it minimizes the data to transfer. The previous system is kept for reference for as long as the company must retain its records, a period to confirm with your accountant.
Which system you are coming from
The core work is the same from any source; what changes is how many sources you have to bring together. Each vendor organizes its product its own way, and the best starting point is how its own public documentation describes it:
| Source system | How its offering is organized | What it means for the migration |
|---|---|---|
| CONTPAQi | Specialized solutions by area: accounting and tax, payroll, administration and sales, point of sale and treasury | If the company uses several, data comes from more than one source, and collections in the sales system are reconciled against accounting before the cut-off |
| Aspel | Separate systems, among them the accounting system (COI) and the administrative system (SAE), which runs from quotation to payment, plus payroll and point-of-sale systems | Same as above: receivables in the administrative system are reconciled against accounting |
| SAP Business One | Its help portal covers inventory, production, material requirements planning and the year-end closing within one product | If the whole operation lives there, there is one source, and the work is mapping its master data structure to Odoo’s |
| NetSuite | Its help center brings accounting, order management, supply chain and employee management together in one product | The same mapping work, from a single source |
| Microsoft Dynamics 365 Business Central | Microsoft describes it as a business management solution for small and mid-sized organizations covering finance, manufacturing, sales, shipping, project management and services | Its lists, such as customers or invoices, export to Excel, which is the format Odoo’s templates read |
There are cases where the current system is still the right choice, or where it is better to wait. If the company only needs accounting and invoicing and its system handles them well, the benefit of integrating departments is smaller; if the switch would fall in the middle of a tax period, it is better to wait for the next close. Migration pays off when the company wants sales, purchasing, inventory and accounting to work on the same data.
How data is imported into Odoo
Odoo’s import tool loads spreadsheets: the documentation mentions Excel and CSV, and the version 20 code also reads the OpenDocument format. The most common data comes with templates, and the documentation sets the order: related records are imported first, from their own list. To keep relationships intact, each record can keep the key it had in the previous system as its external ID; the documentation requires it to be unique across all objects and recommends prefixing it with the name of the source table, so that customer 1 and product 1 do not collide.
The path, one master list at a time, is this:
- Get each master list and each balance report out of the previous system into a spreadsheet.
- Fit each file to the matching Odoo template, with its external ID.
- Load into a test database, in order: master data first, then whatever depends on it.
- Test each file before importing it: the Odoo 20 code runs the full import with its validations and then rolls back the writes, so it shows the errors without touching the database.
- Import, and compare counts and totals against the previous system.
- Repeat the full rehearsal before the cut-off and, on cut-off day, load only the balances.
Two warnings in the documentation shape that path: imports are permanent and cannot be undone, and a very large file can time out, which is solved by importing in smaller batches.
How to reconcile the balances
The risk in an accounting migration is recording the same thing twice. If the trial balance says customers owe 1,000 and the open invoices add up to that same 1,000, loading both as they are leaves receivables of 2,000 in Odoo: 1,000 from the trial balance plus 1,000 from the invoices. The Odoo documentation solves this with clearing accounts. In the trial balance you import, the receivables account is replaced by a receivables clearing account, and the open invoices are loaded against that same clearing account; at the end, the clearing account sits at zero and receivables carry the balance of the invoices. The same applies to payables.
Before loading anything, the documentation asks for four checks. The first one reads:
“The sum of the opening trial balances of all receivable accounts must equal the sum of the open customer invoices minus credit notes.”
| Trial balance account | Must equal |
|---|---|
| Receivables | Open customer invoices, minus their credit notes |
| Payables | Open vendor bills, minus their refunds |
| Inventory | The sum, product by product, of counted quantity times cost |
| The whole trial balance | Its own debits and credits: it must balance |
For inventory, the math is done in plain sight: with 10 units of one product at 250 and 8 of another at 350, inventory is worth 2,500 plus 2,800, that is 5,300, and the trial balance’s inventory account must read 5,300. Open invoices, in turn, are loaded with a single line for the amount due, as the documentation recommends to avoid hitting the tax accounts twice. Finally, once the clearing accounts are at zero, they are switched to off-balance sheet so they no longer appear in reports.
Mexico: stamped invoices and payment complements
Invoices issued in the previous system are already stamped and are not stamped again in Odoo. What does cross the cut-off is their collection. When an invoice was issued with the PPD payment method (pago en parcialidades o diferido, paid in installments or deferred), the SAT’s filling guide requires an additional CFDI carrying the payment receipt complement for each payment received:
«En este supuesto la clave del método de pago debe ser “PPD” (Pago en parcialidades o diferido) y cuando se reciba el pago total o parcial se debe emitir adicionalmente un CFDI al que se le incorpore el “Complemento para recepción de pagos” por cada pago que se reciba.»
Odoo generates that complement only for invoices with the PPD policy, and sends it through the update payments button when a reconciled payment belongs to an invoice with a fiscal folio (the CFDI’s unique identifier). For invoices issued in another system, the Odoo 20 Mexican localization includes an XML reader: when you upload an invoice’s XML, Odoo creates it as a draft with its customer and taxes, and those invoices can issue payment complements. If the invoice was already created as a draft through an import, the documentation says its fiscal folio is retrieved by dragging the XML into its chatter as a log note.
The two routes have different accounting effects: the XML brings the lines and taxes of the original invoice, while the open-balance import uses a single line against the clearing account. That is why the route for open PPD invoices is decided with your accountant and fully tested in the test database before the cut-off. The documentation also warns that an XML created in another system may carry totals different from those Odoo calculates, and asks you to always double-check what is uploaded this way.
The customer list is cleaned against the SAT before migrating. In CFDI 4.0, the invoice carries the customer’s RFC, its name or business name exactly as registered under that RFC, the postal code of its tax address and its tax regime (régimen fiscal), and Odoo asks for them on each contact. Each product also needs its SAT product code so the invoice does not fail validation.
What changes for the accounting team
The Mexican localization’s chart of accounts follows the SAT’s account grouping code (código agrupador). You can create any account that respects that structure —NNN.XX.YY, NNN.XX.YYY or NNN.XX.YYY.ZZ—, and Odoo validates it when it is created. Standard accounts that have an equivalent in the company’s chart are renamed and recoded instead of deleted, because the documentation warns that deleting them or changing their type can break basic processes such as issuing an invoice. And the localization package is chosen before the first journal entry: once one is posted, it can no longer be changed.
Daily work shifts too. In Odoo, each invoice is itself a journal entry —in the version 20 code, invoices, credit notes and manual entries are the same kind of record—, and Odoo creates the journal entries of all invoices and payments. The accountant moves from keying in entries to reviewing the ones the operation generates, reconciling banks and closing the month, and Mexico’s electronic accounting (contabilidad electrónica) comes out of the system: chart of accounts, trial balance and journal entries, in XML.
What changes for operations
Sales, purchasing, inventory and accounting share one database. The invoice is created from the sales order —the Odoo 20 code generates invoices from orders— and its journal entry is born with it, so what was sold, what the warehouse delivered and what was invoiced are read in the same system. If data used to be passed from one system to another, that hand-off disappears.
For a while, the team will keep looking up the past in the previous system. Decide at the cut-off who keeps access and for what, and make sure everything new is captured only in Odoo.
Before the cut-off: the short list
- Customers and vendors with RFC, business name as registered under the RFC, tax postal code and tax regime.
- Products with their category, cost and SAT product code.
- A chart of accounts that follows the grouping code structure.
- A trial balance at the cut-off date that balances.
- Receivables and payables that reconcile with the trial balance, with the fiscal folio of open PPD invoices.
- Inventory counted on the cut-off date, with its cost.
- The balance of each bank account at the cut-off date.
- A full rehearsal in the test database, with one payment complement tested.
Frequently asked questions
Can Odoo import the CONTPAQi, Aspel or SAP Business One database directly?
Odoo’s import tool works with spreadsheets —Excel, CSV or OpenDocument— and ships templates for the most common data. The bridge is getting the data out of your current system into those formats and fitting it to the templates, keeping each record’s key as its external ID.
Can we migrate our full history to Odoo?
Journal entries and documents can be imported, but what is worth bringing over is the balances at the cut-off date and the open documents. The Odoo 20 documentation names the end of the fiscal year as the easiest moment to switch because it minimizes the data to transfer; history is looked up in the previous system.
What happens to invoices already stamped in the previous system?
They stay as they are: they are already stamped and are not stamped again. Those still awaiting payment come into Odoo at their open balance, and if they are PPD (paid in installments or deferred), bringing in their fiscal folio lets you issue the payment complement from Odoo when they are collected.
When is the best time to switch systems?
At the end of the fiscal year, which is the easiest option according to the Odoo 20 documentation, or at the end of a tax period. The middle of a period is not recommended, because the data from both systems has to be combined for the same tax filing.
Do we have to stop using our previous system on go-live day?
For day-to-day work, yes: from the cut-off, whatever was migrated is recorded only in Odoo. For reference, the previous system is kept for as long as the company must retain its records, a period to confirm with your accountant.
By industry
Moving your operation to Odoo from your current system? See our Odoo implementation service, or write to us.
Sources
- Odoo S.A., “Upgrade”, official Odoo 20.0 documentation, odoo.com/
documentation/ . Accessed .20.0/ administration/ upgrade.html - Odoo S.A., “Get started (Accounting)”, official Odoo 20.0 documentation, odoo.com/
documentation/ . Accessed .20.0/ applications/ finance/ accounting/ get_started.html - Odoo S.A., “Export and import data”, official Odoo 20.0 documentation, odoo.com/
documentation/ . Accessed .20.0/ applications/ essentials/ export_import_data.html - Odoo S.A., “Mexico (fiscal localization)”, official Odoo 20.0 documentation, odoo.com/
documentation/ . Accessed .20.0/ applications/ finance/ fiscal_localizations/ mexico.html - Odoo S.A., “addons/base_import/models/base_import.py”, Odoo source code, branch 20.0, commit eaef8b21, github.com/
odoo/ . Accessed .odoo/ blob/ eaef8b21ca849cc8b12be2379a5c87a7dea8f3ff/ addons/ base_import/ models/ base_import.py - Odoo S.A., “addons/account/models/account_move.py”, Odoo source code, branch 20.0, commit eaef8b21, github.com/
odoo/ . Accessed .odoo/ blob/ eaef8b21ca849cc8b12be2379a5c87a7dea8f3ff/ addons/ account/ models/ account_move.py - Odoo S.A., “addons/sale/models/sale_order.py”, Odoo source code, branch 20.0, commit eaef8b21, github.com/
odoo/ . Accessed .odoo/ blob/ eaef8b21ca849cc8b12be2379a5c87a7dea8f3ff/ addons/ sale/ models/ sale_order.py - Servicio de Administración Tributaria (SAT), “Anexo 20. Guía de llenado de los comprobantes fiscales digitales por Internet”, SAT, Mexico, omawww.sat.gob.mx/
tramitesyservicios/ . Accessed .Paginas/ documentos/ Anexo_20_Guia_de_llenado_CFDI.pdf - CONTPAQi, “CONTPAQi® software empresarial y administrativo”, CONTPAQi official website, contpaqi.com/
. Accessed . - Siigo Aspel, “Siigo Aspel México”, Siigo Aspel official website, aspel.com.mx/
. Accessed . - SAP SE, “SAP Business One”, SAP Help Portal, help.sap.com/
docs/ . Accessed .SAP_BUSINESS_ONE - Oracle, “Welcome to the NetSuite Help Center”, Oracle Help Center, NetSuite Applications Online Help, docs.oracle.com/
en/ . Accessed .cloud/ saas/ netsuite/ ns-online-help/ index.html - Microsoft, “Welcome to Microsoft Dynamics 365 Business Central”, Microsoft Learn, learn.microsoft.com/
en-us/ . Accessed .dynamics365/ business-central/ welcome - Microsoft, “View and edit in Excel from Business Central”, Microsoft Learn, learn.microsoft.com/
en-us/ . Accessed .dynamics365/ business-central/ across-work-with-excel