The problem
An industrial bakery does not manufacture like a factory. Four kitchens — bread, ice cream, pastry, viennoiserie — produce through the night for five stores that open in the morning. There is no manufacturing order to launch and close: there is a quantity to produce, materials to draw, and a van to load.
No standard configuration could drive that. Physical counting of raw materials happened outside the system. Deliveries to the stores had no tracking document. Neither did returns of unsold goods.
At the till, nothing governed cash withdrawals, discounts or the deletion of an order. And losses — a broken cake, an expired product — left stock with no way of telling breakage from date.
The approach
The most structural decision was not to use the manufacturing module. None of the sixty-two modules depends on MRP, and that is deliberate. An Odoo bill of materials assumes routings, work centres and work orders you open and close. The reality of a night kitchen is simpler and faster than that: you know the recipe, you draw the materials, you transfer the output to the store.
What was built reproduces exactly that gesture. An in-house bill of materials ties a product to its ingredients, importable from Excel — because that is where recipes actually live. A counting and production model replaces the native inventory adjustment. And output enters stock as a transfer from kitchen to store, with its printed, QR-coded sheet to follow on the ground.
Everywhere else the opposite principle applies: inherit, never overwrite. Transfers, till orders, scrap, companies — all extended by inheritance. And where Odoo offers a clean extension point, that is what gets used rather than a broad override.
Splitting the work across many small modules is a choice too: each need installs, uninstalls and migrates on its own, without tying up the rest of the estate.
The solution
Sixty-two custom modules on Odoo 17.
Production rests on the in-house bill of materials, the rewritten counting model with its state machine and lot handling, and the per-kitchen production sheets. A planning module generates recurring kitchen → store deliveries by day of the week.
Losses are classified at source: breakage or expiry date. Each is valued automatically at product cost, and multi-line entry avoids creating one movement per item.
At the till, an in-house network bridge drives the receipt printer and the cash drawer. The kitchen preparation display received a fix where the standard blocked progression from one stage to the next. A special order taken at the counter — a bespoke cake — automatically triggers a dated transfer from the central warehouse. And discounts, refunds, order deletions and cash movements all run through a single rights panel.
Distribution covers allocation of orders from the warehouse to the stores, automatic receipt of unsold returns into the originating company, and the matching credit notes. Alongside it sit an online quote request form with its delivery zones, loyalty code generation, and generation of missing barcodes.
The result
The night's production enters stock with its sheet and its QR code instead of a phone call. Deliveries to the five stores follow a schedule rather than a habit. Unsold goods come back with their credit note. A loss is qualified and costed the moment it is recorded. And the till no longer lets a discount through without a manager.
Stack
- Odoo
- Odoo 17
- Modules
- InventoryPoint of SaleSalesPurchaseAccountingWebsiteHR
- Tech
- PythonOWLJavaScriptQR
- Protocoles
- TCP