ERP migration
Field-level mapping, validation, and rollback between Sales ERP and Odoo ERP. We move data and schema; workflows are rebuilt natively in Odoo ERP.
Sales ERP
Source
Odoo ERP
Destination
Compatibility
10 of 12
objects map 1:1 between Sales ERP and Odoo ERP.
Complexity
BStandard
Timeline
4-8 weeks
Overview
Moving from Sales ERP to Odoo ERP is a schema rewrite, not a record copy. Sales ERP uses Salesforce's composite ID model to maintain parent-child relationships between Accounts, Contacts, Opportunities, Orders, and Contracts. Odoo uses a res.partner-based model where companies and individuals share a single Partner record with address and contact roles, and Sales Orders are tied to partners rather than through multi-level opportunity hierarchies. We preserve the original Salesforce IDs in custom reference fields to resolve lookups during import, and we sequence the extraction against per-org API rate limits that vary from 1,000 to 100,000 calls per day by license tier. Workflows, automations, and Salesforce Flow rules do not migrate; we deliver a written inventory of every active rule and automation for Odoo reconstruction by your admin. Custom objects and custom fields built in Salesforce require pre-provisioning in Odoo before data ingestion begins.
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 Sales ERP 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.
Sales ERP
Account
Odoo ERP
res.partner
1:1Salesforce Account maps to Odoo res.partner with partner_type set to 'company'. The Salesforce Account Name maps to res.partner.name, BillingAddress and ShippingAddress map to partner addresses via res.partner.address fields. Parent Account hierarchy (Salesforce parentId) maps to Odoo's commercial_partner_id field, which Odoo uses to maintain company-group relationships in its partner database. We store the original Salesforce Account ID in a custom field for cross-reference.
Sales ERP
Contact
Odoo ERP
res.partner
1:manySalesforce Contact records map to Odoo res.partner with partner_type set to 'contact', linked to the parent company via parent_id pointing to the Partner record created from the Contact's Account. Each Contact produces one res.partner contact record. Salesforce's Account Contact Relation (ACR) object, which allows a Contact to link to multiple Accounts, maps to Odoo res.partner multiple address roles; we create one Partner contact record per Account-Contact relationship in the ACR.
Sales ERP
Opportunity
Odoo ERP
crm.lead
1:1Salesforce Opportunity maps to Odoo crm.lead with type='opportunity'. The Opportunity Name maps to crm.lead.name, Amount maps to planned_revenue, CloseDate maps to date_deadline, Stage maps to stage_id via a pre-configured Odoo stage mapping, and Probability maps to probability. Opportunity Team Members do not have a direct Odoo equivalent; we assign the primary Salesforce Opportunity owner to the crm.lead user_id and document additional team member roles in a custom text field for manual Odoo team assignment.
Sales ERP
Opportunity Stage
Odoo ERP
crm.lead.stage
lossyEach Salesforce Opportunity StageName maps to an Odoo crm.stage record. We pre-create the stages in Odoo CRM during schema design, preserving the stage probability percentages as Odoo stage probabilities. Closed-Won and Closed-Lost map to Odoo's won and lost stage states.
Sales ERP
Lead
Odoo ERP
crm.lead
1:1Salesforce Lead maps to Odoo crm.lead with type='lead' (separate from opportunities). Lead_Status maps to crm.lead.activity_state, Lead_Source maps to source_id via an Odoo source mapping, and any custom lead scoring fields migrate to crm.lead.priority or a custom float field. We create Odoo CRM stages for the Lead lifecycle before migration.
Sales ERP
Order
Odoo ERP
sale.order
1:1Salesforce Order maps to Odoo sale.order. OrderNumber maps to name, AccountId resolves to the Partner record (from Account mapping), OrderStatus maps to state, TotalAmount maps to amount_total, and EffectiveDate maps to date_order. We pre-create the corresponding Odoo sale.order records after Partners are loaded so that Partner references are satisfied at insert time.
Sales ERP
OrderItem
Odoo ERP
sale.order.line
1:1Salesforce OrderItems map to Odoo sale.order.line records. Product2Id resolves to the mapped Odoo product.product record via SKU lookup, Quantity resolves to product_uom_qty, and UnitPrice resolves to price_unit. We create the product catalog in Odoo before OrderItems ingest so that product_id references are valid.
Sales ERP
Product2
Odoo ERP
product.product
1:1Salesforce Product2 maps to Odoo product.product. ProductName maps to name, ProductCode maps to default_code (SKU), IsActive maps to sale_ok and purchase_ok flags, and Description maps to description_sale. Standard Price Book entries map to Odoo product.pricelist.item records linked to the product.
Sales ERP
Contract
Odoo ERP
account.analytic.account
1:1Salesforce Contract maps to Odoo account.analytic.account for recurring contract tracking. ContractNumber maps to name, AccountId resolves to the Partner, StartDate and EndDate map to date_start and date, and Status maps to recurring_invoice and active flags. If the customer uses Odoo Subscription management (sale_subscription app), Contracts map to subscription.model instead.
Sales ERP
User
Odoo ERP
res.users
1:1Salesforce User records map to Odoo res.users for active licensed users. We resolve by matching Email on User to login on res.users. Inactive Salesforce Users do not migrate to avoid inflating Odoo seat count. Any User without a matching Odoo login is held in a reconciliation queue for the customer's admin to provision before record ingestion.
Sales ERP
Attachments and Notes
Odoo ERP
ir.attachment
1:1Salesforce Notes migrate to Odoo ir.attachment records linked to the parent record (Partner, Sale Order, CRM Lead) via res_model and res_id. Attachments with Base64-encoded content (standard for Salesforce REST API) are decoded and stored in Odoo's attachment storage. We migrate Notes as ir.attachment with internal notes content; email attachments migrate as separate ir.attachment records.
Sales ERP
Custom Object
Odoo ERP
Custom ir.model.data model
1:1Salesforce custom objects (API name ending in __c) require pre-provisioning as Odoo custom models via Python inheritance of models.Model before any data moves. We pre-create the destination Odoo model with the same field names and types as the Salesforce custom object fields, then ingest the custom object records using Odoo's XML-RPC or CSV import API. Salesforce custom object relationships (lookup, master-detail) map to Odoo many2one and one2many fields on the custom model.
| Sales ERP | Odoo ERP | Compatibility | |
|---|---|---|---|
| Account | res.partner1:1 | Fully supported | |
| Contact | res.partner1:many | Fully supported | |
| Opportunity | crm.lead1:1 | Fully supported | |
| Opportunity Stage | crm.lead.stagelossy | Fully supported | |
| Lead | crm.lead1:1 | Fully supported | |
| Order | sale.order1:1 | Fully supported | |
| OrderItem | sale.order.line1:1 | Fully supported | |
| Product2 | product.product1:1 | Fully supported | |
| Contract | account.analytic.account1:1 | Fully supported | |
| User | res.users1:1 | Fully supported | |
| Attachments and Notes | ir.attachment1:1 | Mapping required | |
| Custom Object | Custom ir.model.data model1: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.
Sales ERP gotchas
API rate limits cap daily call volume by license tier
Historical data is often left behind to cut implementation scope
Custom object attachments require Base64 encoding
Object relationships break silently without ID preservation
Data quality issues derail migration timelines
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 source audit
We audit the Salesforce org across license tier (Starter through Unlimited), API rate limit allocation, standard objects in use, custom objects, custom fields, active Workflow Rules and Flows, and engagement volume. We pair this with a review of the Odoo edition (Community free vs Odoo Online/Enterprise at $24.90/user/month) and the modules required: CRM, Sales, Inventory, and Accounting are the most common combination. The discovery output is a written migration scope, a Salesforce API call budget assessment, and an Odoo module selection recommendation.
Odoo schema pre-configuration
We work with the customer's Odoo partner or internal admin to pre-configure the Odoo environment before any data ingestion. This includes provisioning the chart of accounts, configuring fiscal positions and tax rates, creating product categories and warehouse locations, setting up CRM stages mapped from Salesforce Opportunity stages, and installing any required Odoo Apps. Custom Odoo models for Salesforce custom objects are created as Python model classes. Schema is validated in a staging Odoo database before production configuration begins.
Data quality assessment and cleansing
We extract Salesforce record data and run a quality assessment against the scoping agreement. We flag duplicate Accounts, Contacts without parent Accounts, Orders linked to inactive Contracts, Products with missing SKUs, and inactive Users referenced as record owners. We agree on a cleansing rule set with the customer, apply those rules to the source extract, and re-export clean data before ingestion. This step routinely surfaces 10-25 percent record issues in Salesforce orgs that have been in production for more than three years.
Sandbox migration and reconciliation
We run a full migration into an Odoo test database using production-like data volume. The customer's operations lead reconciles record counts (Partners in, Contacts in, Sale Orders in, Products in), spot-checks 25-50 records against the Salesforce source, and validates that parent-account relationships are intact. Any mapping corrections happen in the test migration, not in production.
Owner and User reconciliation
We extract every distinct Salesforce User referenced as Owner on Account, Contact, Opportunity, Order, and custom object records. We match by email against the Odoo destination res.users table. Users without a matching Odoo login go to a reconciliation queue. The customer's Odoo admin provisions any missing users before production migration. Owner resolution must complete before standard object ingestion because OwnerId references are validated at import time.
Production migration in dependency order
We run production migration in record-dependency order: Partners (from Salesforce Accounts and Contacts), CRM Leads (from Salesforce Leads and Opportunities as type='lead'), CRM Opportunities (from Salesforce Opportunities as type='opportunity'), Products (from Salesforce Product2), Sale Orders (from Salesforce Orders with Partner references resolved), Order Lines (with Product references resolved), custom object records (last, after all parent objects are loaded), and Attachments/Notes. Each phase emits a row-count reconciliation report before the next phase begins.
Cutover, validation, and automation handoff
We freeze Salesforce writes during cutover, run a final delta migration of any records modified during the migration window, then enable Odoo as the system of record. We deliver the Salesforce automation inventory document with Odoo automated action equivalents for the customer's admin or Odoo partner to rebuild. We support a one-week hypercare window where we resolve reconciliation issues. We do not rebuild Salesforce Workflows or Flows as Odoo server actions inside the migration scope; that is a separate engagement.
Platform deep dives
Sales ERP
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 Sales ERP 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
Sales ERP: 1,000 to 100,000 API calls per day depending on license tier; concurrent request limits also apply.
Data volume sensitivity
Sales ERP exposes a bulk API — large-volume migrations stream efficiently.
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 Sales ERP to Odoo ERP migration scoping. Not seeing yours? Book a call.
Walk through your Sales ERP 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 Sales ERP
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.