ERP migration
Field-level mapping, validation, and rollback between Odoo Enterprise and Dolibarr ERP. We move data and schema; workflows are rebuilt natively in Dolibarr ERP.
Odoo Enterprise
Source
Dolibarr ERP
Destination
Compatibility
10 of 12
objects map 1:1 between Odoo Enterprise and Dolibarr ERP.
Complexity
BStandard
Timeline
3-5 weeks
Overview
Migrating from Odoo Enterprise to Dolibarr is a structural simplification as much as a data move. Odoo organizes data around a unified res.partner record used across all apps, while Dolibarr uses separate llx_societe (third parties), llx_contact, and llx_adherent tables that must be split during migration. We extract from Odoo's PostgreSQL database directly or via XML-RPC External API, strip any Enterprise-only module references that would crash a Community-equivalent target, and remap Odoo's Chart of Accounts to Dolibarr's country-specific accounting model. Projects and tasks from project.project and project.task migrate as Dolibarr llx_projet and llx_projet_task records, though Dolibarr lacks Odoo's native timesheet and material planning sheets. We do not migrate Odoo Studio custom modules, ir.filters, server actions, or automated actions as code; we deliver a written inventory of these for the customer's admin to rebuild in Dolibarr's module configuration or via PHP custom scripts.
Every standard and custom field arrives verified.
AI proposes the map; you confirm before any record moves.
Parent–child, lookups, and ownership stay linked.
Calls, emails, meetings — with original timestamps.
Documents, uploads, and inline notes move with the record.
Why teams make this switch
Leaving
What's pushing teams away
Choosing
What's pulling them in
Object mapping
Each row shows how a Odoo Enterprise object lands in Dolibarr ERP, including any object-level transformations, lookup resolution, or schema-design dependencies.
Typical mapping — final map is confirmed during the sample migration step.
Odoo Enterprise
res.partner (Contact / Company)
Dolibarr ERP
llx_societe + llx_contact
1:manyOdoo's res.partner holds both individuals and organizations in a single table with the partner_type (contact/company/invoice/delivery) and is_company flags. We split each res.partner into a Dolibarr llx_societe record (when is_company=true) and a linked llx_contact record (always). For Odoo partners where is_company=false, we create only an llx_contact linked to a parent llx_societe. Address fields (street, city, zip, country) migrate to llx_societe_address or llx_contact with address type preserved via llx_coder_compose. The Dolibarr s.rowid maps to Odoo res.partner.id.
Odoo Enterprise
res.company
Dolibarr ERP
llx_societe + llx_const
1:1Odoo res.company records represent the operating units (branches, subsidiaries) and map to Dolibarr llx_societe records with the company=true flag. Company logo migrates to Dolibarr's /documents/logos/ directory and the logo filename is stored in llx_const.name='MAIN_INFO_SOCIETE_LOGO'. Fiscal address, VAT numbers, and SIREN/SIRET fields migrate to llx_societe and llx_societe_extrafields where the Dolibarr module is activated. Multi-company Odoo setups with separate legal entities produce one llx_societe per Odoo company record.
Odoo Enterprise
product.product + product.template
Dolibarr ERP
llx_product
1:1Odoo product.template holds the product definition (name, description, list_price) and product.product holds variants (size, color, dimension combinations). We flatten these into a single llx_product per product.product variant, with the template name stored in llx_product.description and the variant label in llx_product.label. Product categories from product.category map to llx_categorie with type='product'. For Odoo BoM components (mrp.bom), we create llx_product as type=1 (stockable) and note the bill of materials relationship for Dolibarr's manufacturing module activation or manual rebuild. Units of measure from product_uom migrate to Dolibarr's unit conversion table.
Odoo Enterprise
sale.order + sale.order.line
Dolibarr ERP
llx_commande + llx_commandedet
1:1Odoo sale.order records map to Dolibarr llx_commande with state mapped from Odoo state (draft/quotation->DRAFT, sale_order->VALIDATED, done->SHIPPED, cancel->CANCELED). Odoo order lines migrate to llx_commandedet with product reference, quantity, unit price, and tax rate preserved. The Odoo partner_id lookup resolves to the target llx_societe.rowid; the sale_order_id and client_order_ref map to Dolibarr ref_client and ref. Historical sale orders (state=sale_order, picking_ids, invoice_ids) migrate with their lines; Odoo's on-change pricing rules are resolved at migration time and stored as static prices in llx_commandedet.
Odoo Enterprise
purchase.order + purchase.order.line
Dolibarr ERP
llx_commande_fournisseur + llx_commandedet
1:1Odoo purchase.order records map to Dolibarr llx_commande_fournisseur with state mapped from Odoo state (draft/purchase_order->DRAFT, purchase_order->VALIDATED, done->RECEIVED, cancel->CANCELED). Supplier_id resolves to the target llx_societe.rowid by matching Odoo's partner_id with a supplier flag. Order lines migrate to llx_commandedet with product reference, quantity, buy_price (cost price), and tax rate. Receipt matching from stock.picking migrates to Dolibarr's supplier order receipt workflow; incoming shipments with no linked purchase order become Dolibarr supplier orders in CLOSED state.
Odoo Enterprise
account.move (Customer Invoices)
Dolibarr ERP
llx_facture + llx_facturedet
1:1Odoo account.move records with type in (out_invoice, out_refund) map to Dolibarr llx_facture with type in (invoice, credit_note). Posted invoices migrate with their full line items to llx_facturedet; draft invoices migrate separately with state=DRAFT. Odoo's invoice.line_ids carrying tax_ids resolve to Dolibarr's localtax mechanism (localtax1 or localtax2 depending on the country) which must be pre-configured in Dolibarr before invoice migration. Odoo's account.move.name (invoice number sequence) maps to llx_facture.ref and ref_int. Payment records (account.payment) migrate as Dolibarr llx_paiement linked to the invoice via llx_paiement_facture.
Odoo Enterprise
account.move (Vendor Bills)
Dolibarr ERP
llx_facture_fournisseur + llx_facturedet
1:1Odoo account.move records with type in (in_invoice, in_refund) map to Dolibarr llx_facture_fournisseur. Supplier_id resolves to the target llx_societe.rowid by matching Odoo's partner_id with a supplier flag. Line items with product_id and purchase_price migrate to llx_facturedet. Vendor bill states (posted, draft) map directly. Odoo's vendor bill number (bill_number) maps to llx_facture_fournisseur.ref and ref_supplier. Bills in Odoo reconciled with account.move.line records via full reconciliation are flagged in Dolibarr's payment matching table for the customer to re-reconcile in Dolibarr's bank reconciliation interface.
Odoo Enterprise
project.project + project.task
Dolibarr ERP
llx_projet + llx_projet_task
1:1Odoo project.project maps to Dolibarr llx_projet with name, description, date_start, and date_end preserved. project.task maps to llx_projet_task with parent_id resolved to the target Dolibarr task rowid for sub-task hierarchies. Odoo stage_id (Kanban pipeline stages) migrates as Dolibarr task status values (TODO, IN PROGRESS, DONE, CANCELLED) that the customer configures in Dolibarr's project module settings before migration. Odoo's project.task.timesheet_ids (hr_timesheet.line) do not have a native Dolibarr equivalent; we export them as read-only records in a separate timesheet migration table for the customer to manually enter or configure a Dolibarr timesheet module. Odoo automated stage actions (ir.actions.server) are not migrated and are listed separately for admin rebuild.
Odoo Enterprise
hr.employee
Dolibarr ERP
llx_societe (contact type) + llx_adherent
1:1Odoo hr.employee records migrate to Dolibarr llx_societe with type='contact' and a linked llx_adherent record if the Dolibarr member/adhesion module is activated. Employee fields (job_title, work_email, work_phone, department_id) map to the corresponding llx_contact columns. Employment contract dates (contract_id.date_start, date_end) migrate as Dolibarr llx_adherent.date adhesion membership records for HR visibility. Historical payslip data (hr.payslip) does not have a standard Dolibarr equivalent and migrates as a read-only archive file or custom table for the customer's HR team to reference outside the ERP. Odoo's hr.contract model requires Dolibarr's RH/HR module activation or a custom PHP module.
Odoo Enterprise
stock.quant + stock.move
Dolibarr ERP
llx_product_stock + llx_stock_mouvement
1:1Odoo stock.quant (on-hand inventory by warehouse and location) maps to Dolibarr llx_product_stock with warehouse_id resolved to the target Dolibarr entrepot.rowid. Odoo stock.move records (inventory adjustment, internal transfer, receipt, delivery) migrate to Dolibarr llx_stock_mouvement with product reference, qty (positive for incoming, negative for outgoing), type (INTERNAL, IN, OUT, ADJUST), and warehouse resolved. Lot/serial number traceability from stock.lot migrates to Dolibarr's llx_lot with the product and expiry date. Quant snapshots migrate as the current Dolibarr stock level; full move history migrates as individual llx_stock_mouvement rows for inventory audit trails.
Odoo Enterprise
account.account + account.fiscal.position
Dolibarr ERP
llx_accounting_account + llx_accounting_fiscal_position
lossyOdoo's Chart of Accounts (account.account) does not migrate directly because Dolibarr ships with a pre-configured country-specific Chart of Accounts that must be activated in Dolibarr before any accounting data moves. We extract Odoo's account.account records and produce a mapping spreadsheet that aligns each Odoo account code and name to the nearest Dolibarr account from the target country's localization. Fiscal positions (account.fiscal.position) mapping taxes and accounts by partner country/VAT migrate to Dolibarr llx_accounting_fiscal_position with the account/src/dest pairs remapped to the Dolibarr Chart of Accounts codes. This step requires the customer's country and tax regime to be confirmed before any accounting migration begins.
Odoo Enterprise
ir_attachment + filestore
Dolibarr ERP
llx_ecm_files + /documents/ tree
1:1Odoo stores file attachments in two locations: the PostgreSQL ir_attachment table (db_datas column for small files) and the /filestore/ directory for large files and PDFs. We extract both, reconstruct the filestore directory tree under Dolibarr's /documents/ structure, and create llx_ecm_files records that link the attachment to the target object (llx_societe for company docs, llx_facture for invoices, llx_project_task for task attachments). The original Odoo attachment res_model and res_id are preserved in Dolibarr's ref and ref_id fields so the attachment can be relinked during post-migration cleanup. Binary file content that exceeds Dolibarr's default size limit triggers a separate migration of the /filestore/ directory as a standalone document archive.
| Odoo Enterprise | Dolibarr ERP | Compatibility | |
|---|---|---|---|
| res.partner (Contact / Company) | llx_societe + llx_contact1:many | Fully supported | |
| res.company | llx_societe + llx_const1:1 | Fully supported | |
| product.product + product.template | llx_product1:1 | Fully supported | |
| sale.order + sale.order.line | llx_commande + llx_commandedet1:1 | Fully supported | |
| purchase.order + purchase.order.line | llx_commande_fournisseur + llx_commandedet1:1 | Fully supported | |
| account.move (Customer Invoices) | llx_facture + llx_facturedet1:1 | Fully supported | |
| account.move (Vendor Bills) | llx_facture_fournisseur + llx_facturedet1:1 | Fully supported | |
| project.project + project.task | llx_projet + llx_projet_task1:1 | Fully supported | |
| hr.employee | llx_societe (contact type) + llx_adherent1:1 | Fully supported | |
| stock.quant + stock.move | llx_product_stock + llx_stock_mouvement1:1 | Fully supported | |
| account.account + account.fiscal.position | llx_accounting_account + llx_accounting_fiscal_positionlossy | Fully supported | |
| ir_attachment + filestore | llx_ecm_files + /documents/ tree1:1 | Fully supported |
Gotchas + challenges
Platform-specific issues from each side, plus the pair-specific challenges that don't show up on either platform's page on its own.
Odoo Enterprise gotchas
Enterprise-to-Community downgrade leaves orphaned module references
25% legacy surcharge for older Odoo versions
XML-RPC API lacks public rate limit documentation
Official upgrade service ignores custom and third-party modules
Fiscal localization modules tie accounting data to country
Dolibarr ERP gotchas
Foreign key constraint errors on cross-distribution database restore
SQL injection vulnerabilities in version 9.0.1
Custom fields stored as JSON in extraoptions require field-by-field deserialization
Decimal precision and rounding configuration affects price fields
No native iOS/Android app forces reliance on browser
Pair-specific challenges
Migration approach
Discovery and source audit
We audit the source Odoo Enterprise instance across version (v16, v17, or v18), active modules, PostgreSQL schema size, and custom field count via ir.model.fields. We extract the full module manifest from ir_module_module to identify Enterprise-only modules that will not have a Dolibarr equivalent (CRM Enterprise, POS Enterprise, Documents, Social, IoT, Studio). We document the Odoo version's 25% legacy surcharge exposure for Odoo v16 or earlier per Odoo's April 2026 policy. The discovery output is a written migration scope listing every object to be migrated, every Enterprise module to be flagged as lost, and the recommended Dolibarr version and hosting configuration.
Destination setup and country localization
We install Dolibarr on the customer's target infrastructure (self-hosted VPS, DoliCloud, or a fresh MySQL/PostgreSQL instance) and activate the country-specific accounting localization module matching the customer's operating jurisdiction. We activate the required Dolibarr modules: CRM, Third-party management, Products, Commercial proposals, Customer orders, Supplier orders, Invoices, Projects, Contracts, and the HR/Membership module if employee data is in scope. We activate the webservices module to enable API access; if it is not available on the target plan, we configure direct database write access with a migration user account scoped to INSERT-only on target tables.
Chart of Accounts mapping and accounting configuration
We extract Odoo's account.account records with account_code, name, account_type, and reconcile flag. We map each Odoo account to the nearest equivalent in the activated Dolibarr Chart of Accounts using the country-specific account code ranges. For fiscal positions (account.fiscal.position), we produce a mapping table that aligns Odoo's tax-to-account rules with Dolibarr's localtax mechanism. The accounting configuration step requires a customer accountant sign-off before any invoice or journal entry data migrates. We do not attempt cross-country accounting migration without explicit account code remapping because Dolibarr's validation enforces Chart of Accounts integrity at invoice posting time.
PostgreSQL direct extraction and data scrubbing
We run a direct PostgreSQL read from the Odoo database using SELECT queries scoped to the Odoo PostgreSQL schema (public by default, or a named schema for multi-instance deployments). We extract records in dependency order: res.company first (for multi-branch setups), then res.partner, then product.product and product.template, then sale.order and purchase.order with their line tables, then account.move (posted and draft separately), then project.project and project.task. We scrub any record belonging to an Enterprise-only module from the export set and flag it in the reconciliation report. For the filestore, we use Odoo's filestore path (usually /odoo/filestore/{db_name}/) to package the /attachments/ tree for reconstruction in Dolibarr's /documents/ directory.
Transformation, field mapping, and Dolibarr import
We transform each extracted dataset using the object mapping matrix: res.partner splits into llx_societe and llx_contact; sale.order.line items are restructured to Dolibarr's flat llx_commandedet format; Odoo tax IDs resolve to Dolibarr's localtax1/localtax2 codes. We batch records into chunks of 500 and insert via Dolibarr's REST API (if webservices module is active) or direct MySQL/PostgreSQL multi-row INSERT statements with foreign key lookups resolved at transform time. Each phase emits a row-count reconciliation report (records in Odoo source, records written to Dolibarr, records skipped with reason) before the next phase begins. Validation rules in Dolibarr (required fields on invoice validation, partner code uniqueness) are temporarily bypassed with a migration context flag or disabled via Dolibarr's const table during bulk load and re-enabled at cutover.
Cutover, delta sync, and automation handoff
We freeze writes in the source Odoo instance (typically a 24-48 hour write-freeze window agreed with the customer) and run a final delta migration of any records created or modified since the last extraction. We move the Dolibarr instance to production, validate the record counts, run a spot-check of 25-50 records across each major object, and enable the destination as the system of record. We deliver a written inventory of Odoo Studio custom fields requiring Dolibarr ExtraFields recreation, Odoo automated actions and server actions requiring PHP module development or manual configuration, and Odoo workflows (if any were active in the Odoo instance) with Dolibarr equivalent module recommendations. We provide a one-week hypercare window for reconciliation issues raised by the customer's team.
Platform deep dives
Odoo Enterprise
Source
Strengths
Weaknesses
Dolibarr ERP
Destination
Strengths
Weaknesses
Complexity grading
Standard ERP migration. 1 of 8 objects need a mapping; the rest are 1:1.
Overall complexity
Standard migration
Derived from compatibility, mapping clarity, API constraints, and data volume across Odoo Enterprise and Dolibarr ERP.
Object compatibility
1 of 8 objects need a mapping; the rest are 1:1.
Field mapping clarity
Field mapping is derived from defaults — final spec confirmed during the sample migration.
Timeline complexity
8-object category — typical timelines run 2–7 days end-to-end.
API constraints
Odoo Enterprise: Not publicly documented; timeouts observed on Odoo.sh at high request volumes.
Data volume sensitivity
Odoo Enterprise doesn't expose a bulk API — REST + parallelization used for high-volume runs.
Estimator
Rule-based pricing — no per-record fees, no manual quotes. Migrations over 2M records are scoped individually.
Step 1
Pick a category, then your source and destination platforms.
Category
FAQ
Answers to the questions buyers ask most during Odoo Enterprise to Dolibarr ERP migration scoping. Not seeing yours? Book a call.
Walk through your Odoo Enterprise to Dolibarr ERP migration with a real engineer — 30 minutes, free, written quote within 24 hours.
Book a free 30 minute consultationAdjacent paths
Other ways to leave Odoo Enterprise
Other ways to arrive at Dolibarr ERP
Ready when you are
Tell us record counts and timeline. We'll come back with a written quote inside 1 business day — no commitment, no sales pitch.