Skip to content

Inventory Management

Overview

Inventory Management tracks stock levels for menu items. When inventory tracking is enabled, items automatically show as "Sold Out" when stock reaches zero.

Key Purpose: Track stock levels and prevent overselling.

Purpose

This page lets you track stock levels for menu items per location, set low-stock alerts, and control whether sold-out items remain orderable.

Key Concepts

  • Inventory Tracking: A per-item toggle (track_quantity) that enables stock management; when disabled, the item is treated as always available.
  • Inventory History: An auditable log of every stock change (restock, depletion, bought) stored via InventoryHistoryRepository, used to recalculate the remaining stock from the full history.
  • Stock Depletion Types: The system distinguishes between Restock (adds stock), Depletion (manual removal for damage/expiry), and Bought (automatic deduction when a customer order is placed).
  • Max Order Limit: A per-item cap on the quantity a customer can order in a single transaction, enforced at checkout time independently from stock levels.
  • D1 Stock Sync: After every stock change, the updated stock level is pushed to a Cloudflare D1 edge database so customer-facing menus reflect availability in real time.

Actions

Enable Inventory Tracking for an Item

Turn on the track_quantity flag for a specific menu item to start monitoring its stock level per location.

Restock or Adjust Stock

Add stock (restock) or set stock to a specific value (adjustment). Each change is recorded in the inventory history with the appropriate type and reason.

Delete Inventory Record

Remove inventory tracking for an item at a location. This deletes the D1 stock entry and triggers a menu reload so the item appears as always available again.

Review Inventory Overview

View a paginated overview of all tracked items and their current stock levels for a given location, including timezone-adjusted timestamps.

Location

  • Backoffice Route: /inventory
  • Backend Controller: app/Http/Controllers/Api/InventoryController.php
  • Vue Component: src/views/inventory/index.vue

Concepts

Stock Level

Current quantity of an item available.

Low Stock Alert

Warning when stock falls below threshold.

Stock Tracking

Per-item setting to enable/disable tracking.

Stock Reservation

Temporary hold on stock during checkout.


Fields

Track Inventory

PropertyValue
Field IDtrack_inventory
LabelTrack Inventory
TypeToggle
Defaultfalse
RequiredNo
ScopePer item

Description: Whether to track stock for this item.

Business Logic:

  • Enabled: Stock decremented on order, "Sold Out" when 0
  • Disabled: Item always available (unlimited)

Customer Impact:

  • Stock = 0: Item shows "Sold Out"
  • Stock > 0: Item available

Current Stock

PropertyValue
Field IDstock
LabelCurrent Stock
TypeNumber
RequiredYes (if tracking enabled)
Validationmin: 0

Description: Current quantity available.

Business Logic:

  • Decremented when order placed
  • Incremented when order cancelled/refunded
  • Can be manually adjusted

Low Stock Threshold

PropertyValue
Field IDlow_stock_threshold
LabelLow Stock Alert
TypeNumber
Default10
RequiredNo
Validationmin: 0

Description: Stock level that triggers low stock warning.

Business Logic:

  • When stock <= threshold → Alert shown in backoffice
  • Optional notification sent

Examples:

  • 10: Alert when 10 or fewer left
  • 5: Alert when 5 or fewer left
  • 0: Only alert when out of stock

Allow Backorders

PropertyValue
Field IDallow_backorders
LabelAllow Backorders
TypeToggle
Defaultfalse
RequiredNo

Description: Allow orders even when stock is 0.

Business Logic:

  • Enabled: Item available even at 0 stock
  • Disabled: Item unavailable at 0 stock

Use Cases:

  • Items that can be quickly restocked
  • Made-to-order items
  • Pre-orders

Stock Location

PropertyValue
Field IDstock_location_id
LabelStock Location
TypeSelect
RequiredNo
DefaultPer-location tracking

Description: Which location's stock to track.

Business Logic:

  • Stock can be tracked per-location
  • Or shared across locations (central inventory)

Stock Operations

Restock

PropertyValue
OperationAdd stock
Fieldquantity
TypeNumber
Validationmin: 1

Description: Add inventory when receiving new stock.

Example:

  • Current: 5
  • Restock: +20
  • New stock: 25

Adjust Stock

PropertyValue
OperationSet stock
Fieldquantity
TypeNumber
Validationmin: 0

Description: Set stock to specific value (inventory count).

Example:

  • Current: 15
  • Adjust to: 12 (3 items lost/damaged)
  • New stock: 12

Stock Reason

PropertyValue
Field IDreason
LabelReason
TypeSelect/Text
OptionsRestock, Damaged, Expired, Count Adjustment, Other

Description: Reason for stock change (for audit trail).


Business Logic

Order Stock Flow

Customer places order


For each item in order:
├── Track inventory enabled?
│   ├── No → Skip
│   └── Yes → Continue

├── Check current stock
│   ├── Stock >= Quantity → Reserve stock
│   └── Stock < Quantity → 
│       ├── Allow backorders? → Reserve (negative stock)
│       └── No backorders → Error: "Item sold out"

└── Order confirmed → Deduct stock

Stock Reservation

Customer adds to cart


Reserve stock (temporary hold)

        ├── Checkout completed → Confirm deduction

        ├── Cart abandoned → Release reservation

        └── Timeout (e.g., 15 min) → Release reservation

Low Stock Alert

Stock updated


Check if stock <= low_stock_threshold

        ├── Yes → Trigger alert
        │         - Show in backoffice
        │         - Send notification (if configured)

        └── No → No action

Sold Out Display

Customer views menu


For each item:
├── Track inventory = false → Show as available

