The problem
A palm oil mill takes in its raw material by small truckloads, all day long, often from growers with no commercial structure at all. An ERP's standard circuit — purchase order, then receipt, then invoice — assumes you know the supplier and the quantity before they turn up. Here it works the other way round: the truck arrives, it is weighed, and the weighing is what creates the transaction.
The weighbridge was already there, with its own software and its own database. Nobody was going to replace it — but nothing flowed from it into the ERP. Every weighing was retyped.
Further into the mill, production was tracked on a paper shift log: sterilisation, extraction, clarification, boiler, laboratory, maintenance, purge, silo storage. Every station, every day and night crew, filled in its sheet. Those sheets were consolidated nowhere. Nobody could say, in the morning, what extraction rate the night had achieved — even though that is the single figure that governs the profitability of the whole business.
The approach
Two decisions shape the project.
First: read the weighing software where it already writes. Rather than replacing a tool that works, or asking its vendor for a gateway, an agent installed on the weighing workstation reads the software's database directly and pushes weighings into Odoo. The ERP never touches the proprietary database, and the weighing station carries on exactly as before.
Second: refuse MRP. A standard manufacturing module would have imposed bills of materials and work orders on a continuous process that has neither — you do not manufacture a batch of oil, you keep a line running. The option was opened, then dropped. Production tracking reproduces what the mill was already doing: the shift log, station by station, shift by shift — but digital, and consolidated automatically.
The rest is targeted overrides of standard models, one per need, with no catch-all module.
The solution
Twelve custom modules on Odoo 19.
Weighing becomes the single point of entry: a weighing ticket directly spawns either a receipt with its stock move and its vendor bill, or a sale — without the three successive validations the standard demands. The many small growers go through generic partners rather than cluttering the contact file.
The shift log covers the mill's eight stations. The sheets share one state and workflow mechanism instead of being rebuilt one by one. A SQL view aggregates both shifts' sheets each day, per company, and derives the figures that matter: tonnage of nuts processed, kernel produced, and the oil extraction rate. No threshold is hard-coded — target yield, floor yield and tolerated downtime are parameters. A deviation raises an alert that lands in the discussion feed of the people concerned.
Business intelligence runs on an in-house engine rather than an external tool. Indicators are SQL queries, but executed under strict constraint: read-only transaction, bounded execution time, query validation against an allow-list, per-user data partitioning. All of it is covered by dedicated tests. On top of that engine, a "Palm Oil Control" dashboard crosses five filters with a dozen indicators: nut intake, top suppliers, nut-to-oil conversion, monthly yield, silo stock, revenue per product, alerts per workshop.
Accounting reports to SYSCOHADA standards, with aggregated invoicing and payment receipts matched to local practice.
The result
Weighings come in on their own, and cannot come in twice: every row read is fingerprinted, and only rewritten when it has genuinely changed. A truck becomes a receipt, a stock move and an invoice in one operation instead of three. The shift log is entered once and consolidates itself: yesterday's extraction rate exists in the morning, without anyone having worked it out. And deviations flag themselves instead of being discovered at month end.
The project followed the upgrade from Odoo 18 to Odoo 19, with versioned migration scripts along the way — the system is maintained, not delivered and abandoned.
Stack
- Odoo
- Odoo 19
- Modules
- PurchaseInventorySalesAccountingHRSYSCOHADA
- Tech
- PythonPostgreSQLPySide6OWLECharts
- Protocoles
- XML-RPCODBC