71 lines
1.9 KiB
Dart
71 lines
1.9 KiB
Dart
import 'package:drift/drift.dart';
|
|
|
|
import 'app_database.dart';
|
|
|
|
class InsufficientStockException implements Exception {
|
|
const InsufficientStockException();
|
|
|
|
@override
|
|
String toString() => 'Not enough stock';
|
|
}
|
|
|
|
class ProductNotFoundException implements Exception {
|
|
final String productId;
|
|
|
|
const ProductNotFoundException(this.productId);
|
|
|
|
@override
|
|
String toString() => 'Product not found: $productId';
|
|
}
|
|
|
|
/// Atomic stock updates shared by the product and tab services, so they can
|
|
/// run inside either one's transaction.
|
|
extension StockQueries on AppDatabase {
|
|
Future<void> decreaseStock(String productId, int amount) async {
|
|
_validateStockAmount(amount);
|
|
|
|
final updatedRows =
|
|
await (update(products)..where(
|
|
(row) =>
|
|
row.id.equals(productId) &
|
|
row.stockQuantity.isBiggerOrEqualValue(amount),
|
|
))
|
|
.write(
|
|
ProductsCompanion.custom(
|
|
stockQuantity: products.stockQuantity - Variable(amount),
|
|
),
|
|
);
|
|
|
|
if (updatedRows == 1) return;
|
|
|
|
final product = await (select(
|
|
products,
|
|
)..where((row) => row.id.equals(productId))).getSingleOrNull();
|
|
|
|
if (product == null) throw ProductNotFoundException(productId);
|
|
|
|
throw const InsufficientStockException();
|
|
}
|
|
|
|
Future<void> increaseStock(String productId, int amount) async {
|
|
_validateStockAmount(amount);
|
|
|
|
final updatedRows =
|
|
await (update(
|
|
products,
|
|
)..where((row) => row.id.equals(productId))).write(
|
|
ProductsCompanion.custom(
|
|
stockQuantity: products.stockQuantity + Variable(amount),
|
|
),
|
|
);
|
|
|
|
if (updatedRows != 1) throw ProductNotFoundException(productId);
|
|
}
|
|
|
|
void _validateStockAmount(int amount) {
|
|
if (amount <= 0) {
|
|
throw ArgumentError.value(amount, 'amount', 'Must be greater than zero');
|
|
}
|
|
}
|
|
}
|