Plain-English summary
Foodops orders branch into three primary types — Dine-In, Takeout, and Delivery — picked from the Order Type dropdown in the order-summary panel when creating a new order. The choice is not cosmetic: each type triggers different prerequisites (dine-in needs a table, delivery needs a non-walk-in customer + address), routes the order into a different downstream queue (Dine-in floor plan, Takeouts list, Deliveries list), and shapes what appears on the KOT, the receipt, and reports. Picking the right type up front matters because once the order is saved the type can no longer be changed (the dropdown is disabled on existing orders). [code: foodops.counter.app/src/components/ui/order-type-dropdown.tsx:orderTypeOptions; foodops.counter.app/src/components/orders/OrderSummary.tsx:OrderTypeDropdown(disabled={!!orderId}); haafai.domain/Haafai.Models/Entities/RestaurantManagement/RestaurantOrderType.cs:RestaurantOrderTypesConfiguration]
When you'd use this
- A new cashier is being trained on how to start a counter order — the first decision is order type.
- Someone is debugging why an order did not show up on the expected screen (e.g., expected to see it in the Dine-in floor plan but it landed in Takeouts).
- A store-level configuration question — the outlet has not enabled delivery, so why does the type picker still show the option?
- An inventory question — taxes/service charges differ across types in some deployments; understanding the type explains the line on a customer's receipt.
- A reporting question — the Day Summary slices revenue by order type; the categories are these three.
The three types
Dine-in
When it applies: a customer is eating in the restaurant, seated at a table.
Prerequisites: at least one table configured for the outlet. See Tables (Dine-in).
Flow: choosing Dine - In from the Order Type dropdown opens the table picker (the floor plan). The picker is skipped only when BOTH "enable dine-in without table" is on AND the outlet has an Unassigned system table — then it goes straight to the create screen on that table. If either is missing, a table must be picked. [code: foodops.counter.app/src/components/ui/order-type-dropdown.tsx:106-115 — if (!enableDineInWithoutTable || !unassignedTableId) → open table modal @ main] Selecting a table attaches the ticket to that table. Items are added; KOTs are sent; payment can be deferred until the customer is ready to leave. By default a table holds one active order at a time — starting a second order on an already-occupied table is blocked ("Table is not vacant") unless the outlet enables "Allow multiple active orders per table" (see Tables). [code: hubits-api-sales/Hubits.Sales.Api/Services/Counter/Orders/OrderCreationService.cs:CreateRestaurantOrderAsync (AllowMultipleActiveOrdersPerTable / "Table is not vacant"); foodops.counter.app/src/components/ui/order-type-dropdown.tsx:handleOrderTypeSelect (enableDineInWithoutTable)]
Distinguishing context on KOT: the table number prints prominently. Servers calling out "Order for table 5" matches the KOT label.
Distinguishing context on receipt: the table number may print at the top, helpful for tip-tracking. Service charge is typically applied (configurable per outlet).
Reporting: counts as Dine-in revenue. Day Summary breaks out dine-in totals separately.
Takeout (Takeaway)
The product's canonical label is Takeout — that is the name in both the order-type record and the counter dropdown. "Takeaway" is the regional synonym used in some docs and conversation, not the in-app label. [code: haafai.domain/Haafai.Models/Entities/RestaurantManagement/RestaurantOrderType.cs:RestaurantOrderTypesConfiguration (Name = "Takeout"); foodops.counter.app/src/components/ui/order-type-dropdown.tsx:orderTypeOptions (label: 'Takeout')]
When it applies: a customer at the counter ordering food to take with them. They wait for the order to be ready, pay, and leave.
Prerequisites: none beyond a configured menu.
Flow: choosing Takeout routes the order onto the outlet's takeout (virtual) table and lands the cashier on the order-create screen. Items are added; KOTs are sent; payment is typically taken immediately on or before pickup. Once placed, the ticket joins the Takeouts queue for kitchen tracking. [code: foodops.counter.app/src/components/ui/order-type-dropdown.tsx:navigateToOrderCreate (config.takeOutTableId)]
Distinguishing context on KOT: marked as Takeout. No table number; possibly a counter or queue number.
Distinguishing context on receipt: standard receipt. Service charge typically not applied.
Reporting: counts as Takeout revenue, separately from Dine-in and Delivery.
Delivery
When it applies: the customer is not on the premises; an order is placed (in person, by phone, or via an online channel) for a rider to deliver.
Prerequisites: a real (non-walk-in) customer record and a selected delivery address — both are enforced at order-create time, not just by the UI: the backend rejects a delivery order placed for the walk-in customer ("Delivery orders cannot be created for walk-in customers") or with no address ("Please select a delivery address for this delivery order"). Plus outlet delivery enabled in Settings, and at least one rider/courier configured for the outlet. [code: hubits-api-sales/Hubits.Sales.Api/Services/Counter/Orders/OrderCreationService.cs:CreateRestaurantOrderAsync (Delivery walk-in + DeliveryAddressId guards)]
Flow: choosing Delivery routes the order onto the outlet's delivery (virtual) table and surfaces a customer + address picker. Once those are set, items are added; KOTs are sent; payment is captured at the time of order or on rider return depending on the outlet's delivery cash policy. The ticket joins the Deliveries list where rider assignment, dispatch, and acknowledgement happen. [code: foodops.counter.app/src/components/ui/order-type-dropdown.tsx:navigateToOrderCreate (config.deliveryTableId)]
Distinguishing context on KOT: marked as Delivery. Customer name and address may appear on the prep ticket so packers know what to label the bag.
Distinguishing context on receipt: customer name and delivery address. Delivery charge line where applicable.
Reporting: counts as Delivery revenue. Cash deliveries also surface in the Delivery Cash tab on Session Details until the cash is acknowledged on rider return — see Cash Handling.
Switching type after items are added
The Order Type dropdown lives in the order-summary panel. It can only be changed while building a new, unsaved order — once the order has been saved (i.e. it has an order id) the dropdown is disabled and shows the tooltip "Order type cannot be changed". [code: foodops.counter.app/src/components/orders/OrderSummary.tsx:OrderTypeDropdown(disabled={!!orderId})]
Within the unsaved create flow, switching the type after items have been added is allowed and the cart is preserved across the switch — switching only rewrites the orderType/tableId URL params (the cart is component state, kept by the updateOrderTypeInPlace updater rather than remounting the page). One caveat: if any item already in the cart is not available for the new order type (per the item/variant availability flags above), the app first asks you to confirm removing those incompatible items; the compatible items stay. [code: foodops.counter.app/src/hooks/useOrderCreate.ts:updateOrderTypeInPlace; foodops.counter.app/src/components/orders/OrderSummary.tsx:handleOrderTypeChange/confirmIncompatibleRemoval (isVariantAvailableForOrderType check)]
- Switching to Dine-In prompts for a table (unless the outlet allows dine-in without a table) — compatible items remain on the ticket.
- Switching from Dine-In to Takeout/Delivery swaps the dine-in table for the outlet's takeout/delivery virtual table — the dine-in table becomes available again. Compatible items remain.
- Switching to Delivery surfaces the customer + address picker — compatible items remain.
Because a KOT belongs to a created order and the type can no longer change after creation, you cannot end up with a saved order whose KOT shows a different type than the order now records. Best practice remains: get the type right before saving/sending the first KOT, since you can't change it afterward.
Where the system branches by type
Several behaviours that look uniform on the surface diverge under the hood:
- Available items — individual products/variants carry per-order-type availability flags (
availableForDineIn/availableForTakeout/availableForDelivery), so the item list shown on the create screen is filtered by the selected type: an item flagged unavailable for, say, takeout drops out of the menu when the order is takeout. This is a per-item/variant gate, not a whole-menu/category restriction. [code: foodops.counter.app/src/hooks/useOrderCreate.ts (allProducts filtered via isProductAvailableForOrderType(p, orderType)); foodops.counter.app/src/utils/itemAvailability.ts:isProductAvailableForOrderType,isVariantAvailableForOrderType] - Tax and service charge — outlets configure which service fees auto-apply per order type. Service fees are linked to an order type per organisation (
ServiceFeeOrderType), and on create the order auto-attaches every service fee mapped to its type; the session also exposes per-type flagshasServiceFeesForDineIn/TakeOut/Delivery. So e.g. a service charge applied for dine-in but not takeout is real, configurable behavior. [code: haafai.domain/Haafai.Models/Entities/Accounting/ServiceFees/ServiceFeeOrderType.cs; hubits-api-sales/Hubits.Sales.Api/Services/Counter/Orders/OrderCreationService.cs:CreateRestaurantOrderAsync (auto-apply ServiceFeeOrderTypes loop)]
- KOT routing — KOTs may route to different printers for different types (e.g., a dedicated delivery printer for label generation).
- Payment timing — dine-in usually allows payment deferral; takeaway typically captures payment up front; delivery varies by COD vs paid online.
- Receipt template — different layouts per type (table number for dine-in, address for delivery).
- Status workflow — the order operation-status set includes delivery-specific states: alongside New / Accepted / Preparing / Ready / Served / Picked / Rejected, there are explicit OutForDelivery and Delivered statuses. So a delivery order does carry the additional out-for-delivery / delivered states that dine-in and takeout orders don't reach. [code: haafai.domain/Haafai.Models/Constants/ModelConstants.cs:RestaurantOrderOperationStatus (OutForDelivery=6, Delivered=7)]
- Stock impact — items reserve / decrement stock identically across types, but waste/return reporting may bucket differently.
These are configuration-dependent — not every outlet uses every distinction. The ones to verify per outlet during onboarding: tax/service-charge differences, KOT routing, and payment-timing policy.
Outlet-level configuration
Each order type is independently enable-able per outlet:
- Dine-in — requires tables; some outlets are takeaway-only and skip tables entirely.
- Takeout — typically always enabled; the default fallback (online orders also default to this type).
- Delivery — requires riders + address handling; many outlets do not offer delivery and disable it.
A disabled type does not appear in the dropdown for that outlet — the dropdown filters its options by the enableDineIn / enableDelivery / enableTakeOut flags carried in the order-button config. If a cashier expects to see Delivery but it is missing, the outlet's settings have it off — the fix is in Settings → Outlets → Order Types (or wherever the deployment surfaces this). [code: foodops.counter.app/src/components/ui/order-type-dropdown.tsx:availableOptions; hubits-api-sales/Hubits.Sales.Api/Dto/Counter/Orders/OrderButtonConfigDto.cs; haafai.domain/Haafai.Models/Entities/SystemModels/ApplicationOrganisations/ApplicationOrganisationEnabledOrderType.cs]
Online vs in-person orders
Orders entering Foodops via online channels (e.g., the Online Ordering integrations) are pre-tagged with their type — the online order payload carries an OrderType field (delivery / takeout / dinein, defaulting to takeout). A counter cashier does not pick a type for these — they appear in the relevant queue already classified. The counter Order Type dropdown is only for orders the cashier is creating in person. [code: foodops.ordering.api/Foodops.Ordering.Models/Orders/CreateOrderRequest.cs:OrderType]
Key concepts
- Order type — the categorical label distinguishing how an order is fulfilled: Dine-In, Takeout, or Delivery. Picked from the Order Type dropdown when creating an order.
- Type-driven branching — system behaviours (menu, taxes, KOT routing, payment timing) that differ by type.
- Outlet-level enablement — which types are available is configured per outlet; disabled types are hidden from the picker.
- Type immutability across stations — once a KOT is sent, switching type does not retroactively update the kitchen.
- Online order pre-classification — orders from online channels arrive with type already set; counter does not re-pick.
Common questions
Q: How do I pick the order type? A: When creating a new order, open the Order Type dropdown in the order-summary panel and choose Dine - In, Delivery, or Takeout. Pick before adding items, ideally — and you must pick it before saving, because it can't be changed once the order exists. [code: foodops.counter.app/src/components/ui/order-type-dropdown.tsx:orderTypeOptions]
Q: Can I change the order type after adding items? A: Only while the order is still unsaved (being created) — at that point items already on the cart stay put when you switch. Once the order has been saved, the Order Type dropdown is disabled and shows "Order type cannot be changed", so the type is fixed from then on. Get the type right before saving. [code: foodops.counter.app/src/components/orders/OrderSummary.tsx:OrderTypeDropdown(disabled={!!orderId})]
Q: Why don't I see the Delivery option in my type picker?
A: The outlet does not have delivery enabled (the enableDelivery flag is off), or your account lacks the create permission. Check Settings → Outlets, or speak to a manager. Disabled types are hidden, not greyed out. [code: foodops.counter.app/src/components/ui/order-type-dropdown.tsx:availableOptions; hubits-api-sales/Hubits.Sales.Api/Dto/Counter/Orders/OrderButtonConfigDto.cs:EnableDelivery,HasCreatePermission]
Q: Does service charge apply to all order types? A: It is configured per order type. An outlet maps each service fee to the order types it applies to, and a new order automatically picks up the service fees mapped to its type. Dine-in is the most common application; takeout and delivery often skip it. The receipt shows the line if applied. Check Settings → Outlets → Tax & Service Charge for the per-type configuration. [code: haafai.domain/Haafai.Models/Entities/Accounting/ServiceFees/ServiceFeeOrderType.cs; hubits-api-sales/Hubits.Sales.Api/Services/Counter/Orders/OrderCreationService.cs:CreateRestaurantOrderAsync (ServiceFeeOrderTypes auto-apply)]
Q: How does a delivery order's payment work? A: Two patterns. (1) Paid in advance — captured at order creation, no rider cash to track. (2) Cash on delivery — rider collects cash from the customer, returns it at end of run, the cashier acknowledges in the Delivery Cash tab. The flow depends on the outlet's policy.
Q: Can I change a takeout to a dine-in if a customer decides to eat in? A: Only if the order has not been saved yet — while still creating it, switch the type and pick a table; compatible items stay (any item not available for dine-in is flagged for removal first), and if service charge differs by type, the total updates accordingly. If the order is already saved, the type is locked (the dropdown is disabled), so you'd cancel/re-ring or handle it operationally rather than switching the type. [code: foodops.counter.app/src/components/orders/OrderSummary.tsx:OrderTypeDropdown(disabled={!!orderId}); foodops.counter.app/src/hooks/useOrderCreate.ts:updateOrderTypeInPlace]
Q: What's the difference between Takeaway and Takeout? A: Same thing, different word. The in-app canonical label is Takeout (that's the name stored on the order-type record and shown in the counter dropdown); "Takeaway" is the regional synonym used in conversation and some docs. [code: haafai.domain/Haafai.Models/Entities/RestaurantManagement/RestaurantOrderType.cs:RestaurantOrderTypesConfiguration (Name = "Takeout")]
Q: How does the Day Summary report break out order types? A: It breaks revenue out by type (Dine-In / Takeout / Delivery). The backend summary DTO carries Name, Sales, and Orders (count) per type, but the counter dashboard's Order Type Summary card itself renders only the type name and its sales total — the order count is in the DTO but not shown on that card. (Per-type discount/net breakdowns are not part of this summary DTO — for those see Reports.) [code: hubits-api-sales/Hubits.Sales.Api/Dto/Counter/Dasboard/OrderTypeSummaryDto.cs (Name/Sales/Orders); foodops.counter.app/src/components/dashboard/OrderTypeSummary.tsx (renders name + sales only); foodops.counter.app/src/types/dashboard.ts:OrderTypeSummary (name, sales)]
Q: Can a single order span multiple types (e.g., half eaten in, half taken away)? A: No — one order, one type. If a customer wants to take part of their dine-in order home, the typical pattern is a doggy-bag scenario (no system action) or a separate small takeaway order at end of meal.
Edge cases and known issues
Order Type dropdown won't change (greyed out)
- Symptom: the Order Type control shows the current type but won't open / is greyed, with a "Order type cannot be changed" tooltip.
- Cause: the order already exists (has an order id) — the dropdown is intentionally disabled on saved orders, so type is only editable while first creating the order. [code: foodops.counter.app/src/components/orders/OrderSummary.tsx:OrderTypeDropdown(disabled={!!orderId})]
- Workaround: if you need a different type on a saved order, cancel/re-ring it under the correct type rather than trying to switch. Get the type right before saving.
Delivery order blocked at save — walk-in customer or no address
- Symptom: saving a Delivery order fails with "Delivery orders cannot be created for walk-in customers..." or "Please select a delivery address for this delivery order."
- Cause: by design, a delivery order requires a real (non-walk-in) customer AND a selected delivery address; the backend enforces both at create-time, not only the UI. [code: hubits-api-sales/Hubits.Sales.Api/Services/Counter/Orders/OrderCreationService.cs:CreateRestaurantOrderAsync (Delivery walk-in + DeliveryAddressId guards)]
- Workaround: pick a saved customer that has a delivery address (or add one), then select that address before saving. This is not a bug — it guarantees the rider has a destination. (Note: this corrects an earlier claim that a delivery order could be created with no customer/address — it cannot, on the counter create path.)
Related
POS - Complete Takeaway Order Flow — the takeaway-type walkthrough end to end
Tables (Dine-in) — the prerequisite for dine-in orders
Takeouts — where takeaway orders queue
Deliveries — where delivery orders queue
KOT — the kitchen ticket whose content varies by order type
Kitchen Display — surfaces orders with their type as context
Cash Handling — delivery cash specifically tracks cash-on-delivery returns
Online Ordering — online channels pre-classify type
Reports — Day Summary slices revenue by order type
Counter order (internal-docs) — the screen where the type picker lives
2026-08-09 — codebase: hubits-api-sales 5889642..cdb3b32 (OrdersController.cs, part of this entry's tracked surface). The constructor/
ICustomerOrderingApiNotificationServicewiring and the CancelOrderwasRejectedBeforeAcceptreject-SMS logic in this range are the same change already captured in the 2026-08-06 note (range 5889642..9351716) — no new claim there. What's new in this wider range:ChangeStatusnow also runs an auto-close check. It adds.Include(o => o.SalesOrderStatus)to the order load and, after applying the status update, calls a newTryCloseIfTerminalAndSettledAsync(order, request.StatusId). Per the added comment, this closes an order once it has BOTH (a) reached the terminal service status for its order type — dine-in Served, takeout Picked, or delivery Delivered — and (b) is already settled (paid); the comment notes this is the status-side mirror of an existing payment-side trigger (OrderPaymentController.IsInTerminalServiceStatus), so whichever of 'order gets marked served/picked/delivered' or 'order gets paid' happens second is what actually closes it. This is directly relevant to this entry's 'Status workflow' branching-by-type bullet (Where the system branches by type) and to the per-type terminal-status claim already cited toModelConstants.RestaurantOrderOperationStatus— it doesn't contradict that claim, it extends it with a previously-undocumented type-gated auto-close side effect. The diff shown does not include the body ofTryCloseIfTerminalAndSettledAsyncorIsInTerminalServiceStatus, so the exact per-type status mapping and what 'closed' changes in the UI (e.g. whether it disappears from an active-orders list) are not yet verified from this evidence alone — worth a follow-up read of those two methods before adding a firm claim to the entry body. (auto-applied by the truth pipeline; adversarially gated)2026-08-06 — codebase: hubits-api-sales 5889642..9351716 (OrdersController.cs, part of this entry's tracked surface). New customer-notification behavior layered on the same Cancel/ChangeStatus endpoints this entry's 'cancel/re-ring' workaround relies on — no order-type branching, table/delivery guards, dropdown, or service-fee logic touched, so no existing claim is contradicted. CancelOrder now captures
wasRejectedBeforeAccept = order.RestaurantOrderOperationStatusId == Newbefore the write and, only when true, callsICustomerOrderingApiNotificationService.NotifyOrderStatusChangeAsync(..., Rejected)to SMS the customer — per the added comment, 'Cancelling an order the counter never accepted IS the Reject button — there is no separate reject endpoint.' Cancelling an already-accepted order stays silent by design (avoids texting on every POS/dine-in void). ChangeStatus now also notifies_customerOrderingApiserver-side on every status transition (the commit subject notes the accept-payment SMS moved server-side from the browser). Operational implication for this entry: a cashier following the documented 'cancel/re-ring under the correct type' workaround (Edge cases section, and the takeout→dine-in Q&A) on a saved-but-not-yet-accepted order will now trigger a customer-facing 'order rejected' SMS as a side effect of that cancel, even though the cashier's intent is a same-order re-ring rather than a genuine rejection — worth a note near that workaround. Both notification calls are wrapped in try/catch that only logs on failure, so this is best-effort and doesn't change the request's success path._customerOrderingApiis an optional constructor param (defaults to null in existing DI registrations), so behavior is additive, not a breaking change to the controller's existing contract. (auto-applied by the truth pipeline; adversarially gated)2026-07-22 — codebase: hubits-api-sales@f26ba1f added an explicit permission gate on order cancellation. CancelOrder in OrdersController.cs now requires the SalesOrders.Delete role, checked via a direct org-scoped UserRoles query (not the 3-min-cached User.IsInRole, so it also covers the API-key path); a caller lacking it gets HTTP 403 with message "You do not have permission to cancel orders". This is relevant context for this entry's 'cancel/re-ring' workaround, cited twice (correcting a saved order's locked type, and the takeout-to-dine-in Q&A): a cashier without SalesOrders.Delete can no longer perform that workaround themselves and will need a manager or higher-permission user. Order-type branching itself (dropdown, table/delivery guards, service-fee auto-apply, OrderCreationService) is untouched by this diff — it does not contradict any documented order-type claim, only adds a new constraint on the suggested operational workaround. (auto-applied by the truth pipeline; adversarially gated)
2026-06-29 — codebase (July-10 launch re-verify against new-stack prod HEADs:
foodops.counter.app@32669a9main,hubits-api-sales@19190b9main,haafai.domain@e138944staging,foodops.ordering.api@80e07fdmain). UPHELD: dropdown labels 'Dine - In'/'Delivery'/'Takeout' (order-type-dropdown.tsx:23-40orderTypeOptions);disabled={!!orderId}on the renderedOrderTypeDropdown(OrderSummary.tsx:1938— note this is now a single render site, vs the 3 sites cited in the 2026-06-15 pass; control consolidated, behaviour identical); table-skip logicif (!enableDineInWithoutTable || !unassignedTableId)(order-type-dropdown.tsx:109); virtual-table routing viatakeOutTableId/deliveryTableId(:140-146); delivery walk-in + DeliveryAddressId guards with exact messages (OrderCreationService.cs:112,117); "Table is not vacant" + AllowMultipleActiveOrdersPerTable (:160-184); service-fee auto-apply-by-type loop (:286-294); per-item availability filterisVariantAvailableForOrderType(OrderSummary.tsx:15,451,useOrderCreate.ts/itemAvailability.ts); onlineOrderTypedefault "takeout" (ordering.api CreateOrderRequest.cs:28). CORRECTED: dropped the retiredhaafai.app.foodopsblock fromsource_repos/verified_against_commit(the legacy monolith order-type helper + Razor views are gone at launch — the canonical surface is the counter dropdown +OrderCreationService); frontmatter SHAs + last_verified bumped. Still-unverified (pre-existing HTML-comment flags retained): KOT printer-routing by type, payment-timing enforcement, per-type receipt template, waste/return bucketing.2026-06-15 — codebase (ADVERSARIAL re-verify of the 2026-06-14 corrections, all against prod branches: counter.app main, hubits-api-sales main, haafai.domain staging, ordering.api main). UPHELD: dropdown control + labels ("Dine - In"/"Delivery"/"Takeout") and
disabled={!!orderId}(3 render sites inOrderSummary.tsxlines 1992/2094/2146 + the disabled button title inorder-type-dropdown.tsx); canonical Name="Takeout" / "Dine-In" / "Delivery" and ids DineIn=1/TakeOut=2/Delivery=3 (RestaurantOrderType.cs,ModelConstants.RestaurantOrderTypes); delivery walk-in + DeliveryAddressId guards with exact messages (OrderCreationService.cs:105-122); "Table is not vacant" + AllowMultipleActiveOrdersPerTable + system-table skip (OrderCreationService.cs:157-189); service-fee auto-apply-by-type loop (OrderCreationService.cs:282-295) + per-type session flagshasServiceFeesForDineIn/TakeOut/Delivery(session.ts:339-341); per-outlet enablement (OrderButtonConfigDto,ApplicationOrganisationEnabledOrderType.IsEnabled); onlineOrderTypedefault "takeout" (ordering.api CreateOrderRequest.cs:28);updateOrderTypeInPlaceURL-param rewrite (useOrderCreate.ts:247). CORRECTED the 2026-06-14 pass's own errors: (a) the menu-visibility-by-type UNVERIFIED flag was WRONG —useOrderCreate.tsfilters the product list viaisProductAvailableForOrderType(p, orderType)backed byitemAvailability.tsper-item/variant flags (availableForDineIn/Takeout/Delivery); the prior pass only checked the backendOrderMenuControllerand missed the FE filter. Replaced the flag with a cited statement; (b) the delivery-specific status states UNVERIFIED flag overcorrected —RestaurantOrderOperationStatusdefinesOutForDelivery=6andDelivered=7explicitly; tightened to confirm the constants while keeping the per-type narrative hedged (and noting there is no status named "Open"; initial is "New"); (c) the "items stay put" type-switch claim was overstated —OrderSummary.handleOrderTypeChange/confirmIncompatibleRemovalprompts to REMOVE items not available for the new type, so only compatible items survive a switch (fixed in the switching section + the takeout→dine-in Q&A); (d) the Day Summary Q&A said the counter card "surfaces exactly Name, Sales, and Orders" — the DTO carries Orders butOrderTypeSummary.tsx/dashboard.tsrender only name + sales; tightened. Still-flagged unverifiable: KOT printer routing by type, payment-timing enforcement, per-type receipt template, waste/return bucketing. UI not re-walked this pass.2026-06-14 — codebase: foodops.counter.app@df086e4 (main), hubits-api-sales@f79eb7b (main), haafai.domain@a2bd90e (staging), foodops.ordering.api@d44572f (main). Truth-audit pass against prod branches. CORRECTIONS made: (1) the order-type control is a labeled Order Type dropdown in the order-summary panel, NOT "type-picker tabs at the top" (
order-type-dropdown.tsx, rendered inOrderSummary.tsx); (2) canonical label is Takeout, NOT "Takeaway" — the prior doc had it backwards (RestaurantOrderType.csName="Takeout", dropdown label 'Takeout'); (3) type can only be changed on an UNSAVED order —OrderSummary.tsxpassesdisabled={!!orderId}, so the whole "switch type after KOT sent" narrative was reframed (can't switch on a saved order at all); (4) the "Delivery order created without a customer/address" edge case was a fabrication of the exact failure class this audit hunts —OrderCreationService.CreateRestaurantOrderAsynchard-rejects walk-in customers and missingDeliveryAddressIdon delivery orders; replaced with the real "blocked at save" behavior; (5) Day Summary Q&A overstated the breakdown —OrderTypeSummaryDtois only Name/Sales/Orders. CONFIRMED + cited: three types & ids (DineIn=1/TakeOut=2/Delivery=3), per-outlet enablement (OrderButtonConfigDto,ApplicationOrganisationEnabledOrderType), service-fee-by-type auto-apply (ServiceFeeOrderType+ creation loop), online orders carryOrderType(ordering.api CreateOrderRequest), one-active-order-per-table gate. FLAGGED unverifiable (HTML comments): menu-visibility-by-type, KOT printer routing by type, payment-timing enforcement, per-type receipt template, delivery-specific status states, waste/return bucketing. UI not re-walked this pass.2026-06-04 — codebase: hubits-api-sales@5274891 (main). Re-verified the three-type concept against current order-creation backend. REAL CHANGE (minor, additive): dine-in now defaults to one active order per table, gated by the org setting
AllowMultipleActiveOrdersPerTable(OrderCreationService.cs:157-188); added one clarifying line to the Dine-in flow section. The two 2026-06-03 refresh drivers do not otherwise touch this concept entry:2489d1fis a backend line-item-tax-Id / concurrency-logging fix (no order-number change), and5565dd2just adds.Include(SalesOrderStatus)to the floor-plan query. Type-branching (menu/tax/KOT/payment-timing), type-switching consequences, and online-order pre-classification re-read as still accurate — no other corrections. UI not re-walked this pass.2026-05-04 — codebase: haafai/foodops.counter.app:b9677b0, haafai/haafai.app.foodops:46a80a3 (Services/Restaurants/RestaurantOrderTypeHelper.cs, Dtos/OrderTypeSummaryResult.cs, Views/Orders/All.cshtml, Views/Orders/DineIn.cshtml confirmed; counter.app DineInPage.tsx and TakeoutPage.tsx confirmed); UI not yet verified