From 0b93b2d230e9dba65026d22177c281f5c0148ef3 Mon Sep 17 00:00:00 2001 From: Moritz Utcke Date: Wed, 12 Mar 2025 16:21:27 -0300 Subject: [PATCH 01/17] GEG Nachweis Gewerbe --- .../20250312191621_gng/migration.sql | 47 ++++++ prisma/schema/GEGNachweisGewerbe.prisma | 2 +- src/astro-typesafe-api-caller.ts | 8 +- src/client/lib/nachweisSpeichern.ts | 141 ++++++++++++++---- src/components/Ausweis/Ausweisart.svelte | 6 +- .../Ausweis/ButtonWeiterHilfe.svelte | 2 +- .../GEGNachweis/GEGAusweisart.svelte | 2 +- .../e2e/GEGNachweisGewerbe/erstellen.cy.ts | 134 +++++++++++++++++ src/modules/KundendatenModule.svelte | 19 +-- .../GEGNachweisGewerbeModule.svelte | 124 ++++++++++----- .../GEGNachweisWohnenModule.svelte | 121 +++++++++------ .../geg-nachweis-wohnen-anfragen/index.astro | 4 +- src/pages/api/aufnahme/index.ts | 3 +- src/pages/api/geg-nachweis-gewerbe/index.ts | 5 +- src/pages/api/geg-nachweis-wohnen/index.ts | 7 +- src/pages/api/rechnung/anfordern.ts | 56 +++++-- src/pages/kundendaten.astro | 2 +- 17 files changed, 526 insertions(+), 157 deletions(-) create mode 100644 prisma/migrations/20250312191621_gng/migration.sql create mode 100644 src/cypress/e2e/GEGNachweisGewerbe/erstellen.cy.ts diff --git a/prisma/migrations/20250312191621_gng/migration.sql b/prisma/migrations/20250312191621_gng/migration.sql new file mode 100644 index 00000000..d6f2e9e5 --- /dev/null +++ b/prisma/migrations/20250312191621_gng/migration.sql @@ -0,0 +1,47 @@ +-- AlterTable +ALTER TABLE "Anteilshaber" ALTER COLUMN "uid" SET DEFAULT 'ant-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Aufnahme" ALTER COLUMN "uid" SET DEFAULT 'auf-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "BedarfsausweisGewerbe" ALTER COLUMN "uid" SET DEFAULT 'bag-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "BedarfsausweisWohnen" ALTER COLUMN "uid" SET DEFAULT 'baw-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Bild" ALTER COLUMN "uid" SET DEFAULT 'img-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Event" ALTER COLUMN "uid" SET DEFAULT 'evt-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "GEGEinpreisung" ALTER COLUMN "uid" SET DEFAULT 'gge-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "GEGNachweisGewerbe" ALTER COLUMN "uid" SET DEFAULT 'gng-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "GEGNachweisWohnen" ALTER COLUMN "uid" SET DEFAULT 'gnw-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Objekt" ALTER COLUMN "uid" SET DEFAULT 'obj-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Rechnung" ALTER COLUMN "uid" SET DEFAULT 'inv-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Tickets" ALTER COLUMN "uid" SET DEFAULT 'tkt-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Unterlage" ALTER COLUMN "uid" SET DEFAULT 'pln-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "VerbrauchsausweisGewerbe" ALTER COLUMN "uid" SET DEFAULT 'vag-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "VerbrauchsausweisWohnen" ALTER COLUMN "uid" SET DEFAULT 'vaw-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "benutzer" ALTER COLUMN "uid" SET DEFAULT 'usr-' || gen_random_uuid(); diff --git a/prisma/schema/GEGNachweisGewerbe.prisma b/prisma/schema/GEGNachweisGewerbe.prisma index 236e5824..cdcb9bdf 100644 --- a/prisma/schema/GEGNachweisGewerbe.prisma +++ b/prisma/schema/GEGNachweisGewerbe.prisma @@ -1,6 +1,6 @@ model GEGNachweisGewerbe { id Int @id @default(autoincrement()) - uid String @unique @default(dbgenerated("'gnw-' || gen_random_uuid()")) + uid String @unique @default(dbgenerated("'gng-' || gen_random_uuid()")) /// @zod.describe("Ausstellgrund wie z.B. Vermietung oder Verkauf") ausstellgrund Ausstellgrund? diff --git a/src/astro-typesafe-api-caller.ts b/src/astro-typesafe-api-caller.ts index cf94b56b..cce5b331 100644 --- a/src/astro-typesafe-api-caller.ts +++ b/src/astro-typesafe-api-caller.ts @@ -12,13 +12,13 @@ export const createCaller = createCallerFactory({ "admin/post-ausstellen": await import("../src/pages/api/admin/post-ausstellen.ts"), "admin/registriernummer": await import("../src/pages/api/admin/registriernummer.ts"), "admin/stornieren": await import("../src/pages/api/admin/stornieren.ts"), - "aufnahme": await import("../src/pages/api/aufnahme/index.ts"), "auth/access-token": await import("../src/pages/api/auth/access-token.ts"), "auth/passwort-vergessen": await import("../src/pages/api/auth/passwort-vergessen.ts"), "auth/refresh-token": await import("../src/pages/api/auth/refresh-token.ts"), + "ausweise": await import("../src/pages/api/ausweise/index.ts"), "bedarfsausweis-wohnen/[uid]": await import("../src/pages/api/bedarfsausweis-wohnen/[uid].ts"), "bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"), - "ausweise": await import("../src/pages/api/ausweise/index.ts"), + "aufnahme": await import("../src/pages/api/aufnahme/index.ts"), "bilder/[uid]": await import("../src/pages/api/bilder/[uid].ts"), "geg-nachweis-gewerbe/[uid]": await import("../src/pages/api/geg-nachweis-gewerbe/[uid].ts"), "geg-nachweis-gewerbe": await import("../src/pages/api/geg-nachweis-gewerbe/index.ts"), @@ -31,10 +31,10 @@ export const createCaller = createCallerFactory({ "ticket": await import("../src/pages/api/ticket/index.ts"), "user": await import("../src/pages/api/user/index.ts"), "user/self": await import("../src/pages/api/user/self.ts"), - "verbrauchsausweis-gewerbe/[uid]": await import("../src/pages/api/verbrauchsausweis-gewerbe/[uid].ts"), - "verbrauchsausweis-gewerbe": await import("../src/pages/api/verbrauchsausweis-gewerbe/index.ts"), "verbrauchsausweis-wohnen/[uid]": await import("../src/pages/api/verbrauchsausweis-wohnen/[uid].ts"), "verbrauchsausweis-wohnen": await import("../src/pages/api/verbrauchsausweis-wohnen/index.ts"), + "verbrauchsausweis-gewerbe/[uid]": await import("../src/pages/api/verbrauchsausweis-gewerbe/[uid].ts"), + "verbrauchsausweis-gewerbe": await import("../src/pages/api/verbrauchsausweis-gewerbe/index.ts"), "webhooks/mollie": await import("../src/pages/api/webhooks/mollie.ts"), "aufnahme/[uid]/bilder": await import("../src/pages/api/aufnahme/[uid]/bilder.ts"), "aufnahme/[uid]": await import("../src/pages/api/aufnahme/[uid]/index.ts"), diff --git a/src/client/lib/nachweisSpeichern.ts b/src/client/lib/nachweisSpeichern.ts index 59b2deda..082383bf 100644 --- a/src/client/lib/nachweisSpeichern.ts +++ b/src/client/lib/nachweisSpeichern.ts @@ -16,7 +16,11 @@ export async function nachweisSpeichern( ) { if (objekt.uid) { await api.objekt._uid.PATCH.fetch({ - ...exclude(objekt, ["uid"]) + adresse: objekt.adresse, + latitude: 0, + longitude: 0, + ort: objekt.ort, + plz: objekt.plz }, { params: { uid: objekt.uid @@ -27,7 +31,11 @@ export async function nachweisSpeichern( }) } else { const { uid } = await api.objekt.PUT.fetch({ - ...exclude(objekt, ["uid"]) + adresse: objekt.adresse, + latitude: 0, + longitude: 0, + ort: objekt.ort, + plz: objekt.plz }, { headers: { "Authorization": `Bearer ${Cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)}` @@ -41,10 +49,58 @@ export async function nachweisSpeichern( if (aufnahme.uid) { await api.aufnahme._uid.PATCH.fetch({ - ...exclude(aufnahme, ["uid"]), baujahr_gebaeude: aufnahme.baujahr_gebaeude || [], - baujahr_klima: aufnahme.baujahr_klima || [], baujahr_heizung: aufnahme.baujahr_heizung || [], + baujahr_klima: aufnahme.baujahr_klima || [], + alternative_heizung: aufnahme.alternative_heizung, + alternative_kuehlung: aufnahme.alternative_kuehlung, + alternative_lueftung: aufnahme.alternative_lueftung, + alternative_warmwasser: aufnahme.alternative_warmwasser, + aussenwand_gedaemmt: aufnahme.aussenwand_gedaemmt, + aussenwand_min_12cm_gedaemmt: aufnahme.aussenwand_min_12cm_gedaemmt, + ausweisart: aufnahme.ausweisart, + brennstoff_1: aufnahme.brennstoff_1, + brennstoff_2: aufnahme.brennstoff_2, + brennwert_kessel: aufnahme.brennwert_kessel, + dachgeschoss: aufnahme.dachgeschoss, + dachgeschoss_gedaemmt: aufnahme.dachgeschoss_gedaemmt, + dachgeschoss_min_12cm_gedaemmt: aufnahme.dachgeschoss_min_12cm_gedaemmt, + doppel_verglasung: aufnahme.doppel_verglasung, + dreifach_verglasung: aufnahme.dreifach_verglasung, + durchlauf_erhitzer: aufnahme.durchlauf_erhitzer, + einfach_verglasung: aufnahme.einfach_verglasung, + einheiten: aufnahme.einheiten, + einzelofen: aufnahme.einzelofen, + energieeffizienzklasse: aufnahme.energieeffizienzklasse, + fenster_dicht: aufnahme.fenster_dicht, + fenster_teilweise_undicht: aufnahme.fenster_teilweise_undicht, + flaeche: aufnahme.flaeche, + gebaeudeteil: aufnahme.gebaeudeteil, + gebaeudetyp: aufnahme.gebaeudetyp, + heizungsrohre_gedaemmt: aufnahme.heizungsrohre_gedaemmt, + isolier_verglasung: aufnahme.isolier_verglasung, + keller: aufnahme.keller, + keller_decke_gedaemmt: aufnahme.keller_decke_gedaemmt, + keller_wand_gedaemmt: aufnahme.keller_wand_gedaemmt, + kuehlung: aufnahme.kuehlung, + leerstand: aufnahme.leerstand, + lueftung: aufnahme.lueftung, + niedertemperatur_kessel: aufnahme.niedertemperatur_kessel, + nutzflaeche: aufnahme.nutzflaeche, + oberste_geschossdecke_gedaemmt: aufnahme.oberste_geschossdecke_gedaemmt, + oberste_geschossdecke_min_12cm_gedaemmt: aufnahme.oberste_geschossdecke_min_12cm_gedaemmt, + photovoltaik: aufnahme.photovoltaik, + raum_temperatur_regler: aufnahme.raum_temperatur_regler, + rolllaeden_kaesten_gedaemmt: aufnahme.rolllaeden_kaesten_gedaemmt, + saniert: aufnahme.saniert, + solarsystem_warmwasser: aufnahme.solarsystem_warmwasser, + standard_kessel: aufnahme.standard_kessel, + tueren_dicht: aufnahme.tueren_dicht, + tueren_undicht: aufnahme.tueren_undicht, + waermepumpe: aufnahme.waermepumpe, + warmwasser_rohre_gedaemmt: aufnahme.warmwasser_rohre_gedaemmt, + zentralheizung: aufnahme.zentralheizung, + zirkulation: aufnahme.zirkulation }, { params: { uid: aufnahme.uid @@ -55,7 +111,61 @@ export async function nachweisSpeichern( }) } else { const { uid } = await api.aufnahme.PUT.fetch({ - aufnahme, + aufnahme: { + baujahr_gebaeude: aufnahme.baujahr_gebaeude, + baujahr_heizung: aufnahme.baujahr_heizung, + alternative_heizung: aufnahme.alternative_heizung, + alternative_kuehlung: aufnahme.alternative_kuehlung, + alternative_lueftung: aufnahme.alternative_lueftung, + alternative_warmwasser: aufnahme.alternative_warmwasser, + aussenwand_gedaemmt: aufnahme.aussenwand_gedaemmt, + aussenwand_min_12cm_gedaemmt: aufnahme.aussenwand_min_12cm_gedaemmt, + ausweisart: aufnahme.ausweisart, + baujahr_klima: aufnahme.baujahr_klima, + brennstoff_1: aufnahme.brennstoff_1, + brennstoff_2: aufnahme.brennstoff_2, + brennwert_kessel: aufnahme.brennwert_kessel, + dachgeschoss: aufnahme.dachgeschoss, + dachgeschoss_gedaemmt: aufnahme.dachgeschoss_gedaemmt, + dachgeschoss_min_12cm_gedaemmt: aufnahme.dachgeschoss_min_12cm_gedaemmt, + doppel_verglasung: aufnahme.doppel_verglasung, + dreifach_verglasung: aufnahme.dreifach_verglasung, + durchlauf_erhitzer: aufnahme.durchlauf_erhitzer, + einfach_verglasung: aufnahme.einfach_verglasung, + einheiten: aufnahme.einheiten, + einzelofen: aufnahme.einzelofen, + energieeffizienzklasse: aufnahme.energieeffizienzklasse, + erstellungsdatum: aufnahme.erstellungsdatum, + fenster_dicht: aufnahme.fenster_dicht, + fenster_teilweise_undicht: aufnahme.fenster_teilweise_undicht, + flaeche: aufnahme.flaeche, + gebaeudeteil: aufnahme.gebaeudeteil, + gebaeudetyp: aufnahme.gebaeudetyp, + heizungsrohre_gedaemmt: aufnahme.heizungsrohre_gedaemmt, + isolier_verglasung: aufnahme.isolier_verglasung, + keller: aufnahme.keller, + keller_decke_gedaemmt: aufnahme.keller_decke_gedaemmt, + keller_wand_gedaemmt: aufnahme.keller_wand_gedaemmt, + kuehlung: aufnahme.kuehlung, + leerstand: aufnahme.leerstand, + lueftung: aufnahme.lueftung, + niedertemperatur_kessel: aufnahme.niedertemperatur_kessel, + nutzflaeche: aufnahme.nutzflaeche, + oberste_geschossdecke_gedaemmt: aufnahme.oberste_geschossdecke_gedaemmt, + oberste_geschossdecke_min_12cm_gedaemmt: aufnahme.oberste_geschossdecke_min_12cm_gedaemmt, + photovoltaik: aufnahme.photovoltaik, + raum_temperatur_regler: aufnahme.raum_temperatur_regler, + rolllaeden_kaesten_gedaemmt: aufnahme.rolllaeden_kaesten_gedaemmt, + saniert: aufnahme.saniert, + solarsystem_warmwasser: aufnahme.solarsystem_warmwasser, + standard_kessel: aufnahme.standard_kessel, + tueren_dicht: aufnahme.tueren_dicht, + tueren_undicht: aufnahme.tueren_undicht, + waermepumpe: aufnahme.waermepumpe, + warmwasser_rohre_gedaemmt: aufnahme.warmwasser_rohre_gedaemmt, + zentralheizung: aufnahme.zentralheizung, + zirkulation: aufnahme.zirkulation + }, uid_objekt: objekt.uid }, { headers: { @@ -114,25 +224,4 @@ export async function nachweisSpeichern( uid_aufnahme: aufnahme.uid, uid_objekt: objekt.uid } - - - // await client.v1.tickets.erstellen.mutate({ - // titel: "Ausweis konnte nicht gespeichert werden", - // beschreibung: e.stack, - // email: user.email ?? "", - // metadata: JSON.stringify({ - // ausweis, - // }), - // }); - - // addNotification({ - // dismissable: false, - // message: - // "Ausweis konnte nicht gespeichert werden, bitte versuchen sie es erneut.", - // subtext: - // "Sollte das Problem weiterhin bestehen, kontaktieren sie bitte den Support.", - // timeout: 6000, - // type: "error", - // }); - return null; } diff --git a/src/components/Ausweis/Ausweisart.svelte b/src/components/Ausweis/Ausweisart.svelte index 7cdf51a5..0084a7f2 100644 --- a/src/components/Ausweis/Ausweisart.svelte +++ b/src/components/Ausweis/Ausweisart.svelte @@ -24,6 +24,8 @@ export let aufnahme: AufnahmeClient; export let ausweisart: Enums.Ausweisart; + + export let ausstellgrund: string[] = Object.values(Enums.Ausstellgrund);
- {#each Object.entries(Enums.Ausstellgrund) as [name, ausstellgrund]} - + {#each ausstellgrund as name} + {/each} diff --git a/src/components/Ausweis/ButtonWeiterHilfe.svelte b/src/components/Ausweis/ButtonWeiterHilfe.svelte index 95f606a9..635c412e 100644 --- a/src/components/Ausweis/ButtonWeiterHilfe.svelte +++ b/src/components/Ausweis/ButtonWeiterHilfe.svelte @@ -69,7 +69,7 @@ loginOverlayHidden = true - let result: Awaited> | null = null; + let result: Awaited> | Awaited> | null = null; if (ausweisart === Enums.Ausweisart.GEGNachweisWohnen || ausweisart === Enums.Ausweisart.GEGNachweisGewerbe || ausweisart === Enums.Ausweisart.GEGNachweisBedarfsausweis) { result = await nachweisSpeichern(ausweis, objekt, aufnahme, bilder, unterlagen, ausweisart) } else { diff --git a/src/components/GEGNachweis/GEGAusweisart.svelte b/src/components/GEGNachweis/GEGAusweisart.svelte index 53a1dbdd..4ab40b59 100644 --- a/src/components/GEGNachweis/GEGAusweisart.svelte +++ b/src/components/GEGNachweis/GEGAusweisart.svelte @@ -284,4 +284,4 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
- + \ No newline at end of file diff --git a/src/cypress/e2e/GEGNachweisGewerbe/erstellen.cy.ts b/src/cypress/e2e/GEGNachweisGewerbe/erstellen.cy.ts new file mode 100644 index 00000000..af5013c6 --- /dev/null +++ b/src/cypress/e2e/GEGNachweisGewerbe/erstellen.cy.ts @@ -0,0 +1,134 @@ +import fuelList from "#components/Ausweis/brennstoffListe.js"; +import { faker } from "@faker-js/faker"; +import { Enums } from "#lib/client/prisma.js"; + + +import "cypress-file-upload" +import moment from "moment"; + +describe("Verbrauchsausweis erstellen Schritt 1", () => { + it("erstellt einen neuen Verbrauchsausweis Wohngebäude.", () => { + cy.visit("/angebot-anfragen/geg-nachweis-gewerbe-anfragen"); + + cy.wait(2000); + + // Wir überprüfen, ob alle Ausstelgründe vorhanden sind, diese sollten genau so viele sein wie in der Datenbank vorhanden sind. + cy.get("select[data-cy='ausstellgrund']") + .select( + faker.number.int({ + min: 1, + max: [Enums.Ausstellgrund.Modernisierung, Enums.Ausstellgrund.Neubau].length - 1, + }) + ) + + // Gebäudetyp + cy.get("select[name='gebaeudetyp']").then(($dropdown) => { + const options = $dropdown.find('option'); + // Select the option at the random index + cy.get("select[name='gebaeudetyp']").select(options.eq(faker.number.int({ min: 1, max: options.length - 1 })).val() as string); + }); + + // Sanierungsstatus + cy.get("select[name='saniert']").select( + Math.random() > 0.5 ? "true" : "false" + ); + + // Jetzt Füllen wir das Baujahr vom Gebäude aus. + cy.get("input[name='baujahr_gebaeude']") + .should("have.attr", "type", "number") + .type( + faker.number.int({ min: 1900, max: 2021 }).toString() + + "{enter}", + { delay: 50 } + ); + + // Jetzt Füllen wir das Baujahr der Heizung aus. + cy.get("input[name='baujahr_heizung']") + .should("have.attr", "type", "number") + .type( + faker.number.int({ min: 1900, max: 2021 }).toString() + + "{enter}", + { delay: 50 } + ); + + // Adresse + cy.get("input[name='adresse']").type(faker.location.streetAddress()); + + // Postleitzahl + cy.get("input[name='plz']").type( + faker.location.zipCode({ + format: "#####", + }) + ); + + // TODO: Ort - Dieser wird aus der Datenbank abgefragt, wir müssen also warten, bis der Dropdown da ist. + cy.get("[data-cy='plz-container']").find("button").first().click() + + // Nutzflaeche + cy.get("input[name='nutzflaeche']") + .should("have.attr", "type", "number") + .type(faker.number.int({ min: 50, max: 1000 }).toString()); + + // Keller + cy.get("select[name='keller']").find("option:not([disabled])").should("have.length", (["BEHEIZT", "NICHT_VORHANDEN", "UNBEHEIZT"] as Enums.Heizungsstatus[]).length).parent().select(faker.number.int({ + max: Object.values(Enums.Heizungsstatus).length, + min: 1 + })); + + // Dachgeschoss + cy.get("select[name='dachgeschoss']").find("option:not([disabled])").should("have.length", (["BEHEIZT", "NICHT_VORHANDEN", "UNBEHEIZT"] as Enums.Heizungsstatus[]).length).parent().select(faker.number.int({ + max: Object.values(Enums.Heizungsstatus).length, + min: 1 + })); + + cy.get("[data-cy='beschreibung']").type(faker.lorem.paragraphs({ min: 2, max: 10 })) + + // Wärmedämmung Bilder + cy.get("input[type='file'][name='plaene']").should("have.attr", "type", "file").attachFile("images/daemmung/1.jpeg", { subjectType: "input" }).attachFile("images/daemmung/2.jpeg", { subjectType: "input" }); + cy.get("input[type='file'][name='unterlagen']").should("have.attr", "type", "file").attachFile("images/gebaeude/1.jpeg", { subjectType: "input" }).attachFile("images/daemmung/2.jpeg", { subjectType: "input" }); + + // Jetzt können wir den Verbrauchsausweis erstellen. + cy.get("form[data-cy='nachweis'] button[data-cy='weiter']").click({ force: true }); + + cy.url().should("contain", "/kundendaten"); + + const email = faker.internet.email(); + const passwort = "test1234"; + const vorname = faker.person.firstName(); + const nachname = faker.person.lastName(); + const telefon = faker.phone.number() + + const strasse = faker.location.streetAddress({ useFullAddress: true }) + const plz = faker.location.zipCode("#####") + + cy.get("input[name='vorname']").should("have.attr", "type", "text").type(vorname); + cy.get("input[name='name']").should("have.attr", "type", "text").type(nachname); + cy.get("input[name='telefon']").should("have.attr", "type", "text").type(telefon); + // Rechnung + cy.get("input[name='rechnung_empfaenger']").should("have.attr", "type", "text").type(`${vorname} ${nachname}`); + cy.get("input[name='rechnung_strasse']").should("have.attr", "type", "text").type(strasse); + cy.get("input[name='rechnung_plz']").should("have.attr", "type", "text").type(plz); + cy.get("[data-cy='plz-container']").children().first().click() + cy.get("input[name='rechnung_email']").should("have.attr", "type", "email").type(email); + + cy.get("button[data-cy='bestellen']").click(); + + cy.get("a[data-cy='registrieren']").should("be.visible").click(); + + // Wir sind jetzt registriert und können uns nun einloggen. + // Die Email sollte automatisch eingetragen sein, da wir uns gerade registriert haben. + cy.get("form[name='signup'] input[name='vorname']").should("be.visible").should("have.attr", "type", "text").type(vorname); + cy.get("form[name='signup'] input[name='nachname']").should("be.visible").should("have.attr", "type", "text").type(nachname); + cy.get("form[name='signup'] input[name='email']").should("be.visible").should("have.attr", "type", "email").should("contain.value", email); + cy.get("form[name='signup'] input[name='passwort']").should("be.visible").should("have.attr", "type", "password").type(passwort); + + cy.get("form[name='signup'] button[type='submit']").click(); + cy.get("form[name='login'] button[type='submit']").click(); + + cy.origin('https://www.mollie.com', () => { + // Jetzt sind wir auf der Mollie Seite, dort wählen wir den "paid" status aus + cy.get("input[type='radio'][name='final_state'][value='paid']").check(); + // Da wird unser Test fehlschlagen, da die localhost domain von Mollie aus nicht erreichbar ist. + }) + }); +}); diff --git a/src/modules/KundendatenModule.svelte b/src/modules/KundendatenModule.svelte index 77288a27..15169335 100644 --- a/src/modules/KundendatenModule.svelte +++ b/src/modules/KundendatenModule.svelte @@ -153,27 +153,24 @@ } if (!await validateAccessTokenClient()) { - loginAction = bestellen + loginAction = anfordern loginOverlayHidden = false; return } loginOverlayHidden = true - let result: Awaited> | null = null; + let result: Awaited> | null = null; try { - if (ausweisart === Enums.Ausweisart.GEGNachweisWohnen) { - result = await nachweisSpeichern(ausweis, objekt, aufnahme, bilder, unterlagen, ausweisart) - } else { - result = await ausweisSpeichern(ausweis, objekt, aufnahme, bilder, ausweisart) - } + result = await nachweisSpeichern(ausweis, objekt, aufnahme, bilder, unterlagen, ausweisart) } catch(e) { addNotification({ dismissable: true, message: "Ups... Das hat nicht geklappt.", subtext: "Speichern ist fehlgeschlagen, bitte versuchen sie es erneut oder kontaktieren sie unseren Support." }) + return; } try { @@ -189,7 +186,7 @@ versand_plz: $versand_plz, versand_ort: $versand_ort, telefon: $telefon, - nachweis_uid: ausweis.uid, + nachweis_uid: result.uid_nachweis, }, { headers: { @@ -201,7 +198,7 @@ // Alle alten Ausweisdateien im localStorage löschen. localStorage.clear(); - window.location.href = `/einpreisung/success?e=${uid}&a=${ausweis.uid}`; + window.location.href = `/einpreisung/success?e=${uid}&a=${result.uid_nachweis}`; } catch (e) { addNotification({ dismissable: true, @@ -220,7 +217,7 @@ loginOverlayHidden = true - let result: Awaited> | null = null; + let result: Awaited> | Awaited> | null = null; try { if (ausweisart === Enums.Ausweisart.GEGNachweisWohnen) { result = await nachweisSpeichern(ausweis, objekt, aufnahme, bilder, unterlagen, ausweisart) @@ -267,7 +264,7 @@ loginOverlayHidden = true - let result: Awaited> | null = null; + let result: Awaited> | Awaited> | null = null; if (ausweisart === Enums.Ausweisart.GEGNachweisWohnen || ausweisart === Enums.Ausweisart.GEGNachweisGewerbe || ausweisart === Enums.Ausweisart.GEGNachweisBedarfsausweis) { result = await nachweisSpeichern(ausweis, objekt, aufnahme, bilder, unterlagen, ausweisart) } else { diff --git a/src/modules/angebot-anfragen/GEGNachweisGewerbeModule.svelte b/src/modules/angebot-anfragen/GEGNachweisGewerbeModule.svelte index 4ad89f39..608acdde 100644 --- a/src/modules/angebot-anfragen/GEGNachweisGewerbeModule.svelte +++ b/src/modules/angebot-anfragen/GEGNachweisGewerbeModule.svelte @@ -10,87 +10,124 @@ GEGNachweisWohnenClient, } from "#components/Ausweis/types.js"; import Bereich from "#components/labels/Bereich.svelte"; - import { Enums } from "#lib/client/prisma"; + import { Enums } from "#lib/client/prisma.js"; import InputLabel from "#components/labels/InputLabel.svelte"; import HelpLabel from "#components/labels/HelpLabel.svelte"; import Progressbar from "#components/Ausweis/Progressbar.svelte"; import FileGrid from "#components/FileGrid.svelte"; import ButtonWeiterHilfe from "#components/Ausweis/ButtonWeiterHilfe.svelte"; - export let nachweis: GEGNachweisWohnenClient; export let objekt: ObjektClient; export let aufnahme: AufnahmeClient; export let user: BenutzerClient = {} as BenutzerClient; export let bilder: UploadedGebaeudeBild[] = []; - export let plaene: UnterlageClient[] = - []; + export let plaene: UnterlageClient[] = []; export let unterlagen: UnterlageClient[] = []; if (Object.keys(nachweis).length === 0) { - const localStorageAusweis = localStorage.getItem("ausweis"); + const localStorageAusweis = localStorage.getItem( + "geg-nachweis-gewerbe.ausweis" + ); if (localStorageAusweis) { - nachweis = JSON.parse(localStorageAusweis) + nachweis = JSON.parse(localStorageAusweis); } } if (Object.keys(aufnahme).length === 0) { - const localStorageAufnahme = localStorage.getItem("aufnahme"); + const localStorageAufnahme = localStorage.getItem( + "geg-nachweis-gewerbe.aufnahme" + ); if (localStorageAufnahme) { - aufnahme = JSON.parse(localStorageAufnahme) + aufnahme = JSON.parse(localStorageAufnahme); } } if (Object.keys(objekt).length === 0) { - const localStorageObjekt = localStorage.getItem("objekt"); + const localStorageObjekt = localStorage.getItem( + "geg-nachweis-gewerbe.objekt" + ); if (localStorageObjekt) { - objekt = JSON.parse(localStorageObjekt) + objekt = JSON.parse(localStorageObjekt); } } if (Object.keys(bilder).length === 0) { - const localStorageBilder = localStorage.getItem("bilder"); + const localStorageBilder = localStorage.getItem( + "geg-nachweis-gewerbe.bilder" + ); if (localStorageBilder) { - bilder = JSON.parse(localStorageBilder) + bilder = JSON.parse(localStorageBilder); } } if (Object.keys(unterlagen).length === 0) { - const localStorageUnterlagen = localStorage.getItem("unterlagen"); + const localStorageUnterlagen = localStorage.getItem( + "geg-nachweis-gewerbe.unterlagen" + ); if (localStorageUnterlagen) { - unterlagen = JSON.parse(localStorageUnterlagen) + unterlagen = JSON.parse(localStorageUnterlagen); } } - $: { - localStorage.setItem("ausweis", JSON.stringify(nachweis)) - localStorage.setItem("aufnahme", JSON.stringify(aufnahme)) - localStorage.setItem("objekt", JSON.stringify(objekt)) - localStorage.setItem("bilder", JSON.stringify(bilder)) - localStorage.setItem("unterlagen", JSON.stringify(unterlagen)) + localStorage.setItem( + "geg-nachweis-gewerbe.ausweis", + JSON.stringify(nachweis) + ); + localStorage.setItem( + "geg-nachweis-gewerbe.aufnahme", + JSON.stringify(aufnahme) + ); + localStorage.setItem( + "geg-nachweis-gewerbe.objekt", + JSON.stringify(objekt) + ); + localStorage.setItem( + "geg-nachweis-gewerbe.bilder", + JSON.stringify(bilder) + ); + localStorage.setItem( + "geg-nachweis-gewerbe.unterlagen", + JSON.stringify(unterlagen) + ); } const ausweisart = Enums.Ausweisart.GEGNachweisGewerbe; const anliegen = "Angebot anfragen"; + + let skala: HTMLDivElement; + let form: HTMLFormElement; -
- - - +
+
-
+
- + @@ -108,7 +145,12 @@ title="Angaben zur Heizung, Lüftung, Energieerezugung, Qualität und Aufbau der Gebäudehülle usw." > - +
@@ -181,14 +223,14 @@
- - + bind:ausweis={nachweis} + bind:bilder + bind:unterlagen + bind:user + bind:objekt + bind:aufnahme + ausweisart={Enums.Ausweisart.GEGNachweisGewerbe} + {form} + {skala} + > diff --git a/src/modules/angebot-anfragen/GEGNachweisWohnenModule.svelte b/src/modules/angebot-anfragen/GEGNachweisWohnenModule.svelte index 6b8c0ae3..2d05d14e 100644 --- a/src/modules/angebot-anfragen/GEGNachweisWohnenModule.svelte +++ b/src/modules/angebot-anfragen/GEGNachweisWohnenModule.svelte @@ -1,13 +1,12 @@ -
- - - -
- -
+ +
+ +
- + @@ -112,7 +141,11 @@ title="Angaben zur Heizung, Lüftung, Energieerezugung, Qualität und Aufbau der Gebäudehülle usw." > - +
@@ -185,16 +218,14 @@
- - + bind:ausweis={nachweis} + bind:bilder + bind:unterlagen + bind:user + bind:objekt + bind:aufnahme + ausweisart={Enums.Ausweisart.GEGNachweisWohnen} + {form} + {skala} + > diff --git a/src/pages/angebot-anfragen/geg-nachweis-wohnen-anfragen/index.astro b/src/pages/angebot-anfragen/geg-nachweis-wohnen-anfragen/index.astro index b96d11b4..e8718bea 100644 --- a/src/pages/angebot-anfragen/geg-nachweis-wohnen-anfragen/index.astro +++ b/src/pages/angebot-anfragen/geg-nachweis-wohnen-anfragen/index.astro @@ -1,6 +1,6 @@ --- import AusweisLayout from "#layouts/AusweisLayoutDaten.astro"; -import { AufnahmeClient, GEGNachweisWohnenClient, ObjektClient, UnterlageClient, UploadedGebaeudeBild } from "#components/Ausweis/types"; +import { AufnahmeClient, BildClient, GEGNachweisWohnenClient, ObjektClient, UnterlageClient } from "#components/Ausweis/types"; import { createCaller } from "src/astro-typesafe-api-caller"; import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js"; import { validateAccessTokenServer } from "#server/lib/validateAccessToken.js"; @@ -10,7 +10,7 @@ const uid = Astro.url.searchParams.get("uid"); let nachweis: GEGNachweisWohnenClient = {} as GEGNachweisWohnenClient; let aufnahme: AufnahmeClient = {} as AufnahmeClient; let objekt: ObjektClient = {} as ObjektClient; -let bilder: UploadedGebaeudeBild[] = [] +let bilder: BildClient[] = [] let unterlagen: UnterlageClient[] = [] const valid = validateAccessTokenServer(Astro); diff --git a/src/pages/api/aufnahme/index.ts b/src/pages/api/aufnahme/index.ts index 439fe1ff..1c54363f 100644 --- a/src/pages/api/aufnahme/index.ts +++ b/src/pages/api/aufnahme/index.ts @@ -1,7 +1,8 @@ import { UUidWithPrefix } from "#components/Ausweis/types.js" import { authorizationMiddleware } from "#lib/middleware/authorization.js" -import { AufnahmeSchema, ObjektSchema, prisma } from "#lib/server/prisma.js" +import { prisma } from "#lib/server/prisma.js" import { APIError, defineApiRoute } from "astro-typesafe-api/server" +import { AufnahmeSchema } from "src/generated/zod/aufnahme.js" import { z } from "zod" export const PUT = defineApiRoute({ diff --git a/src/pages/api/geg-nachweis-gewerbe/index.ts b/src/pages/api/geg-nachweis-gewerbe/index.ts index aebdbefc..612350a0 100644 --- a/src/pages/api/geg-nachweis-gewerbe/index.ts +++ b/src/pages/api/geg-nachweis-gewerbe/index.ts @@ -1,7 +1,8 @@ import { UUidWithPrefix } from "#components/Ausweis/types.js"; import { authorizationHeaders, authorizationMiddleware } from "#lib/middleware/authorization.js"; -import { GEGNachweisGewerbeSchema, GEGNachweisWohnenSchema, prisma } from "#lib/server/prisma"; +import { prisma } from "#lib/server/prisma.js"; import { APIError, defineApiRoute } from "astro-typesafe-api/server"; +import { GEGNachweisGewerbeSchema } from "src/generated/zod/gegnachweisgewerbe.js"; import { z } from "zod"; export const PUT = defineApiRoute({ @@ -18,6 +19,7 @@ export const PUT = defineApiRoute({ uid: true, aufnahme_id: true, geg_einpreisung_id: true, + rechnung_id: true }), uid_aufnahme: UUidWithPrefix }), @@ -109,7 +111,6 @@ export const GET = defineApiRoute({ benutzer: true, aufnahme: { include: { - rechnungen: true, events: { include: { benutzer: { diff --git a/src/pages/api/geg-nachweis-wohnen/index.ts b/src/pages/api/geg-nachweis-wohnen/index.ts index 53c0471e..c8a8b968 100644 --- a/src/pages/api/geg-nachweis-wohnen/index.ts +++ b/src/pages/api/geg-nachweis-wohnen/index.ts @@ -1,7 +1,8 @@ import { UUidWithPrefix } from "#components/Ausweis/types.js"; import { authorizationHeaders, authorizationMiddleware } from "#lib/middleware/authorization.js"; -import { GEGNachweisWohnenSchema, prisma } from "#lib/server/prisma"; +import { prisma } from "#lib/server/prisma.js"; import { APIError, defineApiRoute } from "astro-typesafe-api/server"; +import { GEGNachweisWohnenSchema } from "src/generated/zod/gegnachweiswohnen.js"; import { z } from "zod"; export const PUT = defineApiRoute({ @@ -17,7 +18,8 @@ export const PUT = defineApiRoute({ benutzer_id: true, uid: true, aufnahme_id: true, - geg_einpreisung_id: true + geg_einpreisung_id: true, + rechnung_id: true }), uid_aufnahme: UUidWithPrefix }), @@ -109,7 +111,6 @@ export const GET = defineApiRoute({ benutzer: true, aufnahme: { include: { - rechnungen: true, events: { include: { benutzer: { diff --git a/src/pages/api/rechnung/anfordern.ts b/src/pages/api/rechnung/anfordern.ts index a73f7a29..21a50ce6 100644 --- a/src/pages/api/rechnung/anfordern.ts +++ b/src/pages/api/rechnung/anfordern.ts @@ -2,7 +2,7 @@ import { getAusweisartFromUUID, UUidWithPrefix } from "#components/Ausweis/types import { omit } from "#lib/helpers.js"; import { authorizationHeaders, authorizationMiddleware } from "#lib/middleware/authorization.js"; import { sendGEGAnforderungsMail } from "#lib/server/mail/geg-anfordern.js"; -import { Enums, prisma } from "#lib/server/prisma.js"; +import { Enums, GEGNachweisGewerbe, GEGNachweisWohnen, prisma } from "#lib/server/prisma.js"; import { APIError, defineApiRoute } from "astro-typesafe-api/server"; import { GEGEinpreisungSchema } from "src/generated/zod/gegeinpreisung.js"; import { z } from "zod"; @@ -22,21 +22,35 @@ export const PUT = defineApiRoute({ const ausweisart = getAusweisartFromUUID(input.nachweis_uid); let einpreisung; + let nachweis: GEGNachweisWohnen | GEGNachweisGewerbe; if (ausweisart === Enums.Ausweisart.GEGNachweisWohnen) { - const nachweis = await prisma.gEGNachweisWohnen.findUnique({ + nachweis = await prisma.gEGNachweisWohnen.findUnique({ where: { uid: input.nachweis_uid } }) + } else if (ausweisart === Enums.Ausweisart.GEGNachweisGewerbe) { + nachweis = await prisma.gEGNachweisGewerbe.findUnique({ + where: { + uid: input.nachweis_uid + } + }) + } else { + throw new APIError({ + "code": "BAD_REQUEST", + "message": `Ausweisart wird nicht unterstützt: ${ausweisart}` + }) + } + - if (!nachweis || nachweis.benutzer_id !== user.id) { - throw new APIError({ - code: "BAD_REQUEST", - message: "Ausweis existiert nicht oder gehört einem anderen Benutzer." - }) - } - + if (!nachweis || nachweis.benutzer_id !== user.id) { + throw new APIError({ + code: "BAD_REQUEST", + message: "Ausweis existiert nicht oder gehört einem anderen Benutzer." + }) + } + if (ausweisart === Enums.Ausweisart.GEGNachweisWohnen) { einpreisung = await prisma.gEGEinpreisung.create({ data: { ...omit(input, ["nachweis_uid"]), @@ -53,16 +67,26 @@ export const PUT = defineApiRoute({ } } }) - await sendGEGAnforderungsMail(nachweis, user) - } else { - throw new APIError({ - "code": "BAD_REQUEST", - "message": `Ausweisart wird nicht unterstützt: ${ausweisart}` + } else if (ausweisart === Enums.Ausweisart.GEGNachweisGewerbe) { + einpreisung = await prisma.gEGEinpreisung.create({ + data: { + ...omit(input, ["nachweis_uid"]), + status: Enums.Einpreisungsstatus.open, + benutzer: { + connect: { + id: user.id + } + }, + geg_nachweis_gewerbe: { + connect: { + uid: input.nachweis_uid + } + } + } }) } - - + await sendGEGAnforderungsMail(nachweis, user) return { uid: einpreisung.uid diff --git a/src/pages/kundendaten.astro b/src/pages/kundendaten.astro index e11cda87..9a829cee 100644 --- a/src/pages/kundendaten.astro +++ b/src/pages/kundendaten.astro @@ -35,6 +35,6 @@ try { --- - + From ed4f5fdf37c113fcdf772dcc7dca25a9c0b7e0d8 Mon Sep 17 00:00:00 2001 From: Jens Cornelsen <79703163+IB-Cornelsen@users.noreply.github.com> Date: Wed, 12 Mar 2025 20:58:23 +0100 Subject: [PATCH 02/17] E-Mail Text geg-anfordern --- .../migrations/20250312191859_/migration.sql | 47 +++++++++++++++++++ src/astro-typesafe-api-caller.ts | 2 +- .../Dashboard/DashboardAusweis.svelte | 4 +- src/generated/zod/aufnahme.ts | 2 +- src/lib/server/mail/geg-anfordern.ts | 4 +- 5 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 prisma/migrations/20250312191859_/migration.sql diff --git a/prisma/migrations/20250312191859_/migration.sql b/prisma/migrations/20250312191859_/migration.sql new file mode 100644 index 00000000..4e4efaa6 --- /dev/null +++ b/prisma/migrations/20250312191859_/migration.sql @@ -0,0 +1,47 @@ +-- AlterTable +ALTER TABLE "Anteilshaber" ALTER COLUMN "uid" SET DEFAULT 'ant-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Aufnahme" ALTER COLUMN "uid" SET DEFAULT 'auf-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "BedarfsausweisGewerbe" ALTER COLUMN "uid" SET DEFAULT 'bag-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "BedarfsausweisWohnen" ALTER COLUMN "uid" SET DEFAULT 'baw-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Bild" ALTER COLUMN "uid" SET DEFAULT 'img-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Event" ALTER COLUMN "uid" SET DEFAULT 'evt-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "GEGEinpreisung" ALTER COLUMN "uid" SET DEFAULT 'gge-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "GEGNachweisGewerbe" ALTER COLUMN "uid" SET DEFAULT 'gnw-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "GEGNachweisWohnen" ALTER COLUMN "uid" SET DEFAULT 'gnw-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Objekt" ALTER COLUMN "uid" SET DEFAULT 'obj-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Rechnung" ALTER COLUMN "uid" SET DEFAULT 'inv-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Tickets" ALTER COLUMN "uid" SET DEFAULT 'tkt-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Unterlage" ALTER COLUMN "uid" SET DEFAULT 'pln-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "VerbrauchsausweisGewerbe" ALTER COLUMN "uid" SET DEFAULT 'vag-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "VerbrauchsausweisWohnen" ALTER COLUMN "uid" SET DEFAULT 'vaw-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "benutzer" ALTER COLUMN "uid" SET DEFAULT 'usr-' || gen_random_uuid(); diff --git a/src/astro-typesafe-api-caller.ts b/src/astro-typesafe-api-caller.ts index cf94b56b..2409471b 100644 --- a/src/astro-typesafe-api-caller.ts +++ b/src/astro-typesafe-api-caller.ts @@ -13,12 +13,12 @@ export const createCaller = createCallerFactory({ "admin/registriernummer": await import("../src/pages/api/admin/registriernummer.ts"), "admin/stornieren": await import("../src/pages/api/admin/stornieren.ts"), "aufnahme": await import("../src/pages/api/aufnahme/index.ts"), + "ausweise": await import("../src/pages/api/ausweise/index.ts"), "auth/access-token": await import("../src/pages/api/auth/access-token.ts"), "auth/passwort-vergessen": await import("../src/pages/api/auth/passwort-vergessen.ts"), "auth/refresh-token": await import("../src/pages/api/auth/refresh-token.ts"), "bedarfsausweis-wohnen/[uid]": await import("../src/pages/api/bedarfsausweis-wohnen/[uid].ts"), "bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"), - "ausweise": await import("../src/pages/api/ausweise/index.ts"), "bilder/[uid]": await import("../src/pages/api/bilder/[uid].ts"), "geg-nachweis-gewerbe/[uid]": await import("../src/pages/api/geg-nachweis-gewerbe/[uid].ts"), "geg-nachweis-gewerbe": await import("../src/pages/api/geg-nachweis-gewerbe/index.ts"), diff --git a/src/components/Dashboard/DashboardAusweis.svelte b/src/components/Dashboard/DashboardAusweis.svelte index cac40e37..3d6be4d4 100644 --- a/src/components/Dashboard/DashboardAusweis.svelte +++ b/src/components/Dashboard/DashboardAusweis.svelte @@ -145,7 +145,9 @@ {#if ausweis.ausgestellt} Ausgestellt {:else if ausweis.bestellt} - Bestellt + Bestellt + {:else} + Gespeichert {/if}
{objekt.adresse}
diff --git a/src/generated/zod/aufnahme.ts b/src/generated/zod/aufnahme.ts index 0ee517f9..f4c28bce 100644 --- a/src/generated/zod/aufnahme.ts +++ b/src/generated/zod/aufnahme.ts @@ -55,7 +55,7 @@ export const AufnahmeSchema = z.object({ dachgeschoss_gedaemmt: z.boolean().describe("Falls das Dachgeschoss des Gebäudes gedämmt ist, sollte dieser Wert auf true stehen").nullish(), keller_decke_gedaemmt: z.boolean().describe("Falls die Kellerdecke des Gebäudes gedämmt ist, sollte dieser Wert auf true stehen").nullish(), keller_wand_gedaemmt: z.boolean().describe("Falls die Kellerwände des Gebäudes gedämmt sind, sollte dieser Wert auf true stehen").nullish(), - aussenwand_gedaemmt: z.boolean().describe("Falls die Außenwände des Gebäudes gedämmt sind, sollte dieser Wert auf true stehen").nullish(), + aussenwand_gedaemmt: z.boolean().describe("Falls die Außenwände des Gebäudes ged��mmt sind, sollte dieser Wert auf true stehen").nullish(), oberste_geschossdecke_gedaemmt: z.boolean().describe("Falls die oberste Geschossdecke des Gebäudes gedämmt ist, sollte dieser Wert auf true stehen").nullish(), aussenwand_min_12cm_gedaemmt: z.boolean().describe("Falls die Außenwände des Gebäudes mindestens 12cm gedämmt sind, sollte dieser Wert auf true stehen").nullish(), dachgeschoss_min_12cm_gedaemmt: z.boolean().describe("Falls das Dachgeschoss des Gebäudes mindestens 12cm gedämmt ist, sollte dieser Wert auf true stehen").nullish(), diff --git a/src/lib/server/mail/geg-anfordern.ts b/src/lib/server/mail/geg-anfordern.ts index d1624e20..072a0583 100644 --- a/src/lib/server/mail/geg-anfordern.ts +++ b/src/lib/server/mail/geg-anfordern.ts @@ -13,7 +13,7 @@ export async function sendGEGAnforderungsMail( await transport.sendMail({ from: `"IBCornelsen" `, to: user.email, - subject: `GEG Nachweis angefordert beim IBCornelsen (ID: ${nachweis.id})`, + subject: `Angebotsanfrage GEG Nachweis - IBCornelsen (ID: ${nachweis.id})`, cc: { address: user.email || "", name: user.name || "", @@ -22,7 +22,7 @@ export async function sendGEGAnforderungsMail( html: `

Sehr geehrte/r ${user.vorname} ${user.name},

- Sie haben einen GEG Nachweis bei uns angefordert.

+ Ihre Angebotsanfrage zum GEG Nachweis ist bei uns eingegangen.

Mit freundlichen Grüßen,
From 6b255232c68b316907910347c001c4c8d1477abd Mon Sep 17 00:00:00 2001 From: Jens Cornelsen <79703163+IB-Cornelsen@users.noreply.github.com> Date: Wed, 12 Mar 2025 21:18:34 +0100 Subject: [PATCH 03/17] . --- src/components/Dashboard/DashboardAusweis.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Dashboard/DashboardAusweis.svelte b/src/components/Dashboard/DashboardAusweis.svelte index 3d6be4d4..4404fcef 100644 --- a/src/components/Dashboard/DashboardAusweis.svelte +++ b/src/components/Dashboard/DashboardAusweis.svelte @@ -89,7 +89,7 @@ -

+
{#if ausweis.storniert}
Date: Wed, 12 Mar 2025 18:14:13 -0300 Subject: [PATCH 04/17] Bedarfsausweis gewerbe --- dbml/schema.dbml | 18 +- .../migration.sql | 66 +++++ .../migrations/20250312210347_/migration.sql | 62 +++++ prisma/schema/BedarfsausweisGewerbe.prisma | 33 ++- prisma/schema/Bild.prisma | 1 + prisma/schema/GEGNachweisGewerbe.prisma | 2 +- prisma/schema/schema.prisma | 1 - src/astro-typesafe-api-caller.ts | 11 +- src/client/lib/helpers.ts | 7 +- src/client/lib/nachweisSpeichern.ts | 3 + src/components/Ausweis/AnlagenTechnik.svelte | 110 +++++++++ .../Ausweis/AnlagenTechnikImage.svelte | 39 +++ .../Ausweis/ButtonWeiterHilfe.svelte | 2 +- src/components/Ausweis/DaemmungImage.svelte | 2 +- .../Dashboard/DashboardAusweis.svelte | 5 +- .../Dashboard/DashboardNachweis.svelte | 2 +- .../GEGNachweis/GEGAusweisart.svelte | 2 +- src/generated/enums.ts | 2 +- src/generated/zod/bedarfsausweisgewerbe.ts | 17 ++ src/lib/pdf/pdfVerbrauchsausweisGewerbe.ts | 128 +++++----- src/lib/server/mail/invoice.ts | 9 +- src/lib/server/mail/payment-success.ts | 8 +- src/modules/KundendatenModule.svelte | 14 +- .../VerbrauchsausweisWohnenModule.svelte | 2 +- .../BedarfsausweisGewerbeModule.svelte | 233 ++++++++++++++++++ .../index.astro | 91 ++++++- src/pages/api/bedarfsausweis-gewerbe/[uid].ts | 212 ++++++++++++++++ src/pages/api/bedarfsausweis-gewerbe/index.ts | 144 +++++++++++ src/pages/api/rechnung/[uid].ts | 2 +- src/pages/api/rechnung/anfordern.ts | 23 ++ src/server/lib/hash.ts | 13 + src/types/fake-data.ts | 26 +- 32 files changed, 1182 insertions(+), 108 deletions(-) create mode 100644 prisma/migrations/20250312210235_bedarfsausweis_gewerbe/migration.sql create mode 100644 prisma/migrations/20250312210347_/migration.sql create mode 100644 src/components/Ausweis/AnlagenTechnik.svelte create mode 100644 src/components/Ausweis/AnlagenTechnikImage.svelte create mode 100644 src/modules/angebot-anfragen/BedarfsausweisGewerbeModule.svelte create mode 100644 src/pages/api/bedarfsausweis-gewerbe/[uid].ts create mode 100644 src/pages/api/bedarfsausweis-gewerbe/index.ts create mode 100644 src/server/lib/hash.ts diff --git a/dbml/schema.dbml b/dbml/schema.dbml index dfafbfd6..a7e5305a 100644 --- a/dbml/schema.dbml +++ b/dbml/schema.dbml @@ -108,6 +108,22 @@ Table Aufnahme { Table BedarfsausweisGewerbe { id Int [pk, increment] uid String [unique, not null] + ausstellgrund Ausstellgrund [note: '@zod.describe("Ausstellgrund wie z.B. Vermietung oder Verkauf")'] + keller_beheizt Boolean [note: '@zod.describe("Falls der Keller des Gebäudes beheizt wird, sollte dieser Wert auf true stehen")'] + storniert Boolean [default: false, note: '@zod.describe("Falls die Nachweisanfrage storniert wurde, sollte dieser Wert auf true stehen")'] + bestellt Boolean [default: false, note: '@zod.describe("Falls der Nachweis bestellt wurde, sollte dieser Wert auf true stehen")'] + zurueckgestellt Boolean [default: false, note: '@zod.describe("Falls der Nachweis vom Aussteller zurückgestellt wurde, sollte dieser Wert auf true stehen")'] + abluftanlage Boolean [default: false] + zu_abluftanlage Boolean [default: false] + konditionierung_der_zuluft Boolean [default: false] + luftheizung Boolean [default: false] + hallenheizung Boolean [default: false] + dunkelstrahler Boolean [default: false] + direktheizung Boolean [default: false] + infrarotstrahler Boolean [default: false] + fussbodenheizung Boolean [default: false] + bauteilaktivierung Boolean [default: false] + klimatisierung Boolean [default: false] benutzer_id Int [note: '@zod.describe("Die ID des Benutzers, welchem dieser Ausweis gehört")'] benutzer benutzer aufnahme_id Int [unique, not null] @@ -571,6 +587,7 @@ Enum BilderKategorie { Fenster Gebaeude Daemmung + AnlagenTechnik } Enum Einpreisungsstatus { @@ -631,7 +648,6 @@ Enum Ausweisart { BedarfsausweisWohnen BedarfsausweisGewerbe GEGNachweisWohnen - GEGNachweisBedarfsausweis GEGNachweisGewerbe } diff --git a/prisma/migrations/20250312210235_bedarfsausweis_gewerbe/migration.sql b/prisma/migrations/20250312210235_bedarfsausweis_gewerbe/migration.sql new file mode 100644 index 00000000..99b144c7 --- /dev/null +++ b/prisma/migrations/20250312210235_bedarfsausweis_gewerbe/migration.sql @@ -0,0 +1,66 @@ +-- AlterEnum +ALTER TYPE "BilderKategorie" ADD VALUE 'AnlagenTechnik'; + +-- AlterTable +ALTER TABLE "Anteilshaber" ALTER COLUMN "uid" SET DEFAULT 'ant-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Aufnahme" ALTER COLUMN "uid" SET DEFAULT 'auf-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "BedarfsausweisGewerbe" ADD COLUMN "abluftanlage" BOOLEAN DEFAULT false, +ADD COLUMN "ausstellgrund" "Ausstellgrund", +ADD COLUMN "bauteilaktivierung" BOOLEAN DEFAULT false, +ADD COLUMN "bestellt" BOOLEAN DEFAULT false, +ADD COLUMN "direktheizung" BOOLEAN DEFAULT false, +ADD COLUMN "dunkelstrahler" BOOLEAN DEFAULT false, +ADD COLUMN "fussbodenheizung" BOOLEAN DEFAULT false, +ADD COLUMN "hallenheizung" BOOLEAN DEFAULT false, +ADD COLUMN "infrarotstrahler" BOOLEAN DEFAULT false, +ADD COLUMN "keller_beheizt" BOOLEAN, +ADD COLUMN "klimatisierung" BOOLEAN DEFAULT false, +ADD COLUMN "konditionierung_der_zuluft" BOOLEAN DEFAULT false, +ADD COLUMN "luftheizung" BOOLEAN DEFAULT false, +ADD COLUMN "storniert" BOOLEAN DEFAULT false, +ADD COLUMN "zu_abluftanlage" BOOLEAN DEFAULT false, +ADD COLUMN "zurueckgestellt" BOOLEAN DEFAULT false, +ALTER COLUMN "uid" SET DEFAULT 'bag-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "BedarfsausweisWohnen" ALTER COLUMN "uid" SET DEFAULT 'baw-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Bild" ALTER COLUMN "uid" SET DEFAULT 'img-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Event" ALTER COLUMN "uid" SET DEFAULT 'evt-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "GEGEinpreisung" ALTER COLUMN "uid" SET DEFAULT 'gge-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "GEGNachweisGewerbe" ALTER COLUMN "uid" SET DEFAULT 'gng-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "GEGNachweisWohnen" ALTER COLUMN "uid" SET DEFAULT 'gnw-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Objekt" ALTER COLUMN "uid" SET DEFAULT 'obj-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Rechnung" ALTER COLUMN "uid" SET DEFAULT 'inv-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Tickets" ALTER COLUMN "uid" SET DEFAULT 'tkt-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Unterlage" ALTER COLUMN "uid" SET DEFAULT 'pln-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "VerbrauchsausweisGewerbe" ALTER COLUMN "uid" SET DEFAULT 'vag-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "VerbrauchsausweisWohnen" ALTER COLUMN "uid" SET DEFAULT 'vaw-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "benutzer" ALTER COLUMN "uid" SET DEFAULT 'usr-' || gen_random_uuid(); diff --git a/prisma/migrations/20250312210347_/migration.sql b/prisma/migrations/20250312210347_/migration.sql new file mode 100644 index 00000000..ffcf3ff6 --- /dev/null +++ b/prisma/migrations/20250312210347_/migration.sql @@ -0,0 +1,62 @@ +/* + Warnings: + + - The values [GEGNachweisBedarfsausweis] on the enum `Ausweisart` will be removed. If these variants are still used in the database, this will fail. + +*/ +-- AlterEnum +BEGIN; +CREATE TYPE "Ausweisart_new" AS ENUM ('VerbrauchsausweisWohnen', 'VerbrauchsausweisGewerbe', 'BedarfsausweisWohnen', 'BedarfsausweisGewerbe', 'GEGNachweisWohnen', 'GEGNachweisGewerbe'); +ALTER TABLE "Aufnahme" ALTER COLUMN "ausweisart" TYPE "Ausweisart_new" USING ("ausweisart"::text::"Ausweisart_new"); +ALTER TYPE "Ausweisart" RENAME TO "Ausweisart_old"; +ALTER TYPE "Ausweisart_new" RENAME TO "Ausweisart"; +DROP TYPE "Ausweisart_old"; +COMMIT; + +-- AlterTable +ALTER TABLE "Anteilshaber" ALTER COLUMN "uid" SET DEFAULT 'ant-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Aufnahme" ALTER COLUMN "uid" SET DEFAULT 'auf-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "BedarfsausweisGewerbe" ALTER COLUMN "uid" SET DEFAULT 'bag-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "BedarfsausweisWohnen" ALTER COLUMN "uid" SET DEFAULT 'baw-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Bild" ALTER COLUMN "uid" SET DEFAULT 'img-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Event" ALTER COLUMN "uid" SET DEFAULT 'evt-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "GEGEinpreisung" ALTER COLUMN "uid" SET DEFAULT 'gge-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "GEGNachweisGewerbe" ALTER COLUMN "uid" SET DEFAULT 'gng-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "GEGNachweisWohnen" ALTER COLUMN "uid" SET DEFAULT 'gnw-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Objekt" ALTER COLUMN "uid" SET DEFAULT 'obj-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Rechnung" ALTER COLUMN "uid" SET DEFAULT 'inv-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Tickets" ALTER COLUMN "uid" SET DEFAULT 'tkt-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "Unterlage" ALTER COLUMN "uid" SET DEFAULT 'pln-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "VerbrauchsausweisGewerbe" ALTER COLUMN "uid" SET DEFAULT 'vag-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "VerbrauchsausweisWohnen" ALTER COLUMN "uid" SET DEFAULT 'vaw-' || gen_random_uuid(); + +-- AlterTable +ALTER TABLE "benutzer" ALTER COLUMN "uid" SET DEFAULT 'usr-' || gen_random_uuid(); diff --git a/prisma/schema/BedarfsausweisGewerbe.prisma b/prisma/schema/BedarfsausweisGewerbe.prisma index 084827e4..f904331e 100644 --- a/prisma/schema/BedarfsausweisGewerbe.prisma +++ b/prisma/schema/BedarfsausweisGewerbe.prisma @@ -1,16 +1,39 @@ model BedarfsausweisGewerbe { - id Int @id @default(autoincrement()) + id Int @id @default(autoincrement()) uid String @unique @default(dbgenerated("'bag-' || gen_random_uuid()")) - /// @zod.describe("Die ID des Benutzers, welchem dieser Ausweis gehört") + /// @zod.describe("Ausstellgrund wie z.B. Vermietung oder Verkauf") + ausstellgrund Ausstellgrund? + /// @zod.describe("Falls der Keller des Gebäudes beheizt wird, sollte dieser Wert auf true stehen") + keller_beheizt Boolean? + + /// @zod.describe("Falls die Nachweisanfrage storniert wurde, sollte dieser Wert auf true stehen") + storniert Boolean? @default(false) + /// @zod.describe("Falls der Nachweis bestellt wurde, sollte dieser Wert auf true stehen") + bestellt Boolean? @default(false) + /// @zod.describe("Falls der Nachweis vom Aussteller zurückgestellt wurde, sollte dieser Wert auf true stehen") + zurueckgestellt Boolean? @default(false) + + abluftanlage Boolean? @default(false) + zu_abluftanlage Boolean? @default(false) + konditionierung_der_zuluft Boolean? @default(false) + luftheizung Boolean? @default(false) + hallenheizung Boolean? @default(false) + dunkelstrahler Boolean? @default(false) + direktheizung Boolean? @default(false) + infrarotstrahler Boolean? @default(false) + fussbodenheizung Boolean? @default(false) + bauteilaktivierung Boolean? @default(false) + klimatisierung Boolean? @default(false) + + /// @zod.describe("Die ID des Benutzers, welchem dieser Ausweis gehört") benutzer_id Int? benutzer Benutzer? @relation(fields: [benutzer_id], references: [id], onDelete: NoAction, onUpdate: NoAction) - aufnahme_id Int @unique + aufnahme_id Int @unique aufnahme Aufnahme @relation(fields: [aufnahme_id], references: [id], onDelete: NoAction, onUpdate: NoAction) - rechnung_id Int? @unique + rechnung_id Int? @unique rechnung Rechnung? @relation(fields: [rechnung_id], references: [id], onDelete: NoAction, onUpdate: NoAction) - geg_einpreisung_id Int? @unique geg_einpreisung GEGEinpreisung? @relation(fields: [geg_einpreisung_id], references: [id], onDelete: NoAction, onUpdate: NoAction) } \ No newline at end of file diff --git a/prisma/schema/Bild.prisma b/prisma/schema/Bild.prisma index c1910716..9d248380 100644 --- a/prisma/schema/Bild.prisma +++ b/prisma/schema/Bild.prisma @@ -4,6 +4,7 @@ enum BilderKategorie { Fenster Gebaeude Daemmung + AnlagenTechnik } model Bild { diff --git a/prisma/schema/GEGNachweisGewerbe.prisma b/prisma/schema/GEGNachweisGewerbe.prisma index cdcb9bdf..19a2d401 100644 --- a/prisma/schema/GEGNachweisGewerbe.prisma +++ b/prisma/schema/GEGNachweisGewerbe.prisma @@ -23,7 +23,7 @@ model GEGNachweisGewerbe { aufnahme_id Int @unique aufnahme Aufnahme @relation(fields: [aufnahme_id], references: [id], onDelete: NoAction, onUpdate: NoAction) - rechnung_id Int? @unique + rechnung_id Int? @unique rechnung Rechnung? @relation(fields: [rechnung_id], references: [id], onDelete: NoAction, onUpdate: NoAction) geg_einpreisung_id Int? @unique geg_einpreisung GEGEinpreisung? @relation(fields: [geg_einpreisung_id], references: [id], onDelete: NoAction, onUpdate: NoAction) diff --git a/prisma/schema/schema.prisma b/prisma/schema/schema.prisma index c3b8885c..1b46436d 100644 --- a/prisma/schema/schema.prisma +++ b/prisma/schema/schema.prisma @@ -53,7 +53,6 @@ enum Ausweisart { BedarfsausweisWohnen BedarfsausweisGewerbe GEGNachweisWohnen - GEGNachweisBedarfsausweis GEGNachweisGewerbe } diff --git a/src/astro-typesafe-api-caller.ts b/src/astro-typesafe-api-caller.ts index 38206f31..96865d20 100644 --- a/src/astro-typesafe-api-caller.ts +++ b/src/astro-typesafe-api-caller.ts @@ -5,7 +5,6 @@ export const createCaller = createCallerFactory({ "klimafaktoren": await import("../src/pages/api/klimafaktoren.ts"), "postleitzahlen": await import("../src/pages/api/postleitzahlen.ts"), "unterlage": await import("../src/pages/api/unterlage.ts"), - "aufnahme": await import("../src/pages/api/aufnahme/index.ts"), "admin/ausstellen": await import("../src/pages/api/admin/ausstellen.ts"), "admin/bestellbestaetigung": await import("../src/pages/api/admin/bestellbestaetigung.ts"), "admin/erinnern": await import("../src/pages/api/admin/erinnern.ts"), @@ -13,13 +12,15 @@ export const createCaller = createCallerFactory({ "admin/post-ausstellen": await import("../src/pages/api/admin/post-ausstellen.ts"), "admin/registriernummer": await import("../src/pages/api/admin/registriernummer.ts"), "admin/stornieren": await import("../src/pages/api/admin/stornieren.ts"), + "ausweise": await import("../src/pages/api/ausweise/index.ts"), + "aufnahme": await import("../src/pages/api/aufnahme/index.ts"), "auth/access-token": await import("../src/pages/api/auth/access-token.ts"), "auth/passwort-vergessen": await import("../src/pages/api/auth/passwort-vergessen.ts"), "auth/refresh-token": await import("../src/pages/api/auth/refresh-token.ts"), - "ausweise": await import("../src/pages/api/ausweise/index.ts"), + "bedarfsausweis-gewerbe/[uid]": await import("../src/pages/api/bedarfsausweis-gewerbe/[uid].ts"), + "bedarfsausweis-gewerbe": await import("../src/pages/api/bedarfsausweis-gewerbe/index.ts"), "bedarfsausweis-wohnen/[uid]": await import("../src/pages/api/bedarfsausweis-wohnen/[uid].ts"), "bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"), - "aufnahme": await import("../src/pages/api/aufnahme/index.ts"), "bilder/[uid]": await import("../src/pages/api/bilder/[uid].ts"), "geg-nachweis-gewerbe/[uid]": await import("../src/pages/api/geg-nachweis-gewerbe/[uid].ts"), "geg-nachweis-gewerbe": await import("../src/pages/api/geg-nachweis-gewerbe/index.ts"), @@ -30,12 +31,12 @@ export const createCaller = createCallerFactory({ "rechnung/anfordern": await import("../src/pages/api/rechnung/anfordern.ts"), "rechnung": await import("../src/pages/api/rechnung/index.ts"), "ticket": await import("../src/pages/api/ticket/index.ts"), + "verbrauchsausweis-gewerbe/[uid]": await import("../src/pages/api/verbrauchsausweis-gewerbe/[uid].ts"), + "verbrauchsausweis-gewerbe": await import("../src/pages/api/verbrauchsausweis-gewerbe/index.ts"), "user": await import("../src/pages/api/user/index.ts"), "user/self": await import("../src/pages/api/user/self.ts"), "verbrauchsausweis-wohnen/[uid]": await import("../src/pages/api/verbrauchsausweis-wohnen/[uid].ts"), "verbrauchsausweis-wohnen": await import("../src/pages/api/verbrauchsausweis-wohnen/index.ts"), - "verbrauchsausweis-gewerbe/[uid]": await import("../src/pages/api/verbrauchsausweis-gewerbe/[uid].ts"), - "verbrauchsausweis-gewerbe": await import("../src/pages/api/verbrauchsausweis-gewerbe/index.ts"), "webhooks/mollie": await import("../src/pages/api/webhooks/mollie.ts"), "aufnahme/[uid]/bilder": await import("../src/pages/api/aufnahme/[uid]/bilder.ts"), "aufnahme/[uid]": await import("../src/pages/api/aufnahme/[uid]/index.ts"), diff --git a/src/client/lib/helpers.ts b/src/client/lib/helpers.ts index 8017ff52..66dcc00e 100644 --- a/src/client/lib/helpers.ts +++ b/src/client/lib/helpers.ts @@ -58,9 +58,4 @@ export function getZodBaseType(schema: ZodType): ZodType { return getZodBaseType(schema._def.schema) } return schema; -} - -export const sqids = new Sqids({ - alphabet: "0123456789abcdefghijklmnopqrstuvw", - minLength: 8 - }) \ No newline at end of file +} \ No newline at end of file diff --git a/src/client/lib/nachweisSpeichern.ts b/src/client/lib/nachweisSpeichern.ts index 082383bf..d0ec3ca0 100644 --- a/src/client/lib/nachweisSpeichern.ts +++ b/src/client/lib/nachweisSpeichern.ts @@ -184,6 +184,9 @@ export async function nachweisSpeichern( } else if (ausweisart === Enums.Ausweisart.GEGNachweisGewerbe) { patchRoute = api["geg-nachweis-gewerbe"]._uid.PATCH putRoute = api["geg-nachweis-gewerbe"].PUT + } else if (ausweisart === Enums.Ausweisart.BedarfsausweisGewerbe) { + patchRoute = api["bedarfsausweis-gewerbe"]._uid.PATCH + putRoute = api["bedarfsausweis-gewerbe"].PUT } if (nachweis.uid) { diff --git a/src/components/Ausweis/AnlagenTechnik.svelte b/src/components/Ausweis/AnlagenTechnik.svelte new file mode 100644 index 00000000..757f9cc2 --- /dev/null +++ b/src/components/Ausweis/AnlagenTechnik.svelte @@ -0,0 +1,110 @@ + + +
+ + + + + + + + + + + +
+ + + diff --git a/src/components/Ausweis/AnlagenTechnikImage.svelte b/src/components/Ausweis/AnlagenTechnikImage.svelte new file mode 100644 index 00000000..a61fdaa9 --- /dev/null +++ b/src/components/Ausweis/AnlagenTechnikImage.svelte @@ -0,0 +1,39 @@ + + +
+ +
+ + +
+ WICHTIG: + Bild Upload - Anlagentechnik +
+
+ +
+
+ Diese Bilder erscheinen nicht auf Ihrem + Energieausweis!
+
+ + TEXT FEHLT + +
+
diff --git a/src/components/Ausweis/ButtonWeiterHilfe.svelte b/src/components/Ausweis/ButtonWeiterHilfe.svelte index 635c412e..42dff87e 100644 --- a/src/components/Ausweis/ButtonWeiterHilfe.svelte +++ b/src/components/Ausweis/ButtonWeiterHilfe.svelte @@ -70,7 +70,7 @@ loginOverlayHidden = true let result: Awaited> | Awaited> | null = null; - if (ausweisart === Enums.Ausweisart.GEGNachweisWohnen || ausweisart === Enums.Ausweisart.GEGNachweisGewerbe || ausweisart === Enums.Ausweisart.GEGNachweisBedarfsausweis) { + if (ausweisart === Enums.Ausweisart.GEGNachweisWohnen || ausweisart === Enums.Ausweisart.GEGNachweisGewerbe || ausweisart === Enums.Ausweisart.BedarfsausweisGewerbe) { result = await nachweisSpeichern(ausweis, objekt, aufnahme, bilder, unterlagen, ausweisart) } else { result = await ausweisSpeichern(ausweis, objekt, aufnahme, bilder, ausweisart) diff --git a/src/components/Ausweis/DaemmungImage.svelte b/src/components/Ausweis/DaemmungImage.svelte index 9b79ec51..76c74a04 100644 --- a/src/components/Ausweis/DaemmungImage.svelte +++ b/src/components/Ausweis/DaemmungImage.svelte @@ -1,6 +1,6 @@ + +
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
+
+
Pläne
+ +
+ Hier können sie Grundrisspläne, Ansichtspläne und + Schnitte hochladen. Die Dateien können entweder im PDF + Format oder als Bild hochgeladen werden. +
+
+ +
+
+ Bitte laden Sie hier mind. 1 Dokument hoch: +
+ +
+
+
+
+
Unterlagen
+ +
+ Hier können sie weitere Unterlagen wie z.B. + Baugenehmigungen, U-Wert Berechnungen, Anlagentechnik + oder ihren alten Energieausweis hochladen. Die Dateien + können entweder im PDF Format oder als Bild hochgeladen + werden. +
+
+ +
+ +
+
+
+
+ + +
diff --git a/src/pages/angebot-anfragen/bedarfsausweis-gewerbe-anfragen/index.astro b/src/pages/angebot-anfragen/bedarfsausweis-gewerbe-anfragen/index.astro index d2fcab26..68d56348 100644 --- a/src/pages/angebot-anfragen/bedarfsausweis-gewerbe-anfragen/index.astro +++ b/src/pages/angebot-anfragen/bedarfsausweis-gewerbe-anfragen/index.astro @@ -1 +1,90 @@ -bedarfsausweis Gewerbe anfragen \ No newline at end of file +--- +import AusweisLayout from "#layouts/AusweisLayoutDaten.astro"; +import { AufnahmeClient, BildClient, GEGNachweisWohnenClient, ObjektClient, UnterlageClient } from "#components/Ausweis/types"; +import { createCaller } from "src/astro-typesafe-api-caller"; +import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js"; +import { validateAccessTokenServer } from "#server/lib/validateAccessToken.js"; +import BedarfsausweisGewerbeModule from "#modules/angebot-anfragen/BedarfsausweisGewerbeModule.svelte"; + +const uid = Astro.url.searchParams.get("uid"); +let nachweis: GEGNachweisWohnenClient = {} as GEGNachweisWohnenClient; +let aufnahme: AufnahmeClient = {} as AufnahmeClient; +let objekt: ObjektClient = {} as ObjektClient; +let bilder: BildClient[] = [] +let unterlagen: UnterlageClient[] = [] + +const valid = validateAccessTokenServer(Astro); + +const caller = createCaller(Astro); + +if (uid) { + if (!valid) { + return Astro.redirect( + `/auth/login?redirect=${Astro.url.toString()}` + ); + } + + try { + nachweis = await caller["bedarfsausweis-gewerbe"]._uid.GET.fetch(null, { + headers: { + authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}` + }, + params: { + uid + } + }); + + aufnahme = await caller.aufnahme._uid.GET.fetch(null, { + headers: { + authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}` + }, + params: { + uid: nachweis.uid_aufnahme + } + }) + + objekt = await caller.objekt._uid.GET.fetch(null, { + headers: { + authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}` + }, + params: { + uid: nachweis.uid_objekt + } + }) + + bilder = await caller.aufnahme._uid.bilder.GET.fetch(null, { + headers: { + authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}` + }, + params: { + uid: nachweis.uid_aufnahme + } + }) + + unterlagen = await caller.aufnahme._uid.unterlagen.GET.fetch(null, { + headers: { + authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}` + }, + params: { + uid: nachweis.uid_aufnahme + } + }) + + if (!nachweis) { + // Der Ausweis scheint nicht zu existieren. + // Wir leiten auf die generische Ausweisseite ohne UID weiter. + return Astro.redirect( + "/angebot-anfragen/bedarfsausweis-gewerbe-anfragen" + ); + } + } catch(e) { + return Astro.redirect( + "/angebot-anfragen/bedarfsausweis-gewerbe-anfragen" + ); + } +} +--- + + + + diff --git a/src/pages/api/bedarfsausweis-gewerbe/[uid].ts b/src/pages/api/bedarfsausweis-gewerbe/[uid].ts new file mode 100644 index 00000000..526312af --- /dev/null +++ b/src/pages/api/bedarfsausweis-gewerbe/[uid].ts @@ -0,0 +1,212 @@ +import { GEGNachweisWohnenClient, OptionalNullable, UUidWithPrefix, ZodOverlap } from "#components/Ausweis/types.js"; +import { exclude } from "#lib/exclude.js"; +import { authorizationHeaders, authorizationMiddleware } from "#lib/middleware/authorization.js"; +import { prisma } from "#lib/server/prisma.js"; +import { APIError, defineApiRoute } from "astro-typesafe-api/server"; +import { BedarfsausweisGewerbeSchema } from "src/generated/zod/bedarfsausweisgewerbe.js"; +import { z } from "zod"; + +export const PATCH = defineApiRoute({ + input: BedarfsausweisGewerbeSchema.omit({ + uid: true, + id: true, + benutzer_id: true, + geg_einpreisung_id: true, + aufnahme_id: true, + }), + output: z.void(), + headers: { + "Authorization": z.string() + }, + middleware: authorizationMiddleware, + async fetch(input, ctx, user) { + const objekt = await prisma.bedarfsausweisGewerbe.findUnique({ + where: { + uid: ctx.params.uid, + benutzer: { + id: user.id + } + } + }) + + if (!objekt) { + throw new APIError({ + code: "NOT_FOUND", + message: "Nachweis konnte nicht gefunden werden oder gehört einem anderen Benutzer." + }) + } + + await prisma.bedarfsausweisGewerbe.update({ + where: { + uid: ctx.params.uid + }, + data: input + }) + }, +}) + +export const DELETE = defineApiRoute({ + meta: { + description: "Storniert einen Nachweis" + }, + headers: authorizationHeaders, + middleware: authorizationMiddleware, + async fetch(input, ctx, user) { + const { uid } = ctx.params; + + if (!UUidWithPrefix.safeParse(uid).success) { + throw new APIError({ + code: "BAD_REQUEST", + message: "UID konnte nicht verifiziert werden." + }) + } + + // Wir holen uns den BedarfsNachweis + // Dieser MUSS mit dem Nutzer verknüpft sein. + const nachweis = await prisma.bedarfsausweisGewerbe.findUnique({ + where: { + uid, + } + }); + + if (!nachweis) { + // Falls wir den Nachweis nicht finden können, werfen wir einen Fehler + throw new APIError({ + code: "NOT_FOUND", + message: "Nachweis konnte nicht gefunden werden.", + }); + } + + // Wir dürfen den Nachweis nur stornieren, wenn er noch nicht ausgestellt wurde + // Außerdem müssen wir schauen, ob wir Admin oder der Besitzer des Nachweises sind. + if ((nachweis.benutzer_id !== user.id) && user.rolle !== "ADMIN") { + // Falls der Nachweis nicht dem Nutzer gehört, werfen wir einen Fehler + throw new APIError({ + code: "FORBIDDEN", + message: "Nachweis gehört nicht dem Nutzer.", + }); + } + + // if (Nachweis.erledigt) { + // // Falls der Nachweis bereits ausgestellt wurde, werfen wir einen Fehler + // throw new TRPCError({ + // code: "BAD_REQUEST", + // message: "Nachweis wurde bereits ausgestellt.", + // }); + // } + + if (nachweis.storniert) { + // Falls der Nachweis bereits storniert ist, werfen wir einen Fehler + throw new APIError({ + code: "BAD_REQUEST", + message: "Nachweis wurde bereits storniert.", + }); + } + + await prisma.gEGNachweisWohnen.update({ + where: { + id: nachweis.id + }, + data: { + storniert: true + } + }) + + // Wir erstellen ein Event, dass der Nachweis storniert wurde + // Dann können wir das in der Historie anzeigen + await prisma.event.create({ + data: { + title: "Nachweis storniert", + description: ((user.rolle === "ADMIN") && (nachweis.benutzer_id !== user.id)) ? "Nachweis wurde von einem Administrator storniert." : "Nachweis wurde vom Besitzer storniert.", + benutzer: { + connect: { + id: user.id + } + }, + aufnahme: { + connect: { + id: nachweis.aufnahme_id + } + } + } + }) + }, +}) + +export const GET = defineApiRoute({ + meta: { + description: "Gibt ein spezifisches Gebäude des Benutzers zurück.", + tags: ["Gebäude"], + headers: { + "Authorization": { + description: "Ein gültiger Authentifizierungstoken", + required: true, + allowEmptyValue: false, + examples: { + Bearer: { + value: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." + } + } + } + } + }, + output: BedarfsausweisGewerbeSchema.merge(z.object({ + uid_aufnahme: UUidWithPrefix, + uid_objekt: UUidWithPrefix, + uid_benutzer: UUidWithPrefix.optional() + })).omit({ + id: true, + aufnahme_id: true, + benutzer_id: true + }), + middleware: authorizationMiddleware, + async fetch(input, context, user) { + const { uid } = context.params; + + if (!uid) { + throw new APIError({ + code: "BAD_REQUEST", + message: "Missing uid in request params" + }) + } + + const nachweis = await prisma.bedarfsausweisGewerbe.findUnique({ + where: { + uid, + benutzer_id: user.id + }, + include: { + benutzer: { + select: { + uid: true + } + }, + aufnahme: { + select: { + uid: true, + objekt: { + select: { + uid: true + } + } + } + } + } + }); + + if (!nachweis) { + // Falls wir den Nachweis nicht finden können, werfen wir einen Fehler + throw new APIError({ + code: "NOT_FOUND", + message: "Nachweis konnte nicht gefunden werden.", + }); + } + + return { + uid_aufnahme: nachweis.aufnahme.uid, + uid_objekt: nachweis.aufnahme.objekt.uid, + uid_benutzer: nachweis.benutzer?.uid, + ...exclude(nachweis, ["id", "aufnahme_id", "benutzer_id", "aufnahme"]) + } + }, +}); diff --git a/src/pages/api/bedarfsausweis-gewerbe/index.ts b/src/pages/api/bedarfsausweis-gewerbe/index.ts new file mode 100644 index 00000000..367a3d4f --- /dev/null +++ b/src/pages/api/bedarfsausweis-gewerbe/index.ts @@ -0,0 +1,144 @@ +import { UUidWithPrefix } from "#components/Ausweis/types.js"; +import { authorizationHeaders, authorizationMiddleware } from "#lib/middleware/authorization.js"; +import { prisma } from "#lib/server/prisma.js"; +import { APIError, defineApiRoute } from "astro-typesafe-api/server"; +import { BedarfsausweisGewerbeSchema } from "src/generated/zod/bedarfsausweisgewerbe.js"; +import { z } from "zod"; + +export const PUT = defineApiRoute({ + meta: { + contentTypes: ["application/json"], + description: + "Erstellt einen neuen Bedarfsausweis Gewerbe.", + tags: ["GEG Nachweis", "Bedarfsausweis Gewerbe"], + }, + input: z.object({ + nachweis: BedarfsausweisGewerbeSchema.omit({ + id: true, + benutzer_id: true, + uid: true, + aufnahme_id: true, + geg_einpreisung_id: true, + rechnung_id: true + }), + uid_aufnahme: UUidWithPrefix + }), + output: z.object({ + uid: UUidWithPrefix, + objekt_uid: UUidWithPrefix, + aufnahme_uid: UUidWithPrefix, + }), + headers: authorizationHeaders, + middleware: authorizationMiddleware, + async fetch(input, ctx, user) { + const aufnahme = await prisma.aufnahme.findUnique({ + where: { + uid: input.uid_aufnahme + } + }) + + if (!aufnahme || aufnahme.benutzer_id !== user.id) { + throw new APIError({ + code: "FORBIDDEN", + message: "Aufnahme konnte nicht gefunden werden oder gehört nicht zu diesem Benutzer." + }) + } + + const nachweis = await prisma.bedarfsausweisGewerbe.create({ + data: { + ...input.nachweis, + benutzer: { + connect: { + id: user.id, + }, + }, + aufnahme: { + connect: { + id: aufnahme.id, + }, + } + }, + select: { + uid: true, + aufnahme: { + select: { + uid: true, + objekt: { + select: { + uid: true, + }, + }, + }, + }, + }, + }); + + return { + uid: nachweis.uid, + objekt_uid: nachweis.aufnahme.objekt.uid, + aufnahme_uid: nachweis.aufnahme.uid, + }; + }, +}); + +export const GET = defineApiRoute({ + meta: { + description: "Gibt eine spezifische GEG Nachweis Anfrage des Benutzers zurück.", + tags: ["GEG Nachweis"], + headers: { + Authorization: { + description: "Ein gültiger Authentifizierungstoken", + required: true, + allowEmptyValue: false, + examples: { + Bearer: { + value: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + }, + }, + }, + }, + }, + headers: authorizationHeaders, + middleware: authorizationMiddleware, + async fetch(input, context, user) { + const { uid } = context.params; + + const nachweis = await prisma.bedarfsausweisGewerbe.findUnique({ + where: { + uid, + }, + include: { + benutzer: true, + aufnahme: { + include: { + events: { + include: { + benutzer: { + select: { + uid: true, + }, + }, + }, + orderBy: { + date: "asc", + }, + }, + }, + }, + }, + }); + + if ( + !nachweis || + (nachweis.benutzer_id !== null && nachweis.benutzer_id !== user.id) + ) { + // Falls wir den Ausweis nicht finden können, werfen wir einen Fehler + throw new APIError({ + code: "NOT_FOUND", + message: "GEG Nachweis konnte nicht gefunden werden.", + }); + } + + return nachweis; + }, +}); diff --git a/src/pages/api/rechnung/[uid].ts b/src/pages/api/rechnung/[uid].ts index 40c0f49c..dfd64b77 100644 --- a/src/pages/api/rechnung/[uid].ts +++ b/src/pages/api/rechnung/[uid].ts @@ -140,7 +140,7 @@ function getPaymentDescription(ausweisart: Enums.Ausweisart) { return "Verbrauchsausweis Gewerbegebäude" case "VerbrauchsausweisWohnen": return "Verbrauchsausweis Wohngebäude" - case "GEGNachweisBedarfsausweis": + case "BedarfsausweisGewerbe": case "GEGNachweisGewerbe": case "GEGNachweisWohnen": return "GEG Nachweis" diff --git a/src/pages/api/rechnung/anfordern.ts b/src/pages/api/rechnung/anfordern.ts index 21a50ce6..4ada44ff 100644 --- a/src/pages/api/rechnung/anfordern.ts +++ b/src/pages/api/rechnung/anfordern.ts @@ -35,6 +35,12 @@ export const PUT = defineApiRoute({ uid: input.nachweis_uid } }) + } else if (ausweisart === Enums.Ausweisart.BedarfsausweisGewerbe) { + nachweis = await prisma.bedarfsausweisGewerbe.findUnique({ + where: { + uid: input.nachweis_uid + } + }) } else { throw new APIError({ "code": "BAD_REQUEST", @@ -84,6 +90,23 @@ export const PUT = defineApiRoute({ } } }) + } else if (ausweisart === Enums.Ausweisart.BedarfsausweisGewerbe) { + einpreisung = await prisma.gEGEinpreisung.create({ + data: { + ...omit(input, ["nachweis_uid"]), + status: Enums.Einpreisungsstatus.open, + benutzer: { + connect: { + id: user.id + } + }, + bedarfsausweis_gewerbe: { + connect: { + uid: input.nachweis_uid + } + } + } + }) } await sendGEGAnforderungsMail(nachweis, user) diff --git a/src/server/lib/hash.ts b/src/server/lib/hash.ts new file mode 100644 index 00000000..3ec63504 --- /dev/null +++ b/src/server/lib/hash.ts @@ -0,0 +1,13 @@ +function murmurHash36(str: string) { + let h = 0xdeadbeef; + for (let i = 0; i < str.length; i++) { + h = Math.imul(h ^ str.charCodeAt(i), 2654435761); + } + return (h >>> 0).toString(36).toUpperCase().slice(0, 6); +} + +export function shortenUID(uid: string) { + const str = murmurHash36(uid); + const mid = Math.floor(str.length / 2); + return [str.slice(0, mid), str.slice(mid)].join("-"); +} diff --git a/src/types/fake-data.ts b/src/types/fake-data.ts index 77b9fa86..34f9171c 100644 --- a/src/types/fake-data.ts +++ b/src/types/fake-data.ts @@ -165,10 +165,32 @@ export function fakeAufnahmeComplete() { objekt_id: faker.number.int(), }; } +export function fakeBedarfsausweisGewerbe() { + return { + ausstellgrund: undefined, + keller_beheizt: undefined, + }; +} export function fakeBedarfsausweisGewerbeComplete() { return { id: faker.number.int({ max: 2147483647 }), uid: '[object Object]', + ausstellgrund: undefined, + keller_beheizt: undefined, + storniert: false, + bestellt: false, + zurueckgestellt: false, + abluftanlage: false, + zu_abluftanlage: false, + konditionierung_der_zuluft: false, + luftheizung: false, + hallenheizung: false, + dunkelstrahler: false, + direktheizung: false, + infrarotstrahler: false, + fussbodenheizung: false, + bauteilaktivierung: false, + klimatisierung: false, benutzer_id: undefined, aufnahme_id: faker.number.int(), rechnung_id: undefined, @@ -343,13 +365,13 @@ export function fakeBenutzerComplete() { } export function fakeBild() { return { - kategorie: faker.helpers.arrayElement([BilderKategorie.Heizung, BilderKategorie.Fenster, BilderKategorie.Gebaeude, BilderKategorie.Daemmung] as const), + kategorie: faker.helpers.arrayElement([BilderKategorie.Heizung, BilderKategorie.Fenster, BilderKategorie.Gebaeude, BilderKategorie.Daemmung, BilderKategorie.AnlagenTechnik] as const), }; } export function fakeBildComplete() { return { id: faker.number.int({ max: 2147483647 }), - kategorie: faker.helpers.arrayElement([BilderKategorie.Heizung, BilderKategorie.Fenster, BilderKategorie.Gebaeude, BilderKategorie.Daemmung] as const), + kategorie: faker.helpers.arrayElement([BilderKategorie.Heizung, BilderKategorie.Fenster, BilderKategorie.Gebaeude, BilderKategorie.Daemmung, BilderKategorie.AnlagenTechnik] as const), uid: '[object Object]', aufnahme_id: undefined, }; From 8964c9f533778343d520d11c542ec746897e64a7 Mon Sep 17 00:00:00 2001 From: Moritz Utcke Date: Wed, 12 Mar 2025 18:20:23 -0300 Subject: [PATCH 05/17] Redirect --- .../geg-nachweis-gewerbe-anfragen/index.astro | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/angebot-anfragen/geg-nachweis-gewerbe-anfragen/index.astro b/src/pages/angebot-anfragen/geg-nachweis-gewerbe-anfragen/index.astro index 071fac18..c607e198 100644 --- a/src/pages/angebot-anfragen/geg-nachweis-gewerbe-anfragen/index.astro +++ b/src/pages/angebot-anfragen/geg-nachweis-gewerbe-anfragen/index.astro @@ -74,17 +74,17 @@ if (uid) { // Der Ausweis scheint nicht zu existieren. // Wir leiten auf die generische Ausweisseite ohne UID weiter. return Astro.redirect( - "/angebot-anfragen/geg-nachweis-wohnen-anfragen" + "/angebot-anfragen/geg-nachweis-gewerbe-anfragen" ); } } catch(e) { return Astro.redirect( - "/angebot-anfragen/geg-nachweis-wohnen-anfragen" + "/angebot-anfragen/geg-nachweis-gewerbe-anfragen" ); } } --- - + From 2391629b36c7935a7710800a4da8c81372aeebd6 Mon Sep 17 00:00:00 2001 From: Moritz Utcke Date: Wed, 12 Mar 2025 19:56:01 -0300 Subject: [PATCH 06/17] ID ohne strich --- src/server/lib/hash.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/server/lib/hash.ts b/src/server/lib/hash.ts index 3ec63504..0065d087 100644 --- a/src/server/lib/hash.ts +++ b/src/server/lib/hash.ts @@ -7,7 +7,5 @@ function murmurHash36(str: string) { } export function shortenUID(uid: string) { - const str = murmurHash36(uid); - const mid = Math.floor(str.length / 2); - return [str.slice(0, mid), str.slice(mid)].join("-"); + return murmurHash36(uid); } From 2a47b8f4824547c0706cf8d3b6ef8fccfd182e84 Mon Sep 17 00:00:00 2001 From: Moritz Utcke Date: Thu, 13 Mar 2025 17:12:45 -0300 Subject: [PATCH 07/17] Email Betreff --- src/lib/server/mail/geg-bestellung.ts | 4 ++- src/lib/server/mail/helpers.ts | 32 +++++++++++++++++++ src/lib/server/mail/invoice.ts | 7 +++- src/lib/server/mail/payment-success.ts | 10 ++++-- src/pages/api/ausweise/index.ts | 14 +++++--- .../admin/ausweise-pruefen/index.astro | 2 +- 6 files changed, 59 insertions(+), 10 deletions(-) create mode 100644 src/lib/server/mail/helpers.ts diff --git a/src/lib/server/mail/geg-bestellung.ts b/src/lib/server/mail/geg-bestellung.ts index f6a710ed..342e04a0 100644 --- a/src/lib/server/mail/geg-bestellung.ts +++ b/src/lib/server/mail/geg-bestellung.ts @@ -3,6 +3,7 @@ import { Benutzer, GEGNachweisWohnen, } from "#lib/client/prisma.js"; +import { getPaymentSuccessSubject } from "./helpers.js"; export async function sendGEGBestellungsMail( nachweis: GEGNachweisWohnen, @@ -11,7 +12,8 @@ export async function sendGEGBestellungsMail( await transport.sendMail({ from: `"IBCornelsen" `, to: user.email, - subject: `Bestellbestätigung vom IBCornelsen (ID: ${nachweis.uid})`, + // subject: getPaymentSuccessSubject(nachweis, ), + // TODO cc: { address: user.email || "", name: user.name || "", diff --git a/src/lib/server/mail/helpers.ts b/src/lib/server/mail/helpers.ts new file mode 100644 index 00000000..89c8ee62 --- /dev/null +++ b/src/lib/server/mail/helpers.ts @@ -0,0 +1,32 @@ +import { shortenUID } from "#server/lib/hash.js"; +import { BedarfsausweisWohnen, Enums, Rechnung, VerbrauchsausweisGewerbe, VerbrauchsausweisWohnen } from "../prisma.js"; + +export function getPaymentSuccessSubject(ausweis: VerbrauchsausweisWohnen | VerbrauchsausweisGewerbe | BedarfsausweisWohnen, rechnung: Rechnung, ausweisart: Enums.Ausweisart) { + const id = shortenUID(ausweis.uid); + + let subject: string = ""; + if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) { + subject = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Wohnen (ID: ${id})` + if (rechnung.ausweistyp === Enums.AusweisTyp.Beratung) { + subject = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Wohnen mit Beratung (ID: ${id})` + } else if (rechnung.ausweistyp === Enums.AusweisTyp.Offline) { + subject = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Wohnen - offline Service (ID: ${id})` + } + } else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) { + subject = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Gewerbe (ID: ${id})` + if (rechnung.ausweistyp === Enums.AusweisTyp.Beratung) { + subject = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Gewerbe mit Beratung (ID: ${id})` + } else if (rechnung.ausweistyp === Enums.AusweisTyp.Offline) { + subject = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Gewerbe - offline Service (ID: ${id})` + } + } else if (ausweisart === Enums.Ausweisart.BedarfsausweisWohnen) { + subject = `Bestellbestätigung vom IB Cornelsen - Bedarfsausweis Wohnen (ID: ${id})` + if (rechnung.ausweistyp === Enums.AusweisTyp.Beratung) { + subject = `Bestellbestätigung vom IB Cornelsen - Bedarfsausweis Wohnen mit Beratung (ID: ${id})` + } else if (rechnung.ausweistyp === Enums.AusweisTyp.Offline) { + subject = `Bestellbestätigung vom IB Cornelsen - Bedarfsausweis Wohnen - offline Service (ID: ${id})` + } + } + + return subject; +} \ No newline at end of file diff --git a/src/lib/server/mail/invoice.ts b/src/lib/server/mail/invoice.ts index 0e387d3e..2ae0816a 100644 --- a/src/lib/server/mail/invoice.ts +++ b/src/lib/server/mail/invoice.ts @@ -11,6 +11,7 @@ import { prisma } from "#lib/server/prisma.js"; import { getAnsichtsausweis } from "../ausweis.js"; import Mail from "nodemailer/lib/mailer/index.js"; import { shortenUID } from "#server/lib/hash.js"; +import { getPaymentSuccessSubject } from "./helpers.js"; export async function sendInvoiceMail( ausweis: VerbrauchsausweisWohnen, @@ -33,6 +34,10 @@ export async function sendInvoiceMail( const ausweisart = getAusweisartFromUUID(ausweis.uid); + if (!ausweisart) { + return + } + const attachments: Mail.Attachment[] = []; const id = shortenUID(ausweis.uid) @@ -65,7 +70,7 @@ export async function sendInvoiceMail( attachments, from: `"IBCornelsen" `, to: user.email, - subject: `Bestellbestätigung vom IBCornelsen (ID: ${id})`, + subject: getPaymentSuccessSubject(ausweis, rechnung, ausweisart), cc: { address: rechnung.email || "", name: rechnung.empfaenger || "", diff --git a/src/lib/server/mail/payment-success.ts b/src/lib/server/mail/payment-success.ts index 8c106159..c039c9f4 100644 --- a/src/lib/server/mail/payment-success.ts +++ b/src/lib/server/mail/payment-success.ts @@ -10,6 +10,7 @@ import { prisma } from "#lib/server/prisma.js"; import { getAnsichtsausweis } from "../ausweis.js"; import Mail from "nodemailer/lib/mailer/index.js"; import { shortenUID } from "#server/lib/hash.js"; +import { getPaymentSuccessSubject } from "./helpers.js"; export async function sendPaymentSuccessMail( ausweis: VerbrauchsausweisWohnen, @@ -32,6 +33,11 @@ export async function sendPaymentSuccessMail( let info: string = ""; const ausweisart = getAusweisartFromUUID(ausweis.uid); + + if (!ausweisart) { + return; + } + const attachments: Mail.Attachment[] = []; const id = shortenUID(ausweis.uid) @@ -63,12 +69,12 @@ export async function sendPaymentSuccessMail( info = "Die Erstellung des Bedarfsausweises dauert momentan leider etwas länger. Bitte kontaktieren Sie uns in dringenden Fällen telefonisch (9 - 12 Uhr)."; } - + await transport.sendMail({ attachments, from: `"IBCornelsen" `, to: user.email, - subject: `Bestellbestätigung vom IBCornelsen (ID: ${id})`, + subject: getPaymentSuccessSubject(ausweis, rechnung, ausweisart), cc: { address: rechnung.email || "", name: rechnung.empfaenger || "", diff --git a/src/pages/api/ausweise/index.ts b/src/pages/api/ausweise/index.ts index 573adb25..e183b74b 100644 --- a/src/pages/api/ausweise/index.ts +++ b/src/pages/api/ausweise/index.ts @@ -2,7 +2,7 @@ import { AufnahmeClient, ObjektClient, UploadedGebaeudeBild, UUidWithPrefix, Ver import { filterAusweise } from "#lib/filters.js"; import { omit } from "#lib/helpers.js"; import { authorizationHeaders, authorizationMiddleware } from "#lib/middleware/authorization.js"; -import { Enums, prisma, VerbrauchsausweisWohnenSchema } from "#lib/server/prisma"; +import { Enums, prisma } from "#lib/server/prisma.js"; import { defineApiRoute } from "astro-typesafe-api/server"; import { z } from "zod"; @@ -15,12 +15,16 @@ export const GET = defineApiRoute({ skip: z.number().optional() }), async fetch(input, context, user) { + if (user.rolle !== Enums.BenutzerRolle.ADMIN) { + input.filters = input.filters || {} + input.filters["benutzer"] = { + uid: user.uid + } + } + const ausweise = await prisma.verbrauchsausweisWohnen.findMany({ where: { - ...input.filters, - benutzer: { - uid: user.uid - }, + ...input.filters }, include: { aufnahme: { diff --git a/src/pages/dashboard/admin/ausweise-pruefen/index.astro b/src/pages/dashboard/admin/ausweise-pruefen/index.astro index 4c3455a3..4eaa6708 100644 --- a/src/pages/dashboard/admin/ausweise-pruefen/index.astro +++ b/src/pages/dashboard/admin/ausweise-pruefen/index.astro @@ -1,3 +1,3 @@ --- -return Astro.redirect("/dashboard/admin/ausweise-pruefen/1") +return Astro.redirect("/dashboard/admin/ausweise-pruefen/1"); --- \ No newline at end of file From 9ad163a469a16258ef3ce79a194ed8858c30544f Mon Sep 17 00:00:00 2001 From: Moritz Utcke Date: Thu, 13 Mar 2025 17:19:13 -0300 Subject: [PATCH 08/17] Dashboard Ausweistyp --- dbml/schema.dbml | 737 ------------------ .../Dashboard/DashboardAusweis.svelte | 28 +- 2 files changed, 15 insertions(+), 750 deletions(-) delete mode 100644 dbml/schema.dbml diff --git a/dbml/schema.dbml b/dbml/schema.dbml deleted file mode 100644 index a7e5305a..00000000 --- a/dbml/schema.dbml +++ /dev/null @@ -1,737 +0,0 @@ -//// ------------------------------------------------------ -//// THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY) -//// ------------------------------------------------------ - -Project "IBCornelsen Database" { - database_type: 'PostgreSQL' - Note: '' -} - -Table Anteilshaber { - id Int [pk, increment] - benutzer_id Int [not null] - rolle String - privilegien BigInt - uid String [unique, not null] - benutzer benutzer [not null] - objekt_id Int [not null] - objekt Objekt [not null] -} - -Table ApiRequests { - id Int [pk, increment] - date DateTime [default: `now()`, not null] - ip String [not null] - method String [not null] - path String [not null] - status Int [not null] - responseTime Float [not null] - responseSize Int [not null] - userAgent String [not null] - user_id Int - user benutzer -} - -Table Aufnahme { - id Int [pk, increment] - uid String [unique, not null, note: '@zod.describe("UID der Gebäude Aufnahme")'] - benutzer_id Int - benutzer benutzer - ausweisart Ausweisart [note: '@zod.describe("Art des korrespondierenden Ausweises, wie z.B. VerbrauchsausweisWohnen")'] - gebaeudetyp String [note: '@zod.describe("Art des Gebäudes und seiner primären Nutzungsart")'] - gebaeudeteil String [note: '@zod.describe("Betrachteter Teil des Gebäudes, z.B. Gesamtgebäude, Wohnteil, Gewerbeteil")'] - baujahr_gebaeude Int[] [not null, note: '@zod.describe("Alle Jahre in denen das Gebäude konstruiert oder grundlegend verändert wurde")'] - baujahr_heizung Int[] [not null, note: '@zod.describe("Alle Jahre in denen die Heizung eingebaut oder grundlegend verändert wurde")'] - baujahr_klima Int[] [not null, note: '@zod.describe("Alle Jahre in denen die Klimaanlage eingebaut oder grundlegend verändert wurde")'] - einheiten Int [note: '@zod.describe("Anzahl der (Wohn)Einheiten im Gebäude")'] - flaeche Int [note: '@zod.describe("Wohnfläche bei Wohngebäuden, Nutzfläche bei Gewerbegebäuden")'] - nutzflaeche Int [note: '@zod.describe("(energetische) Nutzfläche des Gebäudes. Bei Gewerbegebäuden entspricht Sie der Nutzfläche")'] - saniert Boolean [note: '@zod.describe("Falls das Gebäude energetisch saniert ist, sollte dieser Wert auf true stehen")'] - keller Heizungsstatus [note: '@zod.describe("Ob ein Keller vorhanden, beheizt oder unbeheizt ist")'] - dachgeschoss Heizungsstatus [note: '@zod.describe("Ob ein Dachgeschoss vorhanden, beheizt oder unbeheizt ist")'] - lueftung Lueftungskonzept [note: '@zod.describe("Art der Gebäudelüftung")'] - kuehlung String [note: '@zod.describe("Art der Gebäudekühlung")'] - leerstand Int [note: '@zod.describe("Prozentualer Leerstand des Gebäudes in einem durchschnittlichen Jahr")'] - alternative_heizung Boolean [note: '@zod.describe("Falls der Heizungsverbrauch alternative Energieversorgungssysteme beinhaltet sollte dieser Wert auf true stehen")'] - alternative_warmwasser Boolean [note: '@zod.describe("Falls der Warmwasserverbrauch alternative Energieversorgungssysteme beinhaltet sollte dieser Wert auf true stehen")'] - alternative_lueftung Boolean [note: '@zod.describe("Falls die Lüftung alternative Energieversorgungssysteme beinhaltet sollte dieser Wert auf true stehen")'] - alternative_kuehlung Boolean [note: '@zod.describe("Falls die Kühlung alternative Energieversorgungssysteme beinhaltet sollte dieser Wert auf true stehen")'] - brennstoff_1 String [note: '@zod.describe("Genutzer Brennstoff der primären Energiequelle")'] - brennstoff_2 String [note: '@zod.describe("Genutzer Brennstoff der sekundären Energiequelle")'] - boxpruefung Boolean [default: false] - energieeffizienzklasse String [note: '@zod.describe("Die aus der Berechnung hervorgehende Energieeffizienzklasse des Gebäudes")'] - erstellungsdatum DateTime [default: `now()`, note: '@zod.describe("Datum an dem der Kunde den Ausweis erstellt hat")'] - ausstellungsdatum DateTime [note: '@zod.describe("Datum an dem der Aussteller den Ausweis ausgestellt hat")'] - zentralheizung Boolean [note: '@zod.describe("Falls das Gebäude über eine Zentralbeheizung verfügt, sollte dieser Wert auf true stehen")'] - solarsystem_warmwasser Boolean [note: '@zod.describe("Falls das Gebäude über ein Solarsystem für Warmwasser verfügt, sollte dieser Wert auf true stehen")'] - warmwasser_rohre_gedaemmt Boolean [note: '@zod.describe("Falls die Warmwasserrohre des Gebäudes gedämmt sind, sollte dieser Wert auf true stehen")'] - niedertemperatur_kessel Boolean [note: '@zod.describe("Falls das Gebäude über einen Niedertemperaturkessel verfügt, sollte dieser Wert auf true stehen")'] - brennwert_kessel Boolean [note: '@zod.describe("Falls das Gebäude über einen Brennwertkessel verfügt, sollte dieser Wert auf true stehen")'] - heizungsrohre_gedaemmt Boolean [note: '@zod.describe("Falls die Heizungsrohre des Gebäudes gedämmt sind, sollte dieser Wert auf true stehen")'] - standard_kessel Boolean - waermepumpe Boolean [note: '@zod.describe("Falls das Gebäude über eine Wärmepumpe verfügt, sollte dieser Wert auf true stehen")'] - raum_temperatur_regler Boolean [note: '@zod.describe("Falls das Gebäude über einen Raumtemperaturregler verfügt, sollte dieser Wert auf true stehen")'] - photovoltaik Boolean [note: '@zod.describe("Falls das Gebäude über eine Photovoltaikanlage verfügt, sollte dieser Wert auf true stehen")'] - durchlauf_erhitzer Boolean [note: '@zod.describe("Falls das Gebäude über einen Durchlauferhitzer verfügt, sollte dieser Wert auf true stehen")'] - einzelofen Boolean - zirkulation Boolean [note: '@zod.describe("Falls das Gebäude über eine Zirkulationspumpe verfügt, sollte dieser Wert auf true stehen")'] - einfach_verglasung Boolean [note: '@zod.describe("Falls die Fenster des Gebäudes einfach gedämmt sind, sollte dieser Wert auf true stehen")'] - dreifach_verglasung Boolean [note: '@zod.describe("Falls die Fenster des Gebäudes dreifach gedämmt sind, sollte dieser Wert auf true stehen")'] - fenster_teilweise_undicht Boolean [note: '@zod.describe("Falls die Fenster des Gebäudes teilweise undicht sind, sollte dieser Wert auf true stehen")'] - doppel_verglasung Boolean [note: '@zod.describe("Falls die Fenster des Gebäudes doppelt gedämmt sind, sollte dieser Wert auf true stehen")'] - fenster_dicht Boolean [note: '@zod.describe("Falls die Fenster des Gebäudes dicht sind, sollte dieser Wert auf true stehen")'] - rolllaeden_kaesten_gedaemmt Boolean [note: '@zod.describe("Falls das Gebäude über gedämmte Rolllädenkästen verfügt, sollte dieser Wert auf true stehen")'] - isolier_verglasung Boolean [note: '@zod.describe("Falls die Fenster des Gebäudes isolier Verglasung haben, sollte dieser Wert auf true stehen")'] - tueren_undicht Boolean [note: '@zod.describe("Falls die Türen des Gebäudes undicht sind, sollte dieser Wert auf true stehen")'] - tueren_dicht Boolean [note: '@zod.describe("Falls die Türen des Gebäudes dicht sind, sollte dieser Wert auf true stehen")'] - dachgeschoss_gedaemmt Boolean [note: '@zod.describe("Falls das Dachgeschoss des Gebäudes gedämmt ist, sollte dieser Wert auf true stehen")'] - keller_decke_gedaemmt Boolean [note: '@zod.describe("Falls die Kellerdecke des Gebäudes gedämmt ist, sollte dieser Wert auf true stehen")'] - keller_wand_gedaemmt Boolean [note: '@zod.describe("Falls die Kellerwände des Gebäudes gedämmt sind, sollte dieser Wert auf true stehen")'] - aussenwand_gedaemmt Boolean [note: '@zod.describe("Falls die Außenwände des Gebäudes gedämmt sind, sollte dieser Wert auf true stehen")'] - oberste_geschossdecke_gedaemmt Boolean [note: '@zod.describe("Falls die oberste Geschossdecke des Gebäudes gedämmt ist, sollte dieser Wert auf true stehen")'] - aussenwand_min_12cm_gedaemmt Boolean [note: '@zod.describe("Falls die Außenwände des Gebäudes mindestens 12cm gedämmt sind, sollte dieser Wert auf true stehen")'] - dachgeschoss_min_12cm_gedaemmt Boolean [note: '@zod.describe("Falls das Dachgeschoss des Gebäudes mindestens 12cm gedämmt ist, sollte dieser Wert auf true stehen")'] - oberste_geschossdecke_min_12cm_gedaemmt Boolean [note: '@zod.describe("Falls die oberste Geschossdecke des Gebäudes mindestens 12cm gedämmt ist, sollte dieser Wert auf true stehen")'] - events Event [not null] - bilder Bild [not null] - unterlagen Unterlage [not null] - bedarfsausweise_wohnen BedarfsausweisWohnen [not null] - verbrauchsausweise_gewerbe VerbrauchsausweisGewerbe [not null] - verbrauchsausweise_wohnen VerbrauchsausweisWohnen [not null] - geg_nachweise_wohnen GEGNachweisWohnen [not null] - geg_nachweise_gewerbe GEGNachweisGewerbe [not null] - bedarfsausweise_gewerbe BedarfsausweisGewerbe [not null] - objekt_id Int [not null] - objekt Objekt [not null] -} - -Table BedarfsausweisGewerbe { - id Int [pk, increment] - uid String [unique, not null] - ausstellgrund Ausstellgrund [note: '@zod.describe("Ausstellgrund wie z.B. Vermietung oder Verkauf")'] - keller_beheizt Boolean [note: '@zod.describe("Falls der Keller des Gebäudes beheizt wird, sollte dieser Wert auf true stehen")'] - storniert Boolean [default: false, note: '@zod.describe("Falls die Nachweisanfrage storniert wurde, sollte dieser Wert auf true stehen")'] - bestellt Boolean [default: false, note: '@zod.describe("Falls der Nachweis bestellt wurde, sollte dieser Wert auf true stehen")'] - zurueckgestellt Boolean [default: false, note: '@zod.describe("Falls der Nachweis vom Aussteller zurückgestellt wurde, sollte dieser Wert auf true stehen")'] - abluftanlage Boolean [default: false] - zu_abluftanlage Boolean [default: false] - konditionierung_der_zuluft Boolean [default: false] - luftheizung Boolean [default: false] - hallenheizung Boolean [default: false] - dunkelstrahler Boolean [default: false] - direktheizung Boolean [default: false] - infrarotstrahler Boolean [default: false] - fussbodenheizung Boolean [default: false] - bauteilaktivierung Boolean [default: false] - klimatisierung Boolean [default: false] - benutzer_id Int [note: '@zod.describe("Die ID des Benutzers, welchem dieser Ausweis gehört")'] - benutzer benutzer - aufnahme_id Int [unique, not null] - aufnahme Aufnahme [not null] - rechnung_id Int [unique] - rechnung Rechnung - geg_einpreisung_id Int [unique] - geg_einpreisung GEGEinpreisung -} - -Table BedarfsausweisWohnen { - id Int [pk, increment] - uid String [unique, not null] - benutzer_id Int - ausstellgrund Ausstellgrund - registriernummer String - alternative_heizung Boolean - alternative_warmwasser Boolean - alternative_lueftung Boolean - alternative_kuehlung Boolean - anzahl_vollgeschosse Int - geschosshoehe Float - anzahl_gauben Int - breite_gauben Float - masse_a Float - masse_b Float - masse_c Float - masse_d Float - masse_e Float - masse_f Float - fensterflaeche_so_sw Float - fensterflaeche_nw_no Float - aussenwandflaeche_unbeheizt Float - dachflaeche Float - deckenflaeche Float - dach_u_wert Float - decke_u_wert Float - aussenwand_flaeche Float - aussenwand_u_wert Float - fussboden_flaeche Float - fussboden_u_wert Float - volumen Float - dicht Boolean - fenster_flaeche_1 Float - fenster_art_1 Float - fenster_flaeche_2 Float - fenster_art_2 Float - dachfenster_flaeche Float - dachfenster_art Float - haustuer_flaeche Float - haustuer_art Float - dach_bauart String - decke_bauart String - dach_daemmung Float - decke_daemmung Float - aussenwand_daemmung Float - boden_daemmung Float - aussenwand_bauart String - boden_bauart String - warmwasser_verteilung String - warmwasser_speicherung String - warmwasser_erzeugung String - heizung_zentral Boolean - heizung_verteilung String - heizung_speicherung String - waerme_erzeugung_heizung String - anteil_zusatzheizung Float - kollektor_flaeche Float - ausgestellt Boolean [default: false] - storniert Boolean [default: false, note: '@zod.describe("Falls der Ausweis storniert wurde, sollte dieser Wert auf true stehen")'] - bestellt Boolean [default: false, note: '@zod.describe("Falls der Ausweis bestellt wurde, sollte dieser Wert auf true stehen")'] - zurueckgestellt Boolean [default: false, note: '@zod.describe("Falls der Ausweis vom Aussteller zurückgestellt wurde, sollte dieser Wert auf true stehen")'] - prueftext String [note: '@zod.describe("Durch den Kunden hinzugefügte Anmerkung zur Vorabprüfung")'] - beschreibung String - kontrolldatei_angefragt Boolean [default: false, note: '@zod.describe("Ob bei der Anfrage der Registriernummer eine Kontrolldatei angefragt wurde")'] - benutzer benutzer - rechnung_id Int [unique] - rechnung Rechnung - aufnahme_id Int [unique, not null, note: '@zod.describe("ID der korrespondierenden Gebäudeaufnahme")'] - aufnahme Aufnahme [not null] -} - -Table benutzer { - id Int [pk, increment] - uid String [unique, not null] - name String - vorname String - email String [unique, not null] - passwort String [not null] - profilbild String - plz String - ort String - adresse String - telefon String - anrede String - rolle BenutzerRolle [not null, default: 'USER'] - firma String - lex_office_id String - verified Boolean [not null, default: false] - BedarfsausweisWohnen BedarfsausweisWohnen [not null] - documenttemplates documenttemplates [not null] - objekte Objekt [not null] - rechnungen Rechnung [not null] - tokens tokens [not null] - VerbrauchsausweisGewerbe VerbrauchsausweisGewerbe [not null] - VerbrauchsausweisWohnen VerbrauchsausweisWohnen [not null] - ApiRequests ApiRequests [not null] - RefreshTokens RefreshTokens [not null] - aufnahmen Aufnahme [not null] - geg_einpreisungen GEGEinpreisung [not null] - geg_nachweise_gewerbe GEGNachweisGewerbe [not null] - geg_nachweise_wohnen GEGNachweisWohnen [not null] - bedarfsausweise_gewerbe BedarfsausweisGewerbe [not null] - ErstellteTickets Tickets [not null] - BearbeiteteTickets Tickets [not null] - events Event [not null] -} - -Table Bild { - id Int [pk, increment] - kategorie BilderKategorie [not null] - uid String [unique, not null] - aufnahme_id Int - aufnahme Aufnahme -} - -Table Event { - id Int [pk, increment] - uid String [unique, not null] - date DateTime [default: `now()`, not null] - title String [not null] - description String - aufnahme_id Int [not null] - aufnahme Aufnahme [not null] - benutzer_id Int - benutzer benutzer -} - -Table GEGEinpreisung { - id Int [pk, increment] - uid String [unique, not null] - empfaenger String - strasse String - plz String - ort String - zusatzzeile String - telefon String - email String - abweichende_versand_adresse Boolean [default: false] - versand_empfaenger String - versand_strasse String - versand_plz String - versand_ort String - versand_zusatzzeile String - status Einpreisungsstatus [not null] - geg_nachweis_wohnen GEGNachweisWohnen - geg_nachweis_gewerbe GEGNachweisGewerbe - bedarfsausweis_gewerbe BedarfsausweisGewerbe - benutzer_id Int [note: '@zod.describe("Die ID des Benutzers, der diese Einpreisung bekommt.")'] - benutzer benutzer -} - -Table GEGNachweisGewerbe { - id Int [pk, increment] - uid String [unique, not null] - ausstellgrund Ausstellgrund [note: '@zod.describe("Ausstellgrund wie z.B. Vermietung oder Verkauf")'] - keller_beheizt Boolean [note: '@zod.describe("Falls der Keller des Gebäudes beheizt wird, sollte dieser Wert auf true stehen")'] - storniert Boolean [default: false, note: '@zod.describe("Falls die Nachweisanfrage storniert wurde, sollte dieser Wert auf true stehen")'] - bestellt Boolean [default: false, note: '@zod.describe("Falls der Nachweis bestellt wurde, sollte dieser Wert auf true stehen")'] - zurueckgestellt Boolean [default: false, note: '@zod.describe("Falls der Nachweis vom Aussteller zurückgestellt wurde, sollte dieser Wert auf true stehen")'] - beschreibung String [note: '@zod.describe("Beschreibung des Bauvorhabens")'] - benutzer_id Int [note: '@zod.describe("Die ID des Benutzers, welchem dieser Ausweis gehört")'] - benutzer benutzer - aufnahme_id Int [unique, not null] - aufnahme Aufnahme [not null] - rechnung_id Int [unique] - rechnung Rechnung - geg_einpreisung_id Int [unique] - geg_einpreisung GEGEinpreisung -} - -Table GEGNachweisWohnen { - id Int [pk, increment] - uid String [unique, not null] - ausstellgrund Ausstellgrund [note: '@zod.describe("Ausstellgrund wie z.B. Vermietung oder Verkauf")'] - keller_beheizt Boolean [note: '@zod.describe("Falls der Keller des Gebäudes beheizt wird, sollte dieser Wert auf true stehen")'] - storniert Boolean [default: false, note: '@zod.describe("Falls die Nachweisanfrage storniert wurde, sollte dieser Wert auf true stehen")'] - bestellt Boolean [default: false, note: '@zod.describe("Falls der Nachweis bestellt wurde, sollte dieser Wert auf true stehen")'] - zurueckgestellt Boolean [default: false, note: '@zod.describe("Falls der Nachweis vom Aussteller zurückgestellt wurde, sollte dieser Wert auf true stehen")'] - beschreibung String [note: '@zod.describe("Beschreibung des Bauvorhabens")'] - benutzer_id Int [note: '@zod.describe("Die ID des Benutzers, welchem dieser Ausweis gehört")'] - benutzer benutzer - aufnahme_id Int [unique, not null] - aufnahme Aufnahme [not null] - rechnung_id Int [unique] - rechnung Rechnung - geg_einpreisung_id Int [unique] - geg_einpreisung GEGEinpreisung -} - -Table Klimafaktoren { - id Int [pk, increment] - plz String [not null] - month Int [not null] - year Int [not null] - klimafaktor Float [not null, default: 1] - - indexes { - (plz, month, year) [unique] - } -} - -Table Objekt { - id Int [pk, increment] - uid String [unique, not null] - benutzer_id Int - latitude Float - longitude Float - plz String [note: '@zod.describe("Postleitzahl des Gebäudes")'] - ort String [note: '@zod.describe("Ort des Gebäudes")'] - adresse String [note: '@zod.describe("Adresse (Straße und Hausnummer) des Gebäudes")'] - erstellungsdatum DateTime [default: `now()`] - benutzer benutzer - aufnahmen Aufnahme [not null] - anteilshaber Anteilshaber [not null] -} - -Table Postleitzahlen { - id Int [pk, increment] - plz String [not null] - stadt String [not null] - bundesland String [not null] - landkreis String [not null] - lat Float [not null] - lon Float [not null] -} - -Table Rechnung { - id Int [pk, increment] - uid String [unique, not null] - benutzer_id Int [not null] - empfaenger String - strasse String - plz String - ort String - zusatzzeile String - telefon String - email String - abweichende_versand_adresse Boolean [default: false] - versand_empfaenger String - versand_strasse String - versand_plz String - versand_ort String - versand_zusatzzeile String - bezahlmethode Bezahlmethoden [not null] - status Rechnungsstatus [not null] - services Service[] [not null] - ausweistyp AusweisTyp [not null, default: 'Standard'] - betrag Float [not null] - erstellt_am DateTime [default: `now()`, not null] - bezahlt_am DateTime - storniert_am DateTime - transaktions_referenz String [unique] - benutzer benutzer [not null] - verbrauchsausweis_wohnen VerbrauchsausweisWohnen - verbrauchsausweis_gewerbe VerbrauchsausweisGewerbe - bedarfsausweis_wohnen BedarfsausweisWohnen - bedarfsausweis_gewerbe BedarfsausweisGewerbe - geg_nachweis_gewerbe GEGNachweisGewerbe - geg_nachweis_wohnen GEGNachweisWohnen -} - -Table RefreshTokens { - id Int [pk, increment] - benutzer_id Int [not null] - token String [unique, not null] - ip String [not null] - expiry DateTime [not null] - user benutzer [not null] -} - -Table Tickets { - id Int [pk, increment] - uid String [unique, not null] - benutzer_id Int - created_at DateTime [default: `now()`, not null] - updated_at DateTime - deleted_at DateTime - status TicketStatus [not null, default: 'OFFEN'] - titel String [not null] - beschreibung String [not null] - metadata Json - email String [not null] - bearbeiter_id Int - prioritaet Int [default: 0] - benutzer benutzer - bearbeiter benutzer -} - -Table Unterlage { - id Int [pk, increment] - uid String [unique, not null] - name String - kategorie String - mime String - aufnahme_id Int - aufnahme Aufnahme -} - -Table VerbrauchsausweisGewerbe { - id Int [pk, increment] - uid String [unique, not null] - benutzer_id Int - ausstellgrund Ausstellgrund - registriernummer String - zusaetzliche_heizquelle Boolean - brennstoff_1 String - einheit_1 String - brennstoff_2 String - einheit_2 String - startdatum DateTime - verbrauch_1 Int - verbrauch_2 Int - verbrauch_3 Int - verbrauch_4 Int - verbrauch_5 Int - verbrauch_6 Int - strom_1 Int - strom_2 Int - strom_3 Int - stromverbrauch_enthaelt_heizung Boolean - stromverbrauch_enthaelt_warmwasser Boolean - stromverbrauch_enthaelt_lueftung Boolean - stromverbrauch_enthaelt_beleuchtung Boolean - stromverbrauch_enthaelt_kuehlung Boolean - stromverbrauch_enthaelt_sonstige String - kuehlung_enthalten Boolean - anteil_kuehlung_1 Float - anteil_kuehlung_2 Float - keller_beheizt Boolean - alternative_heizung Boolean - alternative_warmwasser Boolean - alternative_lueftung Boolean - alternative_kuehlung Boolean - warmwasser_enthalten Boolean - warmwasser_anteil_bekannt Boolean [note: '@zod.describe("Falls der Warmwasser Anteil am Verbrauch bekannt ist, sollte dieser Wert auf true stehen")'] - anteil_warmwasser_1 Float - anteil_warmwasser_2 Float - ausgestellt Boolean [default: false] - storniert Boolean [default: false, note: '@zod.describe("Falls der Ausweis storniert wurde, sollte dieser Wert auf true stehen")'] - bestellt Boolean [default: false, note: '@zod.describe("Falls der Ausweis bestellt wurde, sollte dieser Wert auf true stehen")'] - zurueckgestellt Boolean [default: false, note: '@zod.describe("Falls der Ausweis vom Aussteller zurückgestellt wurde, sollte dieser Wert auf true stehen")'] - prueftext String [note: '@zod.describe("Durch den Kunden hinzugefügte Anmerkung zur Vorabprüfung")'] - beschreibung String - kontrolldatei_angefragt Boolean [default: false, note: '@zod.describe("Ob bei der Anfrage der Registriernummer eine Kontrolldatei angefragt wurde")'] - created_at DateTime [default: `now()`, not null] - updated_at DateTime [not null] - benutzer benutzer - rechnung_id Int [unique] - rechnung Rechnung - aufnahme_id Int [unique, not null, note: '@zod.describe("ID der korrespondierenden Gebäudeaufnahme")'] - aufnahme Aufnahme [not null] -} - -Table VerbrauchsausweisWohnen { - id Int [pk, increment] - uid String [unique, not null, note: '@zod.describe("UID des Ausweises")'] - benutzer_id Int [note: '@zod.describe("Die ID des Benutzers, welchem dieser Ausweis gehört")'] - ausstellgrund Ausstellgrund [note: '@zod.describe("Ausstellgrund wie z.B. Vermietung oder Verkauf")'] - registriernummer String [note: '@zod.describe("Die Registriernummer des Ausweises")'] - zusaetzliche_heizquelle Boolean [note: '@zod.describe("Falls eine sekundäre Heizquelle existiert, sollte dieser Wert auf true stehen")'] - einheit_1 String [note: '@zod.describe("Einheit des Energieträgers der primären Heizquelle")'] - einheit_2 String [note: '@zod.describe("Einheit des Energieträgers der sekundären Heizquelle")'] - startdatum DateTime - verbrauch_1 Int [note: '@zod.describe("Energieverbrauch der primären Heizquelle im ersten der drei Verbrauchsjahre")'] - verbrauch_2 Int [note: '@zod.describe("Energieverbrauch der primären Heizquelle im zweiten der drei Verbrauchsjahre")'] - verbrauch_3 Int [note: '@zod.describe("Energieverbrauch der primären Heizquelle im letzten der drei Verbrauchsjahre")'] - verbrauch_4 Int [note: '@zod.describe("Energieverbrauch der sekund̈́ären Heizquelle im ersten der drei Verbrauchsjahre")'] - verbrauch_5 Int [note: '@zod.describe("Energieverbrauch der sekund̈́ären Heizquelle im zweiten der drei Verbrauchsjahre")'] - verbrauch_6 Int [note: '@zod.describe("Energieverbrauch der sekund̈́ären Heizquelle im letzten der drei Verbrauchsjahre")'] - warmwasser_enthalten Boolean [note: '@zod.describe("Falls Warmwasser im Verbrauchswert enthalten ist, sollte dieser Wert auf true stehen")'] - warmwasser_anteil_bekannt Boolean [note: '@zod.describe("Falls der Warmwasser Anteil am Verbrauch bekannt ist, sollte dieser Wert auf true stehen")'] - keller_beheizt Boolean [note: '@zod.describe("Falls der Keller des Gebäudes beheizt wird, sollte dieser Wert auf true stehen")'] - faktorKeller Float [note: '@zod.describe("Der Faktor mit dem die Wohnfläche erhöht wird wenn die beheizte Gesamtfläche (energetische Nutzfläche) unbekannt ist.")'] - alternative_heizung Boolean [note: '@zod.describe("Falls der Heizungsverbrauch alternative Energieversorgungssysteme beinhaltet, sollte dieser Wert auf true stehen.")'] - alternative_warmwasser Boolean [note: '@zod.describe("Falls der Warmwasserverbrauch alternative Energieversorgungssysteme (z.B. Solarsystem, Wärmepumpe, etc.) beinhaltet, sollte dieser Wert auf true stehen.")'] - alternative_lueftung Boolean [note: '@zod.describe("Falls die Lüftung alternative Energieversorgungssysteme beinhaltet sollte dieser Wert auf true stehen.")'] - alternative_kuehlung Boolean [note: '@zod.describe("Falls die Kühlung alternative Energieversorgungssysteme beinhaltet sollte dieser Wert auf true stehen.")'] - anteil_warmwasser_1 Float [note: '@zod.describe("Anteil des Warmwassers am Gesamtverbrauch der primären Energiequelle in Prozent")'] - anteil_warmwasser_2 Float [note: '@zod.describe("Anteil des Warmwassers am Gesamtverbrauch der sekundären Energiequelle in Prozent")'] - ausgestellt Boolean [default: false] - storniert Boolean [default: false, note: '@zod.describe("Falls der Ausweis storniert wurde, sollte dieser Wert auf true stehen")'] - bestellt Boolean [default: false, note: '@zod.describe("Falls der Ausweis bestellt wurde, sollte dieser Wert auf true stehen")'] - zurueckgestellt Boolean [default: false, note: '@zod.describe("Falls der Ausweis vom Aussteller zurückgestellt wurde, sollte dieser Wert auf true stehen")'] - prueftext String [note: '@zod.describe("Durch den Kunden hinzugefügte Anmerkung zur Vorabprüfung")'] - beschreibung String - kontrolldatei_angefragt Boolean [default: false, note: '@zod.describe("Ob bei der Anfrage der Registriernummer eine Kontrolldatei angefragt wurde")'] - created_at DateTime [default: `now()`, not null] - updated_at DateTime [not null] - benutzer benutzer - rechnung_id Int [unique] - rechnung Rechnung - aufnahme_id Int [unique, not null, note: '@zod.describe("ID der korrespondierenden Gebäudeaufnahme")'] - aufnahme Aufnahme [not null] -} - -Table documenttemplates { - id Int [pk, increment] - name String [not null] - shortdescription String [not null] - longdescription String [not null] - user_id Int [not null] - is_private Boolean [not null, default: true] - documenttype Int [not null] - filename String [not null] - created_at DateTime [default: `now()`, not null] - updated_at DateTime [default: `now()`, not null] - benutzer benutzer [not null] - documenttypes documenttypes [not null] -} - -Table documenttypes { - id Int [pk, increment] - name String [not null] - shortdescription String [not null] - longdescription String [not null] - documenttemplates documenttemplates [not null] -} - -Table tokens { - id Int [pk, increment] - token String [not null] - user_id Int [not null] - date_created DateTime [default: `now()`, not null] - last_used DateTime [default: `now()`, not null] - times_used Int [not null, default: 0] - permissions Int [not null, default: 0] - benutzer benutzer [not null] -} - -Enum Heizungsstatus { - BEHEIZT - UNBEHEIZT - NICHT_VORHANDEN -} - -Enum Lueftungskonzept { - Fensterlueftung - Schachtlueftung - LueftungsanlageMitWaermerueckgewinnung - LueftungsanlageOhneWaermerueckgewinnung -} - -Enum BenutzerRolle { - USER - ADMIN -} - -Enum BilderKategorie { - Heizung - Fenster - Gebaeude - Daemmung - AnlagenTechnik -} - -Enum Einpreisungsstatus { - open - canceled - pending - expired -} - -Enum Bezahlmethoden { - paypal - giropay - sofort - creditcard - rechnung -} - -Enum Rechnungsstatus { - open - canceled - pending - authorized - expired - failed - paid -} - -Enum AusweisTyp { - Standard - Beratung - Offline -} - -Enum TicketStatus { - OFFEN - IN_BEARBEITUNG - IN_WARTESCHLEIFE - GESCHLOSSEN - GELOEST -} - -Enum UnterlagenKategorie { - Grundriss - Sonstiges -} - -Enum Ausstellgrund { - Neubau - Vermietung - Verkauf - Modernisierung - Sonstiges -} - -Enum Ausweisart { - VerbrauchsausweisWohnen - VerbrauchsausweisGewerbe - BedarfsausweisWohnen - BedarfsausweisGewerbe - GEGNachweisWohnen - GEGNachweisGewerbe -} - -Enum Service { - Telefonberatung - Aushang - Qualitaetsdruck - SameDay -} - -Ref: Anteilshaber.benutzer_id - benutzer.id [delete: No Action] - -Ref: Anteilshaber.objekt_id > Objekt.id [delete: No Action] - -Ref: ApiRequests.user_id > benutzer.id [delete: No Action] - -Ref: Aufnahme.benutzer_id > benutzer.id [delete: No Action] - -Ref: Aufnahme.objekt_id > Objekt.id [delete: No Action] - -Ref: BedarfsausweisGewerbe.benutzer_id > benutzer.id [delete: No Action] - -Ref: BedarfsausweisGewerbe.aufnahme_id > Aufnahme.id [delete: No Action] - -Ref: BedarfsausweisGewerbe.rechnung_id - Rechnung.id [delete: No Action] - -Ref: BedarfsausweisGewerbe.geg_einpreisung_id - GEGEinpreisung.id [delete: No Action] - -Ref: BedarfsausweisWohnen.benutzer_id > benutzer.id [delete: No Action] - -Ref: BedarfsausweisWohnen.rechnung_id - Rechnung.id [delete: No Action] - -Ref: BedarfsausweisWohnen.aufnahme_id > Aufnahme.id [delete: No Action] - -Ref: Bild.aufnahme_id > Aufnahme.id [delete: No Action] - -Ref: Event.aufnahme_id > Aufnahme.id [delete: No Action] - -Ref: Event.benutzer_id > benutzer.id [delete: No Action] - -Ref: GEGEinpreisung.benutzer_id > benutzer.id [delete: No Action] - -Ref: GEGNachweisGewerbe.benutzer_id > benutzer.id [delete: No Action] - -Ref: GEGNachweisGewerbe.aufnahme_id > Aufnahme.id [delete: No Action] - -Ref: GEGNachweisGewerbe.rechnung_id - Rechnung.id [delete: No Action] - -Ref: GEGNachweisGewerbe.geg_einpreisung_id - GEGEinpreisung.id [delete: No Action] - -Ref: GEGNachweisWohnen.benutzer_id > benutzer.id [delete: No Action] - -Ref: GEGNachweisWohnen.aufnahme_id > Aufnahme.id [delete: No Action] - -Ref: GEGNachweisWohnen.rechnung_id - Rechnung.id [delete: No Action] - -Ref: GEGNachweisWohnen.geg_einpreisung_id - GEGEinpreisung.id [delete: No Action] - -Ref: Objekt.benutzer_id > benutzer.id - -Ref: Rechnung.benutzer_id > benutzer.id [delete: No Action] - -Ref: RefreshTokens.benutzer_id > benutzer.id [delete: Cascade] - -Ref: Tickets.benutzer_id > benutzer.id - -Ref: Tickets.bearbeiter_id > benutzer.id - -Ref: Unterlage.aufnahme_id > Aufnahme.id [delete: No Action] - -Ref: VerbrauchsausweisGewerbe.benutzer_id > benutzer.id [delete: No Action] - -Ref: VerbrauchsausweisGewerbe.rechnung_id - Rechnung.id [delete: No Action] - -Ref: VerbrauchsausweisGewerbe.aufnahme_id > Aufnahme.id [delete: No Action] - -Ref: VerbrauchsausweisWohnen.benutzer_id > benutzer.id [delete: No Action] - -Ref: VerbrauchsausweisWohnen.rechnung_id - Rechnung.id [delete: No Action] - -Ref: VerbrauchsausweisWohnen.aufnahme_id > Aufnahme.id [delete: No Action] - -Ref: documenttemplates.user_id > benutzer.id [delete: Cascade] - -Ref: documenttemplates.documenttype > documenttypes.id [delete: Cascade] - -Ref: tokens.user_id > benutzer.id [delete: No Action] \ No newline at end of file diff --git a/src/components/Dashboard/DashboardAusweis.svelte b/src/components/Dashboard/DashboardAusweis.svelte index 131ee9af..dbce697e 100644 --- a/src/components/Dashboard/DashboardAusweis.svelte +++ b/src/components/Dashboard/DashboardAusweis.svelte @@ -13,7 +13,7 @@ import { api } from "astro-typesafe-api/client"; import Cookies from "js-cookie"; import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js"; - import { Enums, Objekt } from "#lib/client/prisma.js"; + import { AusweisTyp, Enums, Objekt } from "#lib/client/prisma.js"; import { endEnergieVerbrauchVerbrauchsausweisGewerbe_2016 } from "#lib/Berechnungen/VerbrauchsausweisGewerbe/VerbrauchsausweisGewerbe_2016.js"; import { shortenUID } from "#server/lib/hash.js"; @@ -131,19 +131,21 @@
- {#if ausweisart == Enums.Ausweisart.VerbrauchsausweisWohnen} -
+
+ {#if ausweisart == Enums.Ausweisart.VerbrauchsausweisWohnen} Verbrauchsausweis Wohnen -
- {:else if ausweisart == Enums.Ausweisart.BedarfsausweisWohnen} -
- Bedarfsausweis Wohnen -
- {:else if ausweisart == Enums.Ausweisart.VerbrauchsausweisGewerbe} -
- Verbrauchsausweis Gewerbe -
- {/if} + {:else if ausweisart == Enums.Ausweisart.BedarfsausweisWohnen} + Bedarfsausweis Wohnen + {:else if ausweisart == Enums.Ausweisart.VerbrauchsausweisGewerbe} + Verbrauchsausweis Gewerbe + {/if} + + {#if rechnung.ausweistyp === Enums.AusweisTyp.Beratung} + (Beratung) + {:else if rechnung.ausweistyp === Enums.AusweisTyp.Offline} + (Offline) + {/if} +
{#if ausweis.ausgestellt} Ausgestellt From 4378f256423bf5179151edd7e986cc40f5f81cb7 Mon Sep 17 00:00:00 2001 From: Moritz Utcke Date: Thu, 13 Mar 2025 17:23:54 -0300 Subject: [PATCH 09/17] GEG Nachweis Wohnen Test --- .../e2e/GEGNachweisWohnen/erstellen.cy.ts | 125 ++++++++++++++++++ .../GEGNachweisWohnenModule.svelte | 3 +- 2 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 src/cypress/e2e/GEGNachweisWohnen/erstellen.cy.ts diff --git a/src/cypress/e2e/GEGNachweisWohnen/erstellen.cy.ts b/src/cypress/e2e/GEGNachweisWohnen/erstellen.cy.ts new file mode 100644 index 00000000..86f049f4 --- /dev/null +++ b/src/cypress/e2e/GEGNachweisWohnen/erstellen.cy.ts @@ -0,0 +1,125 @@ +import fuelList from "#components/Ausweis/brennstoffListe.js"; +import { faker } from "@faker-js/faker"; +import { Enums } from "#lib/client/prisma.js"; + + +import "cypress-file-upload" +import moment from "moment"; + +describe("Verbrauchsausweis erstellen Schritt 1", () => { + it("erstellt einen neuen Verbrauchsausweis Wohngebäude.", () => { + cy.visit("/angebot-anfragen/geg-nachweis-wohnen-anfragen"); + + cy.wait(2000); + + // Wir überprüfen, ob alle Ausstelgründe vorhanden sind, diese sollten genau so viele sein wie in der Datenbank vorhanden sind. + cy.get("select[data-cy='ausstellgrund']") + .select( + faker.number.int({ + min: 1, + max: [Enums.Ausstellgrund.Modernisierung, Enums.Ausstellgrund.Neubau].length - 1, + }) + ) + + // Gebäudetyp + cy.get("select[name='gebaeudetyp']").then(($dropdown) => { + const options = $dropdown.find('option'); + // Select the option at the random index + cy.get("select[name='gebaeudetyp']").select(options.eq(faker.number.int({ min: 1, max: options.length - 1 })).val() as string); + }); + + // Jetzt Füllen wir das Baujahr vom Gebäude aus. + cy.get("input[name='baujahr_gebaeude']") + .should("have.attr", "type", "number") + .type( + faker.number.int({ min: 1900, max: 2021 }).toString() + + "{enter}", + { delay: 50 } + ); + + // Jetzt Füllen wir das Baujahr der Heizung aus. + cy.get("input[name='baujahr_heizung']") + .should("have.attr", "type", "number") + .type( + faker.number.int({ min: 1900, max: 2021 }).toString() + + "{enter}", + { delay: 50 } + ); + + // Adresse + cy.get("input[name='adresse']").type(faker.location.streetAddress()); + + // Postleitzahl + cy.get("input[name='plz']").type( + faker.location.zipCode({ + format: "#####", + }) + ); + + // TODO: Ort - Dieser wird aus der Datenbank abgefragt, wir müssen also warten, bis der Dropdown da ist. + cy.get("[data-cy='plz-container']").find("button").first().click() + + // Nutzflaeche + cy.get("input[name='nutzflaeche']") + .should("have.attr", "type", "number") + .type(faker.number.int({ min: 50, max: 1000 }).toString()); + + // Keller + cy.get("select[name='keller']").find("option:not([disabled])").should("have.length", (["BEHEIZT", "NICHT_VORHANDEN", "UNBEHEIZT"] as Enums.Heizungsstatus[]).length).parent().select(faker.number.int({ + max: Object.values(Enums.Heizungsstatus).length, + min: 1 + })); + + // Dachgeschoss + cy.get("select[name='dachgeschoss']").find("option:not([disabled])").should("have.length", (["BEHEIZT", "NICHT_VORHANDEN", "UNBEHEIZT"] as Enums.Heizungsstatus[]).length).parent().select(faker.number.int({ + max: Object.values(Enums.Heizungsstatus).length, + min: 1 + })); + + cy.get("[data-cy='beschreibung']").type(faker.lorem.paragraphs({ min: 2, max: 10 })) + + // Wärmedämmung Bilder + cy.get("input[type='file'][name='plaene']").should("have.attr", "type", "file").attachFile("images/daemmung/1.jpeg", { subjectType: "input" }).attachFile("images/daemmung/2.jpeg", { subjectType: "input" }); + cy.get("input[type='file'][name='unterlagen']").should("have.attr", "type", "file").attachFile("images/gebaeude/1.jpeg", { subjectType: "input" }).attachFile("images/daemmung/2.jpeg", { subjectType: "input" }); + + // Jetzt können wir den Verbrauchsausweis erstellen. + cy.get("form[data-cy='nachweis'] button[data-cy='weiter']").click({ force: true }); + + cy.url().should("contain", "/kundendaten"); + + const email = faker.internet.email(); + const passwort = "test1234"; + const vorname = faker.person.firstName(); + const nachname = faker.person.lastName(); + const telefon = faker.phone.number() + + const strasse = faker.location.streetAddress({ useFullAddress: true }) + const plz = faker.location.zipCode("#####") + + cy.get("input[name='vorname']").should("have.attr", "type", "text").type(vorname); + cy.get("input[name='name']").should("have.attr", "type", "text").type(nachname); + cy.get("input[name='telefon']").should("have.attr", "type", "text").type(telefon); + // Rechnung + cy.get("input[name='rechnung_empfaenger']").should("have.attr", "type", "text").type(`${vorname} ${nachname}`); + cy.get("input[name='rechnung_strasse']").should("have.attr", "type", "text").type(strasse); + cy.get("input[name='rechnung_plz']").should("have.attr", "type", "text").type(plz); + cy.get("[data-cy='plz-container']").children().first().click() + cy.get("input[name='rechnung_email']").should("have.attr", "type", "email").type(email); + + cy.get("button[data-cy='bestellen']").click(); + + cy.get("a[data-cy='registrieren']").should("be.visible").click(); + + // Wir sind jetzt registriert und können uns nun einloggen. + // Die Email sollte automatisch eingetragen sein, da wir uns gerade registriert haben. + cy.get("form[name='signup'] input[name='vorname']").should("be.visible").should("have.attr", "type", "text").type(vorname); + cy.get("form[name='signup'] input[name='nachname']").should("be.visible").should("have.attr", "type", "text").type(nachname); + cy.get("form[name='signup'] input[name='email']").should("be.visible").should("have.attr", "type", "email").should("contain.value", email); + cy.get("form[name='signup'] input[name='passwort']").should("be.visible").should("have.attr", "type", "password").type(passwort); + + cy.get("form[name='signup'] button[type='submit']").click(); + cy.get("form[name='login'] button[type='submit']").click(); + + cy.url().should("contain", "/einpreisung/success") + }); +}); diff --git a/src/modules/angebot-anfragen/GEGNachweisWohnenModule.svelte b/src/modules/angebot-anfragen/GEGNachweisWohnenModule.svelte index 2d05d14e..882e5e24 100644 --- a/src/modules/angebot-anfragen/GEGNachweisWohnenModule.svelte +++ b/src/modules/angebot-anfragen/GEGNachweisWohnenModule.svelte @@ -113,7 +113,7 @@ />
-
+
@@ -144,6 +144,7 @@ From fc3f4b0e3e025cc7af0b2775726d553d9fe5a3fa Mon Sep 17 00:00:00 2001 From: Jens Cornelsen <79703163+IB-Cornelsen@users.noreply.github.com> Date: Thu, 13 Mar 2025 22:23:05 +0100 Subject: [PATCH 10/17] Korrektur E-Mail Text --- src/lib/server/mail/invoice.ts | 29 +++----------------------- src/lib/server/mail/payment-success.ts | 2 +- 2 files changed, 4 insertions(+), 27 deletions(-) diff --git a/src/lib/server/mail/invoice.ts b/src/lib/server/mail/invoice.ts index 2ae0816a..5dc869fd 100644 --- a/src/lib/server/mail/invoice.ts +++ b/src/lib/server/mail/invoice.ts @@ -78,40 +78,18 @@ export async function sendInvoiceMail( bcc: "info@online-energieausweis.org", html: `

Sehr geehrte*r ${user.vorname} ${user.name},

-

im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. Nachfolgend finden Sie unsere Bankverbindung. Bitte geben Sie als Verwendungszweck die Rechnungsnummer an (siehe unten). Vielen Dank.

- +

vielen Dank für Ihre Bestellung. Im Anhang finden Sie den Ansichtsausweis als PDF-Datei. Wir werden den Ausweis nun prüfen und Originalausweis und Rechnung nach Prüfung zuschicken.

+

In der Regel erhalten Sie Ihren Ausweis innerhalb von 24 Stunden. Die Ausstellung erfolgt nach aktuellem GEG und Ihr Ausweis wird beim DIBT registriert.


- - - - - - - -
Kreditinstitut:\t Commerzbank AG
Empfänger:\t IB Cornelsen
IBAN:\t DE81 2004 0000 0348 6008 00
BIC:\t COBADEFFXXX
Betrag:\t ${rechnung.betrag}€
Verwendungszweck:\t ${rechnung.id}
+

Ihre Zahlung konnte nicht durchgeführt werden. Sie erhalten Bankverbindung und Verwendungszweck zusammen mit der Rechnung, sobald ihr Ausweis ausgestellt wurde.


- -

- Alternativ können Sie auch direkt online zahlen indem Sie auf den entsprechenden Link klicken: -


- - - - - - - -
Per Einzuglastschrift zahlen : jetzt per ELV bezahlen
Per Sofortüberweisung zahlen : jetzt per Sofortüberweisung bezahlen
Über PayPal zahlen : jetzt per Paypal bezahlen
Per Giropay zahlen : jetzt per Giropay bezahlen
Per Visa oder MasterCard zahlen : jetzt per Kreditkarte bezahlen
-
-

Mit freundlichen Grüßen,
Dipl.-Ing. Jens Cornelsen

- IB Cornelsen
Katendeich 5A @@ -121,7 +99,6 @@ export async function sendInvoiceMail( www.online-energieausweis.org

- fon 040 · 209339850
fax 040 · 209339859 diff --git a/src/lib/server/mail/payment-success.ts b/src/lib/server/mail/payment-success.ts index c039c9f4..99a5929f 100644 --- a/src/lib/server/mail/payment-success.ts +++ b/src/lib/server/mail/payment-success.ts @@ -83,7 +83,7 @@ export async function sendPaymentSuccessMail( html: `

Sehr geehrte/r ${user.name},

- vielen Dank für ihre Bestellung. Wir werden Ihnen Originalausweis und Rechnung nach Prüfung zuschicken. ${info} Die Ausstellung erfolgt nach aktuellem GEG und Ihr Ausweis wird beim DIBT registriert.

+ vielen Dank für ihre Bestellung. Wir werden den Ausweis nun prüfen und Originalausweis und Rechnung nach Prüfung zuschicken. ${info} Die Ausstellung erfolgt nach aktuellem GEG und Ihr Ausweis wird beim DIBT registriert.

Den Rechnungsbetrag haben Sie bereits bezahlt. Vielen Dank.

Mit freundlichen Grüßen, From 4ecbeab1dae5caec8494b64d86d2545fe1fc1c04 Mon Sep 17 00:00:00 2001 From: Moritz Utcke Date: Thu, 13 Mar 2025 18:37:27 -0300 Subject: [PATCH 11/17] Verbrauchsausweis Wohnen Email --- .../pdfDatenblattVerbrauchsausweisGewerbe.ts | 4 +- .../pdfDatenblattVerbrauchsausweisWohnen.ts | 4 +- src/lib/pdf/pdfVerbrauchsausweisGewerbe.ts | 27 ++-- src/lib/pdf/pdfVerbrauchsausweisWohnen.ts | 151 ++++++++++++------ src/lib/server/ausweis.ts | 8 +- 5 files changed, 120 insertions(+), 74 deletions(-) diff --git a/src/lib/pdf/pdfDatenblattVerbrauchsausweisGewerbe.ts b/src/lib/pdf/pdfDatenblattVerbrauchsausweisGewerbe.ts index 37ead769..b363db7d 100644 --- a/src/lib/pdf/pdfDatenblattVerbrauchsausweisGewerbe.ts +++ b/src/lib/pdf/pdfDatenblattVerbrauchsausweisGewerbe.ts @@ -12,7 +12,7 @@ import { PERSISTENT_DIR } from "#lib/server/constants.js"; /* -------------------------------- Pdf Tools ------------------------------- */ -export async function pdfDatenblattVerbrauchsausweisGewerbe(ausweis: VerbrauchsausweisGewerbeClient, aufnahme: AufnahmeClient, objekt: ObjektClient, benutzer: BenutzerClient, bilder: UploadedGebaeudeBild[]) { +export async function pdfDatenblattVerbrauchsausweisGewerbe(ausweis: VerbrauchsausweisGewerbeClient, aufnahme: AufnahmeClient, objekt: ObjektClient, benutzer: BenutzerClient, 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]); @@ -365,8 +365,6 @@ export async function pdfDatenblattVerbrauchsausweisGewerbe(ausweis: Verbrauchsa if (bild.uid) { image = `` - } else if (bild.data) { - image = `` } if (images.length > 0) { diff --git a/src/lib/pdf/pdfDatenblattVerbrauchsausweisWohnen.ts b/src/lib/pdf/pdfDatenblattVerbrauchsausweisWohnen.ts index ba73e5ea..21daada6 100644 --- a/src/lib/pdf/pdfDatenblattVerbrauchsausweisWohnen.ts +++ b/src/lib/pdf/pdfDatenblattVerbrauchsausweisWohnen.ts @@ -12,7 +12,7 @@ import { PERSISTENT_DIR } from "#lib/server/constants.js"; /* -------------------------------- Pdf Tools ------------------------------- */ -export async function pdfDatenblattVerbrauchsausweisWohnen(ausweis: VerbrauchsausweisWohnenClient, aufnahme: AufnahmeClient, objekt: ObjektClient, benutzer: BenutzerClient, bilder: UploadedGebaeudeBild[]) { +export async function pdfDatenblattVerbrauchsausweisWohnen(ausweis: VerbrauchsausweisWohnenClient, aufnahme: AufnahmeClient, objekt: ObjektClient, benutzer: BenutzerClient, 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]); @@ -308,8 +308,6 @@ export async function pdfDatenblattVerbrauchsausweisWohnen(ausweis: Verbrauchsau if (bild.uid) { image = `` - } else if (bild.data) { - image = `` } if (images.length > 0) { diff --git a/src/lib/pdf/pdfVerbrauchsausweisGewerbe.ts b/src/lib/pdf/pdfVerbrauchsausweisGewerbe.ts index 58677b90..bb41a6cb 100644 --- a/src/lib/pdf/pdfVerbrauchsausweisGewerbe.ts +++ b/src/lib/pdf/pdfVerbrauchsausweisGewerbe.ts @@ -1,4 +1,4 @@ -import { AufnahmeClient, BenutzerClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisGewerbeClient } from "#components/Ausweis/types.js"; +import { AufnahmeClient, BenutzerClient, BildClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisGewerbeClient } from "#components/Ausweis/types.js"; import { endEnergieVerbrauchVerbrauchsausweisGewerbe_2016 } from "#lib/Berechnungen/VerbrauchsausweisGewerbe/VerbrauchsausweisGewerbe_2016.js"; import { getEmpfehlungen } from "#lib/XML/getEmpfehlungen.js"; import { Enums } from "#lib/server/prisma.js"; @@ -8,9 +8,11 @@ import { PDFDocument, PDFFont, PDFImage, PDFPage, StandardFonts } from "pdf-lib" import { addCheckMark } from "./utils/checkbox.js"; import { addText } from "./utils/text.js"; import { addAnsichtsausweisLabel, addDatumGEG } from "./utils/helpers.js"; +import { PERSISTENT_DIR } from "#lib/server/constants.js"; +import { fileURLToPath } from "url"; -export async function pdfVerbrauchsausweisGewerbe(ausweis: VerbrauchsausweisGewerbeClient, aufnahme: AufnahmeClient, objekt: ObjektClient, bilder: UploadedGebaeudeBild[], user: BenutzerClient) { +export async function pdfVerbrauchsausweisGewerbe(ausweis: VerbrauchsausweisGewerbeClient, aufnahme: AufnahmeClient, objekt: ObjektClient, bilder: BildClient[], user: BenutzerClient) { 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() @@ -137,20 +139,15 @@ export async function pdfVerbrauchsausweisGewerbe(ausweis: VerbrauchsausweisGewe - const gebaeudeBild = bilder.find(image => image.kategorie === Enums.BilderKategorie.Gebaeude); + const bild = bilder && bilder.find(image => image.kategorie === Enums.BilderKategorie.Gebaeude); - if (gebaeudeBild) { - let image: PDFImage | null; - try { - image = await pdf.embedJpg(gebaeudeBild.data) - } catch(e) { - try { - image = await pdf.embedPng(gebaeudeBild.data) - } catch(e) { - image = null; - } - } - if (image) { + if (bild) { + const path = `${PERSISTENT_DIR}/images/${bild.uid}.jpg`; + + if (fs.existsSync(path)) { + const file = fs.readFileSync(fileURLToPath(new URL(path, import.meta.url))) + let image: PDFImage; + image = await pdf.embedJpg(file) pages[0].drawImage(image, { x: 460.5, y: height - 289, diff --git a/src/lib/pdf/pdfVerbrauchsausweisWohnen.ts b/src/lib/pdf/pdfVerbrauchsausweisWohnen.ts index 5f77f8bc..c3368939 100644 --- a/src/lib/pdf/pdfVerbrauchsausweisWohnen.ts +++ b/src/lib/pdf/pdfVerbrauchsausweisWohnen.ts @@ -48,40 +48,122 @@ export async function pdfVerbrauchsausweisWohnen(ausweis: VerbrauchsausweisWohne } } - const gebaeudetyp = fillFormField("gebaeudetyp", aufnahme.gebaeudetyp || "") + pages[0].drawText(aufnahme.gebaeudetyp || "", { + x: 211, + y: height - 166, + size: 10 + }) - const adresse = fillFormField("adresse", objekt.adresse || "") - + pages[0].drawText(objekt.adresse || "", { + x: 211, + y: height - 194, + size: 10 + }) - const gebaeudeteil = fillFormField("gebaeudeteil", aufnahme.gebaeudeteil || "") + pages[0].drawText(aufnahme.gebaeudeteil || "", { + x: 211, + y: height - 214.5, + size: 10 + }) - const baujahr_gebaeude = fillFormField("baujahr_gebaeude", aufnahme.baujahr_gebaeude?.toString()) + pages[0].drawText(aufnahme.baujahr_gebaeude?.toString() || "", { + x: 211, + y: height - 229.5, + size: 10 + }) - const baujahr_heizung = fillFormField("baujahr_heizung", aufnahme.baujahr_heizung?.toString()) + pages[0].drawText(aufnahme.baujahr_heizung?.toString() || "", { + x: 211, + y: height - 250, + size: 10 + }) - const einheiten = fillFormField("einheiten", (aufnahme.einheiten || 1).toString()) + pages[0].drawText(aufnahme.einheiten?.toString() || "", { + x: 211, + y: height - 271.5, + size: 10 + }) - const nutzflaeche = fillFormField("nutzflaeche", `${berechnungen?.energetischeNutzflaeche?.toString()}m²`) + pages[0].drawText(aufnahme.nutzflaeche?.toString() || "", { + x: 211, + y: height - 285, + size: 10 + }) - fillFormField("energietraeger_heizung", `${aufnahme.brennstoff_1}, ${aufnahme.brennstoff_2 || ""}`) + pages[0].drawText(`${aufnahme.brennstoff_1}, ${aufnahme.brennstoff_2 || ""}`, { + x: 211, + y: height - 298.5, + size: 10 + }) if (ausweis.warmwasser_enthalten) { - fillFormField("energietraeger_warmwasser", `${aufnahme.brennstoff_1}, ${aufnahme.brennstoff_2 || ""}`) + pages[0].drawText(`${aufnahme.brennstoff_1}, ${aufnahme.brennstoff_2 || ""}`, { + x: 211, + y: height - 312, + size: 10 + }) } - if (aufnahme.durchlauf_erhitzer && !ausweis.warmwasser_enthalten) { - fillFormField("energietraeger_warmwasser", "Strommix"); + + const erneuerbareEnergienVerwendung = [] + + if (ausweis.alternative_heizung) { + erneuerbareEnergienVerwendung.push("Heizung") } - toggleCheck("fensterlueftung", aufnahme.lueftung == Enums.Lueftungskonzept.Fensterlueftung) - toggleCheck("schachtlueftung", aufnahme.lueftung == Enums.Lueftungskonzept.Schachtlueftung) - toggleCheck("lueftungsanlage_ohne_waermerueckgewinnung", aufnahme.lueftung == Enums.Lueftungskonzept.LueftungsanlageOhneWaermerueckgewinnung) - toggleCheck("lueftungsanlage_waermerueckgewinnung", aufnahme.lueftung == Enums.Lueftungskonzept.LueftungsanlageMitWaermerueckgewinnung) + if (ausweis.alternative_kuehlung) { + erneuerbareEnergienVerwendung.push("Kühlung") + } - toggleCheck("anlass_neubau", ausweis.ausstellgrund == "Neubau") - toggleCheck("anlass_vermietung", ausweis.ausstellgrund == "Vermietung" || ausweis.ausstellgrund == "Verkauf") - toggleCheck("anlass_modernisierung", ausweis.ausstellgrund == "Modernisierung") - toggleCheck("anlass_sonstiges", ausweis.ausstellgrund == "Sonstiges") + 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[0].drawText(`${aufnahme.brennstoff_1}, ${aufnahme.brennstoff_2 || ""}`, { + x: 211, + y: height - 299, + size: 10 + }) + } + + + if (aufnahme.lueftung === Enums.Lueftungskonzept.Fensterlueftung) { + addCheckMark(pages[0], 213, height - 347) + } else if (aufnahme.lueftung === Enums.Lueftungskonzept.Schachtlueftung) { + addCheckMark(pages[0], 213, height - 358) + } else if (aufnahme.lueftung === Enums.Lueftungskonzept.LueftungsanlageMitWaermerueckgewinnung) { + addCheckMark(pages[0], 355, height - 347) + } else if (aufnahme.lueftung === Enums.Lueftungskonzept.LueftungsanlageOhneWaermerueckgewinnung) { + addCheckMark(pages[0], 355, height - 358) + } + + // Kühlung + if (aufnahme.kuehlung) { + addCheckMark(pages[0], 213, height - 375.5) + } else { + addCheckMark(pages[0], 355, height - 386.5) + } + + if (ausweis.ausstellgrund === Enums.Ausstellgrund.Neubau) { + addCheckMark(pages[0], 213, height - 419) + } else if (ausweis.ausstellgrund === Enums.Ausstellgrund.Vermietung || ausweis.ausstellgrund === Enums.Ausstellgrund.Verkauf) { + addCheckMark(pages[0], 213, height - 430) + } else if (ausweis.ausstellgrund === Enums.Ausstellgrund.Modernisierung) { + addCheckMark(pages[0], 344.5, height - 419) + } else if (ausweis.ausstellgrund === Enums.Ausstellgrund.Sonstiges) { + addCheckMark(pages[0], 463, height - 419) + } const bild = bilder && bilder.find(image => image.kategorie === Enums.BilderKategorie.Gebaeude); @@ -150,35 +232,6 @@ export async function pdfVerbrauchsausweisWohnen(ausweis: VerbrauchsausweisWohne height: 50 }) - 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 - 337, - size: 8 - }) - - // Kühlung - if (aufnahme.kuehlung) { - addCheckMark(pages[0], 354, height - 376.5) - } - /* -------------------------------- Seite 2 -------------------------------- */ diff --git a/src/lib/server/ausweis.ts b/src/lib/server/ausweis.ts index a06672d0..ced5d156 100644 --- a/src/lib/server/ausweis.ts +++ b/src/lib/server/ausweis.ts @@ -31,9 +31,9 @@ export async function getAnsichtsausweis(ausweis: VerbrauchsausweisWohnenClient } if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) { - return await pdfVerbrauchsausweisWohnen(ausweis, aufnahme, objekt, bilder, user) + return await pdfVerbrauchsausweisWohnen(ausweis as VerbrauchsausweisWohnenClient, aufnahme, objekt, bilder, user) } else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) { - return await pdfVerbrauchsausweisGewerbe(ausweis, aufnahme, objekt, bilder, user) + return await pdfVerbrauchsausweisGewerbe(ausweis as VerbrauchsausweisGewerbeClient, aufnahme, objekt, bilder, user) } return null @@ -49,9 +49,9 @@ export async function getDatenblatt(ausweis: VerbrauchsausweisWohnenClient | Ver } if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) { - return await pdfDatenblattVerbrauchsausweisWohnen(ausweis, aufnahme, objekt, bilder, user) + return await pdfDatenblattVerbrauchsausweisWohnen(ausweis as VerbrauchsausweisWohnenClient, aufnahme, objekt, user, bilder) } else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) { - return await pdfDatenblattVerbrauchsausweisGewerbe(ausweis, aufnahme, objekt, bilder, user) + return await pdfDatenblattVerbrauchsausweisGewerbe(ausweis as VerbrauchsausweisGewerbeClient, aufnahme, objekt, user, bilder) } return null From e0faf0bced1fe1774873fe4c6cbf904947c21f48 Mon Sep 17 00:00:00 2001 From: Jens Cornelsen <79703163+IB-Cornelsen@users.noreply.github.com> Date: Thu, 13 Mar 2025 22:40:00 +0100 Subject: [PATCH 12/17] . --- src/lib/server/mail/invoice.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/lib/server/mail/invoice.ts b/src/lib/server/mail/invoice.ts index 5dc869fd..663c81e0 100644 --- a/src/lib/server/mail/invoice.ts +++ b/src/lib/server/mail/invoice.ts @@ -78,12 +78,9 @@ export async function sendInvoiceMail( bcc: "info@online-energieausweis.org", html: `

Sehr geehrte*r ${user.vorname} ${user.name},

-

vielen Dank für Ihre Bestellung. Im Anhang finden Sie den Ansichtsausweis als PDF-Datei. Wir werden den Ausweis nun prüfen und Originalausweis und Rechnung nach Prüfung zuschicken.

-

In der Regel erhalten Sie Ihren Ausweis innerhalb von 24 Stunden. Die Ausstellung erfolgt nach aktuellem GEG und Ihr Ausweis wird beim DIBT registriert.

-
-

Ihre Zahlung konnte nicht durchgeführt werden. Sie erhalten Bankverbindung und Verwendungszweck zusammen mit der Rechnung, sobald ihr Ausweis ausgestellt wurde.

-
-
+

vielen Dank für Ihre Bestellung. Im Anhang finden Sie den Ansichtsausweis als PDF-Datei. Wir werden den Ausweis nun prüfen und Originalausweis und Rechnung nach Prüfung zuschicken.
+ In der Regel erhalten Sie Ihren Ausweis innerhalb von 24 Stunden. Die Ausstellung erfolgt nach aktuellem GEG und Ihr Ausweis wird beim DIBT registriert.

+

Eine Zahlung wurde noch nicht durchgeführt. Sie erhalten Bankverbindung und Verwendungszweck zusammen mit der Rechnung, sobald ihr Ausweis ausgestellt wurde.

Mit freundlichen Grüßen,
From f85a61dcff41d7edc6a26ee5659c78ff9021fb8d Mon Sep 17 00:00:00 2001 From: Jens Cornelsen <79703163+IB-Cornelsen@users.noreply.github.com> Date: Fri, 14 Mar 2025 00:02:13 +0100 Subject: [PATCH 13/17] Email --- src/lib/server/mail/helpers.ts | 106 ++++++++++++++++++++++++++++++++- src/lib/server/mail/invoice.ts | 26 +------- 2 files changed, 107 insertions(+), 25 deletions(-) diff --git a/src/lib/server/mail/helpers.ts b/src/lib/server/mail/helpers.ts index 89c8ee62..9bd86b1e 100644 --- a/src/lib/server/mail/helpers.ts +++ b/src/lib/server/mail/helpers.ts @@ -5,8 +5,11 @@ export function getPaymentSuccessSubject(ausweis: VerbrauchsausweisWohnen | Verb const id = shortenUID(ausweis.uid); let subject: string = ""; + let body: string = ""; + if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) { - subject = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Wohnen (ID: ${id})` + subject = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Wohnen (ID: ${id})`; + body = ` bbbb `; if (rechnung.ausweistyp === Enums.AusweisTyp.Beratung) { subject = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Wohnen mit Beratung (ID: ${id})` } else if (rechnung.ausweistyp === Enums.AusweisTyp.Offline) { @@ -29,4 +32,105 @@ export function getPaymentSuccessSubject(ausweis: VerbrauchsausweisWohnen | Verb } return subject; +} + +export function getPaymentSuccessBody(ausweis: VerbrauchsausweisWohnen | VerbrauchsausweisGewerbe | BedarfsausweisWohnen, rechnung: Rechnung, ausweisart: Enums.Ausweisart) { + const id = shortenUID(ausweis.uid); + + let subject: string = ""; + let body: string = ""; + + if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) { + body = `

Sehr geehrte*r ${user.vorname} ${user.name},

+ +

vielen Dank für Ihre Bestellung. Im Anhang finden Sie den Ansichtsausweis als PDF-Datei. Wir werden den Ausweis nun prüfen und Originalausweis und Rechnung nach Prüfung zuschicken.
+ In der Regel erhalten Sie Ihren Ausweis innerhalb von 24 Stunden. Die Ausstellung erfolgt nach aktuellem GEG und Ihr Ausweis wird beim DIBT registriert.

+

Eine Zahlung wurde noch nicht durchgeführt. Sie erhalten Bankverbindung und Verwendungszweck zusammen mit der Rechnung, sobald ihr Ausweis ausgestellt wurde.

+

+ Mit freundlichen Grüßen, +
+ Dipl.-Ing. Jens Cornelsen +
+
+ IB Cornelsen +
+ Katendeich 5A +
+ 21035 Hamburg +
+ www.online-energieausweis.org +
+
+ fon 040 · 209339850 +
+ fax 040 · 209339859 +

` + if (rechnung.ausweistyp === Enums.AusweisTyp.Beratung) { + body = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Wohnen mit Beratung (ID: ${id})` + } else if (rechnung.ausweistyp === Enums.AusweisTyp.Offline) { + body = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Wohnen - offline Service (ID: ${id})` + } + } else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) { + body = `

Sehr geehrte*r ${user.vorname} ${user.name},

+ +

vielen Dank für Ihre Bestellung. Im Anhang finden Sie den Ansichtsausweis als PDF-Datei. Wir werden den Ausweis nun prüfen und Originalausweis und Rechnung nach Prüfung zuschicken.
+ In der Regel erhalten Sie Ihren Ausweis innerhalb von 24 Stunden. Die Ausstellung erfolgt nach aktuellem GEG und Ihr Ausweis wird beim DIBT registriert.

+

Eine Zahlung wurde noch nicht durchgeführt. Sie erhalten Bankverbindung und Verwendungszweck zusammen mit der Rechnung, sobald ihr Ausweis ausgestellt wurde.

+

+ Mit freundlichen Grüßen, +
+ Dipl.-Ing. Jens Cornelsen +
+
+ IB Cornelsen +
+ Katendeich 5A +
+ 21035 Hamburg +
+ www.online-energieausweis.org +
+
+ fon 040 · 209339850 +
+ fax 040 · 209339859 +

` + if (rechnung.ausweistyp === Enums.AusweisTyp.Beratung) { + body = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Gewerbe mit Beratung (ID: ${id})` + } else if (rechnung.ausweistyp === Enums.AusweisTyp.Offline) { + body = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Gewerbe - offline Service (ID: ${id})` + } + } else if (ausweisart === Enums.Ausweisart.BedarfsausweisWohnen) { + body = `

Sehr geehrte*r ${user.vorname} ${user.name},

+ +

vielen Dank für Ihre Bestellung. Im Anhang finden Sie den Ansichtsausweis als PDF-Datei. Wir werden den Ausweis nun prüfen und Originalausweis und Rechnung nach Prüfung zuschicken.
+ In der Regel erhalten Sie Ihren Ausweis innerhalb von 24 Stunden. Die Ausstellung erfolgt nach aktuellem GEG und Ihr Ausweis wird beim DIBT registriert.

+

Eine Zahlung wurde noch nicht durchgeführt. Sie erhalten Bankverbindung und Verwendungszweck zusammen mit der Rechnung, sobald ihr Ausweis ausgestellt wurde.

+

+ Mit freundlichen Grüßen, +
+ Dipl.-Ing. Jens Cornelsen +
+
+ IB Cornelsen +
+ Katendeich 5A +
+ 21035 Hamburg +
+ www.online-energieausweis.org +
+
+ fon 040 · 209339850 +
+ fax 040 · 209339859 +

` + if (rechnung.ausweistyp === Enums.AusweisTyp.Beratung) { + body = `Bestellbestätigung vom IB Cornelsen - Bedarfsausweis Wohnen mit Beratung (ID: ${id})` + } else if (rechnung.ausweistyp === Enums.AusweisTyp.Offline) { + body = `Bestellbestätigung vom IB Cornelsen - Bedarfsausweis Wohnen - offline Service (ID: ${id})` + } + } + + return body; } \ No newline at end of file diff --git a/src/lib/server/mail/invoice.ts b/src/lib/server/mail/invoice.ts index 663c81e0..e08571f7 100644 --- a/src/lib/server/mail/invoice.ts +++ b/src/lib/server/mail/invoice.ts @@ -12,6 +12,7 @@ import { getAnsichtsausweis } from "../ausweis.js"; import Mail from "nodemailer/lib/mailer/index.js"; import { shortenUID } from "#server/lib/hash.js"; import { getPaymentSuccessSubject } from "./helpers.js"; +import { getPaymentSuccessBody } from "./helpers.js"; export async function sendInvoiceMail( ausweis: VerbrauchsausweisWohnen, @@ -76,29 +77,6 @@ export async function sendInvoiceMail( name: rechnung.empfaenger || "", }, bcc: "info@online-energieausweis.org", - html: `

Sehr geehrte*r ${user.vorname} ${user.name},

- -

vielen Dank für Ihre Bestellung. Im Anhang finden Sie den Ansichtsausweis als PDF-Datei. Wir werden den Ausweis nun prüfen und Originalausweis und Rechnung nach Prüfung zuschicken.
- In der Regel erhalten Sie Ihren Ausweis innerhalb von 24 Stunden. Die Ausstellung erfolgt nach aktuellem GEG und Ihr Ausweis wird beim DIBT registriert.

-

Eine Zahlung wurde noch nicht durchgeführt. Sie erhalten Bankverbindung und Verwendungszweck zusammen mit der Rechnung, sobald ihr Ausweis ausgestellt wurde.

-

- Mit freundlichen Grüßen, -
- Dipl.-Ing. Jens Cornelsen -
-
- IB Cornelsen -
- Katendeich 5A -
- 21035 Hamburg -
- www.online-energieausweis.org -
-
- fon 040 · 209339850 -
- fax 040 · 209339859 -

`, + html: getPaymentSuccessBody(ausweis, rechnung, ausweisart), }); } From 93f22bfe5df0f0a92006dde91e3c1ec69bf0f524 Mon Sep 17 00:00:00 2001 From: Jens Cornelsen <79703163+IB-Cornelsen@users.noreply.github.com> Date: Fri, 14 Mar 2025 00:15:29 +0100 Subject: [PATCH 14/17] . --- src/lib/server/mail/helpers.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/lib/server/mail/helpers.ts b/src/lib/server/mail/helpers.ts index 9bd86b1e..f8cfe354 100644 --- a/src/lib/server/mail/helpers.ts +++ b/src/lib/server/mail/helpers.ts @@ -5,11 +5,9 @@ export function getPaymentSuccessSubject(ausweis: VerbrauchsausweisWohnen | Verb const id = shortenUID(ausweis.uid); let subject: string = ""; - let body: string = ""; if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) { subject = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Wohnen (ID: ${id})`; - body = ` bbbb `; if (rechnung.ausweistyp === Enums.AusweisTyp.Beratung) { subject = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Wohnen mit Beratung (ID: ${id})` } else if (rechnung.ausweistyp === Enums.AusweisTyp.Offline) { @@ -37,7 +35,6 @@ export function getPaymentSuccessSubject(ausweis: VerbrauchsausweisWohnen | Verb export function getPaymentSuccessBody(ausweis: VerbrauchsausweisWohnen | VerbrauchsausweisGewerbe | BedarfsausweisWohnen, rechnung: Rechnung, ausweisart: Enums.Ausweisart) { const id = shortenUID(ausweis.uid); - let subject: string = ""; let body: string = ""; if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) { From a4f1e10f0ecb41c4e1341938bd20dd9dfc17c968 Mon Sep 17 00:00:00 2001 From: Jens Cornelsen <79703163+IB-Cornelsen@users.noreply.github.com> Date: Fri, 14 Mar 2025 00:29:34 +0100 Subject: [PATCH 15/17] . --- src/lib/server/mail/helpers.ts | 9 +++------ src/lib/server/mail/invoice.ts | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/lib/server/mail/helpers.ts b/src/lib/server/mail/helpers.ts index f8cfe354..ffd29936 100644 --- a/src/lib/server/mail/helpers.ts +++ b/src/lib/server/mail/helpers.ts @@ -38,8 +38,7 @@ export function getPaymentSuccessBody(ausweis: VerbrauchsausweisWohnen | Verbrau let body: string = ""; if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) { - body = `

Sehr geehrte*r ${user.vorname} ${user.name},

- + body = `

vielen Dank für Ihre Bestellung. Im Anhang finden Sie den Ansichtsausweis als PDF-Datei. Wir werden den Ausweis nun prüfen und Originalausweis und Rechnung nach Prüfung zuschicken.
In der Regel erhalten Sie Ihren Ausweis innerhalb von 24 Stunden. Die Ausstellung erfolgt nach aktuellem GEG und Ihr Ausweis wird beim DIBT registriert.

Eine Zahlung wurde noch nicht durchgeführt. Sie erhalten Bankverbindung und Verwendungszweck zusammen mit der Rechnung, sobald ihr Ausweis ausgestellt wurde.

@@ -68,8 +67,7 @@ export function getPaymentSuccessBody(ausweis: VerbrauchsausweisWohnen | Verbrau body = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Wohnen - offline Service (ID: ${id})` } } else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) { - body = `

Sehr geehrte*r ${user.vorname} ${user.name},

- + body = `

vielen Dank für Ihre Bestellung. Im Anhang finden Sie den Ansichtsausweis als PDF-Datei. Wir werden den Ausweis nun prüfen und Originalausweis und Rechnung nach Prüfung zuschicken.
In der Regel erhalten Sie Ihren Ausweis innerhalb von 24 Stunden. Die Ausstellung erfolgt nach aktuellem GEG und Ihr Ausweis wird beim DIBT registriert.

Eine Zahlung wurde noch nicht durchgeführt. Sie erhalten Bankverbindung und Verwendungszweck zusammen mit der Rechnung, sobald ihr Ausweis ausgestellt wurde.

@@ -98,8 +96,7 @@ export function getPaymentSuccessBody(ausweis: VerbrauchsausweisWohnen | Verbrau body = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Gewerbe - offline Service (ID: ${id})` } } else if (ausweisart === Enums.Ausweisart.BedarfsausweisWohnen) { - body = `

Sehr geehrte*r ${user.vorname} ${user.name},

- + body = `

vielen Dank für Ihre Bestellung. Im Anhang finden Sie den Ansichtsausweis als PDF-Datei. Wir werden den Ausweis nun prüfen und Originalausweis und Rechnung nach Prüfung zuschicken.
In der Regel erhalten Sie Ihren Ausweis innerhalb von 24 Stunden. Die Ausstellung erfolgt nach aktuellem GEG und Ihr Ausweis wird beim DIBT registriert.

Eine Zahlung wurde noch nicht durchgeführt. Sie erhalten Bankverbindung und Verwendungszweck zusammen mit der Rechnung, sobald ihr Ausweis ausgestellt wurde.

diff --git a/src/lib/server/mail/invoice.ts b/src/lib/server/mail/invoice.ts index e08571f7..e8373291 100644 --- a/src/lib/server/mail/invoice.ts +++ b/src/lib/server/mail/invoice.ts @@ -77,6 +77,6 @@ export async function sendInvoiceMail( name: rechnung.empfaenger || "", }, bcc: "info@online-energieausweis.org", - html: getPaymentSuccessBody(ausweis, rechnung, ausweisart), + html: `

Sehr geehrte*r ${user.vorname} ${user.name},

` + getPaymentSuccessBody(ausweis, rechnung, ausweisart), }); } From 6a0ffe25f2e680fa7447885a8076c4fb73a43bcd Mon Sep 17 00:00:00 2001 From: Jens Cornelsen <79703163+IB-Cornelsen@users.noreply.github.com> Date: Fri, 14 Mar 2025 00:50:07 +0100 Subject: [PATCH 16/17] . --- src/lib/server/mail/helpers.ts | 144 +++++++++++++++++++++++++++++++-- 1 file changed, 138 insertions(+), 6 deletions(-) diff --git a/src/lib/server/mail/helpers.ts b/src/lib/server/mail/helpers.ts index ffd29936..b2f7bf25 100644 --- a/src/lib/server/mail/helpers.ts +++ b/src/lib/server/mail/helpers.ts @@ -62,9 +62,53 @@ export function getPaymentSuccessBody(ausweis: VerbrauchsausweisWohnen | Verbrau fax 040 · 209339859

` if (rechnung.ausweistyp === Enums.AusweisTyp.Beratung) { - body = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Wohnen mit Beratung (ID: ${id})` + body = ` +

vielen Dank für Ihre Bestellung. Sie haben telefonische Beratung zu Ihrer online Eingabe angefordert.
+ Wir werden Sie innerhalb von 48 Stunden unter der von Ihnen hinterlegten Telefonnummer kontaktieren und dann die offenen Fragen zu Ihrer Eingabe beantworten.

+

Eine Zahlung wurde noch nicht durchgeführt. Sie erhalten Bankverbindung und Verwendungszweck zusammen mit der Rechnung, sobald ihr Ausweis ausgestellt wurde.

+

+ Mit freundlichen Grüßen, +
+ Dipl.-Ing. Jens Cornelsen +
+
+ IB Cornelsen +
+ Katendeich 5A +
+ 21035 Hamburg +
+ www.online-energieausweis.org +
+
+ fon 040 · 209339850 +
+ fax 040 · 209339859 +

` } else if (rechnung.ausweistyp === Enums.AusweisTyp.Offline) { - body = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Wohnen - offline Service (ID: ${id})` + body = ` +

vielen Dank für Ihre Bestellung. Sie haben unseren offline Service für Ihren Energieausweis angefordert.
+ Bitte antworten Sie auf diese E-Mail und schicken uns drei aktuelle Heizkostenabrechnungen Ihres Energieversorgers zu. Wir werden Sie innerhalb von 48 Stunden unter der von Ihnen hinterlegten Telefonnummer kontaktieren und die Eingabe in Absprache mit Ihnen durchführen.

+

Eine Zahlung wurde noch nicht durchgeführt. Sie erhalten Bankverbindung und Verwendungszweck zusammen mit der Rechnung, sobald ihr Ausweis ausgestellt wurde.

+

+ Mit freundlichen Grüßen, +
+ Dipl.-Ing. Jens Cornelsen +
+
+ IB Cornelsen +
+ Katendeich 5A +
+ 21035 Hamburg +
+ www.online-energieausweis.org +
+
+ fon 040 · 209339850 +
+ fax 040 · 209339859 +

` } } else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) { body = ` @@ -91,9 +135,53 @@ export function getPaymentSuccessBody(ausweis: VerbrauchsausweisWohnen | Verbrau fax 040 · 209339859

` if (rechnung.ausweistyp === Enums.AusweisTyp.Beratung) { - body = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Gewerbe mit Beratung (ID: ${id})` + body = ` +

vielen Dank für Ihre Bestellung. Sie haben telefonische Beratung zu Ihrer online Eingabe angefordert.
+ Wir werden Sie innerhalb von 48 Stunden unter der von Ihnen hinterlegten Telefonnummer kontaktieren und dann die offenen Fragen zu Ihrer Eingabe beantworten.

+

Eine Zahlung wurde noch nicht durchgeführt. Sie erhalten Bankverbindung und Verwendungszweck zusammen mit der Rechnung, sobald ihr Ausweis ausgestellt wurde.

+

+ Mit freundlichen Grüßen, +
+ Dipl.-Ing. Jens Cornelsen +
+
+ IB Cornelsen +
+ Katendeich 5A +
+ 21035 Hamburg +
+ www.online-energieausweis.org +
+
+ fon 040 · 209339850 +
+ fax 040 · 209339859 +

` } else if (rechnung.ausweistyp === Enums.AusweisTyp.Offline) { - body = `Bestellbestätigung vom IB Cornelsen - Verbrauchsausweis Gewerbe - offline Service (ID: ${id})` + body = ` +

vielen Dank für Ihre Bestellung. Sie haben unseren offline Service für Ihren Energieausweis angefordert.
+ Bitte antworten Sie auf diese E-Mail und schicken uns drei aktuelle Heizkostenabrechnungen Ihres Energieversorgers zu. Wir werden Sie innerhalb von 48 Stunden unter der von Ihnen hinterlegten Telefonnummer kontaktieren und die Eingabe in Absprache mit Ihnen durchführen.

+

Eine Zahlung wurde noch nicht durchgeführt. Sie erhalten Bankverbindung und Verwendungszweck zusammen mit der Rechnung, sobald ihr Ausweis ausgestellt wurde.

+

+ Mit freundlichen Grüßen, +
+ Dipl.-Ing. Jens Cornelsen +
+
+ IB Cornelsen +
+ Katendeich 5A +
+ 21035 Hamburg +
+ www.online-energieausweis.org +
+
+ fon 040 · 209339850 +
+ fax 040 · 209339859 +

` } } else if (ausweisart === Enums.Ausweisart.BedarfsausweisWohnen) { body = ` @@ -120,9 +208,53 @@ export function getPaymentSuccessBody(ausweis: VerbrauchsausweisWohnen | Verbrau fax 040 · 209339859

` if (rechnung.ausweistyp === Enums.AusweisTyp.Beratung) { - body = `Bestellbestätigung vom IB Cornelsen - Bedarfsausweis Wohnen mit Beratung (ID: ${id})` + body = ` +

vielen Dank für Ihre Bestellung. Sie haben telefonische Beratung zu Ihrer online Eingabe angefordert.
+ Wir werden Sie innerhalb von 48 Stunden unter der von Ihnen hinterlegten Telefonnummer kontaktieren und dann die offenen Fragen zu Ihrer Eingabe beantworten.

+

Eine Zahlung wurde noch nicht durchgeführt. Sie erhalten Bankverbindung und Verwendungszweck zusammen mit der Rechnung, sobald ihr Ausweis ausgestellt wurde.

+

+ Mit freundlichen Grüßen, +
+ Dipl.-Ing. Jens Cornelsen +
+
+ IB Cornelsen +
+ Katendeich 5A +
+ 21035 Hamburg +
+ www.online-energieausweis.org +
+
+ fon 040 · 209339850 +
+ fax 040 · 209339859 +

` } else if (rechnung.ausweistyp === Enums.AusweisTyp.Offline) { - body = `Bestellbestätigung vom IB Cornelsen - Bedarfsausweis Wohnen - offline Service (ID: ${id})` + body = ` +

vielen Dank für Ihre Bestellung. Sie haben unseren offline Service für Ihren Energieausweis angefordert.
+ Bitte antworten Sie auf diese E-Mail und schicken uns drei aktuelle Heizkostenabrechnungen Ihres Energieversorgers zu. Wir werden Sie innerhalb von 48 Stunden unter der von Ihnen hinterlegten Telefonnummer kontaktieren und die Eingabe in Absprache mit Ihnen durchführen.

+

Eine Zahlung wurde noch nicht durchgeführt. Sie erhalten Bankverbindung und Verwendungszweck zusammen mit der Rechnung, sobald ihr Ausweis ausgestellt wurde.

+

+ Mit freundlichen Grüßen, +
+ Dipl.-Ing. Jens Cornelsen +
+
+ IB Cornelsen +
+ Katendeich 5A +
+ 21035 Hamburg +
+ www.online-energieausweis.org +
+
+ fon 040 · 209339850 +
+ fax 040 · 209339859 +

` } } From 65ccda0ac036783ab404e92dbb54c357a07df49f Mon Sep 17 00:00:00 2001 From: Jens Cornelsen <79703163+IB-Cornelsen@users.noreply.github.com> Date: Fri, 14 Mar 2025 01:26:49 +0100 Subject: [PATCH 17/17] . --- src/lib/server/mail/helpers.ts | 235 ++++++++++++++++++++++++- src/lib/server/mail/invoice.ts | 4 +- src/lib/server/mail/payment-success.ts | 28 +-- 3 files changed, 236 insertions(+), 31 deletions(-) diff --git a/src/lib/server/mail/helpers.ts b/src/lib/server/mail/helpers.ts index b2f7bf25..64bf204d 100644 --- a/src/lib/server/mail/helpers.ts +++ b/src/lib/server/mail/helpers.ts @@ -32,7 +32,7 @@ export function getPaymentSuccessSubject(ausweis: VerbrauchsausweisWohnen | Verb return subject; } -export function getPaymentSuccessBody(ausweis: VerbrauchsausweisWohnen | VerbrauchsausweisGewerbe | BedarfsausweisWohnen, rechnung: Rechnung, ausweisart: Enums.Ausweisart) { +export function getPaymentInvoiceBody(ausweis: VerbrauchsausweisWohnen | VerbrauchsausweisGewerbe | BedarfsausweisWohnen, rechnung: Rechnung, ausweisart: Enums.Ausweisart) { const id = shortenUID(ausweis.uid); let body: string = ""; @@ -186,7 +186,7 @@ export function getPaymentSuccessBody(ausweis: VerbrauchsausweisWohnen | Verbrau } else if (ausweisart === Enums.Ausweisart.BedarfsausweisWohnen) { body = `

vielen Dank für Ihre Bestellung. Im Anhang finden Sie den Ansichtsausweis als PDF-Datei. Wir werden den Ausweis nun prüfen und Originalausweis und Rechnung nach Prüfung zuschicken.
- In der Regel erhalten Sie Ihren Ausweis innerhalb von 24 Stunden. Die Ausstellung erfolgt nach aktuellem GEG und Ihr Ausweis wird beim DIBT registriert.

+ Die Erstellung des Bedarfsausweises dauert momentan leider etwas länger. Bitte kontaktieren Sie uns in dringenden Fällen telefonisch (9 - 12 Uhr). Die Ausstellung erfolgt nach aktuellem GEG und Ihr Ausweis wird beim DIBT registriert.

Eine Zahlung wurde noch nicht durchgeführt. Sie erhalten Bankverbindung und Verwendungszweck zusammen mit der Rechnung, sobald ihr Ausweis ausgestellt wurde.

Mit freundlichen Grüßen, @@ -234,7 +234,7 @@ export function getPaymentSuccessBody(ausweis: VerbrauchsausweisWohnen | Verbrau } else if (rechnung.ausweistyp === Enums.AusweisTyp.Offline) { body = `

vielen Dank für Ihre Bestellung. Sie haben unseren offline Service für Ihren Energieausweis angefordert.
- Bitte antworten Sie auf diese E-Mail und schicken uns drei aktuelle Heizkostenabrechnungen Ihres Energieversorgers zu. Wir werden Sie innerhalb von 48 Stunden unter der von Ihnen hinterlegten Telefonnummer kontaktieren und die Eingabe in Absprache mit Ihnen durchführen.

+ Bitte antworten Sie auf diese E-Mail und schicken uns Grundriss- und Ansichtspläne Ihres Gebäudes zu. Wir werden Sie innerhalb von 48 Stunden unter der von Ihnen hinterlegten Telefonnummer kontaktieren und die Eingabe in Absprache mit Ihnen durchführen.

Eine Zahlung wurde noch nicht durchgeführt. Sie erhalten Bankverbindung und Verwendungszweck zusammen mit der Rechnung, sobald ihr Ausweis ausgestellt wurde.

Mit freundlichen Grüßen, @@ -258,5 +258,234 @@ export function getPaymentSuccessBody(ausweis: VerbrauchsausweisWohnen | Verbrau } } + return body; +} + +export function getPaymentSuccessBody(ausweis: VerbrauchsausweisWohnen | VerbrauchsausweisGewerbe | BedarfsausweisWohnen, rechnung: Rechnung, ausweisart: Enums.Ausweisart) { + const id = shortenUID(ausweis.uid); + + let body: string = ""; + + if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) { + body = ` +

vielen Dank für Ihre Bestellung. Im Anhang finden Sie den Ansichtsausweis als PDF-Datei. Wir werden den Ausweis nun prüfen und Originalausweis und Rechnung nach Prüfung zuschicken.
+ In der Regel erhalten Sie Ihren Ausweis innerhalb von 24 Stunden. Die Ausstellung erfolgt nach aktuellem GEG und Ihr Ausweis wird beim DIBT registriert.

+

Den Rechnungsbetrag haben Sie bereits bezahlt. Vielen Dank.

+

+ Mit freundlichen Grüßen, +
+ Dipl.-Ing. Jens Cornelsen +
+
+ IB Cornelsen +
+ Katendeich 5A +
+ 21035 Hamburg +
+ www.online-energieausweis.org +
+
+ fon 040 · 209339850 +
+ fax 040 · 209339859 +

` + if (rechnung.ausweistyp === Enums.AusweisTyp.Beratung) { + body = ` +

vielen Dank für Ihre Bestellung. Sie haben telefonische Beratung zu Ihrer online Eingabe angefordert.
+ Wir werden Sie innerhalb von 48 Stunden unter der von Ihnen hinterlegten Telefonnummer kontaktieren und dann die offenen Fragen zu Ihrer Eingabe beantworten.

+

Den Rechnungsbetrag haben Sie bereits bezahlt. Vielen Dank.

+

+ Mit freundlichen Grüßen, +
+ Dipl.-Ing. Jens Cornelsen +
+
+ IB Cornelsen +
+ Katendeich 5A +
+ 21035 Hamburg +
+ www.online-energieausweis.org +
+
+ fon 040 · 209339850 +
+ fax 040 · 209339859 +

` + } else if (rechnung.ausweistyp === Enums.AusweisTyp.Offline) { + body = ` +

vielen Dank für Ihre Bestellung. Sie haben unseren offline Service für Ihren Energieausweis angefordert.
+ Bitte antworten Sie auf diese E-Mail und schicken uns drei aktuelle Heizkostenabrechnungen Ihres Energieversorgers zu. Wir werden Sie innerhalb von 48 Stunden unter der von Ihnen hinterlegten Telefonnummer kontaktieren und die Eingabe in Absprache mit Ihnen durchführen.

+

Den Rechnungsbetrag haben Sie bereits bezahlt. Vielen Dank.

+

+ Mit freundlichen Grüßen, +
+ Dipl.-Ing. Jens Cornelsen +
+
+ IB Cornelsen +
+ Katendeich 5A +
+ 21035 Hamburg +
+ www.online-energieausweis.org +
+
+ fon 040 · 209339850 +
+ fax 040 · 209339859 +

` + } + } else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) { + body = ` +

vielen Dank für Ihre Bestellung. Im Anhang finden Sie den Ansichtsausweis als PDF-Datei. Wir werden den Ausweis nun prüfen und Originalausweis und Rechnung nach Prüfung zuschicken.
+ In der Regel erhalten Sie Ihren Ausweis innerhalb von 24 Stunden. Die Ausstellung erfolgt nach aktuellem GEG und Ihr Ausweis wird beim DIBT registriert.

+

Den Rechnungsbetrag haben Sie bereits bezahlt. Vielen Dank.

+

+ Mit freundlichen Grüßen, +
+ Dipl.-Ing. Jens Cornelsen +
+
+ IB Cornelsen +
+ Katendeich 5A +
+ 21035 Hamburg +
+ www.online-energieausweis.org +
+
+ fon 040 · 209339850 +
+ fax 040 · 209339859 +

` + if (rechnung.ausweistyp === Enums.AusweisTyp.Beratung) { + body = ` +

vielen Dank für Ihre Bestellung. Sie haben telefonische Beratung zu Ihrer online Eingabe angefordert.
+ Wir werden Sie innerhalb von 48 Stunden unter der von Ihnen hinterlegten Telefonnummer kontaktieren und dann die offenen Fragen zu Ihrer Eingabe beantworten.

+

Den Rechnungsbetrag haben Sie bereits bezahlt. Vielen Dank.

+

+ Mit freundlichen Grüßen, +
+ Dipl.-Ing. Jens Cornelsen +
+
+ IB Cornelsen +
+ Katendeich 5A +
+ 21035 Hamburg +
+ www.online-energieausweis.org +
+
+ fon 040 · 209339850 +
+ fax 040 · 209339859 +

` + } else if (rechnung.ausweistyp === Enums.AusweisTyp.Offline) { + body = ` +

vielen Dank für Ihre Bestellung. Sie haben unseren offline Service für Ihren Energieausweis angefordert.
+ Bitte antworten Sie auf diese E-Mail und schicken uns drei aktuelle Heizkostenabrechnungen Ihres Energieversorgers zu. Wir werden Sie innerhalb von 48 Stunden unter der von Ihnen hinterlegten Telefonnummer kontaktieren und die Eingabe in Absprache mit Ihnen durchführen.

+

Den Rechnungsbetrag haben Sie bereits bezahlt. Vielen Dank.

+

+ Mit freundlichen Grüßen, +
+ Dipl.-Ing. Jens Cornelsen +
+
+ IB Cornelsen +
+ Katendeich 5A +
+ 21035 Hamburg +
+ www.online-energieausweis.org +
+
+ fon 040 · 209339850 +
+ fax 040 · 209339859 +

` + } + } else if (ausweisart === Enums.Ausweisart.BedarfsausweisWohnen) { + body = ` +

vielen Dank für Ihre Bestellung. Im Anhang finden Sie den Ansichtsausweis als PDF-Datei. Wir werden den Ausweis nun prüfen und Originalausweis und Rechnung nach Prüfung zuschicken.
+ Die Erstellung des Bedarfsausweises dauert momentan leider etwas länger. Bitte kontaktieren Sie uns in dringenden Fällen telefonisch (9 - 12 Uhr). Die Ausstellung erfolgt nach aktuellem GEG und Ihr Ausweis wird beim DIBT registriert.

+

Den Rechnungsbetrag haben Sie bereits bezahlt. Vielen Dank.

+

+ Mit freundlichen Grüßen, +
+ Dipl.-Ing. Jens Cornelsen +
+
+ IB Cornelsen +
+ Katendeich 5A +
+ 21035 Hamburg +
+ www.online-energieausweis.org +
+
+ fon 040 · 209339850 +
+ fax 040 · 209339859 +

` + if (rechnung.ausweistyp === Enums.AusweisTyp.Beratung) { + body = ` +

vielen Dank für Ihre Bestellung. Sie haben telefonische Beratung zu Ihrer online Eingabe angefordert.
+ Wir werden Sie innerhalb von 48 Stunden unter der von Ihnen hinterlegten Telefonnummer kontaktieren und dann die offenen Fragen zu Ihrer Eingabe beantworten.

+

Den Rechnungsbetrag haben Sie bereits bezahlt. Vielen Dank.

+

+ Mit freundlichen Grüßen, +
+ Dipl.-Ing. Jens Cornelsen +
+
+ IB Cornelsen +
+ Katendeich 5A +
+ 21035 Hamburg +
+ www.online-energieausweis.org +
+
+ fon 040 · 209339850 +
+ fax 040 · 209339859 +

` + } else if (rechnung.ausweistyp === Enums.AusweisTyp.Offline) { + body = ` +

vielen Dank für Ihre Bestellung. Sie haben unseren offline Service für Ihren Energieausweis angefordert.
+ Bitte antworten Sie auf diese E-Mail und schicken uns Grundriss- und Ansichtspläne Ihres Gebäudes zu. Wir werden Sie innerhalb von 48 Stunden unter der von Ihnen hinterlegten Telefonnummer kontaktieren und die Eingabe in Absprache mit Ihnen durchführen.

+

Den Rechnungsbetrag haben Sie bereits bezahlt. Vielen Dank.

+

+ Mit freundlichen Grüßen, +
+ Dipl.-Ing. Jens Cornelsen +
+
+ IB Cornelsen +
+ Katendeich 5A +
+ 21035 Hamburg +
+ www.online-energieausweis.org +
+
+ fon 040 · 209339850 +
+ fax 040 · 209339859 +

` + } + } + return body; } \ No newline at end of file diff --git a/src/lib/server/mail/invoice.ts b/src/lib/server/mail/invoice.ts index e8373291..7672b890 100644 --- a/src/lib/server/mail/invoice.ts +++ b/src/lib/server/mail/invoice.ts @@ -12,7 +12,7 @@ import { getAnsichtsausweis } from "../ausweis.js"; import Mail from "nodemailer/lib/mailer/index.js"; import { shortenUID } from "#server/lib/hash.js"; import { getPaymentSuccessSubject } from "./helpers.js"; -import { getPaymentSuccessBody } from "./helpers.js"; +import { getPaymentInvoiceBody } from "./helpers.js"; export async function sendInvoiceMail( ausweis: VerbrauchsausweisWohnen, @@ -77,6 +77,6 @@ export async function sendInvoiceMail( name: rechnung.empfaenger || "", }, bcc: "info@online-energieausweis.org", - html: `

Sehr geehrte*r ${user.vorname} ${user.name},

` + getPaymentSuccessBody(ausweis, rechnung, ausweisart), + html: `

Sehr geehrte*r ${user.vorname} ${user.name},

` + getPaymentInvoiceBody(ausweis, rechnung, ausweisart), }); } diff --git a/src/lib/server/mail/payment-success.ts b/src/lib/server/mail/payment-success.ts index 99a5929f..a434da03 100644 --- a/src/lib/server/mail/payment-success.ts +++ b/src/lib/server/mail/payment-success.ts @@ -11,6 +11,7 @@ import { getAnsichtsausweis } from "../ausweis.js"; import Mail from "nodemailer/lib/mailer/index.js"; import { shortenUID } from "#server/lib/hash.js"; import { getPaymentSuccessSubject } from "./helpers.js"; +import { getPaymentSuccessBody } from "./helpers.js"; export async function sendPaymentSuccessMail( ausweis: VerbrauchsausweisWohnen, @@ -80,31 +81,6 @@ export async function sendPaymentSuccessMail( name: rechnung.empfaenger || "", }, bcc: "info@online-energieausweis.org", - html: `

Sehr geehrte/r ${user.name}, -
-
- vielen Dank für ihre Bestellung. Wir werden den Ausweis nun prüfen und Originalausweis und Rechnung nach Prüfung zuschicken. ${info} Die Ausstellung erfolgt nach aktuellem GEG und Ihr Ausweis wird beim DIBT registriert.

- Den Rechnungsbetrag haben Sie bereits bezahlt. Vielen Dank.

-

- Mit freundlichen Grüßen, -
- Dipl.-Ing. Jens Cornelsen -
-
- - IB Cornelsen -
- Katendeich 5A -
- 21035 Hamburg -
- www.online-energieausweis.org -
-
- - fon 040 · 209339850 -
- fax 040 · 209339859 -

`, + html: `

Sehr geehrte*r ${user.vorname} ${user.name},

` + getPaymentSuccessBody(ausweis, rechnung, ausweisart), }); }