MIF_E31232435/lib/screens/transaction/transaction_controller.dart

261 lines
6.6 KiB
Dart

import 'package:finalproject/models/transaction_model.dart';
import 'package:finalproject/services/ml_service.dart';
import 'package:flutter/material.dart';
class CartItem {
final int productId;
final String productName;
final String category;
final int unitPrice;
int quantity;
CartItem({
required this.productId,
required this.productName,
required this.category,
required this.unitPrice,
required this.quantity,
});
int get totalPrice => unitPrice * quantity;
}
class TransactionController extends ChangeNotifier {
final quantityController = TextEditingController();
DateTime? selectedDate = DateTime.now();
bool isLoading = false;
int selectedIndex = 2;
final List<String> products = [];
final Map<String, int> productIds = {};
final Map<String, String> productCategories = {};
final Map<String, String> productUnits = {};
final Map<String, int> productPrices = {};
final List<String> categories = [];
String? selectedProduct;
final List<CartItem> cartItems = [];
final List<Transaction> transactions = [];
Future<void> loadProducts() async {
final fetchedProducts = await MLService.getProducts();
products.clear();
productIds.clear();
productCategories.clear();
productUnits.clear();
productPrices.clear();
categories.clear();
for (final product in fetchedProducts) {
final id = product['id'] ?? 0;
final name = product['name'] ?? '';
final category = product['category'] ?? '';
final unit = product['unit'] ?? _defaultUnitFromCategory(category);
final price = product['price'] ?? 0;
if (name.isNotEmpty && id > 0) {
products.add(name);
productIds[name] = id;
productCategories[name] = category;
productUnits[name] = unit;
productPrices[name] = price;
if (!categories.contains(category)) {
categories.add(category);
}
}
}
notifyListeners();
}
void setSelectedProduct(String? value) {
selectedProduct = value;
notifyListeners();
}
void setSelectedDate(DateTime value) {
selectedDate = value;
notifyListeners();
}
void setSelectedIndex(int index) {
selectedIndex = index;
notifyListeners();
}
String? addToCart() {
if (selectedProduct == null || quantityController.text.isEmpty) {
return 'Pilih produk dan masukkan jumlah';
}
final quantity = int.tryParse(quantityController.text) ?? 0;
if (quantity <= 0) {
return 'Jumlah harus lebih dari 0';
}
final existingIndex = cartItems.indexWhere(
(item) => item.productName == selectedProduct,
);
if (existingIndex >= 0) {
cartItems[existingIndex].quantity += quantity;
} else {
cartItems.add(
CartItem(
productId: productIds[selectedProduct!] ?? 0,
productName: selectedProduct!,
category: productCategories[selectedProduct!]!,
unitPrice: productPrices[selectedProduct!]!,
quantity: quantity,
),
);
}
quantityController.clear();
notifyListeners();
return null;
}
void removeFromCart(int index) {
cartItems.removeAt(index);
notifyListeners();
}
void updateQuantity(int index, int newQuantity) {
if (newQuantity <= 0) {
removeFromCart(index);
return;
}
cartItems[index].quantity = newQuantity;
notifyListeners();
}
void clearCart() {
cartItems.clear();
notifyListeners();
}
int get totalPrice =>
cartItems.fold(0, (total, item) => total + item.totalPrice);
Future<Map<String, dynamic>> submitAllTransactions() async {
if (cartItems.isEmpty) {
return {'status': 'error', 'message': 'Keranjang kosong'};
}
isLoading = true;
notifyListeners();
try {
final date = selectedDate ?? DateTime.now();
final dateStr =
'${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
int successCount = 0;
String? firstError;
final originalCount = cartItems.length;
for (final item in cartItems) {
final result = await MLService.addTransactionWithStockUpdate(
productId: item.productId,
quantity: item.quantity,
unitPrice: item.unitPrice,
totalPrice: item.totalPrice,
transactionDate: dateStr,
);
if (result['status'] == 'success') {
successCount++;
transactions.insert(
0,
Transaction(
id: transactions.length + 1,
productName: item.productName,
category: item.category,
quantity: item.quantity,
unitPrice: item.unitPrice,
totalPrice: item.totalPrice,
date: date,
),
);
} else {
firstError ??= result['message'] ?? 'Transaksi gagal';
}
}
cartItems.clear();
selectedDate = DateTime.now();
return {
'status': 'success',
'successCount': successCount,
'totalCount': originalCount,
'error': firstError,
};
} catch (e) {
return {'status': 'error', 'message': 'Error: ${e.toString()}'};
} finally {
isLoading = false;
notifyListeners();
}
}
Future<Map<String, dynamic>> createProduct({
required String productName,
required String category,
required int price,
required int initialStock,
required double minStock,
required String unit,
required String productType,
}) async {
if (products.contains(productName)) {
return {'status': 'error', 'message': 'Produk "$productName" sudah ada'};
}
final result = await MLService.createProduct(
name: productName,
category: category,
price: price,
currentStock: initialStock,
minStock: minStock,
unit: unit,
productType: productType,
);
if (result['status'] == 'success') {
final createdProductId = result['product_id'];
products.add(productName);
if (createdProductId is int && createdProductId > 0) {
productIds[productName] = createdProductId;
}
productCategories[productName] = category;
productUnits[productName] = unit;
productPrices[productName] = price;
if (!categories.contains(category)) {
categories.add(category);
}
notifyListeners();
}
return result;
}
@override
void dispose() {
quantityController.dispose();
super.dispose();
}
static String _defaultUnitFromCategory(String category) {
if (category.toLowerCase() == 'barang') {
return 'pcs';
}
return 'kg';
}
}