Update: 2026-05-15 04:35:25
This commit is contained in:
109
musadaq-app/lib/core/services/thermal_printer_service.dart
Normal file
109
musadaq-app/lib/core/services/thermal_printer_service.dart
Normal file
@@ -0,0 +1,109 @@
|
||||
import 'package:esc_pos_printer/esc_pos_printer.dart';
|
||||
import 'package:esc_pos_utils/esc_pos_utils.dart';
|
||||
import '../utils/logger.dart';
|
||||
|
||||
class ThermalPrinterService {
|
||||
/// Prints an invoice to a WiFi thermal printer
|
||||
Future<bool> printInvoice({
|
||||
required String ip,
|
||||
required Map<String, dynamic> invoice,
|
||||
int port = 9100,
|
||||
PaperSize paperSize = PaperSize.mm80,
|
||||
}) async {
|
||||
try {
|
||||
final profile = await CapabilityProfile.load();
|
||||
final printer = NetworkPrinter(paperSize, profile);
|
||||
|
||||
final PosPrintResult res = await printer.connect(ip, port: port);
|
||||
|
||||
if (res != PosPrintResult.success) {
|
||||
AppLogger.error('Could not connect to printer at $ip:$port');
|
||||
return false;
|
||||
}
|
||||
|
||||
AppLogger.print('Connected to printer, generating ticket...');
|
||||
|
||||
// Generate Ticket
|
||||
_buildInvoiceTicket(printer, invoice);
|
||||
|
||||
printer.feed(2);
|
||||
printer.cut();
|
||||
printer.disconnect();
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
AppLogger.error('Thermal printing failed', e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void _buildInvoiceTicket(NetworkPrinter printer, Map<String, dynamic> invoice) {
|
||||
// Header
|
||||
printer.text(
|
||||
'M U S A D A Q',
|
||||
styles: const PosStyles(
|
||||
align: PosAlign.center,
|
||||
height: PosTextSize.size2,
|
||||
width: PosTextSize.size2,
|
||||
bold: true,
|
||||
),
|
||||
);
|
||||
printer.text(
|
||||
'نظام الفوترة الإلكترونية',
|
||||
styles: const PosStyles(align: PosAlign.center),
|
||||
);
|
||||
printer.hr();
|
||||
|
||||
// Invoice Info
|
||||
printer.text('رقم الفاتورة: ${invoice['invoice_number'] ?? '-'}');
|
||||
printer.text('التاريخ: ${invoice['invoice_date'] ?? '-'}');
|
||||
printer.text('المورد: ${invoice['supplier_name'] ?? '-'}');
|
||||
if (invoice['supplier_tin'] != null) {
|
||||
printer.text('الرقم الضريبي: ${invoice['supplier_tin']}');
|
||||
}
|
||||
printer.hr();
|
||||
|
||||
// Table Header
|
||||
printer.row([
|
||||
PosColumn(text: 'البند', width: 6),
|
||||
PosColumn(text: 'الكمية', width: 2, styles: const PosStyles(align: PosAlign.center)),
|
||||
PosColumn(text: 'الإجمالي', width: 4, styles: const PosStyles(align: PosAlign.right)),
|
||||
]);
|
||||
printer.hr();
|
||||
|
||||
// Items
|
||||
final items = invoice['items'] as List? ?? [];
|
||||
for (var item in items) {
|
||||
printer.row([
|
||||
PosColumn(text: item['description'] ?? '-', width: 6),
|
||||
PosColumn(text: item['quantity']?.toString() ?? '1', width: 2, styles: const PosStyles(align: PosAlign.center)),
|
||||
PosColumn(text: item['line_total']?.toString() ?? '0', width: 4, styles: const PosStyles(align: PosAlign.right)),
|
||||
]);
|
||||
}
|
||||
printer.hr();
|
||||
|
||||
// Totals
|
||||
printer.row([
|
||||
PosColumn(text: 'المجموع الجزئي:', width: 8),
|
||||
PosColumn(text: '${invoice['subtotal'] ?? 0}', width: 4, styles: const PosStyles(align: PosAlign.right)),
|
||||
]);
|
||||
printer.row([
|
||||
PosColumn(text: 'الضريبة:', width: 8),
|
||||
PosColumn(text: '${invoice['tax_amount'] ?? 0}', width: 4, styles: const PosStyles(align: PosAlign.right)),
|
||||
]);
|
||||
printer.row([
|
||||
PosColumn(text: 'الإجمالي الكلي:', width: 8, styles: const PosStyles(bold: true)),
|
||||
PosColumn(text: '${invoice['grand_total'] ?? 0} JOD', width: 4, styles: const PosStyles(align: PosAlign.right, bold: true)),
|
||||
]);
|
||||
|
||||
printer.hr();
|
||||
printer.text(
|
||||
'شكراً لاستخدامكم مُصادَق',
|
||||
styles: const PosStyles(align: PosAlign.center, italic: true),
|
||||
);
|
||||
printer.text(
|
||||
'www.musadaq.com',
|
||||
styles: const PosStyles(align: PosAlign.center),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user