Restaurant and canteen kitchens lose significant time to manual inventory tracking — staff physically count stock, manually calculate ingredient requirements for each dish (BOM), and re-enter data across spreadsheets. This system eliminates that entirely.
The Food Management System provides a unified web interface where kitchen staff log usage, the backend automatically deducts from inventory, generates Bill of Materials for any menu combination, and fires low-stock alerts — all in real time. What took 3 hours of spreadsheet work now happens automatically on each order entry.
Tech Stack
How the System is Built
Each menu item maps to a recipe with ingredient quantities. On order entry: BOM Engine multiplies quantities × servings, checks inventory, deducts atomically, flags shortfalls before the order is confirmed.
Given current inventory levels, the system calculates which menu items can actually be prepared (and how many servings). Eliminates "we ran out of X" surprises mid-service.
How It Works — Step by Step
Inventory Registration
Kitchen manager registers each ingredient with unit type, current stock, and reorder threshold. Items are categorised (Dairy, Produce, Dry Goods, etc.) for organised reporting.
POST /inventory/add · { item, qty, unit, threshold, category }
Recipe / BOM Definition
Each menu item has a recipe attached — a structured list of ingredients and quantities per serving. The BOM Engine stores these as recipe-to-ingredient mappings in the database.
Butter Chicken → { chicken: 250g, cream: 50ml, spices: 15g, ... }
Order Entry & BOM Calculation
Staff enter an order (e.g., "20 × Butter Chicken"). The BOM Engine instantly calculates total ingredient requirements, checks current inventory atomically, and either confirms or raises a shortfall alert.
20 × recipe_bom → deduct inventory → shortfall check → confirm
Auto Menu Generation
The system scans current inventory against all recipe BOMs and outputs a "possible menu" — items that can be prepared today, with maximum servings per item. Reorders are auto-flagged to the purchase list.
GET /menu/possible → [{ item, max_servings, status }]
Reports & Low-Stock Alerts
End-of-day reports show consumption per item, remaining stock, and items that crossed reorder thresholds. Alerts are displayed in the dashboard and can trigger notifications to the purchase team.
Daily report · reorder list · waste tracking · cost summary
Challenges & Solutions
Inventory race conditions on concurrent orders
When two staff members enter orders simultaneously, both reads could show sufficient stock — then both deductions leave inventory negative.
Atomic transactions with SQLAlchemy locking
Wrapped inventory deductions in atomic DB transactions with row-level locking. The second concurrent order is queued until the first commits, then re-evaluated against updated stock. Zero oversell errors in testing.
Complex BOM for composite recipes
Some dishes use sub-recipes (e.g., "Gravy Base" is itself a recipe used in 12 dishes). A flat ingredient lookup fails to resolve these nested dependencies.
Recursive BOM resolver
Built a recursive tree-resolver that expands sub-recipes into leaf ingredients before calculating totals. Handles arbitrary nesting depth and correctly aggregates repeated ingredients from multiple branches.
Manual reorder process wasted staff time
Kitchen managers had to manually scan through 200+ ingredient rows to find what needed reordering — a 45-minute daily task.
Threshold-triggered purchase list
Every inventory write triggers a threshold check. Items below reorder point are auto-added to a live "Purchase Required" list, updated in real time. The 45-minute task now takes zero effort — the list is always current.