import { AufnahmeClient, BenutzerClient, BildClient, ObjektClient, VerbrauchsausweisGewerbeClient } from "#components/Ausweis/types.js"; import { getEmpfehlungen } from "#lib/XML/getEmpfehlungen.js"; import { Enums } from "#lib/server/prisma.js"; import * as fs from "fs" import moment from "moment"; import { PDFDocument, PDFFont, PDFImage, PDFPage, StandardFonts } from "pdf-lib"; import { addText } from "./utils/text.js"; import { addAnsichtsausweisLabel, addDatumGEG, addRegistriernummer } from "./utils/helpers.js"; import { getS3File } from "#lib/s3.js"; import { endEnergieVerbrauchVerbrauchsausweisGewerbe_2016_Server } from "#lib/Berechnungen/VerbrauchsausweisGewerbe/VerbrauchsausweisGewerbe_2016_Server.js"; export async function pdfVerbrauchsausweisGewerbe(ausweis: VerbrauchsausweisGewerbeClient, aufnahme: AufnahmeClient, objekt: ObjektClient, bilder: BildClient[], user: BenutzerClient, vorschau = true) { const VerbrauchsausweisWohnenGEG2024PDF = fs.readFileSync(new URL("../../../public/pdf/templates/GEG24_Nichtwohngebaeude.pdf", import.meta.url), "base64"); const pdf = await PDFDocument.load(VerbrauchsausweisWohnenGEG2024PDF) const pages = pdf.getPages() // const template = VerbrauchsausweisWohnen2016Template as Template; const berechnungen = await endEnergieVerbrauchVerbrauchsausweisGewerbe_2016_Server(ausweis, aufnahme, objekt); const empfehlungen = getEmpfehlungen(ausweis, aufnahme, objekt) const height = pages[0].getHeight() const font = await pdf.embedFont(StandardFonts.Helvetica) const bold = await pdf.embedFont(StandardFonts.HelveticaBold) const form = pdf.getForm() form.updateFieldAppearances(font) pages[0].drawText(`ID: ${ausweis.id || ""}`, { x: 211, y: height - 112.5, size: 10 }) pages[0].drawText(aufnahme.gebaeudetyp || "", { x: 211, y: height - 166, size: 10 }) pages[0].drawText(objekt.adresse || "", { x: 211, y: height - 194, size: 10 }) pages[0].drawText(aufnahme.gebaeudeteil || "", { x: 211, y: height - 214.5, size: 10 }) pages[0].drawText(aufnahme.baujahr_gebaeude?.toString() || "", { x: 211, y: height - 229.5, size: 10 }) pages[0].drawText(aufnahme.baujahr_heizung?.toString() || "", { x: 211, y: height - 250, size: 10 }) pages[0].drawText(aufnahme.nutzflaeche?.toString() || "", { x: 211, y: height - 271.5, size: 10 }) pages[0].drawText(`${ausweis.brennstoff_1}, ${ausweis.brennstoff_2 || ""}`, { x: 211, y: height - 285, size: 10 }) const erneuerbareEnergienVerwendung = [] if (ausweis.alternative_heizung) { erneuerbareEnergienVerwendung.push("Heizung") } if (ausweis.alternative_kuehlung) { erneuerbareEnergienVerwendung.push("Kühlung") } if (ausweis.alternative_lueftung) { erneuerbareEnergienVerwendung.push("Lüftung") } if (ausweis.alternative_warmwasser) { erneuerbareEnergienVerwendung.push("Warmwasser") } pages[0].drawText(erneuerbareEnergienVerwendung.join(", "), { x: 358, y: height - 325, size: 8 }) if (ausweis.warmwasser_enthalten) { pages[3].drawText(`${ausweis.brennstoff_1}, ${ausweis.brennstoff_2 || ""}`, { x: 211, y: height - 299, size: 10 }) } if (aufnahme.lueftung === Enums.Lueftungskonzept.Fensterlueftung) { pages[0].drawText("x", { x: 214, y: height - 342, size: 10, font: bold }) } else if (aufnahme.lueftung === Enums.Lueftungskonzept.Schachtlueftung) { pages[0].drawText("x", { x: 214, y: height - 353, size: 10, font: bold }) } else if (aufnahme.lueftung === Enums.Lueftungskonzept.LueftungsanlageMitWaermerueckgewinnung) { pages[0].drawText("x", { x: 356, y: height - 342, size: 10, font: bold }) } else if (aufnahme.lueftung === Enums.Lueftungskonzept.LueftungsanlageOhneWaermerueckgewinnung) { pages[0].drawText("x", { x: 356, y: height - 353, size: 10, font: bold }) } // Kühlung if (aufnahme.kuehlung === "1" && aufnahme.kuehlung !== null) { pages[0].drawText("x", { x: 356, y: height - 370.5, size: 10, font: bold }) } if (ausweis.ausstellgrund === Enums.Ausstellgrund.Neubau) { pages[0].drawText("x", { x: 214, y: height - 414, size: 10, font: bold }) } else if (ausweis.ausstellgrund === Enums.Ausstellgrund.Vermietung) { pages[0].drawText("x", { x: 214, y: height - 425, size: 10, font: bold }) } else if (ausweis.ausstellgrund === Enums.Ausstellgrund.Modernisierung) { pages[0].drawText("x", { x: 345.5, y: height - 414, size: 10, font: bold }) } else if (ausweis.ausstellgrund === Enums.Ausstellgrund.Sonstiges) { pages[0].drawText("x", { x: 464, y: height - 425, size: 10, font: bold }) } // Aushangpflicht // addCheckMark(pages[0], 463, height - 406) const bild = bilder && bilder.find(image => image.kategorie === Enums.BilderKategorie.Gebaeude); if (bild) { const file = await getS3File("ibc-images", `${bild.id}.jpg`); if (file) { let image: PDFImage; image = await pdf.embedJpg(file) pages[0].drawImage(image, { x: 460.5, y: height - 289, width: 111, height: 138 }) } } // Checkmark Verbrauchsausweis. pages[0].drawText("x", { x: 41, y: height - 558, size: 10, font: bold }) // Datenerhebung durch Eigentümer pages[0].drawText("x", { x: 296.5, y: height - 587.5, size: 10, font: bold }) // Ausstellungsdatum pages[0].drawText(moment().format("DD.MM.YYYY"), { font, size: 10, x: 508, y: height - 752 }) // Gültig bis pages[0].drawText(moment().add(10, "years").format("DD.MM.YYYY"), { font: bold, size: 10, x: 90, y: height - 113 }) // Stempel und Unterschrift if (ausweis.ausgestellt || !vorschau) { const stempel = await pdf.embedPng(fs.readFileSync(new URL("../../../public/pdf/images/stempel-unterschrift.png", import.meta.url), "base64")); const stempelHeight = 65 pages[0].drawImage(stempel, { x: 450, y: height - 750, height: stempelHeight, width: stempel.width / (stempel.height / stempelHeight) }) } // Aussteller const aussteller = await pdf.embedPng(fs.readFileSync(new URL("../../../public/pdf/images/aussteller.png", import.meta.url), "base64")); pages[0].drawImage(aussteller, { x: 260, y: height - 755, width: 130, height: 65 }) // /* -------------------------------- Seite 2 -------------------------------- */ // const co2Emissionen = fillFormField("co2emissionen", berechnungen?.co2EmissionenGesamt.toString(), 8, TextAlignment.Center) const addEnergieverbrauchSkalaPfeile = async (page: PDFPage) => { const pfeilNachUnten = await pdf.embedPng(fs.readFileSync(new URL("../../../public/images/pfeil-nach-unten.png", import.meta.url), "base64")) const pfeilNachOben = await pdf.embedPng(fs.readFileSync(new URL("../../../public/images/pfeil-nach-oben.png", import.meta.url), "base64")) // Wir müssen den berechneten Wert zwischen 0 und 1000 als Wert zwischen 0 und 1 festlegen const endenergieverbrauchTranslationPercentage = Math.min((berechnungen?.vergleichsWertWaerme * 2), Math.max(0, berechnungen?.endEnergieVerbrauchGesamt || 0)) / (berechnungen?.vergleichsWertWaerme * 2) const stromVerbrauchTranslationPercentage = Math.min((berechnungen?.vergleichsWertStrom * 2), Math.max(0, berechnungen?.endEnergieVerbrauchStrom || 0)) / (berechnungen?.vergleichsWertStrom * 2) const vergleichsWertWaermeTranslationPercentage = Math.min((berechnungen?.vergleichsWertWaerme * 2), Math.max(0, berechnungen?.vergleichsWertWaerme || 0)) / (berechnungen?.vergleichsWertWaerme * 2) const vergleichsWertStromTranslationPercentage = Math.min((berechnungen?.vergleichsWertStrom * 2), Math.max(0, berechnungen?.vergleichsWertStrom || 0)) / (berechnungen?.vergleichsWertStrom * 2) const minTranslation = 78 const maxTranslation = 512 const endenergieverbrauchTranslationX = minTranslation + (maxTranslation - minTranslation) * endenergieverbrauchTranslationPercentage; const stromVerbrauchTranslationX = minTranslation + (maxTranslation - minTranslation) * stromVerbrauchTranslationPercentage; const vergleichsWertWaermeTranslationX = minTranslation + (maxTranslation - minTranslation) * vergleichsWertWaermeTranslationPercentage; const vergleichsWertStromTranslationX = minTranslation + (maxTranslation - minTranslation) * vergleichsWertStromTranslationPercentage; const pfeilWidth = 20 const margin = 5; page.drawImage(pfeilNachUnten, { x: endenergieverbrauchTranslationX, y: height - 210, width: pfeilWidth, height: 30 }) page.drawImage(pfeilNachOben, { x: vergleichsWertWaermeTranslationX, y: height - 293, width: pfeilWidth, height: 30 }) const endEnergieVerbrauchGesamt = Math.round(berechnungen?.endEnergieVerbrauchGesamt ?? 0); const MaxvergleichsWertWaerme = Math.round(berechnungen?.vergleichsWertWaerme * 2); const MaxvergleichsWertWaermeText = `> ${MaxvergleichsWertWaerme.toString()}`; const MaxvergleichswertStrom = Math.round(berechnungen?.vergleichsWertStrom * 2); const MaxvergleichswertStromText = `> ${Math.round(MaxvergleichswertStrom).toString()}`; const endEnergieVerbrauchGesamtText = `${endEnergieVerbrauchGesamt.toString()}kWh/(m²a)`; const stromVerbrauchGesamtText = `${Math.round(berechnungen?.endEnergieVerbrauchStrom ?? 0).toString()}kWh/(m²a)`; const vergleichswertWaermeText = `${Math.round(berechnungen?.vergleichsWertWaerme).toString()}kWh/(m²a)` const vergleichswertWaermeText2 = `${Math.round(berechnungen?.vergleichsWertWaerme).toString()}` const vergleichswertStromText = `${Math.round(berechnungen?.vergleichsWertStrom).toString()}kWh/(m²a)` const vergleichswertStromText2 = `${Math.round(berechnungen?.vergleichsWertStrom).toString()}` page.drawText("0", { x: 85, y: height - 241, size: 13, font: bold }) page.drawText(vergleichswertWaermeText2, { x: 295, y: height - 241, size: 13, font: bold }) page.drawText(MaxvergleichsWertWaermeText, { x: vergleichsWertWaermeTranslationX * 2 - 78, y: height - 241, size: 13, font: bold }) page.drawText("0", { x: 85, y: height - 385, size: 13, font: bold }) page.drawText(vergleichswertStromText2, { x: 295, y: height - 385, size: 13, font: bold }) page.drawText(MaxvergleichswertStromText, { x: vergleichsWertStromTranslationX * 2 - 78, y: height - 385, size: 13, font: bold }) if (endenergieverbrauchTranslationPercentage > 0.5) { page.drawText("Endenergieverbrauch Wärme", { x: endenergieverbrauchTranslationX - margin - font.widthOfTextAtSize("Endenergieverbrauch Wärme", 10), y: height - 191, size: 10 }) page.drawText(endEnergieVerbrauchGesamtText, { x: endenergieverbrauchTranslationX - margin - bold.widthOfTextAtSize(endEnergieVerbrauchGesamtText, 10), y: height - 205, size: 10, font: bold }) } else { page.drawText("Endenergieverbrauch Wärme", { x: endenergieverbrauchTranslationX + pfeilWidth + margin, y: height - 191, size: 10 }) page.drawText(endEnergieVerbrauchGesamtText, { x: endenergieverbrauchTranslationX + pfeilWidth + margin, y: height - 205, size: 10, font: bold }) } if (vergleichsWertWaermeTranslationPercentage > 0.5) { page.drawText("Vergleichswert Wärme", { x: vergleichsWertWaermeTranslationX - margin - font.widthOfTextAtSize("Vergleichswert Wärme", 10), y: height - 275, size: 10 }) page.drawText(vergleichswertWaermeText, { x: vergleichsWertWaermeTranslationX - margin - bold.widthOfTextAtSize(vergleichswertWaermeText, 10), y: height - 289, size: 10, font: bold }) } else { page.drawText("Vergleichswert Wärme", { x: vergleichsWertWaermeTranslationX + pfeilWidth + margin, y: height - 275, size: 10 }) page.drawText(vergleichswertWaermeText, { x: vergleichsWertWaermeTranslationX + pfeilWidth + margin, y: height - 289, size: 10, font: bold }) } page.drawImage(pfeilNachUnten, { x: stromVerbrauchTranslationX, y: height - 354, width: pfeilWidth, height: 30 }) page.drawImage(pfeilNachOben, { x: vergleichsWertStromTranslationX, y: height - 437, width: pfeilWidth, height: 30 }) if (stromVerbrauchTranslationPercentage > 0.5) { page.drawText("Endenergieverbrauch Strom", { x: stromVerbrauchTranslationX - margin - font.widthOfTextAtSize("Endenergieverbrauch Strom", 10), y: height - 335, size: 10 }) page.drawText(stromVerbrauchGesamtText, { x: stromVerbrauchTranslationX - margin - bold.widthOfTextAtSize(stromVerbrauchGesamtText, 10), y: height - 349, size: 10, font: bold }) } else { page.drawText("Endenergieverbrauch Strom", { x: stromVerbrauchTranslationX + pfeilWidth + margin, y: height - 335, size: 10 }) page.drawText(stromVerbrauchGesamtText, { x: stromVerbrauchTranslationX + pfeilWidth + margin, y: height - 349, size: 10, font: bold }) } if (vergleichsWertWaermeTranslationPercentage > 0.5) { page.drawText("Vergleichswert Strom", { x: vergleichsWertStromTranslationX - margin - font.widthOfTextAtSize("Vergleichswert Strom", 10), y: height - 420, size: 10 }) page.drawText(vergleichswertStromText, { x: vergleichsWertStromTranslationX - margin - bold.widthOfTextAtSize(vergleichswertStromText, 10), y: height - 434, size: 10, font: bold }) } else { page.drawText("Vergleichswert Strom", { x: vergleichsWertStromTranslationX + pfeilWidth + margin, y: height - 420, size: 10 }) page.drawText(vergleichswertStromText, { x: vergleichsWertStromTranslationX + pfeilWidth + margin, y: height - 434, size: 10, font: bold }) } } addEnergieverbrauchSkalaPfeile(pages[2]) if (ausweis.warmwasser_enthalten) { pages[2].drawText("x", { x: 42, y: height - 301, size: 10, font: bold }) } if (ausweis.kuehlung_enthalten) { pages[2].drawText("x", { x: 42, y: height - 313, size: 10, font: bold }) } if (ausweis.stromverbrauch_enthaelt_heizung) { pages[2].drawText("x", { x: 42, y: height - 464, size: 10, font: bold }) } if (ausweis.stromverbrauch_enthaelt_warmwasser) { pages[2].drawText("x", { x: 132, y: height - 464, size: 10, font: bold }) } if (ausweis.stromverbrauch_enthaelt_lueftung) { pages[2].drawText("x", { x: 219, y: height - 464, size: 10, font: bold }) } if (ausweis.stromverbrauch_enthaelt_beleuchtung) { pages[2].drawText("x", { x: 282, y: height - 464, size: 10, font: bold }) } if (ausweis.stromverbrauch_enthaelt_kuehlung) { pages[2].drawText("x", { x: 423, y: height - 464, size: 10, font: bold }) } if (ausweis.stromverbrauch_enthaelt_sonstige) { pages[2].drawText("x", { x: 493, y: height - 464, size: 10, font: bold }) } addText(pages[2], berechnungen?.primaerEnergieVerbrauchGesamt.toString() || "", 475, height - 637, 10, font) addText(pages[2], berechnungen?.co2EmissionenGesamt.toString() || "", 475, height - 656, 10, font) // const primaerenergiebedarfIst = fillFormField("primaerenergiebedarf_ist", berechnungen?.primaerEnergieVerbrauchGesamt.toString()) /* -------------------------------- Seite 3 -------------------------------- */ // Verbräuche const addVerbrauchGenerator = () => { let i = 0; let yOffset = 14.6; const initialHeight = 297 const initialXOffset = 36; return (zeitraum_von?: string, zeitraum_bis?: string, energietraeger?: string, primaerfaktor?: string, energieverbrauch?: string, anteil_warmwasser?: string, anteil_kaelte?: number, anteil_heizung?: string, klimafaktor?: string, strom?: number) => { pages[2].drawText(zeitraum_von || "", { x: initialXOffset, y: initialHeight - (i * yOffset), size: 8, font }) pages[2].drawText(zeitraum_bis || "", { x: initialXOffset + 47, y: initialHeight - (i * yOffset), size: 8, font }) pages[2].drawText(energietraeger || "", { x: initialXOffset + 94, y: initialHeight - (i * yOffset), size: 8, font }) pages[2].drawText(primaerfaktor || "", { x: initialXOffset + 232, y: initialHeight - (i * yOffset), size: 8, font }) pages[2].drawText(energieverbrauch || "", { x: initialXOffset + 275, y: initialHeight - (i * yOffset), size: 8, font }) pages[2].drawText(anteil_warmwasser || "", { x: initialXOffset + 325, y: initialHeight - (i * yOffset), size: 8, font }) pages[2].drawText(anteil_kaelte?.toString() || "", { x: initialXOffset + 378, y: initialHeight - (i * yOffset), size: 8, font }) pages[2].drawText(anteil_heizung || "", { x: initialXOffset + 430, y: initialHeight - (i * yOffset), size: 8, font }) pages[2].drawText(klimafaktor || "", { x: initialXOffset + 464, y: initialHeight - (i * yOffset), size: 8, font }) pages[2].drawText(strom?.toString() || "", { x: initialXOffset + 504, y: initialHeight - (i * yOffset), size: 8, font }) i++; } } const addVerbrauch = addVerbrauchGenerator(); if (ausweis.warmwasser_enthalten) { // Mit Warmwasserzuschlag addVerbrauch( moment(ausweis.startdatum).format("MM.YYYY"), moment(ausweis.startdatum).add(3, "years").format("MM.YYYY"), ausweis.brennstoff_1 || "", berechnungen?.brennstoff_1.primaerenergiefaktor.toString(), Math.round(berechnungen?.energieVerbrauchGesamt_1 || 0).toString(), Math.round(berechnungen?.energieVerbrauchWarmwasser_1 || 0).toString(), berechnungen?.endEnergieVerbrauchKuehlungsZuschlag_1, Math.round(berechnungen?.energieVerbrauchHeizung_1 || 0).toString(), berechnungen?.durchschnittsKlimafaktor.toString(), berechnungen?.energieVerbrauchStrom ); } else { // Ohne Warmwasserzuschlag addVerbrauch( moment(ausweis.startdatum).format("MM.YYYY"), moment(ausweis.startdatum).add(3, "years").format("MM.YYYY"), ausweis.brennstoff_1 || "", berechnungen?.brennstoff_1.primaerenergiefaktor.toString(), Math.round(berechnungen?.energieVerbrauchGesamt_1 || 0).toString(), Math.round(berechnungen?.energieVerbrauchWarmwasser_1 || 0).toString(), berechnungen?.endEnergieVerbrauchKuehlungsZuschlag_1, Math.round(berechnungen?.energieVerbrauchHeizung_1 || 0).toString(), berechnungen?.durchschnittsKlimafaktor.toString(), berechnungen?.energieVerbrauchStrom ); } if (ausweis.zusaetzliche_heizquelle) { addVerbrauch( moment(ausweis.startdatum).format("MM.YYYY"), moment(ausweis.startdatum).add(3, "years").format("MM.YYYY"), ausweis.brennstoff_2 || "", berechnungen?.brennstoff_2.primaerenergiefaktor.toString(), Math.round(berechnungen?.energieVerbrauchGesamt_2 || 0).toString(), Math.round(berechnungen?.energieVerbrauchWarmwasser_2 || 0).toString(), berechnungen?.endEnergieVerbrauchKuehlungsZuschlag_2, Math.round(berechnungen?.energieVerbrauchHeizung_2 || 0).toString(), berechnungen?.durchschnittsKlimafaktor.toString(), 0 ); } // TODO if (ausweis.warmwasser_enthalten) { /** * Dezentrale Warmwasserversorgung - Pauschale Erhöhung um 20kWh/m² * @link https://www.bundesanzeiger.de/pub/publication/MRYM4nI84Sdlr0EIvvW?2 */ addVerbrauch( moment(ausweis.startdatum).format("MM.YYYY"), moment(ausweis.startdatum).add(3, "years").format("MM.YYYY"), "Warmwasserzuschlag", berechnungen?.brennstoff_1.primaerenergiefaktor.toString(), Math.round(berechnungen?.energieVerbrauchWarmwasser_1 || 0).toString(), Math.round(berechnungen?.energieVerbrauchWarmwasser_1 || 0).toString(), 0, "0" ); } if (aufnahme.leerstand && aufnahme.leerstand > 0) { /** * Leerstandszuschlag * @link https://www.bundesanzeiger.de/pub/publication/MRYM4nI84Sdlr0EIvvW?2 */ if (ausweis.warmwasser_enthalten && ausweis.warmwasser_anteil_bekannt) { addVerbrauch( moment(ausweis.startdatum).format("MM.YYYY"), moment(ausweis.startdatum).add(3, "years").format("MM.YYYY"), "Leerstandszuschlag", berechnungen?.brennstoff_1.primaerenergiefaktor.toString(), Math.round((berechnungen?.leerstandsZuschlagHeizung || 0) + (berechnungen?.leerstandsZuschlagWarmwasser || 0)).toString(), Math.round((berechnungen?.leerstandsZuschlagWarmwasser || 0)).toString(), Math.round((berechnungen?.leerstandsZuschlagHeizung || 0)), berechnungen?.durchschnittsKlimafaktor.toString() ); } else { addVerbrauch( moment(ausweis.startdatum).format("MM.YYYY"), moment(ausweis.startdatum).add(3, "years").format("MM.YYYY"), "Leerstandszuschlag", berechnungen?.brennstoff_1.primaerenergiefaktor.toString(), Math.round((berechnungen?.leerstandsZuschlagHeizung || 0) + (berechnungen?.leerstandsZuschlagWarmwasser || 0)).toString(), "0", 0, berechnungen?.durchschnittsKlimafaktor.toString() ); } } if (aufnahme.kuehlung === "1") { /** * Kühlungszuschlag - Pauschale Erhöhung um 6kWh/m² * Primärenergiefaktor Strom * @link https://www.bundesanzeiger.de/pub/publication/MRYM4nI84Sdlr0EIvvW?2 */ addVerbrauch( moment(ausweis.startdatum).format("MM.YYYY"), moment(ausweis.startdatum).add(3, "years").format("MM.YYYY"), "Kühlungszuschlag", "", // TODO // berechnungen?.primaerfaktorww.toString(), "", "", Math.round(berechnungen?.kuehlungsZuschlag || 0), "" ); } /* -------------------------------- Seite 4 -------------------------------- */ const splitToSize = (text: string, size: number, font: PDFFont, fontSize: number) => { const lines = [] let currentLine = "" for (const char of text) { if (font.widthOfTextAtSize(currentLine + char, fontSize) <= size) { currentLine += char; } else { lines.push(currentLine) currentLine = char; } } lines.push(currentLine) return lines.join("\n") } const addEmpfehlungenGenerator = () => { let i = 0; let yOffset = 43; const initialHeight = 562 const initialXOffset = 36; return (bauteil?: string, beschreibung?: string, alsEinzelmassnahme?: boolean, amortisationszeit?: string, kosten?: string) => { pages[3].drawText((i + 1).toString(), { x: initialXOffset, y: initialHeight - (i * yOffset), size: 8, font }) pages[3].drawText(splitToSize(bauteil || "", 70, font, 8), { x: initialXOffset + 25, y: initialHeight - (i * yOffset), size: 8, font, lineHeight: 10 }) pages[3].drawText(splitToSize(beschreibung || "", 230, font, 8), { x: initialXOffset + 98, y: initialHeight - (i * yOffset), size: 8, font, lineHeight: 10 }) pages[3].drawText(amortisationszeit || "", { x: initialXOffset + 403, y: initialHeight - (i * yOffset), size: 8, font }) pages[3].drawText(kosten || "", { x: initialXOffset + 451, y: initialHeight - (i * yOffset), size: 8, font }) i++; } } const addEmpfehlung = addEmpfehlungenGenerator() for (const empfehlung of empfehlungen) { addEmpfehlung(empfehlung.anlagenteil, empfehlung.description, true, empfehlung.amortisationszeit, empfehlung.kosten) } for (let i = 0; i < pages.length; i++) { const page = pages[i]; if (vorschau) { addAnsichtsausweisLabel(page, font) } addDatumGEG(page, font) if (i !== pages.length - 1) { addRegistriernummer(page, font, ausweis.registriernummer || "") } } // pdf.getForm().flatten() return pdf.save(); }