How to migrate from Odoo to ERPNext without losing the opening position
If your finance and operations team runs Odoo Community or Enterprise and wants ERPNext, the move is a mapping and cutover exercise, not a single export-and-import button. The work is to pull masters and open balances out of Odoo, map each field to an ERPNext Data Import template, load them in controlled batches, and switch over at a period end where the closing position is verified. The Odoo side starts with Action > Export on selected list-view records, which Odoo documents in its export and import guide for Odoo 18.0. Odoo's export can produce .csv or .xls files, and an import-compatible export option shows only the fields Odoo can re-import, which helps when you are building a field map. Odoo also advises processing large exports in smaller batches to avoid time-outs, so plan your extract by record type.
Effort depends on three things you should size before asking anyone for a quote: the volume of partners, products and open transactions, the number of custom Odoo modules whose data sits in fields that have no standard ERPNext equivalent, and how many companies and currencies are in scope. Each added company or currency adds mapping decisions, intercompany treatment and reconciliation checks. Odoo Enterprise source code is not publicly available and requires a subscription or partner access, so you cannot read its models or export logic from the repository. Your extract, your field names and your data quality rules must come from the running application and your Enterprise subscription. Confirm with your Odoo partner or administrator which edition, version and custom modules you run, because the exports you can produce depend on them.
Which Odoo data and features map to ERPNext and which need rework
This table compares Odoo masters, open transactions and modules against their nearest ERPNext equivalents, and flags where Studio fields, custom modules, multi-company rules or posted history will not carry across one to one. Read each row as a planning decision: move it, rebuild it in ERPNext, or archive it before cutover.
| Odoo item | ERPNext equivalent | Transfer approach | Rework or archive decision |
|---|---|---|---|
| Contacts (customers, vendors, addresses) | Customer, Supplier and Address records | Export from Odoo list views, then load through ERPNext Data Import templates | Merge duplicate partners and map contact types before import |
| Products and variants | Item, with variant attributes where used | Import items first; variants need attribute and template design | Confirm how Odoo product variants will be modeled before building the item list |
| Chart of accounts | Chart of Accounts per company | Rebuild the tree in ERPNext; map each Odoo account code to a target account | Account types and tax mappings rarely match one to one |
| Warehouses and locations | Warehouse tree and bin locations | Create warehouses first, then map internal transfers and locations | Multi-level Odoo locations may need flattening or redesign |
| Units of measure and conversions | UOM and UOM conversion factors | Load UOM definitions, then item-specific conversions | Confirm conversion factors with stock owners before opening stock load |
| Open invoices, bills and purchase orders | Sales Invoice, Purchase Invoice and Purchase Order | Carry only open items at cutover, using the opening balance approach | Fully paid history is usually archived, not re-entered |
| Stock on hand | Stock Reconciliation or opening stock entry | Count and valuate stock as of the cutover date | Valuation method and costing data do not transfer as posted history |
| Manufacturing (BoMs, work orders) | BOM, Work Order and Job Card | Rebuild active BoMs; leave completed production orders in the archive | Routings, work centers and scrap logic need redesign |
| Point of sale | POS Profile and POS Invoice | Configure profiles fresh; migrate only open sessions or none | Session history and payment terminal settings must be re-created |
| CRM leads and opportunities | Lead and Opportunity | Export open pipeline only, if the team needs it | Stage definitions and pipeline rules are rebuilt |
| HR and payroll | Employee, Frappe HR and Payroll | Load active employee master data only | Payroll rules and past payslips do not transfer one to one |
| Studio fields, custom modules and multi-company rules | Custom Fields, Server Scripts or custom apps | Inventory each customization before build starts | Each one needs a keep, rebuild or retire decision; confirm feasibility in your environment |
Documented import and export paths for the move
Odoo and ERPNext each document their own way to get records out and in, and the two paths meet at a CSV or Excel file. The cards below cover the export side, the import side, the database copy used for test runs, and the customization limits that shape any transform step between them.
Odoo list view export
Odoo exports values from any field of the records you select in a list view through Action > Export, as .csv or .xls. Use the import-compatible export option so the file shows only fields Odoo can import back, which keeps column names closer to what ERPNext templates expect. Odoo advises exporting large sets in smaller batches to avoid time-outs, so split partners, products and open invoices into separate runs and check row counts against the source before you move on.
Import-compatible export option
Choose the import-compatible option in Odoo when you want a file that mirrors the importable fields of each model. Fields that Odoo shows only in the interface, such as computed totals, will not come across as values, so balances and open amounts must be re-derived or exported from a report. Confirm with a sample export which columns hold stored values and which are computed, and note each one for the mapping sheet.
ERPNext Data Import templates
The ERPNext Data Import tool loads and updates records from CSV or Excel files or public Google Sheets, using a downloadable template for each DocType. Templates set the column headers ERPNext expects, so map Odoo fields to those headers before loading. Child table rows, such as invoice lines or item rows, are supported, which lets you load a parent and its lines from one file. Confirm the template version matches your ERPNext release.
Batch size for ERPNext imports
The ERPNext documentation advises importing only a few thousand records at a time. Plan loads in order of dependency (accounts, parties, items, then transactions) and in batches sized below that guidance. Keep each file named by DocType and batch number so a failed batch can be rerun without duplicating rows. Test the first batch in a copy of the site before loading the full set.
Odoo database duplication for test copies
Odoo's on-premise documentation describes duplicating a database with neutralization, which produces a test copy with outgoing mail, payment and external connections disabled. Use it to run the export, mapping and reconciliation steps repeatedly without touching production or contacting customers. Confirm which neutralization steps your modules and integrations need, since custom modules may hold their own external references.
Server Script limits on ERPNext
Server Scripts run Python on document events or as API endpoints, and from version 15 they are disabled by default and must be enabled with the server_script_enabled setting. Frappe Cloud public shared benches do not allow them at all. If your transforms need scripting, such as splitting Odoo tax codes or deriving opening balances, confirm the hosting target first and plan a self-hosted bench or an offline transform step in the mapping workbook.
How the Odoo to ERPNext cutover sequence works
The sequence moves Odoo masters and open balances into ERPNext in a controlled order, proves the result on a test site, and switches books over at a period end. Each step closes with a check that the next step depends on, so finance signs off on numbers before anyone relies on ERPNext for live transactions.
Inventory Odoo apps and custom modules
Start by listing every Odoo application in use, including accounting, inventory, sales, purchase, manufacturing and any custom modules or Studio changes. Your team and DeployOpen record which fields, workflows and reports each one drives, and which data actually needs to move. The output is a signed-off inventory that shows what ERPNext must replace, what it will cover with standard features, and what needs a decision about retirement.
Map Odoo fields to ERPNext DocTypes
Each Odoo model and field is matched to an ERPNext DocType, child table or custom field, with notes on value translations such as units of measure, tax codes, payment terms and status values. Finance and operations leads review the mapping against their chart of accounts and stock setup. The mapping is complete when every exported Odoo field has a documented destination or an explicit decision to drop it.
Export Odoo data from list views
Records are exported from Odoo list views using Action, then Export, choosing the import-compatible option so only importable fields appear. Large exports are split into smaller batches, as Odoo's documentation advises, to avoid time-outs. The export set is complete when record counts per model match the Odoo list view totals and each file is saved with its source date and filter settings.
Load groups, parties and items in order
Masters are imported through ERPNext's Data Import tool using its downloadable templates, in dependency order: item groups, customer and supplier groups, then customers, suppliers, contacts, addresses and items. ERPNext documentation advises importing only a few thousand records at a time, so loads run in batches. The step closes when each master type has a count check against the Odoo export and any rejected rows are logged with a fix.
Load open balances into the test site
Open invoices, payments, bank positions, stock and any asset balances are loaded after the masters they depend on, using a temporary opening account so the books balance during import. This work is done on a test site created from a neutralized copy of the Odoo database, so no live customer contact or email is triggered. The step is done when every opening balance loads without error and the test site's totals match the Odoo closing position.
Reconcile the pilot against Odoo
Finance and DeployOpen compare the pilot site with Odoo in layers: master counts, open receivables and payables, control accounts, stock valuation and the trial balance. Each difference is isolated to a source record, corrected in the mapping or data, and reloaded on the test site. The step closes with a reconciliation record that finance signs off, listing each accepted difference and its reason.
Run a parallel period close
Odoo and ERPNext run side by side through at least one full period close, with the same transactions entered in both systems or reconciled between them. Finance checks that ERPNext produces the same closing figures, reports and subledger balances that Odoo does for that period. The parallel run is complete when a full close has been performed in ERPNext and its results match Odoo or any gap has an agreed explanation.
Cut over at period end and retire Odoo
At a planned period end, the final Odoo export is reconciled to the closing position, the residual opening journal entry is posted in ERPNext, and users switch to ERPNext for new transactions. Odoo write access is then removed for operational users while a read-only copy is kept for audit queries and retention. The cutover is done when the first ERPNext period is open, the Odoo copy is locked, and access changes are recorded for your auditors.
Where the opening balances and history go when you leave Odoo
Masters and open items move forward, posted history usually stays behind. When you leave Odoo, the practical plan is to bring customers, vendors, products and the chart of accounts across as masters, then bring open invoices, open bills, bank and stock positions as of a single cutover date. Posted journal history from before that date is normally kept in the Odoo archive rather than replayed into ERPNext. Decide this before any file is exported, because it determines which Odoo list views you need and how much reconciliation work the cutover will carry. Confirm with your finance lead how many prior years, if any, must be queryable in ERPNext for audit or tax purposes.
ERPNext holds the closing position in a *temporary opening account*. Opening invoices and balances are posted against that account so the books balance while the historical ledger stays in Odoo. A *residual opening journal entry* then clears whatever difference remains between the opening invoices and the verified closing trial balance from Odoo, so the ERPNext balance sheet matches the figures signed off at period end. Ask your implementation partner to show how each opening entry traces back to an exported Odoo record, and keep the residual entry small and explained. The mechanics are covered in the opening balances section of this guide.
Exporting the data does not require an Odoo Enterprise subscription or the upgrade service. Odoo's export function is available from list views, and the upgrade service is only needed if you also plan to move the source database to a newer Odoo version. Still, confirm the licensing and access terms for your current edition with Odoo before the project starts, including whether your subscription, partner access or Odoo Online plan permits the export, the retention of the database after cutover and any obligations that continue after you stop paying. Write those answers into the project plan so the export is not blocked by a licensing question in the final week.
What drives the cost and duration of an Odoo to ERPNext move
This table lists the factors that change the effort of moving from Odoo to ERPNext, whether each cost is one-time or recurring, and what to request in a written quote. Use it to compare the scope in your Odoo database against the work a partner would price. The main takeaway is that custom Odoo code, data quality and finance reconciliation rounds usually move the estimate more than record volume alone.
| Driver | Why it changes cost or effort | One-time or recurring, and what to request in a quote |
|---|---|---|
| Odoo apps in use | Each app (sales, purchase, inventory, accounting, manufacturing, POS) needs its own mapping to ERPNext modules and its own test cases. | One-time. Ask for a line item per app with the ERPNext module it maps to. |
| Open and historical records | Open invoices, payments and stock moves drive the import work. Years of closed history add extraction and validation time. | One-time. Ask which history is migrated, in what period, and how batches are sized for the Data Import tool. |
| Custom modules and Studio changes | Custom Odoo fields, models and Studio views have no direct equivalent and must be re-created as ERPNext custom fields, scripts or apps. | One-time. Ask for an inventory of each custom item and the ERPNext method chosen for it. |
| Companies, currencies and warehouses | Each legal entity needs its own chart of accounts, opening balances and stock locations. Multi-currency balances need revaluation rules. | One-time. Ask for a count of each and how intercompany balances are treated. |
| Payment, eCommerce and bank integrations | Each connected system needs a new connector or manual feed, with its own tokens, reconciliation rules and test runs. | One-time to build, recurring to run. Ask whether connectors are built, configured or replaced, and who maintains them. |
| Data quality of contacts and products | Duplicate parties, inconsistent units of measure and missing tax data slow cleansing before any load. | One-time. Ask who cleans data, who approves merges and how many cleansing passes are included. |
| Reconciliation rounds required by finance | Each round compares ERPNext balances with Odoo reports, then isolates and fixes differences before sign-off. | One-time. Ask how many rounds are priced, what counts as a round and what happens if a round fails. |
| Hosting, support and upgrades | The ERPNext target runs on infrastructure you control, so servers, backups, monitoring and version upgrades continue after cutover. | Recurring. Ask for the hosting model, support hours, upgrade scope and whether retainer terms apply. |
What usually goes wrong in Odoo to ERPNext migrations
Most Odoo to ERPNext projects fail in the same few places: data that was never cleaned, loads that run in the wrong order, and cutovers that leave two live systems writing to the books. Each card below names one of these failure points and the check that prevents it. Review them before the mapping work starts, because several of them change how the export and import templates are built.
Duplicate contacts and products
Odoo lets the same customer exist as several partner records, often with variant addresses, and products can be duplicated across variants and archived items. Loading these into ERPNext creates duplicate Customers, Suppliers and Items, which splits outstanding balances and stock history across records that look identical in reports. Before exporting, run a duplicate review on partner names, tax IDs and email addresses, decide one surviving record per entity, and keep a mapping table from old Odoo IDs to new ERPNext names so open invoices still point to the right party.
Chart of accounts and tax mismatch
Odoo account codes, account types and tax definitions rarely line up one to one with ERPNext's chart of accounts and tax templates. If the ERPNext chart is built from a default template and Odoo taxes are mapped by name rather than by rate and reporting treatment, opening invoices post to accounts the finance team does not recognize and tax reports drift. Agree the target chart and each tax template with the finance owner first, then map every Odoo account and tax to a named ERPNext counterpart in writing before any balance is loaded.
Batches loaded out of dependency order
ERPNext Data Import resolves links such as an Item Group, a Warehouse, a Supplier or a Sales Invoice's Customer only if the linked record already exists. Loading transactions before their masters produces rejected rows, and partially loaded batches are hard to unwind. Set a fixed order: company and accounts, tax templates, item groups and warehouses, customers and suppliers, items, then opening documents. Import in small batches, since the documentation advises a few thousand records at a time, and keep a log of which batch each file belongs to.
Load without a reconciled control total
A file that imports without errors can still be wrong. Without a control total taken from Odoo before export, nobody can prove that the number of open invoices, the receivable and payable balances, and the stock valuation in ERPNext match the source at the cutover date. Record totals from Odoo's own reports for each control account and each open-document list, compare them to ERPNext after every batch, and do not start parallel use until the differences are explained and signed off by finance.
Odoo write access left open after cutover
If users can still create invoices, adjust stock or confirm orders in Odoo after the cutover date, the books diverge from ERPNext within hours and the reconciliation is wasted. Odoo does not stop writing on its own when a new system goes live. Plan a written freeze: revoke or restrict user groups, switch the database to read-only access where your hosting allows it, and keep a sealed, dated export of the final state as the audit reference. Confirm who can still change records through the API or integrations, since those paths are easy to miss.
Odoo version end of support during the project
Odoo's support windows are fixed, and a multi-month migration can outlast the version you started on. Standard support covers three years after a major release, and Odoo 17.0 standard support ended in September 2026, so a source database on that version is already outside standard support. Confirm the support end date of your source version before scoping, and check whether a version change or upgrade of the Odoo side is needed to get a clean, supported export, since that choice affects the field names you will map.
Custom logic assumed to exist in ERPNext
Custom Odoo modules often hold business rules that users never see as data: computed fields, approval steps, pricing rules and automated actions. Teams assume ERPNext already does the same, then discover it after go-live that a discount, a status flow or a document numbering rule is missing. Inventory every custom module and automated action in Odoo, then classify each as a standard ERPNext setting, a custom field, a server script or a custom app. Server Scripts are disabled by default from version 15, so confirm the setting and hosting policy before you plan them.
Questions buyers ask before moving from Odoo to ERPNext
Is ERPNext free to run compared with Odoo?
Self-hosting ERPNext is free, because the software is open source under GPL-3.0 and the Frappe Framework is under MIT. According to the ERPNext pricing page, Frappe Cloud hosting is the paid option, with shared site hosting starting at 5 US dollars per month and servers starting at 20 US dollars per month for shared instances and 125 US dollars per month for dedicated servers. Your recurring costs are then your own infrastructure, staff time and any support retainer. On the Odoo side, compare your current per-user subscription, the plan you need (Odoo Online, Odoo.sh or on-premise requires the Custom plan for multi-company, Studio, external API access and custom modules) and any upgrade or extended support fees. Ask Odoo to confirm current prices in writing, since they change.
What drives the cost of an Odoo to ERPNext migration?
The main drivers are the number of companies, currencies and books you carry, how much history you move, how many Odoo custom modules need a replacement, and how many integrations must be rebuilt. Cleaning exported data and validating balances against Odoo also take time. One-time costs include the migration work itself, mapping and test loads, and the cutover. Recurring costs include hosting, maintenance and any retainer. When you request a quote, ask for the written scope to list each module, each data object (masters, open balances, stock, open documents), each integration and the test cycles included, so you can compare it with an in-house estimate.
Can our own team migrate from Odoo to ERPNext without a partner?
Yes, a capable internal team can do it, provided it has people who understand both systems and the accounting model. The Odoo side needs list-view exports, which Odoo documents through Action > Export in .csv or .xls format, with an import-compatible option and smaller batches for large exports. The ERPNext side uses the Data Import tool with downloadable templates, which the documentation advises for a few thousand records at a time. Teams without ERPNext experience usually underestimate the mapping of Odoo records to ERPNext DocTypes, the reconciliation to the trial balance and the cutover. Confirm the approach with a test load before committing to a date.
What do finance and operations need to provide during the migration?
Finance must confirm the chart of accounts, the tax setup, open receivables and payables, bank balances, and the closing position at the cutover date. Operations must confirm item and warehouse structures, opening stock by location, unit of measure rules, bills of materials if you use manufacturing, and open orders that continue after go-live. Both teams need to sign off the test loads and agree who owns each reconciliation. Expect repeated review cycles, because differences found in one test load usually change the mapping for the next. Document these decisions early, since they shape every import template.
How long does an Odoo to ERPNext migration take?
Duration depends on scope rather than on a fixed rule. The biggest factors are the number of companies and modules in use, the volume of masters and open documents, the amount of history you carry, the number of custom reports and integrations, and how many test cycles finance requires before sign-off. No general duration is supplied here, so ask any provider, including DeployOpen, to state the duration in the written scope, with the phases, the test loads, the cutover window and the dependencies on your team. For planning, confirm your Odoo version's support window with Odoo, because upgrades and end-of-support dates affect when you must cut over.
Do Odoo custom modules move into ERPNext?
No, Odoo modules do not move. Odoo custom modules are Python and XML code written against Odoo's framework, and ERPNext uses the Frappe Framework with its own DocTypes, scripts and custom apps. Each custom module needs an assessment: some behavior is covered by standard ERPNext features, some needs custom fields or scripts, and some needs a new custom app. Server Scripts are disabled by default from version 15 and must be enabled with the server_script_enabled setting, and Frappe Cloud public shared benches do not allow them, so check hosting constraints early. Ask for a module-by-module list in the scope.
Which Frappe and Odoo versions should we confirm before planning?
Confirm both sides before you fix a date. On the ERPNext side, Frappe's supported versions page lists version 15 as supported until the end of 2027 and version 16 until the end of 2029, and version 14 reached end of life on January 31, 2026. Frappe also states that warranty coverage requires a listed version and a matching Frappe Cloud support plan. On the Odoo side, Odoo's standard and extended support documentation lists the end of standard support for each release, and Odoo SaaS versions cannot use extended support. Confirm the target version with Frappe, and confirm your Odoo version's support dates with Odoo before you choose a cutover period.
Does DeployOpen do the migration onto our own infrastructure?
DeployOpen implements self-hosted open-source platforms inside the client's own infrastructure, including cloud accounts, data centers and air-gapped networks, and most engagements are fixed-scope with scope, deliverables and timelines agreed in writing before work starts. For an Odoo to ERPNext move, that can cover planning the mapping, building the import templates, running test loads, supporting reconciliation and the cutover, and documenting the result. DeployOpen does not publish a price list, so a quote follows from the written scope. Ask for the scope to state which records, modules and integrations are included and which remain with your team.
How DeployOpen scopes and delivers an Odoo to ERPNext migration
DeployOpen approaches the move from Odoo to ERPNext as a written, fixed-scope engagement inside your own infrastructure. We start by agreeing which Odoo masters, open balances and history move, then build, test, document and hand over the import work before the period-end cutover.
How we scope
- We agree in writing which Odoo masters, open balances and history move into ERPNext, and which stay in an archive.
- We inventory the Odoo applications, companies, currencies and chart of accounts in use before choosing import templates.
- Engagements are fixed-scope, so deliverables, timelines and the cutover period end are agreed before work starts.
How we build
- We map Odoo list-view exports to the ERPNext Data Import templates, field by field, including child table rows.
- We load data in small batches into a non-production ERPNext site and log every rejected or transformed record.
- We run repeated test loads and reconciliation checks, then document the final load order used for the production cutover.
How we hand over
- You receive the mapping workbook, transformation rules, load logs and reconciliation results for your finance and operations sign-off.
- We document the cutover runbook, including the opening balance entries and the steps to freeze Odoo at the period end.
- Knowledge transfer covers how your team reruns imports, handles future corrections and manages the ERPNext site afterwards.
How we support
- Ongoing support, upgrades and continuous testing are available as a retainer after go-live.
- We confirm with you which Odoo edition, version and access method apply to your export before the first extract is taken.
- Post-cutover fixes to imported data are scoped as separate written work, so you know what each change costs and why.

