214 lines
4.8 KiB
Dart
214 lines
4.8 KiB
Dart
import 'package:drift/drift.dart';
|
|
import 'package:uuid/uuid.dart';
|
|
|
|
import '../database/app_database.dart';
|
|
import '../models/bar_tab.dart';
|
|
import '../models/product.dart';
|
|
import '../models/tab_item.dart';
|
|
|
|
abstract class BarTabService {
|
|
Future<List<BarTab>> getOpenTabs();
|
|
|
|
Future<BarTab?> getTabById(String id);
|
|
|
|
Future<BarTab> createTab({
|
|
required String customerName,
|
|
});
|
|
|
|
Future<void> addProductToTab({
|
|
required String tabId,
|
|
required Product product,
|
|
});
|
|
|
|
Future<void> updateTabItemQuantity({
|
|
required String tabItemId,
|
|
required int quantity,
|
|
});
|
|
|
|
Future<void> closeTab(String tabId);
|
|
}
|
|
|
|
class DriftBarTabService implements BarTabService {
|
|
final AppDatabase database;
|
|
final _uuid = const Uuid();
|
|
|
|
DriftBarTabService({
|
|
required this.database,
|
|
});
|
|
|
|
TabItem _mapItemRow(TabItemRow row) {
|
|
return TabItem(
|
|
id: row.id,
|
|
tabId: row.tabId,
|
|
productId: row.productId,
|
|
productName: row.productName,
|
|
quantity: row.quantity,
|
|
unitPriceInCents: row.unitPriceInCents,
|
|
);
|
|
}
|
|
|
|
BarTab _mapTabRow(
|
|
BarTabRow row,
|
|
List<TabItem> items,
|
|
) {
|
|
return BarTab(
|
|
id: row.id,
|
|
customerName: row.customerName,
|
|
status: row.status,
|
|
openedAt: row.openedAt,
|
|
closedAt: row.closedAt,
|
|
items: items,
|
|
);
|
|
}
|
|
|
|
Future<List<TabItem>> _getItemsForTab(String tabId) async {
|
|
final query = database.select(database.tabItems)
|
|
..where((item) => item.tabId.equals(tabId))
|
|
..orderBy([
|
|
(item) => OrderingTerm.asc(item.createdAt),
|
|
]);
|
|
|
|
final rows = await query.get();
|
|
|
|
return rows.map(_mapItemRow).toList();
|
|
}
|
|
|
|
@override
|
|
Future<List<BarTab>> getOpenTabs() async {
|
|
final query = database.select(database.barTabs)
|
|
..where((tab) => tab.status.equals('open'))
|
|
..orderBy([
|
|
(tab) => OrderingTerm.desc(tab.openedAt),
|
|
]);
|
|
|
|
final tabRows = await query.get();
|
|
|
|
final tabs = <BarTab>[];
|
|
|
|
for (final tabRow in tabRows) {
|
|
final items = await _getItemsForTab(tabRow.id);
|
|
|
|
tabs.add(_mapTabRow(tabRow, items));
|
|
}
|
|
|
|
return tabs;
|
|
}
|
|
|
|
@override
|
|
Future<BarTab?> getTabById(String id) async {
|
|
final query = database.select(database.barTabs)
|
|
..where((tab) => tab.id.equals(id));
|
|
|
|
final tabRow = await query.getSingleOrNull();
|
|
|
|
if (tabRow == null) {
|
|
return null;
|
|
}
|
|
|
|
final items = await _getItemsForTab(tabRow.id);
|
|
|
|
return _mapTabRow(tabRow, items);
|
|
}
|
|
|
|
@override
|
|
Future<BarTab> createTab({
|
|
required String customerName,
|
|
}) async {
|
|
final id = _uuid.v4();
|
|
|
|
await database.into(database.barTabs).insert(
|
|
BarTabsCompanion.insert(
|
|
id: id,
|
|
customerName: customerName,
|
|
status: const Value('open'),
|
|
openedAt: DateTime.now(),
|
|
),
|
|
);
|
|
|
|
final tab = await getTabById(id);
|
|
|
|
if (tab == null) {
|
|
throw Exception('Could not create tab.');
|
|
}
|
|
|
|
return tab;
|
|
}
|
|
|
|
@override
|
|
Future<void> addProductToTab({
|
|
required String tabId,
|
|
required Product product,
|
|
}) async {
|
|
await database.transaction(() async {
|
|
final existingItemQuery = database.select(database.tabItems)
|
|
..where(
|
|
(item) =>
|
|
item.tabId.equals(tabId) &
|
|
item.productId.equals(product.id),
|
|
);
|
|
|
|
final existingItem = await existingItemQuery.getSingleOrNull();
|
|
|
|
if (existingItem != null) {
|
|
final updateQuery = database.update(database.tabItems)
|
|
..where((item) => item.id.equals(existingItem.id));
|
|
|
|
await updateQuery.write(
|
|
TabItemsCompanion(
|
|
quantity: Value(existingItem.quantity + 1),
|
|
),
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
await database.into(database.tabItems).insert(
|
|
TabItemsCompanion.insert(
|
|
id: _uuid.v4(),
|
|
tabId: tabId,
|
|
productId: product.id,
|
|
productName: product.name,
|
|
quantity: 1,
|
|
unitPriceInCents: product.priceInCents,
|
|
createdAt: DateTime.now(),
|
|
),
|
|
);
|
|
});
|
|
}
|
|
|
|
@override
|
|
Future<void> updateTabItemQuantity({
|
|
required String tabItemId,
|
|
required int quantity,
|
|
}) async {
|
|
if (quantity <= 0) {
|
|
final deleteQuery = database.delete(database.tabItems)
|
|
..where((item) => item.id.equals(tabItemId));
|
|
|
|
await deleteQuery.go();
|
|
return;
|
|
}
|
|
|
|
final updateQuery = database.update(database.tabItems)
|
|
..where((item) => item.id.equals(tabItemId));
|
|
|
|
await updateQuery.write(
|
|
TabItemsCompanion(
|
|
quantity: Value(quantity),
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<void> closeTab(String tabId) async {
|
|
final updateQuery = database.update(database.barTabs)
|
|
..where((tab) => tab.id.equals(tabId));
|
|
|
|
await updateQuery.write(
|
|
BarTabsCompanion(
|
|
status: const Value('closed'),
|
|
closedAt: Value(DateTime.now()),
|
|
),
|
|
);
|
|
}
|
|
} |