ERP migration
Field-level mapping, validation, and rollback between Brightpearl and Odoo ERP. We move data and schema; workflows are rebuilt natively in Odoo ERP.
Brightpearl
Source
Odoo ERP
Destination
Compatibility
8 of 10
objects map 1:1 between Brightpearl and Odoo ERP.
Complexity
BStandard
Timeline
4-6 weeks
Overview
Moving from Brightpearl to Odoo ERP is a data-structure migration as much as a record copy. Brightpearl organises data around Contacts (customers and vendors with a role flag), Products with warehouse Locations across Zones, and a full order lifecycle from sales orders through to invoices and credit notes. Odoo separates its data model across the res.partner Contact table (with customer/supplier flag), product.product (with type variants), stock.location (with a parent_path hierarchy for Locations), and the account.account Chart of Accounts keyed by code. We sequence the migration in dependency order — Chart of Accounts and Contacts load first, then Products with Locations, then Orders and Invoices — so that foreign-key relationships resolve correctly at the destination. We flag the undocumented Brightpearl API rate limits as an extraction risk, the 36-hour pending order recovery window as a cutover risk, and the PCF-prefixed custom fields as explicit mapping work. We do not migrate Brightpearl Automation rules, which must be rebuilt in Odoo Studio or via the Odoo Workflow Automation app by the customer's admin post-migration.
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 Brightpearl object lands in Odoo ERP, including any object-level transformations, lookup resolution, or schema-design dependencies.
Typical mapping — final map is confirmed during the sample migration step.
Brightpearl
Contact (Customer and Supplier)
Odoo ERP
res.partner
1:1Brightpearl stores both customers and vendors as Contact records differentiated by a contact role flag. We map Brightpearl Contact to Odoo res.partner, setting the customer_rank or supplier_rank integer based on the role flag (a contact can have both). Address records (shipping and billing) migrate as res.partner address records with type set to 'invoice', 'delivery', or 'contact'. PCF_* custom fields map to res.partner custom fields that we create via Studio or XML before migration. Country names must be converted from Brightpearl's localisation strings (full country name, not ISO code) to Odoo's res.country lookup; we pre-load the country normalisation table during scoping.
Brightpearl
Product (Item and Service)
Odoo ERP
product.product
1:1Brightpearl Products map to Odoo product.product. The product type (stockable, consumable, service) maps from Brightpearl's product type. Multiple price list assignments per product in Brightpearl map to product.pricelist.item entries tied to the product. SKU (product code) becomes the product's default_code; the PCF_* custom fields migrate to custom fields on product.product. We export the full product catalogue including service items, and handle any Brightpearl product bundles as a separate mapping exercise because Odoo uses kit structures or bom lines for assemblies.
Brightpearl
Warehouse Location (Aisle / Bay / Shelf / Bin)
Odoo ERP
stock.location
lossyBrightpearl's four-level location hierarchy (Aisle / Bay / Shelf / Bin) under Zones maps to Odoo's stock.location tree using the parent_path pattern. Each Brightpearl location becomes a stock.location record with location_type = 'internal' and a parent_id pointing to the next level up. Brightpearl Zones map to stock.warehouse records, which own the top-level location under which picking locations sit. We reconstruct the full path as a string (Aisle-A / Bay-1 / Shelf-3 / Bin-12) in the location's complete_name field. Location-specific inventory levels (per-location stock) map to stock.quant records after both location and product are loaded.
Brightpearl
Inventory Summary and Detail
Odoo ERP
stock.quant
1:1Brightpearl inventory summary (total cost value per SKU) and inventory detail (per-warehouse, per-location levels) map to Odoo stock.quant. Each quant record holds product_id, location_id, quantity, and the lot/serial number if the product uses tracked inventory. We map Brightpearl's available and reserved quantities to Odoo's on_hand and reserved_quantity fields respectively. If Brightpearl uses FIFO costing, we set the product's costing_method to 'fifo' before quant import so that Odoo computes the same cost value.
Brightpearl
Price List
Odoo ERP
product.pricelist
1:manyBrightpearl price lists associate a price value with a product and a price list identifier, with multiple price lists per product being common. We map each Brightpearl price list to an Odoo product.pricelist with the corresponding currency (mapped from Brightpearl's currency code). Each price-list-to-product assignment becomes a product.pricelist.item with the computed price or percentage discount. Tiered pricing rules in Brightpearl map to multiple product.pricelist.item lines with different min_quantity thresholds.
Brightpearl
Sales Order
Odoo ERP
sale.order
1:1Brightpearl sales orders map to Odoo sale.order. Order headers carry order number, order date, customer reference (mapped via res.partner), and owner assignment (mapped via res.users). Line items map to sale.order.line with product_id resolved from the product mapping, quantity from the order line, and price from the applicable product.pricelist. Discounts from Brightpearl order lines migrate as discount fields on sale.order.line. Order status (pending, confirmed, shipped, invoiced) maps to Odoo state (draft, sale, done, cancelled) with attention to Brightpearl's fulfillment status for partial-ship scenarios.
Brightpearl
Purchase Order
Odoo ERP
purchase.order
1:1Brightpearl purchase orders map to Odoo purchase.order. The vendor assignment comes from the res.partner mapping (supplier-ranked contacts). Lead time and expected delivery dates migrate to purchase.order commitment_date. Received quantities and line-level received amounts map to Odoo's move_ids (stock moves) with the relevant product, quantity, and warehouse location. The purchase order state sequence (draft, sent, confirmed, done, cancelled) maps to Odoo's state field.
Brightpearl
Invoice and Credit Note
Odoo ERP
account.move
1:1Brightpearl invoices and credit notes map to Odoo account.move with move_type set to 'out_invoice' for invoices, 'out_refund' for customer credit notes, 'in_invoice' for vendor bills, and 'in_refund' for vendor credit notes. Accounting data embedded in the Brightpearl invoice record (account code, debit/credit amounts, tax) maps to account.move.line entries with account_id resolved via the Chart of Accounts mapping. Brightpearl's invoice-to-sales-order linkage is preserved as a sale_line_id on the Odoo move line. We do not migrate locked accounting periods; the customer must open or close periods in Odoo after migration based on their reporting calendar.
Brightpearl
Chart of Accounts
Odoo ERP
account.account
1:1Brightpearl's Chart of Accounts with account codes maps to Odoo account.account, using the account code as the dedupe key. Each account maps with its name, code, account_type (asset, liability, equity, revenue, expense), and reconcile flag set appropriately. We export the full account code list from Brightpearl and generate the Odoo XML or CSV import file during the pre-migration schema build. The customer validates the account structure before the production migration phase. If Brightpearl uses Sage's account code conventions (e.g., 1xxx assets, 2xxx liabilities), we map to Odoo's standard account types and allow the customer to adjust codes post-migration if their chart of accounts is non-standard.
Brightpearl
User and Owner Assignment
Odoo ERP
res.users
1:1Brightpearl staff members assigned as record Owners map to Odoo res.users. We extract the distinct owner list from Contact, Sales Order, and Purchase Order records and match by email against Odoo's res.users. Any Brightpearl owner without a matching Odoo user goes to a reconciliation queue for the customer's admin to provision before record import resumes. Owner references on migrated records resolve to the res.users id via the lookup table.
| Brightpearl | Odoo ERP | Compatibility | |
|---|---|---|---|
| Contact (Customer and Supplier) | res.partner1:1 | Fully supported | |
| Product (Item and Service) | product.product1:1 | Fully supported | |
| Warehouse Location (Aisle / Bay / Shelf / Bin) | stock.locationlossy | Fully supported | |
| Inventory Summary and Detail | stock.quant1:1 | Fully supported | |
| Price List | product.pricelist1:many | Fully supported | |
| Sales Order | sale.order1:1 | Fully supported | |
| Purchase Order | purchase.order1:1 | Fully supported | |
| Invoice and Credit Note | account.move1:1 | Fully supported | |
| Chart of Accounts | account.account1:1 | Fully supported | |
| User and Owner Assignment | 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.
Brightpearl gotchas
Brightpearl API rate limits are undocumented
Pending order download has a 36-hour recovery window
Country names must match exact localisation strings
Automation rules can execute in locked accounting periods
Placeholder contacts require valid formatted data
Odoo ERP gotchas
No rollback for CSV imports
External ID conflicts on re-import
Many2many field encoding in CSV imports
Large export timeouts require batching
Version schema drift between Odoo releases
Pair-specific challenges
Migration approach
Discovery and schema design
We audit the Brightpearl organisation across contacts, products, warehouse locations and zones, sales orders, purchase orders, invoices, credit notes, price lists, the Chart of Accounts, and inventory summary and detail. We assess data volume, duplicate density, and PCF_* custom field count. We pair this with Odoo edition and module selection (Community vs Enterprise, and which apps: Inventory, Accounting, Sales, Purchase, CRM). We design the destination schema: account.account with validated codes, res.partner with customer/supplier flags, product.product with costing method, stock.location with the parent_path tree, and custom fields created via Studio or XML. The discovery output is a written scope document and a schema design for customer sign-off.
Data quality audit and cleanup plan
We run a data quality audit against the Brightpearl export. This covers duplicate contacts (same email or name variants), products with missing SKUs, contacts without country or email fields, orders with unresolved customer references, and the Chart of Accounts for gaps or inactive accounts. We deliver a cleanup plan to the customer before extraction begins. The customer resolves data quality issues in Brightpearl or approves a data transformation strategy for migration. No extraction starts until the customer signs off on the cleanup plan.
Sandbox migration and reconciliation
We run a full migration into an Odoo test database (staging environment) using the customer's Brightpearl data. The customer's team reconciles record counts (contacts in, products in, orders in, invoices in, stock.quants in), spot-checks 25-50 records against the Brightpearl source for field accuracy, and validates that the Chart of Accounts structure reflects their financial reporting requirements. Any mapping corrections, custom field additions, or account code adjustments happen in this phase. No production migration begins until the customer signs off on the sandbox results.
Owner and user provisioning
We extract every distinct Brightpearl Owner referenced on Contacts, Sales Orders, and Purchase Orders and match by email against the Odoo res.users table. Owners without a matching Odoo user go to a reconciliation queue. The customer's admin provisions any missing Odoo users (active or inactive depending on whether the original Brightpearl user is still employed). This step is a hard gate: OwnerId references are required on most Odoo standard documents and migration cannot proceed past this point without resolution.
Production migration in dependency order
We run production migration in record-dependency order: Chart of Accounts (account.account), Contacts (res.partner), Products (product.product), Price Lists (product.pricelist), Locations (stock.location), Warehouses (stock.warehouse), Inventory (stock.quant), Sales Orders (sale.order), Purchase Orders (purchase.order), Invoices and Credit Notes (account.move). Each phase emits a row-count reconciliation report and the customer validates before the next phase begins. We use Odoo's XML-RPC and JSON-RPC API with rate-limit handling and exponential backoff. The migration user is granted the necessary access rights for the duration of the import.
Cutover, validation, and Automation rebuild handoff
We freeze Brightpearl writes during cutover and run a final delta migration of any records created or modified during the migration window. We validate the Odoo production environment against the Brightpearl source for record counts and spot-check accuracy. We disable any remaining Brightpearl Automation rules that touch financial fields. We deliver the Automation rules inventory document to the customer's admin team for rebuild in Odoo Studio. We support a one-week hypercare window where we resolve reconciliation issues raised during the first days of live use. We do not rebuild Brightpearl Automation rules as Odoo workflows inside the migration scope; that is a separate engagement or an internal admin task.
Platform deep dives
Brightpearl
Source
Strengths
Weaknesses
Odoo ERP
Destination
Strengths
Weaknesses
Complexity grading
Standard ERP 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 Brightpearl and Odoo ERP.
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
Brightpearl: Not publicly documented.
Data volume sensitivity
Brightpearl 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 Brightpearl to Odoo ERP migration scoping. Not seeing yours? Book a call.
Walk through your Brightpearl to Odoo ERP migration with a real engineer — 30 minutes, free, written quote within 24 hours.
Book a free 30 minute consultationAdjacent paths
Other ways to leave Brightpearl
Other ways to arrive at Odoo ERP
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.