UNPKG

@casoon/invoice-generator

Version:

Generate PDF invoices, XRechnung XML, and ZUGFeRD PDF/A-3 from JSON data with TypeScript support

104 lines (89 loc) 3.19 kB
import PDFDocument from 'pdfkit'; import fs from 'fs'; import { Invoice, PDFOptions } from '../types/invoice.types'; import { HeaderSection, SalutationSection, ItemsTableSection, ClosingSection, FooterSection } from './sections'; export class PDFGenerator { private doc: PDFKit.PDFDocument; private options: PDFOptions; private currentY: number = 50; constructor(options: PDFOptions = {}) { this.options = { template: 'default', language: 'de', includeLogo: false, logoPath: undefined, ...options }; this.doc = new PDFDocument({ size: 'A4', margin: 50, compress: false, bufferPages: true, info: { Title: 'Invoice', Author: 'Invoice Generator', Subject: 'Invoice Document', Creator: 'PDFKit', Producer: 'PDFKit' } }); this.doc.font('Helvetica').fontSize(10); } public async generateInvoice(invoice: Invoice): Promise<Buffer> { return new Promise((resolve, reject) => { const chunks: Buffer[] = []; this.doc.on('data', (chunk: Buffer) => chunks.push(chunk)); this.doc.on('end', () => resolve(Buffer.concat(chunks))); this.doc.on('error', reject); this.generateInvoiceContent(invoice); this.doc.end(); }); } public async generateInvoiceToFile(invoice: Invoice, outputPath: string): Promise<void> { return new Promise((resolve, reject) => { const writeStream = fs.createWriteStream(outputPath); this.doc.pipe(writeStream); writeStream.on('finish', resolve); writeStream.on('error', reject); this.doc.on('error', reject); this.generateInvoiceContent(invoice); this.doc.end(); }); } private generateInvoiceContent(invoice: Invoice): void { // Reset Y-Position this.currentY = 50; // Bereich 1: Header mit Adressen und Rechnungsdaten const headerSection = new HeaderSection(this.doc, this.currentY, this.options.logoPath); this.currentY = headerSection.draw(invoice); // Bereich 2: Ansprache zur Rechnung const salutationSection = new SalutationSection(this.doc, this.currentY); this.currentY = salutationSection.draw(invoice); // Bereich 3: Tabelle mit Rechnungspositionen const itemsTableSection = new ItemsTableSection(this.doc, this.currentY); this.currentY = itemsTableSection.draw(invoice); // Bereich 4: Grußformel const closingSection = new ClosingSection(this.doc, this.currentY); this.currentY = closingSection.draw(invoice); // Wiederkehrender Footer const footerSection = new FooterSection(this.doc, this.currentY); this.currentY = footerSection.draw(invoice); } } /** * Convenience-Funktionen für einfache Verwendung */ export async function generateInvoicePDF(invoice: Invoice, options?: PDFOptions): Promise<Buffer> { const generator = new PDFGenerator(options); return generator.generateInvoice(invoice); } export async function generateInvoicePDFToFile(invoice: Invoice, outputPath: string, options?: PDFOptions): Promise<void> { const generator = new PDFGenerator(options); return generator.generateInvoiceToFile(invoice, outputPath); }