Bezahlabschluss (Mollie)

This commit is contained in:
Moritz Utcke
2025-02-06 09:32:49 +07:00
parent bc55b21025
commit 64fa120ccd
14 changed files with 346 additions and 204 deletions

View File

@@ -5,13 +5,13 @@ export const createCaller = createCallerFactory({
"postleitzahlen": await import("../src/pages/api/postleitzahlen.ts"),
"aufnahme/[uid]": await import("../src/pages/api/aufnahme/[uid].ts"),
"aufnahme": await import("../src/pages/api/aufnahme/index.ts"),
"bilder/[uid]": await import("../src/pages/api/bilder/[uid].ts"),
"bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"),
"bilder/[uid]": await import("../src/pages/api/bilder/[uid].ts"),
"auth/access-token": await import("../src/pages/api/auth/access-token.ts"),
"auth/forgot-password": await import("../src/pages/api/auth/forgot-password.ts"),
"auth/refresh-token": await import("../src/pages/api/auth/refresh-token.ts"),
"rechnung": await import("../src/pages/api/rechnung/index.ts"),
"objekt": await import("../src/pages/api/objekt/index.ts"),
"rechnung": await import("../src/pages/api/rechnung/index.ts"),
"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"),
@@ -19,6 +19,7 @@ export const createCaller = createCallerFactory({
"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"),
"webhooks/mollie": await import("../src/pages/api/webhooks/mollie.ts"),
"objekt/[uid]/bilder": await import("../src/pages/api/objekt/[uid]/bilder.ts"),
"objekt/[uid]": await import("../src/pages/api/objekt/[uid]/index.ts"),
})

View File

