manual edit cleaning and fix AI code
parent
b88c301d7d
commit
b3cb5e3e05
|
@ -13,19 +13,16 @@ class EscPosPrintService {
|
|||
static Future<List<int>> generateEscPosBytes({
|
||||
required List<ReceiptItem> items,
|
||||
required DateTime transactionDate,
|
||||
required String cashierId,
|
||||
required String transactionId,
|
||||
}) async {
|
||||
print('Memulai generateEscPosBytes...');
|
||||
print('Jumlah item: ${items.length}');
|
||||
print('Tanggal transaksi: $transactionDate');
|
||||
print('ID kasir: $cashierId');
|
||||
print('ID transaksi: $transactionId');
|
||||
|
||||
// Load store info from shared preferences
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final storeName = prefs.getString('store_name') ?? 'TOKO SEMBAKO MURAH';
|
||||
final storeAddress = prefs.getString('store_address') ?? 'Jl. Merdeka No. 123';
|
||||
final storeAddress =
|
||||
prefs.getString('store_address') ?? 'Jl. Merdeka No. 123';
|
||||
final adminName = prefs.getString('admin_name') ?? 'Budi Santoso';
|
||||
final adminPhone = prefs.getString('admin_phone') ?? '08123456789';
|
||||
|
||||
|
@ -97,18 +94,6 @@ class EscPosPrintService {
|
|||
|
||||
bytes += generator.feed(1);
|
||||
|
||||
// Garis pemisah
|
||||
bytes += generator.text('================================',
|
||||
styles: PosStyles(align: PosAlign.center));
|
||||
|
||||
// Informasi transaksi
|
||||
bytes += generator.text('Kasir: $cashierId',
|
||||
styles: PosStyles(bold: true));
|
||||
bytes += generator.text('ID Transaksi: $transactionId',
|
||||
styles: PosStyles());
|
||||
|
||||
bytes += generator.feed(1);
|
||||
|
||||
// Garis pemisah
|
||||
bytes += generator.text('================================',
|
||||
styles: PosStyles(align: PosAlign.center));
|
||||
|
@ -132,7 +117,8 @@ class EscPosPrintService {
|
|||
for (int i = 0; i < items.length; i++) {
|
||||
try {
|
||||
var item = items[i];
|
||||
print('Item $i: ${item.description}, qty: ${item.quantity}, price: ${item.price}, total: ${item.total}');
|
||||
print(
|
||||
'Item $i: ${item.description}, qty: ${item.quantity}, price: ${item.price}, total: ${item.total}');
|
||||
|
||||
// Untuk item dengan detail kuantitas dan harga
|
||||
bytes += generator.row([
|
||||
|
@ -147,7 +133,10 @@ class EscPosPrintService {
|
|||
PosColumn(
|
||||
text: '${item.quantity} x ${formatRupiah(item.price)}',
|
||||
width: 7,
|
||||
styles: PosStyles(align: PosAlign.left, height: PosTextSize.size1, width: PosTextSize.size1),
|
||||
styles: PosStyles(
|
||||
align: PosAlign.left,
|
||||
height: PosTextSize.size1,
|
||||
width: PosTextSize.size1),
|
||||
),
|
||||
PosColumn(
|
||||
text: formatRupiah(item.total),
|
||||
|
@ -203,12 +192,14 @@ class EscPosPrintService {
|
|||
'Harap periksa kembali struk belanja Anda sebelum meninggalkan toko.';
|
||||
} catch (e) {
|
||||
print('Error saat memuat disclaimer: $e');
|
||||
customDisclaimer = 'Barang yang sudah dibeli tidak dapat dikembalikan/ditukar.';
|
||||
customDisclaimer =
|
||||
'Barang yang sudah dibeli tidak dapat dikembalikan/ditukar.';
|
||||
}
|
||||
|
||||
String customThankYou;
|
||||
try {
|
||||
customThankYou = prefs.getString('thank_you_text') ?? '*** TERIMA KASIH ***';
|
||||
customThankYou =
|
||||
prefs.getString('thank_you_text') ?? '*** TERIMA KASIH ***';
|
||||
} catch (e) {
|
||||
print('Error saat memuat thank you text: $e');
|
||||
customThankYou = '*** TERIMA KASIH ***';
|
||||
|
@ -248,8 +239,8 @@ class EscPosPrintService {
|
|||
}
|
||||
|
||||
for (final line in wrappedDisclaimer) {
|
||||
bytes += generator.text(line,
|
||||
styles: PosStyles(align: PosAlign.center));
|
||||
bytes +=
|
||||
generator.text(line, styles: PosStyles(align: PosAlign.center));
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error saat memproses disclaimer: $e');
|
||||
|
@ -269,8 +260,8 @@ class EscPosPrintService {
|
|||
bytes += generator.feed(1);
|
||||
final pantunLines = customPantun.split('\n');
|
||||
for (final line in pantunLines) {
|
||||
bytes += generator.text(line,
|
||||
styles: PosStyles(align: PosAlign.center));
|
||||
bytes +=
|
||||
generator.text(line, styles: PosStyles(align: PosAlign.center));
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error saat menambahkan pantun: $e');
|
||||
|
@ -299,30 +290,21 @@ class EscPosPrintService {
|
|||
required BuildContext context,
|
||||
required dynamic bluetoothService, // Kita akan sesuaikan tipe ini nanti
|
||||
}) async {
|
||||
// Definisikan cashierId dan transactionId di sini karena tidak berubah
|
||||
final String cashierId = 'KSR001';
|
||||
final String transactionId = 'TXN202508200001';
|
||||
|
||||
print('=== FUNGSI printToThermalPrinter DIPANGGIL ===');
|
||||
print('Memulai proses pencetakan struk...');
|
||||
print('Jumlah item: ${items.length}');
|
||||
print('Tanggal transaksi: ${transactionDate}');
|
||||
print('ID kasir: $cashierId');
|
||||
print('ID transaksi: $transactionId');
|
||||
|
||||
try {
|
||||
print('Menghasilkan byte array ESC/POS menggunakan flutter_esc_pos_utils...');
|
||||
print(
|
||||
'Menghasilkan byte array ESC/POS menggunakan flutter_esc_pos_utils...');
|
||||
print('Jumlah item: ${items.length}');
|
||||
print('Tanggal transaksi: ${transactionDate}');
|
||||
print('ID kasir: $cashierId');
|
||||
print('ID transaksi: $transactionId');
|
||||
|
||||
// Generate struk dalam format byte array menggunakan EscPosPrintService
|
||||
final bytes = await generateEscPosBytes(
|
||||
items: items,
|
||||
transactionDate: transactionDate,
|
||||
cashierId: cashierId,
|
||||
transactionId: transactionId,
|
||||
);
|
||||
|
||||
print('Byte array ESC/POS berhasil dihasilkan');
|
||||
|
@ -330,7 +312,8 @@ class EscPosPrintService {
|
|||
|
||||
// Tampilkan byte array untuk debugging (dalam format hex)
|
||||
print('Isi byte array (hex):');
|
||||
if (bytes.length <= 1000) { // Batasi tampilan untuk mencegah output terlalu panjang
|
||||
if (bytes.length <= 1000) {
|
||||
// Batasi tampilan untuk mencegah output terlalu panjang
|
||||
print(bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(' '));
|
||||
} else {
|
||||
print('Terlalu banyak byte untuk ditampilkan (${bytes.length} bytes)');
|
||||
|
@ -355,7 +338,8 @@ class EscPosPrintService {
|
|||
throw SocketException('Koneksi ke printer terputus: ${e.message}');
|
||||
} on PlatformException catch (e) {
|
||||
print('Platform error saat mengirim perintah cetak ke printer: $e');
|
||||
throw PlatformException(code: e.code, message: 'Error printer: ${e.message}');
|
||||
throw PlatformException(
|
||||
code: e.code, message: 'Error printer: ${e.message}');
|
||||
} catch (printError) {
|
||||
print('Error saat mengirim perintah cetak ke printer: $printError');
|
||||
throw Exception('Gagal mengirim perintah cetak: $printError');
|
||||
|
|
|
@ -15,8 +15,9 @@ class FireflyApiService {
|
|||
required String accessToken,
|
||||
String? type,
|
||||
}) async {
|
||||
final uri =
|
||||
type != null ? Uri.parse('$baseUrl/api/v1/accounts?type=$type') : Uri.parse('$baseUrl/api/v1/accounts');
|
||||
final uri = type != null
|
||||
? Uri.parse('$baseUrl/api/v1/accounts?type=$type')
|
||||
: Uri.parse('$baseUrl/api/v1/accounts');
|
||||
|
||||
final response = await http.get(
|
||||
uri,
|
||||
|
@ -29,7 +30,8 @@ class FireflyApiService {
|
|||
if (response.statusCode == 200) {
|
||||
final dynamic responseBody = json.decode(response.body);
|
||||
|
||||
if (responseBody is Map<String, dynamic> && responseBody.containsKey('data')) {
|
||||
if (responseBody is Map<String, dynamic> &&
|
||||
responseBody.containsKey('data')) {
|
||||
final List accountsJson = responseBody['data'] as List;
|
||||
|
||||
final List<FireflyAccount> accounts = accountsJson
|
||||
|
@ -94,7 +96,6 @@ class FireflyApiService {
|
|||
|
||||
if (responseBody is Map<String, dynamic> &&
|
||||
responseBody.containsKey('data')) {
|
||||
|
||||
final dynamic data = responseBody['data'];
|
||||
|
||||
// Handle case where data is a single object with an 'id' field
|
||||
|
@ -173,7 +174,7 @@ class FireflyApiService {
|
|||
/// Menguji koneksi ke Firefly III.
|
||||
static Future<bool> testConnection({required String baseUrl}) async {
|
||||
try {
|
||||
final response = await http.get(Uri.parse('$baseUrl/api/v1/about'));
|
||||
final response = await http.get(Uri.parse(baseUrl));
|
||||
return response.statusCode == 200;
|
||||
} catch (e) {
|
||||
return false;
|
||||
|
@ -181,7 +182,8 @@ class FireflyApiService {
|
|||
}
|
||||
|
||||
/// Menguji autentikasi dengan token.
|
||||
static Future<bool> testAuthentication({required String baseUrl, required String accessToken}) async {
|
||||
static Future<bool> testAuthentication(
|
||||
{required String baseUrl, required String accessToken}) async {
|
||||
try {
|
||||
final response = await http.get(
|
||||
Uri.parse('$baseUrl/api/v1/about/user'),
|
||||
|
@ -196,3 +198,4 @@ class FireflyApiService {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,8 @@ class PrintService {
|
|||
// Detail tanggal dan ID transaksi
|
||||
list.add(LineText(
|
||||
type: LineText.TYPE_TEXT,
|
||||
content: 'Tanggal: ${DateFormat('dd/MM/yyyy HH:mm').format(transaction.timestamp)}',
|
||||
content:
|
||||
'Tanggal: ${DateFormat('dd/MM/yyyy HH:mm').format(transaction.timestamp)}',
|
||||
align: LineText.ALIGN_LEFT));
|
||||
|
||||
list.add(LineText(
|
||||
|
@ -62,7 +63,8 @@ class PrintService {
|
|||
final itemTotal = item.price * item.quantity;
|
||||
list.add(LineText(
|
||||
type: LineText.TYPE_TEXT,
|
||||
content: 'Rp ${CurrencyFormat.formatRupiahWithoutSymbol(itemTotal)}',
|
||||
content:
|
||||
'Rp ${CurrencyFormat.formatRupiahWithoutSymbol(itemTotal)}',
|
||||
align: LineText.ALIGN_RIGHT,
|
||||
linefeed: 1));
|
||||
}
|
||||
|
@ -82,7 +84,8 @@ class PrintService {
|
|||
|
||||
list.add(LineText(
|
||||
type: LineText.TYPE_TEXT,
|
||||
content: 'Rp ${CurrencyFormat.formatRupiahWithoutSymbol(transaction.total)}',
|
||||
content:
|
||||
'Rp ${CurrencyFormat.formatRupiahWithoutSymbol(transaction.total)}',
|
||||
weight: 2,
|
||||
align: LineText.ALIGN_RIGHT,
|
||||
linefeed: 1));
|
||||
|
@ -139,3 +142,4 @@ class PrintService {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,9 +28,10 @@ class _ReceiptItemListState extends State<ReceiptItemList> {
|
|||
return Column(
|
||||
children: [
|
||||
// Baris tabel keterangan
|
||||
Row(
|
||||
const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
SizedBox(width: 5),
|
||||
Expanded(
|
||||
flex: 4,
|
||||
child: Text(
|
||||
|
@ -79,6 +80,7 @@ class _ReceiptItemListState extends State<ReceiptItemList> {
|
|||
textAlign: TextAlign.right,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 5),
|
||||
],
|
||||
),
|
||||
// Garis pembatas
|
||||
|
@ -124,3 +126,4 @@ class _ReceiptItemListState extends State<ReceiptItemList> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,15 +46,13 @@ class ReceiptSpeedDial extends StatelessWidget {
|
|||
: () {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text(
|
||||
'Pilih akun sumber dan tujuan terlebih dahulu'),
|
||||
content:
|
||||
Text('Pilih akun sumber dan tujuan terlebih dahulu'),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
},
|
||||
backgroundColor: hasItems &&
|
||||
hasSourceAccount &&
|
||||
hasDestinationAccount
|
||||
backgroundColor: hasItems && hasSourceAccount && hasDestinationAccount
|
||||
? Colors.blue
|
||||
: Colors.grey,
|
||||
),
|
||||
|
@ -72,7 +70,8 @@ class ReceiptSpeedDial extends StatelessWidget {
|
|||
),
|
||||
SpeedDialChild(
|
||||
child: bluetoothService.isPrinting
|
||||
? const CircularProgressIndicator(color: Colors.white, strokeWidth: 2)
|
||||
? const CircularProgressIndicator(
|
||||
color: Colors.white, strokeWidth: 2)
|
||||
: const Icon(Icons.receipt),
|
||||
label: 'Cetak Struk',
|
||||
onTap: bluetoothService.isPrinting
|
||||
|
@ -91,43 +90,50 @@ class ReceiptSpeedDial extends StatelessWidget {
|
|||
if (bluetoothService.connectedDevice != null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Mencoba menyambungkan ke printer...')),
|
||||
content:
|
||||
Text('Mencoba menyambungkan ke printer...')),
|
||||
);
|
||||
try {
|
||||
bool connectResult = await bluetoothService.connectToDevice(bluetoothService.connectedDevice!);
|
||||
bool connectResult =
|
||||
await bluetoothService.connectToDevice(
|
||||
bluetoothService.connectedDevice!);
|
||||
if (!connectResult) {
|
||||
throw Exception('Gagal menyambungkan ke printer');
|
||||
}
|
||||
// Tunggu sebentar untuk memastikan koneksi stabil
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
await Future.delayed(
|
||||
const Duration(milliseconds: 500));
|
||||
// Periksa koneksi lagi
|
||||
final isConnectedAfterConnect = await onCheckConnection();
|
||||
final isConnectedAfterConnect =
|
||||
await onCheckConnection();
|
||||
if (isConnectedAfterConnect) {
|
||||
await onPrint();
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Gagal menyambungkan ke printer')),
|
||||
content:
|
||||
Text('Gagal menyambungkan ke printer')),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Gagal menyambungkan ke printer: $e')),
|
||||
content:
|
||||
Text('Gagal menyambungkan ke printer: $e')),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Hubungkan printer terlebih dahulu')),
|
||||
content:
|
||||
Text('Hubungkan printer terlebih dahulu')),
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Tangani error secara umum
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Terjadi kesalahan: $e')),
|
||||
SnackBar(content: Text('Terjadi kesalahan: $e')),
|
||||
);
|
||||
} finally {
|
||||
// Pastikan printing status selalu diakhiri
|
||||
|
@ -140,3 +146,4 @@ class ReceiptSpeedDial extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue