Compare commits
35 Commits
VAOnScreen
...
49-plausib
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6d141a229 | ||
|
|
12d7f11c1b | ||
|
|
19d83c286e | ||
|
|
5b6fbf686b | ||
|
|
7bc549dfc4 | ||
|
|
4bfc4c4baf | ||
|
|
3997f288fa | ||
|
|
a1a0a8e2d9 | ||
|
|
0b735bcf4e | ||
|
|
cc5032e0e1 | ||
|
|
8af5ed39b1 | ||
|
|
25171210a5 | ||
|
|
28a3f9b57c | ||
|
|
63ae424665 | ||
|
|
eb41d87f1c | ||
|
|
b45206290f | ||
|
|
c3d9913cc7 | ||
|
|
918b470639 | ||
|
|
df8fa9cce1 | ||
|
|
39f4435386 | ||
|
|
80d62ffdc2 | ||
|
|
8c188a54fa | ||
|
|
e994383317 | ||
|
|
02e108140a | ||
|
|
538fc7eb01 | ||
|
|
976afd1cd4 | ||
|
|
f679f215cc | ||
|
|
9964fded85 | ||
|
|
4f479b9c6c | ||
|
|
00e283a01c | ||
|
|
26058e3205 | ||
|
|
db7cc9af33 | ||
|
|
f2be7a36bd | ||
|
|
022fe20524 | ||
|
|
0341ea4526 |
20
.github/workflows/build-and-test.yml
vendored
20
.github/workflows/build-and-test.yml
vendored
@@ -1,20 +0,0 @@
|
||||
name: Build and Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ dev ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Build the application
|
||||
uses: actions/checkout@v3
|
||||
- uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: "latest"
|
||||
- run: bun install
|
||||
- run: bun run build
|
||||
- run: bun run test:unit
|
||||
- run: bun run test:e2e
|
||||
37
.github/workflows/dev-pipeline.yml
vendored
37
.github/workflows/dev-pipeline.yml
vendored
@@ -1,27 +1,26 @@
|
||||
name: Dev Pipeline
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
push:
|
||||
branches: [ dev ]
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Deploy dev changes.
|
||||
uses: appleboy/ssh-action@master
|
||||
with:
|
||||
host: "212.227.155.91"
|
||||
username: "root"
|
||||
password: "!2Zc727cI1"
|
||||
port: 22
|
||||
script: |
|
||||
cd ~/apps/online-energieausweis
|
||||
git reset --hard HEAD
|
||||
git clean -f -d
|
||||
git pull origin main
|
||||
git status
|
||||
npm install -g bun
|
||||
bun install
|
||||
bash build.sh
|
||||
- uses: actions/checkout@v2
|
||||
- uses: appleboy/ssh-action@master
|
||||
with:
|
||||
host: ${{ secrets.DEV_HOST }}
|
||||
username: ${{ secrets.DEV_USERNAME }}
|
||||
password: ${{ secrets.DEV_PASSWORD }}
|
||||
port: 22
|
||||
script: |
|
||||
cd ~/online-energieausweis
|
||||
git reset --hard HEAD
|
||||
git clean -f -d
|
||||
git pull origin main
|
||||
git status
|
||||
bash build.sh
|
||||
27
.github/workflows/prod-pipeline.yml
vendored
27
.github/workflows/prod-pipeline.yml
vendored
@@ -1,27 +0,0 @@
|
||||
name: Production Deployment
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [ created ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Deploy to production.
|
||||
uses: appleboy/ssh-action@master
|
||||
with:
|
||||
host: "212.227.155.91"
|
||||
username: "root"
|
||||
password: "!2Zc727cI1"
|
||||
port: 22
|
||||
script: |
|
||||
cd ~/apps/online-energieausweis
|
||||
git reset --hard HEAD
|
||||
git clean -f -d
|
||||
git pull origin main
|
||||
git status
|
||||
npm install -g bun
|
||||
bun install
|
||||
bash build.sh
|
||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"i18n-ally.localesPaths": [
|
||||
"public/locales"
|
||||
]
|
||||
],
|
||||
"typescript.tsdk": "node_modules/typescript/lib"
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import mdx from "@astrojs/mdx";
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [/*astroI18next(),*/svelte(), tailwind(), mdx()],
|
||||
integrations: [svelte(), tailwind(), mdx()],
|
||||
outDir: "./dist",
|
||||
output: "server",
|
||||
vite: {
|
||||
|
||||
75
build.sh
75
build.sh
@@ -9,50 +9,55 @@ DB_USER="main"
|
||||
DB_PASSWORD="hHMP8cd^N3SnzGRR"
|
||||
DB_PORT=5432
|
||||
|
||||
git_pull_force() {
|
||||
git reset --hard HEAD
|
||||
git clean -f -d
|
||||
git pull origin main
|
||||
}
|
||||
# Wir gehen davon aus, dass die Änderungen bereits von GitHub gepullt wurden
|
||||
# Dieses Skript ist nur dafür gedacht, von GitHub bei einer Automation
|
||||
# ausgeführt zu werden. Außerdem würde es nicht wirklich Sinn ergeben, wenn das
|
||||
# Build Skript sich die Änderungen am build Skript holen würde...
|
||||
# Wir müssen alle lokalen Pakete verlinken
|
||||
cd ../database
|
||||
bun link
|
||||
cd ../api
|
||||
bun link
|
||||
cd ../ui
|
||||
bun link
|
||||
cd ../database
|
||||
bun install
|
||||
cd ../api
|
||||
bun install
|
||||
cd ../ui
|
||||
bun install
|
||||
cd ../$APP_NAME
|
||||
|
||||
# Zuerst müssen wir neue Änderungen von GitHub pullen.
|
||||
cd ~/apps/$APP_NAME
|
||||
git_pull_force;
|
||||
|
||||
# Dann bauen wir das Docker Image unserer Application
|
||||
cd ~/apps/$APP_NAME
|
||||
# Als erstes linken wir das package mit bun, damit wir z.B. in online-energieausweis darauf zugreifen können.
|
||||
bun link
|
||||
# Dann installieren wir noch einmal alle dependencies, das ist besonders wichtig
|
||||
# falls wir lokal verlinkte Projekte haben, sonst werden die nicht in unser
|
||||
# docker image übernommen
|
||||
bun install
|
||||
|
||||
# Dann stoppen wir unser altes docker image und bauen es neu.
|
||||
docker stop $APP_NAME
|
||||
docker rm $APP_NAME
|
||||
docker build -t $APP_NAME .
|
||||
|
||||
# SECTION: Startup jobs zu crontab hinzufügen.
|
||||
# Erstmal den cronfile leeren.
|
||||
crontab -r;
|
||||
|
||||
# Alle builds schlagen fehl wenn die Datenbank nicht da ist, also muss der Container zuerst gebaut werden.
|
||||
(crontab -l ; echo "@reboot sudo ~/database/build.sh &") | crontab -;
|
||||
(crontab -l ; echo "@reboot sudo ~/apps/online-energieausweis/build.sh &") | crontab -;
|
||||
(crontab -l ; echo "@reboot sudo ~/apps/layout-tool/build.sh &") | crontab -;
|
||||
|
||||
# Wir legen ein persistent directory an
|
||||
PERSISTENT_DIR="${HOME}/persistent/online-energieausweis";
|
||||
# Jeder unserer Applikationen hat ein Verzeichnis in dem alle Dateien dauerhaft,
|
||||
# Versionsunabhängig gespeichert werden. Dieses legen wir hier an, falls es noch
|
||||
# nicht existiert.
|
||||
PERSISTENT_DIR="${HOME}/persistent/${APP_NAME}";
|
||||
mkdir -p $PERSISTENT_DIR;
|
||||
|
||||
# Wir legen einen .env file für unsere letsencrypt keys an.
|
||||
rm -f ~/apps/$APP_NAME/.env;
|
||||
touch ~/apps/$APP_NAME/.env;
|
||||
echo "PRIVATE_KEY=$(cat /etc/letsencrypt/live/ibcornelsen.de/privkey.pem | base64 | tr -d '\n')" >> ~/apps/$APP_NAME/.env;
|
||||
echo "CERTIFICATE=$(cat /etc/letsencrypt/live/ibcornelsen.de/fullchain.pem | base64 | tr -d '\n')" >> ~/apps/$APP_NAME/.env;
|
||||
# TODO: Wir legen hier die .env Datei an, die die SSL Zertifikate enthält.
|
||||
# rm -f ~/$APP_NAME/.env;
|
||||
# touch ~/$APP_NAME/.env;
|
||||
# echo "PRIVATE_KEY=$(cat /etc/letsencrypt/live/ibcornelsen.de/privkey.pem | base64 | tr -d '\n')" >> ~/$APP_NAME/.env;
|
||||
# echo "CERTIFICATE=$(cat /etc/letsencrypt/live/ibcornelsen.de/fullchain.pem | base64 | tr -d '\n')" >> ~/$APP_NAME/.env;
|
||||
|
||||
# Und starten unsere App wieder.
|
||||
# Jetzt wo wir alle Vorbereitungen getroffen haben, starten wir das Docker Image und linken es mit der Datenbank.
|
||||
docker run -d --name $APP_NAME --link $DB_CONTAINER_NAME \
|
||||
-v "${PERSISTENT_DIR}:/persistent" \
|
||||
-p "${APP_PORT}:80" \
|
||||
-e DB_CONNECTION=postgresql://${DB_USER}:${DB_PASSWORD}@${DB_CONTAINER_NAME}:${DB_PORT}/${DB_NAME} \
|
||||
-e DB_PORT=${DB_PORT} \
|
||||
--env-file ~/apps/${APP_NAME}/.env \
|
||||
-v "./node_modules/@ibcornelsen/database:/${APP_NAME}/node_modules/@ibcornelsen/database" \
|
||||
-v "./node_modules/@ibcornelsen/api:/${APP_NAME}/node_modules/@ibcornelsen/api" \
|
||||
-v "./node_modules/@ibcornelsen/ui:/${APP_NAME}/node_modules/@ibcornelsen/ui" \
|
||||
-p "${APP_PORT}:3000" \
|
||||
$APP_NAME;
|
||||
|
||||
# Crontab Updaten
|
||||
cd ~/$APP_NAME
|
||||
crontab .crontab
|
||||
15
install.sh
Normal file
15
install.sh
Normal file
@@ -0,0 +1,15 @@
|
||||
git clone https://github.com/IBCornelsen/online-energieausweis
|
||||
git clone https://github.com/IBCornelsen/database
|
||||
git clone https://github.com/IBCornelsen/api
|
||||
|
||||
cd ./database
|
||||
bun link
|
||||
bun install
|
||||
|
||||
cd ../api
|
||||
bun link
|
||||
bun install
|
||||
|
||||
cd ../online-energieausweis
|
||||
bun link
|
||||
bun install
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
layout: ../layouts/Layout.astro
|
||||
layout; ../layouts/Layout.astro
|
||||
title: AGB - online-energieausweis.org
|
||||
---
|
||||
|
||||
@@ -3,6 +3,7 @@ layout: ../layouts/Layout.astro
|
||||
title: Energieausweis EnEV/GEG
|
||||
---
|
||||
|
||||
|
||||
# EnEV Zusammenfassung (Archiv - Seit 1. Mai 2021 abgelöst durch GEG)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
layout: ../layouts/Layout.astro
|
||||
title: Welcher Energieausweis?
|
||||
title: "Welcher Energieausweis?"
|
||||
---
|
||||
|
||||
import { BoxWithHeading } from "@ibcornelsen/ui";
|
||||
19
notes/ausweis-erstellung.md
Normal file
19
notes/ausweis-erstellung.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Ausweis Erstellung
|
||||
|
||||
Wenn ein neuer Nutzer auf unsere Seite kommt und einen Ausweis erstellen möchte muss er sich nicht unbedingt sofort registrieren. Um den Kunden ein reibungsloses Erlebnis zu bieten versuchen wir den Nutzer automatisch anzulegen, allerdings kann es sein, dass der Ausweis nicht weiter bearbeitet wird. In diesem Fall müssen wir den Ausweis nach einer Zeit wieder löschen, damit er nicht für immer in unserer Datenbank bleibt.
|
||||
|
||||
```tefcha
|
||||
Nutzer Kommt auf unsere Seite
|
||||
|
||||
if Nutzer ist eingeloggt
|
||||
Ausweis wird erstellt und Nutzer zugewiesen
|
||||
else
|
||||
Ausweis erstellen
|
||||
-> Schritt 2
|
||||
if Nutzer registriert sich
|
||||
Ausweis wird verknüpft
|
||||
else
|
||||
Ausweis nach einer Woche gelöscht
|
||||
|
||||
usw...
|
||||
```
|
||||
@@ -17,7 +17,7 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@astrojs/mdx": "^0.18.4",
|
||||
"@astrojs/mdx": "^2.1.1",
|
||||
"@astrojs/node": "^5.1.4",
|
||||
"@astrojs/svelte": "^2.2.0",
|
||||
"@astrojs/tailwind": "^3.1.3",
|
||||
@@ -51,17 +51,21 @@
|
||||
"katex": "^0.16.7",
|
||||
"knex": "^2.4.2",
|
||||
"moment": "^2.29.4",
|
||||
"moment-timezone": "^0.5.45",
|
||||
"pg": "^8.11.0",
|
||||
"radix-svelte-icons": "^1.0.0",
|
||||
"remark-frontmatter": "^5.0.0",
|
||||
"sass": "^1.62.1",
|
||||
"svelte": "^3.59.1",
|
||||
"svelte-dialogs": "^1.2.2",
|
||||
"svelte-katex": "^0.1.2",
|
||||
"svelte-preprocess": "^5.0.3",
|
||||
"svelte-ripple-action": "^1.0.5",
|
||||
"svelte-tabs": "^1.1.0",
|
||||
"tailwindcss": "^3.3.2",
|
||||
"trpc-openapi": "^1.2.0",
|
||||
"uuid": "^9.0.0",
|
||||
"uuid-validate": "^0.0.3",
|
||||
"vite-tsconfig-paths": "^4.2.0",
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
|
||||
65
src/client/lib/bilderHochladen.ts
Normal file
65
src/client/lib/bilderHochladen.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { GebaeudeClient, UploadedGebaeudeBild, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import { Enums } from "@ibcornelsen/database/client";
|
||||
import { addNotification, updateNotification } from "@ibcornelsen/ui";
|
||||
import { client } from "src/trpc";
|
||||
|
||||
export async function bilderHochladen(images: (UploadedGebaeudeBild & { base64?: string })[], gebaeude_uid: string) {
|
||||
if (images.length == 0) {
|
||||
return images;
|
||||
}
|
||||
|
||||
// Wenn Bilder hochgeladen werden konvertieren wir sie zu base64, das heißt, dass die base64 Eigenschaft bei diesen Bildern
|
||||
// existiert. Das müssen wir TypeScript nur wissen lassen, damit es uns in Ruhe lässt.
|
||||
const imagesToUpload = images.filter(image => !image.uid || image.update) as unknown as { base64: string, kategorie: string, uid?: string, update: boolean }[];
|
||||
|
||||
if (imagesToUpload.length == 0) {
|
||||
return images;
|
||||
}
|
||||
|
||||
// Alle Bilder hochladen
|
||||
const notification = addNotification({
|
||||
dismissable: false,
|
||||
message: "Bilder hochladen.",
|
||||
subtext: `${imagesToUpload.length} Bilder werden hochgeladen, bitte haben sie Geduld.`,
|
||||
timeout: 0,
|
||||
type: "info"
|
||||
})
|
||||
for (let i = 0; i < imagesToUpload.length; i++) {
|
||||
const image = imagesToUpload[i];
|
||||
|
||||
try {
|
||||
if (image.update) {
|
||||
await client.v1.bilder.update.mutate({
|
||||
uid: image.uid as string,
|
||||
base64: image.base64,
|
||||
kategorie: image.kategorie as Enums.BilderKategorie
|
||||
})
|
||||
} else {
|
||||
const response = await client.v1.bilder.upload.mutate({
|
||||
base64: image.base64,
|
||||
kategorie: image.kategorie as Enums.BilderKategorie,
|
||||
gebaeude_uid
|
||||
})
|
||||
|
||||
image.uid = response.uid
|
||||
}
|
||||
|
||||
updateNotification(notification, {
|
||||
dismissable: true,
|
||||
message: "Bild hochgeladen.",
|
||||
subtext: `${i + 1}/${imagesToUpload.length} Bildern wurden erfolgreich hochgeladen.`,
|
||||
timeout: 3000
|
||||
})
|
||||
} catch (e) {
|
||||
updateNotification(notification, {
|
||||
dismissable: true,
|
||||
message: "Bild konnte nicht hochgeladen werden.",
|
||||
subtext: `Eines ihrer Bilder konnte nicht hochgeladen werden. Wir haben bereits ein Ticket erstellt und melden uns so schnell wie möglich bei ihnen.`,
|
||||
timeout: 15000,
|
||||
type: "error"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return images;
|
||||
}
|
||||
86
src/client/lib/verbrauchsausweisWohnenSpeichern.ts
Normal file
86
src/client/lib/verbrauchsausweisWohnenSpeichern.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import {
|
||||
BenutzerClient,
|
||||
GebaeudeAufnahmeClient,
|
||||
GebaeudeClient,
|
||||
UploadedGebaeudeBild,
|
||||
VerbrauchsausweisWohnenClient,
|
||||
} from "#components/Ausweis/types";
|
||||
|
||||
import { exclude } from "#lib/exclude";
|
||||
import { client } from "src/trpc";
|
||||
import { bilderHochladen } from "./bilderHochladen";
|
||||
import { addNotification } from "@ibcornelsen/ui";
|
||||
|
||||
export async function verbrauchsausweisWohnenSpeichern(
|
||||
ausweis: VerbrauchsausweisWohnenClient,
|
||||
gebaeude: GebaeudeClient,
|
||||
gebaeude_aufnahme_allgemein: GebaeudeAufnahmeClient,
|
||||
images: (UploadedGebaeudeBild & { base64?: string })[],
|
||||
user: BenutzerClient
|
||||
) {
|
||||
if (ausweis.uid) {
|
||||
// Anscheinend wurde der Ausweis bereits erstellt und hat eine UID.
|
||||
// Jetzt müssen wir ihn nun nur noch abspeichern.
|
||||
try {
|
||||
await client.v1.verbrauchsausweisWohnen[2016].speichern.mutate({
|
||||
...ausweis,
|
||||
gebaeude_aufnahme_allgemein: {
|
||||
...exclude(
|
||||
gebaeude_aufnahme_allgemein,
|
||||
["erstellungsdatum", "events", "ausstellungsdatum", "rechnungen"]
|
||||
),
|
||||
gebaeude_stammdaten: {
|
||||
...exclude(gebaeude, [
|
||||
"gebaeude_bilder",
|
||||
]),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
images = await bilderHochladen(images, gebaeude.uid);
|
||||
|
||||
return { uid: ausweis.uid, gebaeude_uid: gebaeude.uid, gebaeude_aufnahme_uid: gebaeude_aufnahme_allgemein.uid };
|
||||
} catch (e) {
|
||||
// TODO: Ticket mit Fehldermeldung abschicken.
|
||||
}
|
||||
} else {
|
||||
// Wir speichern den Ausweis ab und leiten auf die "ausweis-gespeichert" Seite weiter.
|
||||
try {
|
||||
const response =
|
||||
await client.v1.verbrauchsausweisWohnen[2016].erstellen.mutate({
|
||||
...ausweis,
|
||||
gebaeude_aufnahme_allgemein: {
|
||||
...gebaeude_aufnahme_allgemein,
|
||||
gebaeude_stammdaten: {
|
||||
...gebaeude,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
images = await bilderHochladen(images, response.gebaeude_uid);
|
||||
|
||||
return response;
|
||||
} catch (e: any) {
|
||||
await client.v1.tickets.erstellen.mutate({
|
||||
titel: "Ausweis konnte nicht gespeichert werden",
|
||||
beschreibung: e.stack,
|
||||
email: user.email ?? "",
|
||||
metadata: JSON.stringify({
|
||||
ausweis,
|
||||
}),
|
||||
});
|
||||
// TODO: Ticket mit Fehldermeldung abschicken.
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1,17 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { BedarfsausweisWohnen, VerbrauchsausweisGewerbe } from "@ibcornelsen/database/client";
|
||||
import { Buffer } from "buffer";
|
||||
import { GebaeudeClient, VerbrauchsausweisWohnenClient } from "./Ausweis/types";
|
||||
import { VerbrauchsausweisWohnenClient } from "./Ausweis/types";
|
||||
|
||||
export let ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbe | BedarfsausweisWohnen;
|
||||
export let gebaeude: GebaeudeClient;
|
||||
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||
|
||||
let base64: string = "";
|
||||
$: {
|
||||
if (ausweis && gebaeude) {
|
||||
base64 = Buffer.from(JSON.stringify({...ausweis, gebaeude_stammdaten: gebaeude}), "utf-8").toString("base64");
|
||||
}
|
||||
}
|
||||
$: base64 = Buffer.from(JSON.stringify(ausweis), "utf-8").toString("base64")
|
||||
</script>
|
||||
|
||||
<a class="border-2 rounded-lg w-[30%] bg-white text-center hover:shadow-md no-underline p-6 cursor-pointer" target="_blank" href="/pdf/ansichtsausweis?base64={base64}">
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
import ImageGrid from "../ImageGrid.svelte";
|
||||
import {
|
||||
Enums,
|
||||
type BedarfsausweisWohnen,
|
||||
type VerbrauchsausweisGewerbe,
|
||||
} from "@ibcornelsen/database/client";
|
||||
|
||||
import {
|
||||
@@ -15,12 +13,8 @@
|
||||
VerbrauchsausweisWohnenClient,
|
||||
} from "./types";
|
||||
|
||||
export let ausweis:
|
||||
| VerbrauchsausweisWohnenClient
|
||||
| VerbrauchsausweisGewerbe
|
||||
| BedarfsausweisWohnen;
|
||||
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||
export let gebaeude: GebaeudeClient;
|
||||
|
||||
export let images: UploadedGebaeudeBild[] = [];
|
||||
</script>
|
||||
|
||||
@@ -53,8 +47,8 @@
|
||||
<hr class="trenner_form_100" />
|
||||
|
||||
<div class="flex flex-row gap-4">
|
||||
<AnsichtsausweisButton {ausweis} {gebaeude} />
|
||||
<DatenblattButton {ausweis} {gebaeude} />
|
||||
<AnsichtsausweisButton {ausweis} />
|
||||
<DatenblattButton {ausweis} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
required
|
||||
bind:value={gebaeude_aufnahme_allgemein.saniert}
|
||||
>
|
||||
<option disabled>Bitte auswählen</option>
|
||||
<option disabled selected value={false}>Bitte auswählen</option>
|
||||
<option value={true}>saniert</option>
|
||||
<option value={false}>unsaniert</option>
|
||||
</select>
|
||||
|
||||
@@ -5,10 +5,6 @@
|
||||
import DaemmungImage from "./DaemmungImage.svelte";
|
||||
import FensterImage from "./FensterImage.svelte";
|
||||
import Label from "../Label.svelte";
|
||||
import type {
|
||||
BedarfsausweisWohnen,
|
||||
VerbrauchsausweisGewerbe,
|
||||
} from "@ibcornelsen/database/client";
|
||||
import {
|
||||
GebaeudeAufnahmeClient,
|
||||
GebaeudeClient,
|
||||
@@ -18,10 +14,7 @@
|
||||
|
||||
export let gebaeude: GebaeudeClient;
|
||||
export let gebaeude_aufnahme_allgemein: GebaeudeAufnahmeClient;
|
||||
export let ausweis:
|
||||
| VerbrauchsausweisWohnenClient
|
||||
| VerbrauchsausweisGewerbe
|
||||
| BedarfsausweisWohnen;
|
||||
export let ausweis: VerbrauchsausweisWohnenClient
|
||||
export let images: UploadedGebaeudeBild[];
|
||||
</script>
|
||||
|
||||
@@ -388,4 +381,4 @@
|
||||
als PDF anschauen</Label
|
||||
>
|
||||
|
||||
<AusweisPreviewContainer {ausweis} {gebaeude} />
|
||||
<AusweisPreviewContainer bind:images bind:ausweis bind:gebaeude />
|
||||
|
||||
@@ -1,17 +1,31 @@
|
||||
<script lang="ts">
|
||||
import { endEnergieVerbrauchVerbrauchsausweis_2016 } from "#lib/Berechnungen/VerbrauchsausweisWohnen/VerbrauchsausweisWohnen_2016";
|
||||
import ThickArrowDown from "radix-svelte-icons/src/lib/icons/ThickArrowDown.svelte";
|
||||
import { BedarfsausweisWohnenClient, GebaeudeAufnahmeClient, GebaeudeClient, VerbrauchsausweisGewerbeClient, VerbrauchsausweisWohnenClient } from "./types";
|
||||
import {
|
||||
BedarfsausweisWohnenClient,
|
||||
GebaeudeAufnahmeClient,
|
||||
GebaeudeClient,
|
||||
VerbrauchsausweisGewerbeClient,
|
||||
VerbrauchsausweisWohnenClient,
|
||||
} from "./types";
|
||||
import ThickArrowUp from "radix-svelte-icons/src/lib/icons/ThickArrowUp.svelte";
|
||||
|
||||
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||
export let gebaeude_aufnahme_allgemein: GebaeudeAufnahmeClient;
|
||||
export let gebaeude: GebaeudeClient;
|
||||
|
||||
let maxPerformance = 250;
|
||||
|
||||
/**
|
||||
* We use linear interpolation to scale the value between the given boundaries.
|
||||
*/
|
||||
function centerValueBetweenBoundaries(value: number, newMinimum: number, newMaximum: number, oldMinimum: number = 0, oldMaximum: number = 100): number {
|
||||
*/
|
||||
function centerValueBetweenBoundaries(
|
||||
value: number,
|
||||
newMinimum: number,
|
||||
newMaximum: number,
|
||||
oldMinimum: number = 0,
|
||||
oldMaximum: number = 100
|
||||
): number {
|
||||
// Calculate the center point of the current range
|
||||
const center = (oldMinimum + oldMaximum) / 2;
|
||||
|
||||
@@ -31,33 +45,62 @@
|
||||
const scaledValue = shiftedValue * scalingFactor;
|
||||
|
||||
// Shift the scaled value back to the center of the new range
|
||||
const centeredValue = scaledValue + ((newMaximum + newMinimum) / 2);
|
||||
const centeredValue = scaledValue + (newMaximum + newMinimum) / 2;
|
||||
|
||||
return centeredValue;
|
||||
}
|
||||
|
||||
|
||||
let translation_1 = 0;
|
||||
let translation_2 = 0;
|
||||
$: {
|
||||
(async () => {
|
||||
const result = (await endEnergieVerbrauchVerbrauchsausweis_2016(ausweis));
|
||||
const result = await endEnergieVerbrauchVerbrauchsausweis_2016({
|
||||
...ausweis,
|
||||
gebaeude_aufnahme_allgemein: {
|
||||
...gebaeude_aufnahme_allgemein,
|
||||
gebaeude_stammdaten: gebaeude,
|
||||
},
|
||||
});
|
||||
|
||||
console.log(result, ausweis);
|
||||
|
||||
if (!result) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
//const primaerEnergieVerbrauch = (await ausweis.primaerEnergieBedarf);
|
||||
translation_1 = Math.max(0, Math.min(100, result.endEnergieVerbrauchGesamt / maxPerformance * 100))
|
||||
//translation_2 = Math.max(0, Math.min(100, primaerEnergieVerbrauch / maxPerformance * 100))
|
||||
})()
|
||||
translation_1 = Math.max(
|
||||
0,
|
||||
Math.min(
|
||||
100,
|
||||
(result.endEnergieVerbrauchGesamt / maxPerformance) * 100
|
||||
)
|
||||
);
|
||||
translation_2 = Math.max(0, Math.min(100, result.primaerEnergieVerbrauchGesamt / maxPerformance * 100))
|
||||
})();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div class="w-full rounded-lg border-[#ffcc03] border-2 relative p-2">
|
||||
<img src="/images/SKALA-910.png" alt="Energieeffizienz Skala">
|
||||
<ThickArrowDown size={28} class="fill-base-content absolute top-1 transition-left duration-1000 ease-in-out"
|
||||
style="left: {translation_1}%; transform: translateX({centerValueBetweenBoundaries(translation_1, 50, -150, 0, 100)}%)" />
|
||||
<ThickArrowUp size={28} class="fill-base-content absolute bottom-1 transition-left duration-1000 ease-in-out"
|
||||
style="left: {translation_2}%; transform: translateX({centerValueBetweenBoundaries(translation_2, 50, -150, 0, 100)}%)" />
|
||||
<img src="/images/SKALA-910.png" alt="Energieeffizienz Skala" />
|
||||
<ThickArrowDown
|
||||
size={28}
|
||||
class="fill-base-content absolute top-1 transition-left duration-1000 ease-in-out"
|
||||
style="left: {translation_1}%; transform: translateX({centerValueBetweenBoundaries(
|
||||
translation_1,
|
||||
50,
|
||||
-150,
|
||||
0,
|
||||
100
|
||||
)}%)"
|
||||
/>
|
||||
<ThickArrowUp
|
||||
size={28}
|
||||
class="fill-base-content absolute bottom-1 transition-left duration-1000 ease-in-out"
|
||||
style="left: {translation_2}%; transform: translateX({centerValueBetweenBoundaries(
|
||||
translation_2,
|
||||
50,
|
||||
-150,
|
||||
0,
|
||||
100
|
||||
)}%)"
|
||||
/>
|
||||
</div>
|
||||
@@ -4,13 +4,20 @@
|
||||
import Label from "../Label.svelte";
|
||||
import fuelList from "./brennstoffListe";
|
||||
import { auditVerbrauchAbweichung } from "../Verbrauchsausweis/audits/VerbrauchAbweichung";
|
||||
import type { VerbrauchsausweisGewerbe } from "@ibcornelsen/database/client";
|
||||
import { GebaeudeAufnahmeClient, GebaeudeClient, VerbrauchsausweisWohnenClient } from "./types";
|
||||
|
||||
let availableYears = [
|
||||
2018, 2019,
|
||||
];
|
||||
let availableMonths = [
|
||||
export let gebaeude: GebaeudeClient;
|
||||
export let gebaeude_aufnahme_allgemein: GebaeudeAufnahmeClient;
|
||||
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||
// Wir dürfen bis zu 4.5 Jahre alte Klimafaktoren benutzen, also nehmen wir alle Monate seitdem und generieren daraus die Auswahl.
|
||||
// Allerdings müssen wir auch berücksichtigen, dass wir drei folgende Jahre brauchen, also
|
||||
// kann der Nutzer nur 36 + 18 Monate zurückgehen.
|
||||
let availableDates: {
|
||||
year: number;
|
||||
month: number;
|
||||
}[] = [];
|
||||
|
||||
let monthNames = [
|
||||
"Januar",
|
||||
"Februar",
|
||||
"März",
|
||||
@@ -25,9 +32,15 @@
|
||||
"Dezember",
|
||||
];
|
||||
|
||||
export let gebaeude: GebaeudeClient;
|
||||
export let gebaeude_aufnahme_allgemein: GebaeudeAufnahmeClient;
|
||||
export let ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbe;
|
||||
const startDate = moment(ausweis.gebaeude_aufnahme_allgemein.erstellungsdatum || Date.now()).subtract(4, "years").subtract(6, "months");
|
||||
const endDate = moment(ausweis.gebaeude_aufnahme_allgemein.erstellungsdatum || Date.now()).subtract(3, "years");
|
||||
|
||||
for (let m = moment(startDate); m.isBefore(endDate); m.add(1, "month")) {
|
||||
availableDates.push({
|
||||
year: m.year(),
|
||||
month: m.month(),
|
||||
});
|
||||
}
|
||||
|
||||
const fuelMap: Record<string, string[]> = {};
|
||||
for (const fuel of fuelList) {
|
||||
@@ -36,14 +49,15 @@
|
||||
fuelMap[fuel[0]].push(fuel[1]);
|
||||
}
|
||||
|
||||
let month: string = "01";
|
||||
let year: string = "2018";
|
||||
|
||||
let month = ausweis.startdatum?.getMonth() || null;
|
||||
let year = ausweis.startdatum?.getFullYear() || null;
|
||||
|
||||
$: {
|
||||
if (month && year) {
|
||||
ausweis.startdatum = moment(`${month}.01.${year}`).toDate();
|
||||
console.log(ausweis.startdatum);
|
||||
|
||||
if (typeof month === "number" && typeof year === "number") {
|
||||
// Wir addieren einfach 2 Tage auf das Datum, falls der Nutzer außerhalb Deutschlands und in einer anderen Zeitzone ist.
|
||||
// NOTE: Das ist eine grauenvolle Lösung aber alle anderen funktionieren irgendwie nicht...
|
||||
ausweis.startdatum = moment().set("month", month).set("year", year).startOf("month").add(2, "days").toDate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,9 +184,18 @@
|
||||
required
|
||||
>
|
||||
<option>auswählen</option>
|
||||
{#each availableMonths as m, i}
|
||||
<option value={i + 1}>{m}</option>
|
||||
{/each}
|
||||
{#if year !== null}
|
||||
{#each availableDates.filter(date => date.year == year) as date}
|
||||
<option value={date.month}>{monthNames[date.month]}</option>
|
||||
{/each}
|
||||
{:else}
|
||||
{#each Array.from(availableDates.reduce((a,c) => {
|
||||
a.add(c.month);
|
||||
return a;
|
||||
}, new Set())) as month}
|
||||
<option value={month}>{monthNames[month]}</option>
|
||||
{/each}
|
||||
{/if}
|
||||
</select>
|
||||
|
||||
<select
|
||||
@@ -182,8 +205,11 @@
|
||||
required
|
||||
>
|
||||
<option>auswählen</option>
|
||||
{#each availableYears as y}
|
||||
<option value={y}>{y}</option>
|
||||
{#each Array.from(availableDates.reduce((a,c) => {
|
||||
a.add(c.year);
|
||||
return a;
|
||||
}, new Set())) as year}
|
||||
<option value={year}>{year}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
@@ -242,7 +268,7 @@
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="column">
|
||||
<span>Verbrauch</span>
|
||||
<span>Verbrauch *</span>
|
||||
<input
|
||||
name="verbrauch_1"
|
||||
type="number"
|
||||
@@ -252,7 +278,7 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="column">
|
||||
<span>Verbrauch</span>
|
||||
<span>Verbrauch *</span>
|
||||
<input
|
||||
name="verbrauch_2"
|
||||
type="number"
|
||||
@@ -262,7 +288,7 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="column">
|
||||
<span>Verbrauch</span>
|
||||
<span>Verbrauch *</span>
|
||||
<input
|
||||
name="verbrauch_3"
|
||||
type="number"
|
||||
|
||||
@@ -2,11 +2,9 @@ import { AppRouter } from "@ibcornelsen/api";
|
||||
import { Benutzer, GebaeudeBilder } from "@ibcornelsen/database/client";
|
||||
import { inferProcedureInput, inferProcedureOutput } from "@trpc/server";
|
||||
|
||||
export type UploadedGebaeudeBild = Omit<
|
||||
GebaeudeBilder,
|
||||
"id" | "gebaeude_stammdaten_id" | "uid"
|
||||
> &
|
||||
({ base64: string; uid?: string });
|
||||
export type UploadedGebaeudeBild = inferProcedureOutput<
|
||||
AppRouter["v1"]["verbrauchsausweisWohnen"]["get"]
|
||||
>["gebaeude_aufnahme_allgemein"]["gebaeude_stammdaten"]["gebaeude_bilder"][0] & { base64?: string, update?: boolean };
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,23 +6,23 @@
|
||||
} from "./Ausweis/types.js";
|
||||
import AusweisPruefenTooltip from "./AusweisPruefenTooltip.svelte";
|
||||
import { addNotification } from "./NotificationProvider/shared";
|
||||
import { CheckCircled, CrossCircled, Image } from "radix-svelte-icons";
|
||||
import ChevronDown from "radix-svelte-icons/src/lib/icons/ChevronDown.svelte";
|
||||
|
||||
|
||||
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||
export let calculations: Awaited<
|
||||
ReturnType<typeof endEnergieVerbrauchVerbrauchsausweis_2016>
|
||||
>;
|
||||
|
||||
console.log(ausweis);
|
||||
|
||||
const gebaeude_aufnahme_allgemein = ausweis.gebaeude_aufnahme_allgemein
|
||||
|
||||
|
||||
const ausweisArt = "VA"; // TODO: Das ist ein Platzhalter, hier muss die Ausweisart aus dem Ausweisobjekt kommen
|
||||
|
||||
|
||||
|
||||
try {
|
||||
// TODO: In Zukunft sollen die Bilder von unserer API kommen, das ist allerdings noch nicht ganz fertig.
|
||||
// images = JSON.parse(ausweis.images)
|
||||
} catch (e) {}
|
||||
const images = ausweis.gebaeude_aufnahme_allgemein.gebaeude_stammdaten.gebaeude_bilder;
|
||||
|
||||
let verbrauchWWGesamt_1 = "";
|
||||
let verbrauchWWGesamt_2 = "";
|
||||
@@ -174,7 +174,7 @@
|
||||
|
||||
tooltip3Z1 = "Wohnfläche in m²";
|
||||
tooltip3Z2 =
|
||||
gebaeude_aufnahme_allgemein.faktorKeller +
|
||||
ausweis.faktorKeller +
|
||||
" x " +
|
||||
gebaeude_aufnahme_allgemein.flaeche +
|
||||
" m² Energetische Nutzfläche (Keller " +
|
||||
@@ -448,328 +448,429 @@
|
||||
|
||||
ausweis = ausweis;
|
||||
}
|
||||
|
||||
let bilderModal: HTMLDialogElement;
|
||||
let infoVisible = false;
|
||||
</script>
|
||||
|
||||
<table class="table table-row border">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="30px"
|
||||
><img
|
||||
src="{StatusIcon}"
|
||||
alt="Status"
|
||||
class="w-8 h-8 max-w-8 max-h-8"
|
||||
/>{zurueckGestellt}</td
|
||||
>
|
||||
<td width="150px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{gebaeude_aufnahme_allgemein.adresse} {gebaeude_aufnahme_allgemein.plz} {gebaeude_aufnahme_allgemein.ort}</span>
|
||||
<br>
|
||||
<span>{gebaeude_aufnahme_allgemein.gebaeudetyp}, Einheiten: {gebaeude_aufnahme_allgemein.einheiten}</span>
|
||||
</div>
|
||||
<span>{ausweisArt} - {ausweis.uid.split("-")[0]}</span>
|
||||
<span>{moment(gebaeude_aufnahme_allgemein.erstellungsdatum).format("DD.MM.YYYY")}</span>
|
||||
</AusweisPruefenTooltip></td
|
||||
>
|
||||
<td width="35px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>Baujahr Gebäude / Baujahr Heizung</span>
|
||||
</div>
|
||||
<span>{gebaeude_aufnahme_allgemein.baujahr_gebaeude.join(", ")}</span>
|
||||
<span>{gebaeude_aufnahme_allgemein.baujahr_heizung.join(", ")}</span>
|
||||
</AusweisPruefenTooltip>
|
||||
<div class="tooltip" data-tip="">
|
||||
|
||||
</div></td
|
||||
>
|
||||
<td width="45px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>Wohnfläche in m²</span>
|
||||
<br>
|
||||
<span>{gebaeude_aufnahme_allgemein.faktorKeller} x {gebaeude_aufnahme_allgemein.flaeche}m² Energetische Nutzfläche (Keller {gebaeude_aufnahme_allgemein.keller}) in m²</span>
|
||||
</div>
|
||||
<span>{gebaeude_aufnahme_allgemein.flaeche}</span>
|
||||
<span><strong>{calculations?.energetische_nutzfläche}</strong></span>
|
||||
</AusweisPruefenTooltip>
|
||||
</td
|
||||
>
|
||||
<td width="90px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip4Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip4Z2}</span>
|
||||
</div>
|
||||
<span>{table4Z1}</span>
|
||||
<span>{table4Z2}</span>
|
||||
</AusweisPruefenTooltip></td
|
||||
>
|
||||
<td width="70px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip5Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip5Z2}</span>
|
||||
<br>
|
||||
<span>{tooltip5Z3}</span>
|
||||
</div>
|
||||
<span>{table5Z1}</span>
|
||||
<span>{table5Z2}</span>
|
||||
</AusweisPruefenTooltip>
|
||||
</td
|
||||
>
|
||||
<td width="50px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip6Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip6Z2}</span>
|
||||
</div>
|
||||
<span><strong>{table6Z1}</strong></span>
|
||||
<span><strong>{table6Z2}</strong></span>
|
||||
</AusweisPruefenTooltip></td
|
||||
>
|
||||
<td width="90px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip7Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip7Z2}</span>
|
||||
</div>
|
||||
<span>{table7Z1}</span>
|
||||
<span>{table7Z2}</span>
|
||||
</AusweisPruefenTooltip></td
|
||||
>
|
||||
<td width="60px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip8Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip8Z2}</span>
|
||||
</div>
|
||||
<span>{table8Z1}</span>
|
||||
<span>{table8Z2}</span>
|
||||
</AusweisPruefenTooltip></td
|
||||
>
|
||||
<td width="50px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip9Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip9Z2}</span>
|
||||
</div>
|
||||
<span>{table9Z1}</span>
|
||||
<span><strong>{table9Z2}</strong></span>
|
||||
</AusweisPruefenTooltip></td
|
||||
>
|
||||
<td width="100px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip10Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip10Z2}</span>
|
||||
</div>
|
||||
<span>{table10Z1}</span>
|
||||
<span>{table10Z2}</span>
|
||||
</AusweisPruefenTooltip></td
|
||||
>
|
||||
<td width="110px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip11Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip11Z2}</span>
|
||||
</div>
|
||||
<span>{table11Z1}</span>
|
||||
<span>{table11Z2}</span>
|
||||
</AusweisPruefenTooltip></td
|
||||
>
|
||||
<td width="50px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip12Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip12Z2}</span>
|
||||
</div>
|
||||
<span>{table12Z1}</span>
|
||||
<span>{table12Z2}</span>
|
||||
</AusweisPruefenTooltip>
|
||||
</td
|
||||
>
|
||||
<td width="60px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip13Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip13Z2}</span>
|
||||
</div>
|
||||
<span>{table13Z1}</span>
|
||||
<span>{table13Z2}</span>
|
||||
</AusweisPruefenTooltip>
|
||||
</td
|
||||
>
|
||||
<td width="45px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip14Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip14Z2}</span>
|
||||
</div>
|
||||
<span>{table14Z1}</span>
|
||||
<span>{table14Z2}</span>
|
||||
</AusweisPruefenTooltip>
|
||||
</td
|
||||
>
|
||||
<td width="45px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip15Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip15Z2}</span>
|
||||
</div>
|
||||
<span><strong>{table15Z1}</strong></span>
|
||||
<span><strong>{table15Z2}</strong></span>
|
||||
</AusweisPruefenTooltip>
|
||||
</td
|
||||
>
|
||||
<td width="50px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip16Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip16Z2}</span>
|
||||
</div>
|
||||
<span><strong>{table16Z1}</strong></span>
|
||||
<span><strong>{table16Z2}</strong></span>
|
||||
</AusweisPruefenTooltip>
|
||||
</td
|
||||
>
|
||||
<td title="Gebäudebilder anzeigen" width="35px"
|
||||
><div
|
||||
class="imagePreview"
|
||||
data-imagePreview="{imagePreview}"
|
||||
>
|
||||
<img
|
||||
src="/images/dashboard/SymbolBilder.svg"
|
||||
alt="Gebäudebilder"
|
||||
width="35"
|
||||
height="35"
|
||||
/>
|
||||
</div></td
|
||||
>
|
||||
<td width="30px"
|
||||
><div class="checkTextPreviewButton">
|
||||
<img src="{symbolPruefung}" alt="Boxpruefung" />
|
||||
<div
|
||||
class="checkTextPreview"
|
||||
style="display:none; position: absolute; background-color: black; color: white; padding: 10px; border-radius: 5px; max-width: 450px; z-index:9999;"
|
||||
<div class="border rounded-box">
|
||||
<table class="table table-row">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><button on:click={() => infoVisible = !infoVisible}><ChevronDown size={22} class="transition-all {infoVisible ? "" : "rotate-180"}"></ChevronDown></button></td>
|
||||
<td class="w-6 px-2"
|
||||
>
|
||||
{gebaeude_aufnahme_allgemein.prueftext}
|
||||
{#if gebaeude_aufnahme_allgemein.erledigt}
|
||||
<div class="tooltip" data-tip="Ausweis wurde ausgestellt">
|
||||
<div class="rounded-full w-6 h-6 bg-success"></div>
|
||||
</div>
|
||||
{:else if gebaeude_aufnahme_allgemein.bestellt}
|
||||
<div class="tooltip" data-tip="Ausweis wurde bestellt">
|
||||
<div class="rounded-full w-6 h-6 bg-warning"></div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="tooltip" data-tip="Ausweis ist in Bearbeitung">
|
||||
<div class="rounded-full w-6 h-6 bg-error"></div>
|
||||
</div>
|
||||
{/if}
|
||||
</td
|
||||
>
|
||||
<td width="150px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{gebaeude_aufnahme_allgemein.adresse} {gebaeude_aufnahme_allgemein.plz} {gebaeude_aufnahme_allgemein.ort}</span>
|
||||
<br>
|
||||
<span>{gebaeude_aufnahme_allgemein.gebaeudetyp}, Einheiten: {gebaeude_aufnahme_allgemein.einheiten}</span>
|
||||
</div>
|
||||
<span>{ausweisArt} - {gebaeude_aufnahme_allgemein.id}</span>
|
||||
<span>{moment(gebaeude_aufnahme_allgemein.erstellungsdatum).format("DD.MM.YYYY")}</span>
|
||||
</AusweisPruefenTooltip></td
|
||||
>
|
||||
<td width="35px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>Baujahr Gebäude / Baujahr Heizung</span>
|
||||
</div>
|
||||
<span>{gebaeude_aufnahme_allgemein.baujahr_gebaeude.join(", ")}</span>
|
||||
<span>{gebaeude_aufnahme_allgemein.baujahr_heizung.join(", ")}</span>
|
||||
</AusweisPruefenTooltip>
|
||||
<div class="tooltip" data-tip="">
|
||||
|
||||
</div></td
|
||||
>
|
||||
<td width="45px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>Wohnfläche in m²</span>
|
||||
<br>
|
||||
<span>{ausweis.faktorKeller} x {gebaeude_aufnahme_allgemein.flaeche}m² Energetische Nutzfläche (Keller {gebaeude_aufnahme_allgemein.keller}) in m²</span>
|
||||
</div>
|
||||
<span>{gebaeude_aufnahme_allgemein.flaeche}</span>
|
||||
<span><strong>{calculations?.energetische_nutzfläche}</strong></span>
|
||||
</AusweisPruefenTooltip>
|
||||
</td
|
||||
>
|
||||
<td width="90px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip4Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip4Z2}</span>
|
||||
</div>
|
||||
<span>{table4Z1}</span>
|
||||
<span>{table4Z2}</span>
|
||||
</AusweisPruefenTooltip></td
|
||||
>
|
||||
<td width="70px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip5Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip5Z2}</span>
|
||||
<br>
|
||||
<span>{tooltip5Z3}</span>
|
||||
</div>
|
||||
<span>{table5Z1}</span>
|
||||
<span>{table5Z2}</span>
|
||||
</AusweisPruefenTooltip>
|
||||
</td
|
||||
>
|
||||
<td width="50px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip6Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip6Z2}</span>
|
||||
</div>
|
||||
<span><strong>{table6Z1}</strong></span>
|
||||
<span><strong>{table6Z2}</strong></span>
|
||||
</AusweisPruefenTooltip></td
|
||||
>
|
||||
<td width="90px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip7Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip7Z2}</span>
|
||||
</div>
|
||||
<span>{table7Z1}</span>
|
||||
<span>{table7Z2}</span>
|
||||
</AusweisPruefenTooltip></td
|
||||
>
|
||||
<td width="60px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip8Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip8Z2}</span>
|
||||
</div>
|
||||
<span>{table8Z1}</span>
|
||||
<span>{table8Z2}</span>
|
||||
</AusweisPruefenTooltip></td
|
||||
>
|
||||
<td width="50px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip9Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip9Z2}</span>
|
||||
</div>
|
||||
<span>{table9Z1}</span>
|
||||
<span><strong>{table9Z2}</strong></span>
|
||||
</AusweisPruefenTooltip></td
|
||||
>
|
||||
<td width="100px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip10Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip10Z2}</span>
|
||||
</div>
|
||||
<span>{table10Z1}</span>
|
||||
<span>{table10Z2}</span>
|
||||
</AusweisPruefenTooltip></td
|
||||
>
|
||||
<td width="110px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip11Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip11Z2}</span>
|
||||
</div>
|
||||
<span>{table11Z1}</span>
|
||||
<span>{table11Z2}</span>
|
||||
</AusweisPruefenTooltip></td
|
||||
>
|
||||
<td width="50px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip12Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip12Z2}</span>
|
||||
</div>
|
||||
<span>{table12Z1}</span>
|
||||
<span>{table12Z2}</span>
|
||||
</AusweisPruefenTooltip>
|
||||
</td
|
||||
>
|
||||
<td width="60px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip13Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip13Z2}</span>
|
||||
</div>
|
||||
<span>{table13Z1}</span>
|
||||
<span>{table13Z2}</span>
|
||||
</AusweisPruefenTooltip>
|
||||
</td
|
||||
>
|
||||
<td width="45px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip14Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip14Z2}</span>
|
||||
</div>
|
||||
<span>{table14Z1}</span>
|
||||
<span>{table14Z2}</span>
|
||||
</AusweisPruefenTooltip>
|
||||
</td
|
||||
>
|
||||
<td width="45px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip15Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip15Z2}</span>
|
||||
</div>
|
||||
<span><strong>{table15Z1}</strong></span>
|
||||
<span><strong>{table15Z2}</strong></span>
|
||||
</AusweisPruefenTooltip>
|
||||
</td
|
||||
>
|
||||
<td width="50px"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{tooltip16Z1}</span>
|
||||
<br>
|
||||
<span>{tooltip16Z2}</span>
|
||||
</div>
|
||||
<span><strong>{table16Z1}</strong></span>
|
||||
<span><strong>{table16Z2}</strong></span>
|
||||
</AusweisPruefenTooltip>
|
||||
</td
|
||||
>
|
||||
<td title="Gebäudebilder anzeigen"
|
||||
><!-- Open the modal using ID.showModal() method -->
|
||||
<button class="btn btn-square" on:click={() => bilderModal.showModal()}><Image size={22}></Image></button>
|
||||
<dialog bind:this={bilderModal} class="modal">
|
||||
<div class="modal-box flex flex-row gap-4 items-center justify-center">
|
||||
{#if images.length === 0}
|
||||
<div class="flex flex-col gap-4 items-center justify-center">
|
||||
<p>Für diesen Ausweis sind noch keine Bilder vorhanden.</p>
|
||||
<button class="btn btn-primary" tabindex="0">Erinnerung Verschicken</button>
|
||||
</div>
|
||||
{:else}
|
||||
{#each images as image}
|
||||
<div>
|
||||
<h2 class="text-lg mb-4 font-bold">{image.kategorie}</h2>
|
||||
<img src="/bilder/{image.uid}.webp">
|
||||
</div>
|
||||
</div></td
|
||||
>
|
||||
<td title="Ausweis anzeigen" width="50px"
|
||||
><a
|
||||
class="energieausweis-img"
|
||||
href="/pdf/ansichtsausweis?uid={ausweis.uid}"
|
||||
target="_blank"
|
||||
><img
|
||||
src="/images/dashboard/ausweis.jpg"
|
||||
alt="Energieausweis"
|
||||
/></a
|
||||
></td
|
||||
>
|
||||
<td title="Datenblatt anzeigen" width="50px"
|
||||
><a
|
||||
class="energieausweis-img"
|
||||
href="/pdf/datenblatt?uid={ausweis.uid}"
|
||||
target="_blank"
|
||||
><img
|
||||
src="/images/dashboard/datenblatt.jpg"
|
||||
alt="Datenblatt"
|
||||
/></a
|
||||
></td
|
||||
>
|
||||
<td
|
||||
title="Ausweis stornieren und Zahlung wenn erforderlich automatisch zurückbuchen"
|
||||
class="w-4 p-1"
|
||||
><button
|
||||
class="btn btn-xs btn-ghost"
|
||||
on:click={() => stornieren(ausweis)}>S</button
|
||||
></td
|
||||
>
|
||||
<td title="Ausweis ausstellen" class="w-4 p-1"
|
||||
><button
|
||||
class="btn btn-xs btn-ghost"
|
||||
on:click={() => ausweisAusstellen('{gebaeude_aufnahme_allgemein.uid}')}>A</button
|
||||
></td
|
||||
>
|
||||
<td
|
||||
title="Ausweis ausstellen und per Post verschicken"
|
||||
class="w-4 p-1"
|
||||
><button
|
||||
class="btn btn-xs btn-ghost"
|
||||
on:click={() => ausweisAusstellenPost('{gebaeude_aufnahme_allgemein.uid}')}>P</button
|
||||
></td
|
||||
>
|
||||
<td
|
||||
title="E-Mail an Kunden schicken mit Erläuterungen warum der Ausweis noch nicht ausgestellt werden kann."
|
||||
class="w-4 p-1"
|
||||
><button
|
||||
class="btn btn-xs btn-ghost"
|
||||
on:click={() => ausweisnichtAusstellen('{gebaeude_aufnahme_allgemein.uid}')}>N</button
|
||||
></td
|
||||
>
|
||||
<td
|
||||
title="Bestellbestätigung nochmal schicken (Zahlung nicht erfolgreich)"
|
||||
class="w-4 p-1"
|
||||
><button
|
||||
class="btn btn-xs btn-ghost"
|
||||
on:click={() => bestellBestaetigung('{gebaeude_aufnahme_allgemein.uid}')}>B</button
|
||||
></td
|
||||
>
|
||||
<td
|
||||
title="E-Mail an Kunden schicken mit Erinnerung die Bestellung abzuschließen."
|
||||
class="w-4 p-1"
|
||||
><button
|
||||
class="btn btn-xs btn-ghost"
|
||||
on:click={() => erinnern('{gebaeude_aufnahme_allgemein.uid}')}
|
||||
>E</button
|
||||
></td
|
||||
>
|
||||
<td
|
||||
title="Zum Formular mit allen Eingabedaten."
|
||||
class="w-4 p-1"
|
||||
><a
|
||||
class="btn btn-xs btn-ghost"
|
||||
target="_blank"
|
||||
href="/energieausweis-erstellen/gespeichert?id={gebaeude_aufnahme_allgemein.uid}">F</a
|
||||
></td
|
||||
>
|
||||
{@html gebaeude_aufnahme_allgemein.kontrolldatei
|
||||
? `<td title="XML-Datei an das DiBT verschicken." class="w-4 p-1"><button class="btn btn-xs btn-ghost" on:click="xmlAbschicken('{gebaeude_aufnahme_allgemein.uid}')">X</button></td>`
|
||||
: ""}
|
||||
{@html !gebaeude_aufnahme_allgemein.registriernummer
|
||||
? `<td title="Registriernummer vom DiBT anfordern." class="w-4 p-1"><button class="btn btn-xs btn-ghost" on:click="registriernummerAnfordern('{gebaeude_aufnahme_allgemein.uid}')">R</button></td>`
|
||||
: ""}
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button>close</button>
|
||||
</form>
|
||||
</dialog></td
|
||||
>
|
||||
<td class="w-[30px]"
|
||||
>
|
||||
<AusweisPruefenTooltip>
|
||||
<div slot="tooltip">
|
||||
<span>{gebaeude_aufnahme_allgemein.prueftext}</span>
|
||||
</div>
|
||||
{#if gebaeude_aufnahme_allgemein.boxpruefung}
|
||||
<CheckCircled size={22}></CheckCircled>
|
||||
{:else}
|
||||
<CrossCircled size={22}></CrossCircled>
|
||||
{/if}
|
||||
</AusweisPruefenTooltip></td
|
||||
>
|
||||
<td title="Ausweis anzeigen" class="w-[50px]"
|
||||
><a
|
||||
class="energieausweis-img"
|
||||
href="/pdf/ansichtsausweis?uid={ausweis.uid}"
|
||||
target="_blank"
|
||||
><img
|
||||
src="/images/dashboard/ausweis.jpg"
|
||||
alt="Energieausweis"
|
||||
class="w-full h-8"
|
||||
/></a
|
||||
></td
|
||||
>
|
||||
<td title="Datenblatt anzeigen" width="50px"
|
||||
><a
|
||||
class="energieausweis-img"
|
||||
href="/pdf/datenblatt?uid={ausweis.uid}"
|
||||
target="_blank"
|
||||
><img
|
||||
src="/images/dashboard/datenblatt.jpg"
|
||||
alt="Datenblatt"
|
||||
/></a
|
||||
></td
|
||||
>
|
||||
<td
|
||||
title="Ausweis stornieren und Zahlung wenn erforderlich automatisch zurückbuchen"
|
||||
class="w-4 p-1"
|
||||
><button
|
||||
class="btn btn-xs btn-ghost"
|
||||
on:click={() => stornieren(ausweis)}>S</button
|
||||
></td
|
||||
>
|
||||
<td title="Ausweis ausstellen" class="w-4 p-1"
|
||||
><button
|
||||
class="btn btn-xs btn-ghost"
|
||||
on:click={() => ausweisAusstellen('{gebaeude_aufnahme_allgemein.uid}')}>A</button
|
||||
></td
|
||||
>
|
||||
<td
|
||||
title="Ausweis ausstellen und per Post verschicken"
|
||||
class="w-4 p-1"
|
||||
><button
|
||||
class="btn btn-xs btn-ghost"
|
||||
on:click={() => ausweisAusstellenPost('{gebaeude_aufnahme_allgemein.uid}')}>P</button
|
||||
></td
|
||||
>
|
||||
<td
|
||||
title="E-Mail an Kunden schicken mit Erläuterungen warum der Ausweis noch nicht ausgestellt werden kann."
|
||||
class="w-4 p-1"
|
||||
><button
|
||||
class="btn btn-xs btn-ghost"
|
||||
on:click={() => ausweisnichtAusstellen('{gebaeude_aufnahme_allgemein.uid}')}>N</button
|
||||
></td
|
||||
>
|
||||
<td
|
||||
title="Bestellbestätigung nochmal schicken (Zahlung nicht erfolgreich)"
|
||||
class="w-4 p-1"
|
||||
><button
|
||||
class="btn btn-xs btn-ghost"
|
||||
on:click={() => bestellBestaetigung('{gebaeude_aufnahme_allgemein.uid}')}>B</button
|
||||
></td
|
||||
>
|
||||
<td
|
||||
title="E-Mail an Kunden schicken mit Erinnerung die Bestellung abzuschließen."
|
||||
class="w-4 p-1"
|
||||
><button
|
||||
class="btn btn-xs btn-ghost"
|
||||
on:click={() => erinnern('{gebaeude_aufnahme_allgemein.uid}')}
|
||||
>E</button
|
||||
></td
|
||||
>
|
||||
<td
|
||||
title="Zum Formular mit allen Eingabedaten."
|
||||
class="w-4 p-1"
|
||||
><a
|
||||
class="btn btn-xs btn-ghost"
|
||||
target="_blank"
|
||||
href="/energieausweis-erstellen/gespeichert?id={gebaeude_aufnahme_allgemein.uid}">F</a
|
||||
></td
|
||||
>
|
||||
{@html gebaeude_aufnahme_allgemein.kontrolldatei
|
||||
? `<td title="XML-Datei an das DiBT verschicken." class="w-4 p-1"><button class="btn btn-xs btn-ghost" on:click="xmlAbschicken('{gebaeude_aufnahme_allgemein.uid}')">X</button></td>`
|
||||
: ""}
|
||||
{@html !gebaeude_aufnahme_allgemein.registriernummer
|
||||
? `<td title="Registriernummer vom DiBT anfordern." class="w-4 p-1"><button class="btn btn-xs btn-ghost" on:click="registriernummerAnfordern('{gebaeude_aufnahme_allgemein.uid}')">R</button></td>`
|
||||
: ""}
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class:hidden={!infoVisible} class:block={infoVisible} class="py-4 border-t">
|
||||
<div class="grid grid-cols-[2fr_1fr] prose max-w-full">
|
||||
<div class="border-r px-8">
|
||||
<h3 class="mt-0">Wichtige Daten</h3>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Angewendete Berechnungsformel</td>
|
||||
<td><strong>EnEV 2016</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Berechnungsergebnis</td>
|
||||
<td>{calculations?.endEnergieVerbrauchGesamt}kWh/m2/A - Energieeffizienzklasse <strong>{calculations?.energieEffizienzKlasse}</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Informationen des Nutzers</td>
|
||||
<td>{gebaeude_aufnahme_allgemein.boxpruefung}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>UID</td>
|
||||
<td><strong><pre>{ausweis.uid}</pre></strong></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="px-8">
|
||||
<h3 class="mt-0">Ereignisse</h3>
|
||||
<ul class="timeline timeline-snap-icon max-md:timeline-compact timeline-vertical">
|
||||
<li>
|
||||
<div class="timeline-middle">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd" /></svg>
|
||||
</div>
|
||||
<div class="timeline-start md:text-end mb-10">
|
||||
<time class="font-mono italic">{moment(ausweis.erstellungsdatum).format("DD.MM.YYYY - HH:mm")} Uhr</time>
|
||||
<div class="text-lg font-black">Ausweis erstellt</div>
|
||||
</div>
|
||||
<hr/>
|
||||
</li>
|
||||
{#each ausweis.gebaeude_aufnahme_allgemein.events as event, i}
|
||||
<li>
|
||||
<hr />
|
||||
<div class="timeline-middle">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd" /></svg>
|
||||
</div>
|
||||
<div class="mb-10" class:timeline-end={i % 2 == 0} class:timeline-start={i % 2 == 1}>
|
||||
<time class="font-mono italic">{moment(event.date).format("DD.MM.YYYY - HH:mm")} Uhr</time>
|
||||
<div class="text-lg font-black">{event.title}</div>
|
||||
{event.description || ""}
|
||||
</div>
|
||||
<hr />
|
||||
</li>
|
||||
{/each}
|
||||
{#if ausweis.erledigt}
|
||||
<li>
|
||||
<hr />
|
||||
<div class="timeline-middle">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd" /></svg>
|
||||
</div>
|
||||
<div class="mb-10 timeline-end">
|
||||
<time class="font-mono italic">{moment(ausweis.ausstellungsdatum).format("DD.MM.YYYY - HH:mm")} Uhr</time>
|
||||
<div class="text-lg font-black">Ausweis ausgestellt</div>
|
||||
{ausweis.registriernummer ? `Registriernummer: ${ausweis.registriernummer}` : ""}
|
||||
</div>
|
||||
<hr />
|
||||
</li>
|
||||
{/if}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
} from "radix-svelte-icons";
|
||||
import { endEnergieVerbrauchVerbrauchsausweis_2016 } from "#lib/Berechnungen/VerbrauchsausweisWohnen/VerbrauchsausweisWohnen_2016";
|
||||
import { client } from "src/trpc";
|
||||
import { verbrauchsausweisWohnenCalculateFormProgress } from "#lib/VerbrauchsausweisWohnen/calculateFormProgress";
|
||||
import { number } from "zod";
|
||||
|
||||
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||
export let progress: number;
|
||||
@@ -62,7 +60,7 @@
|
||||
<div class="card lg:card-side bg-base-200 card-bordered border-base-300">
|
||||
{#if ausweis.gebaeude_aufnahme_allgemein.storniert}
|
||||
<div class="absolute top-0 left-0 w-full h-full bg-[rgba(0,0,0,0.7)] z-[5] rounded-lg select-none">
|
||||
<h1 class="absolute -rotate-[25deg] text-7xl tracking-wide uppercase text-red-500 border-4 border-red-500 rounded-lg top-[50%] translate-y-[-50%] left-[50%] translate-x-[-50%]">Storniert</h1>
|
||||
<h1 class="absolute -rotate-[25deg] text-5xl md:text-7xl tracking-wide uppercase text-red-500 border-4 border-red-500 rounded-lg top-[50%] translate-y-[-50%] left-[50%] translate-x-[-50%]">Storniert</h1>
|
||||
</div>
|
||||
{/if}
|
||||
<figure class="lg:w-1/2">
|
||||
@@ -78,7 +76,7 @@
|
||||
<DotsVertical size={15} />
|
||||
</button>
|
||||
<ul
|
||||
tabindex="0"
|
||||
tabindex="-1"
|
||||
class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-64 gap-2"
|
||||
>
|
||||
<li>
|
||||
@@ -97,15 +95,15 @@
|
||||
</ul>
|
||||
</div>
|
||||
<div class="flex flex-row flex-wrap gap-2">
|
||||
{#if ausweis.ausweisart == "VerbrauchsausweisWohnen"}
|
||||
{#if ausweis.gebaeude_aufnahme_allgemein.ausweisart == "VerbrauchsausweisWohnen"}
|
||||
<div class="badge badge-accent font-semibold">
|
||||
Verbrauchsausweis Wohnen
|
||||
</div>
|
||||
{:else if ausweis.ausweisart == "BedarfsausweisWohnen"}
|
||||
{:else if ausweis.gebaeude_aufnahme_allgemein.ausweisart == "BedarfsausweisWohnen"}
|
||||
<div class="badge badge-accent font-semibold">
|
||||
Bedarfsausweis Wohnen
|
||||
</div>
|
||||
{:else if ausweis.ausweisart == "VerbrauchsausweisGewerbe"}
|
||||
{:else if ausweis.gebaeude_aufnahme_allgemein.ausweisart == "VerbrauchsausweisGewerbe"}
|
||||
<div class="badge badge-accent font-semibold">
|
||||
Verbrauchsausweis Gewerbe
|
||||
</div>
|
||||
@@ -159,6 +157,12 @@
|
||||
: "N/A"}</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex flex-row justify-between">
|
||||
<span>ID</span>
|
||||
<span class="font-bold text-base-content"
|
||||
>{ausweis.uid.split("-")[0]}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
{/await}
|
||||
<div class="card-actions justify-end mt-8">
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { ripple } from "svelte-ripple-action";
|
||||
import type { RippleOptions } from "svelte-ripple-action/dist/constants";
|
||||
import { Home, Reader, EnvelopeClosed, Cube, Bell, Gear, LockClosed } from "radix-svelte-icons"
|
||||
import { Home, Reader, EnvelopeClosed, Cube, Bell, Gear, LockClosed, HamburgerMenu } from "radix-svelte-icons"
|
||||
import NotificationProvider from "#components/NotificationProvider/NotificationProvider.svelte";
|
||||
import DashboardNotification from "./DashboardNotification.svelte";
|
||||
import { notifications } from "#components/NotificationProvider/shared";
|
||||
import ThemeController from "#components/ThemeController.svelte";
|
||||
import { BenutzerClient } from "#components/Ausweis/types";
|
||||
import Cross1 from "radix-svelte-icons/src/lib/icons/Cross1.svelte";
|
||||
|
||||
export let lightTheme: boolean;
|
||||
export let benutzer: BenutzerClient;
|
||||
@@ -15,10 +16,29 @@
|
||||
center: false,
|
||||
color: lightTheme ? "rgba(233,233,233,0.1)" : "rgba(113, 128, 150, 0.1)",
|
||||
};
|
||||
|
||||
let headerOpen = false;
|
||||
</script>
|
||||
|
||||
<aside class="hidden md:flex bg-base-100 border-r border-r-base-300 flex-col py-8">
|
||||
<a href="/" class="px-8"
|
||||
<header class="fixed top-0 left-0 w-full h-16 flex items-center justify-between px-4 border-b z-20">
|
||||
<button on:click={() => headerOpen = !headerOpen}>
|
||||
{#if headerOpen}
|
||||
<Cross1 size={28}></Cross1>
|
||||
{:else}
|
||||
<HamburgerMenu size={28}></HamburgerMenu>
|
||||
{/if}
|
||||
</button>
|
||||
<a href="/" class="block md:hidden"
|
||||
><img
|
||||
src="/images/header/logo-big.svg"
|
||||
class="w-24"
|
||||
alt="IBCornelsen - Logo"
|
||||
/></a
|
||||
>
|
||||
</header>
|
||||
|
||||
<aside class:hidden={!headerOpen} class="fixed left-0 top-16 w-full h-[calc(100%-4rem)] flex z-30 md:relative md:h-auto md:w-auto md:top-0 md:flex bg-base-100 border-r border-r-base-300 flex-col py-8">
|
||||
<a href="/" class="px-8 hidden md:block"
|
||||
><img
|
||||
src="/images/header/logo-big.svg"
|
||||
class="w-36"
|
||||
@@ -26,7 +46,7 @@
|
||||
/></a
|
||||
>
|
||||
|
||||
<div class="menu flex flex-col gap-2 mt-12 px-0">
|
||||
<div class="menu flex flex-col gap-2 mt-0 md:mt-12 px-0">
|
||||
<a use:ripple={rippleOptions} class="button-tab" href="/dashboard">
|
||||
<Home width={22} height={22} />
|
||||
Home
|
||||
|
||||
@@ -1,17 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { BedarfsausweisWohnen, VerbrauchsausweisGewerbe } from "@ibcornelsen/database/client";
|
||||
import { Buffer } from "buffer";
|
||||
import { GebaeudeClient, VerbrauchsausweisWohnenClient } from "./Ausweis/types";
|
||||
import { VerbrauchsausweisWohnenClient } from "./Ausweis/types";
|
||||
|
||||
export let ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbe | BedarfsausweisWohnen;
|
||||
export let gebaeude: GebaeudeClient;
|
||||
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||
|
||||
let base64: string = "";
|
||||
$: {
|
||||
if (ausweis && gebaeude) {
|
||||
base64 = Buffer.from(JSON.stringify({...ausweis, gebaeude_stammdaten: gebaeude}), "utf-8").toString("base64");
|
||||
}
|
||||
}
|
||||
$: base64 = Buffer.from(JSON.stringify(ausweis), "utf-8").toString("base64");
|
||||
</script>
|
||||
|
||||
<a class="border-2 rounded-lg w-[30%] bg-white text-center hover:shadow-md no-underline p-6 cursor-pointer" target="_blank" href="/pdf/datenblatt?base64={base64}">
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import UploadImages from "./UploadImages.svelte";
|
||||
import type { BedarfsausweisWohnen, Enums, VerbrauchsausweisGewerbe } from "@ibcornelsen/database/client";
|
||||
import { GebaeudeClient, UploadedGebaeudeBild, VerbrauchsausweisWohnenClient } from "./Ausweis/types";
|
||||
import { RotateCounterClockwise, Trash } from "radix-svelte-icons";
|
||||
|
||||
export let images: UploadedGebaeudeBild[] = [];
|
||||
export let max: number = 4;
|
||||
@@ -9,6 +10,25 @@
|
||||
export let ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbe | BedarfsausweisWohnen;
|
||||
export let gebaeude: GebaeudeClient;
|
||||
export let kategorie: Enums.BilderKategorie
|
||||
|
||||
async function rotateImage(image: UploadedGebaeudeBild): Promise<UploadedGebaeudeBild> {
|
||||
return new Promise((resolve, reject) => {
|
||||
let img = new Image();
|
||||
img.src = image.base64 ? image.base64 : `/bilder/${image.uid}.webp`;
|
||||
img.onload = () => {
|
||||
let canvas = document.createElement("canvas");
|
||||
let ctx = canvas.getContext("2d");
|
||||
canvas.width = img.height;
|
||||
canvas.height = img.width;
|
||||
ctx?.translate(img.height / 2, img.width / 2);
|
||||
ctx?.rotate((-90 * Math.PI) / 180);
|
||||
ctx?.drawImage(img, -img.width / 2, -img.height / 2);
|
||||
image.base64 = canvas.toDataURL("image/webp");
|
||||
image.update = true;
|
||||
resolve(image)
|
||||
};
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
@@ -18,20 +38,33 @@
|
||||
{#if image.kategorie == kategorie}
|
||||
<div class="relative group">
|
||||
<img
|
||||
src="/bilder/{image.uid}.webp"
|
||||
src={image.base64 ? image.base64 : `/bilder/${image.uid}.webp`}
|
||||
alt={kategorie}
|
||||
class="h-full rounded-lg border-2 group-hover:contrast-50 object-cover transition-all"
|
||||
class="h-full max-h-96 w-full rounded-lg border-2 group-hover:contrast-50 object-cover transition-all"
|
||||
/>
|
||||
<button
|
||||
<div class="invisible group-hover:visible absolute left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] flex flex-row gap-2">
|
||||
<button
|
||||
type="button"
|
||||
class="invisible group-hover:visible absolute left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] rounded-full w-[30px] h-[30px] p-2 bg-[rgba(0,0,0,0.4)]"
|
||||
class="rounded-full w-[30px] h-[30px] flex items-center justify-center p-0 bg-[rgba(0,0,0,0.4)]"
|
||||
on:click={() => {
|
||||
delete images[i];
|
||||
images = images.filter((x) => x);
|
||||
}}
|
||||
>
|
||||
R
|
||||
<Trash size={20} color="#fff"></Trash>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-full w-[30px] h-[30px] flex items-center justify-center p-0 bg-[rgba(0,0,0,0.4)]"
|
||||
on:click={async () => {
|
||||
let image = await rotateImage(images[i]);
|
||||
images[i] = image;
|
||||
images = images
|
||||
}}
|
||||
>
|
||||
<RotateCounterClockwise size={20} color="#fff"></RotateCounterClockwise>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<nav>
|
||||
<div class="nav-card">
|
||||
<div class="card-menu-option dropdown dropdown-right dropdown-hover">
|
||||
<a href="/energieausweis-erstellen"
|
||||
<a href="/energieausweis-erstellen/verbrauchsausweis-wohnen"
|
||||
>Energieausweis erstellen</a
|
||||
>
|
||||
<div class="dropdown-content">
|
||||
|
||||
41
src/components/Tickets/TicketButton.svelte
Normal file
41
src/components/Tickets/TicketButton.svelte
Normal file
@@ -0,0 +1,41 @@
|
||||
<script lang="ts">
|
||||
import { dialogs } from "svelte-dialogs";
|
||||
import TicketPopup from "./TicketPopup.svelte";
|
||||
import { addNotification } from "@ibcornelsen/ui";
|
||||
|
||||
async function showTicketPopup() {
|
||||
const success = await dialogs.modal(TicketPopup);
|
||||
|
||||
if (success) {
|
||||
dialogs.alert({
|
||||
title: "Ticket erstellt",
|
||||
text: "Ihr Support Ticket wurde erfolgreich erstellt. Wir werden uns schnellstmöglich um ihre Angelegenheit kümmern. Vielen Dank für ihre Geduld.",
|
||||
dismissButtonText: "Schließen",
|
||||
dismissButtonClass: "btn btn-primary",
|
||||
dialogClass: "modal-box",
|
||||
headerClass: "bg-base-100 text-center",
|
||||
titleClass: "text-base-content text-xl font-medium",
|
||||
dividerClass: "hidden",
|
||||
footerClass: "bg-base-100 justify-center gap-4 mt-4",
|
||||
});
|
||||
} else {
|
||||
dialogs.alert({
|
||||
title: "Ticket erstellen fehlgeschlagen",
|
||||
text: "Leider ist beim erstellen des Tickets ein Fehler aufgetreten. Bitte versuchen sie es später erneut oder kontaktieren sie uns direkt per email unter info@ib-cornelsen.de.",
|
||||
dismissButtonText: "Schließen",
|
||||
dismissButtonClass: "btn btn-error",
|
||||
dialogClass: "modal-box",
|
||||
headerClass: "bg-base-100 text-center",
|
||||
titleClass: "text-base-content text-xl font-medium",
|
||||
dividerClass: "hidden",
|
||||
footerClass: "bg-base-100 justify-center gap-4 mt-4",
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<button
|
||||
class="btn btn-primary fixed bottom-0 right-8 rounded-b-none rounded-t-xl w-48 h-12 text-xl hover:h-14 transition-all"
|
||||
on:click={showTicketPopup}
|
||||
>Support Ticket</button
|
||||
>
|
||||
104
src/components/Tickets/TicketPopup.svelte
Normal file
104
src/components/Tickets/TicketPopup.svelte
Normal file
@@ -0,0 +1,104 @@
|
||||
<script lang="ts">
|
||||
import { addNotification } from "#components/Notifications/shared";
|
||||
import { client } from "src/trpc";
|
||||
import { getClose } from "svelte-dialogs";
|
||||
|
||||
const close = getClose();
|
||||
|
||||
async function createTicket(e: SubmitEvent) {
|
||||
e.preventDefault();
|
||||
try {
|
||||
await client.v1.tickets.erstellen.mutate({
|
||||
beschreibung: description,
|
||||
email: email,
|
||||
metadata: {
|
||||
category: category,
|
||||
phone: phone,
|
||||
},
|
||||
titel: title,
|
||||
})
|
||||
// Ticket wurde erfolgreich erstellt
|
||||
close(true)
|
||||
} catch (e) {
|
||||
// Beim erstellen des Tickets ist ein Fehler aufgetreten, das ist ja mal ironisch...
|
||||
close(false)
|
||||
}
|
||||
}
|
||||
|
||||
let category = "";
|
||||
let title = "";
|
||||
let description = "";
|
||||
let email = "";
|
||||
let phone = "";
|
||||
</script>
|
||||
|
||||
<form class="max-w-lg" on:submit={createTicket}>
|
||||
<h1 class="text-2xl font-semibold mb-6">Ticket erstellen</h1>
|
||||
<p class="mb-6">
|
||||
Vielen Dank, dass sie sich die Zeit nehmen ein Support Ticket zu
|
||||
erstellen. Wir werden uns schnellstmöglich um ihre Angelegenheit
|
||||
kümmern. Hier können sie alle Details eintragen und uns ihr Problem
|
||||
schildern.
|
||||
</p>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div>
|
||||
<h4>Kategorie *</h4>
|
||||
<select class="select select-bordered" bind:value={category}>
|
||||
<option value="" disabled selected>Bitte Auswählen</option>
|
||||
<option value="Verständnisproblem">Verständnisproblem</option>
|
||||
<option value="Technischer Fehler">Technischer Fehler</option>
|
||||
<option value="Feature anfordern">Feature anfordern</option>
|
||||
<option value="Fehlende Funktionalität"
|
||||
>Fehlende Funktionalität</option
|
||||
>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Überschrift *</h4>
|
||||
<input
|
||||
class="input input-bordered"
|
||||
type="text"
|
||||
placeholder="Überschrift in einem Satz"
|
||||
name="title"
|
||||
bind:value={title}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Beschreibung *</h4>
|
||||
<textarea
|
||||
cols="10"
|
||||
rows="5"
|
||||
class="textarea textarea-bordered"
|
||||
placeholder="Schildern sie hier ihre Erfahrung"
|
||||
bind:value={description}
|
||||
required
|
||||
></textarea>
|
||||
</div>
|
||||
<div class="flex flex-row gap-4">
|
||||
<div class="w-full">
|
||||
<h4>Email Adresse *</h4>
|
||||
<input
|
||||
class="input input-bordered"
|
||||
type="email"
|
||||
placeholder="Ihre Email Adresse"
|
||||
name="email"
|
||||
bind:value={email}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<h4>Telefonnummer</h4>
|
||||
<input
|
||||
class="input input-bordered"
|
||||
type="tel"
|
||||
placeholder="Ihre Telefonnumer"
|
||||
name="phone"
|
||||
bind:value={phone}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-primary" type="submit">Abschicken</button>
|
||||
</div>
|
||||
</form>
|
||||
10
src/components/UMBE_Footer.astro
Normal file
10
src/components/UMBE_Footer.astro
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
const currentYear = new Date().getFullYear();
|
||||
---
|
||||
|
||||
<footer class="max-w-[1920px] w-full">
|
||||
<div class="flex flex-row justify-between px-4 items-center bg-primary py-2 mt-auto">
|
||||
<a class="text-white font-medium text-lg" href="/impressum">Impressum und Datenschutz</a>
|
||||
<a class="text-white font-medium text-lg" href="/">© {currentYear} IB Cornelsen Hamburg.</a>
|
||||
</div>
|
||||
</footer>
|
||||
45
src/components/UMBE_Header.astro
Normal file
45
src/components/UMBE_Header.astro
Normal file
@@ -0,0 +1,45 @@
|
||||
<header class="max-w-[1920px] w-full relative">
|
||||
<a class="hidden md:block w-full h-48 bg-base-200" href="/">
|
||||
<img
|
||||
src="/images/header/header-bg.jpg"
|
||||
class="w-full h-full object-cover"
|
||||
alt="Hintergrund - Rollen Architektenpapier"
|
||||
/>
|
||||
<img
|
||||
src="/images/header/logo-big.svg"
|
||||
class="absolute top-4 right-0 w-[464px]"
|
||||
alt="IBCornelsen - Logo"
|
||||
/>
|
||||
<h2
|
||||
class="text-secondary font-semibold text-2xl absolute top-8 right-4"
|
||||
>
|
||||
Energieausweis online erstellen
|
||||
</h2>
|
||||
<h2
|
||||
class="text-primary font-semibold text-xl absolute top-16 right-4"
|
||||
>
|
||||
Energieausweise nach aktueller GEG
|
||||
</h2>
|
||||
</a>
|
||||
<div class="px-4 flex flex-row w-full md:justify-end items-center bg-primary">
|
||||
<a
|
||||
class="header-button hidden md:block"
|
||||
href="/energieausweis-erstellen/verbrauchsausweis-erstellen"
|
||||
>Energieausweis erstellen</a
|
||||
>
|
||||
<a class="header-button hidden md:block" href="/kontakt"
|
||||
>Kontakt</a
|
||||
>
|
||||
<a class="header-button hidden md:block" href="/agb">AGB</a>
|
||||
|
||||
<a class="hamburger_menu"
|
||||
><img src="/images/hamburger.png" width="22" alt="hamburger" /></a
|
||||
>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<style>
|
||||
.header-button {
|
||||
@apply px-4 py-2 text-primary-content font-medium text-lg tracking-normal hover:bg-secondary h-full;
|
||||
}
|
||||
</style>
|
||||
9
src/components/UMBE_SidebarLeft.astro
Normal file
9
src/components/UMBE_SidebarLeft.astro
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
import Navigation from "../components/UMBE_navcard.astro";
|
||||
---
|
||||
|
||||
<div class="flex flex-col gap-6 bg-slate-200 grow">
|
||||
|
||||
<Navigation>
|
||||
|
||||
</div>
|
||||
3
src/components/UMBE_SidebarRight.astro
Normal file
3
src/components/UMBE_SidebarRight.astro
Normal file
@@ -0,0 +1,3 @@
|
||||
<div class="flex flex-col gap-4 bg-slate-200 grow">
|
||||
|
||||
</div>
|
||||
100
src/components/UMBE_navcard.astro
Normal file
100
src/components/UMBE_navcard.astro
Normal file
@@ -0,0 +1,100 @@
|
||||
<script>
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<ul id="main-navigation">
|
||||
<a class="nav-element-link">
|
||||
<li class="dropdown dropdown-right dropdown-hover nav-element w-full">Energieausweis erstellen<span>❯</span>
|
||||
</a>
|
||||
|
||||
<ul tabindex="0" class="nav-list dropdown-content z-[1] w-full">
|
||||
<li class="nav-second"><a class="nav-element-link">Verbrauchsausweis erstellen</a></li>
|
||||
<li class="nav-second"><a class="nav-element-link">Bedarfsausweis erstellen</a></li>
|
||||
<li class="nav-second"><a class="nav-element-link">Verbrauchsausweis Gewerbe erstellen</a></li>
|
||||
<li class="nav-second"><a class="nav-element-link">Bedarfsausweis Gewerbe erstellen</a></li>
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="no-dropdown nav-element w-full">
|
||||
<a class="nav-element-link" href="">Welcher Energieausweis</a>
|
||||
</li>
|
||||
|
||||
<li class="dropdown lg:dropdown-bottom xl:dropdown-right dropdown-hover nav-element w-full">
|
||||
<a class="nav-element-link" href="">Verbrauchsausweis<span>❯</span></a>
|
||||
<ul tabindex="0" class="nav-list dropdown-content z-[1] w-full">
|
||||
<li class="nav-second"><a class="nav-element-link">Item 1</a></li>
|
||||
<li class="nav-second"><a class="nav-element-link">Item 2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown dropdown-right dropdown-hover nav-element w-full">
|
||||
<a class="nav-element-link" href="">Bedarfsausweis<span>❯</span></a>
|
||||
<ul tabindex="0" class="nav-list dropdown-content z-[1] w-full">
|
||||
<li class="nav-second"><a class="nav-element-link">Item 1</a></li>
|
||||
<li class="nav-second"><a class="nav-element-link">Item 2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown dropdown-right dropdown-hover nav-element w-full">
|
||||
<a class="nav-element-link" href="">Energieausweis<span>❯</span></a>
|
||||
<ul tabindex="0" class="nav-list dropdown-content z-[1] w-full">
|
||||
<li class="nav-second"><a class="nav-element-link">Item 1</a></li>
|
||||
<li class="nav-second"><a class="nav-element-link">Item 2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="no-dropdown nav-element w-full">
|
||||
<a class="nav-element-link" href="">EnEV Zusammenfassung - Archiv</a>
|
||||
</li>
|
||||
|
||||
<li class="no-dropdown nav-element w-full">
|
||||
<a class="nav-element-link" href="">Energieausweis Aussteller</a>
|
||||
</li>
|
||||
|
||||
<li class="no-dropdown nav-element w-full">
|
||||
<a class="nav-element-link" href="">Kundenbewertungen</a>
|
||||
</li>
|
||||
|
||||
<li class="no-dropdown nav-element w-full">
|
||||
<a class="nav-element-link" href="">FAQ</a>
|
||||
</li>
|
||||
|
||||
<li class="no-dropdown nav-element w-full">
|
||||
<a class="nav-element-link" href="">Für Entwickler</a>
|
||||
</li>
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
#main-navigation, .nav-list{border-top: 1px solid #ccc;}
|
||||
#main-navigation li{border-bottom: 1px solid #ccc;border-left: 1px solid #ccc;border-right: 1px solid #ccc;}
|
||||
|
||||
.nav-element{
|
||||
@apply p-2 bg-white font-normal text-lg hover:bg-primary hover:text-white
|
||||
}
|
||||
|
||||
.nav-second{
|
||||
@apply p-2 bg-white font-normal text-lg hover:bg-secondary hover:text-white
|
||||
}
|
||||
|
||||
.nav-element-link{
|
||||
@apply text-black no-underline hover:no-underline hover:text-white
|
||||
}
|
||||
|
||||
.nav-element-link span{
|
||||
position:absolute;right:15px;top:0.65rem;
|
||||
|
||||
}
|
||||
|
||||
.nav-element:hover > .nav-element-link, .nav-second:hover > .nav-element-link{
|
||||
@apply text-white
|
||||
}
|
||||
|
||||
.nav-element ul{margin: -1px 0;}
|
||||
|
||||
</style>
|
||||
@@ -1,17 +1,22 @@
|
||||
import { GebaeudeAufnahmeClient, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
|
||||
export function auditBedarfsausweisBenoetigt(ausweis: VerbrauchsausweisWohnenClient, gebaeude: GebaeudeAufnahmeClient): boolean {
|
||||
if (ausweis.ausstellgrund == "Neubau" || ausweis.ausstellgrund == "Modernisierung") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (gebaeude.saniert == true && ( gebaeude.dachgeschoss_gedaemmt == false || gebaeude.oberste_geschossdecke_gedaemmt == false)){
|
||||
return true;
|
||||
}
|
||||
|
||||
if (gebaeude.baujahr_gebaeude && gebaeude.baujahr_gebaeude.length > 0) {
|
||||
return (
|
||||
(gebaeude.baujahr_gebaeude[0] < 1978 &&
|
||||
(gebaeude.einheiten || 0) <= 4 &&
|
||||
gebaeude.saniert == false &&
|
||||
(gebaeude.saniert == false ) &&
|
||||
(ausweis.ausstellgrund == "Vermietung" ||
|
||||
ausweis.ausstellgrund == "Sonstiges" ||
|
||||
ausweis.ausstellgrund == "Verkauf")) ||
|
||||
ausweis.ausstellgrund == "Neubau" ||
|
||||
ausweis.ausstellgrund == "Modernisierung"
|
||||
ausweis.ausstellgrund == "Verkauf"))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
27
src/components/Verbrauchsausweis/audits/EndEnergie.ts
Normal file
27
src/components/Verbrauchsausweis/audits/EndEnergie.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { GebaeudeClient, VerbrauchsausweisWohnenClient, GebaeudeAufnahmeClient } from "#components/Ausweis/types";
|
||||
import { AuditType, hidden } from "./hidden";
|
||||
import { endEnergieVerbrauchVerbrauchsausweis_2016 } from "#lib/Berechnungen/VerbrauchsausweisWohnen/VerbrauchsausweisWohnen_2016";
|
||||
import { getKlimafaktoren } from "#lib/Klimafaktoren";
|
||||
|
||||
export async function auditEndEnergie(ausweis: VerbrauchsausweisWohnenClient, gebaeude: GebaeudeClient, gebaeude_aufnahme_allgemein: GebaeudeAufnahmeClient): Promise<boolean> {
|
||||
if (hidden.has(AuditType.END_ENERGIE)) {
|
||||
return false;
|
||||
}
|
||||
//sobald Fläche, Klimafaktoren und alle Verbrauchsjahre eingegeben wurden.
|
||||
if (gebaeude_aufnahme_allgemein){
|
||||
if (gebaeude_aufnahme_allgemein.flaeche && ausweis.verbrauch_1 && ausweis.verbrauch_2 && ausweis.verbrauch_3) {
|
||||
try {
|
||||
const response = await getKlimafaktoren(ausweis.startdatum, gebaeude.plz);
|
||||
// Alle Klimfaktoren konnten abgefragt werden.
|
||||
const eevva = await endEnergieVerbrauchVerbrauchsausweis_2016({...ausweis, gebaeude_aufnahme_allgemein: {...gebaeude_aufnahme_allgemein, gebaeude_stammdaten: gebaeude}});
|
||||
if (eevva){
|
||||
if (eevva?.endEnergieVerbrauchGesamt <= 45 || eevva?.endEnergieVerbrauchGesamt >= 500) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1,11 +1,14 @@
|
||||
import { GebaeudeAufnahmeClient } from "#components/Ausweis/types";
|
||||
import { AuditType, hidden } from "../audits/hidden";
|
||||
|
||||
export function auditHeizungJuengerDreiJahre(gebaeude: GebaeudeAufnahmeClient ): boolean {
|
||||
export function auditHeizungJuengerDreiJahre(gebaeude: GebaeudeAufnahmeClient): boolean {
|
||||
|
||||
if (gebaeude.baujahr_heizung && gebaeude.baujahr_heizung.length > 0) {
|
||||
return (
|
||||
(gebaeude.baujahr_heizung.sort()[0] >= (new Date().getFullYear())-3)
|
||||
);
|
||||
if (!hidden.has(AuditType.HEIZUNG_JUENGER_DREI_JAHRE)) {
|
||||
return (
|
||||
(gebaeude.baujahr_heizung.sort()[0] >= (new Date().getFullYear()) - 3)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { GebaeudeClient, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import { AuditType, hidden } from "./hidden";
|
||||
import { prisma } from "@ibcornelsen/database/server";
|
||||
import { client } from "src/trpc";
|
||||
import moment from "moment";
|
||||
import { getKlimafaktoren } from "#lib/Klimafaktoren";
|
||||
|
||||
export async function auditKlimaFaktoren(ausweis: VerbrauchsausweisWohnenClient, gebaeude: GebaeudeClient): Promise<boolean> {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { GebaeudeAufnahmeClient } from "#components/Ausweis/types";
|
||||
import { AuditType, hidden } from "./hidden";
|
||||
|
||||
export function auditLeerStand(gebaeude: GebaeudeAufnahmeClient ): boolean {
|
||||
if (gebaeude.leerstand ) {
|
||||
export function auditLeerStand(gebaeude: GebaeudeAufnahmeClient): boolean {
|
||||
if (gebaeude.leerstand && !hidden.has(AuditType.LEER_STAND)) {
|
||||
return (
|
||||
(gebaeude.leerstand > 30)
|
||||
);
|
||||
|
||||
22
src/components/Verbrauchsausweis/audits/PlzNichtErkannt.ts
Normal file
22
src/components/Verbrauchsausweis/audits/PlzNichtErkannt.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { GebaeudeAufnahmeClient } from "#components/Ausweis/types";
|
||||
import { client } from "src/trpc";
|
||||
import { memoize } from "src/lib/Memoization";
|
||||
import { AuditType, hidden } from "../audits/hidden";
|
||||
|
||||
export const auditPlzNichtErkannt = memoize(async (gebaeude: GebaeudeAufnahmeClient) => {
|
||||
if (gebaeude.plz) {
|
||||
if (gebaeude.plz.length == 5) {
|
||||
try {
|
||||
const result = await client.v1.postleitzahlen.query({ plz: gebaeude.plz, limit: 1 });
|
||||
if (result.length > 0) {
|
||||
return false;
|
||||
}
|
||||
} catch (e) {
|
||||
if (!hidden.has(AuditType.PLZ_NICHT_ERKANNT)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
});
|
||||
@@ -10,19 +10,19 @@ export function auditVerbrauchAbweichung(ausweis: VerbrauchsausweisWohnenClient,
|
||||
return [];
|
||||
}
|
||||
|
||||
if (getAbweichung(ausweis.verbrauch_1 || 0, ausweis.verbrauch_2 || 0) > 0.25) {
|
||||
if (getAbweichung(ausweis.verbrauch_1 || 0, ausweis.verbrauch_2 || 0) > 0.30) {
|
||||
return [1, 2];
|
||||
}
|
||||
|
||||
if (getAbweichung(ausweis.verbrauch_2 || 0, ausweis.verbrauch_3 || 0) > 0.25) {
|
||||
if (getAbweichung(ausweis.verbrauch_2 || 0, ausweis.verbrauch_3 || 0) > 0.30) {
|
||||
return [2, 3];
|
||||
}
|
||||
|
||||
if (getAbweichung(ausweis.verbrauch_4 || 0, ausweis.verbrauch_5 || 0) > 0.25) {
|
||||
if (getAbweichung(ausweis.verbrauch_4 || 0, ausweis.verbrauch_5 || 0) > 0.30) {
|
||||
return [4, 5];
|
||||
}
|
||||
|
||||
if (getAbweichung(ausweis.verbrauch_5 || 0, ausweis.verbrauch_6 || 0) > 0.25) {
|
||||
if (getAbweichung(ausweis.verbrauch_5 || 0, ausweis.verbrauch_6 || 0) > 0.30) {
|
||||
return [5, 6];
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import { AuditType, hidden } from "./hidden";
|
||||
|
||||
export function auditWarmWasser(ausweis: VerbrauchsausweisWohnenClient): boolean {
|
||||
|
||||
if (ausweis.warmwasser_anteil_bekannt && ausweis.warmwasser_enthalten && ausweis.anteil_warmwasser_1) {
|
||||
return (
|
||||
ausweis.anteil_warmwasser_1 <= 6 || ausweis.anteil_warmwasser_1 >= 35
|
||||
);
|
||||
if (!hidden.has(AuditType.WARM_WASSER)){
|
||||
return (
|
||||
ausweis.anteil_warmwasser_1 <= 6 || ausweis.anteil_warmwasser_1 >= 35
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import { GebaeudeAufnahmeClient } from "#components/Ausweis/types";
|
||||
import { AuditType, hidden } from "./hidden";
|
||||
|
||||
export function auditWohnFlaeche(gebaeude: GebaeudeAufnahmeClient ): boolean {
|
||||
if (gebaeude.einheiten && gebaeude.flaeche ) {
|
||||
|
||||
return (
|
||||
(gebaeude.flaeche < gebaeude.einheiten * 30)
|
||||
);
|
||||
if (!hidden.has(AuditType.WOHN_FLAECHE)){
|
||||
return (
|
||||
(gebaeude.flaeche < gebaeude.einheiten * 30)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { GebaeudeAufnahmeClient } from "#components/Ausweis/types";
|
||||
import { AuditType, hidden } from "../audits/hidden";
|
||||
|
||||
export function auditWohnflaecheGroesserGesamtflaeche(gebaeude: GebaeudeAufnahmeClient ): boolean {
|
||||
if (gebaeude.flaeche && gebaeude.nutzflaeche){
|
||||
return (gebaeude.flaeche > gebaeude.nutzflaeche && !hidden.has(AuditType.WOHNFLAECHE_GROESSER_GESAMTFLAECHE));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -8,5 +8,8 @@ export enum AuditType {
|
||||
KLIMA_FAKTOREN,
|
||||
WOHN_FLAECHE,
|
||||
WARM_WASSER,
|
||||
LEER_STAND
|
||||
LEER_STAND,
|
||||
PLZ_NICHT_ERKANNT,
|
||||
END_ENERGIE,
|
||||
WOHNFLAECHE_GROESSER_GESAMTFLAECHE
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import * as fs from "fs";
|
||||
|
||||
const start = moment().set("year", 2019).set("month", 8).set("date", 1);
|
||||
|
||||
const end = moment().set("year", 2022).set("month", 10).set("date", 1);
|
||||
const end = moment().set("year", 2023).set("month", 1).set("date", 1);
|
||||
|
||||
let current = start.clone();
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -8,7 +8,7 @@ import Header from "../components/Header.astro";
|
||||
import SidebarLeft from "../components/SidebarLeft.astro";
|
||||
import SidebarRight from "../components/SidebarRight.astro";
|
||||
import { NotificationWrapper } from "@ibcornelsen/ui";
|
||||
import HeaderAlternative from "#components/HeaderAlternative.svelte";
|
||||
import TicketPopup from "../components/Tickets/TicketButton.svelte"
|
||||
|
||||
export interface Props {
|
||||
title: string;
|
||||
@@ -105,6 +105,7 @@ const schema = JSON.stringify({
|
||||
</main>
|
||||
<Footer />
|
||||
<NotificationWrapper client:load />
|
||||
<TicketPopup client:load />
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
96
src/layouts/UMBE_Layout.astro
Normal file
96
src/layouts/UMBE_Layout.astro
Normal file
@@ -0,0 +1,96 @@
|
||||
---
|
||||
import i18next from "i18next";
|
||||
|
||||
import "../style/UMBE_global.css";
|
||||
import "../../svelte-dialogs.config"
|
||||
import Footer from "../components/UMBE_Footer.astro";
|
||||
import Header from "../components/UMBE_Header.astro";
|
||||
import SidebarLeft from "../components/UMBE_SidebarLeft.astro";
|
||||
import SidebarRight from "../components/UMBE_SidebarRight.astro";
|
||||
import { NotificationWrapper } from "@ibcornelsen/ui";
|
||||
|
||||
export interface Props {
|
||||
title: string;
|
||||
}
|
||||
|
||||
const { title } = Astro.props;
|
||||
|
||||
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang={i18next.language}>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.jpg" />
|
||||
<meta
|
||||
name="description"
|
||||
content="✅ Jetzt Ihren Energieausweis online erstellen. Erhalten Sie Ihren online Energieausweis rechtssicher und nach aktueller GEG (vormals EnEV) vom Diplom Ingenieur geprüft."
|
||||
/>
|
||||
<title>
|
||||
{title || "Energieausweis online erstellen - Online Energieausweis"}
|
||||
</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<container class="max-w-[1920px] w-full mx-auto bg-slate-600 grid border-solid border-grey-200 border">
|
||||
<Header />
|
||||
<main
|
||||
class="lg:grid gap-6 md:p-6 lg:grid-cols-[2fr,6fr,2fr] max-w-[1920px] w-full bg-base-100"
|
||||
>
|
||||
<SidebarLeft />
|
||||
<article class="w-full max-w-full bg-base-200 border border-base-300">
|
||||
<slot />
|
||||
</article>
|
||||
<SidebarRight />
|
||||
|
||||
</main>
|
||||
<Footer />
|
||||
<NotificationWrapper client:load />
|
||||
</container>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style is:global lang="scss">
|
||||
|
||||
:root {
|
||||
@apply bg-base-100 text-base-content;
|
||||
}
|
||||
|
||||
article {
|
||||
@apply rounded-lg w-full shadow-md border;
|
||||
}
|
||||
|
||||
.mainContent {
|
||||
p, h1, h2, h3, h4, h5, h6 {
|
||||
@apply text-base-content;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.button {
|
||||
@apply px-8 py-2 bg-secondary rounded-lg text-white font-medium hover:shadow-lg transition-all hover:underline active:bg-blue-900 text-center cursor-pointer;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
h3 {
|
||||
@apply text-xl font-medium mt-6 mb-4;
|
||||
}
|
||||
|
||||
input {
|
||||
@apply py-1.5 px-4 w-full rounded-lg outline-none text-lg text-slate-700 border bg-gray-50 transition-colors;
|
||||
}
|
||||
|
||||
input:hover,
|
||||
input:focus {
|
||||
@apply bg-gray-100;
|
||||
}
|
||||
|
||||
label {
|
||||
@apply text-base font-semibold;
|
||||
}
|
||||
</style>
|
||||
@@ -103,7 +103,7 @@ let lightTheme = Astro.cookies.get("theme").value === "light";
|
||||
|
||||
<body class="min-h-screen grid md:grid-cols-[300px_1fr]">
|
||||
<DashboardSidebar lightTheme={lightTheme} benutzer={benutzer} client:load></DashboardSidebar>
|
||||
<main class="p-8 overflow-auto h-screen bg-base-100">
|
||||
<main class="p-4 md:p-8 overflow-auto h-screen bg-base-100 pt-20 md:!pt-24">
|
||||
<slot />
|
||||
</main>
|
||||
</body>
|
||||
|
||||
@@ -1,17 +1,42 @@
|
||||
import { VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import { z } from "zod";
|
||||
import { verbrauchsausweisWohnenPDFValidator } from "./validators/verbrauchsausweis-wohnen-pdf-validator";
|
||||
|
||||
export function convertAusweisData(
|
||||
inputs: VerbrauchsausweisWohnenClient
|
||||
inputs: Partial<VerbrauchsausweisWohnenClient>
|
||||
): Record<string, string> {
|
||||
return {
|
||||
"gebaeude_stammdaten.adresse": inputs.gebaeude_aufnahme_allgemein.adresse || "",
|
||||
"gebaeude_stammdaten.gebaeudetyp":
|
||||
inputs.gebaeude_aufnahme_allgemein.gebaeudetyp || "",
|
||||
"gebaeude_stammdaten.baujahr_gebaeude":
|
||||
inputs.gebaeude_aufnahme_allgemein.baujahr_gebaeude.join(", ") || "",
|
||||
"gebaeude_stammdaten.baujahr_heizung":
|
||||
inputs.gebaeude_aufnahme_allgemein.baujahr_heizung.join(", ") || "",
|
||||
"gebaeude_stammdaten.plz": inputs.gebaeude_aufnahme_allgemein.plz || "",
|
||||
"gebaeude_stammdaten.ort": inputs.gebaeude_aufnahme_allgemein.ort || "",
|
||||
};
|
||||
// Wir wollen alle Werte zu einem Flachen Objekt umwandeln, sodass wir dass später benutzen können.
|
||||
// Dazu kommen noch einige wichtige Eigenschaften die man im PDF brauchen könnte.
|
||||
let pdfInputs: z.infer<typeof verbrauchsausweisWohnenPDFValidator> = {
|
||||
...inputs,
|
||||
pdf: {
|
||||
"brennstoff": [inputs.gebaeude_aufnahme_allgemein?.brennstoff_1, inputs.gebaeude_aufnahme_allgemein?.brennstoff_2].filter(x => x).join(", ")
|
||||
}
|
||||
}
|
||||
let result = recursiveFlatten(inputs, "");
|
||||
// Außerdem müssen wir alle Werte zu strings umwandeln.
|
||||
for (const key in result) {
|
||||
result[key] = String(result[key]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
function recursiveFlatten(obj: any, parentKey = ""): Record<string, string> {
|
||||
const result: Record<string, string> = {};
|
||||
|
||||
for (const key in obj) {
|
||||
const value = obj[key];
|
||||
|
||||
const newKey = parentKey ? `${parentKey}.${key}` : key;
|
||||
|
||||
if (typeof value === "object") {
|
||||
Object.assign(result, recursiveFlatten(value, newKey));
|
||||
} else {
|
||||
result[newKey] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import { getKlimafaktoren } from "#lib/Klimafaktoren";
|
||||
import { getHeizwertfaktor } from "#lib/server/Heizwertfaktor";
|
||||
import { Enums } from "@ibcornelsen/database/client";
|
||||
import moment from "moment";
|
||||
|
||||
export function energetischeNutzflaecheVerbrauchsausweisWohnen_2016(
|
||||
@@ -11,14 +12,15 @@ export function energetischeNutzflaecheVerbrauchsausweisWohnen_2016(
|
||||
}
|
||||
|
||||
let faktorKeller = 1.2;
|
||||
if (ausweis.keller_beheizt && (ausweis.gebaeude_aufnahme_allgemein.einheiten || 1) <= 2) {
|
||||
// Falls das Gebäude einen Keller besitzt der Beheizt ist erhöhen wir die Nutzfläche um 15%
|
||||
if (ausweis.gebaeude_aufnahme_allgemein.keller == Enums.Heizungsstatus.BEHEIZT && (ausweis.gebaeude_aufnahme_allgemein.einheiten || 1) <= 2) {
|
||||
faktorKeller = 1.35;
|
||||
}
|
||||
|
||||
if ((ausweis.gebaeude_aufnahme_allgemein.nutzflaeche || 0) > 0) {
|
||||
return ausweis.gebaeude_aufnahme_allgemein.nutzflaeche || 0;
|
||||
return ausweis.gebaeude_aufnahme_allgemein.nutzflaeche || 0;
|
||||
} else {
|
||||
return (ausweis.gebaeude_aufnahme_allgemein.flaeche || 1) * faktorKeller;
|
||||
return (ausweis.gebaeude_aufnahme_allgemein.flaeche || 0) * faktorKeller;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +131,10 @@ export async function endEnergieVerbrauchVerbrauchsausweis_2016(
|
||||
let energieVerbrauchHeizung_1 = energieVerbrauchGesamt_1;
|
||||
let energieVerbrauchHeizung_2 = energieVerbrauchGesamt_2;
|
||||
|
||||
// TODO: Im aktuellen Skript vom Live System kommt hier etwas anderes raus,
|
||||
// vielleicht ist da etwas kaputt? Da scheint es so, als wäre
|
||||
// warmwasser_enthalten immer true...
|
||||
// NOTE: Das hier müsste die richtige Version sein...
|
||||
if (ausweis.warmwasser_enthalten) {
|
||||
energieVerbrauchHeizung_1 -= energieVerbrauchWarmwasser_1;
|
||||
energieVerbrauchHeizung_2 -= energieVerbrauchWarmwasser_2;
|
||||
@@ -232,6 +238,29 @@ export async function endEnergieVerbrauchVerbrauchsausweis_2016(
|
||||
co2EmissionenLeerstandsZuschlag +
|
||||
co2EmissionenKuehlungsZuschlag;
|
||||
|
||||
// Energieeffizienzklasse
|
||||
let energieEffizienzKlasse = "";
|
||||
if (endEnergieVerbrauchGesamt < 30) {
|
||||
energieEffizienzKlasse = 'A+';
|
||||
}else if (endEnergieVerbrauchGesamt < 50) {
|
||||
energieEffizienzKlasse = 'A';
|
||||
}else if (endEnergieVerbrauchGesamt < 75) {
|
||||
energieEffizienzKlasse = 'B';
|
||||
}else if (endEnergieVerbrauchGesamt < 100) {
|
||||
energieEffizienzKlasse = 'C';
|
||||
}else if (endEnergieVerbrauchGesamt < 130) {
|
||||
energieEffizienzKlasse = 'D';
|
||||
}else if (endEnergieVerbrauchGesamt < 160) {
|
||||
energieEffizienzKlasse = 'E';
|
||||
}else if (endEnergieVerbrauchGesamt < 200) {
|
||||
energieEffizienzKlasse = 'F';
|
||||
}else if (endEnergieVerbrauchGesamt < 250) {
|
||||
energieEffizienzKlasse = 'G';
|
||||
}else if (endEnergieVerbrauchGesamt >= 250) {
|
||||
energieEffizienzKlasse = 'H';
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
brennstoff_1: brennstoff_1,
|
||||
brennstoff_2: brennstoff_2,
|
||||
@@ -262,7 +291,7 @@ export async function endEnergieVerbrauchVerbrauchsausweis_2016(
|
||||
(ausweis.verbrauch_6 || 0) * brennstoff_2.umrechnungsfaktor
|
||||
),
|
||||
|
||||
energetische_nutzfläche: Math.round(energetischeNutzflaeche),
|
||||
energetischeNutzflaeche: energetischeNutzflaeche,
|
||||
leerstand: leerstand,
|
||||
leerstandsZuschlagHeizung: Math.round(leerstandsZuschlagHeizung),
|
||||
leerstandsZuschlagWarmwasser: Math.round(leerstandsZuschlagWarmwasser),
|
||||
@@ -308,6 +337,9 @@ export async function endEnergieVerbrauchVerbrauchsausweis_2016(
|
||||
primaerEnergieVerbrauchKuehlungsZuschlag
|
||||
),
|
||||
|
||||
primaerfaktorww,
|
||||
primaerfaktorww_1,
|
||||
|
||||
co2Emissionen_1: co2Emissionen_1,
|
||||
co2Emissionen_2: co2Emissionen_2,
|
||||
|
||||
@@ -320,5 +352,6 @@ export async function endEnergieVerbrauchVerbrauchsausweis_2016(
|
||||
primaerEnergieVerbrauchGesamt: Math.round(
|
||||
primaerEnergieVerbrauchGesamt
|
||||
),
|
||||
energieEffizienzKlasse
|
||||
};
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ export class AusweisBerechnungen2016 {
|
||||
}
|
||||
|
||||
public getAusweisart() {
|
||||
switch (this.ausweis.ausweisart.toLowerCase()) {
|
||||
switch (this.ausweis.gebaeude_aufnahme_allgemein.ausweisart.toLowerCase()) {
|
||||
case ('va'):
|
||||
return {'typ' : 'Wohngebaeude', 'art' : 'Verbrauchsausweis Wohngebäude', 'kuerzel' : 'va'};
|
||||
case ('ba'):
|
||||
@@ -73,7 +73,7 @@ export class AusweisBerechnungen2016 {
|
||||
public getGebaeudeTeil() {
|
||||
if (this.gebaeude.gebaeudeteil == "Gesamtgebäude") {
|
||||
return "Ganzes Gebäude";
|
||||
} else if (this.gebaeude.gebaeudeteil == "Wohnen" && this.ausweis.ausweisart == "VANW") {
|
||||
} else if (this.gebaeude.gebaeudeteil == "Wohnen" && this.ausweis.gebaeude_aufnahme_allgemein.ausweisart == "VANW") {
|
||||
return "Teil des Wohngebäudes";
|
||||
} else {
|
||||
return "Teil des Nichtwohngebäudes";
|
||||
|
||||
@@ -1,33 +1,34 @@
|
||||
import type { GebaeudeStammdaten, VerbrauchsausweisWohnen } from "@ibcornelsen/database/client";
|
||||
import { VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import { Enums } from "@ibcornelsen/database/client";
|
||||
import moment from "moment";
|
||||
|
||||
export function getEmpfehlungen(ausweis: VerbrauchsausweisWohnen, gebaeude: GebaeudeStammdaten): {
|
||||
export function getEmpfehlungen(ausweis: VerbrauchsausweisWohnenClient): {
|
||||
title: string,
|
||||
description: string,
|
||||
anlagenteil: string
|
||||
}[] {
|
||||
let Warmwasserrohre_gedaemmt = gebaeude.warmwasser_rohre_gedaemmt;
|
||||
let Heizungsrohre_gedaemmt = gebaeude.heizungsrohre_gedaemmt;
|
||||
let Waermepumpe = gebaeude.waermepumpe;
|
||||
let Kellerwand_gedaemmt = gebaeude.keller_wand_gedaemmt;
|
||||
let Keller = ausweis.keller_beheizt;
|
||||
let Kellerdecke_Kalraeume_gedaemmt = gebaeude.keller_decke_gedaemmt;
|
||||
let Brennwertkessel = gebaeude.brennwert_kessel;
|
||||
let baujahr_anlagesanlage = gebaeude.baujahr_heizung[0];
|
||||
let Zentralheizung = gebaeude.zentralheizung;
|
||||
let photovoltaik = gebaeude.photovoltaik;
|
||||
let Brennstoff = ausweis.brennstoff_1;
|
||||
let Aussenwand_gedaemmt = gebaeude.aussenwand_gedaemmt;
|
||||
let Dachgeschoss = gebaeude.dachgeschoss;
|
||||
let Dachgeschoss_gedaemmt = gebaeude.dachgeschoss_gedaemmt;
|
||||
let Oberste_Geschossdecke_gedaemmt = gebaeude.oberste_geschossdecke_gedaemmt;
|
||||
let Einfachglas = gebaeude.einfach_verglasung;
|
||||
let Doppelfenster = gebaeude.doppel_verglasung;
|
||||
let Fenster_teilw_undicht = gebaeude.fenster_teilweise_undicht;
|
||||
let Warmwasserrohre_gedaemmt = ausweis.gebaeude_aufnahme_allgemein.warmwasser_rohre_gedaemmt;
|
||||
let Heizungsrohre_gedaemmt = ausweis.gebaeude_aufnahme_allgemein.heizungsrohre_gedaemmt;
|
||||
let Waermepumpe = ausweis.gebaeude_aufnahme_allgemein.waermepumpe;
|
||||
let Kellerwand_gedaemmt = ausweis.gebaeude_aufnahme_allgemein.keller_wand_gedaemmt;
|
||||
let Keller = ausweis.gebaeude_aufnahme_allgemein.keller;
|
||||
let Kellerdecke_Kalraeume_gedaemmt = ausweis.gebaeude_aufnahme_allgemein.keller_decke_gedaemmt;
|
||||
let Brennwertkessel = ausweis.gebaeude_aufnahme_allgemein.brennwert_kessel;
|
||||
let baujahr_anlagesanlage = ausweis.gebaeude_aufnahme_allgemein.baujahr_heizung[0];
|
||||
let Zentralheizung = ausweis.gebaeude_aufnahme_allgemein.zentralheizung;
|
||||
let photovoltaik = ausweis.gebaeude_aufnahme_allgemein.photovoltaik;
|
||||
let Brennstoff = ausweis.gebaeude_aufnahme_allgemein.brennstoff_1;
|
||||
let Aussenwand_gedaemmt = ausweis.gebaeude_aufnahme_allgemein.aussenwand_gedaemmt;
|
||||
let Dachgeschoss = ausweis.gebaeude_aufnahme_allgemein.dachgeschoss;
|
||||
let Dachgeschoss_gedaemmt = ausweis.gebaeude_aufnahme_allgemein.dachgeschoss_gedaemmt;
|
||||
let Oberste_Geschossdecke_gedaemmt = ausweis.gebaeude_aufnahme_allgemein.oberste_geschossdecke_gedaemmt;
|
||||
let Einfachglas = ausweis.gebaeude_aufnahme_allgemein.einfach_verglasung;
|
||||
let Doppelfenster = ausweis.gebaeude_aufnahme_allgemein.doppel_verglasung;
|
||||
let Fenster_teilw_undicht = ausweis.gebaeude_aufnahme_allgemein.fenster_teilweise_undicht;
|
||||
|
||||
let empfehlungen = [];
|
||||
|
||||
if (gebaeude.einfach_verglasung || (Doppelfenster && Fenster_teilw_undicht)) {
|
||||
if (ausweis.gebaeude_aufnahme_allgemein.einfach_verglasung || (Doppelfenster && Fenster_teilw_undicht)) {
|
||||
empfehlungen.push({
|
||||
"title" : "Erneuerung der Fenster",
|
||||
"description" : "Alte und undichte Fenster mit Wärmeschutzfenstern auswechseln.",
|
||||
@@ -35,13 +36,13 @@ export function getEmpfehlungen(ausweis: VerbrauchsausweisWohnen, gebaeude: Geba
|
||||
});
|
||||
}
|
||||
|
||||
if (gebaeude.dachgeschoss == "Unbeheizt" && !Oberste_Geschossdecke_gedaemmt) {
|
||||
if (ausweis.gebaeude_aufnahme_allgemein.dachgeschoss == Enums.Heizungsstatus.UNBEHEIZT && !Oberste_Geschossdecke_gedaemmt) {
|
||||
empfehlungen.push({
|
||||
"title" : "Zusätzliche Dämmung des Fußbodens des kalten Dachraumes",
|
||||
"description" : "Beim Einbringen sollten mindestens 16cm Dämmstoff verarbeitet werden. Das Einsparpotenzial ist für jeden zusätzlichen cm Dämmung sehr hoch.",
|
||||
"anlagenteil" : "Dach"
|
||||
});
|
||||
} else if (Dachgeschoss == "Beheizt" && !Dachgeschoss_gedaemmt) {
|
||||
} else if (Dachgeschoss == Enums.Heizungsstatus.BEHEIZT && !Dachgeschoss_gedaemmt) {
|
||||
empfehlungen.push({
|
||||
"title" : "Zusätzliche Dämmung des Daches bzw. Dachraumes",
|
||||
"description" : "Beim Einbringen sollten mindestens 16cm Dämmstoff, wenn möglich, verarbeitet werden. Das Einsparpotenzial ist für jeden zusätzlichen cm Dämmung sehr hoch.",
|
||||
@@ -67,13 +68,13 @@ export function getEmpfehlungen(ausweis: VerbrauchsausweisWohnen, gebaeude: Geba
|
||||
});
|
||||
}
|
||||
|
||||
if (!Kellerdecke_Kalraeume_gedaemmt && Keller == "Unbeheizt") {
|
||||
if (!Kellerdecke_Kalraeume_gedaemmt && Keller == Enums.Heizungsstatus.UNBEHEIZT) {
|
||||
empfehlungen.push({
|
||||
"title" : "Nachträgliche Dämmung der Kellerdecke",
|
||||
"description" : "Je nach Deckenhöhe, den vorhandenen Raum voll ausnutzen. Das Einsparpotenzial für jeden zusätzlichen cm Dämmung sehr hoch.",
|
||||
"anlagenteil" : "Kellerdecke"
|
||||
});
|
||||
} else if (!Kellerwand_gedaemmt && Keller == "Beheizt") {
|
||||
} else if (!Kellerwand_gedaemmt && Keller == Enums.Heizungsstatus.BEHEIZT) {
|
||||
empfehlungen.push({
|
||||
"title" : "Nachträgliche Dämmung der Kellerwände",
|
||||
"description" : "Man sollte mit Dämmstärken ab 12cm planen. Das Einsparpotenzial für jeden zusätzlichen cm Dämmung sehr hoch.",
|
||||
|
||||
133
src/lib/altes-system/import.ts
Normal file
133
src/lib/altes-system/import.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
import { VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import { faker } from "@faker-js/faker";
|
||||
import { Enums } from "@ibcornelsen/database/client";
|
||||
import moment from "moment";
|
||||
|
||||
export async function importVerbrauchsausweisWohnenAltesSystem(count: number = 5) {
|
||||
const response = await fetch("https://online-energieausweis.org/user/ausweis-import.php", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
i: count,
|
||||
offset: 0,
|
||||
q: {}
|
||||
})
|
||||
})
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
export function verbrauchsausweisWohnenImportTranslate(ausweis: Record<string, any>) {
|
||||
const ausweisTranslated: VerbrauchsausweisWohnenClient = {
|
||||
gebaeude_aufnahme_allgemein: {
|
||||
rechnungen: null,
|
||||
baujahr_gebaeude: [ausweis.baujahr_gebaeude],
|
||||
baujahr_heizung: [ausweis.baujahr_anlage],
|
||||
baujahr_klima: [ausweis.baujahr_klimaanlage],
|
||||
adresse: ausweis.objekt_strasse,
|
||||
plz: ausweis.objekt_plz,
|
||||
ort: ausweis.objekt_ort,
|
||||
nutzflaeche: ausweis.nutzflaeche,
|
||||
einheiten: ausweis.anzahl_einheiten,
|
||||
saniert: ausweis.objekt_saniert,
|
||||
keller: ausweis.keller_beheizt == "Beheizt" ? Enums.Heizungsstatus.BEHEIZT : ausweis.keller_beheizt == "Unbeheizt" ? Enums.Heizungsstatus.UNBEHEIZT : Enums.Heizungsstatus.NICHT_VORHANDEN,
|
||||
dachgeschoss: ausweis.dachgeschoss == "Beheizt" ? Enums.Heizungsstatus.BEHEIZT : ausweis.dachgeschoss == "Unbeheizt" ? Enums.Heizungsstatus.UNBEHEIZT : Enums.Heizungsstatus.NICHT_VORHANDEN,
|
||||
flaeche: ausweis.wohnflaeche,
|
||||
gebaeudetyp: ausweis.objekt_typ,
|
||||
gebaeudeteil: ausweis.objekt_gebaeudeteil,
|
||||
lueftung: ausweis.lueftungskonzept,
|
||||
kuehlung: ausweis.wird_gekuehlt,
|
||||
gebaeude_stammdaten: {
|
||||
adresse: ausweis.objekt_strasse,
|
||||
plz: ausweis.objekt_plz,
|
||||
ort: ausweis.objekt_ort,
|
||||
uid: faker.string.uuid(),
|
||||
gebaeude_bilder: [],
|
||||
latitude: null,
|
||||
longitude: null,
|
||||
},
|
||||
brennstoff_1: ausweis.energietraeger_1,
|
||||
brennstoff_2: ausweis.energietraeger_2,
|
||||
alternative_heizung: ausweis.alheizung,
|
||||
alternative_kuehlung: ausweis.alkuehlung,
|
||||
alternative_lueftung: ausweis.allueftung,
|
||||
alternative_warmwasser: ausweis.alwarmwasser,
|
||||
ausweisart: Enums.Ausweisart.VerbrauchsausweisWohnen,
|
||||
energieeffizienzklasse: "",
|
||||
aussenwand_gedaemmt: ausweis.aussenwand_gedaemmt,
|
||||
aussenwand_min_12cm_gedaemmt: ausweis.aussenwand_min_12cm_gedaemmt,
|
||||
bestellt: ausweis.bestellt,
|
||||
boxpruefung: ausweis.boxpruefung,
|
||||
brennwert_kessel: ausweis.brennwert_kessel,
|
||||
dachgeschoss_gedaemmt: ausweis.dachgeschoss_gedaemmt,
|
||||
dachgeschoss_min_12cm_gedaemmt: ausweis.dachgeschoss_min_12cm_gedaemmt,
|
||||
doppel_verglasung: ausweis.doppel_verglasung,
|
||||
dreifach_verglasung: ausweis.dreifach_verglasung,
|
||||
durchlauf_erhitzer: ausweis.durchlauf_erhitzer,
|
||||
einfach_verglasung: ausweis.einfach_verglasung,
|
||||
einzelofen: ausweis.einzelofen,
|
||||
erledigt: ausweis.erledigt,
|
||||
erstellungsdatum: ausweis.erstellungsdatum,
|
||||
fenster_dicht: ausweis.fenster_dicht,
|
||||
fenster_teilweise_undicht: ausweis.fenster_teilweise_undicht,
|
||||
heizungsrohre_gedaemmt: ausweis.heizungsrohre_gedaemmt,
|
||||
isolier_verglasung: ausweis.isolier_verglasung,
|
||||
keller_decke_gedaemmt: ausweis.keller_decke_gedaemmt,
|
||||
keller_wand_gedaemmt: ausweis.keller_wand_gedaemmt,
|
||||
niedertemperatur_kessel: ausweis.niedertemperatur_kessel,
|
||||
oberste_geschossdecke_gedaemmt: ausweis.oberste_geschossdecke_gedaemmt,
|
||||
oberste_geschossdecke_min_12cm_gedaemmt: ausweis.oberste_geschossdecke_min_12cm_gedaemmt,
|
||||
raum_temperatur_regler: ausweis.raum_temperatur_regler,
|
||||
rolllaeden_kaesten_gedaemmt: ausweis.rolllaeden_kaesten_gedaemmt,
|
||||
solarsystem_warmwasser: ausweis.solarsystem_warmwasser,
|
||||
standard_kessel: ausweis.standard_kessel,
|
||||
waermepumpe: ausweis.waermepumpe,
|
||||
warmwasser_rohre_gedaemmt: ausweis.warmwasser_rohre_gedaemmt,
|
||||
zentralheizung: ausweis.zentralheizung,
|
||||
zirkulation: ausweis.zirkulation,
|
||||
photovoltaik: ausweis.photovoltaik,
|
||||
leerstand: ausweis.leerstand,
|
||||
prueftext: ausweis["check-texts"],
|
||||
|
||||
storniert: false,
|
||||
tueren_dicht: ausweis.tueren_dicht,
|
||||
tueren_undicht: ausweis.tueren_undicht,
|
||||
zurueckgestellt: ausweis.zurueckGestellt,
|
||||
uid: faker.string.uuid(),
|
||||
events: []
|
||||
},
|
||||
verbrauch_1: parseInt(ausweis.energieverbrauch_1_heizquelle_1),
|
||||
verbrauch_2: parseInt(ausweis.energieverbrauch_2_heizquelle_1),
|
||||
verbrauch_3: parseInt(ausweis.energieverbrauch_3_heizquelle_1),
|
||||
verbrauch_4: parseInt(ausweis.energieverbrauch_1_heizquelle_2),
|
||||
verbrauch_5: parseInt(ausweis.energieverbrauch_2_heizquelle_2),
|
||||
verbrauch_6: parseInt(ausweis.energieverbrauch_3_heizquelle_2),
|
||||
einheit_1: ausweis.energietraeger_einheit_heizquelle_1,
|
||||
einheit_2: ausweis.energietraeger_einheit_heizquelle_2,
|
||||
warmwasser_enthalten: ausweis.warmwasser_enthalten,
|
||||
uid: faker.string.uuid(),
|
||||
alternative_heizung: ausweis.alheizung,
|
||||
alternative_kuehlung: ausweis.alkuehlung,
|
||||
alternative_lueftung: ausweis.allueftung,
|
||||
alternative_warmwasser: ausweis.alwarmwasser,
|
||||
anteil_warmwasser_1: ausweis.anteil_warmwasser_1,
|
||||
anteil_warmwasser_2: ausweis.anteil_warmwasser_2,
|
||||
ausstellgrund: ausweis.ausstellgrund,
|
||||
ausstellungsdatum: moment(ausweis.bestelldatum).toDate(),
|
||||
|
||||
erledigt: ausweis.erledigt,
|
||||
erstellungsdatum: moment(ausweis.erstellungsdatum).toDate(),
|
||||
keller_beheizt: ausweis.keller_beheizt,
|
||||
registriernummer: ausweis.regnummer,
|
||||
// Der Monat im alten System ist 1-basiert, in der neuen Datenbank 0-basiert
|
||||
// Also müssen wir hier 1 abziehen
|
||||
startdatum: moment(`${ausweis.energieverbrauch_zeitraum_jahr}-${ausweis.energieverbrauch_zeitraum_monat}-01`).toDate(),
|
||||
|
||||
warmwasser_anteil_bekannt: ausweis.warmwasser_anteil_bekannt,
|
||||
wird_gekuehlt: ausweis.wird_gekuehlt,
|
||||
zusaetzliche_heizquelle: ausweis.zusaetzliche_heizquelle,
|
||||
}
|
||||
|
||||
return ausweisTranslated
|
||||
}
|
||||
118
src/lib/faker/verbrauchsausweis-wohnen.ts
Normal file
118
src/lib/faker/verbrauchsausweis-wohnen.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import { VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import { faker } from "@faker-js/faker";
|
||||
import { Enums } from "@ibcornelsen/database/client";
|
||||
|
||||
export function verbrauchsausweisWohnenFaker(seed: number = 42): VerbrauchsausweisWohnenClient {
|
||||
faker.seed(seed);
|
||||
|
||||
const tuerenDicht = faker.datatype.boolean();
|
||||
const verbrauch_1 = faker.number.int({ min: 5000, max: 20000 });
|
||||
const verbrauch_4 = faker.number.int({ min: 5000, max: 15000 });
|
||||
|
||||
const ausweis: VerbrauchsausweisWohnenClient = {
|
||||
rechnungen: null,
|
||||
gebaeude_aufnahme_allgemein: {
|
||||
baujahr_gebaeude: [faker.number.int({ min: 1960, max: 2014 })],
|
||||
baujahr_heizung: [faker.number.int({ min: 1960, max: 2014 })],
|
||||
baujahr_klima: [faker.number.int({ min: 1985, max: 2014 })],
|
||||
adresse: faker.location.streetAddress(),
|
||||
plz: faker.location.zipCode({ format: "#####" }),
|
||||
ort: faker.location.city(),
|
||||
nutzflaeche: faker.number.int({ min: 50, max: 300 }),
|
||||
einheiten: faker.number.int({ min: 1, max: 3 }),
|
||||
saniert: faker.datatype.boolean(),
|
||||
keller: faker.helpers.enumValue(Enums.Heizungsstatus),
|
||||
dachgeschoss: faker.helpers.enumValue(Enums.Heizungsstatus),
|
||||
flaeche: faker.number.int({ min: 50, max: 300 }),
|
||||
gebaeudetyp: "Einfamilienhaus",
|
||||
gebaeudeteil: "Gesamtgebäude",
|
||||
lueftung: "Fensterlüftung",
|
||||
kuehlung: "Vorhanden",
|
||||
gebaeude_stammdaten: {
|
||||
adresse: faker.location.streetAddress(),
|
||||
plz: faker.location.zipCode({ format: "#####" }),
|
||||
ort: faker.location.city(),
|
||||
uid: faker.string.uuid(),
|
||||
gebaeude_bilder: [],
|
||||
latitude: faker.location.latitude(),
|
||||
longitude: faker.location.longitude(),
|
||||
},
|
||||
brennstoff_1: "Erdgas H",
|
||||
alternative_heizung: faker.datatype.boolean(),
|
||||
alternative_kuehlung: faker.datatype.boolean(),
|
||||
alternative_lueftung: faker.datatype.boolean(),
|
||||
alternative_warmwasser: faker.datatype.boolean(),
|
||||
aussenwand_gedaemmt: faker.datatype.boolean(),
|
||||
aussenwand_min_12cm_gedaemmt: faker.datatype.boolean(),
|
||||
ausweisart: Enums.Ausweisart.VerbrauchsausweisWohnen,
|
||||
bestellt: faker.datatype.boolean(),
|
||||
boxpruefung: faker.datatype.boolean(),
|
||||
brennstoff_2: "Erdgas H",
|
||||
brennwert_kessel: faker.datatype.boolean(),
|
||||
dachgeschoss_gedaemmt: faker.datatype.boolean(),
|
||||
dachgeschoss_min_12cm_gedaemmt: faker.datatype.boolean(),
|
||||
doppel_verglasung: faker.datatype.boolean(),
|
||||
dreifach_verglasung: faker.datatype.boolean(),
|
||||
durchlauf_erhitzer: faker.datatype.boolean(),
|
||||
einfach_verglasung: faker.datatype.boolean(),
|
||||
einzelofen: faker.datatype.boolean(),
|
||||
energieeffizienzklasse: "",
|
||||
erledigt: faker.datatype.boolean(),
|
||||
erstellungsdatum: faker.date.past(),
|
||||
fenster_dicht: faker.datatype.boolean(),
|
||||
fenster_teilweise_undicht: faker.datatype.boolean(),
|
||||
heizungsrohre_gedaemmt: faker.datatype.boolean(),
|
||||
isolier_verglasung: faker.datatype.boolean(),
|
||||
keller_decke_gedaemmt: faker.datatype.boolean(),
|
||||
keller_wand_gedaemmt: faker.datatype.boolean(),
|
||||
leerstand: faker.number.int({ min: 0, max: 20 }),
|
||||
niedertemperatur_kessel: faker.datatype.boolean(),
|
||||
oberste_geschossdecke_gedaemmt: faker.datatype.boolean(),
|
||||
oberste_geschossdecke_min_12cm_gedaemmt: faker.datatype.boolean(),
|
||||
photovoltaik: faker.datatype.boolean(),
|
||||
prueftext: faker.lorem.sentence(),
|
||||
raum_temperatur_regler: faker.datatype.boolean(),
|
||||
rolllaeden_kaesten_gedaemmt: faker.datatype.boolean(),
|
||||
solarsystem_warmwasser: faker.datatype.boolean(),
|
||||
standard_kessel: faker.datatype.boolean(),
|
||||
storniert: false,
|
||||
tueren_dicht: tuerenDicht,
|
||||
tueren_undicht: !tuerenDicht,
|
||||
waermepumpe: faker.datatype.boolean(),
|
||||
warmwasser_rohre_gedaemmt: faker.datatype.boolean(),
|
||||
zentralheizung: faker.datatype.boolean(),
|
||||
zirkulation: faker.datatype.boolean(),
|
||||
zurueckgestellt: faker.datatype.boolean(),
|
||||
uid: faker.string.uuid(),
|
||||
events: []
|
||||
},
|
||||
verbrauch_1: verbrauch_1,
|
||||
verbrauch_2: verbrauch_1 + faker.number.int({ min: -2000, max: 2000 }),
|
||||
verbrauch_3: verbrauch_1 + faker.number.int({ min: -2000, max: 2000 }),
|
||||
einheit_1: "kWh",
|
||||
warmwasser_enthalten: faker.datatype.boolean(),
|
||||
uid: faker.string.uuid(),
|
||||
alternative_heizung: faker.datatype.boolean(),
|
||||
alternative_kuehlung: faker.datatype.boolean(),
|
||||
alternative_lueftung: faker.datatype.boolean(),
|
||||
alternative_warmwasser: faker.datatype.boolean(),
|
||||
anteil_warmwasser_1: faker.number.int({ min: 0, max: 60 }),
|
||||
anteil_warmwasser_2: faker.number.int({ min: 0, max: 60 }),
|
||||
ausstellgrund: faker.helpers.enumValue(Enums.Ausstellgrund),
|
||||
ausstellungsdatum: faker.date.past(),
|
||||
einheit_2: "kWh",
|
||||
erledigt: faker.datatype.boolean(),
|
||||
erstellungsdatum: faker.date.past(),
|
||||
keller_beheizt: faker.datatype.boolean(),
|
||||
registriernummer: faker.string.uuid(),
|
||||
startdatum: faker.date.past({ years: 3 }),
|
||||
verbrauch_4: verbrauch_4,
|
||||
verbrauch_5: verbrauch_4 + faker.number.int({ min: -2000, max: 2000 }),
|
||||
verbrauch_6: verbrauch_4 + faker.number.int({ min: -2000, max: 2000 }),
|
||||
warmwasser_anteil_bekannt: faker.datatype.boolean(),
|
||||
wird_gekuehlt: faker.datatype.boolean(),
|
||||
zusaetzliche_heizquelle: faker.datatype.boolean(),
|
||||
}
|
||||
|
||||
return ausweis;
|
||||
}
|
||||
25
src/lib/helpers/zod.ts
Normal file
25
src/lib/helpers/zod.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { z } from "zod";
|
||||
|
||||
// get zod object keys recursively
|
||||
export const zodGetKeys = <T extends z.ZodTypeAny>(schema: T): string[] => {
|
||||
// make sure schema is not null or undefined
|
||||
if (schema === null || schema === undefined) return [];
|
||||
// check if schema is nullable or optional
|
||||
if (schema instanceof z.ZodNullable || schema instanceof z.ZodOptional) return zodGetKeys(schema.unwrap());
|
||||
// check if schema is an array
|
||||
if (schema instanceof z.ZodArray) return zodGetKeys(schema.element);
|
||||
// check if schema is an object
|
||||
if (schema instanceof z.ZodObject) {
|
||||
// get key/value pairs from schema
|
||||
const entries = Object.entries(schema.shape);
|
||||
// loop through key/value pairs
|
||||
return entries.flatMap(([key, value]) => {
|
||||
// get nested keys
|
||||
const nested = value instanceof z.ZodType ? zodGetKeys(value).map(subKey => `${key}.${subKey}`) : [];
|
||||
// return nested keys
|
||||
return nested.length ? nested : key;
|
||||
});
|
||||
}
|
||||
// return empty array
|
||||
return [];
|
||||
};
|
||||
@@ -1,14 +1,12 @@
|
||||
import {
|
||||
ZOOM,
|
||||
Plugin,
|
||||
Schema,
|
||||
PropPanel,
|
||||
DEFAULT_FONT_NAME,
|
||||
getFallbackFontName,
|
||||
PropPanelSchema,
|
||||
PropPanelWidgetProps,
|
||||
} from "@pdfme/common";
|
||||
import { image, text } from "@pdfme/schemas";
|
||||
import { text } from "@pdfme/schemas";
|
||||
import type { TextSchema } from "@pdfme/schemas/dist/types/src/text/types";
|
||||
|
||||
import {
|
||||
@@ -34,8 +32,10 @@ import {
|
||||
import {
|
||||
GebaeudeStammdaten,
|
||||
Rechnungen,
|
||||
VerbrauchsausweisWohnen,
|
||||
} from "@ibcornelsen/database/client";
|
||||
import { VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import { zodGetKeys } from "#lib/helpers/zod";
|
||||
import { verbrauchsausweisWohnenPDFValidator } from "#lib/validators/verbrauchsausweis-wohnen-pdf-validator";
|
||||
|
||||
const UseDynamicFontSize = (props: PropPanelWidgetProps) => {
|
||||
const { rootElement, changeSchemas, activeSchema, i18n } = props;
|
||||
@@ -62,51 +62,17 @@ const UseDynamicFontSize = (props: PropPanelWidgetProps) => {
|
||||
rootElement.appendChild(label);
|
||||
};
|
||||
|
||||
type AusweisIndex = keyof VerbrauchsausweisWohnen
|
||||
| `gebaeude_stammdaten.${keyof GebaeudeStammdaten}`
|
||||
| `rechnung.${keyof Rechnungen}`;
|
||||
type AusweisIndex = keyof Omit<Omit<VerbrauchsausweisWohnenClient, "gebaeude_aufnahme_allgemein">, "rechnungen">
|
||||
| `gebaeude_aufnahme_allgemein.${keyof VerbrauchsausweisWohnenClient["gebaeude_aufnahme_allgemein"]}`
|
||||
| `gebaeude_aufnahme_allgemein.gebaeude_stammdaten.${keyof VerbrauchsausweisWohnenClient["gebaeude_aufnahme_allgemein"]["gebaeude_stammdaten"]}`
|
||||
| `rechnungen.${keyof Rechnungen}`;
|
||||
|
||||
const sampleData: Partial<Record<AusweisIndex , string>> = {
|
||||
"gebaeude_stammdaten.adresse": "Musterstraße 123",
|
||||
"gebaeude_stammdaten.plz": "12345",
|
||||
"gebaeude_stammdaten.ort": "Musterstadt",
|
||||
"gebaeude_stammdaten.baujahr_gebaeude": "1990",
|
||||
"gebaeude_stammdaten.baujahr_heizung": "2000",
|
||||
}
|
||||
const ausweisKeys = zodGetKeys(verbrauchsausweisWohnenPDFValidator);
|
||||
|
||||
const variableOptions: {
|
||||
label: string;
|
||||
value: AusweisIndex;
|
||||
}[] = [
|
||||
{
|
||||
label: "Gebäude -> Adresse",
|
||||
value: "gebaeude_stammdaten.adresse",
|
||||
},
|
||||
{
|
||||
label: "Gebäude -> PLZ",
|
||||
value: "gebaeude_stammdaten.plz",
|
||||
},
|
||||
{
|
||||
label: "Gebaeude -> Ort",
|
||||
value: "gebaeude_stammdaten.ort",
|
||||
},
|
||||
{
|
||||
label: "Gebäude -> Baujahr Gebäude",
|
||||
value: "gebaeude_stammdaten.baujahr_gebaeude",
|
||||
},
|
||||
{
|
||||
label: "Gebäude -> Baujahr Heizung",
|
||||
value: "gebaeude_stammdaten.baujahr_heizung",
|
||||
},
|
||||
{
|
||||
label: "Gebäude -> Fläche",
|
||||
value: "gebaeude_stammdaten.flaeche"
|
||||
},
|
||||
{
|
||||
label: "Gebäude -> Einheiten",
|
||||
value: "gebaeude_stammdaten.einheiten"
|
||||
}
|
||||
];
|
||||
}[] = ausweisKeys.map((key: AusweisIndex) => ({ label: key as string, value: key }));
|
||||
|
||||
interface VariableSchema extends TextSchema {
|
||||
variable: AusweisIndex | undefined
|
||||
@@ -293,18 +259,21 @@ const propPanel: PropPanel<VariableSchema> = {
|
||||
backgroundColor: "",
|
||||
opacity: DEFAULT_OPACITY,
|
||||
variable: undefined
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
export const variable: Plugin<VariableSchema> = {
|
||||
ui: (props) => {
|
||||
if (props.schema.variable) {
|
||||
props.value = sampleData[props.schema.variable] as string;
|
||||
ui: function(props) {
|
||||
// Wir binden die inputs auf dieses Element, damit wir die Werte später auslesen können.
|
||||
if (props.schema.variable && this) {
|
||||
props.value = (this as unknown as Record<string, string>)[props.schema.variable] as string;
|
||||
}
|
||||
return text.ui(props);
|
||||
},
|
||||
pdf: (props) => {
|
||||
props.value = props.schema.variable as string;
|
||||
if (props.schema.variable && this) {
|
||||
props.value = (this as unknown as Record<string, string>)[props.schema.variable] as string;
|
||||
}
|
||||
text.pdf(props);
|
||||
},
|
||||
propPanel,
|
||||
|
||||
1
src/lib/pdf/templates/GEG24_Verbrauchsausweis.json
Normal file
1
src/lib/pdf/templates/GEG24_Verbrauchsausweis.json
Normal file
File diff suppressed because one or more lines are too long
BIN
src/lib/pdf/templates/GEG24_Wohngebaeude.pdf
Normal file
BIN
src/lib/pdf/templates/GEG24_Wohngebaeude.pdf
Normal file
Binary file not shown.
@@ -0,0 +1,8 @@
|
||||
import { VerbrauchsausweisWohnenValidator } from "@ibcornelsen/api/src/validators";
|
||||
import { z } from "zod";
|
||||
|
||||
export const verbrauchsausweisWohnenPDFValidator = VerbrauchsausweisWohnenValidator.merge(z.object({
|
||||
pdf: z.object({
|
||||
brennstoff: z.string()
|
||||
})
|
||||
}))
|
||||
@@ -9,7 +9,7 @@
|
||||
import ZipSearch from "#components/PlzSuche.svelte";
|
||||
import moment from "moment";
|
||||
import BilderZusatzsysteme from "#components/Ausweis/BilderZusatzsysteme.svelte";
|
||||
import { RawNotificationWrapper, RawNotification, notifications, addNotification, updateNotification } from "@ibcornelsen/ui";
|
||||
import { RawNotificationWrapper, RawNotification, notifications } from "@ibcornelsen/ui";
|
||||
import { auditHeizungGebaeudeBaujahr } from "#components/Verbrauchsausweis/audits/HeizungGebaeudeBaujahr";
|
||||
import { auditHeizungJuengerDreiJahre } from "#components/Verbrauchsausweis/audits/HeizungJuengerDreiJahre";
|
||||
import { auditZeitraumAktuell } from "#components/Verbrauchsausweis/audits/ZeitraumAktuell";
|
||||
@@ -17,157 +17,37 @@
|
||||
import { auditWohnFlaeche } from "#components/Verbrauchsausweis/audits/WohnFlaeche";
|
||||
import { auditWarmWasser } from "#components/Verbrauchsausweis/audits/WarmWasser";
|
||||
import { auditLeerStand } from "#components/Verbrauchsausweis/audits/LeerStand";
|
||||
import { auditPlzNichtErkannt } from "#components/Verbrauchsausweis/audits/PlzNichtErkannt";
|
||||
import { AuditType, hidden } from "#components/Verbrauchsausweis/audits/hidden";
|
||||
import { auditBedarfsausweisBenoetigt } from "#components/Verbrauchsausweis/audits/BedarfsausweisBenoetigt";
|
||||
import { auditVerbrauchAbweichung } from "#components/Verbrauchsausweis/audits/VerbrauchAbweichung";
|
||||
import { auditEndEnergie } from "#components/Verbrauchsausweis/audits/EndEnergie";
|
||||
import { auditWohnflaecheGroesserGesamtflaeche } from "#components/Verbrauchsausweis/audits/WohnflaecheGroesserGesamtflaeche";
|
||||
import { Enums } from "@ibcornelsen/database/client"
|
||||
import { client } from "src/trpc";
|
||||
import Overlay from "#components/Overlay.svelte";
|
||||
import AusweisGespeichertModule from "./AusweisGespeichertModule.svelte";
|
||||
import { validateAccessTokenClient } from "src/client/lib/validateAccessToken";
|
||||
import { VerbrauchsausweisWohnenClient, BenutzerClient } from "#components/Ausweis/types";
|
||||
import { dialogs } from "svelte-dialogs";
|
||||
import LoginDialog from "#components/LoginDialog.svelte";
|
||||
import { exclude } from "#lib/exclude";
|
||||
import { VerbrauchsausweisWohnenClient, BenutzerClient, UploadedGebaeudeBild } from "#components/Ausweis/types";
|
||||
import { verbrauchsausweisWohnenSpeichern } from "src/client/lib/verbrauchsausweisWohnenSpeichern";
|
||||
|
||||
// TODO: Vom Server sollte ein volles Objekt kommen, dass alle Subobjekte enthält, weil es sonst zu Problemen führen kann
|
||||
// wenn gebaeude_aufnahme_allgemein oder gebaeude_stammdaten nicht existiert...
|
||||
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||
export let user: BenutzerClient = {} as BenutzerClient;
|
||||
|
||||
let gebaeude_aufnahme_allgemein = ausweis.gebaeude_aufnahme_allgemein || {};
|
||||
let gebaeude = ausweis.gebaeude_aufnahme_allgemein?.gebaeude_stammdaten || {};
|
||||
let images = ausweis.gebaeude_aufnahme_allgemein?.gebaeude_stammdaten?.gebaeude_bilder || [];
|
||||
|
||||
async function bilderHochladen() {
|
||||
if (images.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const imagesToUpload = images.filter(image => !image.uid);
|
||||
|
||||
if (imagesToUpload.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Alle Bilder hochladen
|
||||
const notification = addNotification({
|
||||
dismissable: false,
|
||||
message: "Bilder hochladen.",
|
||||
subtext: `${imagesToUpload.length} Bilder werden hochgeladen, bitte haben sie Geduld.`,
|
||||
timeout: 0,
|
||||
type: "info"
|
||||
})
|
||||
for (let i = 0; i < imagesToUpload.length; i++) {
|
||||
const image = imagesToUpload[i];
|
||||
|
||||
try {
|
||||
const response = await client.v1.bilder.upload.mutate({
|
||||
base64: image.base64,
|
||||
kategorie: image.kategorie,
|
||||
gebaeude_uid: gebaeude.uid
|
||||
})
|
||||
|
||||
image.uid = response.uid
|
||||
|
||||
updateNotification(notification, {
|
||||
dismissable: true,
|
||||
message: "Bild hochgeladen.",
|
||||
subtext: `${i + 1}/${imagesToUpload.length} Bildern wurden erfolgreich hochgeladen.`,
|
||||
timeout: 3000
|
||||
})
|
||||
} catch (e) {
|
||||
updateNotification(notification, {
|
||||
dismissable: true,
|
||||
message: "Bild konnte nicht hochgeladen werden.",
|
||||
subtext: `Eines ihrer Bilder konnte nicht hochgeladen werden. Wir haben bereits ein Ticket erstellt und melden uns so schnell wie möglich bei ihnen.`,
|
||||
timeout: 15000,
|
||||
type: "error"
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
if (!await validateAccessTokenClient()) {
|
||||
// TOOD: Auf Dialog umstellen.
|
||||
const loggedIn = await dialogs.modal(LoginDialog);
|
||||
|
||||
if (!loggedIn) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ausweis.uid) {
|
||||
// Anscheinend wurde der Ausweis bereits erstellt und hat eine UID.
|
||||
// Jetzt müssen wir ihn nun nur noch abspeichern.
|
||||
try {
|
||||
const gebaeudeBilderEntfernt = exclude(gebaeude, ["gebaeude_bilder"])
|
||||
const gebaeudeAufnahmeGeneratedFieldsEntfernt = exclude(gebaeude_aufnahme_allgemein, ["erstellungsdatum"])
|
||||
const ausweisGeneratedFieldsEntfernt = exclude(ausweis, ["ausweisart", "rechnungen"])
|
||||
await client.v1.verbrauchsausweisWohnen[2016].speichern.mutate({
|
||||
...ausweisGeneratedFieldsEntfernt,
|
||||
gebaeude_aufnahme_allgemein: {
|
||||
...gebaeudeAufnahmeGeneratedFieldsEntfernt,
|
||||
gebaeude_stammdaten: {
|
||||
...gebaeudeBilderEntfernt
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
await bilderHochladen();
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
// TODO: Ticket mit Fehldermeldung abschicken.
|
||||
}
|
||||
} else {
|
||||
// Wir speichern den Ausweis ab und leiten auf die "ausweis-gespeichert" Seite weiter.
|
||||
try {
|
||||
const response = await client.v1.verbrauchsausweisWohnen[2016].erstellen.mutate({
|
||||
...ausweis,
|
||||
gebaeude_aufnahme_allgemein: {
|
||||
...gebaeude_aufnahme_allgemein,
|
||||
gebaeude_stammdaten: {
|
||||
...gebaeude
|
||||
}
|
||||
}
|
||||
})
|
||||
ausweis.uid = response.uid;
|
||||
gebaeude.uid = response.gebaeude_uid;
|
||||
gebaeude_aufnahme_allgemein.uid = response.gebaeude_aufnahme_uid
|
||||
|
||||
await bilderHochladen();
|
||||
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
await client.v1.tickets.erstellen.mutate({
|
||||
titel: "Ausweis konnte nicht gespeichert werden",
|
||||
beschreibung: e.stack,
|
||||
email: user.email ?? "",
|
||||
metadata: JSON.stringify({
|
||||
ausweis
|
||||
})
|
||||
})
|
||||
// TODO: Ticket mit Fehldermeldung abschicken.
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
let images: (UploadedGebaeudeBild & { base64?: string })[] = ausweis.gebaeude_aufnahme_allgemein?.gebaeude_stammdaten?.gebaeude_bilder || [];
|
||||
|
||||
async function spaeterWeitermachen() {
|
||||
const result = await ausweisSpeichern();
|
||||
const result = await verbrauchsausweisWohnenSpeichern(ausweis, gebaeude, gebaeude_aufnahme_allgemein, images, user);
|
||||
|
||||
if (result === true) {
|
||||
window.history.pushState({}, "", `${location.pathname}?uid=${ausweis.uid}`);
|
||||
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
|
||||
gebaeude.uid = result.gebaeude_uid
|
||||
gebaeude_aufnahme_allgemein.uid = result.gebaeude_aufnahme_uid
|
||||
window.history.pushState({}, "", `${location.pathname}?uid=${result.uid}`);
|
||||
speichernOverlayHidden = false;
|
||||
}
|
||||
}
|
||||
@@ -187,10 +67,10 @@
|
||||
gebaeude_aufnahme_allgemein.brennstoff_1 = "Erdgas H";
|
||||
ausweis.einheit_1 = "kWh";
|
||||
ausweis.anteil_warmwasser_1 = 18;
|
||||
ausweis.startdatum = moment("12.01.2019").toDate();
|
||||
gebaeude.plz = "21039";
|
||||
gebaeude.ort = "Hamburg";
|
||||
gebaeude.adresse = "Curslacker Deich 170";
|
||||
ausweis.startdatum = moment("01.01.2019").toDate();
|
||||
gebaeude_aufnahme_allgemein.plz = "21039";
|
||||
gebaeude_aufnahme_allgemein.ort = "Hamburg";
|
||||
gebaeude_aufnahme_allgemein.adresse = "Curslacker Deich 170";
|
||||
gebaeude_aufnahme_allgemein.gebaeudeteil = "Gesamtgebäude";
|
||||
|
||||
gebaeude = gebaeude;
|
||||
@@ -200,18 +80,31 @@
|
||||
|
||||
async function ausweisAbschicken(e: SubmitEvent) {
|
||||
if (e && e.preventDefault) e.preventDefault();
|
||||
const result = await ausweisSpeichern();
|
||||
const result = await verbrauchsausweisWohnenSpeichern(ausweis, gebaeude, gebaeude_aufnahme_allgemein, images, user);
|
||||
|
||||
if (result === true) {
|
||||
if (result !== null) {
|
||||
// Falls der Nutzer zurück navigiert, sollte er wieder auf seinen Vorgang kommen.
|
||||
// Sonst müsste er alles neu eingeben...
|
||||
window.history.pushState({}, "", `${location.pathname}?uid=${ausweis.uid}`);
|
||||
window.location.href = `/kundendaten?uid=${ausweis.uid}`;
|
||||
ausweis.uid = result.uid
|
||||
gebaeude.uid = result.gebaeude_uid
|
||||
gebaeude_aufnahme_allgemein.uid = result.gebaeude_aufnahme_uid
|
||||
window.history.pushState({}, "", `${location.pathname}?uid=${result.uid}`);
|
||||
window.location.href = `/kundendaten?uid=${result.uid}`;
|
||||
}
|
||||
}
|
||||
|
||||
let waitOverlayHidden = true;
|
||||
let speichernOverlayHidden = true;
|
||||
|
||||
$: {
|
||||
if (gebaeude_aufnahme_allgemein.saniert
|
||||
&& gebaeude_aufnahme_allgemein.oberste_geschossdecke_gedaemmt === undefined
|
||||
&& gebaeude_aufnahme_allgemein.dachgeschoss_gedaemmt === undefined) {
|
||||
|
||||
gebaeude_aufnahme_allgemein.oberste_geschossdecke_gedaemmt = true;
|
||||
gebaeude_aufnahme_allgemein.dachgeschoss_gedaemmt = true;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<Overlay bind:hidden={speichernOverlayHidden}>
|
||||
@@ -221,7 +114,9 @@
|
||||
</Overlay>
|
||||
|
||||
<Overlay bind:hidden={waitOverlayHidden}>
|
||||
<p class="text-white font-semibold text-4xl">Bitte warten sie, ihr Ausweis wird nun erstellt.</p>
|
||||
<p class="text-white font-semibold text-4xl">
|
||||
Bitte warten sie, ihr Ausweis wird nun erstellt.
|
||||
</p>
|
||||
</Overlay>
|
||||
|
||||
<div class="flex flex-row gap-8 items-center mb-8">
|
||||
@@ -230,15 +125,19 @@
|
||||
<Progressbar progress={0} />
|
||||
</div>
|
||||
|
||||
<PerformanceScore bind:ausweis />
|
||||
<PerformanceScore
|
||||
bind:ausweis
|
||||
bind:gebaeude_aufnahme_allgemein
|
||||
bind:gebaeude
|
||||
/>
|
||||
</div>
|
||||
|
||||
<form on:submit={ausweisAbschicken} name="ausweis" data-test="ausweis">
|
||||
<div
|
||||
class="yellow-box"
|
||||
>
|
||||
<div class="yellow-box">
|
||||
<div class="flex flex-row justify-between">
|
||||
<button class="button" type="button" on:click={spaeterWeitermachen}>Später Weitermachen</button>
|
||||
<button class="button" type="button" on:click={spaeterWeitermachen}
|
||||
>Später Weitermachen</button
|
||||
>
|
||||
<div class="flex gap-4">
|
||||
<Hilfe />
|
||||
<button
|
||||
@@ -253,7 +152,11 @@
|
||||
|
||||
<Label>A - Prüfung der Ausweisart</Label>
|
||||
|
||||
<Ausweisart bind:gebaeude bind:gebaeude_aufnahme_allgemein bind:ausweis />
|
||||
<Ausweisart
|
||||
bind:gebaeude
|
||||
bind:gebaeude_aufnahme_allgemein
|
||||
bind:ausweis
|
||||
/>
|
||||
|
||||
<hr />
|
||||
|
||||
@@ -271,13 +174,14 @@
|
||||
</HelpLabel>
|
||||
<div>
|
||||
<input
|
||||
name="adresse" data-test="adresse"
|
||||
name="adresse"
|
||||
data-test="adresse"
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
required
|
||||
data-msg-minlength="min. 5 Zeichen"
|
||||
data-msg-maxlength="max. 40 Zeichen"
|
||||
bind:value={gebaeude.adresse}
|
||||
bind:value={gebaeude_aufnahme_allgemein.adresse}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -285,9 +189,9 @@
|
||||
<!-- PLZ -->
|
||||
<div class="form-group col-md-4 PLZ">
|
||||
<ZipSearch
|
||||
bind:zip={gebaeude.plz}
|
||||
bind:city={gebaeude.ort}
|
||||
name="plz" data-test="plz"
|
||||
bind:zip={gebaeude_aufnahme_allgemein.plz}
|
||||
bind:city={gebaeude_aufnahme_allgemein.ort}
|
||||
name="plz"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -297,9 +201,10 @@
|
||||
</HelpLabel>
|
||||
<div>
|
||||
<input
|
||||
name="ort" data-test="ort"
|
||||
name="ort"
|
||||
data-test="ort"
|
||||
readonly={true}
|
||||
bind:value={gebaeude.ort}
|
||||
bind:value={gebaeude_aufnahme_allgemein.ort}
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
@@ -314,7 +219,8 @@
|
||||
</HelpLabel>
|
||||
<div>
|
||||
<input
|
||||
name="flaeche" data-test="flaeche"
|
||||
name="flaeche"
|
||||
data-test="flaeche"
|
||||
maxlength="4"
|
||||
type="number"
|
||||
required
|
||||
@@ -331,14 +237,21 @@
|
||||
<Label>Keller *</Label>
|
||||
<div>
|
||||
<select
|
||||
name="keller" data-test="keller"
|
||||
name="keller"
|
||||
data-test="keller"
|
||||
required
|
||||
bind:value={gebaeude_aufnahme_allgemein.keller}
|
||||
>
|
||||
<option disabled>Bitte auswählen</option>
|
||||
<option value={Enums.Heizungsstatus.NICHT_VORHANDEN}>nicht vorhanden</option>
|
||||
<option value={Enums.Heizungsstatus.UNBEHEIZT}>unbeheizt</option>
|
||||
<option value={Enums.Heizungsstatus.BEHEIZT}>beheizt</option>
|
||||
<option value={Enums.Heizungsstatus.NICHT_VORHANDEN}
|
||||
>nicht vorhanden</option
|
||||
>
|
||||
<option value={Enums.Heizungsstatus.UNBEHEIZT}
|
||||
>unbeheizt</option
|
||||
>
|
||||
<option value={Enums.Heizungsstatus.BEHEIZT}
|
||||
>beheizt</option
|
||||
>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -347,11 +260,22 @@
|
||||
<div class="form-group col-md-3">
|
||||
<Label>Dachgeschoss *</Label>
|
||||
<div>
|
||||
<select name="dachgeschoss" data-test="dachgeschoss" bind:value={gebaeude_aufnahme_allgemein.dachgeschoss} required>
|
||||
<select
|
||||
name="dachgeschoss"
|
||||
data-test="dachgeschoss"
|
||||
bind:value={gebaeude_aufnahme_allgemein.dachgeschoss}
|
||||
required
|
||||
>
|
||||
<option disabled>Bitte auswählen</option>
|
||||
<option value={Enums.Heizungsstatus.NICHT_VORHANDEN}>nicht vorhanden</option>
|
||||
<option value={Enums.Heizungsstatus.UNBEHEIZT}>unbeheizt</option>
|
||||
<option value={Enums.Heizungsstatus.BEHEIZT}>beheizt</option>
|
||||
<option value={Enums.Heizungsstatus.NICHT_VORHANDEN}
|
||||
>nicht vorhanden</option
|
||||
>
|
||||
<option value={Enums.Heizungsstatus.UNBEHEIZT}
|
||||
>unbeheizt</option
|
||||
>
|
||||
<option value={Enums.Heizungsstatus.BEHEIZT}
|
||||
>beheizt</option
|
||||
>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -359,14 +283,16 @@
|
||||
<!-- Gesamtfläche -->
|
||||
<div class="form-group col-md-3">
|
||||
<HelpLabel title="Gesamtfläche m²">
|
||||
Bitte geben Sie hier die beheizte Gesamtfläche in m² ein (wenn bekannt).
|
||||
Dabei handelt es sich um die Wohnfläche + weiterer Flächen innerhalb des Gebäudes
|
||||
(z.B. Fläche des beheizten Kellers).
|
||||
Diese Fläche wird dann im Energieausweis als energetische Nutzfläche (An) ausgewiesen.
|
||||
Bitte geben Sie hier die beheizte Gesamtfläche in m² ein
|
||||
(wenn bekannt). Dabei handelt es sich um die Wohnfläche +
|
||||
weiterer Flächen innerhalb des Gebäudes (z.B. Fläche des
|
||||
beheizten Kellers). Diese Fläche wird dann im Energieausweis
|
||||
als energetische Nutzfläche (An) ausgewiesen.
|
||||
</HelpLabel>
|
||||
<div>
|
||||
<input
|
||||
name="nutzflaeche" data-test="nutzflaeche"
|
||||
name="nutzflaeche"
|
||||
data-test="nutzflaeche"
|
||||
maxlength="4"
|
||||
type="number"
|
||||
required
|
||||
@@ -384,7 +310,11 @@
|
||||
<Label>C - Eingabe von 3 zusammenhängenden Verbrauchsjahren</Label>
|
||||
|
||||
<div class="GRB">
|
||||
<Verbrauch bind:gebaeude bind:gebaeude_aufnahme_allgemein bind:ausweis />
|
||||
<Verbrauch
|
||||
bind:gebaeude
|
||||
bind:gebaeude_aufnahme_allgemein
|
||||
bind:ausweis
|
||||
/>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
@@ -399,22 +329,24 @@
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-row gap-4 items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox"
|
||||
name="warmwasser_enthalten" data-test="warmwasser_enthalten"
|
||||
bind:checked={ausweis.warmwasser_enthalten}
|
||||
/>
|
||||
<Label>Warmwasser im Verbrauch enthalten</Label>
|
||||
type="checkbox"
|
||||
class="checkbox"
|
||||
name="warmwasser_enthalten"
|
||||
data-test="warmwasser_enthalten"
|
||||
bind:checked={ausweis.warmwasser_enthalten}
|
||||
/>
|
||||
<Label>Warmwasser im Verbrauch enthalten</Label>
|
||||
</div>
|
||||
<div class="flex flex-row gap-4 items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox"
|
||||
name="warmwasser_anteil_bekannt" data-test="warmwasser_anteil_bekannt"
|
||||
bind:checked={ausweis.warmwasser_anteil_bekannt}
|
||||
disabled={!ausweis.warmwasser_enthalten}
|
||||
/>
|
||||
<Label>Anteil bekannt</Label>
|
||||
type="checkbox"
|
||||
class="checkbox"
|
||||
name="warmwasser_anteil_bekannt"
|
||||
data-test="warmwasser_anteil_bekannt"
|
||||
bind:checked={ausweis.warmwasser_anteil_bekannt}
|
||||
disabled={!ausweis.warmwasser_enthalten}
|
||||
/>
|
||||
<Label>Anteil bekannt</Label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -426,11 +358,13 @@
|
||||
</HelpLabel>
|
||||
|
||||
<input
|
||||
name="anteil_warmwasser_1" data-test="anteil_warmwasser_1"
|
||||
name="anteil_warmwasser_1"
|
||||
data-test="anteil_warmwasser_1"
|
||||
maxlength="2"
|
||||
type="number"
|
||||
bind:value={ausweis.anteil_warmwasser_1}
|
||||
disabled={!ausweis.warmwasser_anteil_bekannt || !ausweis.warmwasser_enthalten}
|
||||
disabled={!ausweis.warmwasser_anteil_bekannt ||
|
||||
!ausweis.warmwasser_enthalten}
|
||||
autocomplete="off"
|
||||
/>
|
||||
</div>
|
||||
@@ -442,13 +376,15 @@
|
||||
ein Anteil von 18% angenommen.
|
||||
</HelpLabel>
|
||||
<input
|
||||
name="anteil_warmwasser_2" data-test="anteil_warmwasser_2"
|
||||
name="anteil_warmwasser_2"
|
||||
data-test="anteil_warmwasser_2"
|
||||
maxlength="3"
|
||||
type="number"
|
||||
autocomplete="off"
|
||||
bind:value={ausweis.anteil_warmwasser_2}
|
||||
disabled={!ausweis.zusaetzliche_heizquelle ||
|
||||
!ausweis.warmwasser_anteil_bekannt || !ausweis.warmwasser_enthalten}
|
||||
!ausweis.warmwasser_anteil_bekannt ||
|
||||
!ausweis.warmwasser_enthalten}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -465,7 +401,8 @@
|
||||
<label class="checkbox-inline"
|
||||
><input
|
||||
type="checkbox"
|
||||
name="alternative_heizung" data-test="alternative_heizung"
|
||||
name="alternative_heizung"
|
||||
data-test="alternative_heizung"
|
||||
bind:checked={ausweis.alternative_heizung}
|
||||
value="Heizung"
|
||||
/>Heizung</label
|
||||
@@ -473,7 +410,8 @@
|
||||
<label class="checkbox-inline"
|
||||
><input
|
||||
type="checkbox"
|
||||
name="alternative_warmwasser" data-test="alternative_warmwasser"
|
||||
name="alternative_warmwasser"
|
||||
data-test="alternative_warmwasser"
|
||||
bind:checked={ausweis.alternative_warmwasser}
|
||||
value="Warmwasser"
|
||||
/>Warmwasser</label
|
||||
@@ -481,7 +419,8 @@
|
||||
<label class="checkbox-inline"
|
||||
><input
|
||||
type="checkbox"
|
||||
name="alternative_lueftung" data-test="alternative_lueftung"
|
||||
name="alternative_lueftung"
|
||||
data-test="alternative_lueftung"
|
||||
bind:checked={ausweis.alternative_lueftung}
|
||||
value="Lüftung"
|
||||
/>Lüftung</label
|
||||
@@ -489,7 +428,8 @@
|
||||
<label class="checkbox-inline"
|
||||
><input
|
||||
type="checkbox"
|
||||
name="alternative_kuehlung" data-test="alternative_kuehlung"
|
||||
name="alternative_kuehlung"
|
||||
data-test="alternative_kuehlung"
|
||||
bind:checked={ausweis.alternative_kuehlung}
|
||||
value="Kühlung"
|
||||
/>Kühlung</label
|
||||
@@ -512,7 +452,12 @@
|
||||
Bitte wählen Sie hier den Gebäudetyp aus.
|
||||
</HelpLabel>
|
||||
<div>
|
||||
<select name="gebaeudetyp" data-test="gebaeudetyp" required>
|
||||
<select
|
||||
name="gebaeudetyp"
|
||||
data-test="gebaeudetyp"
|
||||
bind:value={gebaeude_aufnahme_allgemein.gebaeudetyp}
|
||||
required
|
||||
>
|
||||
<option disabled>Bitte auswählen</option>
|
||||
<option value="Einfamilienhaus">Einfamilienhaus</option>
|
||||
<option value="Freistehendes Einfamilienhaus"
|
||||
@@ -551,7 +496,12 @@
|
||||
'Gewerbe'.
|
||||
</HelpLabel>
|
||||
<div>
|
||||
<select name="gebaeudeteil" data-test="gebaeudeteil" required>
|
||||
<select
|
||||
name="gebaeudeteil"
|
||||
data-test="gebaeudeteil"
|
||||
bind:value={gebaeude_aufnahme_allgemein.gebaeudeteil}
|
||||
required
|
||||
>
|
||||
<option disabled>Bitte auswählen</option>
|
||||
<option value="Gesamtgebäude">Gesamtgebäude</option>
|
||||
<option value="Wohnen">Wohnen</option>
|
||||
@@ -567,7 +517,8 @@
|
||||
</HelpLabel>
|
||||
<div>
|
||||
<select
|
||||
name="lueftung" data-test="lueftung"
|
||||
name="lueftung"
|
||||
data-test="lueftung"
|
||||
required
|
||||
bind:value={gebaeude_aufnahme_allgemein.lueftung}
|
||||
>
|
||||
@@ -592,7 +543,8 @@
|
||||
</HelpLabel>
|
||||
<div>
|
||||
<select
|
||||
name="kuehlung" data-test="kuehlung"
|
||||
name="kuehlung"
|
||||
data-test="kuehlung"
|
||||
required
|
||||
bind:value={gebaeude_aufnahme_allgemein.kuehlung}
|
||||
>
|
||||
@@ -612,7 +564,8 @@
|
||||
</HelpLabel>
|
||||
<div>
|
||||
<input
|
||||
name="leerstand" data-test="leerstand"
|
||||
name="leerstand"
|
||||
data-test="leerstand"
|
||||
maxlength="2"
|
||||
type="number"
|
||||
bind:value={gebaeude_aufnahme_allgemein.leerstand}
|
||||
@@ -627,7 +580,7 @@
|
||||
>F - Bitte prüfen Sie hier die Angaben zum Sanierungszustand des
|
||||
Gebäudes</Label
|
||||
>
|
||||
<BilderZusatzsysteme {images} {gebaeude} {gebaeude_aufnahme_allgemein} {ausweis} />
|
||||
<BilderZusatzsysteme bind:images bind:gebaeude bind:gebaeude_aufnahme_allgemein bind:ausweis />
|
||||
<hr />
|
||||
<div class="flex flex-row justify-between">
|
||||
<Hilfe />
|
||||
@@ -636,7 +589,6 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
<RawNotificationWrapper>
|
||||
{#each Object.entries($notifications) as [uid, notification] (uid)}
|
||||
<RawNotification notification={{ ...notification, uid }}>
|
||||
@@ -660,6 +612,28 @@
|
||||
</RawNotification>
|
||||
{/if}
|
||||
|
||||
{#await auditPlzNichtErkannt(gebaeude_aufnahme_allgemein) then result}
|
||||
{#if result}
|
||||
<RawNotification
|
||||
notification={{
|
||||
message: "Plausibilitätsprüfung",
|
||||
timeout: 0,
|
||||
uid: "PLZ_NICHT_ERKANNT",
|
||||
dismissable: true,
|
||||
onUserDismiss: () => {
|
||||
hidden.add(AuditType.PLZ_NICHT_ERKANNT);
|
||||
gebaeude = gebaeude;
|
||||
},
|
||||
type: "warning",
|
||||
}}
|
||||
>
|
||||
Die Postleitzahl konnte nicht zugeordnet werden. Bitte prüfen
|
||||
Sie die Eingabe. Sollte die Postleitzahl korrekt eingegeben
|
||||
sein, werden wir den Ort händisch zuordnen.
|
||||
</RawNotification>
|
||||
{/if}
|
||||
{/await}
|
||||
|
||||
{#if auditHeizungGebaeudeBaujahr(gebaeude_aufnahme_allgemein)}
|
||||
<RawNotification
|
||||
notification={{
|
||||
@@ -693,11 +667,12 @@
|
||||
type: "warning",
|
||||
}}
|
||||
>
|
||||
Ihre Heizungsanlage ist jünger als 3 Jahre. Für den Verbrauchsausweis müssen
|
||||
Sie mindestens 3 Verbrauchsjahre eingeben die den aktuellen Stand des Gebäudes
|
||||
abbilden. Ein Verbrauchsausweis ist daher nicht möglich. Bitte klicken Sie
|
||||
<a href="/bedarfsausweis">hier</a> um zum Eingabeformular für den Bedarfsausweis
|
||||
zu gelangen.
|
||||
Ihre Heizungsanlage ist jünger als 3 Jahre. Für den
|
||||
Verbrauchsausweis müssen Sie mindestens 3 Verbrauchsjahre eingeben
|
||||
die den aktuellen Stand des Gebäudes abbilden. Ein Verbrauchsausweis
|
||||
ist daher nicht möglich. Bitte klicken Sie
|
||||
<a href="/bedarfsausweis">hier</a> um zum Eingabeformular für den Bedarfsausweis
|
||||
zu gelangen.
|
||||
</RawNotification>
|
||||
{/if}
|
||||
|
||||
@@ -715,11 +690,11 @@
|
||||
type: "warning",
|
||||
}}
|
||||
>
|
||||
Die Verbrauchszeiträume sind nicht aktuell genug. Das Ende des letzten
|
||||
Verbrauchszeitraumes darf nicht mehr als 18 Monate zurückliegen. Ein
|
||||
Verbrauchsausweis ist mit diesen Zeiträumen daher nicht möglich. Bitte
|
||||
klicken Sie <a href="/bedarfsausweis">hier</a> um zum Eingabeformular
|
||||
für den Bedarfsausweis zu gelangen.
|
||||
Die Verbrauchszeiträume sind nicht aktuell genug. Das Ende des
|
||||
letzten Verbrauchszeitraumes darf nicht mehr als 18 Monate
|
||||
zurückliegen. Ein Verbrauchsausweis ist mit diesen Zeiträumen daher
|
||||
nicht möglich. Bitte klicken Sie <a href="/bedarfsausweis">hier</a> um
|
||||
zum Eingabeformular für den Bedarfsausweis zu gelangen.
|
||||
</RawNotification>
|
||||
{/if}
|
||||
|
||||
@@ -738,11 +713,12 @@
|
||||
type: "warning",
|
||||
}}
|
||||
>
|
||||
Die Verbrauchszeiträume sind zu aktuell und es liegen noch keine
|
||||
Klimafaktoren dazu vor. Bitte verschieben Sie die Verbrauchszeiträume
|
||||
1 Jahr nach hinten. Wenn das nicht möglich ist, klicken Sie
|
||||
<a href="/bedarfsausweis">hier</a> um zum Eingabeformular für den
|
||||
Bedarfsausweis zu gelangen.
|
||||
Die Verbrauchszeiträume sind zu aktuell und es liegen noch keine
|
||||
Klimafaktoren dazu vor. Bitte verschieben Sie die
|
||||
Verbrauchszeiträume 1 Jahr nach hinten. Wenn das nicht möglich
|
||||
ist, klicken Sie
|
||||
<a href="/bedarfsausweis">hier</a> um zum Eingabeformular für den
|
||||
Bedarfsausweis zu gelangen.
|
||||
</RawNotification>
|
||||
{/if}
|
||||
{/await}
|
||||
@@ -761,8 +737,9 @@
|
||||
type: "warning",
|
||||
}}
|
||||
>
|
||||
Die Wohnfläche ist viel zu klein. Bitte überprüfen Sie Ihre Eingabe nochmal
|
||||
und stellen sicher, daß sich Ihre Angaben auf das gesamte Gebäude beziehen.
|
||||
Die Wohnfläche ist viel zu klein. Bitte überprüfen Sie Ihre Eingabe
|
||||
nochmal und stellen sicher, daß sich Ihre Angaben auf das gesamte
|
||||
Gebäude beziehen.
|
||||
</RawNotification>
|
||||
{/if}
|
||||
|
||||
@@ -780,8 +757,8 @@
|
||||
type: "warning",
|
||||
}}
|
||||
>
|
||||
Bitte überprüfen Sie nochmal die Höhe des Warmwasseranteils. Dieser scheint
|
||||
nicht ganz im Rahmen zu liegen.
|
||||
Bitte überprüfen Sie nochmal die Höhe des Warmwasseranteils. Dieser
|
||||
scheint nicht ganz im Rahmen zu liegen.
|
||||
</RawNotification>
|
||||
{/if}
|
||||
|
||||
@@ -799,9 +776,9 @@
|
||||
type: "warning",
|
||||
}}
|
||||
>
|
||||
Bei Leerstand größer als 30% darf kein Verbrauchsausweis ausgestellt werden.
|
||||
Bitte klicken Sie <a href="/bedarfsausweis">hier</a> um zum Eingabeformular
|
||||
für den Bedarfsausweis zu gelangen.
|
||||
Bei Leerstand größer als 30% darf kein Verbrauchsausweis ausgestellt
|
||||
werden. Bitte klicken Sie <a href="/bedarfsausweis">hier</a> um zum Eingabeformular
|
||||
für den Bedarfsausweis zu gelangen.
|
||||
</RawNotification>
|
||||
{/if}
|
||||
|
||||
@@ -819,17 +796,59 @@
|
||||
type: "warning",
|
||||
}}
|
||||
>
|
||||
Die Abweichung der Verbräuche zwischen Zeitraum {auditVerbrauchAbweichung(ausweis,
|
||||
gebaeude
|
||||
)[0]} und {auditVerbrauchAbweichung(ausweis, gebaeude)[1]} beträgt mehr als 25%
|
||||
und sie haben keinen Leerstand angegeben. Sind sie sich sicher, dass
|
||||
das stimmt?
|
||||
Die Abweichung der Verbräuche zwischen Zeitraum {auditVerbrauchAbweichung(
|
||||
ausweis,
|
||||
gebaeude,
|
||||
)[0]} und {auditVerbrauchAbweichung(ausweis, gebaeude)[1]} beträgt mehr
|
||||
als 30% und sie haben keinen Leerstand angegeben. Sind sie sich sicher,
|
||||
dass das stimmt?
|
||||
</RawNotification>
|
||||
{/if}
|
||||
|
||||
{#await auditEndEnergie(ausweis, gebaeude, gebaeude_aufnahme_allgemein) then result}
|
||||
{#if result}
|
||||
<RawNotification
|
||||
notification={{
|
||||
message: "Plausibilitätsprüfung",
|
||||
timeout: 0,
|
||||
uid: "END_ENERGIE",
|
||||
dismissable: true,
|
||||
onUserDismiss: () => {
|
||||
hidden.add(AuditType.END_ENERGIE);
|
||||
gebaeude = gebaeude;
|
||||
},
|
||||
type: "warning",
|
||||
}}
|
||||
>
|
||||
Die Endenergie liegt außerhalb des normalen Rahmens. Bitte
|
||||
nochmal überprüfen. Bei Passivhäusern oder ganz alten
|
||||
unsanierten Gebäuden ist so eine Abweichung durchaus möglich.
|
||||
</RawNotification>
|
||||
{/if}
|
||||
{/await}
|
||||
|
||||
{#if auditWohnflaecheGroesserGesamtflaeche(gebaeude_aufnahme_allgemein)}
|
||||
<RawNotification
|
||||
notification={{
|
||||
message: "Plausibilitätsprüfung",
|
||||
timeout: 0,
|
||||
uid: "WOHNFLAECHE_GROESSER_GESAMTFLAECHE",
|
||||
dismissable: true,
|
||||
onUserDismiss: () => {
|
||||
hidden.add(AuditType.WOHNFLAECHE_GROESSER_GESAMTFLAECHE);
|
||||
gebaeude = gebaeude;
|
||||
},
|
||||
type: "warning",
|
||||
}}
|
||||
>
|
||||
Die Wohnfläche darf nicht größer als die Nutzfläche sein.
|
||||
</RawNotification>
|
||||
{/if}
|
||||
</RawNotificationWrapper>
|
||||
|
||||
<style>
|
||||
:global(input[type="number"]), :global(input[type="text"]) {
|
||||
:global(input[type="number"]),
|
||||
:global(input[type="text"]) {
|
||||
@apply input input-bordered py-1.5 px-2 h-auto;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
limit: 10
|
||||
});
|
||||
|
||||
console.log(ausweise);
|
||||
|
||||
|
||||
if (!ausweise) return;
|
||||
|
||||
ausweisUeberpruefung = ausweise.map(ausweis => verbrauchsausweisWohnenCalculateFormProgress(ausweis));
|
||||
|
||||
@@ -61,9 +61,9 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<h1 class="text-4xl font-medium my-8">Einstellungen</h1>
|
||||
<Tabs class="h-full">
|
||||
<div class="grid grid-cols-[1fr_3fr] h-full gap-8">
|
||||
<h1 class="text-4xl font-medium mb-8">Einstellungen</h1>
|
||||
<Tabs class="h-[calc(100%-6rem)]">
|
||||
<div class="grid grid-cols-1 md:grid-cols-[1fr_3fr] h-full gap-8">
|
||||
<TabList>
|
||||
<Tab>
|
||||
<Person size={22} />
|
||||
@@ -106,7 +106,7 @@
|
||||
<TabPanel>
|
||||
<h2 class="text-2xl font-medium">Profil</h2>
|
||||
<form class="flex flex-col gap-4 my-4 max-w-2xl" on:submit={profilSpeichern}>
|
||||
<div class="flex flex-row gap-4">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="flex flex-col">
|
||||
<span class="whitespace-nowrap">Vorname</span>
|
||||
<input type="text" class="input text-base-content font-medium" placeholder="Max" bind:value={benutzer.vorname}>
|
||||
@@ -124,7 +124,7 @@
|
||||
<span class="whitespace-nowrap">Telefonnummer</span>
|
||||
<input type="phone" class="input text-base-content font-medium" placeholder="040 12345678" bind:value={benutzer.telefon}>
|
||||
</div>
|
||||
<div class="flex flex-row gap-4">
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div class="flex flex-col">
|
||||
<span class="whitespace-nowrap">Adresse</span>
|
||||
<input type="text" class="input text-base-content font-medium" placeholder="Musterstraße 123" bind:value={benutzer.adresse}>
|
||||
@@ -138,7 +138,7 @@
|
||||
<input type="text" class="input text-base-content font-medium" placeholder="Musterhausen" bind:value={benutzer.ort}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-row gap-4">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="flex flex-col">
|
||||
<span class="whitespace-nowrap">Passwort</span>
|
||||
<input type="password" class="input text-base-content font-medium" placeholder="*********" bind:value={passwort}>
|
||||
@@ -152,7 +152,8 @@
|
||||
</form>
|
||||
</TabPanel>
|
||||
<TabPanel>
|
||||
<h1>Panel Two</h1>
|
||||
<h2 class="text-2xl font-medium">Ausweise</h2>
|
||||
<p>In Zukunft werden sie hier spezifische Einstellungen für die Ausweisgenerierung ansehen können. Bitte haben sie Geduld.</p>
|
||||
</TabPanel>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
29
src/modules/Dashboard/DashboardModule.svelte
Normal file
29
src/modules/Dashboard/DashboardModule.svelte
Normal file
@@ -0,0 +1,29 @@
|
||||
<script lang="ts">
|
||||
import { BenutzerClient, GebaeudeClient } from "#components/Ausweis/types";
|
||||
|
||||
export let user: BenutzerClient;
|
||||
export let gebaeudeArray: GebaeudeClient[];
|
||||
</script>
|
||||
|
||||
<h1 class="text-4xl font-medium my-8">Willkommen zurück, {user.vorname}!</h1>
|
||||
<p class="text-lg">
|
||||
Hier finden Sie eine Übersicht über all ihre Ausweise und Gebäude.
|
||||
</p>
|
||||
|
||||
<h1 class="text-4xl font-medium my-8">Gebäude</h1>
|
||||
<div class="grid grid-cols-1 gap-4 lg:grid-cols-2">
|
||||
{#each gebaeudeArray as gebaeude}
|
||||
<div class="card lg:card-side bg-base-200 card-bordered border-base-300">
|
||||
<figure class="lg:w-1/2">
|
||||
<img
|
||||
src={(gebaeude.gebaeude_bilder && `/bilder/${gebaeude.gebaeude_bilder[0]?.uid}.webp`) || "/images/placeholder.jpg"}
|
||||
class="object-cover w-full h-full"
|
||||
alt="Gebäudebild"
|
||||
/>
|
||||
</figure>
|
||||
<div class="card-body lg:w-1/2 p-4">
|
||||
<h4 class="text-lg font-semibold">{gebaeude.adresse}, {gebaeude.plz} {gebaeude.ort}</h4>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
@@ -43,8 +43,9 @@
|
||||
|
||||
function addNewField() {
|
||||
template = designer.getTemplate();
|
||||
const page = designer.getPageCursor();
|
||||
|
||||
template.schemas[0]["new-field"] = {
|
||||
template.schemas[page]["new-field"] = {
|
||||
type: "text",
|
||||
position: { x: 0, y: 0 },
|
||||
width: 10,
|
||||
@@ -87,9 +88,18 @@
|
||||
input.click()
|
||||
}
|
||||
|
||||
function onKeydown(e: KeyboardEvent) {
|
||||
if (e.ctrlKey && e.key === "s") {
|
||||
e.preventDefault();
|
||||
exportTemplate();
|
||||
}
|
||||
}
|
||||
|
||||
let loadTemplateInput: HTMLInputElement;
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={onKeydown}></svelte:window>
|
||||
|
||||
<header class="mb-4">
|
||||
<button class="btn btn-secondary" on:click={() => loadTemplateInput.click()}>Change base PDF</button>
|
||||
<button class="btn btn-secondary" on:click={addNewField}>Add new Field</button>
|
||||
@@ -99,4 +109,4 @@
|
||||
<input type="file" hidden bind:this={loadTemplateInput} on:change={loadBasePDF}>
|
||||
</header>
|
||||
|
||||
<div bind:this={container}></div>
|
||||
<div bind:this={container} class="h-[80vh]"></div>
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
import { Viewer } from "@pdfme/ui";
|
||||
import { Check } from "radix-svelte-icons";
|
||||
import { image, text } from "@pdfme/schemas";
|
||||
import { AusweisData, convertAusweisData } from "#lib/AusweisData";
|
||||
import { VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import { convertAusweisData } from "#lib/AusweisData";
|
||||
|
||||
|
||||
|
||||
export let ausweise: AusweisData[];
|
||||
export let ausweise: VerbrauchsausweisWohnenClient[];
|
||||
|
||||
let pdfInputs: AusweisData;
|
||||
let pdfInputs: VerbrauchsausweisWohnenClient;
|
||||
let template: Template;
|
||||
let viewer: Viewer
|
||||
|
||||
@@ -37,11 +38,13 @@
|
||||
return
|
||||
};
|
||||
|
||||
const convertedInputs = convertAusweisData(pdfInputs);
|
||||
|
||||
viewer = new Viewer({
|
||||
domContainer: pdfViewerContainer,
|
||||
template,
|
||||
inputs: [convertAusweisData(pdfInputs)],
|
||||
plugins: { text, image, variable}
|
||||
inputs: [convertedInputs],
|
||||
plugins: { text, image, variable: { ...variable, pdf: variable.pdf.bind(convertedInputs), ui: variable.ui.bind(convertedInputs) } }
|
||||
})
|
||||
};
|
||||
|
||||
@@ -51,8 +54,9 @@
|
||||
input.click();
|
||||
}
|
||||
|
||||
function changeInputs(inputs: AusweisData) {
|
||||
function changeInputs(inputs: VerbrauchsausweisWohnenClient) {
|
||||
pdfInputs = inputs;
|
||||
|
||||
if (!template) {
|
||||
alert("Bitte laden Sie zuerst ein Template.")
|
||||
return
|
||||
@@ -60,11 +64,13 @@
|
||||
|
||||
if (viewer) viewer.destroy();
|
||||
|
||||
const convertedInputs = convertAusweisData(pdfInputs);
|
||||
|
||||
viewer = new Viewer({
|
||||
domContainer: pdfViewerContainer,
|
||||
template,
|
||||
inputs: [convertAusweisData(pdfInputs)],
|
||||
plugins: { text, image, variable}
|
||||
inputs: [convertedInputs],
|
||||
plugins: { text, image, variable: { ...variable, pdf: variable.pdf.bind(convertedInputs), ui: variable.ui.bind(convertedInputs) } }
|
||||
})
|
||||
}
|
||||
|
||||
@@ -81,7 +87,7 @@
|
||||
<div class="flex flex-col gap-4">
|
||||
{#each ausweise as ausweis}
|
||||
<div class="rounded-lg border p-2 flex flex-row items-center justify-between">
|
||||
<h2 class="text-black">{ausweis.gebaeude_stammdaten.adresse}</h2>
|
||||
<h2 class="text-black">{ausweis.gebaeude_aufnahme_allgemein.gebaeude_stammdaten.adresse}</h2>
|
||||
<button class="btn btn-square btn-ghost p-1.5" on:click={() => {
|
||||
changeInputs(ausweis)
|
||||
}}><Check size={20}/></button>
|
||||
|
||||
@@ -2,11 +2,7 @@
|
||||
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";
|
||||
@@ -15,6 +11,7 @@
|
||||
import type { AppRouter } from "@ibcornelsen/api";
|
||||
import CheckoutItem from "#components/CheckoutItem.svelte";
|
||||
import { BenutzerClient, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import { PRICES } from "#lib/constants";
|
||||
|
||||
export let user: BenutzerClient;
|
||||
export let ausweis:
|
||||
@@ -22,7 +19,18 @@
|
||||
// TODO: überarbeiten und zu inferProcedureOutput machen
|
||||
let rechnung: inferProcedureInput<
|
||||
AppRouter["v1"]["rechnungen"]["erstellen"]
|
||||
> = {};
|
||||
> = {
|
||||
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 = [
|
||||
{
|
||||
@@ -54,15 +62,12 @@
|
||||
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,
|
||||
ausweisart: Enums.Ausweisart.VerbrauchsausweisWohnen,
|
||||
uid: ausweis.uid,
|
||||
bezahlmethode: selectedPaymentType,
|
||||
services: services
|
||||
@@ -72,9 +77,16 @@
|
||||
|
||||
window.location.href = response.checkout_url;
|
||||
}
|
||||
|
||||
const priceTotal = services.reduce((acc, service) => {
|
||||
if (service.selected) {
|
||||
return acc + service.price;
|
||||
}
|
||||
return acc;
|
||||
}, 0) + PRICES[Enums.Ausweisart.VerbrauchsausweisWohnen][0];
|
||||
</script>
|
||||
|
||||
<div class="grid grid-cols-[2fr_1fr] gap-4 h-full">
|
||||
<form class="grid grid-cols-[2fr_1fr] gap-4 h-full" on:submit={createPayment}>
|
||||
<div>
|
||||
<h3 class="font-semibold">Ansprechpartner</h3>
|
||||
<div class="rounded-lg border p-4 border-base-300 bg-base-100">
|
||||
@@ -348,23 +360,23 @@
|
||||
<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">45€</span>
|
||||
<span class="opacity-75 text-sm">Netto</span>
|
||||
<span class="font-semibold text-sm">{priceTotal * 0.81}€</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">45€</span>
|
||||
<span class="opacity-75 text-sm">19% MwSt</span>
|
||||
<span class="font-semibold text-sm">{priceTotal * 0.19}€</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">45€</span>
|
||||
<span class="font-semibold text-sm">{priceTotal}€</span>
|
||||
</div>
|
||||
<p class="mt-8">Mit dem Klick auf "Bestellung Bestätigen" akzeptieren sie unsere <a href="/agb">AGB</a> und <a href="/impressum">Datenschutzbestimmungen</a>. Sie werden zu ihrem ausgewählten Bezahlprovider weitergeleitet, nach Bezahlung werden sie automatisch zu unserem Portal zurückgeleitet.</p>
|
||||
<button class="btn btn-secondary w-full mt-4" disabled
|
||||
<button class="btn btn-secondary w-full mt-4"
|
||||
>Bestellung Bestätigen</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
Bezahlmethoden,
|
||||
} from "@ibcornelsen/database/client";
|
||||
import { Enums } from "@ibcornelsen/database/client";
|
||||
import { dialogs } from "svelte-dialogs";
|
||||
import LoginDialog from "#components/LoginDialog.svelte";
|
||||
|
||||
export let user: BenutzerClient;
|
||||
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||
@@ -40,8 +42,14 @@
|
||||
|
||||
import { PRICES } from "#lib/constants";
|
||||
import { BenutzerClient, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import { validateAccessTokenClient } from "src/client/lib/validateAccessToken";
|
||||
import { client } from "src/trpc";
|
||||
|
||||
const prices = PRICES[ausweis.ausweisart];
|
||||
let prices: number[] = []
|
||||
|
||||
if (ausweis.gebaeude_aufnahme_allgemein.ausweisart) {
|
||||
prices = PRICES[ausweis.gebaeude_aufnahme_allgemein.ausweisart]
|
||||
}
|
||||
|
||||
let basePrice: number = prices[0];
|
||||
|
||||
@@ -52,12 +60,29 @@
|
||||
0
|
||||
);
|
||||
|
||||
function speichern(e: SubmitEvent) {
|
||||
async function speichern(e: SubmitEvent) {
|
||||
e.preventDefault()
|
||||
console.log("Speichern");
|
||||
|
||||
// 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.
|
||||
if (!(await validateAccessTokenClient())) {
|
||||
// TOOD: Auf Dialog umstellen.
|
||||
const loggedIn = await dialogs.modal(LoginDialog);
|
||||
|
||||
if (!loggedIn) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Falls der Ausweis noch keine benutzer_id hat müssen wir ihn claimen, damit er dem jetzigen Nutzer zugewiesen wird...
|
||||
await client.v1.verbrauchsausweisWohnen.claim.mutate({
|
||||
uid: ausweis.uid
|
||||
})
|
||||
|
||||
window.location.href = `/kaufabschluss?uid=${ausweis.uid}`;
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<div class="w-full px-8">
|
||||
|
||||
16
src/pages/UMBE_test.astro
Normal file
16
src/pages/UMBE_test.astro
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
|
||||
|
||||
import Layout from "#layouts/UMBE_Layout.astro";
|
||||
|
||||
|
||||
---
|
||||
|
||||
<Layout title="Energieausweis online erstellen - Online Energieausweis">
|
||||
<h1>HALLO</h1>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { createCaller } from "#lib/caller";
|
||||
import { APIRoute } from "astro";
|
||||
import { validate } from "uuid";
|
||||
|
||||
export const get: APIRoute = async ({params, cookies}) => {
|
||||
const { uid } = params;
|
||||
@@ -8,6 +9,10 @@ export const get: APIRoute = async ({params, cookies}) => {
|
||||
return new Response("No uid provided", { status: 400 });
|
||||
}
|
||||
|
||||
if (!validate(uid)) {
|
||||
return new Response("Invalid uid", { status: 400 });
|
||||
}
|
||||
|
||||
const caller = createCaller({ cookies })
|
||||
|
||||
const image = await caller.v1.bilder.getBase64({ uid })
|
||||
|
||||
@@ -16,7 +16,7 @@ if (!accessTokenValid) {
|
||||
const caller = createCaller(Astro);
|
||||
|
||||
const ausweise = await caller.v1.verbrauchsausweisWohnen.getMany({
|
||||
limit: 25
|
||||
limit: 25,
|
||||
});
|
||||
---
|
||||
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
---
|
||||
import { createCaller } from "#lib/caller";
|
||||
import UserLayout from "../../../layouts/UserLayout.astro";
|
||||
import DashboardPDFViewerModule from "../../../modules/Dashboard/DashboardPDFViewerModule.svelte";
|
||||
import { prisma } from "@ibcornelsen/database/server";
|
||||
|
||||
const ausweise = await prisma.verbrauchsausweisWohnen.findMany({
|
||||
take: 10,
|
||||
include: {
|
||||
benutzer: true,
|
||||
gebaeude_stammdaten: true,
|
||||
rechnungen: true
|
||||
}
|
||||
})
|
||||
const caller = createCaller(Astro);
|
||||
|
||||
const ausweise = await caller.v1.verbrauchsausweisWohnen.getMany({
|
||||
limit: 10
|
||||
});
|
||||
---
|
||||
|
||||
<UserLayout title="PDF Viewer">
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
---
|
||||
import UserLayout from "../../../layouts/UserLayout.astro";
|
||||
import { API_UID_COOKIE_NAME } from "../../../lib/constants";
|
||||
import DashboardAusweiseModule from "#modules/Dashboard/DashboardAusweiseModule.svelte";
|
||||
import { prisma } from "@ibcornelsen/database/server";
|
||||
|
||||
const uid = Astro.cookies.get(API_UID_COOKIE_NAME).value
|
||||
import { validateAccessTokenServer } from "src/server/lib/validateAccessToken";
|
||||
import { createCaller } from "#lib/caller";
|
||||
|
||||
if (!uid) {
|
||||
const accessTokenValid = await validateAccessTokenServer(Astro);
|
||||
|
||||
if (!accessTokenValid) {
|
||||
return Astro.redirect("/auth/login")
|
||||
}
|
||||
|
||||
const user = await prisma.benutzer.findUnique({
|
||||
where: {
|
||||
uid
|
||||
}
|
||||
})
|
||||
const caller = createCaller(Astro);
|
||||
|
||||
if (!user) {
|
||||
return Astro.redirect("/auth/login")
|
||||
}
|
||||
const user = await caller.v1.benutzer.self();
|
||||
---
|
||||
|
||||
<UserLayout title="Dashboard">
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
---
|
||||
import { createCaller } from "#lib/caller";
|
||||
import UserLayout from "../../layouts/UserLayout.astro";
|
||||
import { validateAccessTokenServer } from "src/server/lib/validateAccessToken";
|
||||
import DashboardModule from "#modules/Dashboard/DashboardModule.svelte";
|
||||
|
||||
const accessTokenValid = await validateAccessTokenServer(Astro);
|
||||
|
||||
if (!accessTokenValid) {
|
||||
return Astro.redirect("/auth/login")
|
||||
}
|
||||
|
||||
const caller = createCaller(Astro);
|
||||
|
||||
const user = await caller.v1.benutzer.self();
|
||||
const gebaeudeArray = await caller.v1.gebaeude.getMany({ limit: 5 });
|
||||
---
|
||||
|
||||
<UserLayout title="Dashboard">
|
||||
<DashboardModule user={user} gebaeudeArray={gebaeudeArray} />
|
||||
</UserLayout>
|
||||
31
src/pages/email.astro
Normal file
31
src/pages/email.astro
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
import ThemeController from "../components/ThemeController.svelte";
|
||||
import moment from "moment"
|
||||
|
||||
const lightTheme = Astro.cookies.get("theme").value === "light";
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>email</title>
|
||||
</head>
|
||||
<body class="p-8">
|
||||
<main class="prose border rounded-box flex flex-col items-center border-base-300">
|
||||
<div class="bg-base-200 h-auto w-full flex flex-col items-center gap-4 justify-start py-4 border-b border-base-300 rounded-t-box">
|
||||
<img src="/images/header/logo-big.svg" class="h-12 my-0">
|
||||
</div>
|
||||
<div class="bg-base-100 h-auto w-full flex flex-col items-center gap-4 justify-start py-16 px-8">
|
||||
<h2 class="my-0">Erinnerung vom IBCornelsen</h2>
|
||||
<p class="text-center">Bitte denken sie daran, die restlichen Bilder für ihr Gebäude hochzuladen. Die aktuelle Gesetzgebung erfordert dies, bevor ihr Ausweis ausgestellt werden kann.</p>
|
||||
<a class="btn btn-primary text-primary-content no-underline">Bilder Hochladen</a>
|
||||
</div>
|
||||
<div class="bg-base-200 h-auto w-full flex flex-col items-center gap-4 justify-start py-4 border-t border-base-300 rounded-b-box">
|
||||
<a class="text-base-content font-medium text-sm" href="https://online-energieausweis.org">© {moment().format("YYYY")} IB Cornelsen Hamburg</a>
|
||||
</div>
|
||||
</main>
|
||||
<ThemeController lightTheme={lightTheme}></ThemeController>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,24 +1,27 @@
|
||||
---
|
||||
|
||||
import AusweisLayout from "#layouts/AusweisLayout.astro";
|
||||
import VerbrauchsausweisWohnenModule from "#modules/Ausweise/VerbrauchsausweisWohnenModule.svelte";
|
||||
import { VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import { createCaller } from "#lib/caller";
|
||||
|
||||
const uid = Astro.url.searchParams.get("uid");
|
||||
let ausweis: VerbrauchsausweisWohnenClient = {} as VerbrauchsausweisWohnenClient;
|
||||
let ausweis: VerbrauchsausweisWohnenClient = {
|
||||
gebaeude_aufnahme_allgemein: { gebaeude_stammdaten: {} },
|
||||
} as VerbrauchsausweisWohnenClient;
|
||||
|
||||
const caller = createCaller(Astro);
|
||||
|
||||
if (uid) {
|
||||
ausweis = await caller.v1.verbrauchsausweisWohnen.get({
|
||||
uid: uid
|
||||
})
|
||||
uid: uid,
|
||||
});
|
||||
|
||||
if (!ausweis) {
|
||||
// Der Ausweis scheint nicht zu existieren.
|
||||
// Wir leiten auf die generische Ausweisseite ohne UID weiter.
|
||||
return Astro.redirect("/energieausweis-erstellen/verbrauchsausweis-wohnen");
|
||||
return Astro.redirect(
|
||||
"/energieausweis-erstellen/verbrauchsausweis-wohnen"
|
||||
);
|
||||
}
|
||||
}
|
||||
---
|
||||
|
||||
@@ -21,7 +21,7 @@ const ausweis = await caller.v1.verbrauchsausweisWohnen.get({
|
||||
const user = await caller.v1.benutzer.self();
|
||||
|
||||
|
||||
if (!ausweis || !user) {
|
||||
if (!ausweis) {
|
||||
return Astro.redirect("/404");
|
||||
}
|
||||
---
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
---
|
||||
import { generate } from "@pdfme/generator";
|
||||
import VerbrauchsausweisWohnen2016Template from "../../data/templates/verbrauchsausweis-wohnen-2016.json";
|
||||
import VerbrauchsausweisWohnen2016Template from "../../lib/pdf/templates/GEG24_Verbrauchsausweis.json";
|
||||
import { convertAusweisData } from "#lib/AusweisData";
|
||||
import { variable } from "#lib/pdf/plugins/variables";
|
||||
import { text, image } from "@pdfme/schemas"
|
||||
import { text, image } from "@pdfme/schemas";
|
||||
import { createCaller } from "#lib/caller";
|
||||
import { VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import { Schema, Template } from "@pdfme/common";
|
||||
import { Moment } from "moment";
|
||||
import { endEnergieVerbrauchVerbrauchsausweis_2016 } from "#lib/Berechnungen/VerbrauchsausweisWohnen/VerbrauchsausweisWohnen_2016";
|
||||
import moment from "moment";
|
||||
import { getEmpfehlungen } from "#lib/XML/getEmpfehlungen";
|
||||
|
||||
const base64 = Astro.url.searchParams.get("base64");
|
||||
let ausweis: VerbrauchsausweisWohnenClient | null = null;
|
||||
@@ -23,24 +28,208 @@ if (base64) {
|
||||
const caller = createCaller(Astro);
|
||||
|
||||
ausweis = await caller.v1.verbrauchsausweisWohnen.get({
|
||||
uid: uidAusweis
|
||||
})
|
||||
uid: uidAusweis,
|
||||
});
|
||||
}
|
||||
|
||||
if (!ausweis) {
|
||||
return Astro.redirect("/404");
|
||||
const template = VerbrauchsausweisWohnen2016Template as Template;
|
||||
|
||||
const berechnungen = await endEnergieVerbrauchVerbrauchsausweis_2016(ausweis);
|
||||
|
||||
let inputs: Record<string, string> = {};
|
||||
|
||||
// Verbrauchszeiträume
|
||||
const addVerbrauchszeitraum = (() => {
|
||||
let row = 0;
|
||||
let columnWidth = [16, 16, 80, 12, 18, 18, 18, 12];
|
||||
|
||||
const getPosition = (column: number) => {
|
||||
return {
|
||||
position: {
|
||||
x:
|
||||
15 +
|
||||
columnWidth.reduce(
|
||||
(a, c, i) => (i >= column ? a : a + c),
|
||||
0
|
||||
),
|
||||
y: 141 + row * 5,
|
||||
},
|
||||
height: 5,
|
||||
width: 14,
|
||||
type: "text",
|
||||
fontSize: 8,
|
||||
verticalAlign: "middle",
|
||||
};
|
||||
};
|
||||
|
||||
return (
|
||||
schema: Schema,
|
||||
start: Moment,
|
||||
end: Moment,
|
||||
energietraeger: string,
|
||||
primaerenergiefaktor: number,
|
||||
energieverbrauch: number,
|
||||
anteilWarmwasser: number,
|
||||
klimafaktor: number
|
||||
) => {
|
||||
inputs[`verbrauchszeitraum_${row}_start`] = start.format("MM.YYYY");
|
||||
inputs[`verbrauchszeitraum_${row}_end`] = end.format("MM.YYYY");
|
||||
inputs[`verbrauchszeitraum_${row}_energietraeger`] = energietraeger;
|
||||
inputs[`verbrauchszeitraum_${row}_primaerenergiefaktor`] =
|
||||
primaerenergiefaktor.toString();
|
||||
inputs[`verbrauchszeitraum_${row}_energieverbrauch`] =
|
||||
energieverbrauch.toString();
|
||||
inputs[`verbrauchszeitraum_${row}_anteil_warmwasser`] = Math.round(
|
||||
anteilWarmwasser * energieverbrauch
|
||||
).toString();
|
||||
inputs[`verbrauchszeitraum_${row}_anteil_heizung`] = Math.round(
|
||||
(1 - anteilWarmwasser) *
|
||||
energieverbrauch
|
||||
).toString();
|
||||
inputs[`verbrauchszeitraum_${row}_klimafaktor`] =
|
||||
klimafaktor.toString();
|
||||
|
||||
schema[`verbrauchszeitraum_${row}_start`] = getPosition(0);
|
||||
schema[`verbrauchszeitraum_${row}_end`] = getPosition(1);
|
||||
schema[`verbrauchszeitraum_${row}_energietraeger`] = getPosition(2);
|
||||
schema[`verbrauchszeitraum_${row}_primaerenergiefaktor`] =
|
||||
getPosition(3);
|
||||
schema[`verbrauchszeitraum_${row}_energieverbrauch`] = getPosition(4);
|
||||
schema[`verbrauchszeitraum_${row}_anteil_warmwasser`] = getPosition(5);
|
||||
schema[`verbrauchszeitraum_${row}_anteil_heizung`] = getPosition(6);
|
||||
schema[`verbrauchszeitraum_${row}_klimafaktor`] = getPosition(7);
|
||||
|
||||
row++;
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
addVerbrauchszeitraum(
|
||||
template.schemas[2],
|
||||
moment(ausweis.startdatum),
|
||||
moment(ausweis.startdatum).add("1", "year"),
|
||||
ausweis.gebaeude_aufnahme_allgemein?.brennstoff_1,
|
||||
berechnungen?.primaerfaktorww,
|
||||
berechnungen?.verbrauch_1_kwh,
|
||||
ausweis.anteil_warmwasser_1 / 100,
|
||||
berechnungen?.klimafaktoren[0].klimafaktor
|
||||
);
|
||||
|
||||
addVerbrauchszeitraum(
|
||||
template.schemas[2],
|
||||
moment(ausweis.startdatum).add("1", "year"),
|
||||
moment(ausweis.startdatum).add("2", "years"),
|
||||
ausweis.gebaeude_aufnahme_allgemein?.brennstoff_1,
|
||||
berechnungen?.primaerfaktorww,
|
||||
berechnungen?.verbrauch_2_kwh,
|
||||
ausweis.anteil_warmwasser_1 / 100,
|
||||
berechnungen?.klimafaktoren[1].klimafaktor
|
||||
);
|
||||
|
||||
addVerbrauchszeitraum(
|
||||
template.schemas[2],
|
||||
moment(ausweis.startdatum).add("2", "years"),
|
||||
moment(ausweis.startdatum).add("3", "years"),
|
||||
ausweis.gebaeude_aufnahme_allgemein?.brennstoff_1,
|
||||
berechnungen?.primaerfaktorww,
|
||||
berechnungen?.verbrauch_3_kwh,
|
||||
ausweis.anteil_warmwasser_1 / 100,
|
||||
berechnungen?.klimafaktoren[2].klimafaktor
|
||||
);
|
||||
|
||||
if (ausweis.zusaetzliche_heizquelle) {
|
||||
addVerbrauchszeitraum(
|
||||
template.schemas[2],
|
||||
moment(ausweis.startdatum),
|
||||
moment(ausweis.startdatum).add("1", "year"),
|
||||
ausweis.gebaeude_aufnahme_allgemein?.brennstoff_2,
|
||||
berechnungen?.primaerfaktorww_1,
|
||||
berechnungen?.verbrauch_4_kwh,
|
||||
ausweis.anteil_warmwasser_2 / 100,
|
||||
berechnungen?.klimafaktoren[0].klimafaktor
|
||||
);
|
||||
|
||||
addVerbrauchszeitraum(
|
||||
template.schemas[2],
|
||||
moment(ausweis.startdatum).add("1", "year"),
|
||||
moment(ausweis.startdatum).add("2", "years"),
|
||||
ausweis.gebaeude_aufnahme_allgemein?.brennstoff_2,
|
||||
berechnungen?.primaerfaktorww_1,
|
||||
berechnungen?.verbrauch_5_kwh,
|
||||
ausweis.anteil_warmwasser_2 / 100,
|
||||
berechnungen?.klimafaktoren[1].klimafaktor
|
||||
);
|
||||
|
||||
addVerbrauchszeitraum(
|
||||
template.schemas[2],
|
||||
moment(ausweis.startdatum).add("2", "years"),
|
||||
moment(ausweis.startdatum).add("3", "years"),
|
||||
ausweis.gebaeude_aufnahme_allgemein?.brennstoff_2,
|
||||
berechnungen?.primaerfaktorww_1,
|
||||
berechnungen?.verbrauch_6_kwh,
|
||||
ausweis.anteil_warmwasser_2 / 100,
|
||||
berechnungen?.klimafaktoren[1].klimafaktor
|
||||
);
|
||||
}
|
||||
|
||||
const convertedInputs = { ...convertAusweisData(ausweis), ...inputs };
|
||||
const empfehlungen = getEmpfehlungen(ausweis);
|
||||
|
||||
const addEmpfehlung = (() => {
|
||||
let i = 0;
|
||||
let columnWidth = [9, 25, 81, 13, 10, 17, 31];
|
||||
|
||||
const getPosition = (column: number) => {
|
||||
return {
|
||||
position: {
|
||||
x:
|
||||
13 +
|
||||
columnWidth.reduce(
|
||||
(a, c, i) => (i >= column ? a : a + c),
|
||||
0
|
||||
),
|
||||
y: 94 + i * 15,
|
||||
},
|
||||
height: 15,
|
||||
width: columnWidth[column],
|
||||
type: "text",
|
||||
fontSize: 8,
|
||||
verticalAlign: "middle",
|
||||
};
|
||||
};
|
||||
|
||||
return (empfehlung: ReturnType<typeof getEmpfehlungen>[0]) => {
|
||||
template.schemas[3][`empfehlung_${i}_nr`] = getPosition(0)
|
||||
template.schemas[3][`empfehlung_${i}_bauteil`] = getPosition(1)
|
||||
template.schemas[3][`empfehlung_${i}_beschreibung`] = getPosition(2)
|
||||
template.schemas[3][`empfehlung_${i}_amortisationszeit`] = getPosition(5)
|
||||
template.schemas[3][`empfehlung_${i}_kosten`] = getPosition(6)
|
||||
|
||||
convertedInputs[`empfehlung_${i}_nr`] = (i + 1).toString();
|
||||
convertedInputs[`empfehlung_${i}_bauteil`] = empfehlung.anlagenteil;
|
||||
convertedInputs[`empfehlung_${i}_beschreibung`] = empfehlung.description;
|
||||
convertedInputs[`empfehlung_${i}_amortisationszeit`] = "";
|
||||
convertedInputs[`empfehlung_${i}_kosten`] = "";
|
||||
|
||||
i++;
|
||||
}
|
||||
})()
|
||||
|
||||
|
||||
for (const empfehlung of empfehlungen) {
|
||||
addEmpfehlung(empfehlung);
|
||||
}
|
||||
|
||||
const pdf = await generate({
|
||||
template: VerbrauchsausweisWohnen2016Template,
|
||||
plugins: { text, image, variable },
|
||||
inputs: [convertAusweisData(ausweis)],
|
||||
template,
|
||||
plugins: { text, image, variable: { ...variable, pdf: variable.pdf.bind(convertedInputs), ui: variable.ui.bind(convertedInputs) } },
|
||||
inputs: [convertedInputs],
|
||||
options: {
|
||||
author: "IB Cornelsen",
|
||||
creationDate: new Date(),
|
||||
creator: "IB Cornelsen",
|
||||
language: "de",
|
||||
title: "Verbrauchsausweis Wohnen 2016",
|
||||
title: "Verbrauchsausweis Wohnen GEG 2024",
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
48
src/style/UMBE_global.css
Normal file
48
src/style/UMBE_global.css
Normal file
@@ -0,0 +1,48 @@
|
||||
@import url('https://fonts.googleapis.com/css2?family=Abel&display=swap');
|
||||
@import url("https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,200;0,300;0,400;0,500;0,600;0,700;1,400&display=swap");
|
||||
|
||||
* {
|
||||
font-weight: 400;
|
||||
box-sizing: border-box;
|
||||
font-family: "Abel", "Poppins", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
article hr {
|
||||
@apply mb-4 mt-4;
|
||||
}
|
||||
|
||||
article {
|
||||
@apply px-6 md:px-8 py-6 w-full relative bg-white;
|
||||
}
|
||||
|
||||
article h1 {
|
||||
@apply text-4xl font-normal my-4;
|
||||
}
|
||||
|
||||
article h2 {
|
||||
@apply text-2xl font-normal my-4;
|
||||
}
|
||||
|
||||
article h3 {
|
||||
@apply text-xl font-normal my-2;
|
||||
}
|
||||
|
||||
article a {
|
||||
@apply text-blue-700 font-medium text-lg;
|
||||
}
|
||||
|
||||
article select {
|
||||
@apply rounded-lg px-2 py-1.5 outline-none;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
@apply h-5 w-4 checkbox-secondary;
|
||||
}
|
||||
28
tests/verbrauchsausweis-wohnen/energieverbrauch.test.ts
Normal file
28
tests/verbrauchsausweis-wohnen/energieverbrauch.test.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { test, describe, expect } from "bun:test";
|
||||
import { endEnergieVerbrauchVerbrauchsausweis_2016 } from "#lib/Berechnungen/VerbrauchsausweisWohnen/VerbrauchsausweisWohnen_2016";
|
||||
import { importVerbrauchsausweisWohnenAltesSystem, verbrauchsausweisWohnenImportTranslate } from "#lib/altes-system/import";
|
||||
|
||||
describe('Energieverbrauch', async () => {
|
||||
const alteAusweise = await importVerbrauchsausweisWohnenAltesSystem();
|
||||
const ausweis = verbrauchsausweisWohnenImportTranslate(alteAusweise.data[0]);
|
||||
const berechnungen = await endEnergieVerbrauchVerbrauchsausweis_2016(ausweis);
|
||||
const berechnungenAlt = alteAusweise.data[0].calculations;
|
||||
|
||||
|
||||
test("Klimafaktoren", async () => {
|
||||
console.log("PLZ: " + ausweis.gebaeude_aufnahme_allgemein.plz)
|
||||
|
||||
expect(berechnungen?.klimafaktoren).toHaveLength(3)
|
||||
expect(berechnungen?.klimafaktoren.map(x => x.klimafaktor)).toEqual(berechnungenAlt.klimafaktoren)
|
||||
})
|
||||
|
||||
|
||||
test("Endenergieverbrauch", async () => {
|
||||
expect(berechnungen?.endEnergieVerbrauchGesamt).toBeCloseTo(berechnungenAlt.endEnergieVerbrauchGesamt, 0)
|
||||
})
|
||||
|
||||
test("Primärenergieverbrauch", async () => {
|
||||
|
||||
expect(berechnungen?.primaerEnergieVerbrauchGesamt).toBeCloseTo(berechnungenAlt.primaerEnergieVerbrauchGesamt, 0)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user