apskel-pos-flutter/lib/core/utils/transaction_sales_invoice.dart
2025-08-03 14:39:15 +07:00

163 lines
4.5 KiB
Dart

import 'dart:io';
import 'package:enaklo_pos/core/extensions/date_time_ext.dart';
import 'package:enaklo_pos/core/extensions/int_ext.dart';
import 'package:flutter/services.dart';
import 'package:enaklo_pos/core/utils/helper_pdf_service.dart';
import 'package:enaklo_pos/data/models/response/order_response_model.dart';
import 'package:pdf/widgets.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
class TransactionSalesInvoice {
static late Font ttf;
static Future<File> generate(
List<Order> itemOrders, String searchDateFormatted) async {
final pdf = Document();
// var data = await rootBundle.load("assets/fonts/noto-sans.ttf");
// ttf = Font.ttf(data);
final ByteData dataImage = await rootBundle.load('assets/images/logo.png');
final Uint8List bytes = dataImage.buffer.asUint8List();
// Membuat objek Image dari gambar
final image = pw.MemoryImage(bytes);
pdf.addPage(
MultiPage(
build: (context) => [
buildHeader(image, searchDateFormatted),
SizedBox(height: 1 * PdfPageFormat.cm),
buildInvoice(itemOrders),
Divider(),
SizedBox(height: 0.25 * PdfPageFormat.cm),
],
footer: (context) => buildFooter(),
),
);
return HelperPdfService.saveDocument(
name:
'Apskel POS | Transaction Sales Report | ${DateTime.now().millisecondsSinceEpoch}.pdf',
pdf: pdf);
}
static Widget buildHeader(MemoryImage image, String searchDateFormatted) =>
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 1 * PdfPageFormat.cm),
Text('Apskel POS | Transaction Sales Report',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
)),
SizedBox(height: 0.2 * PdfPageFormat.cm),
Text(
"Data: $searchDateFormatted",
),
Text(
'Created At: ${DateTime.now().toFormattedDate3()}',
),
],
),
Image(
image,
width: 80.0,
height: 80.0,
fit: BoxFit.fill,
),
]);
static Widget buildInvoice(List<Order> itemOrders) {
final headers = [
'Total',
'Sub Total',
'Tax',
'Discount',
'Service',
'Time'
];
final data = itemOrders.map((item) {
return [
item.totalAmount!.currencyFormatRp,
item.subtotal!.currencyFormatRp,
item.taxAmount!.currencyFormatRp,
int.parse(item.discountAmount!.toString().replaceAll('.00', ''))
.currencyFormatRp,
0,
item.createdAt!.toFormattedDate2(),
];
}).toList();
return Table.fromTextArray(
headers: headers,
data: data,
border: null,
headerStyle: TextStyle(
fontWeight: FontWeight.bold, color: PdfColor.fromHex('FFFFFF')),
headerDecoration: BoxDecoration(color: PdfColors.blue),
cellHeight: 30,
cellAlignments: {
0: Alignment.center,
1: Alignment.center,
2: Alignment.center,
3: Alignment.center,
4: Alignment.center,
5: Alignment.center,
},
);
}
static Widget buildFooter() => Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Divider(),
SizedBox(height: 2 * PdfPageFormat.mm),
buildSimpleText(
title: 'Address',
value:
'Jalan Melati No. 12, Mranggen, Demak, Central Java, 89568'),
SizedBox(height: 1 * PdfPageFormat.mm),
],
);
static buildSimpleText({
required String title,
required String value,
}) {
final style = TextStyle(fontWeight: FontWeight.bold);
return Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: pw.CrossAxisAlignment.end,
children: [
Text(title, style: style),
SizedBox(width: 2 * PdfPageFormat.mm),
Text(value),
],
);
}
static buildText({
required String title,
required String value,
double width = double.infinity,
TextStyle? titleStyle,
bool unite = false,
}) {
final style = titleStyle ?? TextStyle(fontWeight: FontWeight.bold);
return Container(
width: width,
child: Row(
children: [
Expanded(child: Text(title, style: style)),
Text(value, style: unite ? style : null),
],
),
);
}
}