Feature Specification: Table Service Integration
App: drinks.catlab.eu
Role: Waiter-operated POS / Table Management
Status: Ready for Development
1. Objective
Implement a "Table Service" mode for the existing POS application, allowing waiters to take orders directly at tables via their mobile devices. This requires significant refactoring to introduce Table and Patron models, separate fulfillment from payment states, and update the order routing logic between the Bar POS and Waiter POS.
2. Database & Model Refactoring
2.1. Tables Model
-
Hierarchy: Tables belong directly to an Event. Each event starts with zero tables.
-
Properties: id, event_id, table_number (integer), name (localized string, e.g., "Table 1").
-
Deletions: Must utilize soft-deletion (deleted_at).
-
Generation Utility: Need an admin function to bulk-generate X tables.
-
Logic: It must query the highest current active (non-soft-deleted) table_number and increment intelligently to prevent duplicates.
-
Renaming: Single tables must be easily renameable by event admins.
=> If a remote order arrives with an unknown table number, create that table.
2.2. Patron Model
- Hierarchy: A new Eloquent model linked to an
Event. An Order belongsTo a Patron.
- Properties:
id, event_id, name (optional, primarily used by quiz software/remote name entry).
2.3. Order Status Split
The Order model must be refactored to separate the physical delivery of the drink from the financial settlement of the tab.
- Fulfillment Status (
status): pending -> prepared -> delivered. (Note: 'processed' is being renamed to 'delivered')
- Payment Status (
payment_status): unpaid, paid, voided.
=> Orders from the 'live' sales are always immediately delivered.
2.4 event.allow_unpaid_orders
Create a new field allow_unpaid_table_orders that determines if waiter can open a 'tab'.
3. Core Logic: Patron & Order Assignment
When a new order is received, the system must determine which Patron group owns it based on the following algorithm:
- Named Orders (Quiz App):
- If a
name is provided, search for an existing Patron with that name who has placed an order within the last X hours (duration configurable).
- If found: Append the new order to this Patron (regardless of the table or paid/unpaid status).
- If not found: Create a new Patron.
- Anonymous Orders (Table QR Scan):
- Prerequisite: Only permitted if the event setting
allow_unpaid_online_orders is true or if some kind of payment system is configured (currently only: a valid card alias is provided)
- Check the last Patron assigned to the scanned Table.
- If the last Patron has an UNPAID order: Append the new order to this existing Patron. (This ensures Waiter orders and QR orders merge seamlessly on the same unpaid tab).
- If the last Patron's orders are all PAID: Create a new Patron group for this table. (We do not care about maintaining history across separate, settled sessions).
4. User Interfaces & Workflows
4.1. The Bar POS (Remote Orders Interface)
- Visibility: Pending orders from table service appear here.
- Action: When the bar finishes making the drinks, they click a button that marks the order as
prepared (or delivered, depending on how the bar treats it locally, but it drops off their active screen).
4.2. The Waiter POS (Table Service Mode)
-
Device Configuration: POS can be toggled into "Table Service" mode.
-
Dashboard: Displays a list of all tables in the event + a "No Table" option.
-
Table Interaction:
-
Clicking a Table shows active Patrons assigned to it.
-
Includes a 1-click "Create New Patron" button (creates an anonymous Patron linked to the table).
-
"No Table" Interaction: Shows a list of Patrons not linked to any table. Waiters can create unlinked Patrons here.
-
Patron View:
-
Shows outstanding balance (sum of unpaid orders).
-
Shows history of previous orders.
-
Provides the interface to place a new order (mirroring the Live Sales layout).
-
Waiter Order Management Queue:
-
Shows a list of all pending or prepared orders.
-
Filters: Toggle to show only orders created by this specific POS device; Toggle to show only prepared orders.
-
Actions: Mark as delivered, or mark as voided (error correction).
4.3. Checkout & Payment Flow
- Order Delivery: When the Waiter marks an order as
delivered (or initiates payment), the standard payment dialog appears (Cash, Card, etc.).
- Pay Later: If
allow_unpaid_table_orders is true, the waiter can select "Pay Later", leaving the payment_status as unpaid while the fulfillment status becomes delivered.
- Settle Balance: From the Patron screen, clicking "Pay Outstanding Balance" initiates the payment flow for the total sum of all unpaid orders. Once completed, all associated orders are updated to
paid. (Partial payments are strictly out-of-scope for this iteration).
General considerations
=> As with all other aspects of the app, the table service part must be completely functional offline. Bar preparations will obviously not be possible, but the waiter must be able to walk to the bar themselves, prepare the order, return and mark the order as delivered. Sync the (offline stored) orders to the api as soon as internet is available again.
Feature Specification: Table Service Integration
App: drinks.catlab.eu
Role: Waiter-operated POS / Table Management
Status: Ready for Development
1. Objective
Implement a "Table Service" mode for the existing POS application, allowing waiters to take orders directly at tables via their mobile devices. This requires significant refactoring to introduce
TableandPatronmodels, separate fulfillment from payment states, and update the order routing logic between the Bar POS and Waiter POS.2. Database & Model Refactoring
2.1. Tables Model
Hierarchy: Tables belong directly to an
Event. Each event starts with zero tables.Properties:
id,event_id,table_number(integer),name(localized string, e.g., "Table 1").Deletions: Must utilize soft-deletion (
deleted_at).Generation Utility: Need an admin function to bulk-generate X tables.
Logic: It must query the highest current active (non-soft-deleted)
table_numberand increment intelligently to prevent duplicates.Renaming: Single tables must be easily renameable by event admins.
=> If a remote order arrives with an unknown table number, create that table.
2.2. Patron Model
Event. AnOrderbelongsToaPatron.id,event_id,name(optional, primarily used by quiz software/remote name entry).2.3. Order Status Split
The
Ordermodel must be refactored to separate the physical delivery of the drink from the financial settlement of the tab.status):pending->prepared->delivered. (Note: 'processed' is being renamed to 'delivered')payment_status):unpaid,paid,voided.=> Orders from the 'live' sales are always immediately delivered.
2.4 event.allow_unpaid_orders
Create a new field allow_unpaid_table_orders that determines if waiter can open a 'tab'.
3. Core Logic: Patron & Order Assignment
When a new order is received, the system must determine which
Patrongroup owns it based on the following algorithm:nameis provided, search for an existing Patron with that name who has placed an order within the last X hours (duration configurable).allow_unpaid_online_ordersistrueor if some kind of payment system is configured (currently only: a valid card alias is provided)4. User Interfaces & Workflows
4.1. The Bar POS (Remote Orders Interface)
prepared(ordelivered, depending on how the bar treats it locally, but it drops off their active screen).4.2. The Waiter POS (Table Service Mode)
Device Configuration: POS can be toggled into "Table Service" mode.
Dashboard: Displays a list of all tables in the event + a "No Table" option.
Table Interaction:
Clicking a Table shows active Patrons assigned to it.
Includes a 1-click "Create New Patron" button (creates an anonymous Patron linked to the table).
"No Table" Interaction: Shows a list of Patrons not linked to any table. Waiters can create unlinked Patrons here.
Patron View:
Shows outstanding balance (sum of unpaid orders).
Shows history of previous orders.
Provides the interface to place a new order (mirroring the Live Sales layout).
Waiter Order Management Queue:
Shows a list of all
pendingorpreparedorders.Filters: Toggle to show only orders created by this specific POS device; Toggle to show only
preparedorders.Actions: Mark as
delivered, or mark asvoided(error correction).4.3. Checkout & Payment Flow
delivered(or initiates payment), the standard payment dialog appears (Cash, Card, etc.).allow_unpaid_table_ordersis true, the waiter can select "Pay Later", leaving thepayment_statusasunpaidwhile the fulfillment status becomesdelivered.paid. (Partial payments are strictly out-of-scope for this iteration).General considerations
=> As with all other aspects of the app, the table service part must be completely functional offline. Bar preparations will obviously not be possible, but the waiter must be able to walk to the bar themselves, prepare the order, return and mark the order as delivered. Sync the (offline stored) orders to the api as soon as internet is available again.