invoice_kit 0.1.0 copy "invoice_kit: ^0.1.0" to clipboard
invoice_kit: ^0.1.0 copied to clipboard

Generate customizable invoice, bill, and receipt PDFs in Flutter with multiple templates, JSON-driven layouts, GST support, QR codes, and cross-platform export.

invoice_kit #

pub.dev version License: MIT Supported platforms: Android, iOS, Web, Windows, macOS, Linux

Production-ready Flutter package for generating customizable invoices, bills, and receipts as PDFs.

Features #

  • ๐ŸŽจ 5 Built-in Templates: Classic (B2B with GST), Modern (minimalist), Compact (events/retail), Thermal (80mm POS), JSON-driven (fully dynamic)
  • ๐Ÿ“‹ Dual Data API: Strongly-typed Invoice models OR raw JSON InvoiceData for server-driven flows
  • ๐Ÿ’ฐ GST-Ready: CGST/SGST/IGST breakdown, multi-currency (default โ‚น INR), multi-locale formatting
  • ๐Ÿ”ค Full Unicode Support: Hindi, Tamil, Arabic, Chinese, etc. via Google Fonts (Roboto, Noto Sans)
  • ๐Ÿ“ฑ QR Codes: UPI payment links and custom QR code generation
  • ๐Ÿ–จ๏ธ Cross-Platform Actions: Generate, download, share, print, save to device
  • ๐ŸŒ True Cross-Platform: Android, iOS, Web, Windows, macOS, Linux
  • ๐Ÿงฉ Custom Templates: Implement InvoiceTemplate interface for custom designs
  • ๐Ÿ“Š JSON Templates: White-label and server-driven invoices via JSON specs
  • ๐Ÿ”’ Type-Safe: Sound null safety with comprehensive error handling
  • ๐Ÿงช Well-Tested: Unit tests with 100% pass rate

Installation #

Add to pubspec.yaml:

dependencies:
  invoice_kit: ^0.1.0

Or run:

flutter pub add invoice_kit

Quick Start (30 seconds) #

import 'package:invoice_kit/invoice_kit.dart';

// 1. Create an invoice
final invoice = Invoice(
  number: 'INV-001',
  date: DateTime.now(),
  seller: Party(name: 'My Business'),
  buyer: Party(name: 'John Doe'),
  items: [
    LineItem(
      description: 'Professional Service',
      quantity: 10,
      unitPrice: 1000,
      taxPercent: 18,
    ),
  ],
);

// 2. Generate PDF
final bytes = await InvoiceGenerator.generate(
  invoice: invoice,
  template: ClassicTemplate(),
);

// 3. Download / Share / Print
await InvoiceGenerator.download(
  invoice: invoice,
  filename: 'INV-001.pdf',
);

Platform Behavior #

Feature Web Android iOS Desktop
generate() โœ… Returns Uint8List โœ… โœ… โœ…
preview() โœ… Inline PdfPreview โœ… โœ… โœ…
download() โœ… Browser download โœ… Share sheet โœ… Share sheet โœ… Save dialog
saveToDevice() โš ๏ธ Falls back to download (returns null) โœ… App docs dir โœ… App docs dir โœ… App docs dir
share() โœ… Web Share API or fallback โœ… Native share โœ… Native share โœ… Native share
printDocument() โœ… Browser print โœ… Android print service โœ… AirPrint โœ… System print

Architecture: Conditional Imports #

The package uses Dart's conditional imports to provide platform-specific implementations without bloating the bundle:

  • Web: Uses dart:html for browser downloads + Printing API for print/share
  • Mobile/Desktop: Uses dart:io + path_provider for file I/O
  • Compile-time selection: Your web build doesn't include dart:io, and Android builds don't include dart:html

See lib/src/actions/pdf_actions.dart and related implementation files for details.

Why download() opens a share sheet on Android #

Android's scoped storage (API 29+) restricts direct file system access for security. The recommended UX is to let the user pick the destination via the system share sheet (which download() does). If you need a guaranteed file path, use saveToDevice() which returns the full path to the saved file.

Web font loading & โ‚น rendering #

On web, Google Fonts (Roboto, Noto Sans) are fetched at runtime via the Printing API. The first PDF generation may take ~200ms longer; subsequent calls are cached. The โ‚น symbol and other Unicode characters render correctly out of the box (Noto Sans provides full script support).

Strongly-Typed API #

Perfect for app code with compile-time type safety:

final invoice = Invoice(
  number: 'INV-001',
  date: DateTime.now(),
  seller: Party(
    name: 'Acme Corp',
    address: '123 Business St',
    city: 'New Delhi',
    state: 'DL',
    postalCode: '110001',
    country: 'India',
    gstin: '23ABCDE1234F2G5',
    bankName: 'State Bank of India',
    bankAccount: '00123456789012',
    ifscCode: 'SBIN0001234',
    upiId: 'acme@okhdfcbank',
  ),
  buyer: Party(
    name: 'Customer Name',
    email: 'customer@example.com',
    phone: '+91-9876543210',
    address: '456 Customer Ave',
    city: 'Mumbai',
    state: 'MH',
  ),
  items: [
    LineItem(
      description: 'Web Development Services',
      quantity: 40,
      unitPrice: 2500,
      cgstPercent: 9,
      sgstPercent: 9,
    ),
    LineItem(
      description: 'UI/UX Design',
      quantity: 20,
      unitPrice: 1500,
      discountPercent: 10,
      cgstPercent: 9,
      sgstPercent: 9,
    ),
  ],
  payment: Payment(
    method: 'Bank Transfer',
    bankName: 'HDFC Bank',
    dueDate: DateTime.now().add(Duration(days: 30)),
  ),
  status: 'Issued',
  notes: 'Thank you for your business!',
  terms: 'Payment due within 30 days of invoice date.',
);

// Auto-calculated totals
print(invoice.totals.grandTotal); // Automatically computed

JSON API #

Perfect for server-driven flows and white-label scenarios:

final data = InvoiceData({
  'invoice': {
    'number': 'INV-001',
    'date': DateTime.now().toIso8601String(),
    'status': 'Issued',
  },
  'seller': {
    'name': 'Acme Inc',
    'gstin': '23ABCDE1234F2G5',
    'address': '123 Business St',
    'city': 'New Delhi',
  },
  'buyer': {
    'name': 'Customer',
    'email': 'customer@example.com',
  },
  'items': [
    {
      'description': 'Service',
      'quantity': 1,
      'unitPrice': 5000,
      'taxPercent': 18,
    },
  ],
});

final bytes = await InvoiceGenerator.generate(data: data);

Seamless conversion between both APIs:

// Invoice โ†’ InvoiceData
final data = invoice.toInvoiceData();

// InvoiceData โ†’ Invoice
final invoice = Invoice.fromInvoiceData(data);

Built-in Templates #

1. ClassicTemplate #

Detailed B2B invoice with GST breakdown, bank details, and signature block. Perfect for invoicing and compliance.

final pdf = await ClassicTemplate().build(data);

2. ModernTemplate #

Clean minimalist design with accent color sidebar and generous whitespace. Ideal for agencies, SaaS, and freelancers.

final pdf = await ModernTemplate().build(data);

3. CompactTemplate #

Compact invoice for events, retail, and service businesses. Matches common POS receipt layouts.

final pdf = await CompactTemplate().build(data);

4. ThermalTemplate #

80mm thermal printer receipt for POS systems, restaurants, and retail counters.

final pdf = await ThermalTemplate().build(data);

5. JsonTemplate #

Fully dynamic JSON-driven templates for white-label and server-driven scenarios.

final layoutJson = {
  'id': 'custom_v1',
  'pageFormat': 'A4',
  'body': [
    {'type': 'text', 'content': 'Invoice {{invoice.number}}'},
    {'type': 'items_table'},
    {'type': 'totals_box'},
  ],
};

final pdf = await JsonTemplate(layoutJson).build(data);

Theming #

Customize colors, fonts, images, and more:

final config = TemplateConfig(
  primaryColor: ColorUtils.hexToColor('#4A90B8'),
  logoAssetPath: 'assets/logo.png',
  logoBytes: await loadImageBytes(),
  signatureImagePath: 'assets/signature.png',
  baseFont: await FontLoader.robotoRegular(),
  boldFont: await FontLoader.robotoBold(),
  currencySymbol: 'โ‚น',
  currencyCode: 'INR',
  locale: 'en_IN',
  dateFormat: 'dd-MM-yyyy',
  footerText: 'Thank you for your business!',
  showSignature: true,
  showQrCode: true,
  qrData: 'upi://pay?pa=acme@okhdfcbank&pn=Acme%20Inc&am=5000',
);

final bytes = await InvoiceGenerator.generate(
  invoice: invoice,
  template: ClassicTemplate(),
  config: config,
);

Custom Templates #

Implement the InvoiceTemplate interface:

class MyCustomTemplate extends InvoiceTemplate {
  @override
  String get id => 'my_custom';

  @override
  String get name => 'My Custom Template';

  @override
  String get description => 'My custom invoice design';

  @override
  PdfPageFormat get pageFormat => PdfPageFormat.a4;

  @override
  Future<pw.Document> build(
    InvoiceData data, {
    TemplateConfig? config,
  }) async {
    final fonts = await FontLoader.autoLoad(data);
    final doc = pw.Document();

    doc.addPage(
      pw.Page(
        build: (context) => pw.Center(
          child: pw.Text(
            'Invoice: ${data.get('invoice.number')}',
            style: pw.TextStyle(font: fonts.bold, fontSize: 24),
          ),
        ),
      ),
    );

    return doc;
  }
}

// Use your custom template
final bytes = await InvoiceGenerator.generate(
  invoice: invoice,
  template: MyCustomTemplate(),
);

Placeholder Templating #

Use {{dot.notation.paths}} with optional formatters:

final resolver = PlaceholderResolver(data);

// Simple paths
resolver.resolve('Invoice {{invoice.number}}'); // "Invoice INV-001"

// Array indexing
resolver.resolve('First item: {{items.0.description}}');

// Formatters (pipe syntax)
resolver.resolve('Amount: {{totals.grandTotal | currency}}');
resolver.resolve('Date: {{invoice.date | date:dd-MM-yyyy}}');
resolver.resolve('Name: {{buyer.name | upper}}');

Supported formatters: currency, number, percent, date:pattern, upper, lower, title, trim, length.

Cross-Platform Actions #

All actions work seamlessly across platforms:

// Generate PDF bytes
final bytes = await InvoiceGenerator.generate(invoice: invoice);

// Save to device (mobile/desktop) โ€” returns File
final file = await InvoiceGenerator.saveToDevice(
  invoice: invoice,
  filename: 'INV-001.pdf',
);

// Download (web: browser dialog, mobile: share sheet, desktop: save dialog)
await InvoiceGenerator.download(
  invoice: invoice,
  filename: 'INV-001.pdf',
);

// Native share sheet
await InvoiceGenerator.share(
  invoice: invoice,
  filename: 'INV-001.pdf',
);

// Print dialog with preview
await InvoiceGenerator.printDocument(
  invoice: invoice,
  name: 'INV-001',
);

// Inline preview widget
final widget = InvoiceGenerator.preview(
  invoice: invoice,
  filename: 'INV-001.pdf',
);

GST & Multi-Locale Support #

Indian GST with CGST/SGST/IGST:

final item = LineItem(
  description: 'Service',
  quantity: 1,
  unitPrice: 10000,
  cgstPercent: 9,  // Central GST
  sgstPercent: 9,  // State GST
);

Interstate (IGST):

final item = LineItem(
  description: 'Service',
  quantity: 1,
  unitPrice: 10000,
  igstPercent: 18, // Integrated GST
);

Multi-locale formatting:

final config = TemplateConfig(
  locale: 'en_IN',        // Indian numbering: 1,23,456.78
  dateFormat: 'dd-MM-yyyy',
  currencySymbol: 'โ‚น',
  currencyCode: 'INR',
);

// Or use formatters directly
CurrencyFormatter.format(123456.78, locale: 'en_US'); // 123,456.78
CurrencyFormatter.format(123456.78, locale: 'en_IN'); // 1,23,456.78

QR Codes & Barcodes #

Generate UPI QR codes:

final upiLink = QrHelper.generateUpiLink(
  upiId: 'acme@okhdfcbank',
  payerName: 'Acme Inc',
  amount: 5000,
  description: 'Invoice INV-001',
); // upi://pay?pa=acme@okhdfcbank&pn=Acme%20Inc&am=5000&tn=Invoice%20INV-001

Or create custom QR codes:

final qr = QrHelper.generateQrCode(
  'https://example.com/invoice/INV-001',
  width: 100,
  height: 100,
);

Examples #

See the /example folder for complete demo apps:

  • Home Screen: Gallery of all 5 templates
  • Invoice Form: Build invoices from form input
  • Template Picker: Switch between templates
  • JSON Editor: Edit JSON templates live
  • Theming Demo: Color picker and theme customization
  • GST Demo: Pre-filled Indian B2B invoice
  • POS Demo: Thermal receipt with QR code

Run the example:

cd example
flutter run

API Reference #

Core Classes #

  • Invoice: Strongly-typed invoice model
  • InvoiceData: JSON-backed flexible container
  • InvoiceGenerator: Main public API
  • InvoiceTemplate: Base class for templates
  • TemplateConfig: Customization options
  • Party: Buyer/seller details
  • LineItem: Invoice line items
  • Totals: Auto-calculated totals with tax breakdown
  • Payment: Payment information
  • Tax: Tax breakdown (CGST, SGST, IGST, simple tax)

Utility Classes #

  • CurrencyFormatter: Multi-currency formatting
  • DateFormatter: Localized date formatting
  • NumberFormatter: Locale-specific number separators
  • ColorUtils: Hex โ†” PdfColor conversion
  • FontLoader: Google Fonts with Unicode auto-detection
  • QrHelper: QR code and barcode generation
  • PlaceholderResolver: Template placeholder resolution

Exceptions #

  • InvoiceDataException: Invalid invoice data
  • TemplateException: Template build failure
  • JsonTemplateException: Invalid JSON template
  • RenderingException: PDF generation failure
  • PdfActionException: File I/O failure

Contributing #

Contributions welcome! File issues or open pull requests on GitHub.

License #

MIT License โ€” see LICENSE file for details.

Support #

For questions, issues, or feature requests, visit:

0
likes
130
points
88
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Generate customizable invoice, bill, and receipt PDFs in Flutter with multiple templates, JSON-driven layouts, GST support, QR codes, and cross-platform export.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

barcode_widget, flutter, intl, path_provider, pdf, printing

More

Packages that depend on invoice_kit