Case study10 Sept 2026
Odoo ERP rollout for a multi-branch trading company in Saudi Arabia
How a distributor operating from several branches replaced spreadsheets and a standalone invoicing tool with one Odoo database covering sales, inventory, purchasing and ZATCA-compliant invoicing — in phases, without stopping trading.
- Client
- Multi-branch trading and distribution company, Saudi Arabia (anonymised)
- Industry
- Businesses
- Technology
- Odoo 17 EnterprisePostgreSQLZATCA e-invoicingREST integrations

Quick Answer
A Saudi trading company with several branches moved from branch-level spreadsheets and a separate invoicing tool to a single Odoo Enterprise database. RaysanDev ran the project in three phases — order-to-invoice first, then inventory and purchasing, then accounting and management reporting — with ZATCA e-invoicing scoped from day one and branch-level permissions so each location sees only its own operations.
Key Takeaways
- Phase one delivered a complete sales-order-to-compliant-invoice cycle before any other module was switched on.
- Branch operations run on one database with location-scoped permissions and consolidated reporting for head office.
- ZATCA Phase 2 e-invoicing, VAT and Arabic/English document layouts were configured and tested before cutover, not after.
- Data migration was the largest single effort; product and customer master data were cleaned before import.
- Customisation was limited to documented gaps; standard Odoo processes were run for a full cycle first.
- A parallel run and a named internal owner per module were the conditions for go-live.
The challenge
- Each branch tracked stock, sales and purchase orders in its own spreadsheets, so head office had no consolidated view without manual consolidation at month end.
- Stock levels were reconciled by hand, producing both over-ordering of slow lines and stockouts of fast-moving ones.
- Invoices were issued from a standalone tool disconnected from stock and orders, creating reconciliation work and ZATCA compliance risk.
- Pricing and discount rules differed by branch with no single source of truth for products or customers.
The solution
- One Odoo Enterprise database covering CRM, sales, inventory, purchasing, invoicing and accounting across all branches.
- Multi-warehouse configuration with branch-scoped permissions and consolidated dashboards for leadership.
- ZATCA Phase 2 e-invoicing, VAT treatment and bilingual invoice layouts configured and validated before go-live.
- Automated reordering rules per warehouse and inter-branch transfer workflows replacing informal WhatsApp requests.
Implementation
How the work was delivered
A phased approach so value arrives before the whole programme is complete.
- 01
Discovery and scope
Two weeks of process walkthroughs at each branch, a master-data audit, and agreement on a phase-one scope limited to the order-to-invoice cycle.
- 02
Configuration
Standard Odoo processes configured first — companies, warehouses, pricelists, taxes, document templates — with customisation restricted to documented gaps.
- 03
Data migration
Customers, suppliers, products, pricelists and opening stock and balances cleaned in staging, imported, and reconciled with the finance team.
- 04
Training, parallel run and go-live
Role-based training per branch, a parallel run against the old spreadsheets for one cycle, then branch-by-branch cutover with on-site support.
The starting point
The company distributes consumer and commercial products from a head office and several regional branches, each with its own warehouse and sales team. Growth had been steady, but the systems had not grown with it. Every branch kept its own sales log, its own stock count and its own list of pending purchase orders in spreadsheets. Invoices were raised in a separate invoicing application that knew nothing about stock or orders, so every invoice was typed a second time.
The symptoms were the usual ones. Month-end took more than a week because head office had to consolidate branch files by hand. The purchasing team ordered against stock figures that were already out of date. Customers with accounts at two branches were treated as two different customers. And the invoicing tool, while functional, had no clear path to the ZATCA Phase 2 integration requirements the company was about to face.
What the client actually asked for
The brief was not "implement an ERP". It was "we want one view of stock and sales across branches, and we want invoicing to be compliant without adding staff". Keeping that phrasing in front of the project team shaped every scoping decision.
Why Odoo, and why Enterprise
The company evaluated a locally developed accounting package, a mid-market ERP and Odoo. Odoo was selected because its sales, inventory, purchasing and accounting applications share one data model — a confirmed sales order reserves stock, triggers a replenishment suggestion and produces the invoice without re-entry — and because the multi-company and multi-warehouse model matched a branch structure without custom development. Our general guidance on this decision is in the Odoo ERP guide for Saudi businesses.
Enterprise edition was chosen over Community for three practical reasons: the depth of the accounting application, the supported upgrade path, and the Studio tooling that let us meet most of the branch-specific reporting requests through configuration rather than code. Hosting was placed on a partner-managed cloud with written responsibilities for backups, monitoring and recovery, and with the finance team's data-residency expectations recorded in the agreement.
How the rollout was phased
The most consequential decision was what to leave out of phase one. Odoo makes it trivial to enable a dozen applications on day one; the discipline is in refusing to. We agreed that phase one would deliver one complete, compliant order-to-invoice cycle and nothing else, because that was the cycle that touched customers and the tax authority.
| Phase | Scope | Exit condition |
|---|---|---|
| 1 — Order to invoice | Customers, products, pricelists, sales orders, deliveries, ZATCA-compliant invoices, VAT | Every branch issues all invoices from Odoo for one full month |
| 2 — Stock and purchasing | Multi-warehouse inventory, reordering rules, purchase orders, receipts, inter-branch transfers | Physical count matches system stock within agreed tolerance at each branch |
| 3 — Finance and reporting | General ledger, bank reconciliation, payables and receivables, branch P&L, management dashboards | Month-end close completed in Odoo without spreadsheet consolidation |
Sequencing stock after invoicing surprised some stakeholders, who expected inventory to come first. The reasoning was that invoicing carried a regulatory deadline and stock accuracy depended on master data that phase one would force the branches to clean anyway.
ZATCA e-invoicing and local requirements
ZATCA Phase 2 was treated as a scope item from the first workshop rather than a compliance afterthought. That meant confirming the company's integration wave, configuring the e-invoicing module, generating and validating the required XML and QR content in the sandbox, and confirming the certificate onboarding steps with the finance team before any live invoice was issued.
- VAT configuration covering standard-rated, zero-rated and exempt lines, with the correct treatment for inter-branch movements.
- Bilingual Arabic/English invoice, credit note and delivery-note layouts approved by finance before user training began.
- Sequence and numbering rules aligned with the company's existing audit expectations.
- A documented procedure for correcting an invoice through credit notes rather than editing issued documents.
Data migration: the real work
As is common, migration consumed more effort than configuration. The branches held overlapping product lists with different codes for the same item, duplicate customers, and pricelists that had drifted apart. We ran migration in a staging database in three iterations: the first exposed the duplicates, the second was cleaned by branch data owners using a shared workbook, and the third was the rehearsal for cutover. Opening stock was taken from a physical count scheduled for the cutover weekend rather than from historical spreadsheets.
Rule we enforced
Nothing was imported that did not have a named owner responsible for keeping it accurate afterwards. Where a branch could not name an owner for a data set, that data set stayed out of the system until phase two.
Where customisation was — and was not — allowed
Requests for custom development were logged but not built until the standard process had been run for a full cycle. Most requests disappeared once users had lived with the standard flow. What remained was genuinely specific: a branch-level commission calculation, an approval step for discounts above a threshold, and a consolidated stock-position report head office used every morning. These were delivered as small, documented modules with upgrade in mind — the approach we describe on the Odoo ERP service page.
Two integrations were built through Odoo's API: a link to the company's existing courier account so delivery labels were generated from the delivery order, and a scheduled export to the bank's payment file format. Both followed the same pattern we use in custom software and integration work — a documented contract, idempotent jobs and error queues visible to the operations team.
Training, parallel run and cutover
Training was delivered by role — sales, warehouse, purchasing, finance — at each branch, using the company's own products and customers rather than demo data. A one-cycle parallel run compared Odoo output with the legacy spreadsheets; discrepancies were treated as data-cleaning tasks, not as reasons to delay. Cutover was branch by branch over consecutive weekends, with a RaysanDev consultant on site for the first working days at each location.
Post-go-live support ran on a defined response-time schedule, and a monthly review with the internal owner covered open requests, data-quality checks and the roadmap for the following phase.
What we would repeat on the next project
- Write the client's own words for the goal on the first page of the scope, and test every request against them.
- Give each phase an exit condition the client can verify without us.
- Schedule the physical stock count as the source of opening balances.
- Refuse to import data without a named owner.
- Run the standard process for a full cycle before commissioning any customisation.
Results
Outcomes
We report only what the client has approved and what can be evidenced.
No results are published for this entry. Measured outcomes appear here once a client approves publication and the figures have been verified together.
FAQ
Questions about this project
Where we help
Services used in this engagement
The capabilities this type of project draws on.
Planning an Odoo rollout across branches?
Tell us how your branches work today and we will propose a phase-one scope, a migration plan and a realistic timeline.
