CRM migration
Field-level mapping, validation, and rollback between Dynamics 365 Field Service and Odoo CRM. We move data and schema; workflows are rebuilt natively in Odoo CRM.
Dynamics 365 Field Service
Source
Odoo CRM
Destination
Compatibility
9 of 12
objects map 1:1 between Dynamics 365 Field Service and Odoo CRM.
Complexity
BStandard
Timeline
48–72 hours
Overview
Microsoft Dynamics 365 Field Service organizes service operations around Work Orders, Bookable Resources, Incidents, and Work Order Products — a schema designed for dispatch, scheduling, and field-technician management. Odoo CRM uses a simpler model: crm.lead for opportunities, res.partner for contacts and companies, and sale.order for quotes and contracts. The migration must collapse D365's field-service object graph into Odoo's standard CRM objects while preserving the operational context that drives your service business. We map Work Orders to a combination of crm.lead records (for customer-facing opportunities) and project.task records (for internal work tracking), Bookable Resources to res.partner with a custom technician type, and Work Order Incidents to crm.lead.tag or custom fields on the opportunity. Owner resolution happens via email match against Odoo users. Activities — service calls, completed jobs, notes — migrate as mail.message and crm.lead.calendar.event records with original timestamps preserved. Custom fields on Work Orders and Bookable Resources become custom fields on crm.lead and res.partner using Odoo's x_studio or custom field conventions. Workflows, booking rules, Resource Scheduling Optimization policies, and Service Agreements do not migrate — they require manual rebuild in Odoo's Automation menu. The migration uses Odoo's XML-RPC API with batched writes to avoid throttling, and FlitStack runs a sample migration with field-level diff before the full cutover.
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 Dynamics 365 Field Service 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.
Dynamics 365 Field Service
Account (msdyn_account / account)
Odoo CRM
res.partner
1:1D365 Account maps to Odoo res.partner where is_company=True. Primary address, phone, website, and industry fields map directly using Odoo's standard address fields. Parent-account hierarchies in D365 map to res.partner.parent_id in Odoo. If the account is a billing entity only, it migrates as a company-type partner; Odoo does not distinguish between 'billing' and 'service' accounts natively.
Dynamics 365 Field Service
Contact (contact)
Odoo CRM
res.partner
1:1D365 Contact maps to Odoo res.partner where is_company=False. Name, email, phone, mobile, job title, and address fields migrate directly. D365's multiple-contact-per-account model is natively supported by Odoo's res.partner structure — no junction table required. Owner (user_id) resolves via email match against Odoo users.
Dynamics 365 Field Service
Bookable Resource (bookableresource)
Odoo CRM
res.partner + project.resource
many:1D365 Bookable Resource has no direct Odoo equivalent. FlitStack creates a res.partner record with a custom 'Technician' partner category for each resource, preserving resource name, email, and organizational unit. If your D365 setup uses resource characteristics (skills, certifications), those migrate as crm.lead.tag entries applied to work-order-linked opportunities — Odoo's project.resource model is used only if Odoo Project is deployed alongside CRM.
Dynamics 365 Field Service
Work Order (msdyn_workorder)
Odoo CRM
crm.lead + project.task
1:manyD365 Work Order is the central service record and cannot map to a single Odoo object. The customer-facing context (account, contact, address, service type) maps to crm.lead as an opportunity with the work order name as the opportunity name. The internal work-tracking context (assigned technician, scheduled date, incident summary) maps to project.task if Odoo Project is in scope; otherwise it stores as custom fields on the crm.lead. The split is determined by whether your Odoo deployment includes the Project app.
Dynamics 365 Field Service
Work Order Incident (msdyn_workorderincident)
Odoo CRM
crm.lead.tag + custom fields
many:1D365 Work Order Incidents record problems or symptoms per work order. Multiple incidents per work order are merged into a set of crm.lead.tag entries on the corresponding Odoo opportunity (e.g., 'Incident: Electrical Fault', 'Incident: Motor Failure'). If incident codes carry pricing or billing weight, those values migrate as custom decimal fields on the opportunity rather than as tags. Symptom codes and incident types without a meaningful Odoo tag equivalent are preserved in an 'Incident_History__c' custom field as a text block.
Dynamics 365 Field Service
Work Order Product (msdyn_workorderproduct)
Odoo CRM
sale.order.line
1:1D365 Work Order Products (parts and materials applied to a work order) map to Odoo sale.order.line records on the linked quotation or sale order. Product name, quantity, unit cost, and unit price migrate directly. If the work order has no linked quote, FlitStack creates a draft sale.order attached to the opportunity's partner. The product.product record must exist in Odoo before the line can map — FlitStack validates product SKU existence and flags missing products before migration.
Dynamics 365 Field Service
Work Order Service (msdyn_workorderservice)
Odoo CRM
sale.order.line
1:1D365 Work Order Services (labor line items) map to sale.order.line with the service flag set to True. Duration and hourly rate from D365 migrate as quantity and unit price on the Odoo line. If D365 tracks service task type (diagnostic, repair, maintenance), that value becomes a crm.lead.tag on the parent opportunity. Tax codes on service lines map to Odoo's account.tax based on the D365 tax code value — value-by-value mapping is required per jurisdiction.
Dynamics 365 Field Service
Case / Service Task (incident)
Odoo CRM
crm.lead
1:1D365 Cases (service incidents not tied to a work order) map to crm.lead records with a dedicated 'Case' stage in the Odoo pipeline. Subject, description, priority, and status migrate as crm.lead name, description, priority, and stage. If cases have a parent-account or parent-contact, those link via the standard partner_id lookup in Odoo. Case resolution notes and internal comments migrate as mail.message records attached to the lead.
Dynamics 365 Field Service
Agreement / Service Contract (msdyn_agreement)
Odoo CRM
sale.subscription
1:1D365 Agreements (recurring service contracts) map to Odoo sale.subscription records. Contract name, start/end dates, billing frequency, and recurring amount migrate directly. If the agreement contains a line-item schedule (services covered), those lines migrate as sale.subscription.line records. One-time setup fees on the agreement map as a non-recurring line on the subscription. Billing term (advance/arear) maps to Odoo's invoicing policy on the subscription product.
Dynamics 365 Field Service
Customer Asset (msdyn_customerasset)
Odoo CRM
stock.production.lot + custom field
1:1D365 Customer Asset links equipment to a customer account with serial number, product, and installed date. Odoo has no native customer asset entity — FlitStack creates stock.production.lot records for each asset serial number and attaches a custom 'Customer_Account__c' field linking the lot to the customer partner. Asset lifecycle status (Active, Inactive, Under Repair) migrates as a custom selection field on the lot. If your Odoo deployment includes the Maintenance app, assets can alternatively map to maintenance.equipment with the customer as the partner_id.
Dynamics 365 Field Service
Resource Booking / Schedule (bookableresourcebooking)
Odoo CRM
project.task + calendar.event
1:1D365 Resource Bookings assign technicians to work orders with start/end times. Each booking maps to a project.task record with the assigned technician as the user_id and the booking window as task planned date range. If the booking has a meeting context (customer on-site visit), a calendar.event is also created in Odoo with the customer partner linked. Odoo's standard calendar uses mail.activity.type records for activity types — FlitStack maps D365 booking type codes to the closest Odoo activity type by name match.
Dynamics 365 Field Service
Product / Service Item (product)
Odoo CRM
product.product + product.template
1:1D365 Field Service products (parts) and service items map to Odoo product.product records. Product name, SKU, list price, standard cost, and product type (inventory vs. consumable vs. service) migrate directly. Product categories from D365 map to product.category in Odoo. If D365 uses product variants (size, color), those migrate as Odoo product variants on the same template.
| Dynamics 365 Field Service | Odoo CRM | Compatibility | |
|---|---|---|---|
| Account (msdyn_account / account) | res.partner1:1 | Fully supported | |
| Contact (contact) | res.partner1:1 | Fully supported | |
| Bookable Resource (bookableresource) | res.partner + project.resourcemany:1 | Fully supported | |
| Work Order (msdyn_workorder) | crm.lead + project.task1:many | Fully supported | |
| Work Order Incident (msdyn_workorderincident) | crm.lead.tag + custom fieldsmany:1 | Fully supported | |
| Work Order Product (msdyn_workorderproduct) | sale.order.line1:1 | Fully supported | |
| Work Order Service (msdyn_workorderservice) | sale.order.line1:1 | Fully supported | |
| Case / Service Task (incident) | crm.lead1:1 | Fully supported | |
| Agreement / Service Contract (msdyn_agreement) | sale.subscription1:1 | Fully supported | |
| Customer Asset (msdyn_customerasset) | stock.production.lot + custom field1:1 | Fully supported | |
| Resource Booking / Schedule (bookableresourcebooking) | project.task + calendar.event1:1 | Fully supported | |
| Product / Service Item (product) | product.product + product.template1: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.
Dynamics 365 Field Service gotchas
Dataverse service protection API limits throttle bulk exports
Offline profile FetchXML tuning is source-environment-specific
Project Operations integration has bidirectional sync limitations
Copilot add-on credits do not migrate and reset at zero
File attachments stored in SharePoint require separate file migration
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
Assess D365 Field Service schema and Odoo CRM target configuration
FlitStack AI begins by querying your D365 Field Service instance via the Dataverse API to inventory all Work Order entities, Bookable Resource definitions, Work Order Incident types, and Agreement records. We simultaneously inspect your Odoo CRM target instance to identify existing crm.lead stages, res.partner categories, product.product records, and sale.subscription configuration. The gap analysis produces a migration map: which D365 objects map to which Odoo models, which fields are direct, which require custom field creation, and which D365 data cannot map to a native Odoo object. This schema map is reviewed with your team before any data moves.
Validate owner and user resolution across both platforms
D365 Bookable Resources and Work Order owners carry a user reference (Azure AD object ID in D365). FlitStack resolves these by email address against Odoo res.users records. Resources without a matching Odoo user are flagged in a pre-migration report — your team either creates Odoo user accounts for those technicians before migration or designates a fallback dispatcher who inherits their records. Accounts and Contacts are resolved similarly: D365 Account and Contact owner IDs map to Odoo user_id on res.partner. This step prevents orphan records at migration time.
Migrate foundational entities first: Accounts, Contacts, Products
FlitStack sequences the migration to honor foreign-key dependencies. res.partner records (Accounts and Contacts) migrate first so that Work Order and Case records can resolve their customer links. product.product records migrate next so that Work Order Product and Service lines can reference existing Odoo products. Custom fields required for the migration — such as Original_Create_Date__c on res.partner, Source_System_ID__c on crm.lead, and Technician_Category__c for Bookable Resources — are created in Odoo during this phase via XML-RPC field creation calls.
Migrate Work Orders and Cases to crm.lead with field-level diff validation
With foundations in place, FlitStack migrates Work Orders to crm.lead records and Work Order Incidents to crm.lead.tag entries. Each opportunity inherits the D365 Work Order name, account, primary incident type, total amount, and status as stage. Cases (D365 incidents not tied to a work order) migrate as separate crm.lead records with a dedicated 'Case' stage. A sample migration of 100–300 records runs first; FlitStack generates a field-level diff comparing source D365 values against destination Odoo values. Your team reviews the diff to confirm incident type mapping, stage routing, and owner assignment before the full migration commits.
Migrate Work Order Products, Services, and Resource Bookings with delta window
Work Order Product and Service lines migrate as sale.order.line records attached to the opportunities created in the previous step. Resource Bookings migrate as project.task records linked to the technician res.partner records created from Bookable Resources. During the full migration, a delta-pickup window (24–48 hours) captures any D365 Work Orders created or modified during the cutover window. FlitStack's audit log records every insert operation; one-click rollback reverts all migrated records if reconciliation against the D365 source fails. The migration uses batched XML-RPC writes to stay within Odoo's API rate limits.
Platform deep dives
Dynamics 365 Field Service
Source
Strengths
Weaknesses
Odoo CRM
Destination
Strengths
Weaknesses
Complexity grading
Standard CRM migration. All 8 core objects map 1:1 between Dynamics 365 Field Service and Odoo CRM.
Overall complexity
Standard migration
Derived from compatibility, mapping clarity, API constraints, and data volume across Dynamics 365 Field Service and Odoo CRM.
Object compatibility
All 8 core objects map 1:1 between Dynamics 365 Field Service and Odoo CRM.
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
Dynamics 365 Field Service: Service protection limits enforced per org; specific numeric thresholds are not publicly documented by Microsoft and vary by workload type.
Data volume sensitivity
Dynamics 365 Field Service 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 Dynamics 365 Field Service to Odoo CRM migration scoping. Not seeing yours? Book a call.
Walk through your Dynamics 365 Field Service 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 Dynamics 365 Field Service
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.