feat: add historical data
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
import 'payment_method.dart';
|
||||
|
||||
/// Types of [TabEvent] the server understands.
|
||||
enum TabEventType {
|
||||
lineAdded('line_added'),
|
||||
lineRemoved('line_removed'),
|
||||
settled('settled');
|
||||
|
||||
final String value;
|
||||
|
||||
const TabEventType(this.value);
|
||||
}
|
||||
|
||||
/// Something that happened on a tab, reported to the server for sales
|
||||
/// statistics. [payload] is the JSON object that is stored in the outbox and
|
||||
/// sent as is.
|
||||
class TabEvent {
|
||||
final String id;
|
||||
final Map<String, dynamic> payload;
|
||||
|
||||
const TabEvent({required this.id, required this.payload});
|
||||
}
|
||||
|
||||
/// One settled line in a `settled` event.
|
||||
typedef SettledLine = ({
|
||||
String productName,
|
||||
int quantity,
|
||||
int unitPriceInCents,
|
||||
});
|
||||
|
||||
/// Builds the events, so their JSON shape lives in one place.
|
||||
class TabEventFactory {
|
||||
final _uuid = const Uuid();
|
||||
final DateTime Function() _now;
|
||||
|
||||
TabEventFactory({DateTime Function()? now}) : _now = now ?? DateTime.now;
|
||||
|
||||
/// [quantity] is how many pieces were added; always positive.
|
||||
TabEvent lineAdded({
|
||||
required String tabId,
|
||||
required String customerName,
|
||||
required String productName,
|
||||
required int unitPriceInCents,
|
||||
required int quantity,
|
||||
}) {
|
||||
return _lineEvent(
|
||||
TabEventType.lineAdded,
|
||||
tabId: tabId,
|
||||
customerName: customerName,
|
||||
productName: productName,
|
||||
unitPriceInCents: unitPriceInCents,
|
||||
quantity: quantity,
|
||||
);
|
||||
}
|
||||
|
||||
/// [quantity] is how many pieces were removed; always positive.
|
||||
TabEvent lineRemoved({
|
||||
required String tabId,
|
||||
required String customerName,
|
||||
required String productName,
|
||||
required int unitPriceInCents,
|
||||
required int quantity,
|
||||
}) {
|
||||
return _lineEvent(
|
||||
TabEventType.lineRemoved,
|
||||
tabId: tabId,
|
||||
customerName: customerName,
|
||||
productName: productName,
|
||||
unitPriceInCents: unitPriceInCents,
|
||||
quantity: quantity,
|
||||
);
|
||||
}
|
||||
|
||||
TabEvent settled({
|
||||
required String tabId,
|
||||
required String customerName,
|
||||
required int amountInCents,
|
||||
required PaymentMethod paymentMethod,
|
||||
required List<SettledLine> items,
|
||||
String? commandId,
|
||||
}) {
|
||||
return _event(
|
||||
TabEventType.settled,
|
||||
tabId: tabId,
|
||||
customerName: customerName,
|
||||
fields: {
|
||||
'amountInCents': amountInCents,
|
||||
'paymentMethod': paymentMethodValue(paymentMethod),
|
||||
'commandId': ?commandId,
|
||||
'items': [
|
||||
for (final item in items)
|
||||
{
|
||||
'productName': item.productName,
|
||||
'quantity': item.quantity,
|
||||
'unitPriceInCents': item.unitPriceInCents,
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// The server's payment method names: `cash`, `payconiq`,
|
||||
/// `payment_pending` or `other`.
|
||||
static String paymentMethodValue(PaymentMethod method) {
|
||||
return switch (method) {
|
||||
PaymentMethod.cash => 'cash',
|
||||
PaymentMethod.payconiq => 'payconiq',
|
||||
PaymentMethod.paymentPending => 'payment_pending',
|
||||
};
|
||||
}
|
||||
|
||||
TabEvent _lineEvent(
|
||||
TabEventType type, {
|
||||
required String tabId,
|
||||
required String customerName,
|
||||
required String productName,
|
||||
required int unitPriceInCents,
|
||||
required int quantity,
|
||||
}) {
|
||||
if (quantity < 1) {
|
||||
throw ArgumentError.value(quantity, 'quantity', 'Must be at least 1');
|
||||
}
|
||||
|
||||
return _event(
|
||||
type,
|
||||
tabId: tabId,
|
||||
customerName: customerName,
|
||||
fields: {
|
||||
'productName': productName,
|
||||
'unitPriceInCents': unitPriceInCents,
|
||||
'quantity': quantity,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
TabEvent _event(
|
||||
TabEventType type, {
|
||||
required String tabId,
|
||||
required String customerName,
|
||||
required Map<String, dynamic> fields,
|
||||
}) {
|
||||
final id = _uuid.v4();
|
||||
|
||||
return TabEvent(
|
||||
id: id,
|
||||
payload: {
|
||||
'id': id,
|
||||
'type': type.value,
|
||||
'tabId': tabId,
|
||||
'customerName': customerName,
|
||||
'occurredAt': _now().toUtc().toIso8601String(),
|
||||
...fields,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user