171 lines
5.5 KiB
Dart
171 lines
5.5 KiB
Dart
import 'dart:io';
|
|
import 'package:path_provider/path_provider.dart';
|
|
import 'package:pdf/widgets.dart' as pw;
|
|
import 'package:cashumit/models/receipt_item.dart';
|
|
import 'package:open_file/open_file.dart';
|
|
|
|
class PdfExportService {
|
|
static Future<String?> generateReceiptPdf(
|
|
List<ReceiptItem> items,
|
|
String storeName,
|
|
String storeAddress,
|
|
String storePhone,
|
|
) async {
|
|
try {
|
|
final pdf = pw.Document();
|
|
|
|
pdf.addPage(
|
|
pw.Page(
|
|
build: (pw.Context context) => pw.Column(
|
|
children: [
|
|
// Header
|
|
pw.Text(
|
|
storeName,
|
|
style: pw.TextStyle(
|
|
fontSize: 20,
|
|
fontWeight: pw.FontWeight.bold,
|
|
),
|
|
textAlign: pw.TextAlign.center,
|
|
),
|
|
pw.SizedBox(height: 4),
|
|
pw.Text(storeAddress, textAlign: pw.TextAlign.center),
|
|
pw.Text(storePhone, textAlign: pw.TextAlign.center),
|
|
pw.SizedBox(height: 8),
|
|
pw.Divider(),
|
|
pw.SizedBox(height: 8),
|
|
|
|
// Item list header
|
|
pw.Row(
|
|
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
pw.Expanded(
|
|
flex: 3,
|
|
child: pw.Text(
|
|
'ITEM',
|
|
style: pw.TextStyle(fontWeight: pw.FontWeight.bold),
|
|
),
|
|
),
|
|
pw.Expanded(
|
|
flex: 1,
|
|
child: pw.Text(
|
|
'QTY',
|
|
style: pw.TextStyle(fontWeight: pw.FontWeight.bold),
|
|
textAlign: pw.TextAlign.center,
|
|
),
|
|
),
|
|
pw.Expanded(
|
|
flex: 2,
|
|
child: pw.Text(
|
|
'HARGA',
|
|
style: pw.TextStyle(fontWeight: pw.FontWeight.bold),
|
|
textAlign: pw.TextAlign.right,
|
|
),
|
|
),
|
|
pw.Expanded(
|
|
flex: 2,
|
|
child: pw.Text(
|
|
'TOTAL',
|
|
style: pw.TextStyle(fontWeight: pw.FontWeight.bold),
|
|
textAlign: pw.TextAlign.right,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
pw.SizedBox(height: 4),
|
|
pw.Divider(),
|
|
pw.SizedBox(height: 8),
|
|
|
|
// Items
|
|
...items.map(
|
|
(item) => pw.Padding(
|
|
padding: const pw.EdgeInsets.only(bottom: 4.0),
|
|
child: pw.Row(
|
|
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
pw.Expanded(
|
|
flex: 3,
|
|
child: pw.Text(
|
|
item.description,
|
|
style: const pw.TextStyle(fontSize: 14),
|
|
),
|
|
),
|
|
pw.Expanded(
|
|
flex: 1,
|
|
child: pw.Text(
|
|
item.quantity.toString(),
|
|
textAlign: pw.TextAlign.center,
|
|
style: const pw.TextStyle(fontSize: 14),
|
|
),
|
|
),
|
|
pw.Expanded(
|
|
flex: 2,
|
|
child: pw.Text(
|
|
item.price.toStringAsFixed(0),
|
|
textAlign: pw.TextAlign.right,
|
|
style: const pw.TextStyle(fontSize: 14),
|
|
),
|
|
),
|
|
pw.Expanded(
|
|
flex: 2,
|
|
child: pw.Text(
|
|
item.total.toStringAsFixed(0),
|
|
textAlign: pw.TextAlign.right,
|
|
style: const pw.TextStyle(fontSize: 14),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
|
|
pw.SizedBox(height: 8),
|
|
pw.Divider(),
|
|
pw.SizedBox(height: 8),
|
|
|
|
// Total
|
|
pw.Row(
|
|
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
pw.Text(
|
|
'TOTAL:',
|
|
style: pw.TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: pw.FontWeight.bold,
|
|
),
|
|
),
|
|
pw.Text(
|
|
items.fold(0.0, (sum, item) => sum + item.total).toStringAsFixed(0),
|
|
style: pw.TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: pw.FontWeight.bold,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
|
|
// Dapatkan direktori dokumen
|
|
final dir = await getApplicationDocumentsDirectory();
|
|
final file = File("${dir.path}/receipt.pdf");
|
|
final pdfBytes = await pdf.save();
|
|
await file.writeAsBytes(pdfBytes);
|
|
|
|
return file.path;
|
|
} catch (e) {
|
|
// Handle error
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// Membuka file PDF yang telah dibuat
|
|
static Future<void> openPdf(String filePath) async {
|
|
try {
|
|
await OpenFile.open(filePath);
|
|
} catch (e) {
|
|
// Handle error
|
|
}
|
|
}
|
|
} |