CRM migration
Field-level mapping, validation, and rollback between Open Dental and Odoo CRM. We move data and schema; workflows are rebuilt natively in Odoo CRM.
Open Dental
Source
Odoo CRM
Destination
Compatibility
12 of 13
objects map 1:1 between Open Dental and Odoo CRM.
Complexity
BStandard
Timeline
5–10 business days
Overview
Open Dental organizes dental-practice data around the Patient record — a composite object holding demographics, family-group membership, insurance plans, procedure history, prescriptions, and PatField custom fields. The platform exposes this data through a REST API that paginates at 100 records per request and returns Pascal-cased JSON fields. Odoo CRM models its sales side around crm.lead (unsourced pipeline entries) and res.partner (contacts/companies), with opportunity tracking via crm.lead itself once a lead converts. The two models share the concept of a named contact with contact details, but Open Dental's clinical fields — insurance carrier, Rx lists, recall schedule, treatment notes, PatFields — have no native equivalent in Odoo's standard crm module and require Odoo custom field creation before migration values can land. We extract Open Dental patients via the API using /patients endpoints with optional PatNum and SecDateTEdit filters for delta runs, resolve family-group heads using guarantor relationships, then map each record into Odoo res.partner (for existing patients) or crm.lead (for unsourced referrals). Appointment history, recall dates, and treatment notes migrate as Odoo mail.message or crm.activity records linked to the partner. Insurance plan data, Rx lists, and PatField custom values go into Odoo custom fields on res.partner — Odoo requires either Studio GUI access or a custom module with Python/XML for field creation, so we deliver a setup plan before data lands. No Open Dental workflow, automation, or practice-configuration data transfers: those constructs are destination-side schema in Odoo and must be rebuilt.
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 Open Dental 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.
Open Dental
Patient
Odoo CRM
res.partner
1:1Open Dental's Patient record maps to Odoo res.partner as the primary contact entity. The patient name, birthdate, address, phone, and email fields align directly. Family-group members share one res.partner record per patient; guarantor relationships are preserved via custom field or parent_id if the family head is set as a company-type partner.
Open Dental
Patient (referral source only)
Odoo CRM
crm.lead
1:manyOpen Dental patients that exist purely as referral sources (no appointment history, no insurance, no billing) route to Odoo crm.lead so they enter the sales pipeline without creating a full res.partner record. Any referral with actual treatment history lands as res.partner to preserve clinical context.
Open Dental
Patient (Guarantor / SuperFamilyHead)
Odoo CRM
res.partner (parent_id or custom family link)
1:1Open Dental's guarantor field identifies the family-group head. Odoo res.partner has parent_id for company hierarchies only, not family groups. We map guarantor to a custom field Family_Guarantor__c on res.partner, or set the guarantor as a separate company-type partner with child partners for each family member — your admin chooses the model before migration runs.
Open Dental
Appointment
Odoo CRM
crm.activity + mail.message
1:1Open Dental appointment history (date, provider, operatory, procedure codes, confirmed status) maps to Odoo crm.activity records linked to the res.partner. The appointment Note field migrates as a mail.message note attached to the activity. Original appointment timestamps are preserved in Odoo's date and create_date fields.
Open Dental
Recall
Odoo CRM
Custom field on res.partner (NextRecallDate__c) + crm.activity
1:1Open Dental's Recall system tracks next cleaning or checkup dates per patient. Odoo CRM has no native recall concept. We create NextRecallDate__c and RecallType__c custom fields on res.partner and optionally schedule a crm.activity reminder for the recall date so front-office staff see it in the Odoo activity queue.
Open Dental
InsPlan + PatPlan + Benefit
Odoo CRM
Custom fields on res.partner + ir.attachment
1:1Open Dental's insurance plan, patplan, and benefit tables contain normalized insurance data (carrier, group number, coverage percentages, annual maximums). Odoo CRM has no native insurance object. We map carrier name to InsuranceCarrier__c, group number to InsuranceGroup__c, and remaining benefit detail as an ir.attachment PDF or as a structured custom field depending on what your Odoo admin pre-creates.
Open Dental
RxPat (Prescription)
Odoo CRM
Custom field on res.partner (RxList__c, LastRxDate__c)
1:1Open Dental prescription records list medications per patient. Odoo CRM has no native prescription object. We consolidate active prescriptions into a custom text or character field (RxList__c) and store the most-recent Rx date separately (LastRxDate__c). Full Rx history is preserved as an exported PDF attached to the partner record.
Open Dental
PatField (custom fields)
Odoo CRM
Odoo custom fields on res.partner
1:1Open Dental PatFields support Text, PickList, Date, Checkbox, and Currency types. Each unique PatFieldDef in Open Dental requires a corresponding ir.model.fields entry in Odoo. We generate the Odoo custom field creation plan (field name, type, pick-list options for PickList types, and whether the field is required) so your Odoo admin can pre-create them before migration data is loaded.
Open Dental
Document (images, PDFs, scanned forms)
Odoo CRM
ir.attachment on res.partner
1:1Open Dental Documents (images, PDFs, radiographs) are stored in the Open Dental folder with a DocNum reference. We re-upload all document types except x-rays (which Open Dental's own conversion docs note are best bridged rather than imported) as ir.attachment records linked to the res.partner. File size limits and MIME type handling follow Odoo's ir_attachment constraints.
Open Dental
Provider / Referring Dentist
Odoo CRM
res.partner (type=contact, customer=False)
1:1Open Dental's Provider table (referring dentists, in-network providers) maps to Odoo res.partner records with customer=False so they appear in the Odoo contact directory without entering the sales pipeline. Provider specialty and NPI number map to custom fields ReferrerSpecialty__c and NPI__c.
Open Dental
ClaimProc (procedure claim history)
Odoo CRM
ir.attachment on res.partner
1:1Open Dental ClaimProc records track insurance claim status per procedure. Odoo CRM has no native claims-processing module. We export claim history as a CSV and attach it to the res.partner as an ir.attachment for reference. If your Odoo setup includes the Odoo Accounting app, claim payment history can map to account.move records in a separate accounting migration.
Open Dental
ProcedureLog (completed procedures)
Odoo CRM
mail.message on res.partner
1:1Open Dental procedure logs (ADA codes, tooth surfaces, surface notes, provider, date) migrate as mail.message records on the res.partner so the treatment history is visible in the Odoo chatter. Each procedure is logged as a separate message with the procedure code and description in the body.
Open Dental
Adjustment / PayPlan (billing ledger)
Odoo CRM
Custom note field or ir.attachment
1:1Open Dental account module holds adjustments, payment plans, and ledger entries. Odoo CRM does not include billing ledger functionality. We export the patient ledger as a CSV and attach it to the res.partner. If you activate Odoo Accounting alongside CRM, the ledger can map to account.move and account.move.line records in a follow-on accounting migration.
| Open Dental | Odoo CRM | Compatibility | |
|---|---|---|---|
| Patient | res.partner1:1 | Fully supported | |
| Patient (referral source only) | crm.lead1:many | Fully supported | |
| Patient (Guarantor / SuperFamilyHead) | res.partner (parent_id or custom family link)1:1 | Fully supported | |
| Appointment | crm.activity + mail.message1:1 | Fully supported | |
| Recall | Custom field on res.partner (NextRecallDate__c) + crm.activity1:1 | Fully supported | |
| InsPlan + PatPlan + Benefit | Custom fields on res.partner + ir.attachment1:1 | Fully supported | |
| RxPat (Prescription) | Custom field on res.partner (RxList__c, LastRxDate__c)1:1 | Fully supported | |
| PatField (custom fields) | Odoo custom fields on res.partner1:1 | Fully supported | |
| Document (images, PDFs, scanned forms) | ir.attachment on res.partner1:1 | Fully supported | |
| Provider / Referring Dentist | res.partner (type=contact, customer=False)1:1 | Fully supported | |
| ClaimProc (procedure claim history) | ir.attachment on res.partner1:1 | Fully supported | |
| ProcedureLog (completed procedures) | mail.message on res.partner1:1 | Fully supported | |
| Adjustment / PayPlan (billing ledger) | Custom note field or ir.attachment1: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.
Open Dental gotchas
X-ray images do not migrate between systems
Scanned documents require a separate image conversion with additional cost
Server must run MySQL with myISAM engine, not InnoDB
API pagination is limited to 100 records per request
Custom sheets use proprietary XML that only imports to Open Dental
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
Audit Open Dental PatField schema and insurance table structure
We connect to the Open Dental API (or database directly if self-hosted) and enumerate all PatFieldDef records, InsPlan records, and PatPlan relationships. We extract a full patient export including guarantor relationships, recall dates, Rx lists, and procedure history. This audit produces a PatField-to-Odoo-custom-field mapping plan with field names, Odoo field types, and pick-list options that your Odoo admin must pre-create. We also flag any patient with more than 5 active PatFields so you can decide whether to migrate all of them or prioritize a subset.
Build Odoo custom field schema and family-group mapping plan
Based on the audit, we deliver a step-by-step schema setup plan: which custom fields to create on res.partner via Odoo Studio (for simple Text/Date/Checkbox fields) and which require a custom Python module (for PickList fields with defined options). We also deliver the family-group mapping plan — for each patient with a guarantor, we specify whether the family maps via a dedicated Family partner (company-type parent) or via a custom Family_Guarantor__c field. Your Odoo admin creates the fields before we proceed to data load. We validate the schema before migration runs by doing a dry-run write on a test partner.
Extract and transform patient data with ETL layer
We extract Open Dental patients via the /patients API endpoint, paginating at 100 records per request with optional SecDateTEdit filters for delta runs. Our ETL layer transforms Pascal-cased JSON field names to Odoo's snake_case conventions, converts date formats to UTC-aware datetime, resolves guarantor PatNum values to Odoo partner IDs, and splits patients into res.partner (existing patients) and crm.lead (referral-only patients) based on appointment history. Appointment history, procedure logs, and recall dates are extracted as separate record sets linked to the patient by PatNum.
Run sample migration with field-level diff and owner resolution
A representative sample — typically 200–500 patient records spanning different clinics, family groups, and PatField configurations — migrates first. We generate a field-level diff showing source value, destination field, and mapped value for every field on each record. Owner and provider resolution is validated: Open Dental provider numbers are matched by email or name to Odoo res.users; any unmatched providers are flagged for admin review before the full run. You verify the family-group mapping and insurance field landing before we commit the full dataset.
Execute full migration with delta-pickup window and rollback readiness
The full patient dataset loads into Odoo via the XML-RPC API in sequenced batches (patients first, then appointments as activities, then documents as attachments). A delta-pickup window — typically 24–48 hours from the start of the full run — captures any patient records modified in Open Dental during cutover (new appointments, insurance updates, Rx additions). Our audit log records every write operation. If reconciliation finds discrepancies, one-click rollback reverts all Odoo records written during the migration run so you can correct the mapping and re-execute without data contamination.
Platform deep dives
Open Dental
Source
Strengths
Weaknesses
Odoo CRM
Destination
Strengths
Weaknesses
Complexity grading
Standard CRM migration. All 8 core objects map 1:1 between Open Dental and Odoo CRM.
Overall complexity
Standard migration
Derived from compatibility, mapping clarity, API constraints, and data volume across Open Dental and Odoo CRM.
Object compatibility
All 8 core objects map 1:1 between Open Dental 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
Open Dental: Remote mode: 1,000 elements; Local/Service mode: 10,000 elements; Enterprise tier doubles Remote mode limits.
Data volume sensitivity
Open Dental 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 Open Dental to Odoo CRM migration scoping. Not seeing yours? Book a call.
Walk through your Open Dental 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 Open Dental
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.