└── Track inventory = true
    ├── Stock > 0 → Show as available
    └── Stock = 0
        ├── Allow backorders → Show as available
        └── No backorders → Show "Sold Out"

Customer Impact

Online Ordering

Stock StatusCustomer Sees
In stockNormal item display
Low stockNormal (no indication)
Out of stock"Sold Out" badge, cannot add
Backorders allowedNormal (may show "Pre-order")

Kiosk

  • Same behavior as Online Ordering
  • "Sold Out" items grayed out or hidden

Cart Behavior

  • If item goes out of stock while in cart → Warning shown
  • Customer must remove item to proceed
  • Or item auto-removed with notification

Relations

Depends On

  • Menu Items: Stock tracked per item
  • Locations: Stock can be per-location

Affects

  • Online Ordering: Item availability
  • Kiosk: Item availability
  • Transactions: Stock deducted
  • Reports: Inventory reports

Business Rules

  • Remaining stock is recalculated by replaying the full inventory history (all restock, depletion, and bought entries); if the calculated value goes below zero, the system aborts with a "Not enough remaining stock" error.
  • When a customer places an order, the system checks track_quantity for each item; if stock is insufficient and backorders are not allowed, a 400 error is returned before the order is created.
  • Stock adjustments that result in zero change (quantity delta of 0) are silently skipped and no history entry is created.
  • Deleting an inventory record also removes the corresponding D1 edge database entry and fires a ReloadMenu event so all ordering channels reflect the change immediately.
  • Inventory expiry dates are calculated relative to the location's timezone and are set to end-of-day for future dates or start-of-day for same-day expiry.

FAQs

  • Does stock update automatically when a customer places an order? Yes, the manageLocationStocks method automatically creates a "Bought" history entry and decrements stock for each tracked item in the order.
  • Can I track stock differently per location? Yes, inventory records are scoped per item and per location, so each location maintains independent stock levels.
  • What happens if two customers order the last item at the same time? The system checks stock at order creation time; the first order to be processed will succeed, and the second will receive a "Not enough remaining stock" error.
  • Is there an undo for stock adjustments? There is no direct undo, but you can create a new restock or depletion entry to correct the stock level. All changes are recorded in the history for auditability.
  • How quickly do stock changes appear on the customer menu? Stock changes are pushed to the Cloudflare D1 edge database immediately after the update, and a ReloadMenu event is fired, so changes typically appear within seconds.

Troubleshooting

Problem: Item showing "Sold Out" but has stock

Causes:

  1. Stock not updated after restock
  2. Wrong location's stock
  3. Cache not refreshed

Solutions:

  1. Update stock in inventory
  2. Check correct location
  3. Refresh/clear cache

Problem: Item sold when out of stock

Causes:

  1. Inventory tracking not enabled
  2. Allow backorders enabled
  3. Race condition (simultaneous orders)

Solutions:

  1. Enable inventory tracking
  2. Disable backorders if not wanted
  3. Stock reservation should prevent this

Problem: Stock count incorrect

Causes:

  1. Manual adjustments not recorded
  2. Cancelled orders not restocking
  3. Sync issues

Solutions:

  1. Do physical count and adjust
  2. Check cancelled order handling
  3. Review stock history

Problem: Low stock alerts not working

Causes:

  1. Threshold set to 0
  2. Notifications disabled
  3. Item not tracked

Solutions:

  1. Set appropriate threshold
  2. Enable notifications
  3. Enable inventory tracking

Examples

Simple Stock Tracking

json
{
  "item": {
    "name": "Special Burger",
    "track_inventory": true,
    "stock": 50,
    "low_stock_threshold": 10,
    "allow_backorders": false
  }
}

Behavior:

  • 50 available
  • Alert at 10 remaining
  • "Sold Out" at 0

High-Demand Limited Item

json
{
  "item": {
    "name": "Chef's Special (Limited)",
    "track_inventory": true,
    "stock": 20,
    "low_stock_threshold": 5,
    "allow_backorders": false
  }
}

Behavior:

  • Only 20 available per day
  • Alert at 5 remaining
  • Creates urgency for customers

Pre-Order Item

json
{
  "item": {
    "name": "Holiday Special Box",
    "track_inventory": true,
    "stock": 0,
    "low_stock_threshold": 0,
    "allow_backorders": true
  }
}

Behavior:

  • Available for pre-order
  • Stock goes negative (tracks demand)
  • Fulfill when stock arrives

No Tracking (Always Available)

json
{
  "item": {
    "name": "French Fries",
    "track_inventory": false
  }
}

Behavior:

  • Always available
  • No stock management needed
  • Good for items that never run out

Multi-Location Stock

json
{
  "item": {
    "name": "Signature Dish",
    "track_inventory": true,
    "stock_by_location": {
      "location-amsterdam": 30,
      "location-rotterdam": 25,
      "location-utrecht": 20
    },
    "low_stock_threshold": 5
  }
}

Behavior:

  • Different stock per location
  • Each location manages own inventory
  • Alerts per location

Stock History

Track all stock changes for audit:

json
{
  "stock_history": [
    {
      "date": "2024-01-15 09:00",
      "type": "restock",
      "quantity": +50,
      "reason": "Weekly delivery",
      "user": "Manager"
    },
    {
      "date": "2024-01-15 12:30",
      "type": "order",
      "quantity": -2,
      "reason": "Order #1234",
      "user": "System"
    },
    {
      "date": "2024-01-15 14:00",
      "type": "adjustment",
      "quantity": -3,
      "reason": "Damaged items",
      "user": "Staff"
    }
  ]
}