Skip to main content

Data model

The proposed data model. This is a draft for discussion with the partner — field names and relations are refined during implementation in DirectusDirectusAn open-source headless platform on top of PostgreSQL: provides the data model, REST/GraphQL API, authentication, RBAC and a ready-made admin UI without writing code..

Key idea — brand_id everywhere

Almost every business table carries brand_id (directly or via a relation). TenantTenantA logically isolated customer in a multi-tenant system. In Ghost Kitchen a tenant is a brand: its data is separated from others by `brand_id` and access rules. isolation is built on it: access policies filter rows by the user's brand.

ER diagram (draft)

Notes on key entities

  • brand — the tenantTenantA logically isolated customer in a multi-tenant system. In Ghost Kitchen a tenant is a brand: its data is separated from others by `brand_id` and access rules.. domain, theme (colors/logo), settings (currency, language, checkout policy).
  • kitchen — a brand's location. Delivery zones and time slots live here (not in a paid plugin).
  • menu_item — a menu itemMenu itemAn individual dish or product in a brand's menu available for ordering. May have modifiers and an associated SKU. at the brand level; sku links to accounting. kitchen_menu_item — publishing an item at a specific kitchen with optional local price/availability (stop-list).
  • modifier_group / modifiermodifiersModifierAn option that alters a menu item: add-on, size, doneness, ingredient removal. May affect the price. (size, add-ons) with min/max selection rules.
  • order / order_item / order_item_modifier — the order as a snapshot: prices are frozen at order time (unit_price_cents) so later menu changes don't alter history.
  • payment — the payment in MollieMollieA European payment provider. Accepts payments (cards, iDEAL, Apple/Google Pay, etc.) and reports payment status via webhooks.; provider_payment_id for reconciliation and webhook idempotencyIdempotencyThe property of an operation yielding the same result when repeated. Protects against duplicate orders/payments when a webhook is redelivered or a request is retried..
  • customer — a single customer at the platform level (cross-brand analytics and loyalty).
  • user_role — the user × role × scope (brand/kitchen) link for RBACRBACRole-Based Access Control — access management based on roles. Permissions are granted to a role (Company Admin, Brand Admin, Restaurant Manager) rather than to each user individually..

Money and time

  • All amounts are in the minor currency unit (*_cents, integers) to avoid losing cents to floating point.
  • All timestamps are in UTC; the UI converts them to the kitchen's time zone.

:::warning Open questions

  • Is separate inventory/stock tracking needed, or is a kitchen stop-list enough?
  • Delivery addresses/zones — free text, a geocoder, or zone polygons?
  • Are promo codes/loyalty needed in the MVP or in phase 2? :::