CRM migration

Migrate from PHP CRM to Odoo CRM

Field-level mapping, validation, and rollback between PHP CRM and Odoo CRM. We move data and schema; workflows are rebuilt natively in Odoo CRM.

PHP CRM logo

PHP CRM

Source

Odoo CRM

Destination

Odoo CRM logo

Compatibility

67%

8 of 12

objects map 1:1 between PHP CRM and Odoo CRM.

Complexity

BStandard

Timeline

3-5 weeks

Rollback included Accuracy guarantee Field-level validation

Overview

What this migration involves

Moving from PHP CRM to Odoo CRM is a structural migration from a small-business niche platform to a modular ERP suite used by over five million organizations. PHP CRM stores all data in a flat or loosely relational schema with user-defined custom fields, no published API documentation, and application-layer workflows that are not accessible for export. Odoo CRM uses a strict ORM model with crm.lead for pre-qualification and crm.lead for qualified opportunities, both inheriting from res.partner. We enumerate every custom field in the source PHP CRM deployment during discovery, then map them to Odoo custom fields on the correct model before import. Pipeline stages migrate as Odoo stage records attached to crm.lead pipeline definitions. Activities (calls, emails, meetings) map to Odoo's mail.message and crm.activity models. Workflows, email templates, and automations in PHP CRM are application-layer code and do not migrate; we deliver a written inventory of every configured rule requiring rebuild in Odoo Studio or server actions post-migration.

Field-level fidelity

Every standard and custom field arrives verified.

Schema-aware mapping

AI proposes the map; you confirm before any record moves.

Relationships preserved

Parent–child, lookups, and ownership stay linked.

Full activity history

Calls, emails, meetings — with original timestamps.

Attachments & notes

Documents, uploads, and inline notes move with the record.

Why teams make this switch

Two sides of the same decision

Leaving

PHP CRM logo

PHP CRM

What's pushing teams away

  • Extremely limited online presence with very few user reviews makes it difficult to assess long-term reliability and support quality.
  • Advanced feature setup complexity frustrates less technical users despite the interface being described as user-friendly for basic navigation.
  • Performance issues reported in G2 reviews suggest the platform may struggle under heavier data volumes or concurrent user loads.
  • Lack of transparent API documentation and community resources makes integrations and custom development high-effort for internal teams.

Choosing

Odoo CRM logo

Odoo CRM

What's pulling them in

  • Teams choose Odoo CRM for its modular architecture — one base install with one-click app additions means they can adopt CRM alone and add accounting, inventory, or sales later as the business grows.
  • Small businesses pick Odoo because the Community edition is free and open-source, with no per-user or contact limits, allowing full evaluation before committing to a paid Enterprise tier.
  • The drag-and-drop Kanban pipeline and AI lead scoring are highlighted across G2 reviews as concrete features that make lead management faster and more visual than spreadsheet-based workflows.
  • Odoo's native integration with email, live chat, SMS, VoIP, and WhatsApp means inbound leads from multiple channels feed into a single pipeline without third-party middleware.
  • Companies in retail, supply chain, and construction value that Odoo's CRM module shares the same PostgreSQL database and UI as its ERP modules, eliminating data silos between sales and operations.

Object mapping

How PHP CRM objects map to Odoo CRM

Each row shows how a PHP CRM 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.

PHP CRM

Contact

maps to

Odoo CRM

res.partner

1:1
Fully supported

PHP CRM Contact records map to Odoo res.partner with partner_type set to 'contact'. The source email field maps to Odoo's email field; phone maps to phone. We resolve the parent Company relationship by matching the source company_name against the already-migrated res.partner records and populate parent_id accordingly. If the source contact has no company, the record is imported as an individual partner without a parent_id. Address fields (street, city, state, country, zip) map via Odoo's partner address fields.

PHP CRM

Company

maps to

Odoo CRM

res.partner

1:1
Fully supported

PHP CRM Company records map to Odoo res.partner with partner_type set to 'company'. The company_name field maps to Odoo's name field on the partner record. We import Companies first as parent entities before any Contact import so that the parent_id lookup is satisfied at Contact insert time. Company-level custom fields from PHP CRM map to custom res.partner fields in Odoo. If the source Company has no associated address, we set address fields to empty rather than null to satisfy Odoo's address format expectations.

PHP CRM

Deal

maps to

Odoo CRM

crm.lead

1:1
Fully supported

PHP CRM Deal records map to Odoo crm.lead (the opportunity model). The source dealstage maps to an Odoo crm.stage record on the crm.lead.pipeline. We resolve partner_id from the source deal's linked Company or Contact at migration time. The deal's expected_close_date maps to Odoo's date_deadline field; amount maps to Odoo's planned_revenue field. Type on crm.lead is set to 'opportunity' during import. Owner assignment maps to Odoo user_id via email matching against res.users.

PHP CRM

Pipeline

maps to

Odoo CRM

crm.lead.model

lossy
Fully supported

PHP CRM Pipeline definitions map to Odoo crm.lead.model records. Each source pipeline becomes a separate crm.lead.model in Odoo with a name matching the source pipeline name. We configure the model's stage_ids to reference the migrated crm.stage records. The pipeline's sequence order is preserved via Odoo's sequence field on the model. If the source deployment has a single default pipeline, it maps to the standard Odoo CRM pipeline without configuration changes.

PHP CRM

Pipeline Stage

maps to

Odoo CRM

crm.stage

lossy
Fully supported

PHP CRM Pipeline Stage records map to Odoo crm.stage records attached to the corresponding crm.lead.model. Stage name, sequence order, and probability percentage migrate from the source stage values. Odoo requires stage records to belong to a specific pipeline model; we resolve the parent pipeline before inserting each stage. If a source stage has no Odoo equivalent (e.g., custom named stages with no close/won equivalent), we flag them for manual Odoo stage creation before migration resumes.

PHP CRM

Task

maps to

Odoo CRM

project.task

1:1
Fully supported

PHP CRM Task records map to Odoo project.task linked to the default crm_project if the task is CRM-related. The source due date maps to date_deadline; assignee maps to user_id via email matching. Task status (open/closed) maps to Odoo's kanban_state field. If the source task has a linked Deal or Contact, we resolve the destination crm.lead or res.partner ID and set the task's project_id and partner_id accordingly. Task description maps to the Odoo description field as plain text.

PHP CRM

Note

maps to

Odoo CRM

mail.message

1:1
Fully supported

PHP CRM Note records attach free-text content to any entity. We migrate Notes as Odoo mail.message records with message_type set to 'comment'. The WhoId (Contact or Company) and WhatId (Deal) are resolved to destination res.partner and crm.lead IDs, and the message is linked via mail.message.model and mail.message.res_id. Author is set to the migrating Odoo user who owns the note assignment. Note body migrates as HTML-formatted plain text without image attachments unless the source provides a file path accessible during extraction.

PHP CRM

Activity

maps to

Odoo CRM

mail.message or crm.activity

1:1
Fully supported

PHP CRM Activity records (calls, emails, meetings) with timestamps and outcome data map to a combination of Odoo mail.message and crm.activity. Call activities map to mail.message with message_type='comment' and a custom call disposition field; the source call duration and outcome map to custom crm.activity fields if defined. Email activities map to mail.message with attachments preserved as ir.attachment records linked via mail.message. Meeting activities map to calendar.event records in Odoo's calendar module if available, or to mail.message if calendar is not in scope. We enumerate the actual activity field schema present in the source PHP CRM instance during discovery since PHP CRM activity schemas vary by deployment.

PHP CRM

Custom Field

maps to

Odoo CRM

ir.model.fields

lossy
Fully supported

PHP CRM user-defined custom fields on any standard object map to Odoo ir.model.fields records created via Odoo Studio or direct Python model definition. Each custom field requires a separate Odoo field creation step before the associated record import begins. We enumerate all custom fields during mandatory discovery, capture the field type (text, number, date, checkbox, dropdown) from PHP CRM, and map to the equivalent Odoo field type (char, text, float, datetime, boolean, selection). Fields with no Odoo equivalent are flagged for manual field creation before migration resumes.

PHP CRM

User/Owner

maps to

Odoo CRM

res.users

1:1
Fully supported

PHP CRM Owner records on Deals, Tasks, and Contacts map to Odoo res.users by email matching. We extract every distinct owner referenced across all objects, match against the destination Odoo res.users table, and flag any owner without a matching user for admin provisioning. Owner assignment on crm.lead maps to Odoo's user_id; task assignment maps to project.task user_id. Active/inactive status from the source is preserved in the Odoo user record. The customer's Odoo admin provisions any missing users before record import resumes.

PHP CRM

Tag/Label

maps to

Odoo CRM

crm.tag

lossy
Fully supported

PHP CRM Tags are per-instance label vocabulary that map to Odoo crm.tag records. We extract the full tag taxonomy from the source, create matching crm.tag records in Odoo, then link them to the appropriate crm.lead records via crm.lead.tag_rel at migration time. If the source tag vocabulary is large (50+ tags), we recommend the customer audit the taxonomy before import to remove deprecated labels. Tags with no clear Odoo equivalent are flagged for customer review.

PHP CRM

Attachment

maps to

Odoo CRM

ir.attachment (manual)

1:1
Fully supported

PHP CRM stores file attachments on the local filesystem (self-hosted) or cloud storage path, not through a documented API endpoint. We cannot programmatically extract attachments. We export the attachment directory to a local path for the customer's review and advise re-uploading manually via Odoo's document management interface or using Odoo's bulk file import tools post-migration. This gap is documented explicitly in the migration scope.

Gotchas + challenges

What specifically takes care here

Platform-specific issues from each side, plus the pair-specific challenges that don't show up on either platform's page on its own.

PHP CRM logo

PHP CRM gotchas

High

No publicly documented API rate limits or endpoints

High

Attachment and file storage not accessible via API

Medium

Custom field taxonomy varies per deployment

Medium

Workflows and automations are not portable

Low

Limited review corpus for accurate benchmarking

Odoo CRM logo

Odoo CRM gotchas

High

Odoo.sh version gating blocks assisted migrations from trial

High

Enterprise modules fail to install on Community after database restore

Medium

Custom module view inheritance breaks between Odoo major versions

Medium

Custom fields risk losing their application context on Community

Low

API access for Community is gated behind the Custom Plan

Pair-specific challenges

  • PHP CRM exposes no publicly documented API endpoints or rate limits

    PHP CRM's developer tools page is accessible to logged-in users but publishes no endpoint schemas, authentication details, or rate limits publicly. Without documented limits, we pace all API calls conservatively to avoid triggering unknown throttling rules that could interrupt a live migration. If API access credentials cannot be obtained or the API proves unreliable during scoping, we fall back to CSV export via the PHP CRM admin panel. CSV export has lower record counts per file and no guarantee of relationship preservation across objects, which increases transformation work during the extract phase.

  • Odoo crm.lead and crm.lead model split requires schema design before import

    Odoo separates unqualified prospects (crm.lead) from qualified opportunities (crm.lead), with crm.lead records inheriting from res.partner. PHP CRM uses a single Deal object for all opportunities regardless of qualification stage. We design the Odoo stage-to-model mapping during scoping: source Deals in early pipeline stages map to crm.lead (lead), and source Deals past a configurable stage threshold map to crm.lead (opportunity). The threshold is defined per customer based on their pipeline definition. Migrations that skip this step result in all source Deals landing as leads without the opportunity-level properties needed for revenue reporting.

  • Custom field enumeration is mandatory and must complete before any record import

    PHP CRM allows user-defined custom fields on all standard objects without a standardized taxonomy, meaning every deployment has a unique field inventory. We run a mandatory discovery phase enumerating every custom field present in the source instance before writing any Odoo field mapping or schema. Custom fields that are not discovered before import are silently dropped when the source record is loaded into Odoo. We use the PHP CRM REST API to query the field metadata per object type, cross-referenced against any CSV export headers.

  • Odoo custom fields require field creation before record import

    Odoo does not auto-create custom fields from an import; each ir.model.fields record must be created explicitly before associated data is loaded. This creates a two-phase import process: first, create all destination custom field definitions in Odoo via the ir.model.fields API or Odoo Studio; second, import the record data referencing those fields. If a record is loaded before its custom field is created, Odoo ignores the field value silently. We sequence schema creation as a gate before every record import phase.

  • Workflows and automations in PHP CRM are application-layer code and do not migrate

    PHP CRM automated workflow rules and business logic live in application code or admin-configured rules that are not exposed via API or CSV export. We do not migrate automations as code. Every migration plan includes a written inventory of every configured PHP CRM automation with its trigger, conditions, and actions, mapped to the equivalent Odoo automated action, server action, or workflow trigger. The customer's Odoo administrator rebuilds these in Odoo Studio post-migration. We do not provide post-migration admin support or workflow rebuild as standard scope.

Migration approach

Six steps for a successful PHP CRM to Odoo CRM data migration

  1. Discovery and credentials scoping

    We audit the source PHP CRM instance via REST API and admin panel access, enumerating every object type, custom field, pipeline, stage, user, tag, and activity schema present. We capture record counts per object, API pagination behavior, and any errors encountered during API calls to determine whether API extraction or CSV export is the primary extraction method. We request PHP CRM admin credentials, Odoo database credentials or API key, and Odoo.sh or self-hosted access for field creation and record import. The discovery output is a written migration scope with object inventory, record counts, and a recommendation on extraction method (API or CSV).

  2. Source data extraction and transformation

    We extract data in dependency order: Companies first (parent), then Contacts (with parent_id resolved to Companies), then Deals/Leads (with partner_id resolved), then Tasks and Notes (with parent entity resolved), then Activities (with linked entity IDs from the prior phases). For CSV exports, we handle the relationship by including foreign-key columns (company_id, contact_id) that we resolve against the extracted records. For API extraction, we paginate through the source records using the API's pagination parameters. All extracted data is staged in a transformation workspace with a schema manifest documenting every field, type, and mapping rule.

  3. Odoo schema preparation and custom field creation

    We create all required Odoo schema elements before importing records. This includes crm.lead.model pipeline definitions with stage sequences, crm.stage records per pipeline, custom res.partner fields for company-level custom data, custom crm.lead fields for deal-level custom data, and crm.tag records for the source tag taxonomy. Custom field creation is sequenced as a gate: no record import begins until the corresponding custom field exists in the destination Odoo instance. We deploy schema changes via Odoo XML-RPC API or direct database insert into a staging environment first for validation.

  4. Staging migration and reconciliation

    We run a full migration into a staging Odoo environment (copy of production database or a separate Odoo instance) using the full extracted data volume. The customer's Odoo administrator reconciles record counts against the source PHP CRM database, spot-checks 25-50 records per object for field accuracy and relationship correctness, and validates that pipeline stages display correctly in the Odoo Kanban view. Any mapping corrections, dropped fields, or relationship resolution failures are fixed in the transformation layer and re-run in staging before production migration begins.

  5. Production migration in dependency order

    We run production migration in strict record-dependency order: Companies (res.partner with partner_type=company), then Contacts (res.partner with partner_type=contact and parent_id resolved), then crm.tag records, then crm.lead.model and crm.stage pipeline definitions, then crm.lead records (leads and opportunities with user_id and partner_id resolved), then project.task records, then mail.message records for Notes and Activities. Each phase emits a row-count reconciliation report before the next phase begins. The PHP CRM instance remains writable during migration; we capture any records modified during the migration window as a delta load before cutover.

  6. Cutover, validation, and workflow rebuild handoff

    We freeze writes to PHP CRM during the cutover window, execute the final delta migration of any records modified during the migration window, then set Odoo CRM as the system of record. We validate record counts, spot-check 10 records per object in Odoo against the source PHP CRM database, and confirm that pipeline stages and Kanban views display correctly. We deliver the workflow and automation inventory document to the customer's Odoo administrator. We support a one-week hypercare window where we resolve reconciliation issues raised by the customer's team. Post-migration admin support, Odoo Studio workflow rebuild, and user training are outside standard scope and are separate engagements.

Platform deep dives

Context on both ends of the pair

PHP CRM logo

PHP CRM

Source

Strengths

  • Free open-source self-hosted option with full source code access for modification and audit.
  • Managed cloud hosting from $120/year is low cost compared to per-seat SaaS alternatives.
  • REST API available for lead capture from websites and external integrations.
  • Fully customizable codebase allows adding or modifying modules without vendor constraints.
  • Self-hosted data on customer server provides complete data sovereignty and compliance flexibility.

Weaknesses

  • Very limited online reviews and community presence makes due diligence difficult.
  • API documentation is not publicly detailed, requiring direct access to the developer tools page for integration planning.
  • Small team or niche market positioning raises concerns about long-term product support and development roadmap.
  • Advanced customization requires PHP development expertise, limiting adoption to teams with technical resources.
  • Performance issues reported in reviews suggest potential scaling limitations under heavier workloads.
Odoo CRM logo

Odoo CRM

Destination

Strengths

  • Modular open-source architecture lets teams start with CRM and add ERP apps as needs grow, all sharing one PostgreSQL database.
  • Free Community edition with no contact limits and full source code access means zero licensing cost for evaluation and small deployments.
  • Drag-and-drop Kanban pipeline with AI lead scoring gives a visual, prioritized view of the sales funnel without requiring custom configuration.
  • Native integrations with email, live chat, SMS, VoIP, WhatsApp, and social media feed all inbound leads into a single unified inbox.
  • Active Odoo Community Association (OCA) maintains dozens of community-maintained modules on GitHub for extended functionality.

Weaknesses

  • Gmail and email integration reliability is a recurring complaint — threads drop and conversations scatter across inboxes, disrupting sales team workflows.
  • Enterprise edition pricing stacks quickly: multiple apps at per-user rates ($25–$50/user/month) plus Odoo.sh hosting costs more than many SMBs anticipate.
  • Setup and configuration complexity increases significantly once custom fields, automation rules, and multiple installed modules are in play.
  • Odoo.sh trial databases run on a version (e.g., 18.3) that is not directly migratable to Odoo.sh, blocking the assisted migration path Odoo advertises.
  • Version upgrades between major Odoo releases (e.g., 17→18) frequently break custom module view definitions and XPath expressions, requiring manual remediation.

Complexity grading

How hard is this migration?

Standard CRM migration. 2 of 8 objects need a mapping; the rest are 1:1.

B

Overall complexity

Standard migration

Derived from compatibility, mapping clarity, API constraints, and data volume across PHP CRM and Odoo CRM.

  • Object compatibility

    B

    2 of 8 objects need a mapping; the rest are 1:1.

  • Field mapping clarity

    C

    Field mapping is derived from defaults — final spec confirmed during the sample migration.

  • Timeline complexity

    B

    8-object category — typical timelines run 2–7 days end-to-end.

  • API constraints

    B

    PHP CRM: Not publicly documented.

  • Data volume sensitivity

    B

    PHP CRM doesn't expose a bulk API — REST + parallelization used for high-volume runs.

Estimator

Estimate your PHP CRM to Odoo CRM migration cost

Rule-based pricing — no per-record fees, no manual quotes. Migrations over 2M records are scoped individually.

Step 1

What are you migrating?

Pick a category, then your source and destination platforms.

Category

FAQ

Frequently asked questions about PHP CRM to Odoo CRM data migrations

Answers to the questions buyers ask most during PHP CRM to Odoo CRM migration scoping. Not seeing yours? Book a call.

Can't find your answer?

Walk through your PHP CRM to Odoo CRM migration with a real engineer — 30 minutes, free, written quote within 24 hours.

Book a free 30 minute consultation

Most PHP CRM to Odoo CRM migrations land between three and five weeks for accounts under 15,000 contacts, 3,000 deals, and fewer than 20 custom fields with no multi-pipeline complexity. Migrations with 30+ custom fields, multiple pipelines, large activity histories (over 200,000 records), or co-migration of Odoo accounting or inventory modules extend to six to ten weeks because of custom field enumeration, stage mapping design, and the parent-record resolution work required. The timeline also depends on PHP CRM API responsiveness and whether API extraction or CSV export is used as the primary extraction method.

Adjacent paths

Related migrations to explore

Ready when you are

Move from PHP CRM.
Land in Odoo CRM, intact.

Tell us record counts and timeline. We'll come back with a written quote inside 1 business day — no commitment, no sales pitch.

Accuracy guarantee Rollback included Quote in 1 business day