@@ -4,13 +4,15 @@ import { api } from "astro-typesafe-api/client"
import { exclude } from "#lib/exclude.js";
import Cookies from "js-cookie";
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
import { AufnahmeClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisWohnenClient, } from "#components/Ausweis/types.js";
import { AufnahmeClient, BedarfsausweisWohnenClient, getAusweisartFromUUID, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisGewerbeClient, VerbrauchsausweisWohnenClient, } from "#components/Ausweis/types.js";
import { Enums } from "@ibcornelsen/database/client";
export async function verbrauchsausweisWohnenSpeichern(
ausweis: VerbrauchsausweisWohnenClient,
export async function ausweisSpeichern(
ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbeClient | BedarfsausweisWohnenClient,
objekt: ObjektClient,
aufnahme: AufnahmeClient,
bilder: (UploadedGebaeudeBild & { base64?: string })[]
bilder: (UploadedGebaeudeBild & { base64?: string })[],
ausweisart: Enums.Ausweisart
) {
if (objekt.uid) {
await api.objekt._uid.PATCH.fetch({
@@ -61,8 +63,21 @@ export async function verbrauchsausweisWohnenSpeichern(
aufnahme.uid = uid
}
let patchRoute: any;
let putRoute: any;
if (ausweisart = Enums.Ausweisart.VerbrauchsausweisWohnen) {
patchRoute = api["verbrauchsausweis-wohnen"]._uid.PATCH
putRoute = api["verbrauchsausweis-wohnen"].PUT
} else if (ausweisart = Enums.Ausweisart.VerbrauchsausweisGewerbe) {
patchRoute = api["verbrauchsausweis-gewerbe"]._uid.PATCH
putRoute = api["verbrauchsausweis-gewerbe"].PUT
} else if (ausweisart = Enums.Ausweisart.BedarfsausweisWohnen) {
patchRoute = api["bedarfsausweis-wohnen"]._uid.PATCH
putRoute = api["bedarfsausweis-wohnen"].PUT
}
if (ausweis.uid) {
await api["verbrauchsausweis-wohnen"]._uid.PATCH.fetch({
await patchRoute.fetch({
...exclude(ausweis, ["uid"])
}, {
params: {
@@ -73,7 +88,7 @@ export async function verbrauchsausweisWohnenSpeichern(
}
})
} else {
const { uid } = await api["verbrauchsausweis-wohnen"].PUT.fetch({
const { uid } = await putRoute.fetch({
ausweis,
uid_aufnahme: aufnahme.uid
}, {

View File

@@ -10,12 +10,14 @@
VerbrauchsausweisGewerbeClient,
VerbrauchsausweisWohnenClient,
} from "./types.js";
import { Enums } from "@ibcornelsen/database/client";
export let ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbeClient | BedarfsausweisWohnenClient;
export let bilder: UploadedGebaeudeBild[];
export let user: BenutzerClient;
export let objekt: ObjektClient;
export let aufnahme: AufnahmeClient;
export let ausweisart: Enums.Ausweisart
export let spaeterWeitermachen;
</script>
@@ -38,6 +40,7 @@
bind:user
bind:objekt
bind:aufnahme
{ausweisart}
></AusweisWeiter>
</div>
</div>

View File

@@ -1,14 +0,0 @@
<script lang="ts">
</script>
<div
class="w-full grid grid-cols-[min-content_1fr_min-content_min-content] grid-rows-[min_content_1fr] gap-x-2 self-start justify-self-end mt-8"
>
<button class="button justify-self-start">Zurück</button>
<div></div>
<button class="button">Speichern</button>
<button class="button">kostenpflichtig bestellen</button>
</div>

View File

@@ -6,19 +6,7 @@
import { BenutzerClient, RechnungClient } from "./types.js";
export let user: BenutzerClient;
let rechnung: RechnungClient = {
email: user.email,
empfaenger: user.vorname + " " + user.name,
strasse: user.adresse,
plz: user.plz,
ort: user.ort,
versand_empfaenger: user.vorname + " " + user.name,
versand_strasse: user.adresse,
versand_plz: user.plz,
versand_ort: user.ort,
telefon: user.telefon,
};
export let rechnung: Partial<RechnungClient>;

View File

@@ -3,9 +3,6 @@
import Inputlabel from "#components/labels/InputLabel.svelte";
import Verbrauchslabel from "#components/labels/VerbrauchsLabel.svelte";
import VerbrauchsHelpLabel from "#components/labels/VerbrauchsHelpLabel.svelte";
import Label from "../Label.svelte";
import moment from "moment";
import fuelList from "./brennstoffListe.js";
import { auditVerbrauchAbweichung } from "../Verbrauchsausweis/audits/VerbrauchAbweichung.js";
@@ -16,7 +13,7 @@
} from "./types.js";
import { addNotification } from "#components/Notifications/shared.js";
export let gebaeude: ObjektClient;
export let objekt: ObjektClient;
export let aufnahme: AufnahmeClient;
export let ausweis: VerbrauchsausweisWohnenClient;
@@ -43,14 +40,13 @@
"Dezember",
];
const startDate = moment(
aufnahme.erstellungsdatum || Date.now()
)
const startDate = moment(aufnahme.erstellungsdatum || Date.now())
.subtract(4, "years")
.subtract(6, "months");
const endDate = moment(
aufnahme.erstellungsdatum || Date.now()
).subtract(3, "years");
const endDate = moment(aufnahme.erstellungsdatum || Date.now()).subtract(
3,
"years"
);
for (let m = moment(startDate); m.isBefore(endDate); m.add(1, "month")) {
availableDates.push({
@@ -84,21 +80,28 @@
$: {
console.log(month, year);
if ((availableDates.filter(date => date.month === month && date.year === year).length === 0) && typeof month === "number" && typeof year === "number") {
if (
availableDates.filter(
(date) => date.month === month && date.year === year
).length === 0 &&
typeof month === "number" &&
typeof year === "number"
) {
addNotification({
message: "Monat nicht verfügbar.",
subtext: "Der ausgewählte Monat ist in diesem Jahr nicht verfügbar, bitte wählen sie einen neuen Start Monat.",
subtext:
"Der ausgewählte Monat ist in diesem Jahr nicht verfügbar, bitte wählen sie einen neuen Start Monat.",
dismissable: true,
type: "warning",
timeout: 0,
uid: "monat_nicht_verfuegbar",
selector: "select[name='energieverbrauch_zeitraum_monat']"
})
selector: "select[name='energieverbrauch_zeitraum_monat']",
});
}
}
$: abweichung = auditVerbrauchAbweichung(ausweis, gebaeude);
$: abweichung = auditVerbrauchAbweichung(ausweis, aufnahme);
</script>
<div
@@ -149,10 +152,14 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
</div>
<div class="help-label">
<HelpLabel>Sie haben die Möglichkeit neben der Hauptheizung die <b>Verbräuche weiterer Heizquellen</b>
(z.B. Einzelöfen, Kamin, Nachtspeicher, Wärmepumpe, zweiter Heizkessel etc.) einzugeben.
Dazu setzen Sie den Haken bei zusätzlicher Heizquelle. Eine weiterer Bereich zur Eingabe der
Verbräuche öffnet sich dann.</HelpLabel>
<HelpLabel
>Sie haben die Möglichkeit neben der Hauptheizung die <b
>Verbräuche weiterer Heizquellen</b
>
(z.B. Einzelöfen, Kamin, Nachtspeicher, Wärmepumpe, zweiter Heizkessel
etc.) einzugeben. Dazu setzen Sie den Haken bei zusätzlicher Heizquelle.
Eine weiterer Bereich zur Eingabe der Verbräuche öffnet sich dann.</HelpLabel
>
</div>
</div>
@@ -189,10 +196,13 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
</select>
<div class="help-label">
<HelpLabel>Bitte geben Sie hier den <b>Startmonat der ersten Verbrauchsperiode</b> ein. Es sind nur Monate auswählbar,
die im zulässigen Zeitraum (Endzeitpunkt von Jahr 3 darf nicht älter als 18 Monate sein) liegen. Wählen Sie ein
aktuellerses Jahr um alle Monate zu sehen.
</HelpLabel>
<HelpLabel
>Bitte geben Sie hier den <b
>Startmonat der ersten Verbrauchsperiode</b
> ein. Es sind nur Monate auswählbar, die im zulässigen Zeitraum
(Endzeitpunkt von Jahr 3 darf nicht älter als 18 Monate sein)
liegen. Wählen Sie ein aktuellerses Jahr um alle Monate zu sehen.
</HelpLabel>
</div>
</div>
@@ -218,8 +228,12 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
</select>
<div class="help-label">
<HelpLabel>Bitte geben Sie das <b>Startjahr der ersten Verbrauchsperiode</b> ein. Weitere Zeitangaben müssen nichht
gemacht werden, da alle 3 Verbrauchsjahre zusammenhängend sein sollen.</HelpLabel>
<HelpLabel
>Bitte geben Sie das <b
>Startjahr der ersten Verbrauchsperiode</b
> ein. Weitere Zeitangaben müssen nichht gemacht werden, da alle
3 Verbrauchsjahre zusammenhängend sein sollen.</HelpLabel
>
</div>
</div>
</div>
@@ -244,16 +258,24 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
<div class="help-label">
<HelpLabel>
<b>Heizöl:</b> Flüssiger fossiler Brennstoff.<br/>
<b>Erdgas:</b> Gasförmiger fossiler Brennstoff.<br/>
<b>Flüssiggas:</b> Wie Erdgas fossiler Brennstoff - im Flüssiggastank gelagert<br/>
<b>Braunkohle:</b> Fester fossiler Brennstoff<br/>
<b>Holz-Pellets:</b> Stäbchenförmige Pellets - erneuerbarer (nachwachsender) Brennstoff<br/>
<b>Holzhackschnitzel:</b>Wie Holz-Pellets<br/>
<b>Fernwärme, Nahwärme:</b> kommunales Wärmenetz - <strong>erfragen Sie
den Primärenergiefaktor bei Ihrem Energieversorger</strong> (meistens mit regenartivem Anteil)<br/>
<b>Strommix:</b> Meist bei Wärmepumpe oder Nachtspeicher.<br/>
<b>Koks:</b> stark kohlenstoffhaltiger fossiler Brennstoff.<br/>
<b>Heizöl:</b> Flüssiger fossiler Brennstoff.<br />
<b>Erdgas:</b> Gasförmiger fossiler Brennstoff.<br />
<b>Flüssiggas:</b> Wie Erdgas fossiler Brennstoff - im
Flüssiggastank gelagert<br />
<b>Braunkohle:</b> Fester fossiler Brennstoff<br />
<b>Holz-Pellets:</b> Stäbchenförmige Pellets - erneuerbarer
(nachwachsender) Brennstoff<br />
<b>Holzhackschnitzel:</b>Wie Holz-Pellets<br />
<b>Fernwärme, Nahwärme:</b> kommunales Wärmenetz -
<strong
>erfragen Sie den Primärenergiefaktor bei Ihrem
Energieversorger</strong
>
(meistens mit regenartivem Anteil)<br />
<b>Strommix:</b> Meist bei Wärmepumpe oder Nachtspeicher.<br
/>
<b>Koks:</b> stark kohlenstoffhaltiger fossiler Brennstoff.<br
/>
</HelpLabel>
</div>
</div>
@@ -276,9 +298,10 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
<div class="help-label">
<HelpLabel>
Bitte geben Sie die Einheit ein. Die Liste passt sich entsprechend des ausgeählten Brennstoffes an.
Erdgas wird meist auf der Abrechnung in kWh ausgewiesen. Heizöl liegt meistens in
Litern vor. Pellets oder Brennholz in kg.
Bitte geben Sie die Einheit ein. Die Liste passt sich
entsprechend des ausgeählten Brennstoffes an. Erdgas wird
meist auf der Abrechnung in kWh ausgewiesen. Heizöl liegt
meistens in Litern vor. Pellets oder Brennholz in kg.
</HelpLabel>
</div>
</div>
@@ -397,8 +420,13 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
</div>
<div class="help-label">
<HelpLabel>Hier sind die <b>Verbräuche einer zusätzlichen Heizquelle</b>
(z.B. Einzelöfen, Kamin, Nachtspeicher, Wärmepumpe, zweiter Heizkessel etc.) einzugeben</HelpLabel>
<HelpLabel
>Hier sind die <b
>Verbräuche einer zusätzlichen Heizquelle</b
>
(z.B. Einzelöfen, Kamin, Nachtspeicher, Wärmepumpe, zweiter Heizkessel
etc.) einzugeben</HelpLabel
>
</div>
</div>
@@ -427,16 +455,24 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
<div class="help-label">
<HelpLabel>
<b>Heizöl:</b> Flüssiger fossiler Brennstoff.<br/>
<b>Erdgas:</b> Gasförmiger fossiler Brennstoff.<br/>
<b>Flüssiggas:</b> Wie Erdgas fossiler Brennstoff - im Flüssiggastank gelagert<br/>
<b>Braunkohle:</b> Fester fossiler Brennstoff<br/>
<b>Holz-Pellets:</b> Stäbchenförmige Pellets - erneuerbarer (nachwachsender) Brennstoff<br/>
<b>Holzhackschnitzel:</b>Wie Holz-Pellets<br/>
<b>Fernwärme, Nahwärme:</b> kommunales Wärmenetz - <strong>erfragen Sie
den Primärenergiefaktor bei Ihrem Energieversorger</strong> (meistens mit regenartivem Anteil)<br/>
<b>Strommix:</b> Meist bei Wärmepumpe oder Nachtspeicher.<br/>
<b>Koks:</b> stark kohlenstoffhaltiger fossiler Brennstoff.<br/>
<b>Heizöl:</b> Flüssiger fossiler Brennstoff.<br />
<b>Erdgas:</b> Gasförmiger fossiler Brennstoff.<br />
<b>Flüssiggas:</b> Wie Erdgas fossiler Brennstoff - im
Flüssiggastank gelagert<br />
<b>Braunkohle:</b> Fester fossiler Brennstoff<br />
<b>Holz-Pellets:</b> Stäbchenförmige Pellets -
erneuerbarer (nachwachsender) Brennstoff<br />
<b>Holzhackschnitzel:</b>Wie Holz-Pellets<br />
<b>Fernwärme, Nahwärme:</b> kommunales Wärmenetz -
<strong
>erfragen Sie den Primärenergiefaktor bei Ihrem
Energieversorger</strong
>
(meistens mit regenartivem Anteil)<br />
<b>Strommix:</b> Meist bei Wärmepumpe oder
Nachtspeicher.<br />
<b>Koks:</b> stark kohlenstoffhaltiger fossiler
Brennstoff.<br />
</HelpLabel>
</div>
</div>
@@ -462,9 +498,11 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
<div class="help-label">
<HelpLabel>
Bitte geben Sie die Einheit ein. Die Liste passt sich entsprechend des ausgeählten Brennstoffes an.
Erdgas wird meist auf der Abrechnung in kWh ausgewiesen. Heizöl liegt meistens in
Litern vor. Pellets oder Brennholz in kg.
Bitte geben Sie die Einheit ein. Die Liste passt sich
entsprechend des ausgeählten Brennstoffes an. Erdgas
wird meist auf der Abrechnung in kWh ausgewiesen. Heizöl
liegt meistens in Litern vor. Pellets oder Brennholz in
kg.
</HelpLabel>
</div>
</div>

View File

@@ -159,7 +159,8 @@
}
</script>
<div id="skala" class="bg-white grid grid-cols-1 gap-x-8 gap-y-4 p-4
<div id="skala" class="bg-white grid grid-cols-1 gap-x-8 gap-y-4 p-4">
<div class="w-full rounded-lg border-gray/35 border-2 relative px-4">
<PerformanceScore
@@ -177,8 +178,6 @@
<ProgressBar progress={0} />
</div>
</div>
<form id="formInput-1" on:submit={ausweisAbschicken} name="ausweis" data-test="ausweis">
<div id="formular-box" class="formular-boxen ring-0">
@@ -1009,8 +1008,9 @@ title="Eingabe der Gebäudeadresse - Angaben zu Wohnfläche, Keller und Dachgesc
bind:ausweis
bind:images
bind:user
bind:gebaeude
bind:gebaeude_aufnahme_allgemein
bind:objekt
bind:aufnahme
ausweisart={Enums.Ausweisart.BedarfsausweisWohnen}
>
<BilderZusatzsysteme
{ausweis}

View File

@@ -12,22 +12,39 @@
import { Enums } from "@ibcornelsen/database/client";
import { dialogs } from "svelte-dialogs";
import LoginDialog from "#components/LoginDialog.svelte";
import { PRICES } from "#lib/constants.js";
import { API_ACCESS_TOKEN_COOKIE_NAME, PRICES } from "#lib/constants.js";
import Cookies from "js-cookie";
import {
AufnahmeClient,
BenutzerClient,
getAusweisartFromUUID,
ObjektClient,
RechnungClient,
VerbrauchsausweisWohnenClient,
} from "#components/Ausweis/types.js";
import { validateAccessTokenClient } from "src/client/lib/validateAccessToken.js";
import ButtonZurueckSpeichernKaufabschluss from "#components/Ausweis/ButtonZurueckSpeichernKaufabschluss.svelte";
import { api } from "astro-typesafe-api/client";
import A10WaermequellenAnlagentechnikTrinkwarmwasser from "#components/Tabellen/A10WaermequellenAnlagentechnikTrinkwarmwasser.svelte";
export let user: BenutzerClient;
export let ausweis: VerbrauchsausweisWohnenClient;
export let aufnahme: AufnahmeClient;
export let objekt: ObjektClient;
let services = [
let rechnung: Partial<RechnungClient> = {
email: user.email,
empfaenger: user.vorname + " " + user.name,
strasse: user.adresse,
plz: user.plz,
ort: user.ort,
versand_empfaenger: user.vorname + " " + user.name,
versand_strasse: user.adresse,
versand_plz: user.plz,
versand_ort: user.ort,
telefon: user.telefon,
}
let services: { name: string, id: Enums.Service, price: number, selected: boolean }[] = [
{
name: "Qualitätsdruck per Post (zusätzlich zur PDF Version)",
id: Enums.Service.Qualitaetsdruck,
@@ -54,7 +71,7 @@
},
];
export let selectedPaymentType: Bezahlmethoden =
export let bezahlmethode: Bezahlmethoden =
Enums.Bezahlmethoden.paypal;
let prices: number[] = [];
@@ -93,6 +110,38 @@
window.location.href = `/kaufabschluss?uid=${ausweis.uid}`;
}
async function bestellen() {
const ausweisart = getAusweisartFromUUID(ausweis.uid) as Enums.Ausweisart;
try {
const { uid, checkout_url } = await api.rechnung.PUT.fetch({
ausweisart,
bezahlmethode,
services: services.filter(service => service.selected).map(service => service.id),
email: rechnung.email,
empfaenger: rechnung.empfaenger,
strasse: rechnung.strasse,
plz: rechnung.plz,
ort: rechnung.ort,
versand_empfaenger: rechnung.versand_empfaenger,
versand_strasse: rechnung.versand_strasse,
versand_plz: rechnung.versand_plz,
versand_ort: rechnung.versand_ort,
telefon: rechnung.telefon,
ausweis_uid: ausweis.uid
}, {
headers: {
Authorization: `Bearer ${Cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)}`
}
})
window.location.href = checkout_url;
} catch(e) {
console.log(e);
}
}
</script>
<div
@@ -121,7 +170,7 @@
</div>
</div>
<form id="formInput-2" on:submit={speichern}>
<div id="formInput-2">
<div id="formular-box" class="formular-boxen ring-0">
<Bereich
bereich="1"
@@ -131,11 +180,11 @@
>
<Bereich bereich="2" title="Rechnungsadresse">
<Rechnungsadresse bind:user /></Bereich
<Rechnungsadresse bind:user bind:rechnung /></Bereich
>
<Bereich bereich="3" title="Bezahlmethode">
<Bezahlung bind:selectedPaymentType /></Bereich
<Bezahlung bind:selectedPaymentType={bezahlmethode} /></Bereich
>
<div class="grid grid-cols-2 gap-x-6 my-6">
@@ -193,8 +242,8 @@
<div>:</div>
<div class="justify-self-end">
<img
src="images/{selectedPaymentType}.png"
alt={selectedPaymentType}
src="images/{bezahlmethode}.png"
alt={bezahlmethode}
/>
</div>
</div>
@@ -202,7 +251,18 @@
</div>
</div>
<ButtonZurueckSpeichernKaufabschluss />
<div
class="w-full grid grid-cols-[min-content_1fr_min-content_min-content] grid-rows-[min_content_1fr] gap-x-2 self-start justify-self-end mt-8"
>
<button class="button justify-self-start">Zurück</button>
<div></div>
<button class="button">Speichern</button>
<button class="button" on:click={bestellen}>kostenpflichtig bestellen</button>
</div>
<div class="bereich-box pr-12 mt-6">
<Pruefung
@@ -332,7 +392,7 @@
</div>
<!-- <ButtonZurueckSpeichernKaufabschluss bind:ausweis bind:aufnahme bind:objekt bind:bilder bind:user /> -->
</form>
</div>
<style lang="postcss">
h3 {

View File

@@ -6,7 +6,6 @@
import ButtonSpaeterHilfe from "#components/Ausweis/ButtonSpaeterHilfe.svelte";
import ButtonWeiterHilfe from "#components/Ausweis/ButtonWeiterHilfe.svelte";
import Ausweisart from "#components/Ausweis/Ausweisart.svelte";
import objektDaten from "#components/Ausweis/GebaeudeDaten.svelte";
import Warmwasseranteil from "#components/Ausweis/Warmwasseranteil.svelte";
import ThermischeKuehlung from "#components/Ausweis/ThermischeKuehlung.svelte";
import LueftungundLeerstand from "#components/Ausweis/LueftungundLeerstand.svelte";
@@ -20,6 +19,7 @@
import { AufnahmeClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisGewerbeClient } from "#components/Ausweis/types.js";
import { BenutzerClient } from "#components/Ausweis/types.js";
import GebaeudeDaten from "#components/Ausweis/GebaeudeDaten.svelte";
import { Enums } from "@ibcornelsen/database/client";
export let ausweis: VerbrauchsausweisGewerbeClient;
export let user: BenutzerClient = {} as BenutzerClient;
@@ -192,6 +192,7 @@
bind:user
bind:objekt
bind:aufnahme
ausweisart={Enums.Ausweisart.VerbrauchsausweisGewerbe}
>
</ButtonWeiterHilfe>

View File

@@ -1,75 +1,30 @@
<script lang="ts">
import { ausweisSpeichern } from "#client/lib/ausweisSpeichern.js";
import { validateAccessTokenClient } from "#client/lib/validateAccessToken.js";
import { verbrauchsausweisWohnenSpeichern } from "#client/lib/verbrauchsausweisWohnenSpeichern.js";
import { AufnahmeClient, BedarfsausweisWohnenClient, BenutzerClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisGewerbeClient, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types.js";
import { addNotification } from "#components/Notifications/index.js";
import Overlay from "#components/Overlay.svelte";
import EmbeddedAuthFlowModule from "#modules/EmbeddedAuthFlowModule.svelte";
import { api } from "astro-typesafe-api/client"
import { Enums } from "@ibcornelsen/database/client";
export let objekt: ObjektClient;
export let bilder: UploadedGebaeudeBild[];
export let ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbeClient | BedarfsausweisWohnenClient;
export let user: BenutzerClient;
export let aufnahme: AufnahmeClient;
export let ausweisart: Enums.Ausweisart
async function ausweisSpeichern() {
// Um einen Ausweis zu speichern müssen wir eingeloggt sein, andernfalls wird die API den call ablehnen.
// Wir prüfen also ob wir eingeloggt sind und leiten den Nutzer ggf. auf die Login Seite weiter.
async function ausweisAbschicken() {
if (!await validateAccessTokenClient()) {
loginOverlayHidden = false;
return
}
loginOverlayHidden = true
loginOverlayHidden = true;
const result = await ausweisSpeichern(ausweis, objekt, aufnahme, bilder, ausweisart);
// Wir speichern den Ausweis ab und leiten auf die "ausweis-gespeichert" Seite weiter.
try {
const response = await verbrauchsausweisWohnenSpeichern(ausweis,
objekt,
aufnahme,
bilder)
if (response !== null) {
// Falls der Nutzer zurück navigiert, sollte er wieder auf seinen Vorgang kommen.
// Sonst müsste er alles neu eingeben...
ausweis.uid = response.uid_ausweis;
objekt.uid = response.uid_objekt;
aufnahme.uid = response.uid_aufnahme;
return true
}
} catch (e: any) {
console.log(e);
await api.ticket.PUT.fetch({
titel: "Ausweis konnte nicht gespeichert werden",
beschreibung: e.stack,
email: user.email ?? "",
metadata: JSON.stringify({
ausweis,
gebaeude: objekt
})
})
}
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 false
}
async function ausweisAbschicken() {
const result = await ausweisSpeichern();
if (result === true) {
if (result !== null) {
window.history.pushState(
{},
"",

View File

@@ -50,7 +50,6 @@
ObjektClient,
AufnahmeClient,
} from "#components/Ausweis/types.js";
import { verbrauchsausweisWohnenSpeichern } from "src/client/lib/verbrauchsausweisWohnenSpeichern.js";
import { Enums } from "@ibcornelsen/database/client";
// TODO: Vom Server sollte ein volles Objekt kommen, dass alle Subobjekte enthält, weil es sonst zu Problemen führen kann
@@ -62,26 +61,27 @@
export let bilder: UploadedGebaeudeBild[] = []
async function spaeterWeitermachen() {
const result = await verbrauchsausweisWohnenSpeichern(
ausweis,
objekt,
aufnahme,
bilder
);
// TODO FIX
// const result = await ausweisSpeichern(
// ausweis,
// objekt,
// aufnahme,
// bilder
// );
if (result !== null) {
// Falls der Nutzer zurück navigiert, sollte er wieder auf seinen Vorgang kommen.
// Sonst müsste er alles neu eingeben...
ausweis.uid = result.uid_ausweis;
objekt.uid = result.uid_objekt;
aufnahme.uid = result.uid_aufnahme;
window.history.pushState(
{},
"",
`${location.pathname}?uid=${result.uid_ausweis}`
);
speichernOverlayHidden = false;
}
// if (result !== null) {
// // Falls der Nutzer zurück navigiert, sollte er wieder auf seinen Vorgang kommen.
// // Sonst müsste er alles neu eingeben...
// ausweis.uid = result.uid_ausweis;
// objekt.uid = result.uid_objekt;
// aufnahme.uid = result.uid_aufnahme;
// window.history.pushState(
// {},
// "",
// `${location.pathname}?uid=${result.uid_ausweis}`
// );
// speichernOverlayHidden = false;
// }
}
function automatischAusfüllen() {
@@ -118,27 +118,27 @@
}
async function ausweisAbschicken(e: SubmitEvent) {
if (e && e.preventDefault) e.preventDefault();
const result = await verbrauchsausweisWohnenSpeichern(
ausweis,
objekt,
aufnahme,
bilder
);
// if (e && e.preventDefault) e.preventDefault();
// const result = await ausweisSpeichern(
// ausweis,
// objekt,
// aufnahme,
// bilder
// );
if (result !== null) {
// Falls der Nutzer zurück navigiert, sollte er wieder auf seinen Vorgang kommen.
// Sonst müsste er alles neu eingeben...
ausweis.uid = result.uid_ausweis;
objekt.uid = result.uid_objekt;
aufnahme.uid = result.uid_aufnahme;
window.history.pushState(
{},
"",
`${location.pathname}?uid=${result.uid_ausweis}`
);
// window.location.href = `/kundendaten?uid=${result.uid_ausweis}`;
}
// if (result !== null) {
// // Falls der Nutzer zurück navigiert, sollte er wieder auf seinen Vorgang kommen.
// // Sonst müsste er alles neu eingeben...
// ausweis.uid = result.uid_ausweis;
// objekt.uid = result.uid_objekt;
// aufnahme.uid = result.uid_aufnahme;
// window.history.pushState(
// {},
// "",
// `${location.pathname}?uid=${result.uid_ausweis}`
// );
// // window.location.href = `/kundendaten?uid=${result.uid_ausweis}`;
// }
}
let waitOverlayHidden = true;
@@ -229,7 +229,7 @@ const ausweisart: Enums.Ausweisart = "VerbrauchsausweisWohnen"
bereich="C"
title="Eingabe von 3 zusammenhängenden Verbrauchsjahren"
><Verbrauch
bind:gebaeude={objekt}
bind:objekt={objekt}
bind:aufnahme={aufnahme}
bind:ausweis
/></Bereich
@@ -300,6 +300,7 @@ const ausweisart: Enums.Ausweisart = "VerbrauchsausweisWohnen"
bind:user
bind:objekt
bind:aufnahme
ausweisart={Enums.Ausweisart.VerbrauchsausweisWohnen}
>
</ButtonWeiterHilfe>

View File

@@ -8,6 +8,7 @@ import {
authorizationHeaders,
authorizationMiddleware,
} from "#lib/middleware/authorization.js";
import { UUidWithPrefix } from "#components/Ausweis/types.js";
export const PUT = defineApiRoute({
meta: {
@@ -20,11 +21,12 @@ export const PUT = defineApiRoute({
input: z
.object({
ausweisart: z.nativeEnum(Enums.Ausweisart),
uid: z.string().uuid(),
ausweis_uid: UUidWithPrefix,
})
.merge(
RechnungSchema.omit({
benutzer_id: true,
aufnahme_id: true,
bezahlt_am: true,
erstellt_am: true,
id: true,
@@ -37,7 +39,7 @@ export const PUT = defineApiRoute({
),
output: z.object({
checkout_url: z.string(),
uid: z.string().uuid(),
uid: UUidWithPrefix,
}),
headers: authorizationHeaders,
middleware: authorizationMiddleware,
@@ -45,7 +47,7 @@ export const PUT = defineApiRoute({
// Wir erstellen eine Mollie Payment Referenz und eine neue Rechnung in unserer Datenbank, daraufhin geben
// wir eine Checkout URL zurück auf die der Nutzer weitergeleitet werden kann.
const { uid, ausweisart, bezahlmethode, services } = input;
const { ausweis_uid, ausweisart, bezahlmethode, services } = input;
// TODO: Services Implementieren
@@ -64,7 +66,7 @@ export const PUT = defineApiRoute({
// Wir müssen überprüfen, ob dem Nutzer der Ausweis tatsächlich gehört.
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
where: {
uid,
uid: ausweis_uid,
},
});
@@ -116,7 +118,7 @@ export const PUT = defineApiRoute({
method: input.bezahlmethode as PaymentMethod,
description: "Verbrauchsausweis Wohnen 2016",
redirectUrl: "https://ibcornelsen.de/payment/success",
webhookUrl: "http://api.ibcornelsen.de/v1/webhooks/mollie",
webhookUrl: `http://ibcornelsen.de/api/webhooks/mollie?uid=${rechnung.uid}`,
});
const checkoutUrl = payment.getCheckoutUrl();

View File

@@ -0,0 +1,63 @@
/**
* Der Webhook wird von Mollie ausgelöst, wenn sich der Status einer Transaktion ändert.
* https://docs.mollie.com/overview/webhooks
* @param _props { id: string }
*/
import { z } from "zod";
import { Enums, prisma } from "@ibcornelsen/database/server";
import { mollieClient } from "#lib/mollie.js";
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
export const POST = defineApiRoute({
input: z.object({
id: z.string(),
}),
output: z.void(),
async fetch(input, ctx) {
const { id } = input;
// Wir holen uns die Transaktion von Mollie.
const payment = await mollieClient.payments.get(id);
const metadata = payment.metadata as { rechnung_uid: string }
if (!payment) {
throw new APIError({
code: "NOT_FOUND",
message: "Transaktion nicht gefunden.",
});
}
if (!metadata.rechnung_uid) {
throw new APIError({
code: "BAD_REQUEST",
message: "Rechnung UID nicht gefunden.",
});
}
// Wir holen uns die Rechnung aus unserer Datenbank.
const rechnung = await prisma.rechnung.findUnique({
where: {
uid: metadata.rechnung_uid,
},
});
if (!rechnung) {
throw new APIError({
code: "NOT_FOUND",
message: "Rechnung nicht gefunden.",
});
}
// Wir aktualisieren den Status der Rechnung.
await prisma.rechnung.update({
where: {
id: rechnung.id,
},
data: {
status: payment.status as Enums.Rechnungsstatus,
transaktions_referenz: payment.id,
},
});
},
});

View File

@@ -1,10 +1,39 @@
---
import { prisma } from "@ibcornelsen/database/server";
import Layout from "../../layouts/Layout.astro";
import { createCaller } from "../../astro-typesafe-api-caller.js";
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants";
const { uid } = Astro.params;
const caller = createCaller(Astro)
const user = await caller.user.self.GET.fetch(undefined, {
headers: {
Authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
}
});
if (!uid || !user) {
return Astro.redirect("/")
}
const rechnung = await prisma.rechnung.findUnique({
where: {
uid: uid,
benutzer_id: user.id
}
})
if (!rechnung) {
return Astro.redirect("/404")
}
---
<Layout title="Zahlung Erfolgreich - IBCornelsen">
Supa! Hat geklappt ne!
{rechnung.uid}
</Layout>