Mixed Postpaid and Prepaid Lines
A table session may carry both waiter-entered postpaid lines and customer-submitted prepaid lines on the same POS check. Lines added by the waiter before the customer scans appear in the initial snapshot. Lines added by the waiter after the scan arrive as TableOrderSnapshotChanged(POS_LINE_ADDED) alongside any customer-submitted prepaid items, until ORDER_CLOSED.
Two composition variants built from the existing table, prepaid, and postpaid-bill messages cover the design space. The POS does not branch on which variant the app follows; both are valid concurrent paths against the same open table session.
Whole-table settlement
This variant applies when the customer's checkout intent is "pay everything now, including the waiter-added lines". It produces one OpenApp payment and one POS-facing payment record.
- OpenApp sends
OrderSubmissionRequested(orderContext=TABLE, items=[customer-added])withoutpayment. The customer-added items are submitted postpaid and join the open check alongside the waiter lines. - OpenApp sends
BillPreparationRequested(orderContext=TABLE, checkpoint)with noitemssubset. The POS returns a full bill covering both the customer-added and waiter-added lines. - OpenApp executes the customer payment for the full total.
- OpenApp sends
BillPaymentCompleted(posBillId, payment). The POS records the payment and pushesTableOrderSnapshotChanged(ORDER_CLOSED)per Postpaid Bill Payment.
Customer-item prepayment with separate residual settlement
This variant applies when the customer's intent is "prepay what I added now" - either standalone, with the remaining lines left for the waiter.
- OpenApp sends
OrderSubmissionRequested(orderContext=TABLE, items=[customer-added], payment)with the prepaid customer payment for the customer-added items. The POS accepts the items and returns the receipt inline. The prepaid submission mechanics are described in Prepaid Ordering. - In the optional or deferred manual residual step, OpenApp sends
BillPreparationRequested(orderContext=TABLE, items=[waiter-line-refs])for the residual subset, thenBillPaymentCompleted(posBillId, payment)after the customer pays the residual. If this step is skipped, the waiter handles the residual physically.
If the residual step fails after the prepaid step succeeded, OpenApp refunds only the residual portion; the customer-added items remain paid and attached to the check.