Canteen & meals.
A school canteen is a small business inside a bigger one: a catalogue, a kitchen, a till, a stockroom, and a duty of care that no other shop carries — the food cannot harm the child eating it. YESS runs all five at once. Menus with allergen tags, recipes costed from live inventory, meal-plan subscriptions, prepaid student wallets, a walk-up cashier, and a dietary cross-check that runs at the database the instant an order is placed. This handbook follows a plate from the menu board to the ledger.
- 14canteen routes
- 15data tables
- 6-stateorder lifecycle
- ≈18 minto read
Prologue
A note on the kitchen and the ledger#
Most school systems treat the canteen as an afterthought — a free-text note on a fees line, a cash box no one reconciles. YESS treats it as what it is: a daily-operations business that touches food safety, inventory, cash handling, and the general ledger every single day. The canteen module lives inside Cluster C7 (Daily Operations) and carries the gold commerce pillar, because at the end of the day it has to balance like the bursary does.
The module is layered. A small day school can run on a menu, a till, and a transactions log. A boarding school can turn on meal-plan subscriptions, prepaid wallets, recipe costing against stock, and per-shift operator reconciliation. The chapters below move from the simplest layer to the most complete; stop wherever your school sits.
The plate is checked before it is served, and counted after it is sold.
Chapter one
A lunch service#
It is 11:50 at Greenwood. Follow one lunch service end to end and the rest of this book is just detail.
11:50. The canteen manager opens the hub at /dashboard/canteen. The gold KPI rail reads the morning back to her: today's revenue, orders today, active subscribers, low-stock items, and the month's profit margin. The Active orders feed shows four tickets still preparing.
11:58. A boarder walks up to the counter. The cashier opens /dashboard/canteen/daily-payment, picks the student, adds a jollof rice and a drink to the cart, and chooses wallet. The order is created paid and delivered in one shot. Behind the scenes a database trigger atomically debits the student's prepaid wallet — and, because the dish carries a peanut allergen tag and the student's health profile lists a peanut allergy, a second trigger stamps a dietary flag on the order and fires a notification to the student's parents. The cashier sees the flag and swaps the dish.
12:30. Lunch rush over. The kitchen produced a batch of stew from a costed recipe at /dashboard/canteen/recipes: fifty servings, which drew the exact ingredient quantities out of stock and posted the cost of goods to the ledger automatically.
15:00. The operator files the shift report at /dashboard/canteen/reports — total sales, cash and mobile-money received, meal-plan servings, any cash discrepancy — and submits it for the manager's approval. The day's canteen revenue is already on the school's P&L.
Chapter three
Recipes costed from stock#
A menu item is what you sell; a recipe is what it costs to make. Recipes live at /dashboard/canteen/recipes. Each recipe carries a default meal type, a serving count, allergen and dietary-tag arrays, and a list of ingredients. Every ingredient is drawn from the school's inventory items, with a quantity per serving — and YESS recomputes the recipe's cost per serving automatically every time the ingredient list changes, through a database trigger.
The killer feature is Produce now. Enter how many servings you are making and YESS runs a pre-flight check against live stock: if any ingredient is short, it refuses and lists exactly what is missing. If stock is sufficient, it decrements each ingredient and posts the cost of goods to the ledger — debit COGS, credit canteen inventory — in one atomic operation.
Chapter four
Meal plans and subscriptions#
A meal plan is a bundle a family or staff member subscribes to. Plans live at /dashboard/canteen/meal-plans, each with a plan type — boarder_full, boarder_half, staff_monthly, student_weekly, student_daily, or custom — a billing frequency (daily, weekly, monthly, per_term, per_year), a price, the meals it includes, and a daily meal cap.
Subscriptions live at /dashboard/canteen/subscriptions. A subscription ties a student or staff member to a plan over a date range, with a status (active, paused, expired, cancelled) and a payment status (pending, paid, partial, waived). Staff can pause and resume a subscription in one click.
The clever bit is for boarders. Mark exactly one plan as the boarder default, and the moment a student is flipped to boarder status anywhere in YESS, a database trigger auto-enrols them on that plan — no manual subscription needed. A nightly cron job renews auto-renewing subscriptions the day before they expire.
Chapter five
Orders, the till, and the wallet#
There are two ways a plate gets sold. The kitchen order board at /dashboard/canteen/orders walks an order through the canonical six-state lifecycle — pending → confirmed → preparing → ready → delivered (or cancelled). The walk-up till at /dashboard/canteen/daily-payment is the cashier's point of sale: pick who is paying (student, staff, or guest), build a cart, take the payment, and the order is created already paid and delivered.
An order can be paid by cash, mobile_money, card, wallet, meal_plan, or invoice. The wallet is the prepaid balance a student carries. The cashier (or, in a future release, a parent online) tops it up at the till; topping up posts a debit to cash and a credit to the prepaid-wallet liability account. When a wallet order is placed, a database trigger debits the balance atomically — and if the balance is short, the order is blocked at the database, not merely warned about.
Revenue is recognised cleanly. A non-wallet order that is paid and delivered posts debit cash, credit canteen revenue. A wallet order already recognised its revenue when the wallet was debited, so the order trigger deliberately skips it — no double counting.
Chapter six
The dietary cross-check#
This is the chapter that makes the canteen module unlike any other shop. Every time a student order is created, a database trigger fires before the row is even written. It loads the student's health profile — their food allergens and dietary restrictions — and walks every item in the order.
It runs two checks. An allergen conflict is the intersection of an item's allergens with the student's allergen list — a peanut dish for a peanut-allergic child. A restriction conflict is a dietary requirement the item fails to meet — a student who needs halal being served an item that is not tagged halal. Any conflict stamps a structured dietary flag onto the order recording exactly which items and which conflicts, and a second trigger fans out a notification to every linked parent with a link into /portal/canteen.
One honest caveat: the check flags, it does not block. The order still goes through; the cashier and the parents are warned. This is a deliberate operational choice — a hard block at the till would stop service over a mis-tagged side dish — but it means the tags must be accurate and the operator must read the flag. Allergen safety is a shared duty between the catalogue, the till, and the health record.
Chapter seven
Stock, transactions, and the money#
The canteen's own stockroom lives at /dashboard/canteen/inventory. Items are filed under raw_ingredient, prepared, packaging, cleaning, equipment, or other, each with a stock level, a reorder threshold, a unit cost, and a supplier. Every stock change is a movement — purchase, consumption, waste, adjustment, return, or transfer — and a consumption movement posts the cost of goods to the ledger automatically.
The canteen's standalone ledger lives at /dashboard/canteen/transactions. Each line is income or expense, filed under sales, purchase, salary, utilities, maintenance, equipment, or other. This is where the manager records the diesel for the generator or the bag of rice bought for cash.
At the end of each shift the operator files a reconciliation report at /dashboard/canteen/reports: total sales, cash, mobile money and card received, meal-plan servings, waste, and any cash discrepancy. The report moves draft → submitted → approved. Finally, the read-only analytics at /dashboard/canteen/analytics show revenue, expenses, net profit and margin over a date range, the top-ten most-sold items, and an expenses-by-category breakdown.
Chapter eight
Tuning the canteen#
The canteen's behaviour is configured once at /dashboard/canteen/settings, across three cards. Financial: currency, tax rate, and a default delivery fee. Orders: an order cut-off window, whether guest orders are allowed, whether pre-orders are required, and whether orders auto-deduct from the wallet. Inventory alerts: whether low-stock alerts fire, the low-stock threshold percentage, and whether cost prices are shown to floor staff.
One operational note: the auto-deduct-from-wallet toggle is configured here but is not yet consumed by the order flow — wallet payment today is chosen per order at the till. Treat it as a setting that records intent ahead of the automation that will read it.
Chapter nine
What makes the canteen module elite#
Six things that make this elite
- 1
A safety check at the database, not the screen
The allergen and dietary-restriction cross-check runs as a BEFORE-INSERT trigger inside Postgres — so it fires no matter how the order was created: the till, the kitchen board, the parent portal, or a future mobile app. Safety logic that lives in one screen can be bypassed; safety logic in the database cannot.
- 2
Recipes that cost themselves
Every recipe recomputes its cost per serving automatically the moment its ingredient list changes, and the Produce flow refuses to run if stock is short — listing exactly what is missing — then posts the cost of goods to the ledger atomically. The kitchen and the books never disagree about what a meal cost.
- 3
Prepaid wallets that can't go negative
A wallet order debits the balance inside a row-locked transaction; a short balance raises a database error and the order is never created. The prepaid-wallet liability is a real ledger account, so the money owed to families is on the balance sheet, not in a spreadsheet.
- 4
Boarders enrolled the instant they move in
Flip a student to boarder status and a trigger auto-enrols them on the school's default meal plan — no kitchen handover note, no missed meals on day one. A nightly cron renews auto-renewing subscriptions before they lapse.
- 5
Two recognition paths, no double count
Cash, card and mobile-money orders recognise revenue when paid and delivered; wallet orders recognise it at debit time. The order trigger deliberately skips wallet orders so canteen revenue is counted exactly once, however the plate was paid for.
- 6
Shift reconciliation built in
Operators file a per-shift report — sales, cash, mobile money, meal-plan servings, waste, discrepancy — that moves draft → submitted → approved. The canteen reconciles like a till, not like a petty-cash drawer.
Planned features
What comes next#
In the spirit of an honest handbook, here is what is scaffolded but not yet complete. These are real gaps, listed so you can plan around them.
Five things still cooking
- 1
Dishes on the daily menu
A daily menu is created with a date, meal type and publish flag, but there is not yet a UI to attach specific dishes to it — the dish list is created empty. Today the daily menu is a published placeholder; the dish-picker is planned.
- 2
Subscriptions that bill themselves
Subscriptions carry a payment status, but the plan price is not yet charged automatically — auto-enrolled and renewed subscriptions are left pending. Linking a subscription to an invoice and collecting it through the fees engine is the next step.
- 3
A blocking allergy mode
The dietary cross-check flags and notifies but never blocks. A configurable hard-block mode — refuse the sale on a severe allergen match — is on the roadmap for schools that want it.
- 4
Parent online wallet top-up
Cashier top-up works today; the parent-facing online top-up was intentionally gated off until it routes through the payment gateway, so families top up at the counter for now.
- 5
meal_plan & invoice payment paths
The order payment-method list includes meal_plan and invoice, but only wallet and the cash-class methods post revenue automatically today; meal-plan and invoice orders are marked paid without a dedicated billing path. Wiring them to the ledger is planned.
Adjacent modules
Where the canteen connects#
The canteen is wired into four other modules. Some connections are automatic; some are configured.
Adjacent modules
- 23Boarding lifeMoving a student into a boarding place auto-enrols them on the default meal plan, the day it happens.
- 20Finance & accountingCanteen revenue, wallet liabilities and cost of goods all post to the general ledger automatically.
- 14Student health & careThe dietary cross-check reads each student's food allergens and dietary restrictions from their health profile.
- 24Assets & equipmentRecipes draw their ingredients from the school's shared inventory register; consumption draws down that stock.
- 17Notifications & alertsA dietary flag and a low wallet balance both fan out as notifications to the right parents and managers.
- 34School storeThe shop shares the same cashier-shift reconciliation and prepaid-wallet plumbing as the canteen till.
Tutorial
Do it step by step#
Stand up a working canteen — catalogue, plan, wallet, sale, reconcile — in the order a kitchen actually opens for business. Six steps.
- 1
Build the menu with honest tags
Open /dashboard/canteen/menu and add each dish with its price, cost price, category, and — this is the one that matters — its allergens and dietary tags. The dietary safety check can only protect a child against what you have tagged.Tag allergens before you take the first order. An untagged peanut sauce passes the safety check silently.
- 2
Cost a recipe from stock
At /dashboard/canteen/recipes create a recipe, add ingredients from the inventory register with a quantity per serving — the cost per serving computes itself — then use Produce now to draw the batch out of stock and post the cost of goods to the ledger. - 3
Define a meal plan and a default
At /dashboard/canteen/meal-plans create a plan (type, frequency, price, meals included) and mark one plan the boarder default so new boarders are enrolled automatically. Subscribe individuals at /dashboard/canteen/subscriptions. - 4
Top up a wallet, take a sale
At the till — /dashboard/canteen/daily-payment — top up a student's wallet, then build a cart and choose a payment method. A wallet sale debits the balance atomically; a short balance is refused outright.Watch for the dietary flag on the order — if it appears, the dish conflicts with the student's health profile. Swap it.
- 5
Work the kitchen order board
For sit-down or pre-orders, the board at /dashboard/canteen/orders walks each ticket pending → confirmed → preparing → ready → delivered, with cancel available at any stage. - 6
Reconcile the shift
At day's end file the operator report at /dashboard/canteen/reports — sales, cash, mobile money, meal-plan servings, discrepancy — submit it for approval, and read the margin at /dashboard/canteen/analytics.
The catalogue is tagged, the recipes cost themselves, the wallet can't go negative, and the day's plates are on the school's P&L — checked before serving, counted after selling.