Core & Plugins

Shop

Products, categories, stock, orders and pluggable shipping — a full commerce engine other verticals build on.

The shop storefront — product catalogue.
The shop storefront — product catalogue.

Commerce engine

The shop owns products, categories, warehouses/stock and orders. It integrates with core through the line-item registry (its order lines become invoice lines) and the event bus (stock blocking, order state). Pricing flows through the shared PriceFactory, so per-rate tax and discounts reconcile on the invoice.

Shipping providers

Shipping is a capability: implement a provider, register it, and it appears at checkout. A flat-rate provider ships as an example. This is the same open/closed pattern used for payments — add a provider without touching the shop core.

Product types

A product type is a named, additive cluster of custom fields layered on the universal base product. It carries no behaviour — fields only. A product references at most one type via product_type_slug (NULL = the plain default product) and stores its answers in type_field_values. Types live in the shop_product_type table; the shop self-registers a digital type as the reference example.

There are two ways to define one, no config file involved:

  • In the admin — a full CRUD API (/api/v1/admin/shop/product-types) and the fe-admin Product Types view. These are source="admin": fully editable and deletable. Post {name, slug, description?, product_type_fields[]}; each field is {slug, type, label, required, options, sort_order} over string / url / integer / number / boolean / select / multiselect.
  • From plugin code — a plugin's on_enable calls register_product_type(descriptor); shop's enable reconcile_product_types() upserts it idempotently as source="plugin" (read-only in the UI; the owning plugin owns the cluster). Adding a type never edits shop.

On save, values are validated against the type's schema — required fields present, value types matched, select values drawn from their options. Product types are additive metadata; they are not product variants (priced/stocked SKUs) and not the pharma product-class gate.

Verticals on top

The shop is itself a substrate: the merchant / software store and the pharma module are full verticals layered on the shop engine, reusing its catalogue, cart, checkout, stock and orders.