chore: normalize line endings (CRLF -> LF)

No content changes: git diff --ignore-all-space over these files is empty.
The churn came from editing on Windows against a repo checked out with LF.
This commit is contained in:
fhanyuh committed 2026-08-27 10:40:49 +07:00
1 parent 15566a6951
commit caf8e98378
315 files changed
+86950 -86950

No files matched your search

+235 -235
View File
@@ -1,235 +1,235 @@
import 'package:flutter/widgets.dart' show AssetImage;
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:printing/printing.dart';
import '../../models/document_model.dart';
class PdfService {
static Future<void> generateAndPrintReceipt(DocumentModel document) async {
final pdf = pw.Document();
// Load PFM logo asset
final logoImage = await flutterImageProvider(const AssetImage('assets/logo.png'));
final isProductScan = document.docType == 'Product';
// Add page
pdf.addPage(
pw.Page(
pageFormat: PdfPageFormat.a4,
build: (pw.Context context) {
return pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.start,
children: [
// Header & Title
pw.Row(
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
children: [
pw.Text(
isProductScan ? 'BUKTI VERIFIKASI SCAN PRODUK' : 'TANDA TERIMA PENGIRIMAN',
style: pw.TextStyle(fontSize: 22, fontWeight: pw.FontWeight.bold)
),
pw.SizedBox(
width: 60,
height: 60,
child: pw.Image(logoImage),
),
]
),
pw.SizedBox(height: 20),
// Document Headers
pw.Container(
padding: const pw.EdgeInsets.all(10),
decoration: pw.BoxDecoration(
border: pw.Border.all(color: PdfColors.grey),
borderRadius: const pw.BorderRadius.all(pw.Radius.circular(8)),
),
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.start,
children: isProductScan
? [
_buildTextRow('Tanggal Scan', document.tanggal),
_buildTextRow('Toko / Cabang', document.kepadaYth),
_buildTextRow('Jenis Verifikasi', 'Pemindaian Produk & Kadaluwarsa'),
]
: [
_buildTextRow('Tanggal', document.tanggal),
_buildTextRow('No PO', document.noPo),
_buildTextRow('No SO', document.noSo),
_buildTextRow('No DO', document.noDo),
]
),
),
pw.SizedBox(height: 20),
// Detail Scan / Pengiriman Section
pw.Text(
isProductScan ? 'Informasi Verifikasi' : 'Detail Pengiriman',
style: pw.TextStyle(fontSize: 16, fontWeight: pw.FontWeight.bold)
),
pw.SizedBox(height: 8),
pw.Container(
padding: const pw.EdgeInsets.all(10),
decoration: pw.BoxDecoration(
color: PdfColors.grey100,
borderRadius: const pw.BorderRadius.all(pw.Radius.circular(8)),
),
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.start,
children: isProductScan
? [
_buildTextRow('Nama Produk', document.items.isNotEmpty ? document.items.first.namaBarang : '-'),
_buildTextRow('Kode SKU', document.items.isNotEmpty ? document.items.first.nomorSku : '-'),
_buildTextRow('Nomor Batch', document.noDo),
_buildTextRow('Tanggal Expired', document.alamat.replaceAll("Product Scan: Expired ", "")),
]
: [
_buildTextRow('Kepada Yth', document.kepadaYth),
_buildTextRow('Order Untuk', document.orderUntuk),
_buildTextRow('Alamat', document.alamat),
_buildTextRow('Plat Truk', document.platTruk),
_buildTextRow('Nama Driver', document.namaDriver),
]
),
),
pw.SizedBox(height: 20),
// Items Table / Scanned Product Details
pw.Text(
isProductScan ? 'Detail Item Scanned' : 'Barang Dikirim',
style: pw.TextStyle(fontSize: 16, fontWeight: pw.FontWeight.bold)
),
pw.SizedBox(height: 8),
isProductScan
? pw.Table.fromTextArray(
context: context,
border: pw.TableBorder.all(color: PdfColors.grey),
headerDecoration: const pw.BoxDecoration(color: PdfColors.grey300),
headerHeight: 25,
cellHeight: 25,
columnWidths: {
0: const pw.FixedColumnWidth(100), // SKU
1: const pw.FlexColumnWidth(2), // Nama Barang
2: const pw.FixedColumnWidth(100), // Batch
3: const pw.FixedColumnWidth(100), // Expired
},
cellAlignments: {
0: pw.Alignment.centerLeft,
1: pw.Alignment.centerLeft,
2: pw.Alignment.center,
3: pw.Alignment.center,
},
headers: ['Nomor SKU', 'Nama Barang', 'Nomor Batch', 'Expired Date'],
data: [
[
document.items.isNotEmpty ? document.items.first.nomorSku : '-',
document.items.isNotEmpty ? document.items.first.namaBarang : '-',
document.noDo,
document.alamat.replaceAll("Product Scan: Expired ", ""),
]
],
)
: pw.Table.fromTextArray(
context: context,
border: pw.TableBorder.all(color: PdfColors.grey),
headerDecoration: const pw.BoxDecoration(color: PdfColors.grey300),
headerHeight: 25,
cellHeight: 25,
columnWidths: {
0: const pw.FixedColumnWidth(80), // SKU
1: const pw.FlexColumnWidth(2), // Nama Barang
2: const pw.FixedColumnWidth(70), // Banyak
3: const pw.FixedColumnWidth(70), // Jumlah
},
cellAlignments: {
0: pw.Alignment.centerLeft,
1: pw.Alignment.centerLeft,
2: pw.Alignment.centerRight,
3: pw.Alignment.centerRight,
},
headers: ['Nomor SKU', 'Nama Barang', 'Banyak', 'Jumlah'],
data: document.items.map((item) {
return [
item.nomorSku,
item.namaBarang,
item.banyak,
item.jumlah,
];
}).toList(),
),
pw.Spacer(),
// Footer & Signatures
pw.Row(
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
children: isProductScan
? [
pw.Column(
children: [
pw.SizedBox(height: 40),
pw.Text('_______________________', style: pw.TextStyle(fontWeight: pw.FontWeight.bold)),
pw.SizedBox(height: 4),
pw.Text('Petugas / Staff Toko'),
]
),
pw.Column(
children: [
pw.SizedBox(height: 40),
pw.Text('_______________________', style: pw.TextStyle(fontWeight: pw.FontWeight.bold)),
pw.SizedBox(height: 4),
pw.Text('Penanggung Jawab Toko'),
]
)
]
: [
pw.Column(
children: [
pw.SizedBox(height: 40),
pw.Text(document.namaDriver.isNotEmpty ? document.namaDriver : '_______________________', style: pw.TextStyle(fontWeight: pw.FontWeight.bold)),
pw.SizedBox(height: 4),
pw.Text('Pengirim (Driver)'),
]
),
pw.Column(
children: [
pw.SizedBox(height: 40),
pw.Text(document.namaPenerima.isNotEmpty ? document.namaPenerima : '_______________________', style: pw.TextStyle(fontWeight: pw.FontWeight.bold)),
pw.SizedBox(height: 4),
pw.Text('Penerima (Penjaga Toko)'),
]
)
]
)
],
);
},
),
);
// Prompt user to view/print/save the PDF natively
await Printing.layoutPdf(
onLayout: (PdfPageFormat format) async => pdf.save(),
format: PdfPageFormat.a4,
name: isProductScan
? 'ProductScan_${document.items.isNotEmpty ? document.items.first.nomorSku : "unknown"}'
: 'Document_${document.noDo.replaceAll('/', '_')}',
);
}
static pw.Widget _buildTextRow(String label, String value) {
return pw.Padding(
padding: const pw.EdgeInsets.symmetric(vertical: 2),
child: pw.Row(
crossAxisAlignment: pw.CrossAxisAlignment.start,
children: [
pw.SizedBox(width: 100, child: pw.Text(label, style: pw.TextStyle(fontWeight: pw.FontWeight.bold))),
pw.Expanded(
child: pw.Text(': $value', softWrap: true),
),
]
)
);
}
}
import 'package:flutter/widgets.dart' show AssetImage;
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:printing/printing.dart';
import '../../models/document_model.dart';
class PdfService {
static Future<void> generateAndPrintReceipt(DocumentModel document) async {
final pdf = pw.Document();
// Load PFM logo asset
final logoImage = await flutterImageProvider(const AssetImage('assets/logo.png'));
final isProductScan = document.docType == 'Product';
// Add page
pdf.addPage(
pw.Page(
pageFormat: PdfPageFormat.a4,
build: (pw.Context context) {
return pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.start,
children: [
// Header & Title
pw.Row(
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
children: [
pw.Text(
isProductScan ? 'BUKTI VERIFIKASI SCAN PRODUK' : 'TANDA TERIMA PENGIRIMAN',
style: pw.TextStyle(fontSize: 22, fontWeight: pw.FontWeight.bold)
),
pw.SizedBox(
width: 60,
height: 60,
child: pw.Image(logoImage),
),
]
),
pw.SizedBox(height: 20),
// Document Headers
pw.Container(
padding: const pw.EdgeInsets.all(10),
decoration: pw.BoxDecoration(
border: pw.Border.all(color: PdfColors.grey),
borderRadius: const pw.BorderRadius.all(pw.Radius.circular(8)),
),
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.start,
children: isProductScan
? [
_buildTextRow('Tanggal Scan', document.tanggal),
_buildTextRow('Toko / Cabang', document.kepadaYth),
_buildTextRow('Jenis Verifikasi', 'Pemindaian Produk & Kadaluwarsa'),
]
: [
_buildTextRow('Tanggal', document.tanggal),
_buildTextRow('No PO', document.noPo),
_buildTextRow('No SO', document.noSo),
_buildTextRow('No DO', document.noDo),
]
),
),
pw.SizedBox(height: 20),
// Detail Scan / Pengiriman Section
pw.Text(
isProductScan ? 'Informasi Verifikasi' : 'Detail Pengiriman',
style: pw.TextStyle(fontSize: 16, fontWeight: pw.FontWeight.bold)
),
pw.SizedBox(height: 8),
pw.Container(
padding: const pw.EdgeInsets.all(10),
decoration: pw.BoxDecoration(
color: PdfColors.grey100,
borderRadius: const pw.BorderRadius.all(pw.Radius.circular(8)),
),
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.start,
children: isProductScan
? [
_buildTextRow('Nama Produk', document.items.isNotEmpty ? document.items.first.namaBarang : '-'),
_buildTextRow('Kode SKU', document.items.isNotEmpty ? document.items.first.nomorSku : '-'),
_buildTextRow('Nomor Batch', document.noDo),
_buildTextRow('Tanggal Expired', document.alamat.replaceAll("Product Scan: Expired ", "")),
]
: [
_buildTextRow('Kepada Yth', document.kepadaYth),
_buildTextRow('Order Untuk', document.orderUntuk),
_buildTextRow('Alamat', document.alamat),
_buildTextRow('Plat Truk', document.platTruk),
_buildTextRow('Nama Driver', document.namaDriver),
]
),
),
pw.SizedBox(height: 20),
// Items Table / Scanned Product Details
pw.Text(
isProductScan ? 'Detail Item Scanned' : 'Barang Dikirim',
style: pw.TextStyle(fontSize: 16, fontWeight: pw.FontWeight.bold)
),
pw.SizedBox(height: 8),
isProductScan
? pw.Table.fromTextArray(
context: context,
border: pw.TableBorder.all(color: PdfColors.grey),
headerDecoration: const pw.BoxDecoration(color: PdfColors.grey300),
headerHeight: 25,
cellHeight: 25,
columnWidths: {
0: const pw.FixedColumnWidth(100), // SKU
1: const pw.FlexColumnWidth(2), // Nama Barang
2: const pw.FixedColumnWidth(100), // Batch
3: const pw.FixedColumnWidth(100), // Expired
},
cellAlignments: {
0: pw.Alignment.centerLeft,
1: pw.Alignment.centerLeft,
2: pw.Alignment.center,
3: pw.Alignment.center,
},
headers: ['Nomor SKU', 'Nama Barang', 'Nomor Batch', 'Expired Date'],
data: [
[
document.items.isNotEmpty ? document.items.first.nomorSku : '-',
document.items.isNotEmpty ? document.items.first.namaBarang : '-',
document.noDo,
document.alamat.replaceAll("Product Scan: Expired ", ""),
]
],
)
: pw.Table.fromTextArray(
context: context,
border: pw.TableBorder.all(color: PdfColors.grey),
headerDecoration: const pw.BoxDecoration(color: PdfColors.grey300),
headerHeight: 25,
cellHeight: 25,
columnWidths: {
0: const pw.FixedColumnWidth(80), // SKU
1: const pw.FlexColumnWidth(2), // Nama Barang
2: const pw.FixedColumnWidth(70), // Banyak
3: const pw.FixedColumnWidth(70), // Jumlah
},
cellAlignments: {
0: pw.Alignment.centerLeft,
1: pw.Alignment.centerLeft,
2: pw.Alignment.centerRight,
3: pw.Alignment.centerRight,
},
headers: ['Nomor SKU', 'Nama Barang', 'Banyak', 'Jumlah'],
data: document.items.map((item) {
return [
item.nomorSku,
item.namaBarang,
item.banyak,
item.jumlah,
];
}).toList(),
),
pw.Spacer(),
// Footer & Signatures
pw.Row(
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
children: isProductScan
? [
pw.Column(
children: [
pw.SizedBox(height: 40),
pw.Text('_______________________', style: pw.TextStyle(fontWeight: pw.FontWeight.bold)),
pw.SizedBox(height: 4),
pw.Text('Petugas / Staff Toko'),
]
),
pw.Column(
children: [
pw.SizedBox(height: 40),
pw.Text('_______________________', style: pw.TextStyle(fontWeight: pw.FontWeight.bold)),
pw.SizedBox(height: 4),
pw.Text('Penanggung Jawab Toko'),
]
)
]
: [
pw.Column(
children: [
pw.SizedBox(height: 40),
pw.Text(document.namaDriver.isNotEmpty ? document.namaDriver : '_______________________', style: pw.TextStyle(fontWeight: pw.FontWeight.bold)),
pw.SizedBox(height: 4),
pw.Text('Pengirim (Driver)'),
]
),
pw.Column(
children: [
pw.SizedBox(height: 40),
pw.Text(document.namaPenerima.isNotEmpty ? document.namaPenerima : '_______________________', style: pw.TextStyle(fontWeight: pw.FontWeight.bold)),
pw.SizedBox(height: 4),
pw.Text('Penerima (Penjaga Toko)'),
]
)
]
)
],
);
},
),
);
// Prompt user to view/print/save the PDF natively
await Printing.layoutPdf(
onLayout: (PdfPageFormat format) async => pdf.save(),
format: PdfPageFormat.a4,
name: isProductScan
? 'ProductScan_${document.items.isNotEmpty ? document.items.first.nomorSku : "unknown"}'
: 'Document_${document.noDo.replaceAll('/', '_')}',
);
}
static pw.Widget _buildTextRow(String label, String value) {
return pw.Padding(
padding: const pw.EdgeInsets.symmetric(vertical: 2),
child: pw.Row(
crossAxisAlignment: pw.CrossAxisAlignment.start,
children: [
pw.SizedBox(width: 100, child: pw.Text(label, style: pw.TextStyle(fontWeight: pw.FontWeight.bold))),
pw.Expanded(
child: pw.Text(': $value', softWrap: true),
),
]
)
);
}
}