CRM migration
Field-level mapping, validation, and rollback between Odoo CRM and Microsoft Dynamics 365 Sales . We move data and schema; workflows are rebuilt natively in Microsoft Dynamics 365 Sales .
Odoo CRM
Source
Microsoft Dynamics 365 Sales
Destination
Compatibility
5 of 10
objects map 1:1 between Odoo CRM and Microsoft Dynamics 365 Sales .
Complexity
BStandard
Timeline
3-5 weeks
Try the reverse
Overview
Moving from Odoo CRM to Microsoft Microsoft Dynamics 365 Sales is a structural remapping: Odoo stores Leads and Opportunities in a single crm.lead table with a type discriminator, while Dynamics separates them into a distinct Lead object and a Contact linked to an Account. We resolve that split during scoping by classifying every crm.lead record on its type and stage before generating the correct destination object. Odoo's res.partner (used for both individuals and companies) maps to Contact and Account depending on the partner's is_company flag, with the original partner ID preserved as a legacy key. Activity history (mail.activity) migrates as Dynamics Tasks and Notes linked to the parent Contact or Opportunity via Dataverse. We do not migrate Enterprise-only Odoo features including AI lead scoring rules and automation server actions; we deliver a written inventory of these for the customer's admin to rebuild in Dynamics 365's Power Automate or native workflow designer.
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
Microsoft Dynamics 365 Sales platform overview
Scorecard, SWOT, gotchas, and pricing for Microsoft Dynamics 365 Sales .
Data migration guide
The complete Microsoft Dynamics 365 Sales 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
Microsoft Dynamics 365 Sales migration checklist
Pre- and post-cutover tasks for moving onto Microsoft Dynamics 365 Sales .
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 Microsoft Dynamics 365 Sales , including any object-level transformations, lookup resolution, or schema-design dependencies.
Typical mapping — final map is confirmed during the sample migration step.
Odoo CRM
crm.lead (type=lead)
Microsoft Dynamics 365 Sales
Lead
1:1Odoo crm.lead records with type='lead' map directly to Dynamics 365 Lead. The Odoo lead name becomes Lead.fullname, email_from becomes Lead.emailaddress1, phone becomes Lead.mobilephone or telephone, source_id becomes Lead.leadsource1, and stage_id maps to Lead.statecode (or a custom status field). We use the Odoo crm.lead.id as a legacy key in a custom field odoo_lead_id__c on the destination Lead for reconciliation and cross-reference.
Odoo CRM
crm.lead (type=opportunity)
Microsoft Dynamics 365 Sales
Opportunity
1:1Odoo crm.lead records with type='opportunity' map to Dynamics 365 Opportunity. The partner_id foreign key (res.partner) must resolve to an Account lookup first, so we import Accounts before Opportunities. Key field mappings: planned_revenue becomes Opportunity.estimatedvalue, probability becomes Opportunity.stepid probability (mapped to the Dynamics stage), date_deadline becomes Opportunity.estimatedclosedate, team_id maps to Opportunity.territoryid or a custom team field, and user_id maps to Opportunity.ownerid.
Odoo CRM
res.partner
Microsoft Dynamics 365 Sales
Account and Contact (split required)
1:manyOdoo res.partner is a polymorphic table used for both individuals and organizations. Partners with is_company=True map to Dynamics Account; partners with is_company=False map to Contact linked to the parent Account. The parent_id foreign key in res.partner becomes the Contact.parentaccountid lookup. Email, phone, street, city, country, and vat map to Account/Contact standard address and contact fields. We preserve the original res.partner.id in odoo_partner_id__c for reconciliation.
Odoo CRM
crm.stage
Microsoft Dynamics 365 Sales
Opportunity Stage
lossyOdoo pipeline stages from crm.stage map to Dynamics Opportunity Stage values. We create a Sales Process in Dynamics 365 that whitelists the migrated stage names, preserving the Odoo stage sequence order and probability percentages (rounded to Dynamics' integer-allowed format). Stages are sequenced before any Opportunity data loads.
Odoo CRM
crm.team
Microsoft Dynamics 365 Sales
Team or Territory
lossyOdoo crm.team records map to Dynamics 365 Teams or Territory records depending on the customer's reporting structure. Team member_ids from Odoo (res.users) map to Team Membership records in Dynamics. If the customer uses territory-based quota allocation, we map teams to Territory hierarchy; otherwise we use the standard Dynamics Team object.
Odoo CRM
mail.activity
Microsoft Dynamics 365 Sales
Task and Note
1:1Odoo mail.activity records linked to crm.lead (via res_id/res_model) migrate to Dynamics 365 Task records. The activity type (call, meeting, email, upload_document, etc.) maps to a custom Task.customertype or TaskSubject field; date_deadline maps to Task.scheduledend; user_id resolves to Task.ownerid; note (HTML body) maps to Task.description or a linked Note. We chunk mail.activity exports by date range to avoid memory exhaustion and preserve the activity timeline ordering via the original Odoo create_date.
Odoo CRM
crm.tag
Microsoft Dynamics 365 Sales
Topic or Multi-Select Picklist
lossyOdoo crm.tag records (many2many with crm.lead) map either to Dynamics Topics (via Topic and TopicAssignment) or to a custom multi-select picklist field on Opportunity. The customer selects the strategy during scoping. Tag names are preserved as a flat list, and any tag frequencies are documented for the customer's admin to decide consolidation before import.
Odoo CRM
Custom fields (crm.lead via Studio or custom addon)
Microsoft Dynamics 365 Sales
Custom fields on Lead or Opportunity
lossyOdoo custom fields defined via Studio or in custom addons are stored as columns in crm.lead but have no separate field definition registry in Community. We export field definitions alongside the data during discovery, then pre-create matching custom fields in Dynamics 365 with equivalent types (selection fields become picklists, many2one become lookups, many2many become multi-select picklists or related entities). If the custom field references an Odoo-specific model, we document it as a manual field for the customer's admin to configure post-migration.
Odoo CRM
ir.attachment (linked to crm.lead)
Microsoft Dynamics 365 Sales
Note (with Document Attachment)
1:1Odoo ir.attachment records linked to crm.lead via res_model/res_id migrate to Dynamics Note records with an associated Document (SharePoint or Dataverse file attachment). Large attachment volumes are chunked separately from record data. We remap ir.attachment.res_id to the destination Dynamics record ID using the legacy key mapping built during earlier migration phases.
Odoo CRM
sale.order (linked to crm.lead)
Microsoft Dynamics 365 Sales
Opportunity Products or Quote
1:1Odoo sale.order records linked to Opportunities migrate as Opportunity Product line items if the order is open, or as historical Quote records if closed or lost. sale.order.line items (product, quantity, price, tax) map to OpportunityLineItem records. We resolve the Pricebook2 reference, Product2 reference, and parent Opportunity at migration time and flag any orders in draft state as requiring a re-quote workflow in Dynamics.
| Odoo CRM | Microsoft Dynamics 365 Sales | Compatibility | |
|---|---|---|---|
| crm.lead (type=lead) | Lead1:1 | Fully supported | |
| crm.lead (type=opportunity) | Opportunity1:1 | Fully supported | |
| res.partner | Account and Contact (split required)1:many | Fully supported | |
| crm.stage | Opportunity Stagelossy | Fully supported | |
| crm.team | Team or Territorylossy | Fully supported | |
| mail.activity | Task and Note1:1 | Fully supported | |
| crm.tag | Topic or Multi-Select Picklistlossy | Fully supported | |
| Custom fields (crm.lead via Studio or custom addon) | Custom fields on Lead or Opportunitylossy | Fully supported | |
| ir.attachment (linked to crm.lead) | Note (with Document Attachment)1:1 | Fully supported | |
| sale.order (linked to crm.lead) | Opportunity Products or Quote1: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
Microsoft Dynamics 365 Sales gotchas
Professional tier 15-table custom table limit blocks migrations
October 2024 pricing increase applies at renewal for all customers
Custom fields must be created in the UI before API writes
Power Platform request limits apply to bulk migrations
Activity records orphaned to inactive owners fail silently
Pair-specific challenges
Migration approach
Discovery and source audit
We audit the source Odoo database via XML-RPC (Enterprise) or direct PostgreSQL read-only connection (Community). The audit covers: crm.lead record count and type distribution (lead vs opportunity), res.partner count with is_company flag breakdown, crm.stage and crm.team counts, mail.activity volume and date range, crm.tag distinct values, custom fields (ir.model.fields entries for crm.lead and res.partner), Enterprise-only module detection (ir_module_module entries flagged as Enterprise), and sale.order linkage to crm.lead. We produce a written migration scope document before any data is extracted.
Lead/Opportunity split rule and destination schema design
We define the split rule: all crm.lead records with type='lead' become Dynamics Lead; type='opportunity' become Dynamics Opportunity. We design the Dynamics destination schema in a Sandbox: custom fields on Lead and Opportunity matching Odoo custom field types, Opportunity Stages preserving the Odoo stage sequence and probability, Sales Process scoping the stage whitelist, Account and Contact standard fields, and any custom Team or Territory structure matching the Odoo crm.team. Schema is validated in Sandbox before production migration begins.
Owner and User reconciliation
We extract every distinct user_id referenced on crm.lead, mail.activity, crm.team, and sale.order records. Each Odoo res.users record is matched by email to the Dynamics 365 destination User table. Users without a match enter a reconciliation queue for the customer's admin to provision before record import. OwnerId references on Lead, Opportunity, and Task cannot be satisfied without an active User in Dynamics 365.
Sandbox migration and reconciliation
We run a full migration into a Dynamics 365 Sandbox using a representative data sample. The customer's RevOps lead spot-checks 25-50 records against the Odoo source for field accuracy, verifies the Lead/Opportunity split counts, confirms Account-Contact parent relationships, and validates activity timeline ordering. Any mapping corrections are made in the sandbox before the production migration phase begins.
Production migration in dependency order
We run production migration in record-dependency order: Accounts (from Odoo res.partner where is_company=True), Contacts (from res.partner where is_company=False with parentaccountid resolved), Leads (from crm.lead type='lead' with owner resolved), Opportunities (from crm.lead type='opportunity' with AccountId, OwnerId, and stage resolved), Tasks (mail.activity via Dataverse API with parent-record lookup), Tags (as multi-select picklist or Topic), Custom fields (filled after base objects are stable), Attachments (as Notes with Document links), and sale.order line items (as Opportunity Products). Each phase emits a row-count reconciliation report before the next begins.
Cutover, validation, and Enterprise-feature handoff
We freeze Odoo writes during the cutover window, run a final delta migration of any records modified during the migration window, then enable Dynamics 365 as the system of record. We deliver the Enterprise feature inventory (scoring rules, automation actions, Enterprise-only modules) as a written document for the customer's admin to rebuild in Power Automate or Dynamics workflows. We support a one-week post-cutover window for reconciliation issues. Workflow rebuild, Power Automate setup, and admin training are outside standard migration scope and are handled as separate engagements.
Platform deep dives
Odoo CRM
Source
Strengths
Weaknesses
Microsoft Dynamics 365 Sales
Destination
Strengths
Weaknesses
Complexity grading
Standard CRM migration. All 8 core objects map 1:1 between Odoo CRM and Microsoft Dynamics 365 Sales .
Overall complexity
Standard migration
Derived from compatibility, mapping clarity, API constraints, and data volume across Odoo CRM and Microsoft Dynamics 365 Sales .
Object compatibility
All 8 core objects map 1:1 between Odoo CRM and Microsoft Dynamics 365 Sales .
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 Microsoft Dynamics 365 Sales migration scoping. Not seeing yours? Book a call.
Walk through your Odoo CRM to Microsoft Dynamics 365 Sales 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 Microsoft Dynamics 365 Sales
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.