CRM migration
Field-level mapping, validation, and rollback between Odoo CRM and Salesforce Sales Cloud. We move data and schema; workflows are rebuilt natively in Salesforce Sales Cloud.
Odoo CRM
Source
Salesforce Sales Cloud
Destination
Compatibility
6 of 12
objects map 1:1 between Odoo CRM and Salesforce Sales Cloud.
Complexity
BStandard
Timeline
3-5 weeks
Try the reverse
Overview
Moving from Odoo CRM to Salesforce Sales Cloud is a structural migration because Odoo stores Leads and Opportunities in a single crm.lead table differentiated only by a type field, while Salesforce separates them into distinct Lead and Opportunity objects. The more complex challenge is Odoo's res.partner model, which is polymorphic — it stores both companies and individual contacts in one table — and Salesforce requires Accounts and Contacts as separate objects with a parent lookup relationship. We resolve the Partner split during scoping by analyzing parent_id links and contact_type fields, then map company-type partners to Account and individual-type partners to Contact with AccountId resolved. We preserve the original Odoo crm.lead type field as a custom field on both Lead and Opportunity for audit. Server Actions, automation rules, and Odoo AI lead scoring do not migrate to Salesforce Flow; we deliver a written inventory for the customer's admin to rebuild. Activity history (calls, emails, meetings, tasks) migrates through the Salesforce Bulk API 2.0 with WhoId and WhatId parent-record resolution so the timeline attaches to the correct Contact and Opportunity in the destination.
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.
Source platform
Odoo CRM platform overview
Scorecard, SWOT, gotchas, and pricing for Odoo CRM.
Destination platform
Salesforce Sales Cloud platform overview
Scorecard, SWOT, gotchas, and pricing for Salesforce Sales Cloud.
Data migration guide
The complete Salesforce migration guide
Data model, import mechanisms, field mapping strategy, pitfalls, and cutover — by the engineers running it.
Source platform guide
Odoo CRM migration guide
Understand the data you're exporting from Odoo CRM before mapping it.
Destination checklist
Salesforce migration checklist
Pre- and post-cutover tasks for moving onto Salesforce Sales Cloud.
Source checklist
Odoo CRM migration checklist
Exit checklist for unwinding your Odoo CRM setup cleanly.
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 CRM object lands in Salesforce Sales Cloud, including any object-level transformations, lookup resolution, or schema-design dependencies.
Typical mapping — final map is confirmed during the sample migration step.
Odoo CRM
Contact / Partner
Salesforce Sales Cloud
Account and Contact
1:manyOdoo res.partner is polymorphic — it stores both company records (contact_type='contact' or blank) and individual contact records linked to a company via parent_id. We split by analyzing parent_id chains and contact_type values: partner records with no parent_id and contact_type indicating a company become Salesforce Account records. Their children with parent_id set become Salesforce Contact records with AccountId resolved. Partner records that are standalone individuals without a parent_id company create an Account with the same name and a Contact linked to it. The Odoo partner ID is preserved in a custom field odoo_partner_id__c for reconciliation.
Odoo CRM
Lead
Salesforce Sales Cloud
Lead
1:1Odoo crm.lead records with type='lead' (not yet converted to an Opportunity) map directly to Salesforce Lead. The Odoo partner_id is resolved to the target Account or Contact created in step 1, and if no match exists a Contact is created inline. Email, phone, company name, source, and any custom fields map to equivalent Salesforce Lead fields. The original Odoo crm.lead ID is preserved in odoo_lead_id__c.
Odoo CRM
Opportunity
Salesforce Sales Cloud
Opportunity
1:1Odoo crm.lead records with type='opportunity' map to Salesforce Opportunity. The partner_id (Odoo contact) is resolved to a Salesforce Contact and Account, and AccountId is set accordingly. Fields including expected_revenue, probability, date_close, name, and description map directly. Odoo's stage_id resolves to the Salesforce Opportunity StageName via the stage mapping defined in the pipeline configuration step. The Odoo crm.lead ID is preserved in odoo_lead_id__c.
Odoo CRM
Pipeline Stage
Salesforce Sales Cloud
Opportunity Stage
lossyOdoo crm.stage values migrate as Salesforce Opportunity StageName entries with probability percentages preserved from Odoo's stage probability. Stage sequence order is maintained. If the customer uses multiple Odoo pipelines, we create multiple Salesforce Sales Processes and assign them to Opportunity Record Types per pipeline. Stage probability maps to StageProbability in Salesforce, rounded to the nearest allowed integer value.
Odoo CRM
Sales Team
Salesforce Sales Cloud
Public Group or Custom Territory Field
lossyOdoo crm.team groups Opportunities and assigns Leads via user_id and member_ids. Salesforce has no direct crm.team equivalent at standard tiers — Territory Management is an add-on. We map each Odoo team to either a Salesforce Public Group (team members as members), a custom picklist field crm_team__c on Opportunity, or a queue if territory-based routing is required. The customer selects the approach during scoping. Team-level stage configurations in Odoo become Salesforce Sales Processes assigned to Record Types.
Odoo CRM
Activity (mail.activity)
Salesforce Sales Cloud
Task (TaskSubtype = Call, Email, Meeting, or generic)
1:1Odoo mail.activity records linked to crm.lead migrate to Salesforce Task records with TaskSubtype set from Odoo's activity_type_id (call, email, meeting, or other). Activity date_deadline and note migrate to Task ActivityDate and Description. Owner assignment maps via email from Odoo user_id to the Salesforce User lookup. High-volume activity migrations use the Salesforce Bulk API 2.0 with WhoId and WhatId resolved to the migrated Lead, Contact, or Opportunity ID. Activity records without a resolvable parent are held in a reconciliation queue.
Odoo CRM
Custom Fields (crm.lead)
Salesforce Sales Cloud
Custom Fields (Lead, Contact, Opportunity)
lossyOdoo custom fields defined via Studio or in custom addon modules are stored as columns in crm.lead or res.partner. We export field definitions (name, type, selection options, relational target) and pre-create matching Salesforce custom fields before the data migration phase. Field types are mapped: Odoo selection fields become Salesforce picklists or multi-select picklists; many2one becomes a lookup; many2many becomes a multi-select picklist or junction object; char and text become text or textarea. If the custom field is defined in an addon module not deployed in the target, we document it and flag it as data-only (present in database, no UI definition).
Odoo CRM
Attachment (ir.attachment)
Salesforce Sales Cloud
ContentDocument (Salesforce Files)
1:1Odoo ir.attachment records linked to crm.lead are stored in the Odoo filestore as binary files. We export the filestore contents, chunking by subdirectory and record reference. Files are uploaded to Salesforce via the Connect API (Chunks for large files) and linked via ContentDocumentLink to the migrated Lead, Contact, Account, or Opportunity. ir.attachment.res_model and res_id are mapped to the corresponding Salesforce object and record ID. Large attachment volumes (over 50,000 files) require staged migration with the customer's storage allocation confirmed before the upload phase begins.
Odoo CRM
Tag (crm.tag)
Salesforce Sales Cloud
Custom Multi-Select Picklist or Topic
lossyOdoo crm.tag records applied to crm.lead via many2many are exported as a flat tag list. Tags used for lead categorization migrate to a Salesforce custom multi-select picklist field on Lead (lead_tags__c) or Opportunity (opp_tags__c), or to Salesforce Topics if the customer uses topic-based classification. Tag names are normalized (trimmed, de-duplicated) before import. The customer selects the tagging strategy during scoping.
Odoo CRM
Quotation / Sale Order (sale.order)
Salesforce Sales Cloud
Opportunity with Products or Quote
1:manyOdoo sale.order records linked to crm.lead migrate as Salesforce Opportunity records if the destination is Sales Cloud only, or as Salesforce Quote records if the destination includes the Salesforce CPQ bundle or Sales Cloud Quote management. Odoo sale.order.line records migrate as OpportunityLineItems (if mapping to Opportunity) or QuoteLineItems (if mapping to Quote). Product2 and PricebookEntry are created from Odoo product.product before line item migration. Tax and discount fields map to Salesforce equivalents where available; custom fiscal or tax logic is documented separately.
Odoo CRM
Lead Scoring Rule (crm.scoring.rule)
Salesforce Sales Cloud
Salesforce Einstein Lead Scoring or Custom Field
1:1Odoo AI lead scoring (crm.scoring.rule) is an Enterprise-only feature with a proprietary scoring algorithm trained on Odoo's behavioral data. It has no direct Salesforce equivalent. We do not migrate scoring rules. If the customer licenses Salesforce Einstein Lead Scoring (available from Sales Cloud Professional), we document the top Odoo scoring fields and their relative weights as a reference for manual Einstein configuration. The scoring rule inventory is included in the delivered documentation.
Odoo CRM
Automation Rule (base.action.rule, ir.actions.server)
Salesforce Sales Cloud
Salesforce Flow (record-triggered)
1:1Odoo CRM automation rules scoped to crm.lead (base.action.rule, ir.actions.server) are Enterprise-exclusive and tightly coupled to Odoo's action framework. They do not migrate to Salesforce Flow because the trigger conditions, action types, and delay models differ. We deliver a written inventory of every active automation rule with its trigger object, conditions, actions, and recommended Salesforce Flow alternative, including whether the automation maps to a record-triggered Flow, scheduled Flow, or Platform Event pattern. The customer's admin or a Salesforce partner rebuilds them post-migration.
| Odoo CRM | Salesforce Sales Cloud | Compatibility | |
|---|---|---|---|
| Contact / Partner | Account and Contact1:many | Fully supported | |
| Lead | Lead1:1 | Fully supported | |
| Opportunity | Opportunity1:1 | Fully supported | |
| Pipeline Stage | Opportunity Stagelossy | Fully supported | |
| Sales Team | Public Group or Custom Territory Fieldlossy | Fully supported | |
| Activity (mail.activity) | Task (TaskSubtype = Call, Email, Meeting, or generic)1:1 | Fully supported | |
| Custom Fields (crm.lead) | Custom Fields (Lead, Contact, Opportunity)lossy | Fully supported | |
| Attachment (ir.attachment) | ContentDocument (Salesforce Files)1:1 | Fully supported | |
| Tag (crm.tag) | Custom Multi-Select Picklist or Topiclossy | Fully supported | |
| Quotation / Sale Order (sale.order) | Opportunity with Products or Quote1:many | Fully supported | |
| Lead Scoring Rule (crm.scoring.rule) | Salesforce Einstein Lead Scoring or Custom Field1:1 | Fully supported | |
| Automation Rule (base.action.rule, ir.actions.server) | Salesforce Flow (record-triggered)1: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 CRM gotchas
Odoo.sh version gating blocks assisted migrations from trial
Enterprise modules fail to install on Community after database restore
Custom module view inheritance breaks between Odoo major versions
Custom fields risk losing their application context on Community
API access for Community is gated behind the Custom Plan
Salesforce Sales Cloud gotchas
Workflow Rules and Process Builder are retired
Bulk API batch quota exhaustion during large imports
Storage overage billing is non-obvious
Account-Contact many-to-many relationship mapping
Territory and team member import ordering dependencies
Pair-specific challenges
Migration approach
Discovery and Odoo schema audit
We audit the source Odoo database via direct PostgreSQL read access or XML-RPC (depending on edition). We catalog crm.lead record counts split by type (lead vs opportunity), res.partner record counts by contact_type and parent_id relationship, crm.stage pipeline stage values, crm.team membership, mail.activity volume, ir.attachment count and filestore size, crm.tag distinct values, sale.order count, and any custom fields stored in crm.lead or res.partner. We also identify Enterprise-only installed modules via ir_module_module to flag any data from those modules that requires customer acknowledgment before migration. The discovery output is a written scope document with record counts, custom field inventory, and the res.partner splitting strategy.
Salesforce destination schema design
We design the Salesforce destination schema in a Sandbox org. This includes pre-creating all custom fields (odoo_partner_id__c, odoo_lead_id__c, odoo_crm_team__c, lead_tags__c, and any custom fields from Odoo custom addons), defining Opportunity Stage entries matching the Odoo crm.stage pipeline, creating Sales Processes and Record Types per Odoo pipeline, and configuring Public Groups or the crm_team__c picklist for Odoo Sales Team mapping. Schema is deployed via Salesforce Metadata API into the Sandbox. The customer reviews the schema design and confirms the res.partner splitting logic before production migration begins.
Sandbox migration and reconciliation
We run a full migration into a Salesforce Sandbox using production-equivalent data volume. The customer reconciles record counts (Accounts, Contacts, Leads, Opportunities, Activities), spot-checks 25-50 records against the Odoo source, and reviews the Partner splitting results to confirm that no contacts are orphaned without an Account. Mapping corrections identified during sandbox reconciliation are applied to the migration scripts before the production migration. The customer signs off the sandbox results in writing before we proceed to production.
Owner reconciliation and User provisioning
We extract every distinct user_id referenced on crm.lead, crm.team, and mail.activity records and match by email against the destination Salesforce org's User table. Odoo users without a matching Salesforce User are held in a reconciliation queue. The customer's Salesforce admin provisions any missing Users (active for current team members, inactive for departed users) before record import resumes. OwnerId lookups on Opportunity and Lead cannot be resolved without User records, so this step gates the production migration.
Production migration in dependency order
We run production migration in strict record-dependency order: Accounts (from company-type res.partner records), Contacts (from individual-type res.partner records with parent_id resolved to AccountId), Leads (from crm.lead with type='lead'), Opportunities (from crm.lead with type='opportunity' with AccountId and OwnerId resolved), Activities (Tasks via Bulk API 2.0 with WhoId and WhatId resolved to migrated IDs), Attachments (uploaded to Salesforce Files and linked via ContentDocumentLink), Tags (as multi-select picklist values or Topics), Custom fields (loaded into pre-created custom field columns), and Quotations (as Opportunity with Products or Quote records). Each phase emits a row-count reconciliation report and the customer validates before the next phase begins.
Cutover, validation, and automation inventory handoff
We freeze Odoo write access during cutover, run a final delta migration for any records modified during the cutover window, then enable Salesforce as the system of record. We validate record counts, cross-reference 25 random Opportunities against their Odoo source values, and confirm the Partner split produced no orphaned Contacts. We deliver the automation inventory document listing every active Odoo automation rule with its trigger, conditions, and recommended Salesforce Flow equivalent. We do not rebuild Odoo automation as Salesforce Flow within the migration scope; that is a separate engagement. We support a one-week hypercare window for reconciliation issues raised by the customer's sales team.
Platform deep dives
Odoo CRM
Source
Strengths
Weaknesses
Salesforce Sales Cloud
Destination
Strengths
Weaknesses
Complexity grading
Standard CRM 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 CRM and Salesforce Sales Cloud.
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 CRM: Not publicly documented; no published rate limit found in Odoo's official developer documentation.
Data volume sensitivity
Odoo CRM 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 CRM to Salesforce Sales Cloud migration scoping. Not seeing yours? Book a call.
Walk through your Odoo CRM to Salesforce Sales Cloud 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 CRM
Other ways to arrive at Salesforce Sales Cloud
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.