feat: New Open Tab dialog with search and optional customer email. Drinks are now grouped per order. Payments trigger cha-ching and money rain.

This commit is contained in:
2026-10-28 02:11:32 +01:00
parent 1aee0541c4
commit 29ceb51177
41 changed files with 2771 additions and 812 deletions
+22 -3
View File
@@ -47,6 +47,10 @@ class TabEvent {
const TabEvent({required this.id, required this.payload});
}
/// The order a removal takes drinks off: `orderId`, or (when null) the
/// drinks rung up before orders were tracked.
typedef OrderRef = ({String? orderId});
/// One settled line in a `settled` event.
typedef SettledLine = ({
String productId,
@@ -66,12 +70,16 @@ class TabEventFactory {
required String tabId,
required String customerName,
required DateTime openedAt,
String? email,
}) {
return _event(
TabEventType.tabOpened,
tabId: tabId,
customerName: customerName,
fields: {'openedAt': openedAt.toUtc().toIso8601String()},
fields: {
'openedAt': openedAt.toUtc().toIso8601String(),
'email': ?email,
},
);
}
@@ -96,7 +104,8 @@ class TabEventFactory {
}
/// [quantity] is how many pieces were added; always positive. [lineId] is
/// the local line, so the server can keep its id.
/// the local line, so the server can keep its id. [orderId] is the order
/// they are part of.
TabEvent lineAdded({
required String tabId,
required String customerName,
@@ -105,6 +114,7 @@ class TabEventFactory {
required String productName,
required int unitPriceInCents,
required int quantity,
required String? orderId,
}) {
return _lineEvent(
TabEventType.lineAdded,
@@ -115,10 +125,13 @@ class TabEventFactory {
productName: productName,
unitPriceInCents: unitPriceInCents,
quantity: quantity,
order: (orderId: orderId),
);
}
/// [quantity] is how many pieces were removed; always positive.
/// [quantity] is how many pieces were removed; always positive. With
/// [order] they are taken off that order only; without, the latest drinks
/// of the line (as before orders).
TabEvent lineRemoved({
required String tabId,
required String customerName,
@@ -127,6 +140,7 @@ class TabEventFactory {
required String productName,
required int unitPriceInCents,
required int quantity,
OrderRef? order,
}) {
return _lineEvent(
TabEventType.lineRemoved,
@@ -137,6 +151,7 @@ class TabEventFactory {
productName: productName,
unitPriceInCents: unitPriceInCents,
quantity: quantity,
order: order,
);
}
@@ -246,6 +261,7 @@ class TabEventFactory {
required String productName,
required int unitPriceInCents,
required int quantity,
required OrderRef? order,
}) {
if (quantity < 1) {
throw ArgumentError.value(quantity, 'quantity', 'Must be at least 1');
@@ -263,6 +279,9 @@ class TabEventFactory {
'productName': productName,
'unitPriceInCents': unitPriceInCents,
'quantity': quantity,
// Also when null: a removal then only takes drinks without an order,
// where a removal without `orderId` takes the latest of the line
if (order != null) 'orderId': order.orderId,
},
);
}