172 lines
4.4 KiB
TypeScript
172 lines
4.4 KiB
TypeScript
import { PDFDocument, rgb, StandardFonts } from 'pdf-lib';
|
|
import { readFile } from 'fs/promises';
|
|
import path from 'path';
|
|
import { formatDate } from './date-utils';
|
|
|
|
export async function generateContractFromTemplate(
|
|
booking: any,
|
|
location: any,
|
|
photobox: any,
|
|
signatureData?: string
|
|
) {
|
|
try {
|
|
// Load the template PDF
|
|
const templatePath = path.join(process.cwd(), 'mietvertrag-vorlage.pdf');
|
|
const templateBytes = await readFile(templatePath);
|
|
|
|
// Load PDF
|
|
const pdfDoc = await PDFDocument.load(templateBytes);
|
|
const pages = pdfDoc.getPages();
|
|
const firstPage = pages[0];
|
|
|
|
// Embed font
|
|
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
|
|
const fontBold = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
|
|
|
|
const { width, height } = firstPage.getSize();
|
|
|
|
// PDF coordinate system: (0,0) is bottom-left, Y increases upwards
|
|
// A4 page height is ~842 points
|
|
|
|
// Page 1: Customer Info & Table
|
|
|
|
// Customer name (under "und") - around middle of page
|
|
if (booking.customerName) {
|
|
firstPage.drawText(booking.customerName, {
|
|
x: 250,
|
|
y: 465,
|
|
size: 10,
|
|
font: font,
|
|
color: rgb(0, 0, 0),
|
|
});
|
|
}
|
|
|
|
// Customer address (next line)
|
|
if (booking.customerAddress) {
|
|
firstPage.drawText(
|
|
`${booking.customerAddress}, ${booking.customerZip} ${booking.customerCity}`,
|
|
{
|
|
x: 250,
|
|
y: 450,
|
|
size: 10,
|
|
font: font,
|
|
color: rgb(0, 0, 0),
|
|
}
|
|
);
|
|
}
|
|
|
|
// Distance (in "Lieferung inkl. Aufbau" row)
|
|
if (booking.distance) {
|
|
const distance = booking.distance || 0;
|
|
const totalKm = distance * 2;
|
|
|
|
// Fill in the km field
|
|
firstPage.drawText(`${distance.toFixed(1)}`, {
|
|
x: 735,
|
|
y: 95,
|
|
size: 9,
|
|
font: font,
|
|
color: rgb(0, 0, 0),
|
|
});
|
|
|
|
firstPage.drawText(`${totalKm.toFixed(1)}`, {
|
|
x: 895,
|
|
y: 95,
|
|
size: 9,
|
|
font: font,
|
|
color: rgb(0, 0, 0),
|
|
});
|
|
}
|
|
|
|
// Event location and date (Section 2 - MIETZWECK) - bottom of page 1
|
|
if (booking.eventLocation && booking.eventDate) {
|
|
firstPage.drawText(
|
|
`${booking.eventLocation} am ${formatDate(booking.eventDate)}`,
|
|
{
|
|
x: 100,
|
|
y: 35,
|
|
size: 10,
|
|
font: font,
|
|
color: rgb(0, 0, 0),
|
|
}
|
|
);
|
|
}
|
|
|
|
// Page 2: Mietzeit & Mietpreis
|
|
const secondPage = pages[1];
|
|
|
|
// Event date (Section 3 - MIETZEIT)
|
|
if (booking.eventDate) {
|
|
secondPage.drawText(formatDate(booking.eventDate), {
|
|
x: 210,
|
|
y: height - 85,
|
|
size: 10,
|
|
font: font,
|
|
color: rgb(0, 0, 0),
|
|
});
|
|
}
|
|
|
|
// Price (Section 4 - MIETPREIS)
|
|
if (booking.calculatedPrice) {
|
|
const price = booking.calculatedPrice.toFixed(2);
|
|
secondPage.drawText(`${price}`, {
|
|
x: 475,
|
|
y: height - 165,
|
|
size: 10,
|
|
font: font,
|
|
color: rgb(0, 0, 0),
|
|
});
|
|
}
|
|
|
|
// Signature on last page if provided
|
|
if (signatureData && pages.length >= 4) {
|
|
const lastPage = pages[pages.length - 1];
|
|
|
|
// Convert base64 signature to image
|
|
try {
|
|
const signatureImage = await pdfDoc.embedPng(signatureData);
|
|
const signatureDims = signatureImage.scale(0.25);
|
|
|
|
// Right side signature box
|
|
lastPage.drawImage(signatureImage, {
|
|
x: 420,
|
|
y: 120,
|
|
width: signatureDims.width,
|
|
height: signatureDims.height,
|
|
});
|
|
|
|
// Signature name below
|
|
if (booking.customerName) {
|
|
lastPage.drawText(booking.customerName, {
|
|
x: 420,
|
|
y: 100,
|
|
size: 10,
|
|
font: font,
|
|
color: rgb(0, 0, 0),
|
|
});
|
|
}
|
|
|
|
// Signature date and info
|
|
const sigDate = new Date();
|
|
lastPage.drawText(`Digital signiert am ${formatDate(sigDate)}`, {
|
|
x: 420,
|
|
y: 85,
|
|
size: 8,
|
|
font: font,
|
|
color: rgb(0.4, 0.4, 0.4),
|
|
});
|
|
} catch (err) {
|
|
console.error('Signature embedding error:', err);
|
|
}
|
|
}
|
|
|
|
// Serialize the PDF
|
|
const pdfBytes = await pdfDoc.save();
|
|
return Buffer.from(pdfBytes);
|
|
|
|
} catch (error) {
|
|
console.error('PDF generation from template error:', error);
|
|
throw error;
|
|
}
|
|
}
|