This commit is contained in:
2026-07-11 17:47:40 +02:00
commit 6587779a58
66 changed files with 7325 additions and 0 deletions
+214
View File
@@ -0,0 +1,214 @@
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()),
),
);
}
}
+121
View File
@@ -0,0 +1,121 @@
import 'package:drift/drift.dart';
import 'package:uuid/uuid.dart';
import '../database/app_database.dart';
import '../models/product.dart';
abstract class ProductService {
Future<List<Product>> getProducts();
Future<Product?> getProductById(String id);
Future<void> createProduct({
required String name,
required String category,
required int stockQuantity,
required int lowStockThreshold,
required int priceInCents,
required String? imagePath,
});
Future<void> updateProduct(Product product);
Future<void> deleteProduct(String id);
}
class DriftProductService implements ProductService {
final AppDatabase database;
final _uuid = const Uuid();
DriftProductService({
required this.database,
});
Product _mapRowToProduct(ProductRow row) {
return Product(
id: row.id,
name: row.name,
category: row.category,
stockQuantity: row.stockQuantity,
lowStockThreshold: row.lowStockThreshold,
priceInCents: row.priceInCents,
imagePath: row.imagePath,
active: row.active,
);
}
@override
Future<List<Product>> getProducts() async {
final query = database.select(database.products)
..where((product) => product.active.equals(true))
..orderBy([
(product) => OrderingTerm.asc(product.name),
]);
final rows = await query.get();
return rows.map(_mapRowToProduct).toList();
}
@override
Future<Product?> getProductById(String id) async {
final query = database.select(database.products)
..where((product) => product.id.equals(id));
final row = await query.getSingleOrNull();
if (row == null) {
return null;
}
return _mapRowToProduct(row);
}
@override
Future<void> createProduct({
required String name,
required String category,
required int stockQuantity,
required int lowStockThreshold,
required int priceInCents,
required String? imagePath,
}) async {
await database.into(database.products).insert(
ProductsCompanion.insert(
id: _uuid.v4(),
name: name,
category: category,
stockQuantity: stockQuantity,
lowStockThreshold: lowStockThreshold,
priceInCents: priceInCents,
imagePath: Value(imagePath),
),
);
}
@override
Future<void> updateProduct(Product product) async {
final query = database.update(database.products)
..where((row) => row.id.equals(product.id));
await query.write(
ProductsCompanion(
name: Value(product.name),
category: Value(product.category),
stockQuantity: Value(product.stockQuantity),
lowStockThreshold: Value(product.lowStockThreshold),
priceInCents: Value(product.priceInCents),
imagePath: Value(product.imagePath),
active: Value(product.active),
),
);
}
@override
Future<void> deleteProduct(String id) async {
final query = database.delete(database.products)
..where((product) => product.id.equals(id));
await query.go();
}
}