Discover powerful Dolibarr extensions designed to automate your business processes

DoliBiscuit turns Dolibarr into a vertical ERP/MES for industrial biscuit manufacturing. It covers the whole value chain, from raw-material purchasing through production, quality, laboratory, traceability, maintenance, energy and analytics, up to the delivery of the finished product. It is designed to replace a dedicated MES/GPAO package while remaining fully integrated with the native Dolibarr modules, with no data duplication and no external software.
· Referentials: suppliers, raw materials, allergens, packaging, production lines, machines and ovens, teams.
· Engineering: versioned recipes and formulations, bills of materials (BOM), operation routes.
· Manufacturing (MES): planning, scheduling, manufacturing orders, real-time shop-floor tracking, declarations, scrap, yield and OEE.
· Process steps: mixing, dosing, kneading, laminating, cutting, baking, cooling, packing, palletizing.
· Quality: control plan across reception, manufacturing, baking, packaging, storage and shipping; non-conformities, CAPA, audits and inspections.
· Laboratory: a full LIMS covering physico-chemical, physical, organoleptic, microbiological and chemical analyses.
· Traceability: upstream, internal and downstream, with a one-click product-recall scope.
· Food safety: HACCP (CCP, PRP, PRPo) and ISO 22000 documentation with indicators.
· Maintenance (CMMS): preventive, corrective, curative and condition-based, with MTBF and MTTR.
· HSE and energy: incident register, five utilities (electricity, gas, water, steam, compressed air) and CO2 footprint.
· Artificial intelligence: forecasting, anomaly detection and optimisation, on a local explainable engine.
· Business Intelligence: configurable pivot table with drill-down, plus a 15-report suite exportable to CSV, Excel, Word and PDF.
|
Item |
Value |
|
Dolibarr |
16.0 and above (developed and verified on 17.0.3) |
|
PHP |
7.1 minimum, fully PHP 8.x compatible |
|
Database |
MariaDB / MySQL (InnoDB) |
|
Module number |
523100 |
|
Technical name |
dolibiscuit |
|
Rights class |
dolibiscuit |
|
Table prefix |
llx_dbi_* |
|
Language prefix |
Dbi |
|
Dependencies |
modSociete, modProduct |
|
Languages |
fr_FR, en_US, es_ES, it_IT, de_DE |
|
Licence |
GPL v3 or later |
The module follows the official Dolibarr architecture. Every persistent object extends CommonObject and is described by a $fields array, which gives the generic list and card engine its columns, filters and renderers for free. Objects, SQL schema and page stubs are emitted from a single field specification, so the schema, the ORM classes and the UI can never drift apart.
|
Path |
Contents |
|
core/modules/modDoliBiscuit.class.php |
Module descriptor: rights, menus, init/remove, schema self-heal. |
|
class/*.class.php |
One CommonObject subclass per business object (29 objects). |
|
class/dolibiscuitsampledata.class.php |
Demonstration dataset generator and purger. |
|
sql/llx_dbi_*.sql |
Table definitions; *.key.sql holds the indexes. |
|
lib/dolibiscuit.lib.php |
Shared helpers, right mapping, business vocabularies, schema self-heal. |
|
lib/dolibiscuit_objects.php |
Generated object registry consumed by the generic engine. |
|
lib/dolibiscuit_menu.php |
Left-menu synchronisation and the in-page tab bar. |
|
lib/dolibiscuit_page.php |
main.inc.php bootstrap for standalone pages (top-level include). |
|
lib/dolibiscuit_ai.php |
Local AI engine: OLS forecasting, z-score anomalies, optimisation rules. |
|
lib/dolibiscuit_report.php |
Report definitions and the CSV/Excel/Word/PDF exporters. |
|
objectlist.inc.php / objectcard.inc.php |
Generic list and card engine shared by all 29 objects. |
|
dashboard.php, ia.php, bi.php, traceability.php, notifications.php, reporting.php |
Bespoke pages. |
|
admin/setup.php |
Configuration, feature toggles, business parameters, demo data actions. |
|
css/dolibiscuit.css.php |
Biscuit charter: palette, KPI cards, gauges, heatmap, pills, timeline. |
|
langs/<lang>/dolibiscuit.lang |
Translations; every key is Dbi-prefixed. |
· gen.py holds the single source of truth: one F(name, type, label) entry per field, grouped by OBJ(...).
· It emits the SQL schema, the index files, the CommonObject classes, the list/card stubs and the registry.
· gen_lang.py emits the five language files from one keyed dictionary of 5-tuples.
· accents.py restores diacritics PER LANGUAGE at generation time (see section 6.3).
· make_icons.py generates the module and object pictograms.
· To add a field: declare it in gen.py, re-run it, and the schema self-heal ALTERs the live table on the next activation. Dolibarr's _load_tables() only ever runs CREATE TABLE and never adds a column to an existing table, so dbiEnsureSchema() parses the SQL files and issues the missing ADD COLUMN statements.
29 business objects. Every table carries the standard Dolibarr columns: rowid, entity, status, date_creation, tms, fk_user_creat, fk_user_modif and import_key. The entity column makes every object MultiCompany-aware through getEntity().
|
Table |
Class |
Fields |
Kind |
|
llx_dbi_supplier |
Dbisupplier |
12 |
hub |
|
llx_dbi_material |
Dbimaterial |
14 |
hub |
|
llx_dbi_allergen |
Dbiallergen |
7 |
standard |
|
llx_dbi_packaging |
Dbipackaging |
10 |
standard |
|
llx_dbi_reception |
Dbireception |
15 |
hub |
|
llx_dbi_recipe |
Dbirecipe |
21 |
hub |
|
llx_dbi_recipe_line |
Dbirecipeline |
11 |
lines of dbirecipe |
|
llx_dbi_bom |
Dbibom |
11 |
hub |
|
llx_dbi_bom_line |
Dbibomline |
10 |
lines of dbibom |
|
llx_dbi_route |
Dbiroute |
12 |
standard |
|
llx_dbi_line |
Dbiline |
9 |
hub |
|
llx_dbi_machine |
Dbimachine |
16 |
hub |
|
llx_dbi_team |
Dbiteam |
9 |
standard |
|
llx_dbi_order |
Dbiorder |
24 |
hub |
|
llx_dbi_op_line |
Dbiopline |
13 |
lines of dbiorder |
|
llx_dbi_baking |
Dbibaking |
17 |
standard |
|
llx_dbi_packing |
Dbipacking |
15 |
standard |
|
llx_dbi_lot |
Dbilot |
14 |
hub |
|
llx_dbi_control |
Dbicontrol |
15 |
hub |
|
llx_dbi_nc |
Dbinc |
14 |
hub |
|
llx_dbi_capa |
Dbicapa |
12 |
standard |
|
llx_dbi_audit |
Dbiaudit |
14 |
standard |
|
llx_dbi_lab |
Dbilab |
18 |
hub |
|
llx_dbi_haccp |
Dbihaccp |
17 |
hub |
|
llx_dbi_isodoc |
Dbiisodoc |
15 |
standard |
|
llx_dbi_maint |
Dbimaint |
18 |
hub |
|
llx_dbi_hse |
Dbihse |
12 |
standard |
|
llx_dbi_energy |
Dbienergy |
14 |
hub |
|
llx_dbi_forecast |
Dbiforecast |
16 |
hub |
reception -> material -> recipe + formulation -> BOM -> route -> manufacturing order -> operations (mixing, dosing, kneading, laminating, cutting) -> baking -> cooling -> packing -> palletizing -> lot -> controls, laboratory -> traceability -> shipping.
Rights use the standard 6-column definition [id, label, type, bydefault, perms, subperms]. Read and write are granted by default so the module is usable immediately after activation; delete and admin are not. Every object is gated through dbiCan(), which maps the object key to its functional group.
|
Right group |
Actions |
|
referential |
read / write / delete |
|
recipe |
read / write / delete |
|
production |
read / write / delete |
|
quality |
read / write / delete |
|
lab |
read / write / delete |
|
traceability |
read / write / delete |
|
haccp |
read / write / delete |
|
maintenance |
read / write / delete |
|
hse |
read / write / delete |
|
ai |
read / write / delete |
|
reporting |
read only |
|
admin |
administer the module |
Total: 32 rights, allocated from base 523100. The band is verified free against llx_rights_def AND every build tree immediately before activation: a primary-key collision inserts only part of the rights silently while menus, tables and data still land, so init() returning 1 is not proof. The build asserts COUNT(llx_rights_def WHERE module='dolibiscuit') == 32 after activation.
The module never duplicates data that Dolibarr already owns.
|
Native module |
How DoliBiscuit uses it |
|
Third parties (Societe) |
Suppliers and customers are real Tiers; dbi_supplier and dbi_lot hold only the fk_soc link. |
|
Products |
Raw materials and finished goods are native Products; stock and pricing stay in Dolibarr. |
|
Stock / Warehouses |
Material stock is carried by the native product stock; the module adds alert thresholds. |
|
Lots / Serial numbers |
Lot numbers are produced per manufacturing order and carried through packing. |
|
Barcode |
Packing rows carry an EAN-compatible barcode. |
|
Users |
Controllers, analysts, technicians and team leaders are native Users (fk:User fields). |
|
Projects / Agenda |
Available for linking through the standard object links. |
|
ECM / GED |
Documents (certificates, technical sheets, analyses) attach through the native GED. |
|
MultiCompany |
Every table has an entity column; all queries filter through getEntity(). |
|
MultiLanguage |
All strings resolve through Translate::trans() against the five shipped lang files. |
|
Sales / Purchasing / Invoicing |
Customer orders and supplier receptions remain native; the module links to them. |
· CSRF: main.inc.php validates the posted token automatically; every form emits newToken(). Note that verifCsrfToken() does not exist in Dolibarr 17 and calling it is a fatal error.
· SQL injection: every value is passed through $db->escape() or cast to int/float. Identifiers that come from the request (BI pivot axes and measures, report codes) are resolved through a WHITELIST and never interpolated raw, because an identifier cannot be bound as a parameter.
· Permissions: every page starts with an accessforbidden() gate driven by dbiCan() / hasRight().
· Output: all rendered values pass through dol_escape_htmltag().
· Logging: dol_syslog() is used on activation and seeding paths.
· Deliberately statistical and explainable rather than a black box; no external service or API key.
· Forecasting: ordinary least squares linear trend; confidence is the coefficient of determination (R2) of the fit; every forecast ships an explanation string and a recommendation.
· Anomaly detection: z-score against each series' own mean and standard deviation, reporting |z| >= 2. Applied to OEE per order, baking temperature deviation and energy ratio per ton.
· Failure risk: derived from the elapsed share of the MTBF window since the last maintenance, the availability shortfall and the corrective-intervention history.
· Optimisation: rules over measured plant data (worst yields, lines below their OEE target, costliest utilities).
· EVERY visible language key carries the Dbi prefix. Dolibarr merges all active modules into a single tab_translate and the last file loaded wins, so even a generic key such as Ref, Qty or Machine would silently render another module's wording. Prefixing removes the collision surface instead of fighting it after the fact. Verified against the installed instance: 0 collisions out of 498 keys against 27390 keys from other custom modules and 12566 core keys.
· No literal percent sign is ever stored in a language value: Translate::trans() runs the result through sprintf() and PHP 8 raises a ValueError on an invalid specifier. Values read '(percent)' and the sign is concatenated in PHP. Only valid specifiers (%s) are allowed, and a generation-time assertion enforces it.
· Language files are authored in ASCII and diacritics are restored per language at generation time. A language-blind map is unsafe: 'Reference' is French ASCII and correct English, 'Allergene' is French ASCII and correct German, so a global replace corrupts the other columns.
· CSV, Excel (.xls), Word (.doc) and PDF (TCPDF) for all 15 reports.
· Translate::trans() returns HTML entities, so every cell of a non-HTML export is passed through html_entity_decode(); decoding only the headers leaks entities into the data rows.
· dol_escape_htmltag() RE-ENCODES accents (it decodes then calls htmlentities), so HTML-format exports use htmlspecialchars(..., ENT_QUOTES, 'UTF-8') instead, which escapes only & < > " ' and leaves real UTF-8 accents untouched. Verified: 0 HTML entities in all four formats.
· CSV carries a UTF-8 BOM so Excel opens it with the correct encoding.
· A versioned dataset (DATASET_VERSION) rather than a boolean guard, so an improved dataset re-seeds on upgrade instead of being skipped forever.
· Tagged with import_key = 'DBIDEMO' (the column is varchar(14)).
· Removal deletes only tagged rows and cascades to user-created children of demo parents, which carry no import_key of their own and would otherwise be stranded on a dead foreign key. Verified: a real untagged record survives both purge and re-install.
· Societe rows are created with code_client/code_fournisseur = -1: forcing a code makes create() return <= 0 silently. Product::create() does not persist import_key, so it is tagged with a follow-up UPDATE.
· Data realism is treated as a defect class. Measured values are drawn INSIDE their own tolerance band with an explicit small reject rate, and the first orders are forced to start today, so the headline KPIs are credible: yield 97 percent, conformity 98 percent, OEE 73 percent, availability 91 percent, and 'production today' is never zero.
· Unzip dolibiscuit-1.0.zip into the Dolibarr custom/ directory (the result is custom/dolibiscuit/).
· Open Home > Setup > Modules, find 'DoliBiscuit - ERP Biscuiterie' in the Products family and enable it.
· Activation creates the 29 tables, the menus and the 32 rights, self-heals the schema and seeds the demonstration dataset.
· Grant the right groups to the relevant user groups from the standard Dolibarr permission screen.
|
Constant |
Default |
Purpose |
|
DOLIBISCUIT_OEE_TARGET |
75 |
OEE target used by the gauges and the AI planning optimisation. |
|
DOLIBISCUIT_YIELD_TARGET |
95 |
Yield target used by the gauges. |
|
DOLIBISCUIT_SCRAP_MAX |
3 |
Maximum tolerated scrap rate. |
|
DOLIBISCUIT_DLC_ALERT_DAYS |
30 |
Use-by alert window, in days. |
|
DOLIBISCUIT_CO2_ELECTRICITY |
0.057 |
CO2 factor for electricity, kg per kWh. |
|
DOLIBISCUIT_CO2_GAS |
2.04 |
CO2 factor for gas, kg per m3. |
|
DOLIBISCUIT_FEATURE_<AREA> |
1 |
Feature toggle per functional area (QUALITY, HACCP, MAINT, ENERGY, AI, BI). |
|
DOLIBISCUIT_SAMPLE_DATA_DONE |
- |
Demonstration dataset version guard. |
The module was installed and exercised on a live Dolibarr 17.0.3 instance carrying about 110 other custom modules, which is the realistic worst case for menu, right and language collisions.
|
Check |
Result |
|
init() return value |
1 |
|
Rights inserted (llx_rights_def) |
32 of 32 declared |
|
Right band exclusivity |
Band owned only by dolibiscuit |
|
Menus created |
1 top + 36 left |
|
Tables created |
29 of 29 |
|
Language key collisions vs other custom modules |
0 of 498 |
|
Language key collisions vs Dolibarr core |
0 of 498 |
|
FontAwesome icons missing from the bundled FA5 |
0 (all names FA5-safe) |
|
Pages returning HTTP 200 with no fatal |
44 of 44 |
|
Pages with an empty <title> (hidden fatal) |
0 |
|
Data-bearing sections rendering rows |
All (no swallowed DB_ERROR) |
|
Raw language keys leaking to the UI |
0 |
|
HTML entities in CSV / Excel / Word exports |
0 |
|
PDF export |
Valid (%PDF- magic) |
|
Double-encoded UTF-8 in the database (HEX C383) |
0 |
|
Demo purge preserving real user data |
Verified with a planted untagged record |
|
Demo re-install after purge |
Verified |
Developed by: DoliResources | Copyright (C) 2026 DoliResources | www.doliresources.com