Module: FoodVerse / Restaurant (food / food+tiffin)
Status: ๐ข Production verified (real order lines + commission) ยท Last validated: 2026-09-06 ยท Priority: P0
Restaurant discovery + food ordering + tiffin subscriptions + dine-in table booking + group orders. Validated against classs/RestaurantModule.php (6,422 lines by wc -l, 2026-09-06 โ corrected from an earlier "~4,700 lines" estimate) and the live schema.
A. Purpose
Customers discover restaurants and place food orders (instant delivery), subscribe to tiffin plans, book dine-in tables, and run group orders. Merchants (restaurant owners) manage menu, branches, orders, and refunds. Revenue = 5% commission (platform_commission_settings.setting_key='food_order', live โ 19 processed rows in commission_transactions for order_table='food_orders', 2026-09-06; corrected from an earlier count of 17 โ this is a moving snapshot on an actively-tested environment).
B. Actors
Customer/buyer; restaurant owner + restaurant_staff; delivery partner (hyperlocal/courier); admin. Tiffin provider is the tiffin enrollment type.
C. Entry points
Consumer: /restaurants.php, /foodverse.php, restaurant detail, cart/checkout; tracking JS assets/newjs/food_track_order.js. Merchant: food dashboard, menu, orders (owner methods below). Writes flow through RestaurantModule (via forms/doaction_*).
D. Onboarding
registerRestaurant(userId, companyId, data) (:794) โ restaurant_master. Module food on; merchant enrolled; menu built before publishing. Food is FSSAI/licence-sensitive (see ../../30-core/kyc-trust.md).
E. Feature registry (prefix FOOD-)
| ID | Feature | Actor | Method | Tables (write) | Status |
|---|---|---|---|---|---|
| FOOD-001 | List / discover restaurants | anon+cust | listRestaurants :1000 | โ | ๐ข |
| FOOD-002 | Restaurant detail (buyer) | anon+cust | getRestaurantDetails(publicOnly) :1191 | โ | ๐ข |
| FOOD-003 | View menu | anon+cust | getMenu(publicOnly) :1293 | โ | ๐ข |
| FOOD-004 | Register restaurant | owner | registerRestaurant :794 | restaurant_master, restaurant_operating_hours, restaurant_meal_slots | ๐ข |
| FOOD-005 | Menu CRUD | owner/staff | ownerAddCategory/AddMenuItem/UpdateMenuItem/ToggleMenuItem :1482-1793 | menu tables | ๐ข |
| FOOD-006 | Branches | owner | ownerListBranches/CreateBranch :1877/:1913 | restaurant_master (branch) | ๐ข |
| FOOD-007 | Place order (instant) | customer | placeOrderInstant :2432 | food_orders, food_order_items, food_order_status_history | ๐ข (money) |
| FOOD-008 | Order status update | owner | updateRestaurantOrderStatus :2164 | food_orders, food_order_status_history | ๐ข |
| FOOD-009 | Cancel order | customer | cancelOrderByUser :3646 | food_orders, ledger | ๐ก |
| FOOD-010 | Merchant refund | owner | refundOrderByMerchant :4033 | refund + wallet | ๐ก |
| FOOD-011 | Tiffin subscription | customer | createTiffinSubscription :4254 | tiffin_plans, tiffin_order_map, tiffin_plan_items | ๐ข |
| FOOD-012 | Dine-in table booking | customer | (writes restaurant_table_bookings :6236) | restaurant_table_bookings | ๐ก |
| FOOD-013 | Group order | customer | (writes food_group_orders :5240) | food_group_orders, food_group_order_items | ๐ก |
| FOOD-014 | Meal preferences | customer | saveMealPreferences/getMealPreferences :4635/:4714 | food_meal_preferences | ๐ข |
F. Order flow (FOOD-007, the money path)
restaurants.php โ restaurant detail โ cart โ placeOrderInstant(userId, restaurantId, items, deliveryData) :2432
validate items + delivery; server-side pricing from menu (like CommerceX, not client)
wallet debit (wallet-first) :2774
escrow credit to CLASSIFIED_ESCROW_BUCKET_USER_ID :2809 (platform holds funds until delivery โ
CommerceSettlementModule::releaseFoodPayouts() pays the restaurant out later)
INSERT food_orders (header) :2875
INSERT food_order_items (one per line) :3063 โ FoodVerse IS normalized (header+items)
INSERT food_order_status_history :3087
commission โ CommissionEngineModule::computeAndRecord('food_order', โฆ) :2937 โ commission_transactions
central payments ledger (PaymentsModule::recordWalletPayment) :2977
notify restaurant + customer
Correction (2026-09-06): an earlier pass of this page cited the header/items/status-history INSERTs at :6043/:6075/:6113. Those line numbers are real INSERTs into the same three tables, but they belong to a different method further down the file โ the tiffin daily-order auto-generator (it builds a food_orders row from tiffin_plan_items/sub['plan_id'], not from a customer's cart) โ not placeOrderInstant. The actual placeOrderInstant writes are at :2875 (header, confirmed by the 'placeOrderInstant ledger error' log string right after it at :2989), :3063 (items), and :3087 (status history), corrected above. Contrast with CommerceX: Food normalizes lines into food_order_items, whereas CommerceX keeps lines on orders_master. When aggregating "an order", Food = 1 header + N item rows.
G. Data model (2026-09-06)
| Table | Rows | Role |
|---|---|---|
restaurant_master | 872 | restaurants (+ branches) |
food_orders | 1 | order header |
food_order_items | 82 | order lines |
food_order_status_history | 80 | status transitions |
restaurant_table_bookings | 0 | dine-in bookings (feature wired, no live bookings yet) |
tiffin_plans / tiffin_order_map | 15 / 30 | tiffin subscription plans + orders |
food_group_orders / food_group_order_items | 3 / 0 | group ordering |
food_meal_preferences | 0 | customer diet prefs (no rows yet) |
restaurant_staff | 0 | staff sub-users (no rows yet) |
Data-state anomaly (requires verification):food_orders= 1 header butfood_order_items= 82 andfood_order_status_history= 80. Child rows without matching headers strongly suggests the order-header table was purged/reset while child + finance rows were retained. The schema is header+items (validated from the INSERT sites); the counts need a reconcile before quoting "N orders". Same pattern seen in StayGo โ see ../hotels/overview.md for its current (2026-09-06) counts, which have themselves moved since this page'shotel_paymentscross-reference was first written; do not copy a specific number across module pages, re-check live.
H. Financial impact
Wallet-first debit (:2774) โ escrow credit to CLASSIFIED_ESCROW_BUCKET_USER_ID (:2809, held until delivery) โ central ledger (module_key='food') โ 5% commission (commission_transactions, live) โ CommerceSettlementModule::releaseFoodPayouts() settles the restaurant. Refund via refundOrderByMerchant (:4033) โ wallet credit + ledger refund_processed entry. See ../../40-financial/central-finance-ledger.md. Note: neither the customer debit (:2774) nor the escrow credit (:2809) passes an acct_purpose in $meta to WalletModule, so both fall through to the historical default account mapping in WalletModule::journalAccountsFor() (classs/WalletModule.php:952-983) โ the debit is journaled as USER_WALLET_LIABILITY โ REVENUE_GENERAL (booked as recognised revenue) rather than an escrow-liability movement, even though the money is actually being held, not earned, at this point. This is the same class of gap the function's own docblock documents (WalletModule.php:938-946, "AccountingJournalModule context-blind mapping"); flagging here because Food's checkout path is a live, unfixed caller of the vulnerable default โ see this audit's cover report for the corresponding note on Hotels/Freelancer/Events.
K. State machine (food_orders.order status)
placed โ accepted โ preparing โ ready โ out_for_delivery โ delivered โ completed, with cancelled / rejected / refunded. Transitions via updateRestaurantOrderStatus (owner) and cancelOrderByUser (customer); each writes food_order_status_history.
L. Errors (prefix FOOD-E)
FOOD-E001item unavailable / restaurant closed at checkout โplaceOrderInstantrefuses (menu
publicOnly/availability); inspect menu item is_available + operating hours/meal slots.
FOOD-E002order-header/item count mismatch โ see data-state anomaly above.
M. Cross-module dependencies
Wallet, finance ledger, commission, hyperlocal/courier delivery, notifications, trust (getFoodSellerTrust :2373).
N. Change-impact
Changing placeOrderInstant affects money (wallet/ledger/commission), menu pricing integrity, delivery routing, and status history. Re-test the order money path + normalized item writes.