CRM migration
Field-level mapping, validation, and rollback between FreeCRM and Odoo CRM. We move data and schema; workflows are rebuilt natively in Odoo CRM.
FreeCRM
Source
Odoo CRM
Destination
Compatibility
10 of 12
objects map 1:1 between FreeCRM and Odoo CRM.
Complexity
CModerate
Timeline
3-5 weeks
Overview
FreeCRM and Odoo CRM differ fundamentally in data architecture. FreeCRM uses per-record template-driven fields where no two accounts share the same field schema; Odoo CRM uses a fixed PostgreSQL schema with res.partner for contacts and companies, crm.lead for both leads and opportunities, and ir.model.data for custom fields. We inventory every FreeCRM template in use during discovery, build a per-account field map, then pre-create matching custom fields in Odoo before writing any records. FreeCRM's CSV export covers Contacts, Companies, Deals, and Activity history but does not export workflow automations or custom template definitions. We flag these gaps during scoping so the customer knows exactly what requires manual rebuilding in Odoo. Pipeline stages are free-text values in FreeCRM; we extract the full stage list and configure corresponding stage columns in Odoo's crm.lead kanban before migration. Owner assignment in FreeCRM is inconsistently populated; we resolve by email against Odoo's res.users table and queue unmatched owners for admin provisioning before record import proceeds.
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 FreeCRM 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.
FreeCRM
Contact
Odoo CRM
res.partner
1:1FreeCRM Contact records map to Odoo res.partner with partner_type = contact. Standard fields (name, email, phone, address) migrate directly. FreeCRM's template-driven custom fields on contacts are inventoried during discovery and pre-created as custom fields on res.partner in Odoo. We split comma-separated FreeCRM tags into a character field or create Odoo tags via the crm.tag model depending on the customer's preference. Owner assignment from FreeCRM maps to res.partner.user_id by email match against Odoo res.users.
FreeCRM
Company
Odoo CRM
res.partner (company type)
1:1FreeCRM Company records map to Odoo res.partner with partner_type = company. The company name becomes res.partner.name; website and industry fields map to website and industry_id (the latter to res.partner.industry as a many2one). The parent-child relationship between FreeCRM contacts and companies maps to res.partner.parent_id on each contact record, which Odoo uses to build the company hierarchy in the kanban view.
FreeCRM
Lead
Odoo CRM
crm.lead (type = lead)
1:1FreeCRM Lead records map to Odoo crm.lead with type = lead. Lead status values from FreeCRM (which vary per account template) are mapped to Odoo's lead_stage_id stage columns during discovery. We extract the full FreeCRM field set per template, normalize picklist values, and create Odoo stage columns matching the FreeCRM stage names before migration. Lead source from FreeCRM maps to crm.lead.source_id. Any FreeCRM lead scoring or rating properties map to crm.lead.priority or a custom float field.
FreeCRM
Deal
Odoo CRM
crm.lead (type = opportunity)
1:1FreeCRM Deal records map to Odoo crm.lead with type = opportunity. Deal amount maps to crm.lead.expected_revenue; expected close date maps to date_deadline. The FreeCRM deal stage maps to an Odoo crm.lead.stage_id that we configure as a stage column in the pipeline kanban before migration. FreeCRM pipeline names map to Odoo crm.lead.team_id (sales team) or to a separate crm.lead.campaign_id if the customer uses Odoo's CRM campaign module. Closed-Lost and Closed-Won statuses from FreeCRM map to Odoo's lost and won stage states respectively.
FreeCRM
Pipeline Stage
Odoo CRM
crm.stage
lossyFreeCRM pipeline stages are free-text categorical values defined per account, not a structured stage object. We extract the full stage list from every FreeCRM pipeline during discovery, create corresponding crm.stage records in Odoo with the same sequence order, and map each FreeCRM stage name to its Odoo equivalent during Deal import. Probability percentages from FreeCRM migrate to crm.stage.probability on each stage.
FreeCRM
Activity: Task
Odoo CRM
mail.activity
1:1FreeCRM task records export with title, due date, status, and related-to (contact or company) fields. We map these to Odoo mail.activity with activity_type_id, res_model = res.partner or crm.lead, res_id pointing to the migrated record ID, user_id resolved by email match, and date_deadline from the FreeCRM due date. Activity creation timestamp migrates to mail.activity.create_date for historical sequencing.
FreeCRM
Activity: Event
Odoo CRM
calendar.event
1:1FreeCRM event records (meetings, calls) export with title, start datetime, end datetime, location, and related-to. We map these to Odoo calendar.event with name, start_datetime, stop_datetime, and location preserved. Attendee links from FreeCRM migrate as calendar.attendee records with partner_id resolved via email match against Odoo res.partner. Recurring events in FreeCRM export as individual rows per occurrence.
FreeCRM
Activity: Call Log
Odoo CRM
mail.activity (activity_type = Call)
1:1FreeCRM call logs export as activity records with type = call, duration, disposition, and related-to. We map these to Odoo mail.activity with activity_type_id set to the Odoo Call activity type, duration stored in a custom field or in the activity's note, and res_id/res_model pointing to the migrated contact or lead. Call outcome from FreeCRM maps to the activity note field or a custom disposition field.
FreeCRM
Custom Field
Odoo CRM
ir.model.fields (custom)
lossyFreeCRM custom fields are defined per-record via templates and vary by account. We inventory every distinct custom field across all FreeCRM templates during discovery, create corresponding custom fields on the appropriate Odoo model (res.partner, crm.lead, etc.) via Settings > Technical > Fields or metadata API before migration begins, and map each source field to the new Odoo field during data load. Field types are inferred from FreeCRM data values (text, number, date, checkbox, dropdown).
FreeCRM
Tag
Odoo CRM
crm.tag
1:1FreeCRM tags export as comma-separated values on Contact and Company records. We split them into distinct values and map each to Odoo crm.tag records. Tag assignments migrate as crm.lead.tag_ids (many2many) entries on the corresponding crm.lead records. If FreeCRM tags appear on Company records, we attach them to the corresponding res.partner as an Odoo tag or as a character field depending on the customer's tagging strategy preference.
FreeCRM
Form (Web-to-Lead)
Odoo CRM
Form mapping delivered as documentation
1:1FreeCRM web-to-lead form definitions export with field names and submission history. Form submissions migrate as crm.lead records with type = lead and source identified as the originating form. We deliver a written mapping of form field names to Odoo crm.lead fields rather than migrating form definitions, because FreeCRM form builder configurations do not export. The customer rebuilds forms in Odoo Forms or a third-party form tool and maps the new form IDs during setup.
FreeCRM
User / Owner
Odoo CRM
res.users
1:1FreeCRM user accounts export with name and email. We match by email against Odoo res.users to resolve OwnerId on crm.lead and res.partner.user_id on contacts. Owners without a matching Odoo user are placed in a reconciliation queue for the customer's admin to provision the user account before record import resumes. This step gates all subsequent imports because OwnerId is required on crm.lead in most Odoo configurations.
| FreeCRM | Odoo CRM | Compatibility | |
|---|---|---|---|
| Contact | res.partner1:1 | Fully supported | |
| Company | res.partner (company type)1:1 | Fully supported | |
| Lead | crm.lead (type = lead)1:1 | Fully supported | |
| Deal | crm.lead (type = opportunity)1:1 | Fully supported | |
| Pipeline Stage | crm.stagelossy | Fully supported | |
| Activity: Task | mail.activity1:1 | Fully supported | |
| Activity: Event | calendar.event1:1 | Fully supported | |
| Activity: Call Log | mail.activity (activity_type = Call)1:1 | Fully supported | |
| Custom Field | ir.model.fields (custom)lossy | Fully supported | |
| Tag | crm.tag1:1 | Fully supported | |
| Form (Web-to-Lead) | Form mapping delivered as documentation1:1 | Fully supported | |
| User / Owner | res.users1: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.
FreeCRM gotchas
Template-driven fields vary per account
Free tier storage and feature caps are undocumented
Workflow automations do not export
No documented public API
Invoice and campaign data only in Pro tier
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 template inventory
We audit every FreeCRM template in active use by extracting the full field set across a sample of exported records. We identify the distinct field names, infer field types from data values, and categorize fields as standard (name, email, phone, address) or custom (industry-specific or account-specific). We also identify active FreeCRM pipeline stages, owner assignments, tag values, and any automation definitions in use. The discovery output is a written migration scope document with the per-template field map, stage mapping table, and a flag list of automations requiring manual rebuild.
Odoo schema provisioning
We create the destination Odoo schema before any data migration begins. This includes creating custom fields identified during discovery on res.partner and crm.lead via Settings > Technical > Fields or via Odoo's XML-RPC ir.model.data API. We configure crm.stage records matching the FreeCRM pipeline stages in sequence order with corresponding probability values. We set up crm.tag records for each distinct FreeCRM tag value. If the customer uses multiple Odoo CRM teams, we configure crm.team records corresponding to FreeCRM pipeline groupings. All schema changes are applied to a staging Odoo database first for validation.
Owner reconciliation
We extract every distinct owner email referenced on FreeCRM Contact, Company, Lead, Deal, and Activity records. We match by email against Odoo res.users to resolve the user_id on each destination record. Owners without a matching Odoo user are placed in a reconciliation queue for the customer's admin to provision before record import resumes. Migration cannot proceed past owner reconciliation because OwnerId is a required reference on crm.lead in most Odoo CRM configurations. We also confirm Odoo user licensing (Community free users vs Enterprise paid seats) aligns with the migration scope.
Sandbox migration and validation
We run a full migration into an Odoo staging database using a representative data sample (typically the 10 most recent months or 10% of total records). The customer's admin reviews migrated records for field-level accuracy, checks that pipeline stages display correctly in the kanban view, and spot-checks 25-50 random records against the FreeCRM source. We reconcile record counts per object and validate that parent-child relationships (company to contacts, leads and opportunities to owner) resolved correctly. Mapping corrections happen in staging, not in production.
Production migration in dependency order
We run production migration in strict dependency order: res.users validated, then res.partner (companies first, then contacts with parent_id resolved), then crm.lead (leads with stage_id resolved, then opportunities with partner_id and user_id resolved), then mail.activity and calendar.event for historical activity. Custom field values load in the same pass as their parent records. Each phase emits a row-count reconciliation report before the next phase begins. We use Odoo's XML-RPC API with batch chunking for all writes.
Cutover, validation, and automation handoff
We freeze FreeCRM writes during cutover, run a final delta migration of any records modified during the migration window, then set Odoo as the system of record. We validate that pipeline kanban stage counts match FreeCRM deal stage counts, that activity timelines are ordered by original FreeCRM timestamp, and that custom field values are present on a random sample of migrated records. We deliver the automation inventory document listing every FreeCRM workflow requiring rebuild in Odoo Studio, with a recommended Odoo action type per workflow trigger. We do not rebuild automations as Odoo Studio records inside the migration scope.
Platform deep dives
FreeCRM
Source
Strengths
Weaknesses
Odoo CRM
Destination
Strengths
Weaknesses
Complexity grading
Moderate CRM migration. 4 of 8 objects need a mapping; the rest are 1:1.
Overall complexity
Moderate migration
Derived from compatibility, mapping clarity, API constraints, and data volume across FreeCRM and Odoo CRM.
Object compatibility
4 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
FreeCRM: Not publicly documented.
Data volume sensitivity
FreeCRM 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 FreeCRM to Odoo CRM migration scoping. Not seeing yours? Book a call.
Walk through your FreeCRM 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 FreeCRM
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.