329 lines
15 KiB
TypeScript
329 lines
15 KiB
TypeScript
import { AufnahmeClient, BildClient, ObjektClient, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types.js";
|
|
import * as fs from "fs"
|
|
import { PDFDocument, StandardFonts } from "pdf-lib";
|
|
import { xml2pdf } from "./elements/xml2pdf.js";
|
|
import moment from "moment";
|
|
import { Enums, Heizungsstatus, Rechnung } from "#lib/server/prisma.js";
|
|
import { copyPage } from "./utils/copyPage.js";
|
|
import { endEnergieVerbrauchVerbrauchsausweis_2016_Server } from "#lib/Berechnungen/VerbrauchsausweisWohnen/VerbrauchsausweisWohnen_2016_Server.js";
|
|
|
|
/* -------------------------------- Pdf Tools ------------------------------- */
|
|
|
|
export async function pdfDatenblattVerbrauchsausweisWohnen(ausweis: VerbrauchsausweisWohnenClient, aufnahme: AufnahmeClient, objekt: ObjektClient, rechnung: Rechnung | null, bilder: BildClient[]) {
|
|
const VerbrauchsausweisWohnenGEG2024PDF = fs.readFileSync(new URL("../../../public/pdf/templates/Leerseite_Datenblatt.pdf", import.meta.url), "base64");
|
|
const pdf = await PDFDocument.load(VerbrauchsausweisWohnenGEG2024PDF)
|
|
const page3 = copyPage(pdf.getPages()[0]);
|
|
pdf.addPage(page3);
|
|
const pages = pdf.getPages()
|
|
|
|
|
|
// const template = VerbrauchsausweisWohnen2016Template as Template;
|
|
|
|
const berechnungen = await endEnergieVerbrauchVerbrauchsausweis_2016_Server(ausweis, aufnahme, objekt);
|
|
|
|
const height = pages[0].getHeight()
|
|
const width = pages[0].getWidth()
|
|
|
|
const font = await pdf.embedFont(StandardFonts.Helvetica)
|
|
const bold = await pdf.embedFont(StandardFonts.HelveticaBold)
|
|
|
|
const form = pdf.getForm()
|
|
form.updateFieldAppearances(font)
|
|
|
|
const marginX = 60;
|
|
const marginY = 150;
|
|
|
|
const translateHeizungsstatus: Record<Heizungsstatus, string> = {
|
|
BEHEIZT: "beheizt",
|
|
NICHT_VORHANDEN: "nicht vorhanden",
|
|
UNBEHEIZT: "unbeheizt"
|
|
}
|
|
|
|
const innerWidth = pages[0].getWidth() - marginX * 2;
|
|
|
|
const id = ausweis.id;
|
|
|
|
const layout = xml2pdf(`<layout height="${pages[0].getHeight()}" width="${pages[0].getWidth()}" marginTop="150" marginLeft="${marginX}" marginRight="${marginX}">
|
|
<text size="12" lineHeight="14">${rechnung?.versand_empfaenger || ""}</text>
|
|
<text size="12" lineHeight="14">${rechnung?.versand_zusatzzeile || ""}</text>
|
|
<text size="12" lineHeight="14">${rechnung?.versand_strasse || ""}</text>
|
|
<text size="12" lineHeight="14">${rechnung?.versand_plz || ""} ${rechnung?.versand_ort || ""}</text>
|
|
<flex direction="row" justify="space-between" marginTop="55" width="${innerWidth}">
|
|
<text size="12" font="bold">Datenblatt Energieausweis</text>
|
|
<text size="12">Ausweis ID: ${id}</text>
|
|
</flex>
|
|
<text size="12" lineHeight="14" font="bold" marginTop="10">Gebäudedaten</text>
|
|
<text size="12" lineHeight="14">Adresse: ${objekt.adresse}, ${objekt.plz} ${objekt.ort}</text>
|
|
|
|
<flex direction="row" justify="space-between" width="${innerWidth}" marginTop="25">
|
|
<flex direction="row" gap="5" align="center">
|
|
<checkbox width="8" height="8" checked="${ausweis.ausstellgrund === "Neubau"}"></checkbox>
|
|
<text size="12">Neubau</text>
|
|
</flex>
|
|
<flex direction="row" gap="5" align="center">
|
|
<checkbox width="8" height="8" checked="${ausweis.ausstellgrund === "Verkauf" || ausweis.ausstellgrund === "Vermietung"}"></checkbox>
|
|
<text size="12">Vermietung/Verkauf</text>
|
|
</flex>
|
|
<flex direction="row" gap="5" align="center">
|
|
<checkbox width="8" height="8" checked="${ausweis.ausstellgrund === "Modernisierung"}"></checkbox>
|
|
<text size="12">Modernisierung</text>
|
|
</flex>
|
|
<flex direction="row" gap="5" align="center">
|
|
<checkbox width="8" height="8" checked="${ausweis.ausstellgrund === "Sonstiges"}"></checkbox>
|
|
<text size="12">Sonstiges</text>
|
|
</flex>
|
|
</flex>
|
|
|
|
<flex direction="row" marginTop="25" gap="15">
|
|
<flex direction="column" width="${(innerWidth) / 2 - 7.5}">
|
|
<flex direction="row" align="center" justify="space-between" width="${(innerWidth) / 2 - 7.5}">
|
|
<text size="12" lineHeight="14">Gebäudetyp:</text>
|
|
<text size="12" lineHeight="14">${aufnahme.gebaeudetyp}</text>
|
|
</flex>
|
|
<flex direction="row" align="center" justify="space-between" width="${(innerWidth) / 2 - 7.5}">
|
|
<text size="12" lineHeight="14">Wohnfläche:</text>
|
|
<text size="12" lineHeight="14">DIN Wohnfläche innen ${aufnahme.flaeche} m²</text>
|
|
</flex>
|
|
<flex direction="row" align="center" justify="space-between" width="${(innerWidth) / 2 - 7.5}">
|
|
<text size="12" lineHeight="14">Leerstand:</text>
|
|
<text size="12" lineHeight="14">${aufnahme.leerstand || 0}%</text>
|
|
</flex>
|
|
<flex direction="row" align="center" justify="space-between" width="${(innerWidth) / 2 - 7.5}">
|
|
<text size="12" lineHeight="14">Wohnungen:</text>
|
|
<text size="12" lineHeight="14">${aufnahme.einheiten}</text>
|
|
</flex>
|
|
</flex>
|
|
<flex direction="column" width="${(innerWidth) / 2 - 7.5}">
|
|
<flex direction="row" align="center" justify="space-between" width="${(innerWidth) / 2 - 7.5}">
|
|
<text size="12" lineHeight="14">Dachgeschoss:</text>
|
|
<text size="12" lineHeight="14">${translateHeizungsstatus[aufnahme.dachgeschoss || "NICHT_VORHANDEN"]}</text>
|
|
</flex>
|
|
<flex direction="row" align="center" justify="space-between" width="${(innerWidth) / 2 - 7.5}">
|
|
<text size="12" lineHeight="14">Keller:</text>
|
|
<text size="12" lineHeight="14">${translateHeizungsstatus[aufnahme.keller || "NICHT_VORHANDEN"]}</text>
|
|
</flex>
|
|
</flex>
|
|
</flex>
|
|
|
|
<text size="12" lineHeight="14" font="bold" marginTop="25">Verbrauch</text>
|
|
|
|
<flex direction="row" justify="space-between" align="center" width="${(innerWidth)}" marginTop="5">
|
|
<flex direction="column" gap="4">
|
|
<text></text>
|
|
<text></text>
|
|
<text size="12">Von: ${moment(ausweis.startdatum).format("DD.MM.YYYY")}</text>
|
|
<text size="12">Von: ${moment(ausweis.startdatum).add("1", "years").format("DD.MM.YYYY")}</text>
|
|
<text size="12">Von: ${moment(ausweis.startdatum).add("2", "years").format("DD.MM.YYYY")}</text>
|
|
</flex>
|
|
<flex direction="column" gap="4">
|
|
<text></text>
|
|
<text></text>
|
|
<text size="12">Bis: ${moment(ausweis.startdatum).add("1", "year").format("DD.MM.YYYY")}</text>
|
|
<text size="12">Bis: ${moment(ausweis.startdatum).add("2", "years").format("DD.MM.YYYY")}</text>
|
|
<text size="12">Bis: ${moment(ausweis.startdatum).add("3", "years").format("DD.MM.YYYY")}</text>
|
|
</flex>
|
|
<flex direction="column" gap="4">
|
|
<text></text>
|
|
<text size="12" font="bold">${ausweis.brennstoff_1}</text>
|
|
<text size="12">${ausweis.verbrauch_1} ${ausweis.einheit_1}</text>
|
|
<text size="12">${ausweis.verbrauch_2} ${ausweis.einheit_1}</text>
|
|
<text size="12">${ausweis.verbrauch_3} ${ausweis.einheit_1}</text>
|
|
</flex>
|
|
<flex direction="column" gap="4">
|
|
<text size="12">zusätzliche Heizquelle</text>
|
|
<text size="12" font="bold">${ausweis.brennstoff_2 || ""}</text>
|
|
<text size="12">${ausweis.verbrauch_4 || ""} ${ausweis.einheit_2 || ""}</text>
|
|
<text size="12">${ausweis.verbrauch_5 || ""} ${ausweis.einheit_2 || ""}</text>
|
|
<text size="12">${ausweis.verbrauch_6 || ""} ${ausweis.einheit_2 || ""}</text>
|
|
</flex>
|
|
</flex>
|
|
|
|
<text size="12" marginTop="5">Warmwasseranteil: ${ausweis.anteil_warmwasser_1}%</text>
|
|
</layout>`, {
|
|
"default": font,
|
|
bold: bold
|
|
})
|
|
|
|
const layoutPage2 = xml2pdf(`<layout height="${pages[1].getHeight()}" width="${pages[1].getWidth()}" marginTop="150" marginLeft="60" marginRight="60">
|
|
<text size="12" font="bold">Stand der Technik:</text>
|
|
<text size="12" marginTop="15">Heizungsanlage</text>
|
|
<flex direction="row" justify="space-between" width="${pages[1].getWidth() - 120}" marginTop="15">
|
|
<flex direction="column" gap="4">
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.zentralheizung || false}"></checkbox>
|
|
<text size="12">Zentralheizung</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.einzelofen || false}"></checkbox>
|
|
<text size="12">Einzelöfen</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.durchlauf_erhitzer || false}"></checkbox>
|
|
<text size="12">Durchlauferhitzer</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.standard_kessel || false}"></checkbox>
|
|
<text size="12">Standardkessel</text>
|
|
</flex>
|
|
</flex>
|
|
<flex direction="column" gap="4">
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.solarsystem_warmwasser || false}"></checkbox>
|
|
<text size="12">Solarsystem für Warmwasser</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.waermepumpe || false}"></checkbox>
|
|
<text size="12">Wärmepumpe</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.niedertemperatur_kessel || false}"></checkbox>
|
|
<text size="12">Niedertemperaturkessel</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.brennwert_kessel || false}"></checkbox>
|
|
<text size="12">Brennwertkessel</text>
|
|
</flex>
|
|
</flex>
|
|
<flex direction="column" gap="4">
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.warmwasser_rohre_gedaemmt || false}"></checkbox>
|
|
<text size="12">Warmwasserrohre gedämmt</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.heizungsrohre_gedaemmt || false}"></checkbox>
|
|
<text size="12">Heizungsrohre gedämmt</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.zirkulation || false}"></checkbox>
|
|
<text size="12">Zirkulation</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.raum_temperatur_regler || false}"></checkbox>
|
|
<text size="12">Raumtemperaturregelung</text>
|
|
</flex>
|
|
</flex>
|
|
</flex>
|
|
<text size="12" marginTop="15">Fenster/Dachfenster/Türen</text>
|
|
<flex direction="row" justify="space-between" width="${pages[1].getWidth() - 120}" marginTop="15">
|
|
<flex direction="column" gap="4">
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.einfach_verglasung || false}"></checkbox>
|
|
<text size="12">Einfachglas</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.doppel_verglasung || false}"></checkbox>
|
|
<text size="12">Doppelverglasung</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.isolier_verglasung || false}"></checkbox>
|
|
<text size="12">Isolierverglasung</text>
|
|
</flex>
|
|
</flex>
|
|
<flex direction="column" gap="4">
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${false}"></checkbox>
|
|
<text size="12">Passivhausfenster</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.fenster_dicht || false}"></checkbox>
|
|
<text size="12">Alle Fenster dicht</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.fenster_teilweise_undicht || false}"></checkbox>
|
|
<text size="12">Fenster teilweise undicht</text>
|
|
</flex>
|
|
</flex>
|
|
<flex direction="column" gap="4">
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.tueren_undicht || false}"></checkbox>
|
|
<text size="12">Türen teilweise undicht</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.tueren_dicht || false}"></checkbox>
|
|
<text size="12">Alle Türen dicht</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.rolllaeden_kaesten_gedaemmt || false}"></checkbox>
|
|
<text size="12">Rollladenkästen gedämmt</text>
|
|
</flex>
|
|
</flex>
|
|
</flex>
|
|
<text size="12" marginTop="15">Wärmedämmung</text>
|
|
<flex direction="row" justify="space-between" width="${pages[1].getWidth() - 120}" marginTop="15">
|
|
<flex direction="column" gap="4">
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.keller_wand_gedaemmt || false}"></checkbox>
|
|
<text size="12">Kelleraußenwand gedämmt</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.keller_decke_gedaemmt || false}"></checkbox>
|
|
<text size="12">Kellerdecke gedämmt</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.aussenwand_gedaemmt || false}"></checkbox>
|
|
<text size="12">Außenwand gedämmt</text>
|
|
</flex>
|
|
</flex>
|
|
<flex direction="column" gap="4">
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.dachgeschoss_min_12cm_gedaemmt || false}"></checkbox>
|
|
<text size="12">Dachgeschoss min. 12cm gedämmt</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.dachgeschoss_gedaemmt || false}"></checkbox>
|
|
<text size="12">Dachgeschoss gedämmt</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.oberste_geschossdecke_gedaemmt || false}"></checkbox>
|
|
<text size="12">Oberste Geschossdecke gedämmt</text>
|
|
</flex>
|
|
<flex direction="row" gap="4" align="center">
|
|
<checkbox width="8" height="8" checked="${aufnahme.oberste_geschossdecke_min_12cm_gedaemmt || false}"></checkbox>
|
|
<text size="12">Oberste Geschossdecke min. 12cm gedämmt</text>
|
|
</flex>
|
|
</flex>
|
|
</flex>
|
|
</layout>`, {
|
|
"default": font,
|
|
bold
|
|
})
|
|
|
|
const images: string[][] = []
|
|
|
|
for (const bild of bilder) {
|
|
let batch: string[];
|
|
let image: string = "";
|
|
|
|
if (bild.kategorie === Enums.BilderKategorie.Gebaeude) {
|
|
continue;
|
|
}
|
|
|
|
if (bild.id) {
|
|
image = `<img src="${bild.id}.jpg" width="${(pages[2].getWidth() - 120) / 3.1}" height="${(pages[2].getHeight() - marginY * 2) / 4}" />`
|
|
}
|
|
|
|
if (images.length > 0) {
|
|
let batch = images[images.length - 1]
|
|
if (batch.length == 3) {
|
|
batch = [image]
|
|
images.push(batch)
|
|
} else {
|
|
batch.push(image)
|
|
}
|
|
} else {
|
|
batch = [image]
|
|
images.push(batch)
|
|
}
|
|
}
|
|
|
|
const layoutPage3 = xml2pdf(`<layout height="${pages[2].getHeight()}" width="${pages[2].getWidth()}" marginTop="150" marginLeft="60" marginRight="60">
|
|
${images.map(batch => `<flex direction="row" justify="space-between" width="${pages[2].getWidth() - 120}" height="${(pages[2].getHeight() - marginY * 2) / 4}" marginTop="15">${batch.join("")}</flex>`).join("")}
|
|
</layout>`, { "default": font })
|
|
|
|
|
|
await layout.draw(pages[0], 0, pages[0].getHeight())
|
|
await layoutPage2.draw(pages[1], 0, pages[1].getHeight())
|
|
await layoutPage3.draw(pages[2], 0, pages[2].getHeight())
|
|
|
|
return pdf.save();
|
|
} |