Skip to content

Instantly share code, notes, and snippets.

@gboliknow
Created June 18, 2025 16:58
Show Gist options
  • Save gboliknow/9df593e3505f3cb03f09bfa063597728 to your computer and use it in GitHub Desktop.
Save gboliknow/9df593e3505f3cb03f09bfa063597728 to your computer and use it in GitHub Desktop.
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.a4,
margin: const pw.EdgeInsets.all(24),
build: (pw.Context context) {
return [
_buildStoreInfoSection(invoice, formattedDate, storeLogo),
pw.SizedBox(height: 24),
_buildBillToInfo(invoice),
pw.SizedBox(height: 24),
_buildInvoiceSummaryCard(invoice, itemImages),
pw.SizedBox(height: 24),
if (invoice.termsAndConditions != "") _buildTermsAndConditions(invoice.termsAndConditions),
if (invoice.supportingImages.isNotEmpty) ...[
pw.SizedBox(height: 10),
_buildSupportingImages(invoice.supportingImages, supportingImages),
pw.SizedBox(height: 10),
],
pw.SizedBox(height: 40),
_buildFooter(vendawLogo),
];
},
),
);
//InvoiceSummaryCard Section
static pw.Widget _buildInvoiceSummaryCard(InvoiceModel invoice, Map<String, pw.MemoryImage> loadedItemImages) {
return pw.Container(
decoration: pw.BoxDecoration(
border: pw.Border.all(color: flutterToPdfColor(AppColors.grey100)),
borderRadius: pw.BorderRadius.circular(8),
),
child: pw.Column(
children: [
_buildInvoiceSummaryHeader(),
_buildInvoiceItemList(invoice, loadedItemImages),
_buildInvoiceSummaryDetails(invoice),
_buildPaymentScheduleSection(invoice),
],
),
);
}
static pw.Widget _buildInvoiceItemList(InvoiceModel invoice, Map<String, pw.MemoryImage> loadedItemImages) {
return pw.Padding(
padding: const pw.EdgeInsets.all(8),
child: pw.Column(
mainAxisSize: pw.MainAxisSize.min,
children: invoice.items
.map(
(item) => pw.Padding(
padding: const pw.EdgeInsets.only(bottom: 12),
child: _buildInvoiceSummaryItem(item, loadedItemImages),
),
)
.toList(),
),
);
}
static pw.Widget _buildInvoiceSummaryDetails(InvoiceModel invoice) {
double total = (invoice.total - invoice.fee).toDouble();
return pw.Padding(
padding: const pw.EdgeInsets.symmetric(horizontal: 8),
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.start,
children: [
// pw.SizedBox(height: 8),
_buildDottedLine(),
pw.SizedBox(height: 16),
_buildOrderSummaryPriceInfo("Subtotal", AppUtils.formatCurrencyWithoutSymbol(invoice.subtotal.toDouble())),
pw.SizedBox(height: 8),
_buildOrderSummaryPriceInfo("Discount", AppUtils.formatCurrencyWithoutSymbol(invoice.discount.toDouble())),
pw.SizedBox(height: 8),
_buildOrderSummaryPriceInfo(
"Delivery Fee", AppUtils.formatCurrencyWithoutSymbol(invoice.deliveryFee.toDouble())),
if (invoice.damagesCharge != 0) ...[
pw.SizedBox(height: 8),
_buildOrderSummaryPriceInfo(
"Damages Charge", AppUtils.formatCurrencyWithoutSymbol(invoice.damagesCharge.toDouble())),
],
if (invoice.serviceCharge != 0) ...[
pw.SizedBox(height: 8),
_buildOrderSummaryPriceInfo(
"Service Charge", AppUtils.formatCurrencyWithoutSymbol(invoice.serviceCharge.toDouble())),
],
if (invoice.vat != 0) ...[
pw.SizedBox(height: 8),
_buildOrderSummaryPriceInfo("VAT", "${invoice.vat}%", isPrice: false),
],
pw.SizedBox(height: 4),
pw.Container(
height: 1,
width: double.infinity,
color: flutterToPdfColor(AppColors.grey300),
),
pw.SizedBox(height: 4),
if (invoice.status.toLowerCase() == "partial_payment")
_buildOrderSummaryPriceInfo(
"Amount Paid",
AppUtils.formatCurrencyWithoutSymbol(
invoice.payments.isEmpty ? 0.0 : double.parse(invoice.payments.first.amount)),
isBold: true,
)
else
_buildOrderSummaryPriceInfo(
"Amount Paid",
AppUtils.formatCurrencyWithoutSymbol(total),
isBold: true,
),
pw.SizedBox(height: 8),
],
),
);
}
static pw.Widget _buildPaymentScheduleSection(InvoiceModel invoice) {
final sortedSchedule = [...invoice.paymentSchedule]
..sort((a, b) => (a.dueDate ?? DateTime(2100)).compareTo(b.dueDate ?? DateTime(2100)));
if (sortedSchedule.isEmpty) return pw.SizedBox();
return pw.Container(
width: double.infinity,
padding: const pw.EdgeInsets.all(8),
decoration: pw.BoxDecoration(
color: flutterToPdfColor(AppColors.invoiceGrey),
borderRadius: const pw.BorderRadius.only(
bottomLeft: pw.Radius.circular(8),
bottomRight: pw.Radius.circular(8),
),
),
child: pw.Column(
children: sortedSchedule.asMap().entries.map((entry) {
final index = entry.key;
final schedule = entry.value;
return pw.Container(
margin: pw.EdgeInsets.only(bottom: index < sortedSchedule.length - 1 ? 5 : 0),
child: pw.Column(
children: [
_buildPaymentScheduleItem(schedule, index, invoice.allowPartPayment),
if (index < sortedSchedule.length - 1)
pw.Container(
margin: const pw.EdgeInsets.symmetric(vertical: 5),
height: 1,
width: double.infinity,
color: flutterToPdfColor(AppColors.white.withOpacity(0.4)),
),
],
),
);
}).toList(),
),
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment