ERP migration
Field-level mapping, validation, and rollback between metasfresh and Odoo ERP. We move data and schema; workflows are rebuilt natively in Odoo ERP.
metasfresh
Source
Odoo ERP
Destination
Compatibility
6 of 11
objects map 1:1 between metasfresh and Odoo ERP.
Complexity
BStandard
Timeline
6-8 weeks
Overview
metasfresh and Odoo ERP are both open-source ERPs, but they differ fundamentally in how data is accessed and in the breadth of their ecosystems. metasfresh has no well-documented public REST API; migrations require direct PostgreSQL reads against the source database using read-only credentials. Odoo exposes XML-RPC, JSON-RPC, and a REST API for inbound data loading, so the migration pipeline ends in Odoo's API rather than in a flat-file loader. The metasfresh ADempiere-rooted data model (Business Partners, Products, multi-table Orders, BOMs, Pricing Systems) maps to Odoo's res.partner, product.product, sale.order/purchase.order, account.move, mrp.bom, and product.pricelist structures. We preserve partner type (customer versus vendor), BOM component relationships, pricing version effective dates, and project hierarchy throughout. Automations, workflows, and DATEV-specific export configurations do not migrate; we deliver a written inventory of these for the customer's Odoo admin to rebuild.
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 metasfresh object lands in Odoo ERP, including any object-level transformations, lookup resolution, or schema-design dependencies.
Typical mapping — final map is confirmed during the sample migration step.
metasfresh
Business Partners
Odoo ERP
res.partner
1:1metasfresh Business Partners (C_BPartner table) cover both customers and vendors with roles stored in the PartnerType property. We map vendor records to res.partner with type=supplier, customer records to res.partner with type=contact or type=company depending on whether the record has sub-contact entries. metasfresh contact persons stored in AD_User map to additional res.partner records linked via parent_id to the owning company partner. Bank account references stored in C_BP_BankAccount map to res.partner.bank_ids in Odoo. Address and location data from C_Location transfers to res.partner (street, city, country, zip). The is_customer and is_vendor boolean flags from metasfresh set the corresponding flags on res.partner. We preserve the metasfresh BPartner value (document number) as a reference field for audit traceability.
metasfresh
Products
Odoo ERP
product.product / product.template
1:1metasfresh products (M_Product and M_Product_Category) map to Odoo product.template with product.product variants when the metasfresh product has attribute values set. The M_Product_Category hierarchy becomes product.category in Odoo. Product codes (value) map to default_code, SKUs from the XLS export map to barcodes, and product types (item vs service) map to Odoo's type field (product vs service). If metasfresh uses multi-variant products via its attribute system, we split into product.template plus product.product variants in Odoo. Products without variants create a single product.product record with no variants. Stockable, consumable, and service product types all transfer directly.
metasfresh
Bill of Materials
Odoo ERP
mrp.bom
1:1metasfresh BOM data lives in pp_product_bom and pp_product_bomline tables, with dependencies on the MRP module that must be confirmed active during discovery. Each pp_product_bom record maps to Odoo mrp.bom with bom_line records for every component. The pp_product_bomline quantities_per_bom and is_active flags transfer to Odoo's product_qty and active fields. Component products are resolved to their Odoo product.product IDs before bom_line insert. We inspect the PP_Product_BOM table during discovery to confirm the MRP module is populated; BOM migration is skipped if the tables are empty. Work center and routing data (pp_order_bomrecord) maps to mrp.routing_workcenter if the metasfresh installation uses routings.
metasfresh
Sales Orders and Purchase Orders
Odoo ERP
sale.order / purchase.order
1:manymetasfresh orders span the C_Order header and C_OrderLine lines table with a document direction flag determining whether an order is a sales or purchase document. We split on that direction flag: sales orders map to Odoo sale.order with sol lines; purchase orders map to Odoo purchase.order with pol lines. Order document status (draft, in progress, completed, closed, cancelled) maps to Odoo's state field. Header-level financial terms (pricing list, payment rule, incoterms) transfer to the Odoo order header; line-level discount, tax, and quantity fields transfer to each order line. Completed and closed orders migrate as confirmed records; draft orders migrate as draft in Odoo. Order-to-order references (linking a purchase order to a sales order) are preserved as notes or via the Odoo procurement group if the customer activates the supply chain module.
metasfresh
Invoices
Odoo ERP
account.move (Customer Invoice / Vendor Bill)
1:manymetasfresh invoices are stored in C_Invoice (header) and C_InvoiceLine (lines) with a DocStatus flag that determines whether the record is a Customer Invoice (AR) or Vendor Bill (AP). We split on document type: AR invoices map to Odoo account.move with move_type=out_invoice, AP invoices map to move_type=in_invoice. Payment terms stored in C_PaymentTerm resolve to account.payment.term lines in Odoo. Tax lines in C_Tax are resolved to account.tax records in Odoo before invoice import so that tax_id lookups succeed. The invoice-to-order reference (C_Invoice.C_Order_ID) is preserved as a link to the corresponding Odoo sale.order or purchase.order. Historical invoices with DocStatus=CO (completed) and payment records in C_Payment are migrated together so that Odoo shows open or paid state accurately.
metasfresh
Pricing Systems and Price Lists
Odoo ERP
product.pricelist / product.pricelist.version
1:manymetasfresh pricing organizes into M_PricingSystem containing multiple M_PriceList versions with effective-from dates. Each M_PriceList maps to Odoo product.pricelist, and each M_PriceList_Version becomes a product.pricelist.version record linked to its parent pricelist. Price list item records (M_PriceListItem) map to product.pricelist.item with the original metasfresh price, surcharge, and discount percentage fields transferred to Odoo's base_price, price_surcharge, and percent_price. We order version inserts by effective date so that the correct price is active on the correct date in Odoo. Currency data from C_Currency maps to res.currency; the customer country pricing rules in metasfresh become Odoo country_id rules on the pricelist item.
metasfresh
Projects and Project Lines
Odoo ERP
project.project / project.task
1:1metasfresh projects (C_Project header plus project lines tracking time, costs, and deliverables) map to Odoo project.project with project.task records for each project line. Project phases stored as C_ProjectPhase map to Odoo task records with the parent project reference. Milestones map to Odoo milestones if the Odoo project module version supports them. The owning Business Partner reference on the metasfresh project transfers as partner_id on the Odoo project. Project status, dates, and budget information migrate to project.project fields. Deliverables and costs stored in project line columns map to task description and task-level planned/actual hour fields.
metasfresh
Bank Accounts and Payment Terms
Odoo ERP
res.partner.bank / account.payment.term
1:1metasfresh bank accounts stored per organization in C_BP_BankAccount map to res.partner.bank records in Odoo with the IBAN, SWIFT/BIC, and bank name fields transferred. Payment terms (net 30, net 60, 2/10 net 30) stored in C_PaymentTerm map to Odoo account.payment.term with line definitions matching the metasfresh discount days, discount percentage, and net days. These reference records must migrate before Orders and Invoices so that the payment term lookups are satisfied at insert time.
metasfresh
Tax Categories and Tax Codes
Odoo ERP
account.tax / account.tax.group
1:1metasfresh tax configuration in C_Tax with country and effective date ranges maps to Odoo account.tax with the rate, tax_scope (sale vs purchase vs none), and applicable countries transferred. Tax groups from C_TaxCategory map to account.tax.group in Odoo. metasfresh uses taxIncludedInPrice flags that we translate to Odoo's price_include field on account.tax. Tax jurisdictions per geographic zone become Odoo tax.repartition.line records for the customer tax accounts if the Odoo country localization module supports it. We preserve effective-from dates so that the correct tax rate is active in Odoo on the correct date.
metasfresh
Complaints and Service Repairs
Odoo ERP
helpdesk.ticket or project.project
lossymetasfresh customer complaints and repair workflows create service project records linked to returned products (C_Project with project category = service/repair). These migrate to Odoo helpdesk.ticket if the customer activates the Odoo Helpdesk module, or to project.project with a service task type if Helpdesk is not in scope. The link back to the originating sales order is preserved as a note on the ticket or project record. We flag this object as configuration-dependent and confirm the customer's Odoo app set during scoping.
metasfresh
Custom Fields (AD_Column extensions)
Odoo ERP
ir.model.fields
lossymetasfresh custom fields added via the Table and Column system are stored as rows in AD_Column with a custom flag. They are not surfaced in metasfresh's standard export format. We query AD_Column during the discovery phase to identify all custom fields per table and add them as additional columns to the export. In Odoo, we pre-create each custom field as ir.model.fields with the correct type (Char, Integer, Many2one, Selection, etc.) before the relevant object migration begins. The custom field identification and Odoo schema extension step adds approximately one to two days to the discovery phase.
| metasfresh | Odoo ERP | Compatibility | |
|---|---|---|---|
| Business Partners | res.partner1:1 | Fully supported | |
| Products | product.product / product.template1:1 | Fully supported | |
| Bill of Materials | mrp.bom1:1 | Fully supported | |
| Sales Orders and Purchase Orders | sale.order / purchase.order1:many | Fully supported | |
| Invoices | account.move (Customer Invoice / Vendor Bill)1:many | Mapping required | |
| Pricing Systems and Price Lists | product.pricelist / product.pricelist.version1:many | Mapping required | |
| Projects and Project Lines | project.project / project.task1:1 | Mapping required | |
| Bank Accounts and Payment Terms | res.partner.bank / account.payment.term1:1 | Fully supported | |
| Tax Categories and Tax Codes | account.tax / account.tax.group1:1 | Fully supported | |
| Complaints and Service Repairs | helpdesk.ticket or project.projectlossy | Mapping required | |
| Custom Fields (AD_Column extensions) | ir.model.fieldslossy | Mapping required |
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.
metasfresh gotchas
No well-documented public REST API for data migration
Attachment and archived document extraction is unreliable
BOM and manufacturing data requires deep schema knowledge
Custom fields discovered at runtime, not import time
Odoo ERP gotchas
No rollback for CSV imports
External ID conflicts on re-import
Many2many field encoding in CSV imports
Large export timeouts require batching
Version schema drift between Odoo releases
Pair-specific challenges
Migration approach
Discovery and PostgreSQL schema inspection
We connect to the metasfresh PostgreSQL instance using read-only credentials provided by the customer. We run discovery queries against the core tables (C_BPartner, M_Product, M_Product_Category, M_Product_BOM, C_Order, C_Invoice, M_PricingSystem, M_PriceList, C_Project, C_PaymentTerm, C_Tax, AD_Column) to assess record counts, data freshness, and the presence of custom fields. We confirm whether the MRP module is active (pp_product_bom tables populated) and whether the metasfresh installation uses multi-company configuration or custom table extensions. The discovery output is a written migration scope covering object counts, identified data quality issues, and a confirmed object-to-object mapping plan.
Odoo destination schema design
We design the Odoo destination schema based on the discovery output. This includes provisioning product categories, product templates and variants, price lists with versioned entries, the Manufacturing app (mrp.bom, mrp.routing_workcenter) if BOM data is in scope, account.tax and account.tax.group records matched to metasfresh tax rates and effective dates, account.payment.term records, res.partner.bank records for bank account reference data, and custom fields on each target model identified from AD_Column. Schema is deployed into an Odoo test database or sandbox instance first. We coordinate with the customer's Odoo partner or admin to confirm the correct country localization module (l10n_de, l10n_fr, etc.) is activated so that chart of accounts and tax defaults are pre-populated.
Pilot migration and data quality resolution
We run a full migration into the Odoo test instance using representative data volumes (a sample of each object type, not a full extract) to validate the PostgreSQL-to-Odoo pipeline end to end. This pilot surfaces blocking issues: missing required Odoo fields on metasfresh records, foreign key lookup failures (e.g., a metasfresh order with a null partner_id), and duplicate BPartner records that violate Odoo's uniqueness constraints. We deliver a data quality report listing every record that requires resolution, categorized by severity. The customer cleans or approves each batch before we proceed to production migration. No production migration begins until the pilot migration achieves greater than 99% record acceptance.
Production migration in dependency order
We run production migration in strict dependency order so that foreign key lookups succeed at each phase: reference data first (payment terms, tax codes, product categories, bank accounts), then master data (partners, products, price lists and versions, BOMs), then transactional data (sales orders, purchase orders, invoices). Each phase emits a row-count reconciliation report comparing records inserted in Odoo against the PostgreSQL source count. Custom fields are included in each phase insert as additional columns, not as a separate post-migration step. Discrepancies are investigated and corrected before the next phase begins.
Cutover, delta migration, and validation
We freeze writes to metasfresh at a defined cutover moment, extract any records modified during the migration window as a delta load, and insert them into Odoo. We run a final reconciliation comparing Odoo totals (partner count, product count, order count, invoice count, BOM line count) against metasfresh totals for each object type. The customer's operations lead spot-checks a sample of migrated records against the metasfresh source for accuracy of field values and preservation of document relationships. Any remaining mapping corrections are applied in Odoo directly. The metasfresh instance is left in read-only archive mode. We do not decommission the source system; that decision is the customer's.
Automation and workflow rebuild handoff
We deliver a written inventory of metasfresh workflow configurations, automation rules, and any DATEV-specific export setups that cannot migrate to Odoo as code. The inventory documents each metasfresh workflow trigger, conditions, and actions with a recommended Odoo counterpart (automated actions, server actions, or Odoo Workflow configuration). DATEV export configurations are documented for the customer's tax advisor and Odoo localization partner to rebuild using Odoo's l10n_de module or a certified DATEV-compatible accounting module from the Odoo Apps store. We do not rebuild metasfresh automations or DATEV configurations inside the migration scope.
Platform deep dives
metasfresh
Source
Strengths
Weaknesses
Odoo 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 metasfresh and Odoo 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
metasfresh: Not publicly documented.
Data volume sensitivity
metasfresh 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 metasfresh to Odoo ERP migration scoping. Not seeing yours? Book a call.
Walk through your metasfresh to Odoo 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 metasfresh
Other ways to arrive at Odoo 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.