CRM migration
Field-level mapping, validation, and rollback between XSale and Odoo CRM. We move data and schema; workflows are rebuilt natively in Odoo CRM.
XSale
Source
Odoo CRM
Destination
Compatibility
7 of 12
objects map 1:1 between XSale and Odoo CRM.
Complexity
CModerate
Timeline
3-5 weeks
Overview
XSale organizes data around field execution concepts—Reps, Routes, Visits, and pre-order transactions—that do not have native equivalents in Odoo CRM's relational model. We resolve this by mapping Reps to Odoo User records, Routes to Sales Teams, Visits to Odoo Activity records linked to the correct Contact, and Orders to Odoo Sale Orders. The XSale Visit schema (status, timestamps, notes, rep attribution) reconstructs as Odoo's mail.activity table with the original visit outcome preserved in custom fields. Because Odoo is an ERP rather than a field-service tool, route sequencing and geolocation data from XSale require a configuration decision during scoping—we surface these and document the mapping options for the customer's admin. Custom fields on the Order and Visit objects are the highest-risk migration items; we enumerate every custom field in discovery and pre-create the matching Odoo fields before any data moves. Workflows, automations, and route-optimization logic do not migrate; we deliver a written inventory of these for the admin to rebuild in Odoo's automation framework.
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 XSale 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.
XSale
Rep
Odoo CRM
User
1:1XSale Rep records map to Odoo res.users by email match. We extract every distinct rep_id referenced on Visit, Order, and Route records and attempt email-based lookup against the destination Odoo User table. Any Rep without a matching User goes to a reconciliation queue for the customer's admin to provision before record import begins. Active versus inactive status is preserved by setting the corresponding Odoo User to active or inactive. If XSale stores rep attributes beyond email (name, phone, territory), these migrate as res.users fields or custom fields on res.users.
XSale
Route
Odoo CRM
Sales Team
lossyXSale Route records (territory groupings of stores and visit sequences) have no direct Odoo CRM equivalent. Routes are recreated as Odoo crm.team records, where each team represents a geographic territory or route grouping. The route sequence of stores is documented in a custom field (e.g., xsale_route_sequence__c) on the Sales Team for admin reference. This is primarily a configuration step; the customer's admin defines the Sales Team structure in Odoo settings and we validate the mapping against the XSale route list.
XSale
Company / Store
Odoo CRM
Partner (Account + Contact)
1:manyXSale stores and companies map to Odoo res.partner records. We perform a 1:N split: the XSale company or store header becomes an Odoo res.partner with type=contact and is_contact=False (the Account record). Individual store contacts, buyer names, and branch contacts become res.partner records with type=contact and is_company=False linked via parent_id to the Account. The XSale store address, phone, and custom fields map to the corresponding res.partner fields.
XSale
Visit
Odoo CRM
Activity (mail.activity)
1:1XSale Visit records are the highest-volume migration object. Each Visit maps to an Odoo mail.activity record with activity_type_id set to the visit-related activity type (created during configuration as 'Visit' or 'Field Visit'). The XSale visit status (completed, skipped, no-answer) migrates as a custom char field xsale_visit_status__c. The visit timestamp and duration migrate to Odoo's date_deadline and create_date. The related store (partner) and rep (user) are resolved via lookup before activity insertion. Visit notes migrate as Odoo mail.message records on the activity's res_id.
XSale
Pre-Order
Odoo CRM
Sale Order (quotation state)
1:1XSale pre-order records (orders captured before delivery confirmation) map to Odoo sale.order with state=quotation. The pre-order line items map to sale.order.line with product_id, product_uom_qty, and price_unit preserved. Pre-order metadata (order taken by, order timestamp, store reference) migrates to custom fields on sale.order. The customer's admin decides whether pre-orders should remain as quotations pending delivery confirmation or be confirmed immediately as sale.order with state=sale.
XSale
Order (confirmed)
Odoo CRM
Sale Order
1:1XSale confirmed orders map directly to Odoo sale.order with state=sale. Order status (delivered, partially delivered, pending) maps to Odoo picking state via the stock.picking record created by the sale order. The link between sale.order and stock.picking is created at migration time using Odoo's delivery workflow. Order totals, taxes, and discounts migrate as sale.order.line records. If XSale stores order approval or sign-off data, this migrates as custom fields on sale.order.
XSale
Product
Odoo CRM
Product (product.product)
1:1XSale product catalog records map to Odoo product.product. Product name, SKU, unit of measure, and price migrate to the corresponding Odoo fields. If XSale tracks product images or descriptions, these migrate to product.product's image fields and description fields. Product categories in XSale map to product.category records in Odoo before product migration so that categ_id references are satisfied at insert time.
XSale
Route Assignment
Odoo CRM
Sales Team membership
lossyXSale route-to-rep assignments (which reps are assigned to which routes on which days) have no direct Odoo equivalent. We extract all route assignment records, document the rep-route-day relationships in a CSV inventory, and deliver this to the customer's admin for rebuild using Odoo Sales Team membership and the calendar module if scheduling is required. This is a configuration handoff item, not a data migration item.
XSale
Custom Fields: Order
Odoo CRM
Custom Fields on sale.order
lossyXSale custom fields added to the Order object require pre-creation in Odoo as ir.model.fields records before any sale.order data inserts. We enumerate every custom Order field during discovery, determine the appropriate Odoo field type (char, selection, float, many2one, etc.) for each, create the fields in the staging environment, and validate that migration transforms populate them correctly. Custom field pre-creation is the most common source of migration delay if discovered late.
XSale
Custom Fields: Visit
Odoo CRM
Custom Fields on mail.activity
lossySame as Order custom fields: XSale custom fields on the Visit object require ir.model.fields creation in Odoo before mail.activity records can be imported with those values. We surface every custom Visit field during discovery, classify the Odoo field type, and create them in staging before production migration. Visit custom fields often include outcome codes, visit ratings, and field-collected attributes that have no Odoo standard equivalent.
XSale
Deal / Opportunity
Odoo CRM
CRM Lead
1:1If XSale captures deal-level pipeline data (expected value, stage, expected close date, probability), these map to Odoo crm.lead fields (planned_revenue, stage_id, date_deadline, probability). XSale's pipeline stages map to Odoo crm.stage records within the relevant crm.team. The xsale_original_stage__c custom field preserves the source stage name for audit. Deals without an associated Contact are imported as crm.lead; deals with a Contact are converted to crm.lead and linked to the Contact partner.
XSale
Delivery Record
Odoo CRM
Stock Picking
1:1XSale delivery confirmations map to Odoo stock.picking records linked to the corresponding sale.order. The picking state (done, cancelled, waiting) is preserved. If XSale captures delivery confirmation signatures or photos, these migrate as Odoo ir.attachment records linked to the stock.picking. The stock.picking records are created as a downstream step after sale.order migration using Odoo's delivery workflow chain.
| XSale | Odoo CRM | Compatibility | |
|---|---|---|---|
| Rep | User1:1 | Fully supported | |
| Route | Sales Teamlossy | Fully supported | |
| Company / Store | Partner (Account + Contact)1:many | Fully supported | |
| Visit | Activity (mail.activity)1:1 | Fully supported | |
| Pre-Order | Sale Order (quotation state)1:1 | Fully supported | |
| Order (confirmed) | Sale Order1:1 | Fully supported | |
| Product | Product (product.product)1:1 | Fully supported | |
| Route Assignment | Sales Team membershiplossy | Fully supported | |
| Custom Fields: Order | Custom Fields on sale.orderlossy | Fully supported | |
| Custom Fields: Visit | Custom Fields on mail.activitylossy | Fully supported | |
| Deal / Opportunity | CRM Lead1:1 | Fully supported | |
| Delivery Record | Stock Picking1: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.
XSale gotchas
SAP integration metadata is critical for ongoing operations
Mobile-captured data syncs from rugged devices
GPS tracking data volume is high
Catalog and brand naming inconsistency
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 XSale schema audit
We audit the source XSale environment across the Rep, Route, Visit, Order, Pre-Order, and Company objects, cataloging every standard and custom field on each. We extract record counts, identify duplicate risks, note null rates per field, and capture the XSale API export capability available on the customer's plan. We also review the Odoo destination instance (edition, installed modules, existing partner and opportunity records) and confirm whether the Odoo Inventory module is present. The discovery output is a written data audit report and a migration scope document requiring customer sign-off before staging begins.
Schema design and custom field pre-creation
We design the Odoo destination schema based on the discovery findings. This includes creating the XSale-to-Odoo object mapping (Rep→User, Store→Partner, Visit→Activity, Order→Sale Order), creating every custom field identified on the Order and Visit objects as ir.model.fields records in the staging database, configuring Odoo Sales Teams to represent XSale Routes, and defining crm.stage values that map to XSale order and visit status. We also configure the Odoo partner model to handle the Contact-Account split from XSale's flat store structure. Schema design is validated in a staging environment before any production migration begins.
Staging migration and reconciliation
We run a full migration into the Odoo staging environment using a representative data sample (typically 10-20% of total volume). The customer's operations lead reviews migrated records—checking Visit timestamps against XSale source, Order totals against XSale exports, and Contact names against the XSale store list—and signs off the mapping logic. Any custom field mapping corrections, partner split decisions, or custom field type changes happen in staging, not in production. We also validate that Odoo's foreign-key constraints are satisfied by the insertion order and that stock.picking records are correctly linked to sale.order records if Inventory is present.
Rep-to-User reconciliation and provisioning
We extract every distinct XSale rep_id referenced on Visit, Order, and Route records and match by email against the Odoo User table. Reps without a matching Odoo User go to a reconciliation queue. The customer's admin provisions any missing Users and confirms active versus inactive status for each. Migration cannot proceed past the Visit and Order import phases until all OwnerId references are resolved, because Odoo's Activity and Order models require a valid create_uid reference.
Production migration in dependency order
We run production migration in insertion order: res.partner records (Account first, Contact second with parent_id resolved), product.product records (with product.category pre-inserted), crm.team (Sales Teams from Routes), crm.lead (from XSale deal/pipeline data), sale.order (Pre-Orders as quotations, confirmed Orders as sale orders), mail.activity (Visits with partner_id and user_id resolved via lookup), and stock.picking (delivery records linked to sale.order if Inventory is present). Each phase emits a row-count reconciliation report before the next phase begins. The total migration window is chosen during a low-activity period agreed with the customer, during which XSale writes are frozen.
Cutover, validation, and automation handoff
We perform a final delta migration of any records modified during the cutover window, then enable Odoo as the system of record. We deliver a post-migration reconciliation report comparing record counts between XSale source and Odoo destination by object. We deliver a written Route and Automation inventory document listing every XSale route assignment, workflow, and automation requiring rebuild in Odoo, with Odoo CRM equivalents noted where applicable (e.g., Odoo automated actions as a partial Workflow substitute, crm.team membership as a Route substitute). We do not rebuild automations or configure Odoo Sales Teams; those are admin tasks documented for handoff. We support a one-week post-cutover window for reconciliation issues raised by the operations team.
Platform deep dives
XSale
Source
Strengths
Weaknesses
Odoo CRM
Destination
Strengths
Weaknesses
Complexity grading
Moderate CRM migration. 1 of 8 objects need a manual workaround.
Overall complexity
Moderate migration
Derived from compatibility, mapping clarity, API constraints, and data volume across XSale and Odoo CRM.
Object compatibility
1 of 8 objects need a manual workaround.
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
XSale: Not publicly documented — typical SaaS limits assumed and confirmed during scoping..
Data volume sensitivity
XSale 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 XSale to Odoo CRM migration scoping. Not seeing yours? Book a call.
Walk through your XSale 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 XSale
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.