Kaufabschluss Update

This commit is contained in:
Moritz Utcke
2024-02-17 16:34:12 +07:00
parent 06b423a22e
commit c4a7c48511
9 changed files with 692 additions and 572 deletions

View File

@@ -244,7 +244,10 @@ describe("Verbrauchsausweis erstellen Schritt 1", () => {
// Der Ausweis sollte jetzt schon erstellt worden sein und wir sollten auf die kundendaten seite weitergeleitet worden sein. // Der Ausweis sollte jetzt schon erstellt worden sein und wir sollten auf die kundendaten seite weitergeleitet worden sein.
cy.url().should("contain", "/kundendaten"); cy.url().should("contain", "/kundendaten");
cy.wait(1000)
// Wir füllen jetzt die Kundendaten aus. // Wir füllen jetzt die Kundendaten aus.
cy.get("select[name='anrede']").select(Math.random() > 0.5 ? "Herr" : "Frau");
cy.get("input[name='vorname']").should("contain.value", vorname); cy.get("input[name='vorname']").should("contain.value", vorname);
cy.get("input[name='name']").should("contain.value", nachname); cy.get("input[name='name']").should("contain.value", nachname);
cy.get("input[name='email']").should("contain.value", email); cy.get("input[name='email']").should("contain.value", email);

View File

@@ -4,8 +4,8 @@
<div class="flex flex-col relative"> <div class="flex flex-col relative">
<div class="progress-section"> <div class="progress-section">
<div class="w-[85%] left-9 bg-gray-100 absolute h-3 rounded-lg"> <div class="w-full bg-gray-100 absolute h-3 rounded-lg">
<div class="bg-green-600 left-2 h-3 absolute" style={`width: ${progress}%;`}></div> <div class="bg-green-600 left-0 h-3 absolute" style={`width: ${progress}%;`}></div>
</div> </div>
<span>1</span> <span>1</span>
<span>2</span> <span>2</span>
@@ -14,14 +14,14 @@
<div class="flex flex-row justify-between"> <div class="flex flex-row justify-between">
<p>Gebäudedaten</p> <p>Gebäudedaten</p>
<p>Kundendaten</p> <p>Prüfung</p>
<p>Kaufabschluss</p> <p>Kaufabschluss</p>
</div> </div>
</div> </div>
<style> <style>
.progress-section { .progress-section {
@apply relative items-center flex flex-row justify-between px-8; @apply relative items-center flex flex-row justify-between px-0;
} }
.progress-section span { .progress-section span {

View File

@@ -0,0 +1,36 @@
<script lang="ts">
import { get_current_component } from "svelte/internal";
const component = get_current_component();
export let image: string;
export let name: string;
export let description: string;
export let price: number;
export let quantity: number;
export let removable: boolean = true;
export let maxQuantity: number = Infinity;
</script>
<div class="flex flex-row justify-between items-center">
<div class="flex flex-row gap-4">
<img src={image} class="w-24" alt="">
<div class="flex flex-col">
<h4 class="font-semibold">{name}</h4>
<span class="opacity-75">{description}</span>
<span class="font-semibold text-sm">{price * quantity}</span>
</div>
</div>
<div class="join">
<button class="btn btn-sm join-item" disabled={!removable && quantity == 1} on:click={() => {
quantity--
if ((quantity == 0) && removable) {
component.$destroy();
}
}}>-</button>
<button class="btn btn-sm join-item btn-ghost">{quantity}</button>
<button class="btn btn-sm join-item" disabled={quantity <= maxQuantity} on:click={() => quantity++}>+</button>
</div>
</div>

View File

@@ -1,204 +0,0 @@
<script lang="ts">
import { PRICES } from "#lib/constants";
import type { BedarfsausweisWohnen, Enums, VerbrauchsausweisGewerbe, VerbrauchsausweisWohnen } from "@ibcornelsen/database/client";
export let ausweis: VerbrauchsausweisWohnen | VerbrauchsausweisGewerbe | BedarfsausweisWohnen;
const prices = PRICES[ausweis.ausweisart];
export let services: { name: string, price: number, selected: boolean, id: Enums.Service }[] = [];
let basePrice: number = prices[0];
$: price =
basePrice + services.reduce((acc, service) => (service.selected && acc + service.price) || acc, 0)
</script>
<div>
<div class="yellow-box flex flex-col gap-4">
<div class="flex flex-col gap-2 test-box">
<strong>A - Prüfung der Ausweisart</strong>
<div>
<span>Vermietung, Verkauf oder sonstiges</span>
<span>Baujahr Heizung nicht kleiner als Baujahr Gebäude</span><span
>Baujahr nach 1977 oder saniert oder mehr als 4 Wohneinheiten</span
><span>Heizung min. 3 Jahre alt</span><span
>Verbrauchsausweis zulässig</span
>
</div>
</div>
<div class="flex flex-col gap-2 test-box">
<strong>B - Prüfung der Adresse, Wohnfläche, Keller und Dach</strong
>
<div>
<span>PLZ gültig</span><span>Klimafaktorern</span><span
>Wohnfläche passt zu Wohneinheiten</span
>
</div>
</div>
<div class="flex flex-col gap-2 test-box">
<strong>C - Prüfung der Verbrauchsangaben</strong>
<div>
<span>Verbrauchsmenge schlüssig</span><span
>Verbrauchsabweichung im Rahmen</span
><span>Endenergieverbrauch schlüssig</span>
</div>
</div>
<div class="flex flex-col gap-2 test-box">
<strong
>D - Prüfung Warmwasser und alternative Energieversorgung</strong
>
<div>
<span>Warmwasseranteil schlüssig</span>
</div>
</div>
<div class="flex flex-col gap-2 test-box">
<strong
>E - Prüfung von Gebäudetyp, Lüftung, Kühlung und Leerstand</strong
>
<div>
<span>Leerstand nicht größer als 30%</span>
</div>
</div>
<div class="flex flex-col gap-2 test-box">
<strong
>F - Prüfung des Sanierungsstandes und der Gebäudebilder</strong
>
<div>
<span>Mindestens ein Bild pro Abschnitt vorhanden</span><span
>Angaben zum Sanierungsstand vorhanden</span
><span
>Bei Baujahr vor 1978 Dach oder Geschossdecke min. 12 cm gedämmt</span
>
</div>
</div>
</div>
<hr />
<div class="yellow-box flex flex-col gap-4">
<table>
<tr>
<td><strong>Produkt:</strong></td>
<td
><div class="bg-white p-2 border border-gray-300">
Verbrauchsausweis
</div></td
>
</tr>
<tr>
<td><strong>Beschreibung:</strong></td>
<td>
<div class="bg-white p-2 border border-gray-300">
Registrierung beim DiBt<br />
Prüfung durch Diplom Ingenieur<br />
Energieausweis Vorschau als PDF<br />
</div>
</td>
</tr>
<tr>
<td>Netto-Preis</td>
<td
><div class="bg-white p-2 border border-gray-300">
{(price * 0.81).toFixed(2) + "€"}
</div></td
>
</tr>
<tr>
<td>19% gesetzl. MwSt.</td>
<td
><div class="bg-white p-2 border border-gray-300">
{(price * 0.19).toFixed(2) + "€"}
</div></td
>
</tr>
<tr>
<td>Preis inkl. MwSt.</td>
<td
><div class="bg-white p-2 border border-gray-300">
<strong>{price + "€"}</strong>
</div>
</td>
</tr>
</table>
</div>
<hr />
<div class="yellow-box flex flex-col gap-4">
<strong
>Hiermit bestelle ich folgende Version des Energieausweises:<br
/></strong
>
<table>
<tr>
<td
>Verbrauchsausweis online für {prices[0]} € inkl. MwSt. als PDF
per E-Mail</td
>
<td
><input
type="radio"
bind:group={basePrice}
value={prices[0]}
name="Preis"
checked
/>
</td>
</tr>
<tr>
<td
>Verbrauchsausweis online inkl. Beratung für {prices[1]}
€ inkl. MwSt. als PDF per E-Mail</td
>
<td
><input
type="radio"
bind:group={basePrice}
value={prices[1]}
name="Preis"
/>
</td>
</tr><tr>
<td
>Verbrauchsausweis offline für {prices[2]} € inkl. MwSt. als
PDF per E-Mail (Sie schicken uns 3 Verbrauchsabrechnungen)</td
>
<td
><input
type="radio"
bind:group={basePrice}
value={prices[2]}
name="Preis"
/></td
>
</tr>
</table>
</div>
<hr />
<div class="yellow-box flex flex-col gap-4">
<table>
<strong>Zusatzleistungen:<br /></strong>
{#each services as service}
<tr>
<td
>{service.name}</td
>
<td
><input
type="checkbox"
class="IGZusatzleistung"
bind:checked={service.selected}
/>
</td>
</tr>
{/each}
</table>
</div>
</div>
<style>
.test-box div {
@apply flex flex-col gap-1.5;
}
</style>

View File

@@ -86,7 +86,7 @@ const schema = JSON.stringify({
<Header /> <Header />
<main class="grid gap-6 p-6 grid-cols-[2fr,8fr] max-w-[1920px] w-full bg-base-100"> <main class="grid gap-6 p-6 grid-cols-[2fr,8fr] max-w-[1920px] w-full bg-base-100">
<SidebarLeft></SidebarLeft> <SidebarLeft></SidebarLeft>
<article class="bg-base-200 rounded-lg border border-base-300"> <article class="bg-base-200 rounded-lg border border-base-300 h-min">
<slot /> <slot />
</article> </article>
</main> </main>

View File

@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { BenutzerClient, GebaeudeClient, UploadedGebaeudeBild, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types"; import { BenutzerClient, GebaeudeClient, UploadedGebaeudeBild, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
import { addNotification, updateNotification } from "@ibcornelsen/ui"; import { addNotification, updateNotification } from "@ibcornelsen/ui";
import { validateAccessTokenClient } from "#client/lib/validateAccessToken"; import { validateAccessTokenClient } from "../../client/lib/validateAccessToken";
import { client } from "src/trpc"; import { client } from "src/trpc";
import EmbeddedAuthFlowModule from "#modules/EmbeddedAuthFlowModule.svelte"; import EmbeddedAuthFlowModule from "#modules/EmbeddedAuthFlowModule.svelte";
import Overlay from "#components/Overlay.svelte"; import Overlay from "#components/Overlay.svelte";

View File

@@ -0,0 +1,370 @@
<script lang="ts">
import HelpLabel from "#components/HelpLabel.svelte";
import ZipSearch from "../components/PlzSuche.svelte";
import Label from "../components/Label.svelte";
import type {
BedarfsausweisWohnen,
Benutzer,
Bezahlmethoden,
VerbrauchsausweisGewerbe,
VerbrauchsausweisWohnen,
} from "@ibcornelsen/database/client";
import { Enums } from "@ibcornelsen/database/client";
import PaymentOption from "#components/PaymentOption.svelte";
import { client } from "src/trpc";
import type { inferProcedureInput } from "@trpc/server";
import type { AppRouter } from "@ibcornelsen/api";
import CheckoutItem from "#components/CheckoutItem.svelte";
export let user: Benutzer;
export let ausweis:
| VerbrauchsausweisWohnen
| BedarfsausweisWohnen
| VerbrauchsausweisGewerbe;
let rechnung: inferProcedureInput<
AppRouter["v1"]["rechnungen"]["erstellen"]
> = {};
let services = [
{
name: "Qualitätsdruck per Post (zusätzlich zur PDF Version) für 9€ inkl. MwSt.",
id: Enums.Service.Qualitaetsdruck,
price: 9,
selected: false,
},
{
name: "Aushang (für öffentliche Gebäude gesetzlich vorgeschrieben) für 10€ inkl. MwSt.",
id: Enums.Service.Aushang,
price: 10,
selected: false,
},
{
name: "Same Day Service (Bestellung Werktags vor 12:00 Uhr - Ausstellung bis 18:00 Uhr am gleichen Tag) für 29€ inkl. MwSt.",
id: Enums.Service.SameDay,
price: 29,
selected: false,
},
{
name: "Telefonische Energieeffizienzberatung für 75€ inkl. MwSt.",
id: Enums.Service.Telefonberatung,
price: 75,
selected: false,
},
];
export let selectedPaymentType: Bezahlmethoden =
Enums.Bezahlmethoden.PAYPAL;
let agbAkzeptiert: boolean;
let datenschutzAkzeptiert: boolean;
async function createPayment(e: SubmitEvent) {
e.preventDefault();
const response = await client.v1.rechnungen.erstellen.mutate({
...rechnung,
ausweisart: ausweis.ausweisart,
uid: ausweis.uid,
bezahlmethode: selectedPaymentType,
services: services
.filter((service) => service.selected)
.map((service) => service.id),
});
window.location.href = response.checkout_url;
}
</script>
<div class="grid grid-cols-[2fr_1fr] gap-4 h-full">
<div>
<h3 class="font-semibold">Ansprechpartner</h3>
<div class="rounded-lg border p-4 border-base-300 bg-base-100">
<div class="grid grid-cols-3 gap-4">
<!-- Anrede -->
<div>
<Label>Anrede *</Label>
<div>
<select name="anrede" bind:value={user.anrede}>
<option>bitte auswählen</option>
<option value="Herr">Herr</option>
<option value="Frau">Frau</option>
</select>
</div>
</div>
<!-- Vorname -->
<div>
<Label>Vorname *</Label>
<input
name="vorname"
type="text"
bind:value={user.vorname}
required
/>
</div>
<!-- Nachname -->
<div>
<Label>Nachname *</Label>
<input
name="name"
type="text"
bind:value={user.name}
required
/>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<!-- Telefon -->
<div>
<Label>Telefon</Label>
<input
name="telefon"
bind:value={user.telefon}
type="text"
/>
</div>
<!-- Email -->
<div>
<Label>E-Mail *</Label>
<input
name="email"
type="email"
bind:value={user.email}
required
/>
</div>
</div>
</div>
<h3 class="mt-8 font-semibold">Rechnungsadresse</h3>
<div class="rounded-lg border p-4 border-base-300 bg-base-100">
<div class="grid grid-cols-2 gap-4">
<div>
<Label>Empfänger *</Label>
<input
name="rechnung_empfaenger"
type="text"
bind:value={rechnung.empfaenger}
required
data-rule-maxlength="100"
data-msg-maxlength="max. 100 Zeichen"
/>
</div>
<!-- Zusatzzeile -->
<div>
<Label>Zusatzzeile</Label>
<input
name="rechnung_zusatzzeile"
bind:value={rechnung.zusatzzeile}
type="text"
data-rule-maxlength="80"
data-msg-maxlength="max. 80 Zeichen"
/>
</div>
</div>
<div class="grid grid-cols-3 gap-4">
<!-- Strasse -->
<div>
<Label>Straße, Hausnummer *</Label>
<input
name="rechnung_strasse"
bind:value={rechnung.strasse}
type="text"
required
data-rule-maxlength="40"
data-msg-maxlength="max. 40 Zeichen"
/>
</div>
<!-- PLZ -->
<ZipSearch
name="rechnung_plz"
bind:zip={rechnung.plz}
bind:city={rechnung.ort}
/>
<!-- Ort -->
<div>
<Label>Ort *</Label>
<input
name="rechnung_ort"
readonly
type="text"
required
value={rechnung.ort}
/>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<!-- Telefon -->
<div>
<Label>Telefon</Label>
<input
name="rechnung_telefon"
bind:value={rechnung.telefon}
type="text"
/>
</div>
<!-- Email -->
<div>
<Label>E-Mail</Label>
<input
name="rechnung_email"
bind:value={rechnung.email}
type="email"
/>
</div>
</div>
</div>
<h3 class="mt-8 font-semibold">Versandadresse</h3>
<div class="rounded-lg border p-4 border-base-300 bg-base-100">
<div class="flex flex-row gap-2 items-center">
<input
class="w-[15px] h-[15px]"
type="checkbox"
name="abweichende_versand_adresse"
bind:checked={rechnung.abweichende_versand_adresse}
/>
<Label>Abweichende Versandadresse</Label>
</div>
<div class="grid grid-cols-2 gap-4">
<!-- Empfänger -->
<div>
<Label>Empfänger *</Label>
<input
name="versand_empfaenger"
type="text"
readonly={!rechnung.abweichende_versand_adresse}
bind:value={rechnung.versand_empfaenger}
required
data-rule-maxlength="100"
data-msg-maxlength="max. 100 Zeichen"
/>
</div>
<!-- Zusatzzeile -->
<div>
<Label>Zusatzzeile</Label>
<input
name="versand_zusatzzeile"
type="text"
readonly={!rechnung.abweichende_versand_adresse}
bind:value={rechnung.versand_zusatzzeile}
data-rule-maxlength="80"
data-msg-maxlength="max. 80 Zeichen"
/>
</div>
</div>
<div class="grid grid-cols-3 gap-4">
<!-- Strasse -->
<div>
<Label>Straße, Hausnummer *</Label>
<input
name="versand_strasse"
type="text"
readonly={!rechnung.abweichende_versand_adresse}
bind:value={rechnung.versand_strasse}
required
data-rule-maxlength="40"
data-msg-maxlength="max. 40 Zeichen"
/>
</div>
<!-- PLZ -->
<ZipSearch
name="versand_plz"
readonly={!rechnung.abweichende_versand_adresse}
bind:zip={rechnung.versand_plz}
bind:city={rechnung.versand_ort}
/>
<!-- Ort -->
<div>
<Label>Ort *</Label>
<input
name="versand_ort"
type="text"
readonly
required
bind:value={rechnung.versand_ort}
/>
</div>
</div>
</div>
<h3 class="mt-8 font-semibold">Bezahlmethode</h3>
<div
class="rounded-lg border p-4 border-base-300 bg-base-100 flex flex-row gap-4 justify-between"
>
<PaymentOption
paymentType={Enums.Bezahlmethoden.paypal}
bind:selectedPaymentType
name={"PayPal"}
icon={"/images/paypal.png"}
></PaymentOption>
<PaymentOption
paymentType={Enums.Bezahlmethoden.sofort}
bind:selectedPaymentType
name={"Sofort"}
icon={"/images/sofort.png"}
></PaymentOption>
<PaymentOption
paymentType={Enums.Bezahlmethoden.giropay}
bind:selectedPaymentType
name={"Giropay"}
icon={"/images/giropay.png"}
></PaymentOption>
<PaymentOption
paymentType={Enums.Bezahlmethoden.creditcard}
bind:selectedPaymentType
name={"Kreditkarte"}
icon={"/images/mastercard.png"}
></PaymentOption>
<PaymentOption
paymentType={Enums.Bezahlmethoden.rechnung}
bind:selectedPaymentType
name={"Rechnung"}
icon={"/images/rechnung.png"}
></PaymentOption>
</div>
</div>
<div>
<h3 class="font-semibold">Zusammenfassung</h3>
<div class="rounded-lg border p-4 border-base-300 bg-base-100">
<CheckoutItem
image={"https://www.gih.de/wp-content/uploads/2015/11/EnergieausweisW-E.jpg"}
name={"Energieausweis"}
description={"Verbrauchsausweis Wohnen"}
price={45}
quantity={1}
removable={false}
maxQuantity={1}
/>
<div class="mt-auto">
<hr />
<div class="flex flex-row items-center justify-between">
<span class="opacity-75 text-sm">Brutto</span>
<span class="font-semibold text-sm">75$</span>
</div>
<div class="flex flex-row items-center justify-between">
<span class="opacity-75 text-sm">Netto</span>
<span class="font-semibold text-sm">75$</span>
</div>
<hr />
<div class="flex flex-row items-center justify-between">
<span class="opacity-75 text-sm">Gesamt</span>
<span class="font-semibold text-sm">75$</span>
</div>
<button class="btn btn-secondary w-full mt-4" disabled
>Bestellung Bestätigen</button
>
</div>
</div>
</div>
</div>

View File

@@ -1,397 +1,271 @@
<script lang="ts"> <script lang="ts">
import ProgressBar from "#components/Ausweis/Progressbar.svelte"; import ProgressBar from "#components/Ausweis/Progressbar.svelte";
import HelpLabel from "#components/HelpLabel.svelte"; import type {
import ZipSearch from "../components/PlzSuche.svelte"; BedarfsausweisWohnen,
import Label from "../components/Label.svelte"; Benutzer,
import PriceContainer from "#components/Kaufabschluss/PriceContainer.svelte"; Bezahlmethoden,
import type { BedarfsausweisWohnen, Benutzer, Bezahlmethoden, Rechnungen, VerbrauchsausweisGewerbe, VerbrauchsausweisWohnen } from "@ibcornelsen/database/client"; VerbrauchsausweisGewerbe,
import { Enums } from "@ibcornelsen/database/client" VerbrauchsausweisWohnen,
import PaymentOption from "#components/PaymentOption.svelte"; } from "@ibcornelsen/database/client";
import { client } from "src/trpc"; import { Enums } from "@ibcornelsen/database/client";
import type { inferProcedureInput } from "@trpc/server";
import type { AppRouter } from "@ibcornelsen/api";
export let user: Benutzer; export let user: Benutzer;
export let ausweis: VerbrauchsausweisWohnen | BedarfsausweisWohnen | VerbrauchsausweisGewerbe; export let ausweis:
let rechnung: inferProcedureInput<AppRouter["v1"]["rechnungen"]["erstellen"]> = {}; | VerbrauchsausweisWohnen
| BedarfsausweisWohnen
| VerbrauchsausweisGewerbe;
let services = [{ let services = [
{
name: "Qualitätsdruck per Post (zusätzlich zur PDF Version) für 9€ inkl. MwSt.", name: "Qualitätsdruck per Post (zusätzlich zur PDF Version) für 9€ inkl. MwSt.",
id: Enums.Service.Qualitaetsdruck, id: Enums.Service.Qualitaetsdruck,
price: 9, price: 9,
selected: false selected: false,
}, { },
{
name: "Aushang (für öffentliche Gebäude gesetzlich vorgeschrieben) für 10€ inkl. MwSt.", name: "Aushang (für öffentliche Gebäude gesetzlich vorgeschrieben) für 10€ inkl. MwSt.",
id: Enums.Service.Aushang, id: Enums.Service.Aushang,
price: 10, price: 10,
selected: false selected: false,
}, { },
{
name: "Same Day Service (Bestellung Werktags vor 12:00 Uhr - Ausstellung bis 18:00 Uhr am gleichen Tag) für 29€ inkl. MwSt.", name: "Same Day Service (Bestellung Werktags vor 12:00 Uhr - Ausstellung bis 18:00 Uhr am gleichen Tag) für 29€ inkl. MwSt.",
id: Enums.Service.SameDay, id: Enums.Service.SameDay,
price: 29, price: 29,
selected: false selected: false,
}, { },
{
name: "Telefonische Energieeffizienzberatung für 75€ inkl. MwSt.", name: "Telefonische Energieeffizienzberatung für 75€ inkl. MwSt.",
id: Enums.Service.Telefonberatung, id: Enums.Service.Telefonberatung,
price: 75, price: 75,
selected: false selected: false,
}] },
];
export let selectedPaymentType: Bezahlmethoden = Enums.Bezahlmethoden.PAYPAL; export let selectedPaymentType: Bezahlmethoden =
Enums.Bezahlmethoden.paypal;
let agbAkzeptiert: boolean; import { PRICES } from "#lib/constants";
let datenschutzAkzeptiert: boolean;
async function createPayment(e: SubmitEvent) { const prices = PRICES[ausweis.ausweisart];
e.preventDefault()
const response = await client.v1.rechnungen.erstellen.mutate({ let basePrice: number = prices[0];
...rechnung,
ausweisart: ausweis.ausweisart,
uid: ausweis.uid,
bezahlmethode: selectedPaymentType,
services: services.filter(service => service.selected).map(service => service.id)
})
window.location.href = response.checkout_url $: price =
} basePrice +
services.reduce(
(acc, service) => (service.selected && acc + service.price) || acc,
0
);
</script> </script>
<div class="w-full px-8"> <div class="w-full px-8">
<div class="flex flex-row gap-8 items-center mb-8 w-3/5"> <div class="flex flex-row gap-8 items-center mb-8 w-full">
<div class="flex flex-col w-full"> <div class="flex flex-col w-full">
<h1>Verbrauchsausweis erstellen - 45€</h1> <h1>Verbrauchsausweis erstellen - 45€</h1>
<ProgressBar progress={50} /> <ProgressBar progress={50} />
</div> </div>
</div> </div>
<div <form>
class="w-full" <div class="grid grid-cols-[1.5fr_2fr] gap-4">
<div class="rounded-lg border p-4 border-base-300 bg-base-100 flex flex-col gap-4">
<div class="flex flex-col gap-2 test-box">
<strong>A - Prüfung der Ausweisart</strong>
<div>
<span>Vermietung, Verkauf oder sonstiges</span>
<span
>Baujahr Heizung nicht kleiner als Baujahr Gebäude</span
><span
>Baujahr nach 1977 oder saniert oder mehr als 4
Wohneinheiten</span
><span>Heizung min. 3 Jahre alt</span><span
>Verbrauchsausweis zulässig</span
>
</div>
</div>
<div class="flex flex-col gap-2 test-box">
<strong
>B - Prüfung der Adresse, Wohnfläche, Keller und Dach</strong
> >
<form class="flex flex-row gap-8" on:submit={createPayment}>
<div class="w-3/5">
<div class="GRB3">
<HelpLabel title="Ansprechpartner" />
<hr />
<div class="grid grid-cols-3 gap-4">
<!-- Anrede -->
<div> <div>
<Label>Anrede *</Label> <span>PLZ gültig</span><span>Klimafaktorern</span><span
>Wohnfläche passt zu Wohneinheiten</span
>
</div>
</div>
<div class="flex flex-col gap-2 test-box">
<strong>C - Prüfung der Verbrauchsangaben</strong>
<div> <div>
<select name="anrede" bind:value={user.anrede}> <span>Verbrauchsmenge schlüssig</span><span
<option>bitte auswählen</option> >Verbrauchsabweichung im Rahmen</span
<option value="Herr">Herr</option> ><span>Endenergieverbrauch schlüssig</span>
<option value="Frau">Frau</option>
</select>
</div> </div>
</div> </div>
<div class="flex flex-col gap-2 test-box">
<!-- Vorname --> <strong
>D - Prüfung Warmwasser und alternative
Energieversorgung</strong
>
<div> <div>
<Label>Vorname *</Label> <span>Warmwasseranteil schlüssig</span>
<input name="vorname" type="text" bind:value={user.vorname} required />
</div> </div>
</div>
<!-- Nachname --> <div class="flex flex-col gap-2 test-box">
<strong
>E - Prüfung von Gebäudetyp, Lüftung, Kühlung und
Leerstand</strong
>
<div> <div>
<Label>Nachname *</Label> <span>Leerstand nicht größer als 30%</span>
<input name="name" type="text" bind:value={user.name} required />
</div> </div>
</div> </div>
<div class="grid grid-cols-2 gap-4"> <div class="flex flex-col gap-2 test-box">
<!-- Telefon --> <strong
>F - Prüfung des Sanierungsstandes und der Gebäudebilder</strong
>
<div> <div>
<Label>Telefon</Label> <span>Mindestens ein Bild pro Abschnitt vorhanden</span
<input name="telefon" bind:value={user.telefon} type="text" /> ><span>Angaben zum Sanierungsstand vorhanden</span><span
>Bei Baujahr vor 1978 Dach oder Geschossdecke min.
12 cm gedämmt</span
>
</div>
</div>
</div> </div>
<!-- Email -->
<div> <div>
<Label>E-Mail *</Label> <div class="rounded-lg border p-4 border-base-300 bg-base-100 flex flex-col">
<input name="email" type="email" bind:value={user.email} required /> <table>
<tr>
<td><strong>Produkt:</strong></td>
<td
><div class="py-2">
Verbrauchsausweis
</div></td
>
</tr>
<tr>
<td><strong>Beschreibung:</strong></td>
<td>
<div class="py-2">
Registrierung beim DiBt<br />
Prüfung durch Diplom Ingenieur<br />
Energieausweis Vorschau als PDF<br />
</div> </div>
</td>
</tr>
<tr>
<td>Netto-Preis</td>
<td
><div class="py-2">
{(price * 0.81).toFixed(2) + "€"}
</div></td
>
</tr>
<tr>
<td>19% gesetzl. MwSt.</td>
<td
><div class="py-2">
{(price * 0.19).toFixed(2) + "€"}
</div></td
>
</tr>
<hr>
<tr>
<td>Preis inkl. MwSt.</td>
<td
><div class="py-2">
<strong>{price + "€"}</strong>
</div> </div>
</td>
</tr>
</table>
</div> </div>
<h3 class="font-semibold mt-8">Hiermit bestelle ich folgende Version des Energieausweises:</h3>
<hr /> <div class="rounded-lg border p-4 border-base-300 bg-base-100 flex flex-col">
<table>
<div class="GRB3"> <tr>
<HelpLabel title="Rechnungsadresse" /> <td
<hr /> >Verbrauchsausweis online für {prices[0]} € inkl. MwSt.
<!-- Empfänger --> als PDF per E-Mail</td
>
<div class="grid grid-cols-2 gap-4"> <td
<div> ><input
<Label>Empfänger *</Label> type="radio"
<input class="radio radio-secondary"
name="rechnung_empfaenger" bind:group={basePrice}
type="text" value={prices[0]}
bind:value={rechnung.empfaenger} name="Preis"
required checked
data-rule-maxlength="100"
data-msg-maxlength="max. 100 Zeichen"
/> />
</div> </td>
</tr>
<!-- Zusatzzeile --> <tr>
<div> <td
<Label>Zusatzzeile</Label> >Verbrauchsausweis online inkl. Beratung für {prices[1]}
<input € inkl. MwSt. als PDF per E-Mail</td
name="rechnung_zusatzzeile" >
bind:value={rechnung.zusatzzeile} <td
type="text" ><input
data-rule-maxlength="80" type="radio"
data-msg-maxlength="max. 80 Zeichen" class="radio radio-secondary"
/> bind:group={basePrice}
</div> value={prices[1]}
</div> name="Preis"
<div class="grid grid-cols-3 gap-4">
<!-- Strasse -->
<div>
<Label>Straße, Hausnummer *</Label>
<input
name="rechnung_strasse"
bind:value={rechnung.strasse}
type="text"
required
data-rule-maxlength="40"
data-msg-maxlength="max. 40 Zeichen"
/> />
</td>
</tr><tr>
<td
>Verbrauchsausweis offline für {prices[2]} € inkl. MwSt.
als PDF per E-Mail (Sie schicken uns 3 Verbrauchsabrechnungen)</td
>
<td
><input
type="radio"
class="radio radio-secondary"
bind:group={basePrice}
value={prices[2]}
name="Preis"
/></td
>
</tr>
</table>
</div> </div>
<!-- PLZ --> <h3 class="font-semibold mt-8">Zusatzleistungen</h3>
<ZipSearch <div class="rounded-lg border p-4 border-base-300 bg-base-100 flex flex-col">
name="rechnung_plz" <table>
bind:zip={rechnung.plz} {#each services as service}
bind:city={rechnung.ort} <tr>
/> <td>{service.name}</td>
<td
<!-- Ort --> ><input
<div>
<Label>Ort *</Label>
<input
name="rechnung_ort"
readonly
type="text"
required
value={rechnung.ort}
/>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<!-- Telefon -->
<div>
<Label>Telefon</Label>
<input name="rechnung_telefon" bind:value={rechnung.telefon} type="text" />
</div>
<!-- Email -->
<div>
<Label>E-Mail</Label>
<input name="rechnung_email" bind:value={rechnung.email} type="email" />
</div>
</div>
</div>
<hr />
<div class="GRB3">
<HelpLabel title="Versandadresse" />
<hr />
<div class="flex flex-row gap-2 items-center">
<input
class="w-[15px] h-[15px]"
type="checkbox" type="checkbox"
name="abweichende_versand_adresse" class="checkbox checkbox-secondary"
bind:checked={rechnung.abweichende_versand_adresse} bind:checked={service.selected}
/> />
<Label>Abweichende Versandadresse</Label> </td>
</div> </tr>
<div class="grid grid-cols-2 gap-4"> {/each}
<!-- Empfänger --> </table>
<div>
<Label>Empfänger *</Label>
<input
name="versand_empfaenger"
type="text"
readonly={!rechnung.abweichende_versand_adresse}
bind:value={rechnung.versand_empfaenger}
required
data-rule-maxlength="100"
data-msg-maxlength="max. 100 Zeichen"
/>
</div>
<!-- Zusatzzeile -->
<div>
<Label>Zusatzzeile</Label>
<input
name="versand_zusatzzeile"
type="text"
readonly={!rechnung.abweichende_versand_adresse}
bind:value={rechnung.versand_zusatzzeile}
data-rule-maxlength="80"
data-msg-maxlength="max. 80 Zeichen"
/>
</div>
</div>
<div class="grid grid-cols-3 gap-4">
<!-- Strasse -->
<div>
<Label>Straße, Hausnummer *</Label>
<input
name="versand_strasse"
type="text"
readonly={!rechnung.abweichende_versand_adresse}
bind:value={rechnung.versand_strasse}
required
data-rule-maxlength="40"
data-msg-maxlength="max. 40 Zeichen"
/>
</div>
<!-- PLZ -->
<ZipSearch
name="versand_plz"
readonly={!rechnung.abweichende_versand_adresse}
bind:zip={rechnung.versand_plz}
bind:city={rechnung.versand_ort}
/>
<!-- Ort -->
<div>
<Label>Ort *</Label>
<input
name="versand_ort"
type="text"
readonly
required
bind:value={rechnung.versand_ort}
/>
</div>
</div> </div>
</div> </div>
<hr />
<div class="GRB3">
<HelpLabel title="Bezahlmethode" />
<hr />
<div class="flex flex-row justify-between gap-4">
<PaymentOption paymentType={Enums.Bezahlmethoden.paypal} bind:selectedPaymentType name={"PayPal"} icon={"/images/paypal.png"}></PaymentOption>
<PaymentOption paymentType={Enums.Bezahlmethoden.sofort} bind:selectedPaymentType name={"Sofort"} icon={"/images/sofort.png"}></PaymentOption>
<PaymentOption paymentType={Enums.Bezahlmethoden.giropay} bind:selectedPaymentType name={"Giropay"} icon={"/images/giropay.png"}></PaymentOption>
<PaymentOption paymentType={Enums.Bezahlmethoden.creditcard} bind:selectedPaymentType name={"Kreditkarte"} icon={"/images/mastercard.png"}></PaymentOption>
<PaymentOption paymentType={Enums.Bezahlmethoden.rechnung} bind:selectedPaymentType name={"Rechnung"} icon={"/images/rechnung.png"}></PaymentOption>
</div> </div>
<div class="w-1/2"> <div class="flex flex-row justify-between">
<div class="flex-row justify-between"> <!-- TODO: Zurück implementieren -->
<h5>{selectedPaymentType}</h5> <button class="btn btn-secondary mt-4">Zurück</button>
<img <div class="flex flex-row gap-4">
src="../../images/{selectedPaymentType == <!-- TODO: Speichern implementieren -->
Enums.Bezahlmethoden.creditcard <button class="btn btn-secondary mt-4">Speichern</button>
? 'mastercard' <button class="btn btn-secondary mt-4">Zum Kaufabschluss</button>
: selectedPaymentType}.png"
class="payment-option-logo"
/>
</div> </div>
{#if selectedPaymentType == Enums.Bezahlmethoden.rechnung}
<p>
Sobald sie AGB und Datenschutzerklärung
gelesen und akzeptiert haben können sie den
Kauf fortsetzen. Durch das Klicken auf
'Kostenpflichtig Bestellen' wird ihnen eine
Email mit weiteren Informationen über ihren
Kauf zugeschickt, von der aus sie den
Bezahlvorgang abschließen können.
</p>
{:else}
<p>
Sobald sie AGB und Datenschutzerklärung
gelesen und akzeptiert haben können sie den
Kauf fortsetzen. Durch das Klicken auf
'Kostenpflichtig Bestellen' werden sie zu <strong
>{selectedPaymentType}</strong
> weitergeleitet.
</p>
{/if}
<div class="column">
<div class="flex-row center">
<input type="checkbox" name="agb-akzeptieren" bind:checked={agbAkzeptiert} />
<label for="agb-akzeptieren"
>Ich erkläre mich mit den <a
href="https://online-energieausweis.org/agb"
>AGB</a
> vom Ingenieur-Büro Cornelsen einverstanden.</label
>
</div>
<div class="flex-row center">
<input
type="checkbox"
name="datenschutz-akzeptieren"
bind:checked={datenschutzAkzeptiert}
/>
<label for="datenschutz-akzeptieren"
>Ich erkläre mich mit der <a
href="https://online-energieausweis.org/impressum"
>Datenschutzerklärung</a
>
und
<a
href="https://online-energieausweis.org/agb#widerruf"
>Widerrufsbelehrung</a
> vom Ingenieur-Büro Cornelsen einverstanden.</label
>
</div>
</div>
<button type="submit" class="pay-button" disabled={!agbAkzeptiert || !datenschutzAkzeptiert}
>Kostenpflichtig Bestellen</button
>
</div>
</div>
<hr />
<div class="flex flex-row w-full justify-between">
<button class="button">Zurück</button>
</div>
</div>
<div class="w-2/5">
<PriceContainer {ausweis} bind:services />
</div> </div>
</form> </form>
</div> </div>
</div>
<style> <style>
input, .test-box div {
select { @apply flex flex-col gap-1.5;
display: block;
width: 100%;
height: calc(2.25rem + 2px);
padding: 0.375rem 0.75rem;
font-size: 1rem;
line-height: 1.5;
color: #495057;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #ced4da;
border-radius: 0.25rem;
}
.pay-button {
@apply w-full px-4 py-3 text-center flex items-center justify-center bg-gray-500 text-white rounded-md cursor-not-allowed mt-4 select-none no-underline font-semibold;
}
.pay-button:hover {
@apply no-underline;
}
.pay-button:not([disabled]) {
@apply cursor-pointer bg-yellow-500;
}
.pay-button:not([disabled]):hover {
@apply bg-yellow-600;
} }
</style> </style>

View File

@@ -0,0 +1,41 @@
---
import KaufabschlussModule from "#modules/KaufabschlussModule.svelte";
import AusweisLayout from "#layouts/AusweisLayout.astro";
import { Benutzer, Enums } from "@ibcornelsen/database/client";
import { prisma } from "@ibcornelsen/database/server";
// Man sollte nur auf diese Seite kommen, wenn ein Ausweis bereits vorliegt und in der Datenbank abgespeichert wurde.
const uidAusweis = Astro.url.searchParams.get("uid");
if (!uidAusweis) {
return Astro.redirect("/404");
}
const uid = Astro.cookies.get("uid").value;
if (!uid) {
return Astro.redirect("/401");
}
const user = await prisma.benutzer.findUnique({
where: {
uid
},
}) as Benutzer;
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
where: {
uid: uidAusweis,
},
});
if (!ausweis) {
return Astro.redirect("/404");
}
---
<AusweisLayout title="Kundendaten Aufnehmen - IBCornelsen">
<KaufabschlussModule user={user} ausweis={ausweis} selectedPaymentType={Enums.Bezahlmethoden.PAYPAL} client:load></KaufabschlussModule>
</AusweisLayout>