CRM migration
Field-level mapping, validation, and rollback between PracticeHub and Odoo CRM. We move data and schema; workflows are rebuilt natively in Odoo CRM.
PracticeHub
Source
Odoo CRM
Destination
Compatibility
11 of 11
objects map 1:1 between PracticeHub and Odoo CRM.
Complexity
BStandard
Timeline
4–8 weeks
Overview
PracticeHub stores patient data as dedicated objects — patients with healthcare fields (date of birth, blood type, allergies, emergency contact), appointments with practitioner and visit-type metadata, prescriptions, and files. Odoo CRM uses a modular model: res.partner holds contacts and companies, crm.lead handles leads and opportunities, and ir.attachment stores files. There is no native healthcare-equivalent object in Odoo, so patient medical metadata migrates to custom fields on res.partner, medical history documents migrate as ir.attachment records linked to the partner, and appointment records become crm.lead entries or calendar events with custom visit-type fields. PracticeHub exposes a REST API at https://{account_domain}.{region}.practicehub.io/api with a hard rate limit of 1 request per second per account — large patient databases require staged batch extraction with pagination. FlitStack AI sequences the migration so foreign keys resolve correctly: practitioners matched by email to Odoo users, clinic locations mapped to a custom clinic field, and files downloaded from PracticeHub and re-uploaded as binary ir.attachment records. Workflows, automation rules, and notification triggers are Odoo-specific constructs that do not transfer — we export definitions as a rebuild reference for the Odoo admin. A 24–48 hour delta-pickup window captures new appointments created in PracticeHub during cutover before the final reconciliation and one-click rollback.
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 PracticeHub 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.
PracticeHub
Patient
Odoo CRM
res.partner
1:1PracticeHub patient maps to Odoo res.partner, which is the unified model for contacts and companies. Standard fields (name, email, phone, address) migrate directly. Healthcare-specific fields — date_of_birth, blood_type, allergies, emergency_contact — map to custom fields on res.partner that must be pre-created in Odoo before migration data loads.
PracticeHub
Patient (contact details)
Odoo CRM
res.partner (contact fields)
1:1Patient first_name, last_name, email, phone, mobilephone, address_line_1, address_line_2, city, state, zip, and country map directly to Odoo res.partner fields. The address stored as structured fields in PracticeHub maps to Odoo's street, street2, city, state_id, zip, and country_id fields — address components must be parsed if PracticeHub exports as a single string.
PracticeHub
Appointment
Odoo CRM
crm.lead
1:1PracticeHub appointment records map to Odoo crm.lead entries with the patient linked via res.partner. Fields like visit_type, visit_status, and appointment_date become custom fields on the lead or are encoded in the lead name. The appointment_time field is preserved as a note or custom datetime field. Lead stages (New, In Progress, Completed, Cancelled) are mapped value-by-value to Odoo crm_stage entries.
PracticeHub
Appointment (practitioner)
Odoo CRM
res.users
1:1The practitioner_id and practitioner_email on a PracticeHub appointment map to an Odoo res.users record matched by email. Unmatched practitioners are flagged before migration — the admin either invites them to Odoo or assigns their appointments to a fallback user. This ensures activity ownership resolves correctly in Odoo after migration.
PracticeHub
Prescription
Odoo CRM
ir.attachment
1:1Prescription records (medication_name, dosage, frequency, prescribing_doctor, prescription_date) do not have a native equivalent in Odoo CRM. FlitStack creates a prescription_summary custom field on res.partner and stores the structured prescription data as a JSON-serialized note or text field. If the source has PDF prescriptions, they are downloaded and re-uploaded as ir.attachment records linked to the patient partner.
PracticeHub
Document
Odoo CRM
ir.attachment
1:1PracticeHub documents (title, description, file_url) and files (file_name, file_url, file_type) map to Odoo ir.attachment. The ir_attachment record requires res_model set to res.partner and res_id set to the partner id so the file attaches to the correct patient record in Odoo. FlitStack downloads files from PracticeHub URLs and re-uploads them as binary content to ir_attachment — this step is required because PracticeHub stores files externally.
PracticeHub
Clinic Location
Odoo CRM
res.partner (custom field)
1:1PracticeHub clinic_location stored as a value on patient records maps to a custom pick-list field (Clinic_Location__c) on res.partner in Odoo. If multiple clinic locations exist, a value-mapping table maps each PracticeHub location name to the corresponding Odoo clinic identifier. This prevents clinic data from being lost when patients have a location attribute in the source.
PracticeHub
Referring Doctor
Odoo CRM
res.partner (custom field)
1:1PracticeHub referring_doctor and referring_doctor_email fields have no Odoo CRM native equivalent. These migrate as custom fields on res.partner. If the referring doctor is an existing Odoo contact, the field can store the partner id; otherwise it stores the free-text name for manual reconciliation post-migration.
PracticeHub
Insurance Provider
Odoo CRM
res.partner (custom fields)
1:1PracticeHub insurance_provider and policy_number map to custom text fields on res.partner in Odoo. If the insurance company exists as a company record in Odoo, the insurance_provider field can store a res.partner id linking to the insurer as a related company. This preserves the carrier relationship for billing workflows in Odoo.
PracticeHub
Medical History / Notes
Odoo CRM
mail.message / ir.attachment
1:1PracticeHub medical_history is a free-text or structured field with no Odoo CRM native equivalent. It migrates as a long-text custom field on res.partner (medical_history__c) for searchability. If medical history is stored as a PDF or structured document in PracticeHub, it is downloaded and re-attached as an ir.attachment record linked to the patient partner, preserving the original document.
PracticeHub
Custom Patient Fields
Odoo CRM
res.partner (custom fields)
1:1PracticeHub allows custom fields per patient object — any field not covered by the standard mappings above requires a corresponding custom field on res.partner in Odoo. FlitStack audits the full PracticeHub field list during pre-migration, generates a custom-field creation checklist for the Odoo admin, and maps each field with type-aware handling (text, date, pick-list, boolean, integer) before data loads.
| PracticeHub | Odoo CRM | Compatibility | |
|---|---|---|---|
| Patient | res.partner1:1 | Fully supported | |
| Patient (contact details) | res.partner (contact fields)1:1 | Fully supported | |
| Appointment | crm.lead1:1 | Fully supported | |
| Appointment (practitioner) | res.users1:1 | Fully supported | |
| Prescription | ir.attachment1:1 | Fully supported | |
| Document | ir.attachment1:1 | Fully supported | |
| Clinic Location | res.partner (custom field)1:1 | Fully supported | |
| Referring Doctor | res.partner (custom field)1:1 | Fully supported | |
| Insurance Provider | res.partner (custom fields)1:1 | Fully supported | |
| Medical History / Notes | mail.message / ir.attachment1:1 | Fully supported | |
| Custom Patient Fields | res.partner (custom fields)1: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.
PracticeHub gotchas
1 req/sec API rate limit severely restricts bulk migration speed
Region-specific API base URLs must be resolved before extraction
Patient Library assets export as separate binary blobs
Prescription records may reference external Chewy pharmacy integration
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
Pre-migration audit and schema mapping
FlitStack reviews the PracticeHub REST API endpoint structure, enumerates all patient fields (standard and custom), appointment fields, practitioner records, prescription fields, document and file attachment references, and clinic location values. We generate a field-by-field mapping plan that identifies which PracticeHub fields map to Odoo standard fields, which require custom fields on res.partner or crm.lead, and which require custom field creation in Odoo before migration data loads. This audit output includes a custom-field creation checklist for the Odoo admin and a data-cleanse specification if duplicate patients or inconsistent address formats are found in the source.
Set up Odoo schema — custom fields and crm stages
Before any data moves, the Odoo admin (or FlitStack with admin credentials) creates the custom fields required for healthcare metadata: date_of_birth__c, blood_type__c, allergies__c, emergency_contact__c, insurance_provider__c, policy_number__c, clinic_location__c, contact_status__c, visit_type__c, and prescription_summary__c on res.partner; planned_date__c, appointment_time__c, visit_type__c, and reminder_sent__c on crm.lead. Odoo crm_stage entries are configured to match PracticeHub appointment visit_status values (New, In Progress, Completed, Cancelled). This step produces a ready-to-receive Odoo environment so the migration data load encounters no schema gaps.
Extract patient records in staged batches from PracticeHub API
FlitStack pulls PracticeHub patient records via the REST API using paginated GET requests, batching at 50 records per page to manage the 1-request-per-second rate limit. Extraction runs in a background job with automatic retry on HTTP 429 responses, progress logging, and a resumable checkpoint so a network interruption does not restart from zero. Extracted records are written to a staging area, cleaned (duplicate check on email, address normalization), and validated against the mapping plan before loading into Odoo.
Run sample migration with field-level diff
A representative slice — typically 50–200 patient records spanning different clinic locations and contact statuses — migrates first. FlitStack generates a field-level diff comparing source PracticeHub field values against the destination Odoo res.partner and crm.lead field values. The diff report is reviewed jointly with the Odoo admin to verify that date_of_birth maps correctly, pick-list values resolve as expected, and attachments are linked to the correct partner record. Custom field mapping is validated at this stage. No full migration commits until the sample diff is approved.
Execute full migration with delta-pickup window
With the schema validated, FlitStack runs the full migration: patients → res.partner first, then appointments → crm.lead with practitioner_email matched to res.users, then prescriptions and file attachments downloaded and re-uploaded to ir.attachment. During the cutover window, PracticeHub remains fully operational — the API stays in read-only mode so clinic staff can continue booking appointments. A 24–48 hour delta-pickup window captures any new patients or appointments created after the initial extraction cut-off. After delta records are loaded and reconciled, the final cutover is confirmed. An audit log records every operation; one-click rollback reverts to the pre-migration state if reconciliation finds data discrepancies.
Platform deep dives
PracticeHub
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 PracticeHub 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
PracticeHub: 1 request per second per account.
Data volume sensitivity
PracticeHub 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 PracticeHub to Odoo CRM migration scoping. Not seeing yours? Book a call.
Walk through your PracticeHub 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 PracticeHub
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.