CRM migration
Field-level mapping, validation, and rollback between Salesforce Sales Cloud and Odoo CRM. We move data and schema; workflows are rebuilt natively in Odoo CRM.
Salesforce Sales Cloud
Source
Odoo CRM
Destination
Compatibility
15 of 16
objects map 1:1 between Salesforce Sales Cloud and Odoo CRM.
Complexity
BStandard
Timeline
4-6 weeks
Try the reverse
Overview
Moving from Salesforce Sales Cloud to Odoo CRM is an ERP-first migration, not a like-for-like CRM replacement. Salesforce stores data in a relational object graph with REST, Bulk, and Composite APIs; Odoo uses a Python/PostgreSQL model where CRM (crm.lead), Contacts (res.partner), and Accounts (res.partner in company mode) share the same partner table under different contexts. We resolve the Account-Contact distinction explicitly — Salesforce keeps Accounts and Contacts as separate objects with a junction table; Odoo models the same entity as a res.partner record with a contact_type flag. We extract Salesforce data via the Bulk API with batch pacing against the 15,000-batch daily quota, clean and transform records in staging, and load them into Odoo through its native XML/CSV import or the XML-RPC API. Apex triggers, Visualforce pages, and Salesforce Flow automations do not migrate as code — we deliver a written map of every active trigger and workflow with an Odoo automated action or Python module equivalent for the customer's functional team to rebuild post-migration.
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
Salesforce Sales Cloud platform overview
Scorecard, SWOT, gotchas, and pricing for Salesforce Sales Cloud.
Destination platform
Odoo CRM platform overview
Scorecard, SWOT, gotchas, and pricing for Odoo CRM.
Data migration guide
The complete Odoo CRM migration guide
Data model, import mechanisms, field mapping strategy, pitfalls, and cutover — by the engineers running it.
Source platform guide
Salesforce migration guide
Understand the data you're exporting from Salesforce Sales Cloud before mapping it.
Destination checklist
Odoo CRM migration checklist
Pre- and post-cutover tasks for moving onto Odoo CRM.
Source checklist
Salesforce migration checklist
Exit checklist for unwinding your Salesforce Sales Cloud 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 Salesforce Sales Cloud object lands in Odoo CRM, including any object-level transformations, lookup resolution, or schema-design dependencies.
Typical mapping — final map is confirmed during the sample migration step.
Salesforce Sales Cloud
Account
Odoo CRM
res.partner (contact_type = company)
1:1Salesforce Account maps to Odoo res.partner with contact_type = company. The Account Name becomes the partner's name, Industry maps to industry_id, Type maps to customer_rank (1 for customer, 0 otherwise), and Annual Revenue maps to a custom float field. Parent-Account hierarchies in Salesforce become parent_id on res.partner — we import top-level Accounts first, then resolve parent_id for child Accounts in a second pass. Account Team Members are handled as a separate pass against crm.team membership.
Salesforce Sales Cloud
Contact
Odoo CRM
res.partner (contact_type = contact)
1:1Salesforce Contact maps to Odoo res.partner with contact_type = contact. The contact's Name, Email, Phone, Title, and Department migrate directly. AccountId maps to parent_id on the res.partner, establishing the company-contact hierarchy in Odoo. The AccountContactRelation junction (many-to-many) maps to a separate pass creating additional parent_id records or child contacts under each related Account — we import all Contacts after parent Accounts are committed.
Salesforce Sales Cloud
Lead
Odoo CRM
crm.lead
1:1Salesforce Lead maps to Odoo crm.lead (in pipeline mode, not the merged lead/opportunity model). LeadSource, Status, Rating, and AnnualRevenue map directly to crm.lead source_id, stage_id, priority, and planned_revenue. Any custom Lead fields migrate to custom Char, Float, or Selection fields on crm.lead. Converted Leads in Salesforce create Account + Contact + Opportunity — in Odoo, the same lifecycle maps to a single crm.lead that moves through stages to won/lost with a linked partner_id (from the Account) and an optional sale_order_id (from the converted Opportunity).
Salesforce Sales Cloud
Opportunity
Odoo CRM
crm.lead (won/lost stage) or sale.order
1:manySalesforce Opportunity maps to Odoo crm.lead for pipeline tracking and sale.order for active quotes and orders. StageName maps to crm.lead stage_id with probability percentages preserved. Amount maps to planned_revenue. Close Date maps to date_deadline. When an Opportunity reaches Closed-Won in Salesforce, we create an Odoo sale.order carrying the same account, partner, amount, and line items. When it reaches Closed-Lost, we set the stage to Odoo's lost stage with a lost_reason field populated from Salesforce's Loss Reason.
Salesforce Sales Cloud
Opportunity Product / Price Book Entry
Odoo CRM
product.product / product.pricelist
1:1Salesforce Products (Product2) map to Odoo product.product with a product_tmpl_id link. Standard Price Book maps to Odoo product.pricelist with price list items migrated as product.pricelist.item records. Opportunity Line Items map to sale.order.line with price, quantity, and discount preserved. Pricebook2Id on the Opportunity resolves to the correct product.pricelist on the sale.order.
Salesforce Sales Cloud
Case
Odoo CRM
helpdesk.ticket
1:1Salesforce Case maps to Odoo helpdesk.ticket (a module within the Odoo suite). Case Status maps to ticket stage_id, Priority maps to priority, Origin maps to category_id or a custom selection field, and the ContactId maps to the res.partner created from the original Contact. Cases with open Tasks or Events have those Activities migrated separately as Odoo mail.message or project.task records linked to the ticket. If the customer does not activate the helpdesk module, Cases map to project.task as an alternative.
Salesforce Sales Cloud
Campaign
Odoo CRM
marketing.campaign
1:1Salesforce Campaign maps to Odoo marketing.campaign. Campaign Name, Budget, Status, Type, and StartDate/EndDate migrate directly. Campaign Members (Contacts and Leads who responded) map to marketing.utm.mixin records linked to the campaign, preserving Member Status (Sent, Responded, Handled). Campaign Member custom fields migrate to custom fields on marketing.utm.mixin.
Salesforce Sales Cloud
Contract
Odoo CRM
account.move / contract.contract
1:1Salesforce Contract maps to Odoo account.move (for posted invoices) or contract.contract (for recurring billing if the customer activates Odoo's Contract module). Contract Start Date, End Date, Term, Status, and the linked AccountId map directly. Contract Line Items map to account.move.line records. If the customer uses Odoo Subscription Management, Contracts map to sale.subscription instead, preserving recurring_price and recurring_rule_type.
Salesforce Sales Cloud
Order
Odoo CRM
sale.order
1:1Salesforce Order maps to Odoo sale.order. Order Status, Effective Date, and the linked AccountId and ContractId migrate directly. Order Products map to sale.order.line. If the Salesforce org uses Advanced Order Management or Revenue Cloud, order lineage is more complex — we scope this during the pre-migration audit and flag any non-standard Order-to-Opportunity linkage as a configuration item.
Salesforce Sales Cloud
Asset
Odoo CRM
stock.production.lot
1:1Salesforce Asset maps to Odoo stock.production.lot (serialized inventory tracking) or maintenance.equipment (for equipment under service contracts). Asset Name, SerialNumber, Status, InstallDate, Quantity, and the linked AccountId and ContactId migrate. If the asset links to a Product, we resolve the product.product reference. Assets created automatically from Contracts or Orders require those parent records in Odoo first.
Salesforce Sales Cloud
Task
Odoo CRM
mail.message / project.task
1:1Salesforce Task maps to Odoo mail.message (as a log note on the related record) or project.task (if the task is tracked work). Task Subject, Status, Priority, ActivityDate, and Description migrate. WhoId (Lead or Contact) resolves to the migrated res.partner record; WhatId (Account, Opportunity, Case) resolves to the migrated parent record. Open tasks with completed = false in Salesforce map to project.task with kanban_state = blocked; completed tasks map as mail.message records on the timeline.
Salesforce Sales Cloud
Event
Odoo CRM
calendar.event
1:1Salesforce Event maps to Odoo calendar.event. Event Subject, StartDateTime, EndDateTime, Duration, Location, and Description migrate directly. Event attendees map to calendar.attendee records linked to the event, with each attendee resolved to a res.partner (User or Contact). Recurring Events in Salesforce map to Odoo calendar.recurrence records with the same recurrence rule.
Salesforce Sales Cloud
Custom Object
Odoo CRM
ir.model / custom model
1:1Salesforce Custom Objects (API name ending in __c) map to Odoo custom models defined via the Settings > Technical > Models interface or as Python classes in a custom module. We create the Odoo model with all custom fields (Char, Float, Date, Many2one, etc.) before any data import. Custom Object relationships (lookup fields) map to Odoo Many2one fields pointing to the correct res.partner, crm.lead, or custom model. Validation rules and required-field constraints are replicated as Odoo Python constraints.
Salesforce Sales Cloud
Account Team Member
Odoo CRM
crm.team membership
1:1Salesforce Account Team Members (AccountTeamMember) assign a UserId to an AccountId with a TeamRole. We import these after both Account and User records exist in Odoo. Each team member maps to res.users (for Odoo internal users) or res.partner (for external collaborators) added to crm.team with the TeamRole mapped to a custom field or a group assignment in Odoo's access control system.
Salesforce Sales Cloud
Opportunity Team Member
Odoo CRM
crm.lead / crm.team assignment
1:1Salesforce Opportunity Team Members assign a UserId to an OpportunityId with a TeamMemberRole. We import these after the crm.lead record exists. Each team member maps to a record in crm.team.member linked to the crm.lead, with the TeamMemberRole preserved as a custom selection field on the membership record.
Salesforce Sales Cloud
User
Odoo CRM
res.users
1:1Salesforce User records map to Odoo res.users. We resolve by email match. Active status, Username, FirstName, LastName, Title, and the Salesforce profile name (mapped to Odoo groups) migrate. A Salesforce User without a matching Odoo res.users is held in a reconciliation queue for the customer's Odoo admin to provision before record migration continues, because OwnerId references on Opportunities and Leads require a valid res.users.
| Salesforce Sales Cloud | Odoo CRM | Compatibility | |
|---|---|---|---|
| Account | res.partner (contact_type = company)1:1 | Fully supported | |
| Contact | res.partner (contact_type = contact)1:1 | Fully supported | |
| Lead | crm.lead1:1 | Fully supported | |
| Opportunity | crm.lead (won/lost stage) or sale.order1:many | Fully supported | |
| Opportunity Product / Price Book Entry | product.product / product.pricelist1:1 | Fully supported | |
| Case | helpdesk.ticket1:1 | Fully supported | |
| Campaign | marketing.campaign1:1 | Fully supported | |
| Contract | account.move / contract.contract1:1 | Fully supported | |
| Order | sale.order1:1 | Fully supported | |
| Asset | stock.production.lot1:1 | Fully supported | |
| Task | mail.message / project.task1:1 | Fully supported | |
| Event | calendar.event1:1 | Fully supported | |
| Custom Object | ir.model / custom model1:1 | Fully supported | |
| Account Team Member | crm.team membership1:1 | Fully supported | |
| Opportunity Team Member | crm.lead / crm.team assignment1:1 | Fully supported | |
| User | res.users1: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.
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
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
Pair-specific challenges
Migration approach
Discovery and Odoo edition selection
We audit the source Salesforce org across edition (Starter through Agentforce 1 Sales), active Custom Objects, active Workflow Rules and Process Builder processes, Apex triggers, installed packages, API usage volume, and record counts per object. We pair this with an Odoo edition decision: Community (free, self-hosted or Odoo Online free tier) covers core CRM and Sales; Enterprise ($31-$100 per user per month) is required for the Studio interface, automated actions, and the full helpdesk, project, and accounting modules; Online ($100 per user per month) provides Odoo-hosted infrastructure. The discovery output is a written migration scope with object inventory, a complexity assessment, and an Odoo edition recommendation.
Schema design and Odoo model provisioning
We design the destination schema in Odoo. This includes activating the relevant modules (CRM, Contacts, Sales, Helpdesk, Project, Inventory, Accounting depending on scope), creating custom fields on res.partner and crm.lead to receive migrated Salesforce custom fields, configuring pipeline stages to match the source Opportunity stages, setting up sale teams to map to Salesforce Territories, and defining the res.partner contact_type hierarchy (company vs. contact) with parent_id linkage. We deploy to a staging Odoo database first. Any Salesforce Custom Object gets a corresponding Odoo model created via Settings > Technical > Models before any data import begins.
Data extraction from Salesforce
We extract Salesforce data using the Bulk API 2.0 with batch pacing against the 15,000-batch daily quota and exponential backoff on concurrent-request limits. Data extraction runs in dependency order: Users first (by email), then Accounts, then Contacts (with AccountId resolved), then Leads, then Opportunities, then Products and Price Book Entries, then Cases, then Campaigns, then Activity history. Custom Objects extract last because they often contain lookups to standard objects. We run a pre-extraction data audit to identify duplicates, missing required fields, and inactive OwnerId references, and we address these before extraction begins rather than during import.
Data cleansing, transformation, and staging import
We transform Salesforce data into Odoo's import format (CSV with XML-RPC load or direct database injection for large volumes). Key transformations include: splitting Salesforce Account and Contact into res.partner records with contact_type differentiation; converting Salesforce Lead to crm.lead in pipeline mode; mapping Opportunity Stage to crm.lead stage_id; resolving Owner email to res.users id; converting Salesforce dates to Odoo's datetime format; and mapping picklist values to Odoo selection fields or many2one relationships. We run a staging import into the staging Odoo database and deliver a reconciliation report (record counts per object, field coverage percentage, null rate on required fields) before proceeding.
Production migration in dependency order with parallel testing
We run production migration in the same dependency order used for extraction: Users (manually provisioned in Odoo, validated), Accounts (res.partner, contact_type=company), Contacts (res.partner, contact_type=contact with parent_id to Account), Leads (crm.lead), Opportunities (crm.lead with won/lost stage handling), Price Book Entries and Products, Cases (helpdesk.ticket), Campaigns and Campaign Members, Activity history (mail.message, calendar.event), and Custom Objects. Each phase emits a row-count reconciliation report before the next phase begins. We do not import Attachments as binary blobs — we deliver a written inventory of ContentDocument records with their links for the customer's admin to re-attach post-migration.
Cutover, validation, and automation rebuild 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 Apex trigger and Workflow Rule inventory document with Odoo automated action equivalents to the customer's functional team. We do not rebuild Apex triggers as Python modules, Workflow Rules as Odoo automated actions, or Visualforce pages as QWeb views within the migration scope — these are separate engagements. We support a one-week hypercare window where we resolve any record-reconciliation issues raised by the customer's team.
Platform deep dives
Salesforce Sales Cloud
Source
Strengths
Weaknesses
Odoo CRM
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 Salesforce Sales Cloud and Odoo CRM.
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
Salesforce Sales Cloud: 100,000 daily API requests base for Enterprise, plus 1,000 requests per user license; concurrent long-running requests capped at 25; individual call timeout 10 minutes.
Data volume sensitivity
Salesforce Sales Cloud 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 Salesforce Sales Cloud to Odoo CRM migration scoping. Not seeing yours? Book a call.
Walk through your Salesforce Sales Cloud to Odoo CRM migration with a real engineer — 30 minutes, free, written quote within 24 hours.
Book a free 30 minute consultationAdjacent paths
Other ways to leave Salesforce Sales Cloud
Other ways to arrive at Odoo CRM
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.