first commit
This commit is contained in:
@@ -0,0 +1,259 @@
|
||||
// import 'package:enaklo_pos/core/extensions/int_ext.dart';
|
||||
// import 'package:enaklo_pos/core/extensions/string_ext.dart';
|
||||
// import 'package:enaklo_pos/presentation/home/models/product_quantity.dart';
|
||||
// import 'package:imin_printer/column_maker.dart';
|
||||
// import 'package:imin_printer/enums.dart';
|
||||
// import 'package:imin_printer/imin_printer.dart';
|
||||
// import 'package:imin_printer/imin_style.dart';
|
||||
// import 'package:intl/intl.dart';
|
||||
|
||||
// class LamanPrint {
|
||||
// LamanPrint._init();
|
||||
|
||||
// static final LamanPrint instance = LamanPrint._init();
|
||||
// static IminPrinter? _iminPrinter;
|
||||
|
||||
// static Future init() async {
|
||||
// _iminPrinter = IminPrinter();
|
||||
// await _iminPrinter!.initPrinter();
|
||||
// }
|
||||
|
||||
// Future<void> printOrderV3(
|
||||
// List<ProductQuantity> products,
|
||||
// int totalQuantity,
|
||||
// int totalPrice,
|
||||
// String paymentMethod,
|
||||
// int nominalBayar,
|
||||
// int kembalian,
|
||||
// int subTotal,
|
||||
// int discount,
|
||||
// int pajak,
|
||||
// int serviceCharge,
|
||||
// String namaKasir,
|
||||
// String customerName,
|
||||
// int paper,
|
||||
// ) async {
|
||||
// final iminPrinter = _iminPrinter!;
|
||||
|
||||
// await iminPrinter.printText(
|
||||
// 'Jago Resto',
|
||||
// style: IminTextStyle(align: IminPrintAlign.center, fontSize: 24),
|
||||
// );
|
||||
|
||||
// await iminPrinter.printText(
|
||||
// 'Jl. Kebun Raya No. 1, Sinduhadi, Ngaglik, Sleman',
|
||||
// style: IminTextStyle(align: IminPrintAlign.center, fontSize: 20),
|
||||
// );
|
||||
|
||||
// await iminPrinter.printText(
|
||||
// '------------------------------------------------------',
|
||||
// style: IminTextStyle(align: IminPrintAlign.center, fontSize: 20),
|
||||
// );
|
||||
|
||||
// await iminPrinter.printColumnsText(
|
||||
// cols: [
|
||||
// ColumnMaker(
|
||||
// text: DateFormat('dd MMM yyyy').format(DateTime.now()),
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.left,
|
||||
// ),
|
||||
// ColumnMaker(
|
||||
// text: DateFormat('HH:mm').format(DateTime.now()),
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.right,
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
|
||||
// await iminPrinter.printColumnsText(
|
||||
// cols: [
|
||||
// ColumnMaker(
|
||||
// text: 'Receipt Number',
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.left,
|
||||
// ),
|
||||
// ColumnMaker(
|
||||
// text: 'JF-${DateFormat('yyyyMMddhhmm').format(DateTime.now())}',
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.right,
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
|
||||
// await iminPrinter.printColumnsText(
|
||||
// cols: [
|
||||
// ColumnMaker(
|
||||
// text: 'Kasir',
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.left,
|
||||
// ),
|
||||
// ColumnMaker(
|
||||
// text: namaKasir,
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.right,
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
|
||||
// for (final product in products) {
|
||||
// await iminPrinter.printColumnsText(
|
||||
// cols: [
|
||||
// ColumnMaker(
|
||||
// text: '${product.quantity} x ${product.product.name}',
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.left,
|
||||
// ),
|
||||
// ColumnMaker(
|
||||
// text:
|
||||
// '${product.product.price!.toIntegerFromText * product.quantity}'
|
||||
// .currencyFormatRpV2,
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.right,
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// }
|
||||
|
||||
// // await iminPrinter.printText(
|
||||
// // '--------------------------------',
|
||||
// // style: IminTextStyle(align: IminPrintAlign.center, fontSize: 20),
|
||||
// // );
|
||||
|
||||
// final subTotalPrice = products.fold<int>(
|
||||
// 0,
|
||||
// (previousValue, element) =>
|
||||
// previousValue +
|
||||
// (element.product.price!.toIntegerFromText * element.quantity));
|
||||
|
||||
// await iminPrinter.printColumnsText(
|
||||
// cols: [
|
||||
// ColumnMaker(
|
||||
// text: 'Subtotal $totalQuantity Product',
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.left,
|
||||
// ),
|
||||
// ColumnMaker(
|
||||
// text: subTotalPrice.currencyFormatRpV2,
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.right,
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
|
||||
// await iminPrinter.printColumnsText(
|
||||
// cols: [
|
||||
// ColumnMaker(
|
||||
// text: 'Discount',
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.left,
|
||||
// ),
|
||||
// ColumnMaker(
|
||||
// text: discount.currencyFormatRpV2,
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.right,
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// await iminPrinter.printColumnsText(
|
||||
// cols: [
|
||||
// ColumnMaker(
|
||||
// text: 'Tax PB1 (10%)',
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.left,
|
||||
// ),
|
||||
// ColumnMaker(
|
||||
// text: '${(totalPrice * 0.1).ceil()}'.currencyFormatRpV2,
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.right,
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// await iminPrinter.printColumnsText(
|
||||
// cols: [
|
||||
// ColumnMaker(
|
||||
// text: 'Service Charge(5%)',
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.left,
|
||||
// ),
|
||||
// ColumnMaker(
|
||||
// text: '${(totalPrice * 0.05).ceil()}'.currencyFormatRpV2,
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.right,
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// await iminPrinter.printColumnsText(
|
||||
// cols: [
|
||||
// ColumnMaker(
|
||||
// text: 'Total',
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.left,
|
||||
// ),
|
||||
// ColumnMaker(
|
||||
// text: totalPrice.currencyFormatRpV2,
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.right,
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
|
||||
// await iminPrinter.printColumnsText(
|
||||
// cols: [
|
||||
// ColumnMaker(
|
||||
// text: 'Bayar',
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.left,
|
||||
// ),
|
||||
// ColumnMaker(
|
||||
// text: nominalBayar.currencyFormatRpV2,
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.right,
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// await iminPrinter.printColumnsText(
|
||||
// cols: [
|
||||
// ColumnMaker(
|
||||
// text: 'Kembali',
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.left,
|
||||
// ),
|
||||
// ColumnMaker(
|
||||
// text: kembalian.currencyFormatRpV2,
|
||||
// width: 2,
|
||||
// fontSize: 20,
|
||||
// align: IminPrintAlign.right,
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
|
||||
// await iminPrinter.printText(
|
||||
// 'Terima Kasih',
|
||||
// style: IminTextStyle(align: IminPrintAlign.center, fontSize: 20),
|
||||
// );
|
||||
|
||||
// await iminPrinter.printAndFeedPaper(100);
|
||||
// await iminPrinter.partialCut();
|
||||
// }
|
||||
// }
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,51 @@
|
||||
import 'package:enaklo_pos/data/models/response/auth_response_model.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class AuthLocalDataSource {
|
||||
Future<void> saveAuthData(AuthResponseModel authResponseModel) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('auth_data', authResponseModel.toJson());
|
||||
}
|
||||
|
||||
Future<void> removeAuthData() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove('auth_data');
|
||||
}
|
||||
|
||||
Future<AuthResponseModel> getAuthData() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final authData = prefs.getString('auth_data');
|
||||
|
||||
return AuthResponseModel.fromJson(authData!);
|
||||
}
|
||||
|
||||
Future<bool> isAuthDataExists() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
return prefs.containsKey('auth_data');
|
||||
}
|
||||
|
||||
Future<void> saveMidtransServerKey(String serverKey) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('server_key', serverKey);
|
||||
}
|
||||
|
||||
//get midtrans server key
|
||||
Future<String> getMitransServerKey() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final serverKey = prefs.getString('server_key');
|
||||
return serverKey ?? '';
|
||||
}
|
||||
|
||||
// save size receipt
|
||||
Future<void> saveSizeReceipt(String sizeReceipt) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('size_receipt', sizeReceipt);
|
||||
}
|
||||
|
||||
// get size receipt
|
||||
Future<String> getSizeReceipt() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final sizeReceipt = prefs.getString('size_receipt');
|
||||
return sizeReceipt ?? '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:enaklo_pos/core/constants/variables.dart';
|
||||
import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart';
|
||||
import 'package:enaklo_pos/data/models/response/auth_response_model.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class AuthRemoteDatasource {
|
||||
Future<Either<String, AuthResponseModel>> login(
|
||||
String email, String password) async {
|
||||
final url = Uri.parse('${Variables.baseUrl}/api/login');
|
||||
final response = await http.post(
|
||||
url,
|
||||
body: {
|
||||
'email': email,
|
||||
'password': password,
|
||||
},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return Right(AuthResponseModel.fromJson(response.body));
|
||||
} else {
|
||||
return const Left('Failed to login');
|
||||
}
|
||||
}
|
||||
|
||||
//logout
|
||||
Future<Either<String, bool>> logout() async {
|
||||
final authData = await AuthLocalDataSource().getAuthData();
|
||||
final url = Uri.parse('${Variables.baseUrl}/api/logout');
|
||||
final response = await http.post(
|
||||
url,
|
||||
headers: {
|
||||
'Authorization': 'Bearer ${authData.token}',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return const Right(true);
|
||||
} else {
|
||||
return const Left('Failed to logout');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:enaklo_pos/core/constants/variables.dart';
|
||||
import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart';
|
||||
import 'package:enaklo_pos/data/models/response/category_response_model.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class CategoryRemoteDatasource {
|
||||
Future<Either<String, CategroyResponseModel>> getCategories() async {
|
||||
final authData = await AuthLocalDataSource().getAuthData();
|
||||
final Map<String, String> headers = {
|
||||
'Authorization': 'Bearer ${authData.token}',
|
||||
'Accept': 'application/json',
|
||||
};
|
||||
final response = await http.get(
|
||||
Uri.parse('${Variables.baseUrl}/api/api-categories'),
|
||||
headers: headers);
|
||||
log(response.statusCode.toString());
|
||||
log(response.body);
|
||||
if (response.statusCode == 200) {
|
||||
return right(CategroyResponseModel.fromJson(response.body));
|
||||
} else {
|
||||
return left(response.body);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:enaklo_pos/core/constants/variables.dart';
|
||||
import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart';
|
||||
import 'package:enaklo_pos/data/models/response/discount_response_model.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class DiscountRemoteDatasource {
|
||||
Future<Either<String, DiscountResponseModel>> getDiscounts() async {
|
||||
final url = Uri.parse('${Variables.baseUrl}/api/api-discounts');
|
||||
final authData = await AuthLocalDataSource().getAuthData();
|
||||
final response = await http.get(url, headers: {
|
||||
'Authorization': 'Bearer ${authData.token}',
|
||||
'Accept': 'application/json',
|
||||
});
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return Right(DiscountResponseModel.fromJson(response.body));
|
||||
} else {
|
||||
return const Left('Failed to get discounts');
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<String, bool>> addDiscount(
|
||||
String name,
|
||||
String description,
|
||||
int value,
|
||||
) async {
|
||||
final url = Uri.parse('${Variables.baseUrl}/api/api-discounts');
|
||||
final authData = await AuthLocalDataSource().getAuthData();
|
||||
final response = await http.post(url, headers: {
|
||||
'Authorization': 'Bearer ${authData.token}',
|
||||
'Accept': 'application/json',
|
||||
}, body: {
|
||||
'name': name,
|
||||
'description': description,
|
||||
'value': value.toString(),
|
||||
'type': 'percentage',
|
||||
});
|
||||
|
||||
if (response.statusCode == 201) {
|
||||
return const Right(true);
|
||||
} else {
|
||||
return const Left('Failed to add discount');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart';
|
||||
import 'package:enaklo_pos/data/models/response/qris_response_model.dart';
|
||||
import 'package:enaklo_pos/data/models/response/qris_status_response_model.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class MidtransRemoteDatasource {
|
||||
String generateBasicAuthHeader(String serverKey) {
|
||||
final base64Credentials = base64Encode(utf8.encode('$serverKey:'));
|
||||
final authHeader = 'Basic $base64Credentials';
|
||||
|
||||
return authHeader;
|
||||
}
|
||||
|
||||
Future<QrisResponseModel> generateQRCode(
|
||||
String orderId, int grossAmount) async {
|
||||
final serverKey = await AuthLocalDataSource().getMitransServerKey();
|
||||
final headers = {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': generateBasicAuthHeader(serverKey),
|
||||
};
|
||||
|
||||
final body = jsonEncode({
|
||||
'payment_type': 'gopay',
|
||||
'transaction_details': {
|
||||
'gross_amount': grossAmount,
|
||||
'order_id': orderId,
|
||||
},
|
||||
});
|
||||
|
||||
final response = await http.post(
|
||||
Uri.parse('https://api.midtrans.com/v2/charge'),
|
||||
// Uri.parse('https://api.sandbox.midtrans.com/v2/charge'),
|
||||
|
||||
headers: headers,
|
||||
body: body,
|
||||
);
|
||||
|
||||
log("StatusCode: ${response.statusCode}");
|
||||
log("Body: ${response.body}");
|
||||
|
||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||
return QrisResponseModel.fromJson(response.body);
|
||||
} else {
|
||||
throw Exception('Failed to generate QR Code');
|
||||
}
|
||||
}
|
||||
|
||||
Future<QrisStatusResponseModel> checkPaymentStatus(String orderId) async {
|
||||
final serverKey = await AuthLocalDataSource().getMitransServerKey();
|
||||
final headers = {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': generateBasicAuthHeader(serverKey),
|
||||
};
|
||||
|
||||
final response = await http.get(
|
||||
Uri.parse('https://api.midtrans.com/v2/$orderId/status'),
|
||||
// Uri.parse('https://api.sandbox.midtrans.com/v2/$orderId/status'),
|
||||
headers: headers,
|
||||
);
|
||||
log("StatusCode: ${response.statusCode}");
|
||||
log("Body: ${response.body}");
|
||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||
return QrisStatusResponseModel.fromJson(response.body);
|
||||
} else {
|
||||
throw Exception('Failed to check payment status');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import 'dart:developer';
|
||||
import 'package:enaklo_pos/core/constants/variables.dart';
|
||||
import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart';
|
||||
import 'package:enaklo_pos/data/models/response/item_sales_response_model.dart';
|
||||
import 'package:enaklo_pos/data/models/response/product_sales_response_model.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:dartz/dartz.dart';
|
||||
|
||||
class OrderItemRemoteDatasource {
|
||||
Future<Either<String, ItemSalesResponseModel>> getItemSalesByRangeDate(
|
||||
String stratDate,
|
||||
String endDate,
|
||||
) async {
|
||||
try {
|
||||
final authData = await AuthLocalDataSource().getAuthData();
|
||||
final response = await http.get(
|
||||
Uri.parse(
|
||||
'${Variables.baseUrl}/api/order-item?start_date=$stratDate&end_date=$endDate'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer ${authData.token}',
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
);
|
||||
log("Response: ${response.statusCode}");
|
||||
log("Response: ${response.body}");
|
||||
if (response.statusCode == 200) {
|
||||
return Right(ItemSalesResponseModel.fromJson(response.body));
|
||||
} else {
|
||||
return const Left("Failed Load Data");
|
||||
}
|
||||
} catch (e) {
|
||||
log("Error: $e");
|
||||
return Left("Failed: $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<String, ProductSalesResponseModel>> getProductSalesByRangeDate(
|
||||
String stratDate,
|
||||
String endDate,
|
||||
) async {
|
||||
try {
|
||||
final authData = await AuthLocalDataSource().getAuthData();
|
||||
final response = await http.get(
|
||||
Uri.parse(
|
||||
'${Variables.baseUrl}/api/order-sales?start_date=$stratDate&end_date=$endDate'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer ${authData.token}',
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
);
|
||||
log("Response: ${response.statusCode}");
|
||||
log("Response: ${response.body}");
|
||||
if (response.statusCode == 200) {
|
||||
return Right(ProductSalesResponseModel.fromJson(response.body));
|
||||
} else {
|
||||
return const Left("Failed Load Data");
|
||||
}
|
||||
} catch (e) {
|
||||
log("Error: $e");
|
||||
return Left("Failed: $e");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:enaklo_pos/core/constants/variables.dart';
|
||||
import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart';
|
||||
import 'package:enaklo_pos/data/models/response/order_remote_datasource.dart';
|
||||
import 'package:enaklo_pos/data/models/response/payment_method_response_model.dart';
|
||||
import 'package:enaklo_pos/data/models/response/summary_response_model.dart';
|
||||
import 'package:enaklo_pos/presentation/home/models/order_model.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class OrderRemoteDatasource {
|
||||
//save order to remote server
|
||||
Future<bool> saveOrder(OrderModel orderModel) async {
|
||||
final authData = await AuthLocalDataSource().getAuthData();
|
||||
print("🌐 API CALL: saveOrder");
|
||||
print("📡 URL: ${Variables.baseUrl}/api/save-order");
|
||||
print("🔑 Token: ${authData.token?.substring(0, 20)}...");
|
||||
try {
|
||||
final response = await http.post(
|
||||
Uri.parse('${Variables.baseUrl}/api/save-order'),
|
||||
body: orderModel.toJson(),
|
||||
headers: {
|
||||
'Authorization': 'Bearer ${authData.token}',
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
);
|
||||
|
||||
print("📥 HTTP Status Code: ${response.statusCode}");
|
||||
print("📥 Response Body: ${response.body}");
|
||||
print("📥 Response Headers: ${response.headers}");
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
print("✅ API call successful - Order saved to server");
|
||||
return true;
|
||||
} else {
|
||||
print("❌ API call failed - Status: ${response.statusCode}");
|
||||
print("❌ Error Response: ${response.body}");
|
||||
return false;
|
||||
}
|
||||
} catch (e) {
|
||||
print("💥 API call error: $e");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<String, OrderResponseModel>> getOrderByRangeDate(
|
||||
String stratDate,
|
||||
String endDate,
|
||||
) async {
|
||||
try {
|
||||
final authData = await AuthLocalDataSource().getAuthData();
|
||||
final response = await http.get(
|
||||
Uri.parse(
|
||||
'${Variables.baseUrl}/api/orders?start_date=$stratDate&end_date=$endDate'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer ${authData.token}',
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
);
|
||||
print("📥 HTTP Status Code: ${response.statusCode}");
|
||||
print("📥 Response Body: ${response.body}");
|
||||
print("📥 Response Headers: ${response.headers}");
|
||||
if (response.statusCode == 200) {
|
||||
print("✅ getOrderByRangeDate API call successful");
|
||||
return Right(OrderResponseModel.fromJson(response.body));
|
||||
} else {
|
||||
print("❌ getOrderByRangeDate API call failed - Status: ${response.statusCode}");
|
||||
print("❌ Error Response: ${response.body}");
|
||||
return const Left("Failed Load Data");
|
||||
}
|
||||
} catch (e) {
|
||||
print("💥 getOrderByRangeDate API call error: $e");
|
||||
return Left("Failed: $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<String, SummaryResponseModel>> getSummaryByRangeDate(
|
||||
String stratDate,
|
||||
String endDate,
|
||||
) async {
|
||||
try {
|
||||
final authData = await AuthLocalDataSource().getAuthData();
|
||||
final response = await http.get(
|
||||
Uri.parse(
|
||||
'${Variables.baseUrl}/api/summary?start_date=$stratDate&end_date=$endDate'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer ${authData.token}',
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
);
|
||||
print("📡 URL: ${response.request!.url}");
|
||||
print("📥 HTTP Status Code: ${response.statusCode}");
|
||||
print("📥 Response Body: ${response.body}");
|
||||
print("📥 Response Headers: ${response.headers}");
|
||||
if (response.statusCode == 200) {
|
||||
print("✅ getSummaryByRangeDate API call successful");
|
||||
return Right(SummaryResponseModel.fromJson(response.body));
|
||||
} else {
|
||||
print("❌ getSummaryByRangeDate API call failed - Status: ${response.statusCode}");
|
||||
print("❌ Error Response: ${response.body}");
|
||||
return const Left("Failed Load Data");
|
||||
}
|
||||
} catch (e) {
|
||||
print("💥 getSummaryByRangeDate API call error: $e");
|
||||
return Left("Failed: $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<String, PaymentMethodResponseModel>> getPaymentMethodByRangeDate(
|
||||
String startDate,
|
||||
String endDate,
|
||||
) async {
|
||||
try {
|
||||
final authData = await AuthLocalDataSource().getAuthData();
|
||||
final response = await http.get(
|
||||
Uri.parse(
|
||||
'${Variables.baseUrl}/api/order-paymentmethod?start_date=$startDate&end_date=$endDate'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer ${authData.token}',
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
);
|
||||
print("📥 Payment Method HTTP Status Code: ${response.statusCode}");
|
||||
print("📥 Payment Method Response Body: ${response.body}");
|
||||
print("📥 Payment Method Response Headers: ${response.headers}");
|
||||
if (response.statusCode == 200) {
|
||||
print("✅ getPaymentMethodByRangeDate API call successful");
|
||||
return Right(PaymentMethodResponseModel.fromJson(response.body));
|
||||
} else {
|
||||
print("❌ getPaymentMethodByRangeDate API call failed - Status: ${response.statusCode}");
|
||||
print("❌ Error Response: ${response.body}");
|
||||
return const Left("Failed Load Payment Method Data");
|
||||
}
|
||||
} catch (e) {
|
||||
print("💥 getPaymentMethodByRangeDate API call error: $e");
|
||||
return Left("Failed: $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<String, bool>> addOrderItems(
|
||||
int orderId,
|
||||
List<Map<String, dynamic>> orderItems,
|
||||
) async {
|
||||
try {
|
||||
final authData = await AuthLocalDataSource().getAuthData();
|
||||
final response = await http.post(
|
||||
Uri.parse('${Variables.baseUrl}/api/orders/add-items'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer ${authData.token}',
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: jsonEncode({
|
||||
'order_id': orderId,
|
||||
'order_items': orderItems,
|
||||
}),
|
||||
);
|
||||
|
||||
print("📥 Add Order Items HTTP Status Code: ${response.statusCode}");
|
||||
print("📥 Add Order Items Response Body: ${response.body}");
|
||||
print("📥 Add Order Items Response Headers: ${response.headers}");
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
print("✅ addOrderItems API call successful");
|
||||
return const Right(true);
|
||||
} else {
|
||||
print("❌ addOrderItems API call failed - Status: ${response.statusCode}");
|
||||
print("❌ Error Response: ${response.body}");
|
||||
return Left("Failed to add order items: ${response.body}");
|
||||
}
|
||||
} catch (e) {
|
||||
print("💥 addOrderItems API call error: $e");
|
||||
return Left("Failed: $e");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:enaklo_pos/core/constants/variables.dart';
|
||||
import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart';
|
||||
import 'package:enaklo_pos/data/models/response/payment_methods_response_model.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class PaymentMethodsRemoteDatasource {
|
||||
Future<Either<String, PaymentMethodsResponseModel>> getPaymentMethods() async {
|
||||
try {
|
||||
final authData = await AuthLocalDataSource().getAuthData();
|
||||
final response = await http.get(
|
||||
Uri.parse('${Variables.baseUrl}/api/payment-methods'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer ${authData.token}',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
);
|
||||
|
||||
log("Payment Methods Response Status: ${response.statusCode}");
|
||||
log("Payment Methods Response Body: ${response.body}");
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return Right(PaymentMethodsResponseModel.fromJson(response.body));
|
||||
} else {
|
||||
return const Left('Failed to get payment methods');
|
||||
}
|
||||
} catch (e) {
|
||||
log("Error getting payment methods: $e");
|
||||
return Left('Error: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,613 @@
|
||||
import 'dart:developer';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:enaklo_pos/data/models/response/print_model.dart';
|
||||
import 'package:enaklo_pos/data/models/response/product_response_model.dart';
|
||||
import 'package:enaklo_pos/data/models/response/table_model.dart';
|
||||
import 'package:enaklo_pos/presentation/home/models/order_model.dart';
|
||||
import 'package:enaklo_pos/presentation/table/models/draft_order_item.dart';
|
||||
import 'package:enaklo_pos/presentation/table/models/draft_order_model.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
|
||||
import '../../presentation/home/models/product_quantity.dart';
|
||||
|
||||
class ProductLocalDatasource {
|
||||
ProductLocalDatasource._init();
|
||||
|
||||
static final ProductLocalDatasource instance = ProductLocalDatasource._init();
|
||||
|
||||
final String tableProduct = 'products';
|
||||
final String tableOrder = 'orders';
|
||||
final String tableOrderItem = 'order_items';
|
||||
final String tableManagement = 'table_management';
|
||||
final String tablePrint = 'prints';
|
||||
static Database? _database;
|
||||
|
||||
// "id": 1,
|
||||
// "category_id": 1,
|
||||
// "name": "Mie Ayam",
|
||||
// "description": "Ipsa dolorem impedit dolor. Libero nisi quidem expedita quod mollitia ad. Voluptas ut quia nemo nisi odit fuga. Fugit autem qui ratione laborum eum.",
|
||||
// "image": "https://via.placeholder.com/640x480.png/002200?text=nihil",
|
||||
// "price": "2000.44",
|
||||
// "stock": 94,
|
||||
// "status": 1,
|
||||
// "is_favorite": 1,
|
||||
// "created_at": "2024-02-08T14:30:22.000000Z",
|
||||
// "updated_at": "2024-02-08T15:14:22.000000Z"
|
||||
|
||||
Future<void> _createDb(Database db, int version) async {
|
||||
await db.execute('''
|
||||
CREATE TABLE $tableProduct (
|
||||
id INTEGER PRIMARY KEY,
|
||||
product_id INTEGER,
|
||||
name TEXT,
|
||||
printer_type TEXT,
|
||||
categoryId INTEGER,
|
||||
categoryName TEXT,
|
||||
description TEXT,
|
||||
image TEXT,
|
||||
price TEXT,
|
||||
stock INTEGER,
|
||||
status INTEGER,
|
||||
isFavorite INTEGER,
|
||||
createdAt TEXT,
|
||||
updatedAt TEXT
|
||||
)
|
||||
''');
|
||||
|
||||
await db.execute('''
|
||||
CREATE TABLE $tableOrder (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
payment_amount INTEGER,
|
||||
sub_total INTEGER,
|
||||
tax INTEGER,
|
||||
discount INTEGER,
|
||||
discount_amount INTEGER,
|
||||
service_charge INTEGER,
|
||||
total INTEGER,
|
||||
payment_method TEXT,
|
||||
total_item INTEGER,
|
||||
id_kasir INTEGER,
|
||||
nama_kasir TEXT,
|
||||
transaction_time TEXT,
|
||||
table_number INTEGER,
|
||||
customer_name TEXT,
|
||||
status TEXT,
|
||||
payment_status TEXT,
|
||||
order_type TEXT DEFAULT 'DINE IN',
|
||||
is_sync INTEGER DEFAULT 0
|
||||
)
|
||||
''');
|
||||
|
||||
await db.execute('''
|
||||
CREATE TABLE $tableOrderItem (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
id_order INTEGER,
|
||||
id_product INTEGER,
|
||||
quantity INTEGER,
|
||||
price INTEGER,
|
||||
notes TEXT DEFAULT ''
|
||||
)
|
||||
''');
|
||||
|
||||
await db.execute('''
|
||||
CREATE TABLE $tableManagement (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
table_name Text,
|
||||
start_time Text,
|
||||
order_id INTEGER,
|
||||
payment_amount INTEGER,
|
||||
x_position REAL NOT NULL,
|
||||
y_position REAL NOT NULL,
|
||||
status TEXT
|
||||
)
|
||||
''');
|
||||
|
||||
await db.execute('''
|
||||
CREATE TABLE draft_orders (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
total_item INTEGER,
|
||||
subtotal INTEGER,
|
||||
tax INTEGER,
|
||||
discount INTEGER,
|
||||
discount_amount INTEGER,
|
||||
service_charge INTEGER,
|
||||
total INTEGER,
|
||||
transaction_time TEXT,
|
||||
table_number INTEGER,
|
||||
draft_name TEXT
|
||||
)
|
||||
''');
|
||||
|
||||
await db.execute('''
|
||||
CREATE TABLE draft_order_items (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
id_draft_order INTEGER,
|
||||
id_product INTEGER,
|
||||
quantity INTEGER,
|
||||
price INTEGER
|
||||
)
|
||||
''');
|
||||
|
||||
await db.execute('''
|
||||
CREATE TABLE $tablePrint (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
code TEXT,
|
||||
name TEXT,
|
||||
address TEXT,
|
||||
paper TEXT,
|
||||
type TEXT
|
||||
)
|
||||
''');
|
||||
}
|
||||
|
||||
Future<Database> _initDB(String filePath) async {
|
||||
final dbPath = await getDatabasesPath();
|
||||
final path = dbPath + filePath;
|
||||
|
||||
// Force delete existing database to ensure new schema
|
||||
try {
|
||||
final dbExists = await databaseExists(path);
|
||||
if (dbExists) {
|
||||
log("Deleting existing database to ensure new schema with order_type column");
|
||||
await deleteDatabase(path);
|
||||
}
|
||||
} catch (e) {
|
||||
log("Error deleting database: $e");
|
||||
}
|
||||
|
||||
return await openDatabase(
|
||||
path,
|
||||
version: 2,
|
||||
onCreate: _createDb,
|
||||
onUpgrade: _onUpgrade,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _onUpgrade(Database db, int oldVersion, int newVersion) async {
|
||||
if (oldVersion < 2) {
|
||||
// Add order_type column to orders table if it doesn't exist
|
||||
try {
|
||||
await db.execute('ALTER TABLE $tableOrder ADD COLUMN order_type TEXT DEFAULT "DINE IN"');
|
||||
log("Added order_type column to orders table");
|
||||
} catch (e) {
|
||||
log("order_type column might already exist: $e");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<Database> get database async {
|
||||
if (_database != null) return _database!;
|
||||
_database = await _initDB('dbresto36.db');
|
||||
return _database!;
|
||||
}
|
||||
|
||||
//save order
|
||||
Future<int> saveOrder(OrderModel order) async {
|
||||
final db = await instance.database;
|
||||
|
||||
// Since we're forcing database recreation, order_type column should exist
|
||||
final orderMap = order.toMap(includeOrderType: true);
|
||||
log("Final orderMap for insertion: $orderMap");
|
||||
|
||||
int id = await db.insert(tableOrder, orderMap,
|
||||
conflictAlgorithm: ConflictAlgorithm.replace);
|
||||
|
||||
for (var item in order.orderItems) {
|
||||
log("Item: ${item.toLocalMap(id)}");
|
||||
await db.insert(tableOrderItem, item.toLocalMap(id),
|
||||
conflictAlgorithm: ConflictAlgorithm.replace);
|
||||
}
|
||||
log("Success Order: ${order.toMap()}");
|
||||
return id;
|
||||
}
|
||||
|
||||
//get data order
|
||||
Future<List<OrderModel>> getOrderByIsNotSync() async {
|
||||
final db = await instance.database;
|
||||
final List<Map<String, dynamic>> maps =
|
||||
await db.query(tableOrder, where: 'is_sync = ?', whereArgs: [0]);
|
||||
return List.generate(maps.length, (i) {
|
||||
return OrderModel.fromMap(maps[i]);
|
||||
});
|
||||
}
|
||||
|
||||
Future<List<OrderModel>> getAllOrder(
|
||||
DateTime date,
|
||||
) async {
|
||||
final db = await instance.database;
|
||||
//date to iso8601
|
||||
final dateIso = date.toIso8601String();
|
||||
//get yyyy-MM-dd
|
||||
final dateYYYYMMDD = dateIso.substring(0, 10);
|
||||
// final formattedDate = DateFormat('yyyy-MM-dd').format(date);
|
||||
final List<Map<String, dynamic>> maps = await db.query(
|
||||
tableOrder,
|
||||
where: 'transaction_time like ?',
|
||||
whereArgs: ['$dateYYYYMMDD%'],
|
||||
// where: 'transaction_time BETWEEN ? AND ?',
|
||||
// whereArgs: [
|
||||
// DateFormat.yMd().format(start),
|
||||
// DateFormat.yMd().format(end)
|
||||
// ],
|
||||
);
|
||||
return List.generate(maps.length, (i) {
|
||||
log("Save save OrderModel: ${OrderModel.fromMap(maps[i])}");
|
||||
return OrderModel.fromMap(maps[i]);
|
||||
});
|
||||
}
|
||||
|
||||
//get order item by order id
|
||||
Future<List<ProductQuantity>> getOrderItemByOrderId(int orderId) async {
|
||||
final db = await instance.database;
|
||||
final List<Map<String, dynamic>> maps = await db
|
||||
.query(tableOrderItem, where: 'id_order = ?', whereArgs: [orderId]);
|
||||
return List.generate(maps.length, (i) {
|
||||
log("ProductQuantity: ${ProductQuantity.fromLocalMap(maps[i])}");
|
||||
return ProductQuantity.fromLocalMap(maps[i]);
|
||||
});
|
||||
}
|
||||
|
||||
//update payment status by order id
|
||||
Future<void> updatePaymentStatus(
|
||||
int orderId, String paymentStatus, String status) async {
|
||||
final db = await instance.database;
|
||||
await db.update(
|
||||
tableOrder, {'payment_status': paymentStatus, 'status': status},
|
||||
where: 'id = ?', whereArgs: [orderId]);
|
||||
log('update payment status success | order id: $orderId | payment status: $paymentStatus | status: $status');
|
||||
}
|
||||
|
||||
//update order is sync
|
||||
Future<void> updateOrderIsSync(int orderId) async {
|
||||
final db = await instance.database;
|
||||
await db.update(tableOrder, {'is_sync': 1},
|
||||
where: 'id = ?', whereArgs: [orderId]);
|
||||
}
|
||||
|
||||
//insert data product
|
||||
|
||||
Future<void> insertProduct(Product product) async {
|
||||
log("Product: ${product.toMap()}");
|
||||
final db = await instance.database;
|
||||
await db.insert(tableProduct, product.toMap(),
|
||||
conflictAlgorithm: ConflictAlgorithm.replace);
|
||||
}
|
||||
|
||||
//update product
|
||||
Future<void> updateProduct(Product product) async {
|
||||
log("Update Product: ${product.toMap()}");
|
||||
final db = await instance.database;
|
||||
await db.update(
|
||||
tableProduct,
|
||||
product.toLocalMap(),
|
||||
where: 'product_id = ?',
|
||||
whereArgs: [product.productId],
|
||||
);
|
||||
}
|
||||
|
||||
//insert list of product
|
||||
Future<void> insertProducts(List<Product> products) async {
|
||||
final db = await instance.database;
|
||||
log("Save Products to Local");
|
||||
for (var product in products) {
|
||||
await db.insert(tableProduct, product.toLocalMap(),
|
||||
conflictAlgorithm: ConflictAlgorithm.replace);
|
||||
log('inserted success id: ${product.productId} | name: ${product.name} | price: ${product.price} | Printer Type ${product.printerType}');
|
||||
}
|
||||
}
|
||||
|
||||
//get all products
|
||||
Future<List<Product>> getProducts() async {
|
||||
final db = await instance.database;
|
||||
final List<Map<String, dynamic>> maps = await db.query(tableProduct);
|
||||
return List.generate(maps.length, (i) {
|
||||
return Product.fromLocalMap(maps[i]);
|
||||
});
|
||||
}
|
||||
|
||||
Future<Product?> getProductById(int id) async {
|
||||
final db = await instance.database;
|
||||
final result =
|
||||
await db.query(tableProduct, where: 'product_id = ?', whereArgs: [id]);
|
||||
|
||||
if (result.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Product.fromMap(result.first);
|
||||
}
|
||||
|
||||
// get Last Table Management
|
||||
|
||||
Future<TableModel?> getLastTableManagement() async {
|
||||
final db = await instance.database;
|
||||
final List<Map<String, dynamic>> maps =
|
||||
await db.query(tableManagement, orderBy: 'id DESC', limit: 1);
|
||||
if (maps.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
return TableModel.fromMap(maps[0]);
|
||||
}
|
||||
|
||||
// generate table managent with count
|
||||
Future<void> createTableManagement(String tableName, Offset position) async {
|
||||
final db = await instance.database;
|
||||
TableModel newTable = TableModel(
|
||||
tableName: tableName,
|
||||
status: 'available',
|
||||
orderId: 0,
|
||||
paymentAmount: 0,
|
||||
startTime: DateTime.now().toIso8601String(),
|
||||
position: position,
|
||||
);
|
||||
await db.insert(
|
||||
tableManagement,
|
||||
newTable.toMap(),
|
||||
);
|
||||
}
|
||||
|
||||
// change position table
|
||||
Future<void> changePositionTable(int id, Offset position) async {
|
||||
final db = await instance.database;
|
||||
await db.update(
|
||||
tableManagement,
|
||||
{'x_position': position.dx, 'y_position': position.dy},
|
||||
where: 'id = ?',
|
||||
whereArgs: [id],
|
||||
);
|
||||
}
|
||||
|
||||
// update table
|
||||
Future<void> updateTable(TableModel table) async {
|
||||
final db = await instance.database;
|
||||
await db.update(
|
||||
tableManagement,
|
||||
table.toMap(),
|
||||
where: 'id = ?',
|
||||
whereArgs: [table.id],
|
||||
);
|
||||
}
|
||||
|
||||
// get all table
|
||||
Future<List<TableModel>> getAllTable() async {
|
||||
final db = await instance.database;
|
||||
final List<Map<String, dynamic>> maps = await db.query(tableManagement);
|
||||
log("Table Management: $maps");
|
||||
return List.generate(maps.length, (i) {
|
||||
return TableModel.fromMap(maps[i]);
|
||||
});
|
||||
}
|
||||
|
||||
// get last order where table number
|
||||
Future<OrderModel?> getLastOrderTable(int tableNumber) async {
|
||||
final db = await instance.database;
|
||||
final List<Map<String, dynamic>> maps = await db.query(
|
||||
tableOrder,
|
||||
where: 'table_number = ?',
|
||||
whereArgs: [tableNumber],
|
||||
orderBy: 'id DESC', // Urutkan berdasarkan id dari yang terbesar (terbaru)
|
||||
limit: 1, // Ambil hanya satu data terakhir
|
||||
);
|
||||
|
||||
if (maps.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return OrderModel.fromMap(maps[0]);
|
||||
}
|
||||
|
||||
// get table by status
|
||||
Future<List<TableModel>> getTableByStatus(String status) async {
|
||||
final db = await instance.database;
|
||||
List<Map<String, dynamic>> maps;
|
||||
|
||||
if (status == 'all') {
|
||||
// Get all tables
|
||||
maps = await db.query(tableManagement);
|
||||
log("Getting all tables, found: ${maps.length}");
|
||||
|
||||
// If no tables exist, create some default tables
|
||||
if (maps.isEmpty) {
|
||||
log("No tables found, creating default tables...");
|
||||
await _createDefaultTables();
|
||||
maps = await db.query(tableManagement);
|
||||
log("After creating default tables, found: ${maps.length}");
|
||||
}
|
||||
} else {
|
||||
// Get tables by specific status
|
||||
maps = await db.query(
|
||||
tableManagement,
|
||||
where: 'status = ?',
|
||||
whereArgs: [status],
|
||||
);
|
||||
log("Getting tables with status '$status', found: ${maps.length}");
|
||||
}
|
||||
|
||||
final tables = List.generate(maps.length, (i) {
|
||||
return TableModel.fromMap(maps[i]);
|
||||
});
|
||||
|
||||
log("Returning ${tables.length} tables");
|
||||
tables.forEach((table) {
|
||||
log("Table: ${table.tableName} (ID: ${table.id}, Status: ${table.status})");
|
||||
});
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
// Create default tables if none exist
|
||||
Future<void> _createDefaultTables() async {
|
||||
final db = await instance.database;
|
||||
|
||||
// Create 5 default tables
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
await db.insert(tableManagement, {
|
||||
'table_name': 'Table $i',
|
||||
'start_time': DateTime.now().toIso8601String(),
|
||||
'order_id': 0,
|
||||
'payment_amount': 0,
|
||||
'x_position': 100.0 + (i * 50.0),
|
||||
'y_position': 100.0 + (i * 50.0),
|
||||
'status': 'available',
|
||||
});
|
||||
log("Created default table: Table $i");
|
||||
}
|
||||
}
|
||||
|
||||
// update status tabel
|
||||
Future<void> updateStatusTable(TableModel table) async {
|
||||
log("Updating table status: ${table.toMap()}");
|
||||
final db = await instance.database;
|
||||
await db.update(tableManagement, table.toMap(),
|
||||
where: 'id = ?', whereArgs: [table.id]);
|
||||
log("Success Update Status Table: ${table.toMap()}");
|
||||
|
||||
// Verify the update
|
||||
final updatedTable = await db.query(
|
||||
tableManagement,
|
||||
where: 'id = ?',
|
||||
whereArgs: [table.id],
|
||||
);
|
||||
if (updatedTable.isNotEmpty) {
|
||||
log("Verified table update: ${updatedTable.first}");
|
||||
}
|
||||
}
|
||||
|
||||
// Debug method to reset all tables to available status
|
||||
Future<void> resetAllTablesToAvailable() async {
|
||||
log("Resetting all tables to available status...");
|
||||
final db = await instance.database;
|
||||
await db.update(
|
||||
tableManagement,
|
||||
{
|
||||
'status': 'available',
|
||||
'order_id': 0,
|
||||
'payment_amount': 0,
|
||||
'start_time': DateTime.now().toIso8601String(),
|
||||
},
|
||||
);
|
||||
log("All tables reset to available status");
|
||||
}
|
||||
|
||||
//delete all products
|
||||
Future<void> deleteAllProducts() async {
|
||||
final db = await instance.database;
|
||||
await db.delete(tableProduct);
|
||||
}
|
||||
|
||||
Future<int> saveDraftOrder(DraftOrderModel order) async {
|
||||
log("save draft order: ${order.toMapForLocal()}");
|
||||
final db = await instance.database;
|
||||
int id = await db.insert('draft_orders', order.toMapForLocal());
|
||||
log("draft order id: $id | ${order.discountAmount}");
|
||||
for (var orderItem in order.orders) {
|
||||
await db.insert('draft_order_items', orderItem.toMapForLocal(id));
|
||||
log("draft order item ${orderItem.toMapForLocal(id)}");
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
//get all draft order
|
||||
Future<List<DraftOrderModel>> getAllDraftOrder() async {
|
||||
final db = await instance.database;
|
||||
final result = await db.query('draft_orders', orderBy: 'id ASC');
|
||||
|
||||
List<DraftOrderModel> results = await Future.wait(result.map((item) async {
|
||||
// Your asynchronous operation here
|
||||
final draftOrderItem =
|
||||
await getDraftOrderItemByOrderId(item['id'] as int);
|
||||
return DraftOrderModel.newFromLocalMap(item, draftOrderItem);
|
||||
}));
|
||||
return results;
|
||||
}
|
||||
|
||||
// get Darft Order by id
|
||||
Future<DraftOrderModel?> getDraftOrderById(int id) async {
|
||||
final db = await instance.database;
|
||||
final result =
|
||||
await db.query('draft_orders', where: 'id = ?', whereArgs: [id]);
|
||||
if (result.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
final draftOrderItem =
|
||||
await getDraftOrderItemByOrderId(result.first['id'] as int);
|
||||
log("draft order item: $draftOrderItem | ${result.first.toString()}");
|
||||
return DraftOrderModel.newFromLocalMap(result.first, draftOrderItem);
|
||||
}
|
||||
|
||||
//get draft order item by id order
|
||||
Future<List<DraftOrderItem>> getDraftOrderItemByOrderId(int idOrder) async {
|
||||
final db = await instance.database;
|
||||
final result =
|
||||
await db.query('draft_order_items', where: 'id_draft_order = $idOrder');
|
||||
|
||||
List<DraftOrderItem> results = await Future.wait(result.map((item) async {
|
||||
// Your asynchronous operation here
|
||||
final product = await getProductById(item['id_product'] as int);
|
||||
return DraftOrderItem(
|
||||
product: product!, quantity: item['quantity'] as int);
|
||||
}));
|
||||
return results;
|
||||
}
|
||||
|
||||
//remove draft order by id
|
||||
Future<void> removeDraftOrderById(int id) async {
|
||||
final db = await instance.database;
|
||||
await db.delete('draft_orders', where: 'id = ?', whereArgs: [id]);
|
||||
await db.delete('draft_order_items',
|
||||
where: 'id_draft_order = ?', whereArgs: [id]);
|
||||
}
|
||||
|
||||
//update draft order
|
||||
Future<void> updateDraftOrder(DraftOrderModel draftOrder) async {
|
||||
final db = await instance.database;
|
||||
|
||||
// Update the draft order
|
||||
await db.update(
|
||||
'draft_orders',
|
||||
draftOrder.toMapForLocal(),
|
||||
where: 'id = ?',
|
||||
whereArgs: [draftOrder.id],
|
||||
);
|
||||
|
||||
// Remove existing items and add new ones
|
||||
await db.delete('draft_order_items',
|
||||
where: 'id_draft_order = ?', whereArgs: [draftOrder.id]);
|
||||
|
||||
for (var orderItem in draftOrder.orders) {
|
||||
await db.insert('draft_order_items', orderItem.toMapForLocal(draftOrder.id!));
|
||||
}
|
||||
}
|
||||
|
||||
/// create printer
|
||||
Future<void> createPrinter(PrintModel print) async {
|
||||
final db = await instance.database;
|
||||
await db.insert(tablePrint, print.toMap());
|
||||
}
|
||||
|
||||
Future<void> updatePrinter(PrintModel print, int id) async {
|
||||
final db = await instance.database;
|
||||
log("Update Printer: ${print.toMap()} | id: $id");
|
||||
await db
|
||||
.update(tablePrint, print.toMap(), where: 'id = ?', whereArgs: [id]);
|
||||
}
|
||||
|
||||
Future<void> deletePrinter(int id) async {
|
||||
final db = await instance.database;
|
||||
await db.delete(tablePrint, where: 'id = ?', whereArgs: [id]);
|
||||
}
|
||||
|
||||
// get printer by code
|
||||
Future<PrintModel?> getPrinterByCode(String code) async {
|
||||
final db = await instance.database;
|
||||
final result =
|
||||
await db.query(tablePrint, where: 'code = ?', whereArgs: [code]);
|
||||
if (result.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
return PrintModel.fromMap(result.first);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:enaklo_pos/data/models/request/product_request_model.dart';
|
||||
import 'package:enaklo_pos/data/models/response/add_product_response_model.dart';
|
||||
import 'package:enaklo_pos/data/models/response/product_response_model.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import '../../core/constants/variables.dart';
|
||||
import 'auth_local_datasource.dart';
|
||||
|
||||
class ProductRemoteDatasource {
|
||||
Future<Either<String, ProductResponseModel>> getProducts() async {
|
||||
final url = Uri.parse('${Variables.baseUrl}/api/products');
|
||||
final authData = await AuthLocalDataSource().getAuthData();
|
||||
final response = await http.get(url, headers: {
|
||||
'Authorization': 'Bearer ${authData.token}',
|
||||
'Accept': 'application/json',
|
||||
});
|
||||
log("Status Code: ${response.statusCode}");
|
||||
log("Body: ${response.body}");
|
||||
if (response.statusCode == 200) {
|
||||
return Right(ProductResponseModel.fromJson(response.body));
|
||||
} else {
|
||||
return const Left('Failed to get products');
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<String, AddProductResponseModel>> addProduct(
|
||||
ProductRequestModel productRequestModel) async {
|
||||
final authData = await AuthLocalDataSource().getAuthData();
|
||||
final Map<String, String> headers = {
|
||||
'Authorization': 'Bearer ${authData.token}',
|
||||
};
|
||||
var request = http.MultipartRequest(
|
||||
'POST', Uri.parse('${Variables.baseUrl}/api/products'));
|
||||
request.fields.addAll(productRequestModel.toMap());
|
||||
request.files.add(await http.MultipartFile.fromPath(
|
||||
'image', productRequestModel.image!.path));
|
||||
request.headers.addAll(headers);
|
||||
|
||||
http.StreamedResponse response = await request.send();
|
||||
|
||||
final String body = await response.stream.bytesToString();
|
||||
log(response.stream.toString());
|
||||
log(response.statusCode.toString());
|
||||
if (response.statusCode == 201) {
|
||||
return right(AddProductResponseModel.fromJson(body));
|
||||
} else {
|
||||
return left(body);
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<String, AddProductResponseModel>> updateProduct(
|
||||
ProductRequestModel productRequestModel) async {
|
||||
final authData = await AuthLocalDataSource().getAuthData();
|
||||
final Map<String, String> headers = {
|
||||
'Authorization': 'Bearer ${authData.token}',
|
||||
};
|
||||
|
||||
log("Update Product Request Data: ${productRequestModel.toMap()}");
|
||||
log("Update Product ID: ${productRequestModel.id}");
|
||||
log("Update Product Name: ${productRequestModel.name}");
|
||||
log("Update Product Price: ${productRequestModel.price}");
|
||||
log("Update Product Stock: ${productRequestModel.stock}");
|
||||
log("Update Product Category ID: ${productRequestModel.categoryId}");
|
||||
log("Update Product Is Best Seller: ${productRequestModel.isBestSeller}");
|
||||
log("Update Product Printer Type: ${productRequestModel.printerType}");
|
||||
log("Update Product Has Image: ${productRequestModel.image != null}");
|
||||
|
||||
var request = http.MultipartRequest(
|
||||
'POST', Uri.parse('${Variables.baseUrl}/api/products/edit'));
|
||||
request.fields.addAll(productRequestModel.toMap());
|
||||
if (productRequestModel.image != null) {
|
||||
request.files.add(await http.MultipartFile.fromPath(
|
||||
'image', productRequestModel.image!.path));
|
||||
}
|
||||
request.headers.addAll(headers);
|
||||
|
||||
log("Update Product Request Fields: ${request.fields}");
|
||||
log("Update Product Request Files: ${request.files.length}");
|
||||
|
||||
http.StreamedResponse response = await request.send();
|
||||
|
||||
final String body = await response.stream.bytesToString();
|
||||
log("Update Product Status Code: ${response.statusCode}");
|
||||
log("Update Product Body: $body");
|
||||
if (response.statusCode == 200) {
|
||||
return right(AddProductResponseModel.fromJson(body));
|
||||
} else {
|
||||
return left(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../../presentation/setting/models/tax_model.dart';
|
||||
|
||||
class SettingsLocalDatasource {
|
||||
// save tax to shared preferences
|
||||
Future<bool> saveTax(TaxModel taxModel) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
return prefs.setString('tax', taxModel.toJson());
|
||||
}
|
||||
|
||||
// get tax from shared preferences
|
||||
Future<TaxModel> getTax() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final tax = prefs.getString('tax');
|
||||
if (tax != null) {
|
||||
return TaxModel.fromJson(tax);
|
||||
} else {
|
||||
return TaxModel(
|
||||
name: 'Tax',
|
||||
type: TaxType.pajak,
|
||||
value: 11,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// save service charge to shared preferences
|
||||
Future<bool> saveServiceCharge(int serviceCharge) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
return prefs.setInt('serviceCharge', serviceCharge);
|
||||
}
|
||||
|
||||
// get service charge from shared preferences
|
||||
Future<int> getServiceCharge() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
return prefs.getInt('serviceCharge') ?? 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
|
||||
class ProductRequestModel {
|
||||
final int? id;
|
||||
final String name;
|
||||
final int price;
|
||||
final int stock;
|
||||
final int categoryId;
|
||||
final int isBestSeller;
|
||||
final XFile? image;
|
||||
final String? printerType;
|
||||
ProductRequestModel({
|
||||
this.id,
|
||||
required this.name,
|
||||
required this.price,
|
||||
required this.stock,
|
||||
required this.categoryId,
|
||||
required this.isBestSeller,
|
||||
this.image,
|
||||
this.printerType,
|
||||
});
|
||||
|
||||
Map<String, String> toMap() {
|
||||
log("toMap: $isBestSeller");
|
||||
final map = {
|
||||
'name': name,
|
||||
'price': price.toString(),
|
||||
'stock': stock.toString(),
|
||||
'category_id': categoryId.toString(),
|
||||
'is_best_seller': isBestSeller.toString(),
|
||||
'printer_type': printerType ?? '',
|
||||
};
|
||||
|
||||
if (id != null) {
|
||||
map['id'] = id.toString();
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:enaklo_pos/data/models/response/product_response_model.dart';
|
||||
|
||||
class AddProductResponseModel {
|
||||
final bool success;
|
||||
final String message;
|
||||
final Product data;
|
||||
|
||||
AddProductResponseModel({
|
||||
required this.success,
|
||||
required this.message,
|
||||
required this.data,
|
||||
});
|
||||
|
||||
factory AddProductResponseModel.fromJson(String str) =>
|
||||
AddProductResponseModel.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory AddProductResponseModel.fromMap(Map<String, dynamic> json) =>
|
||||
AddProductResponseModel(
|
||||
success: json["success"],
|
||||
message: json["message"],
|
||||
data: Product.fromMap(json["data"]),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"success": success,
|
||||
"message": message,
|
||||
"data": data.toMap(),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class AuthResponseModel {
|
||||
final String? status;
|
||||
final String? token;
|
||||
final User? user;
|
||||
|
||||
AuthResponseModel({
|
||||
this.status,
|
||||
this.token,
|
||||
this.user,
|
||||
});
|
||||
|
||||
factory AuthResponseModel.fromJson(String str) => AuthResponseModel.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory AuthResponseModel.fromMap(Map<String, dynamic> json) => AuthResponseModel(
|
||||
status: json["status"],
|
||||
token: json["token"],
|
||||
user: json["user"] == null ? null : User.fromMap(json["user"]),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"status": status,
|
||||
"token": token,
|
||||
"user": user?.toMap(),
|
||||
};
|
||||
}
|
||||
|
||||
class User {
|
||||
final int? id;
|
||||
final String? name;
|
||||
final String? email;
|
||||
final DateTime? emailVerifiedAt;
|
||||
final dynamic twoFactorSecret;
|
||||
final dynamic twoFactorRecoveryCodes;
|
||||
final dynamic twoFactorConfirmedAt;
|
||||
final DateTime? createdAt;
|
||||
final DateTime? updatedAt;
|
||||
final String? role;
|
||||
|
||||
User({
|
||||
this.id,
|
||||
this.name,
|
||||
this.email,
|
||||
this.emailVerifiedAt,
|
||||
this.twoFactorSecret,
|
||||
this.twoFactorRecoveryCodes,
|
||||
this.twoFactorConfirmedAt,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.role,
|
||||
});
|
||||
|
||||
factory User.fromJson(String str) => User.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory User.fromMap(Map<String, dynamic> json) => User(
|
||||
id: json["id"],
|
||||
name: json["name"],
|
||||
email: json["email"],
|
||||
emailVerifiedAt: json["email_verified_at"] == null ? null : DateTime.parse(json["email_verified_at"]),
|
||||
twoFactorSecret: json["two_factor_secret"],
|
||||
twoFactorRecoveryCodes: json["two_factor_recovery_codes"],
|
||||
twoFactorConfirmedAt: json["two_factor_confirmed_at"],
|
||||
createdAt: json["created_at"] == null ? null : DateTime.parse(json["created_at"]),
|
||||
updatedAt: json["updated_at"] == null ? null : DateTime.parse(json["updated_at"]),
|
||||
role: json["role"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"id": id,
|
||||
"name": name,
|
||||
"email": email,
|
||||
"email_verified_at": emailVerifiedAt?.toIso8601String(),
|
||||
"two_factor_secret": twoFactorSecret,
|
||||
"two_factor_recovery_codes": twoFactorRecoveryCodes,
|
||||
"two_factor_confirmed_at": twoFactorConfirmedAt,
|
||||
"created_at": createdAt?.toIso8601String(),
|
||||
"updated_at": updatedAt?.toIso8601String(),
|
||||
"role": role,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
import 'dart:convert';
|
||||
|
||||
class CategroyResponseModel {
|
||||
final String status;
|
||||
final List<CategoryModel> data;
|
||||
|
||||
CategroyResponseModel({
|
||||
required this.status,
|
||||
required this.data,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return <String, dynamic>{
|
||||
'status': status,
|
||||
'data': data.map((x) => x.toMap()).toList(),
|
||||
};
|
||||
}
|
||||
|
||||
factory CategroyResponseModel.fromMap(Map<String, dynamic> map) {
|
||||
return CategroyResponseModel(
|
||||
status: map['status'] as String,
|
||||
data: List<CategoryModel>.from(
|
||||
(map['data']).map<CategoryModel>(
|
||||
(x) => CategoryModel.fromMap(x as Map<String, dynamic>),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
factory CategroyResponseModel.fromJson(String str) =>
|
||||
CategroyResponseModel.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
}
|
||||
|
||||
class CategoryModel {
|
||||
int? id;
|
||||
String? name;
|
||||
int? categoryId;
|
||||
int? isSync;
|
||||
String? image;
|
||||
// DateTime createdAt;
|
||||
// DateTime updatedAt;
|
||||
|
||||
CategoryModel({this.id, this.name, this.categoryId, this.isSync, this.image});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return <String, dynamic>{
|
||||
// 'id': id,
|
||||
'name': name,
|
||||
'is_sync': isSync ?? 1,
|
||||
'category_id': id,
|
||||
'image': image
|
||||
};
|
||||
}
|
||||
|
||||
factory CategoryModel.fromMap(Map<String, dynamic> map) {
|
||||
return CategoryModel(
|
||||
id: map['id'] as int?,
|
||||
name: map['name'] as String?,
|
||||
isSync: map['is_sync'] as int?,
|
||||
categoryId: map['id'],
|
||||
image: map['image']);
|
||||
}
|
||||
|
||||
factory CategoryModel.fromJson(String str) =>
|
||||
CategoryModel.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
@override
|
||||
bool operator ==(covariant CategoryModel other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other.id == id &&
|
||||
other.name == name &&
|
||||
other.categoryId == categoryId &&
|
||||
other.isSync == isSync &&
|
||||
other.image == image;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return id.hashCode ^
|
||||
name.hashCode ^
|
||||
categoryId.hashCode ^
|
||||
isSync.hashCode ^
|
||||
image.hashCode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class DiscountResponseModel {
|
||||
final String? status;
|
||||
final List<Discount>? data;
|
||||
|
||||
DiscountResponseModel({
|
||||
this.status,
|
||||
this.data,
|
||||
});
|
||||
|
||||
factory DiscountResponseModel.fromJson(String str) =>
|
||||
DiscountResponseModel.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory DiscountResponseModel.fromMap(Map<String, dynamic> json) =>
|
||||
DiscountResponseModel(
|
||||
status: json["status"],
|
||||
data: json["data"] == null
|
||||
? []
|
||||
: List<Discount>.from(
|
||||
json["data"]!.map((x) => Discount.fromMap(x))),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"status": status,
|
||||
"data":
|
||||
data == null ? [] : List<dynamic>.from(data!.map((x) => x.toMap())),
|
||||
};
|
||||
}
|
||||
|
||||
class Discount {
|
||||
final int? id;
|
||||
final String? name;
|
||||
final String? description;
|
||||
final String? type;
|
||||
final String? value;
|
||||
final String? status;
|
||||
final DateTime? expiredDate;
|
||||
final DateTime? createdAt;
|
||||
final DateTime? updatedAt;
|
||||
|
||||
Discount({
|
||||
this.id,
|
||||
this.name,
|
||||
this.description,
|
||||
this.type,
|
||||
this.value,
|
||||
this.status,
|
||||
this.expiredDate,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
});
|
||||
|
||||
factory Discount.fromJson(String str) => Discount.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory Discount.fromMap(Map<String, dynamic> json) => Discount(
|
||||
id: json["id"],
|
||||
name: json["name"],
|
||||
description: json["description"],
|
||||
type: json["type"],
|
||||
value: json["value"],
|
||||
status: json["status"],
|
||||
expiredDate: json["expired_date"] == null
|
||||
? null
|
||||
: DateTime.parse(json["expired_date"]),
|
||||
createdAt: json["created_at"] == null
|
||||
? null
|
||||
: DateTime.parse(json["created_at"]),
|
||||
updatedAt: json["updated_at"] == null
|
||||
? null
|
||||
: DateTime.parse(json["updated_at"]),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"id": id,
|
||||
"name": name,
|
||||
"description": description,
|
||||
"type": type,
|
||||
"value": value,
|
||||
"status": status,
|
||||
"expired_date":
|
||||
"${expiredDate!.year.toString().padLeft(4, '0')}-${expiredDate!.month.toString().padLeft(2, '0')}-${expiredDate!.day.toString().padLeft(2, '0')}",
|
||||
"created_at": createdAt?.toIso8601String(),
|
||||
"updated_at": updatedAt?.toIso8601String(),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class ItemSalesResponseModel {
|
||||
String? status;
|
||||
List<ItemSales>? data;
|
||||
|
||||
ItemSalesResponseModel({
|
||||
this.status,
|
||||
this.data,
|
||||
});
|
||||
|
||||
factory ItemSalesResponseModel.fromJson(String str) =>
|
||||
ItemSalesResponseModel.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory ItemSalesResponseModel.fromMap(Map<String, dynamic> json) =>
|
||||
ItemSalesResponseModel(
|
||||
status: json["status"],
|
||||
data: json["data"] == null
|
||||
? []
|
||||
: List<ItemSales>.from(
|
||||
json["data"]!.map((x) => ItemSales.fromMap(x))),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"status": status,
|
||||
"data":
|
||||
data == null ? [] : List<dynamic>.from(data!.map((x) => x.toMap())),
|
||||
};
|
||||
}
|
||||
|
||||
class ItemSales {
|
||||
int? id;
|
||||
int? orderId;
|
||||
int? productId;
|
||||
int? quantity;
|
||||
int? price;
|
||||
DateTime? createdAt;
|
||||
DateTime? updatedAt;
|
||||
String? productName;
|
||||
|
||||
ItemSales({
|
||||
this.id,
|
||||
this.orderId,
|
||||
this.productId,
|
||||
this.quantity,
|
||||
this.price,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.productName,
|
||||
});
|
||||
|
||||
factory ItemSales.fromJson(String str) => ItemSales.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory ItemSales.fromMap(Map<String, dynamic> json) => ItemSales(
|
||||
id: json["id"],
|
||||
orderId: json["order_id"],
|
||||
productId: json["product_id"],
|
||||
quantity: json["quantity"],
|
||||
price: json["price"],
|
||||
createdAt: json["created_at"] == null
|
||||
? null
|
||||
: DateTime.parse(json["created_at"]),
|
||||
updatedAt: json["updated_at"] == null
|
||||
? null
|
||||
: DateTime.parse(json["updated_at"]),
|
||||
productName: json["product_name"]!,
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"id": id,
|
||||
"order_id": orderId,
|
||||
"product_id": productId,
|
||||
"quantity": quantity,
|
||||
"price": price,
|
||||
"created_at": createdAt?.toIso8601String(),
|
||||
"updated_at": updatedAt?.toIso8601String(),
|
||||
"product_name": productName,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class OrderResponseModel {
|
||||
String? status;
|
||||
List<ItemOrder>? data;
|
||||
|
||||
OrderResponseModel({
|
||||
this.status,
|
||||
this.data,
|
||||
});
|
||||
|
||||
factory OrderResponseModel.fromJson(String str) =>
|
||||
OrderResponseModel.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory OrderResponseModel.fromMap(Map<String, dynamic> json) =>
|
||||
OrderResponseModel(
|
||||
status: json["status"],
|
||||
data: json["data"] == null
|
||||
? []
|
||||
: List<ItemOrder>.from(
|
||||
json["data"]!.map((x) => ItemOrder.fromMap(x))),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"status": status,
|
||||
"data":
|
||||
data == null ? [] : List<dynamic>.from(data!.map((x) => x.toMap())),
|
||||
};
|
||||
}
|
||||
|
||||
class ItemOrder {
|
||||
int? id;
|
||||
int? paymentAmount;
|
||||
int? subTotal;
|
||||
int? tax;
|
||||
int? discount;
|
||||
String? discountAmount;
|
||||
int? serviceCharge;
|
||||
int? total;
|
||||
String? paymentMethod;
|
||||
int? totalItem;
|
||||
int? idKasir;
|
||||
String? namaKasir;
|
||||
DateTime? transactionTime;
|
||||
DateTime? createdAt;
|
||||
DateTime? updatedAt;
|
||||
|
||||
ItemOrder({
|
||||
this.id,
|
||||
this.paymentAmount,
|
||||
this.subTotal,
|
||||
this.tax,
|
||||
this.discount,
|
||||
this.discountAmount,
|
||||
this.serviceCharge,
|
||||
this.total,
|
||||
this.paymentMethod,
|
||||
this.totalItem,
|
||||
this.idKasir,
|
||||
this.namaKasir,
|
||||
this.transactionTime,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
});
|
||||
|
||||
factory ItemOrder.fromJson(String str) => ItemOrder.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory ItemOrder.fromMap(Map<String, dynamic> json) => ItemOrder(
|
||||
id: json["id"],
|
||||
paymentAmount: json["payment_amount"],
|
||||
subTotal: json["sub_total"],
|
||||
tax: json["tax"],
|
||||
discount: json["discount"],
|
||||
discountAmount: json["discount_amount"],
|
||||
serviceCharge: json["service_charge"],
|
||||
total: json["total"],
|
||||
paymentMethod: json["payment_method"]!,
|
||||
totalItem: json["total_item"],
|
||||
idKasir: json["id_kasir"],
|
||||
namaKasir: json["nama_kasir"],
|
||||
transactionTime: json["transaction_time"] == null
|
||||
? null
|
||||
: DateTime.parse(json["transaction_time"]),
|
||||
createdAt: json["created_at"] == null
|
||||
? null
|
||||
: DateTime.parse(json["created_at"]),
|
||||
updatedAt: json["updated_at"] == null
|
||||
? null
|
||||
: DateTime.parse(json["updated_at"]),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"id": id,
|
||||
"payment_amount": paymentAmount,
|
||||
"sub_total": subTotal,
|
||||
"tax": tax,
|
||||
"discount": discount,
|
||||
"discount_amount": discountAmount,
|
||||
"service_charge": serviceCharge,
|
||||
"total": total,
|
||||
"payment_method": paymentMethod,
|
||||
"total_item": totalItem,
|
||||
"id_kasir": idKasir,
|
||||
"nama_kasir": namaKasir,
|
||||
"transaction_time": transactionTime?.toIso8601String(),
|
||||
"created_at": createdAt?.toIso8601String(),
|
||||
"updated_at": updatedAt?.toIso8601String(),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class PaymentMethodResponseModel {
|
||||
final String? status;
|
||||
final PaymentMethodData? data;
|
||||
|
||||
PaymentMethodResponseModel({
|
||||
this.status,
|
||||
this.data,
|
||||
});
|
||||
|
||||
factory PaymentMethodResponseModel.fromJson(String str) =>
|
||||
PaymentMethodResponseModel.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory PaymentMethodResponseModel.fromMap(Map<String, dynamic> json) =>
|
||||
PaymentMethodResponseModel(
|
||||
status: json["status"],
|
||||
data: json["data"] == null
|
||||
? null
|
||||
: PaymentMethodData.fromMap(json["data"]),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"status": status,
|
||||
"data": data?.toMap(),
|
||||
};
|
||||
}
|
||||
|
||||
class PaymentMethodData {
|
||||
final String? total;
|
||||
final List<PaymentMethodItem>? paymentMethods;
|
||||
|
||||
PaymentMethodData({
|
||||
this.total,
|
||||
this.paymentMethods,
|
||||
});
|
||||
|
||||
factory PaymentMethodData.fromJson(String str) =>
|
||||
PaymentMethodData.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory PaymentMethodData.fromMap(Map<String, dynamic> json) =>
|
||||
PaymentMethodData(
|
||||
total: json["total"],
|
||||
paymentMethods: json["payment_methods"] == null
|
||||
? []
|
||||
: List<PaymentMethodItem>.from(
|
||||
json["payment_methods"]!.map((x) => PaymentMethodItem.fromMap(x))),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"total": total,
|
||||
"payment_methods": paymentMethods == null
|
||||
? []
|
||||
: List<dynamic>.from(paymentMethods!.map((x) => x.toMap())),
|
||||
};
|
||||
}
|
||||
|
||||
class PaymentMethodItem {
|
||||
final String? paymentMethod;
|
||||
final String? totalAmount;
|
||||
final int? transactionCount;
|
||||
|
||||
PaymentMethodItem({
|
||||
this.paymentMethod,
|
||||
this.totalAmount,
|
||||
this.transactionCount,
|
||||
});
|
||||
|
||||
factory PaymentMethodItem.fromJson(String str) =>
|
||||
PaymentMethodItem.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory PaymentMethodItem.fromMap(Map<String, dynamic> json) =>
|
||||
PaymentMethodItem(
|
||||
paymentMethod: json["payment_method"],
|
||||
totalAmount: json["total_amount"],
|
||||
transactionCount: json["transaction_count"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"payment_method": paymentMethod,
|
||||
"total_amount": totalAmount,
|
||||
"transaction_count": transactionCount,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class PaymentMethodsResponseModel {
|
||||
final String? status;
|
||||
final List<PaymentMethod>? data;
|
||||
|
||||
PaymentMethodsResponseModel({
|
||||
this.status,
|
||||
this.data,
|
||||
});
|
||||
|
||||
factory PaymentMethodsResponseModel.fromJson(String str) =>
|
||||
PaymentMethodsResponseModel.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory PaymentMethodsResponseModel.fromMap(Map<String, dynamic> json) =>
|
||||
PaymentMethodsResponseModel(
|
||||
status: json["status"],
|
||||
data: json["data"] == null
|
||||
? []
|
||||
: List<PaymentMethod>.from(
|
||||
json["data"]!.map((x) => PaymentMethod.fromMap(x))),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"status": status,
|
||||
"data": data == null
|
||||
? []
|
||||
: List<dynamic>.from(data!.map((x) => x.toMap())),
|
||||
};
|
||||
}
|
||||
|
||||
class PaymentMethod {
|
||||
final int? id;
|
||||
final String? name;
|
||||
final String? description;
|
||||
final bool? isActive;
|
||||
final int? sortOrder;
|
||||
final DateTime? createdAt;
|
||||
final DateTime? updatedAt;
|
||||
|
||||
PaymentMethod({
|
||||
this.id,
|
||||
this.name,
|
||||
this.description,
|
||||
this.isActive,
|
||||
this.sortOrder,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
});
|
||||
|
||||
factory PaymentMethod.fromJson(String str) =>
|
||||
PaymentMethod.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory PaymentMethod.fromMap(Map<String, dynamic> json) => PaymentMethod(
|
||||
id: json["id"],
|
||||
name: json["name"],
|
||||
description: json["description"],
|
||||
isActive: json["is_active"],
|
||||
sortOrder: json["sort_order"],
|
||||
createdAt: json["created_at"] == null
|
||||
? null
|
||||
: DateTime.parse(json["created_at"]),
|
||||
updatedAt: json["updated_at"] == null
|
||||
? null
|
||||
: DateTime.parse(json["updated_at"]),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"id": id,
|
||||
"name": name,
|
||||
"description": description,
|
||||
"is_active": isActive,
|
||||
"sort_order": sortOrder,
|
||||
"created_at": createdAt?.toIso8601String(),
|
||||
"updated_at": updatedAt?.toIso8601String(),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
class PrintModel {
|
||||
int? id;
|
||||
final String code;
|
||||
final String name;
|
||||
final String address;
|
||||
final String paper;
|
||||
final String type;
|
||||
|
||||
PrintModel({
|
||||
this.id,
|
||||
required this.code,
|
||||
required this.name,
|
||||
required this.address,
|
||||
required this.paper,
|
||||
required this.type,
|
||||
});
|
||||
|
||||
// from map
|
||||
factory PrintModel.fromMap(Map<String, dynamic> map) {
|
||||
return PrintModel(
|
||||
id: map['id'],
|
||||
code: map['code'],
|
||||
name: map['name'],
|
||||
address: map['address'],
|
||||
paper: map['paper'],
|
||||
type: map['type'],
|
||||
);
|
||||
}
|
||||
|
||||
// to map
|
||||
Map<String, dynamic> toMap() => {
|
||||
"code": code,
|
||||
"name": name,
|
||||
"address": address,
|
||||
"paper": paper,
|
||||
"type": type,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:enaklo_pos/presentation/home/pages/confirm_payment_page.dart';
|
||||
|
||||
class ProductResponseModel {
|
||||
final String? status;
|
||||
final List<Product>? data;
|
||||
|
||||
ProductResponseModel({
|
||||
this.status,
|
||||
this.data,
|
||||
});
|
||||
|
||||
factory ProductResponseModel.fromJson(String str) =>
|
||||
ProductResponseModel.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory ProductResponseModel.fromMap(Map<String, dynamic> json) =>
|
||||
ProductResponseModel(
|
||||
status: json["status"],
|
||||
data: json["data"] == null
|
||||
? []
|
||||
: List<Product>.from(json["data"]!.map((x) => Product.fromMap(x))),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"status": status,
|
||||
"data":
|
||||
data == null ? [] : List<dynamic>.from(data!.map((x) => x.toMap())),
|
||||
};
|
||||
}
|
||||
|
||||
class Product {
|
||||
final int? id;
|
||||
final int? productId;
|
||||
final int? categoryId;
|
||||
final String? name;
|
||||
final String? description;
|
||||
final String? image;
|
||||
final String? price;
|
||||
final int? stock;
|
||||
final int? status;
|
||||
final int? isFavorite;
|
||||
final DateTime? createdAt;
|
||||
final DateTime? updatedAt;
|
||||
final Category? category;
|
||||
final String? printerType;
|
||||
|
||||
Product({
|
||||
this.id,
|
||||
this.productId,
|
||||
this.categoryId,
|
||||
this.name,
|
||||
this.description,
|
||||
this.image,
|
||||
this.price,
|
||||
this.stock,
|
||||
this.status,
|
||||
this.isFavorite,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.category,
|
||||
this.printerType,
|
||||
});
|
||||
|
||||
factory Product.fromJson(String str) => Product.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory Product.fromMap(Map<String, dynamic> json) => Product(
|
||||
id: json["id"] is String ? int.tryParse(json["id"]) : json["id"],
|
||||
productId: json["product_id"] is String ? int.tryParse(json["product_id"]) : json["product_id"],
|
||||
categoryId: json["category_id"] is String
|
||||
? int.tryParse(json["category_id"])
|
||||
: json["category_id"],
|
||||
name: json["name"],
|
||||
description: json["description"],
|
||||
image: json["image"],
|
||||
// price: json["price"].substring(0, json["price"].length - 3),
|
||||
price: json["price"].toString().replaceAll('.00', ''),
|
||||
stock: json["stock"] is String ? int.tryParse(json["stock"]) : json["stock"],
|
||||
status: json["status"] is String ? int.tryParse(json["status"]) : json["status"],
|
||||
isFavorite: json["is_favorite"] is String ? int.tryParse(json["is_favorite"]) : json["is_favorite"],
|
||||
createdAt: json["created_at"] == null
|
||||
? null
|
||||
: DateTime.parse(json["created_at"]),
|
||||
updatedAt: json["updated_at"] == null
|
||||
? null
|
||||
: DateTime.parse(json["updated_at"]),
|
||||
category: json["category"] == null
|
||||
? null
|
||||
: Category.fromMap(json["category"]),
|
||||
printerType: json["printer_type"] ?? 'bar',
|
||||
);
|
||||
|
||||
factory Product.fromOrderMap(Map<String, dynamic> json) => Product(
|
||||
id: json["id_product"],
|
||||
price: json["price"].toString(),
|
||||
);
|
||||
|
||||
factory Product.fromLocalMap(Map<String, dynamic> json) => Product(
|
||||
id: json["id"],
|
||||
productId: json["product_id"],
|
||||
categoryId: json["categoryId"],
|
||||
category: Category(
|
||||
id: json["categoryId"],
|
||||
name: json["categoryName"],
|
||||
),
|
||||
name: json["name"],
|
||||
description: json["description"],
|
||||
image: json["image"],
|
||||
price: json["price"],
|
||||
stock: json["stock"],
|
||||
status: json["status"],
|
||||
isFavorite: json["isFavorite"],
|
||||
createdAt: json["createdAt"] == null
|
||||
? null
|
||||
: DateTime.parse(json["createdAt"]),
|
||||
updatedAt: json["updatedAt"] == null
|
||||
? null
|
||||
: DateTime.parse(json["updatedAt"]),
|
||||
printerType: json["printer_type"] ?? 'bar',
|
||||
);
|
||||
|
||||
Map<String, dynamic> toLocalMap() => {
|
||||
"product_id": id,
|
||||
"categoryId": categoryId,
|
||||
"categoryName": category?.name,
|
||||
"name": name,
|
||||
"description": description,
|
||||
"image": image,
|
||||
"price": price?.replaceAll(RegExp(r'\.0+$'), ''),
|
||||
"stock": stock,
|
||||
"status": status,
|
||||
"isFavorite": isFavorite,
|
||||
"createdAt": createdAt?.toIso8601String(),
|
||||
"updatedAt": updatedAt?.toIso8601String(),
|
||||
"printer_type": printerType,
|
||||
};
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"id": id,
|
||||
"product_id": productId,
|
||||
"category_id": categoryId,
|
||||
"name": name,
|
||||
"description": description,
|
||||
"image": image,
|
||||
"price": price,
|
||||
"stock": stock,
|
||||
"status": status,
|
||||
"is_favorite": isFavorite,
|
||||
"created_at": createdAt?.toIso8601String(),
|
||||
"updated_at": updatedAt?.toIso8601String(),
|
||||
"category": category?.toMap(),
|
||||
"printer_type": printerType,
|
||||
};
|
||||
|
||||
@override
|
||||
bool operator ==(covariant Product other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other.id == id &&
|
||||
other.productId == productId &&
|
||||
other.categoryId == categoryId &&
|
||||
other.name == name &&
|
||||
other.description == description &&
|
||||
other.image == image &&
|
||||
other.price == price &&
|
||||
other.stock == stock &&
|
||||
other.status == status &&
|
||||
other.isFavorite == isFavorite &&
|
||||
other.createdAt == createdAt &&
|
||||
other.updatedAt == updatedAt &&
|
||||
other.category == category &&
|
||||
other.printerType == printerType;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return id.hashCode ^
|
||||
productId.hashCode ^
|
||||
categoryId.hashCode ^
|
||||
name.hashCode ^
|
||||
description.hashCode ^
|
||||
image.hashCode ^
|
||||
price.hashCode ^
|
||||
stock.hashCode ^
|
||||
status.hashCode ^
|
||||
isFavorite.hashCode ^
|
||||
createdAt.hashCode ^
|
||||
updatedAt.hashCode ^
|
||||
category.hashCode ^
|
||||
printerType.hashCode;
|
||||
}
|
||||
|
||||
Product copyWith({
|
||||
int? id,
|
||||
int? productId,
|
||||
int? categoryId,
|
||||
String? name,
|
||||
String? description,
|
||||
String? image,
|
||||
String? price,
|
||||
int? stock,
|
||||
int? status,
|
||||
int? isFavorite,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
Category? category,
|
||||
String? printerType,
|
||||
}) {
|
||||
return Product(
|
||||
id: id ?? this.id,
|
||||
productId: productId ?? this.productId,
|
||||
categoryId: categoryId ?? this.categoryId,
|
||||
name: name ?? this.name,
|
||||
description: description ?? this.description,
|
||||
image: image ?? this.image,
|
||||
price: price ?? this.price,
|
||||
stock: stock ?? this.stock,
|
||||
status: status ?? this.status,
|
||||
isFavorite: isFavorite ?? this.isFavorite,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
category: category ?? this.category,
|
||||
printerType: printerType ?? this.printerType,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Category {
|
||||
final int? id;
|
||||
final String? name;
|
||||
final String? description;
|
||||
final String? image;
|
||||
final DateTime? createdAt;
|
||||
final DateTime? updatedAt;
|
||||
|
||||
Category({
|
||||
this.id,
|
||||
this.name,
|
||||
this.description,
|
||||
this.image,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
});
|
||||
|
||||
factory Category.fromJson(String str) => Category.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory Category.fromMap(Map<String, dynamic> json) => Category(
|
||||
id: json["id"] is String ? int.tryParse(json["id"]) : json["id"],
|
||||
name: json["name"],
|
||||
description: json["description"],
|
||||
image: json["image"],
|
||||
createdAt: json["created_at"] == null
|
||||
? null
|
||||
: DateTime.parse(json["created_at"]),
|
||||
updatedAt: json["updated_at"] == null
|
||||
? null
|
||||
: DateTime.parse(json["updated_at"]),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"id": id,
|
||||
"name": name,
|
||||
"description": description,
|
||||
"image": image,
|
||||
"created_at": createdAt?.toIso8601String(),
|
||||
"updated_at": updatedAt?.toIso8601String(),
|
||||
};
|
||||
|
||||
@override
|
||||
bool operator ==(covariant Category other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other.id == id &&
|
||||
other.name == name &&
|
||||
other.description == description &&
|
||||
other.image == image &&
|
||||
other.createdAt == createdAt &&
|
||||
other.updatedAt == updatedAt;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return id.hashCode ^
|
||||
name.hashCode ^
|
||||
description.hashCode ^
|
||||
image.hashCode ^
|
||||
createdAt.hashCode ^
|
||||
updatedAt.hashCode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class ProductSalesResponseModel {
|
||||
String? status;
|
||||
List<ProductSales>? data;
|
||||
|
||||
ProductSalesResponseModel({
|
||||
this.status,
|
||||
this.data,
|
||||
});
|
||||
|
||||
factory ProductSalesResponseModel.fromJson(String str) =>
|
||||
ProductSalesResponseModel.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory ProductSalesResponseModel.fromMap(Map<String, dynamic> json) =>
|
||||
ProductSalesResponseModel(
|
||||
status: json["status"],
|
||||
data: json["data"] == null
|
||||
? []
|
||||
: List<ProductSales>.from(
|
||||
json["data"]!.map((x) => ProductSales.fromMap(x))),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"status": status,
|
||||
"data":
|
||||
data == null ? [] : List<dynamic>.from(data!.map((x) => x.toMap())),
|
||||
};
|
||||
}
|
||||
|
||||
class ProductSales {
|
||||
int? productId;
|
||||
String? productName;
|
||||
String? totalQuantity;
|
||||
|
||||
ProductSales({
|
||||
this.productId,
|
||||
this.productName,
|
||||
this.totalQuantity,
|
||||
});
|
||||
|
||||
factory ProductSales.fromJson(String str) =>
|
||||
ProductSales.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory ProductSales.fromMap(Map<String, dynamic> json) => ProductSales(
|
||||
productId: json["product_id"],
|
||||
productName: json["product_name"],
|
||||
totalQuantity: json["total_quantity"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"product_id": productId,
|
||||
"product_name": productName,
|
||||
"total_quantity": totalQuantity,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class QrisResponseModel {
|
||||
final String? statusCode;
|
||||
final String? statusMessage;
|
||||
final String? transactionId;
|
||||
final String? orderId;
|
||||
final String? merchantId;
|
||||
final String? grossAmount;
|
||||
final String? currency;
|
||||
final String? paymentType;
|
||||
final DateTime? transactionTime;
|
||||
final String? transactionStatus;
|
||||
final String? fraudStatus;
|
||||
final List<Action>? actions;
|
||||
final DateTime? expiryTime;
|
||||
|
||||
QrisResponseModel({
|
||||
this.statusCode,
|
||||
this.statusMessage,
|
||||
this.transactionId,
|
||||
this.orderId,
|
||||
this.merchantId,
|
||||
this.grossAmount,
|
||||
this.currency,
|
||||
this.paymentType,
|
||||
this.transactionTime,
|
||||
this.transactionStatus,
|
||||
this.fraudStatus,
|
||||
this.actions,
|
||||
this.expiryTime,
|
||||
});
|
||||
|
||||
factory QrisResponseModel.fromJson(String str) =>
|
||||
QrisResponseModel.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory QrisResponseModel.fromMap(Map<String, dynamic> json) =>
|
||||
QrisResponseModel(
|
||||
statusCode: json["status_code"],
|
||||
statusMessage: json["status_message"],
|
||||
transactionId: json["transaction_id"],
|
||||
orderId: json["order_id"],
|
||||
merchantId: json["merchant_id"],
|
||||
grossAmount: json["gross_amount"],
|
||||
currency: json["currency"],
|
||||
paymentType: json["payment_type"],
|
||||
transactionTime: json["transaction_time"] == null
|
||||
? null
|
||||
: DateTime.parse(json["transaction_time"]),
|
||||
transactionStatus: json["transaction_status"],
|
||||
fraudStatus: json["fraud_status"],
|
||||
actions: json["actions"] == null
|
||||
? []
|
||||
: List<Action>.from(json["actions"]!.map((x) => Action.fromMap(x))),
|
||||
expiryTime: json["expiry_time"] == null
|
||||
? null
|
||||
: DateTime.parse(json["expiry_time"]),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"status_code": statusCode,
|
||||
"status_message": statusMessage,
|
||||
"transaction_id": transactionId,
|
||||
"order_id": orderId,
|
||||
"merchant_id": merchantId,
|
||||
"gross_amount": grossAmount,
|
||||
"currency": currency,
|
||||
"payment_type": paymentType,
|
||||
"transaction_time": transactionTime?.toIso8601String(),
|
||||
"transaction_status": transactionStatus,
|
||||
"fraud_status": fraudStatus,
|
||||
"actions": actions == null
|
||||
? []
|
||||
: List<dynamic>.from(actions!.map((x) => x.toMap())),
|
||||
"expiry_time": expiryTime?.toIso8601String(),
|
||||
};
|
||||
}
|
||||
|
||||
class Action {
|
||||
final String? name;
|
||||
final String? method;
|
||||
final String? url;
|
||||
|
||||
Action({
|
||||
this.name,
|
||||
this.method,
|
||||
this.url,
|
||||
});
|
||||
|
||||
factory Action.fromJson(String str) => Action.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory Action.fromMap(Map<String, dynamic> json) => Action(
|
||||
name: json["name"],
|
||||
method: json["method"],
|
||||
url: json["url"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"name": name,
|
||||
"method": method,
|
||||
"url": url,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class QrisStatusResponseModel {
|
||||
final String? maskedCard;
|
||||
final String? approvalCode;
|
||||
final String? bank;
|
||||
final String? eci;
|
||||
final String? channelResponseCode;
|
||||
final String? channelResponseMessage;
|
||||
final DateTime? transactionTime;
|
||||
final String? grossAmount;
|
||||
final String? currency;
|
||||
final String? orderId;
|
||||
final String? paymentType;
|
||||
final String? signatureKey;
|
||||
final String? statusCode;
|
||||
final String? transactionId;
|
||||
final String? transactionStatus;
|
||||
final String? fraudStatus;
|
||||
final DateTime? settlementTime;
|
||||
final String? statusMessage;
|
||||
final String? merchantId;
|
||||
final String? cardType;
|
||||
final String? threeDsVersion;
|
||||
final bool? challengeCompletion;
|
||||
|
||||
QrisStatusResponseModel({
|
||||
this.maskedCard,
|
||||
this.approvalCode,
|
||||
this.bank,
|
||||
this.eci,
|
||||
this.channelResponseCode,
|
||||
this.channelResponseMessage,
|
||||
this.transactionTime,
|
||||
this.grossAmount,
|
||||
this.currency,
|
||||
this.orderId,
|
||||
this.paymentType,
|
||||
this.signatureKey,
|
||||
this.statusCode,
|
||||
this.transactionId,
|
||||
this.transactionStatus,
|
||||
this.fraudStatus,
|
||||
this.settlementTime,
|
||||
this.statusMessage,
|
||||
this.merchantId,
|
||||
this.cardType,
|
||||
this.threeDsVersion,
|
||||
this.challengeCompletion,
|
||||
});
|
||||
|
||||
factory QrisStatusResponseModel.fromJson(String str) =>
|
||||
QrisStatusResponseModel.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory QrisStatusResponseModel.fromMap(Map<String, dynamic> json) =>
|
||||
QrisStatusResponseModel(
|
||||
maskedCard: json["masked_card"],
|
||||
approvalCode: json["approval_code"],
|
||||
bank: json["bank"],
|
||||
eci: json["eci"],
|
||||
channelResponseCode: json["channel_response_code"],
|
||||
channelResponseMessage: json["channel_response_message"],
|
||||
transactionTime: json["transaction_time"] == null
|
||||
? null
|
||||
: DateTime.parse(json["transaction_time"]),
|
||||
grossAmount: json["gross_amount"],
|
||||
currency: json["currency"],
|
||||
orderId: json["order_id"],
|
||||
paymentType: json["payment_type"],
|
||||
signatureKey: json["signature_key"],
|
||||
statusCode: json["status_code"],
|
||||
transactionId: json["transaction_id"],
|
||||
transactionStatus: json["transaction_status"],
|
||||
fraudStatus: json["fraud_status"],
|
||||
settlementTime: json["settlement_time"] == null
|
||||
? null
|
||||
: DateTime.parse(json["settlement_time"]),
|
||||
statusMessage: json["status_message"],
|
||||
merchantId: json["merchant_id"],
|
||||
cardType: json["card_type"],
|
||||
threeDsVersion: json["three_ds_version"],
|
||||
challengeCompletion: json["challenge_completion"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"masked_card": maskedCard,
|
||||
"approval_code": approvalCode,
|
||||
"bank": bank,
|
||||
"eci": eci,
|
||||
"channel_response_code": channelResponseCode,
|
||||
"channel_response_message": channelResponseMessage,
|
||||
"transaction_time": transactionTime?.toIso8601String(),
|
||||
"gross_amount": grossAmount,
|
||||
"currency": currency,
|
||||
"order_id": orderId,
|
||||
"payment_type": paymentType,
|
||||
"signature_key": signatureKey,
|
||||
"status_code": statusCode,
|
||||
"transaction_id": transactionId,
|
||||
"transaction_status": transactionStatus,
|
||||
"fraud_status": fraudStatus,
|
||||
"settlement_time": settlementTime?.toIso8601String(),
|
||||
"status_message": statusMessage,
|
||||
"merchant_id": merchantId,
|
||||
"card_type": cardType,
|
||||
"three_ds_version": threeDsVersion,
|
||||
"challenge_completion": challengeCompletion,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class SummaryResponseModel {
|
||||
String? status;
|
||||
SummaryModel? data;
|
||||
|
||||
SummaryResponseModel({
|
||||
this.status,
|
||||
this.data,
|
||||
});
|
||||
|
||||
factory SummaryResponseModel.fromJson(String str) =>
|
||||
SummaryResponseModel.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory SummaryResponseModel.fromMap(Map<String, dynamic> json) =>
|
||||
SummaryResponseModel(
|
||||
status: json["status"],
|
||||
data: json["data"] == null ? null : SummaryModel.fromMap(json["data"]),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"status": status,
|
||||
"data": data?.toMap(),
|
||||
};
|
||||
}
|
||||
|
||||
class SummaryModel {
|
||||
String? totalRevenue;
|
||||
String? totalDiscount;
|
||||
String? totalTax;
|
||||
String? totalSubtotal;
|
||||
String? totalServiceCharge;
|
||||
int? total;
|
||||
|
||||
SummaryModel({
|
||||
this.totalRevenue,
|
||||
this.totalDiscount,
|
||||
this.totalTax,
|
||||
this.totalSubtotal,
|
||||
this.totalServiceCharge,
|
||||
this.total,
|
||||
});
|
||||
|
||||
factory SummaryModel.fromJson(String str) =>
|
||||
SummaryModel.fromMap(json.decode(str));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory SummaryModel.fromMap(Map<String, dynamic> json) => SummaryModel(
|
||||
totalRevenue: json["total_revenue"] is int
|
||||
? json["total_revenue"].toString()
|
||||
: json["total_revenue"],
|
||||
totalDiscount: json["total_discount"] is int
|
||||
? json["total_discount"].toString()
|
||||
: json["total_discount"],
|
||||
totalTax: json["total_tax"] is int
|
||||
? json["total_tax"].toString()
|
||||
: json["total_tax"],
|
||||
totalSubtotal: json["total_subtotal"] is int
|
||||
? json["total_subtotal"].toString()
|
||||
: json["total_subtotal"],
|
||||
totalServiceCharge: json["total_service_charge"] is int
|
||||
? json["total_service_charge"].toString()
|
||||
: json["total_service_charge"],
|
||||
total: json["total"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"total_revenue": totalRevenue,
|
||||
"total_discount": totalDiscount,
|
||||
"total_tax": totalTax,
|
||||
"total_subtotal": totalSubtotal,
|
||||
"total_service_charge": totalServiceCharge,
|
||||
"total": total,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
import 'dart:ui';
|
||||
|
||||
class TableModel {
|
||||
int? id;
|
||||
final String tableName;
|
||||
final String startTime;
|
||||
final String status;
|
||||
final int orderId;
|
||||
final int paymentAmount;
|
||||
final Offset position;
|
||||
|
||||
TableModel({
|
||||
this.id,
|
||||
required this.tableName,
|
||||
required this.startTime,
|
||||
required this.status,
|
||||
required this.orderId,
|
||||
required this.paymentAmount,
|
||||
required this.position,
|
||||
});
|
||||
|
||||
@override
|
||||
|
||||
// from map
|
||||
factory TableModel.fromMap(Map<String, dynamic> map) {
|
||||
return TableModel(
|
||||
id: map['id'],
|
||||
tableName: map['table_name'],
|
||||
startTime: map['start_time'],
|
||||
status: map['status'],
|
||||
orderId: map['order_id'],
|
||||
paymentAmount: map['payment_amount'],
|
||||
position: Offset(map['x_position'], map['y_position']),
|
||||
);
|
||||
}
|
||||
|
||||
// to map
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'table_name': tableName,
|
||||
'status': status,
|
||||
'start_time': startTime,
|
||||
'order_id': orderId,
|
||||
'payment_amount': paymentAmount,
|
||||
'x_position': position.dx,
|
||||
'y_position': position.dy,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(covariant TableModel other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other.id == id &&
|
||||
other.tableName == tableName &&
|
||||
other.startTime == startTime &&
|
||||
other.status == status &&
|
||||
other.orderId == orderId &&
|
||||
other.paymentAmount == paymentAmount &&
|
||||
other.position == position;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return id.hashCode ^
|
||||
tableName.hashCode ^
|
||||
startTime.hashCode ^
|
||||
status.hashCode ^
|
||||
orderId.hashCode ^
|
||||
paymentAmount.hashCode ^
|
||||
position.hashCode;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user