Printer Local data and remove unused

This commit is contained in:
efrilm
2025-09-20 03:56:07 +07:00
parent 04811015b6
commit 44402140fb
46 changed files with 685 additions and 7150 deletions
@@ -0,0 +1,317 @@
import 'dart:developer';
import 'package:enaklo_pos/core/database/database_handler.dart';
import 'package:enaklo_pos/data/models/response/print_model.dart';
import 'package:sqflite/sqflite.dart';
class PrinterLocalDatasource {
static PrinterLocalDatasource? _instance;
PrinterLocalDatasource._internal();
static PrinterLocalDatasource get instance {
_instance ??= PrinterLocalDatasource._internal();
return _instance!;
}
Future<Database> get _db async => await DatabaseHelper.instance.database;
// Create new printer
Future<int> createPrinter(PrintModel printer) async {
final db = await _db;
try {
log('Creating printer: ${printer.toString()}');
final id = await db.insert(
'printers',
printer.toMapForInsert(),
conflictAlgorithm:
ConflictAlgorithm.abort, // Fail if code already exists
);
log('Successfully created printer with ID: $id');
return id;
} catch (e) {
log('Error creating printer: $e');
rethrow;
}
}
// Update existing printer
Future<void> updatePrinter(PrintModel printer, int id) async {
final db = await _db;
try {
log('Updating printer ID $id: ${printer.toString()}');
final updatedRows = await db.update(
'printers',
printer.toMapForUpdate(),
where: 'id = ?',
whereArgs: [id],
);
if (updatedRows == 0) {
throw Exception('Printer with ID $id not found');
}
log('Successfully updated printer ID: $id');
} catch (e) {
log('Error updating printer: $e');
rethrow;
}
}
// Delete printer by ID
Future<void> deletePrinter(int id) async {
final db = await _db;
try {
log('Deleting printer ID: $id');
final deletedRows = await db.delete(
'printers',
where: 'id = ?',
whereArgs: [id],
);
if (deletedRows == 0) {
throw Exception('Printer with ID $id not found');
}
log('Successfully deleted printer ID: $id');
} catch (e) {
log('Error deleting printer: $e');
rethrow;
}
}
// Get printer by code
Future<PrintModel?> getPrinterByCode(String code) async {
final db = await _db;
try {
log('Getting printer by code: $code');
final result = await db.query(
'printers',
where: 'code = ?',
whereArgs: [code],
);
if (result.isEmpty) {
log('Printer with code $code not found');
return null;
}
final printer = PrintModel.fromMap(result.first);
log('Found printer: ${printer.toString()}');
return printer;
} catch (e) {
log('Error getting printer by code: $e');
return null;
}
}
// Get printer by ID
Future<PrintModel?> getPrinterById(int id) async {
final db = await _db;
try {
log('Getting printer by ID: $id');
final result = await db.query(
'printers',
where: 'id = ?',
whereArgs: [id],
);
if (result.isEmpty) {
log('Printer with ID $id not found');
return null;
}
final printer = PrintModel.fromMap(result.first);
log('Found printer: ${printer.toString()}');
return printer;
} catch (e) {
log('Error getting printer by ID: $e');
return null;
}
}
// Get all printers
Future<List<PrintModel>> getAllPrinters() async {
final db = await _db;
try {
log('Getting all printers');
final result = await db.query(
'printers',
orderBy: 'name ASC',
);
final printers = result.map((map) => PrintModel.fromMap(map)).toList();
log('Found ${printers.length} printers');
return printers;
} catch (e) {
log('Error getting all printers: $e');
return [];
}
}
// Get printers by type
Future<List<PrintModel>> getPrintersByType(String type) async {
final db = await _db;
try {
log('Getting printers by type: $type');
final result = await db.query(
'printers',
where: 'type = ?',
whereArgs: [type],
orderBy: 'name ASC',
);
final printers = result.map((map) => PrintModel.fromMap(map)).toList();
log('Found ${printers.length} printers with type $type');
return printers;
} catch (e) {
log('Error getting printers by type: $e');
return [];
}
}
// Search printers by name
Future<List<PrintModel>> searchPrintersByName(String query) async {
final db = await _db;
try {
log('Searching printers by name: $query');
final result = await db.query(
'printers',
where: 'name LIKE ?',
whereArgs: ['%$query%'],
orderBy: 'name ASC',
);
final printers = result.map((map) => PrintModel.fromMap(map)).toList();
log('Found ${printers.length} printers matching "$query"');
return printers;
} catch (e) {
log('Error searching printers: $e');
return [];
}
}
// Check if printer code exists
Future<bool> isPrinterCodeExists(String code, {int? excludeId}) async {
final db = await _db;
try {
String whereClause = 'code = ?';
List<dynamic> whereArgs = [code];
if (excludeId != null) {
whereClause += ' AND id != ?';
whereArgs.add(excludeId);
}
final result = await db.query(
'printers',
where: whereClause,
whereArgs: whereArgs,
);
final exists = result.isNotEmpty;
log('Printer code "$code" exists: $exists');
return exists;
} catch (e) {
log('Error checking printer code existence: $e');
return false;
}
}
// Get printer statistics
Future<Map<String, dynamic>> getPrinterStats() async {
final db = await _db;
try {
// Total count
final totalResult =
await db.rawQuery('SELECT COUNT(*) as total FROM printers');
final totalCount = totalResult.first['total'] as int;
// Count by type
final typeResult = await db.rawQuery('''
SELECT type, COUNT(*) as count
FROM printers
WHERE type IS NOT NULL
GROUP BY type
''');
final typeStats = <String, int>{};
for (final row in typeResult) {
typeStats[row['type'] as String] = row['count'] as int;
}
final stats = {
'total_printers': totalCount,
'by_type': typeStats,
};
log('Printer stats: $stats');
return stats;
} catch (e) {
log('Error getting printer stats: $e');
return {
'total_printers': 0,
'by_type': <String, int>{},
};
}
}
// Clear all printers (for testing/reset purposes)
Future<void> clearAllPrinters() async {
final db = await _db;
try {
log('Clearing all printers');
await db.delete('printers');
log('All printers cleared');
} catch (e) {
log('Error clearing printers: $e');
rethrow;
}
}
// Batch insert printers
Future<void> insertPrinters(List<PrintModel> printers) async {
final db = await _db;
try {
log('Batch inserting ${printers.length} printers');
await db.transaction((txn) async {
for (final printer in printers) {
await txn.insert(
'printers',
printer.toMapForInsert(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
});
log('Successfully batch inserted ${printers.length} printers');
} catch (e) {
log('Error batch inserting printers: $e');
rethrow;
}
}
}
@@ -1,639 +0,0 @@
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: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]);
});
}
Future<List<OrderModel>> getAllOrderByRange(
DateTime start, DateTime end) async {
final db = await instance.database;
// Format ke ISO 8601 untuk range, hasil: yyyy-MM-ddTHH:mm:ss
final startIso = start.toIso8601String();
final endIso = end.toIso8601String();
final startDateYYYYMMDD = startIso.substring(0, 10);
final endDateYYYYMMDD = endIso.substring(0, 10);
final List<Map<String, dynamic>> maps = await db.query(
tableOrder,
where: 'substr(transaction_time, 1, 10) BETWEEN ? AND ?',
whereArgs: [startDateYYYYMMDD, endDateYYYYMMDD],
orderBy: 'transaction_time DESC',
);
log("Get All Order By Range: $startDateYYYYMMDD $endDateYYYYMMDD");
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.id],
);
}
//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.id} | name: ${product.name} | price: ${product.price} ');
}
}
//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);
}
}
+121 -15
View File
@@ -5,6 +5,8 @@ class PrintModel {
final String address;
final String paper;
final String type;
final DateTime? createdAt;
final DateTime? updatedAt;
PrintModel({
this.id,
@@ -13,26 +15,130 @@ class PrintModel {
required this.address,
required this.paper,
required this.type,
this.createdAt,
this.updatedAt,
});
// from map
// Factory constructor from map (updated)
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'],
id: map['id'] as int?,
code: map['code'] as String,
name: map['name'] as String,
address: map['address'] as String,
paper: map['paper'] as String,
type: map['type'] as String,
createdAt: map['created_at'] != null
? DateTime.tryParse(map['created_at'] as String)
: null,
updatedAt: map['updated_at'] != null
? DateTime.tryParse(map['updated_at'] as String)
: null,
);
}
// to map
Map<String, dynamic> toMap() => {
"code": code,
"name": name,
"address": address,
"paper": paper,
"type": type,
};
// Convert to map for database insertion (without id, with timestamps)
Map<String, dynamic> toMapForInsert() {
final now = DateTime.now().toIso8601String();
return {
'code': code,
'name': name,
'address': address,
'paper': paper,
'type': type,
'created_at': now,
'updated_at': now,
};
}
// Convert to map for database update (without id and created_at)
Map<String, dynamic> toMapForUpdate() {
return {
'code': code,
'name': name,
'address': address,
'paper': paper,
'type': type,
'updated_at': DateTime.now().toIso8601String(),
};
}
// Convert to complete map (original method, enhanced)
Map<String, dynamic> toMap() {
return {
if (id != null) 'id': id,
'code': code,
'name': name,
'address': address,
'paper': paper,
'type': type,
if (createdAt != null) 'created_at': createdAt!.toIso8601String(),
if (updatedAt != null) 'updated_at': updatedAt!.toIso8601String(),
};
}
// Copy with method for creating modified instances
PrintModel copyWith({
int? id,
String? code,
String? name,
String? address,
String? paper,
String? type,
DateTime? createdAt,
DateTime? updatedAt,
}) {
return PrintModel(
id: id ?? this.id,
code: code ?? this.code,
name: name ?? this.name,
address: address ?? this.address,
paper: paper ?? this.paper,
type: type ?? this.type,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
);
}
// Equality and hashCode
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is PrintModel &&
other.id == id &&
other.code == code &&
other.name == name &&
other.address == address &&
other.paper == paper &&
other.type == type;
}
@override
int get hashCode {
return Object.hash(id, code, name, address, paper, type);
}
// String representation for debugging (matches datasource logging)
@override
String toString() {
return 'PrintModel(id: $id, code: $code, name: $name, address: $address, paper: $paper, type: $type, createdAt: $createdAt, updatedAt: $updatedAt)';
}
// Validation methods
bool get isValid {
return code.isNotEmpty &&
name.isNotEmpty &&
address.isNotEmpty &&
paper.isNotEmpty &&
type.isNotEmpty;
}
String? get validationError {
if (code.isEmpty) return 'Printer code cannot be empty';
if (name.isEmpty) return 'Printer name cannot be empty';
if (address.isEmpty) return 'Printer address cannot be empty';
if (paper.isEmpty) return 'Paper size cannot be empty';
if (type.isEmpty) return 'Printer type cannot be empty';
return null;
}
}