What an industry pack actually switches on
A pack is not a theme and it is not a module bundle. It is a set of rules that change how the core behaves — and a boundary that keeps them out of the core.
Most ERPs sold to a pharmacy and to a spare-parts shop are the same product with a different logo. The pharmacy gets fields it does not understand; the parts shop gets a batch-expiry screen it will never open.
We took a different route. The core is industry-neutral. A pack layers on top.
What a pack can do
- Add screens. The expiry dashboard belongs to Pharma. The vehicle master belongs to Spare-parts. Neither exists in the core.
- Add fields. MoH registration number, ATC code, dosage form — custom fields declared by the pack, stored against the product, and visible only when the pack is on.
- Change rules. FEFO allocation is a Pharma rule. Cold-chain enforcement on putaway and allocation is a Pharma rule. The core allocates without either.
What a pack cannot do
It cannot live in the core. Pack-specific logic in a core module is rejected at merge — that is an architectural rule, checked by tests, not a convention.
The reason is boring and important: the moment InventoryService contains an if (isPharmacy), every future pack becomes a branch inside the same function, and the fifth vertical is unshippable.
Switching
Packs have a status. Pharma is active. Spare-parts ships inactive — installed, switched off, one setting away. Supermarket and General-retail are still in build, and we say so on the site rather than letting a screenshot imply otherwise.
Changing pack later does not migrate your data. The ledger, the audit chain, the permission matrix, and the document counters are the same underneath all four.