tRPC Hinzugefügt

This commit is contained in:
Moritz Utcke
2024-01-07 22:58:12 +07:00
parent dfd7cce6c8
commit ff16c3b547
39 changed files with 1302 additions and 1652 deletions

View File

@@ -24,6 +24,8 @@
"@ibcornelsen/database": "link:@ibcornelsen/database",
"@ibcornelsen/ui": "^0.0.2",
"@mollie/api-client": "^3.7.0",
"@trpc/client": "^10.45.0",
"@trpc/server": "^10.45.0",
"astro": "^2.5.1",
"astro-i18next": "1.0.0-beta.21",
"bun": "^1.0.2",
@@ -46,6 +48,7 @@
"svelte": "^3.59.1",
"svelte-preprocess": "^5.0.3",
"tailwindcss": "^3.3.2",
"trpc-openapi": "^1.2.0",
"uuid": "^9.0.0",
"vite-tsconfig-paths": "^4.2.0",
"zod": "^3.21.4"

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import { endEnergieVerbrauch } from "#lib/Berechnungen/endEnergieVerbrauch";
import { endEnergieVerbrauchVerbrauchsausweis_2016 } from "#lib/Berechnungen/VerbrauchsausweisWohnen/VerbrauchsausweisWohnen_2016";
import { BedarfsausweisWohnen, GebaeudeStammdaten, VerbrauchsausweisGewerbe, VerbrauchsausweisWohnen } from "@ibcornelsen/database";
export let ausweis: VerbrauchsausweisWohnen | VerbrauchsausweisGewerbe | BedarfsausweisWohnen;
@@ -40,9 +40,13 @@
let translation_2 = 0;
$: {
(async () => {
const energieVerbrauch = (await endEnergieVerbrauch({ ...ausweis, gebaeude_stammdaten: gebaeude}));
const result = (await endEnergieVerbrauchVerbrauchsausweis_2016({ ...ausweis, gebaeude_stammdaten: gebaeude}));
if (!result) {
return
}
//const primaerEnergieVerbrauch = (await ausweis.primaerEnergieBedarf);
translation_1 = Math.max(0, Math.min(100, energieVerbrauch / maxPerformance * 100))
translation_1 = Math.max(0, Math.min(100, result.endEnergieVerbrauchGesamt / maxPerformance * 100))
//translation_2 = Math.max(0, Math.min(100, primaerEnergieVerbrauch / maxPerformance * 100))
})()
}

View File

@@ -5,7 +5,7 @@ export function auditBedarfsausweisBenoetigt(ausweis: VerbrauchsausweisWohnen, g
if (gebaeude.baujahr_gebaeude && gebaeude.baujahr_gebaeude.length > 0) {
return (
(gebaeude.baujahr_gebaeude[0] < 1978 &&
gebaeude.einheiten <= 4 &&
(gebaeude.einheiten || 0) <= 4 &&
gebaeude.saniert == false &&
(ausweis.ausstellgrund == "Vermietung" ||
ausweis.ausstellgrund == "Sonstiges" ||

View File

@@ -51,8 +51,7 @@
<input
name={name}
id={name}
class=""
type="number"
type="text"
required
readonly={readonly}
bind:value={zip}

View File

@@ -1,37 +0,0 @@
import { Bedarfsausweis } from "./Bedarfsausweis";
import { Verbrauchsausweis } from "./Verbrauchsausweis";
import { VerbrauchsausweisGewerbe } from "./VerbrauchsausweisGewerbe";
export enum AusweisType {
VERBRAUCHSAUSWEIS,
VERBRAUCHSAUSWEIS_NICHT_WOHNGEBAEUDE,
BEDARFSAUSWEIS,
}
export type Ausweisart = "VA" | "BA" | "VANW";
export type Ausstellgrund =
| "Vermietung"
| "Neubau"
| "Verkauf"
| "Modernisierung"
| "Sonstiges";
export type Lueftungskonzept = "Fensterlüftung" | "Schachtlüftung" | "Lüftungsanlage ohne Wärmerückgewinnung" | "Lüftungsanlage mit Wärmerückgewinnung"
export type Ausweis = Verbrauchsausweis | Bedarfsausweis | VerbrauchsausweisGewerbe;
export function getAusweis(ausweisart: Ausweisart, initializer?: Ausweis): Ausweis {
let ausweis;
if (ausweisart == "VA") {
ausweis = new Verbrauchsausweis();
} else if (ausweisart == "VANW") {
ausweis = new VerbrauchsausweisGewerbe();
} else if (ausweisart == "BA") {
ausweis = new Bedarfsausweis();
} else {
throw new Error("Unbekannte Ausweisart.");
}
return ausweis;
}

View File

@@ -1,437 +0,0 @@
import { Moment } from "moment";
import { getHeizwertfaktor } from "../server/Heizwertfaktor";
import moment from "moment";
import { BitChecker } from "../BitChecker";
import { getHeizungswerte } from "../Heizungswerte";
import { Ausstellgrund, Ausweisart, Dachgeschoss, Lueftungskonzept } from "./types";
export class Bedarfsausweis {
public ausweisart: Ausweisart = "VA";
public id: number = 0;
public user_id: number = 0;
public rechnung_adresse: number = 0;
public versand_adresse: number = 0;
public objekt_typ: string = "";
public objekt_plz: string = "";
public objekt_ort: string = "";
public objekt_strasse: string = "";
public objekt_gebaeudeteil: string = "";
public objekt_saniert: boolean = false;
public baujahr_gebaeude: number = 0;
public baujahr_anlage: number[] = [];
public anzahl_einheiten: number = 0;
public erstellungsdatum: Date = new Date();
public ausstellgrund: Ausstellgrund = "Vermietung";
public energieverbrauch_zeitraum: Moment = moment();
public energieverbrauch_1_heizquelle_1: number = 0;
public energieverbrauch_2_heizquelle_1: number = 0;
public energieverbrauch_3_heizquelle_1: number = 0;
public energieverbrauch_1_heizquelle_2: number = 0;
public energieverbrauch_2_heizquelle_2: number = 0;
public energieverbrauch_3_heizquelle_2: number = 0;
public energietraeger_einheit_heizquelle_1: string = "";
public energietraeger_einheit_heizquelle_2: string = "";
public energietraeger_1: string = "";
public energietraeger_2: string = "";
public anteil_warmwasser_1: number = 0;
public anteil_warmwasser_2: number = 0;
public uid: string = "";
public wohnflaeche: number = 0;
public keller_beheizt: boolean = false;
public dachgeschoss: Dachgeschoss = Dachgeschoss.UNBEHEIZT;
public zusaetzliche_heizquelle: boolean = false;
public warmwasser_enthalten: boolean = false;
public lueftungskonzept: Lueftungskonzept = "Fensterlüftung";
public wird_gekuehlt: boolean = false;
public leerstand: number = 0;
public images: string[] = [];
public versorgungssysteme: boolean[] = BitChecker(0);
public fenster_dach: boolean[] = BitChecker(0);
public energiequelle_2_nutzung: boolean[] = BitChecker(0);
public daemmung: boolean[] = BitChecker(0);
public get energetische_nutzfläche(): number {
if (this.geschosshoehe < 2.5 || this.geschosshoehe > 3) {
return (1 / this.geschosshoehe - 0.04) * this.volumen;
} else {
return 0.32 * this.volumen;
}
}
/**
* Bedarfsausweis spezifische Eigenschaften
*/
public anzahl_vollgeschosse: number = 0;
public geschosshoehe: number = 0;
public anzahl_gauben: number = 0;
public breite_gauben: number = 0;
public masse_a: number = 0;
public masse_b: number = 0;
public masse_c: number = 0;
public masse_d: number = 0;
public masse_e: number = 0;
public masse_f: number = 0;
public fensterflaeche_so_sw: number = 0;
public fensterflaeche_nw_no: number = 0;
public aussenwandflaeche_unbeheizt: number = 0;
public dachflaeche: number = 0;
public dach_u_wert: number = 0;
public deckenflaeche: number = 0;
public decke_u_wert: number = 0;
public aussenwand_flaeche: number = 0;
public aussenwand_u_wert: number = 0;
public fussboden_flaeche: number = 0;
public fussboden_u_wert: number = 0;
public volumen: number = 0;
public dicht: boolean = false;
public fenster_flaeche_1: number = 0;
public fenster_art_1: number = 0;
public fenster_flaeche_2: number = 0;
public fenster_art_2: number = 0;
public dachfenster_flaeche: number = 0;
public dachfenster_art: number = 0;
public haustuer_flaeche: number = 0;
public haustuer_art: number = 0;
public dach_bauart: string = "";
public dach_daemmung: number = 0;
public decke_bauart: string = "";
public decke_daemmung: number = 0;
public aussenwand_bauart: string = "";
public aussenwand_daemmung: number = 0;
public boden_bauart: string = "";
public boden_daemmung: number = 0;
public warmwasser_verteilung: string = "";
public warmwasser_speicherung: string = "";
public warmwasser_erzeugung: string = "";
public heizung_zentral: boolean = false;
public heizung_verteilung: string = "";
public heizung_speicherung: string = "";
public waerme_erzeugung_heizung: string = "";
public anteil_zusatzheizung: number = 0;
public kollektor_flaeche: number = 0;
// VANW
public vanw_stromverbrauch_enthalten: number = 0;
public vanw_stromverbrauch_sonstige: string = "";
public vanw_strom_1: number = 0;
public vanw_strom_2: number = 0;
public vanw_strom_3: number = 0;
public regnummer: string = "";
public erledigt: boolean = false;
public anrede: string = "";
public name: string = "";
public vorname: string = "";
public email: string = "";
public telefonnummer: string = "";
// Temporär
public tabellenwerte_aendern: boolean = false;
public gebaeude_uid?: string;
public kennwerte: Energiekennwerte = new Energiekennwerte();
public constructor() {}
public static fromBase64(base64: string): Bedarfsausweis | null {
try {
const text = Buffer.from(base64, "base64");
const json = JSON.parse(text.toString());
return json;
} catch (e) {
return null;
}
}
public get primaerEnergieBedarf(): number {
const Endenergieverbrauch = this.endEnergieVerbrauch;
const brennstoff_1 = getHeizwertfaktor(
this.energietraeger_1,
this.energietraeger_einheit_heizquelle_1
);
return Endenergieverbrauch * brennstoff_1.primaerenergiefaktor;
}
public get endEnergieVerbrauch(): number {
let dach_u_wert = 1 / (1 / this.dach_daemmung / 0.04);
let aussenwand_u_wert = 1 / (1 / this.aussenwand_daemmung / 0.04);
let fussboden_u_wert = 1 / (1 / this.boden_daemmung / 0.04);
let decke_u_wert = 1 / (1 / this.decke_daemmung / 0.04);
if (!this.tabellenwerte_aendern) {
this.dach_u_wert = Math.round(dach_u_wert);
this.decke_u_wert = Math.round(decke_u_wert);
this.aussenwand_u_wert = Math.round(aussenwand_u_wert);
this.fussboden_u_wert = Math.round(fussboden_u_wert);
}
if (this.dachgeschoss) {
var IOGdeckef = 0;
var dachgeschossf = 0.5;
var dachgeschossf2 = 1;
} else if (!this.dachgeschoss) {
var IOGdeckef = 0.8;
var dachgeschossf = 0;
var dachgeschossf2 = 0;
// TODO: Dachgeschoss braucht 3 optionen
} else {
var IOGdeckef = 1;
var dachgeschossf = 0;
var dachgeschossf2 = 0;
}
if (this.keller_beheizt) {
var keller_beheizt = 1;
} else {
var keller_beheizt = 0;
}
var gaubenflaeche =
this.breite_gauben * 2 * 0.3 + this.anzahl_gauben * 2 * 1.5;
var gaubenvolumen = this.breite_gauben * 1.5;
let aussenwand_anteil = 1;
if (
this.objekt_typ === "Doppelhaushälfte" ||
this.objekt_typ === "Reihenendhaus"
) {
aussenwand_anteil = 0.7;
} else if (this.objekt_typ === "Reihenmittelhaus") {
aussenwand_anteil = 0.4;
}
// Außenwand
var aussenwand_flaeche =
((2 * this.masse_a +
2 * this.masse_b +
2 * this.masse_d +
2 * this.masse_e +
2 * this.masse_f) *
this.geschosshoehe *
this.anzahl_vollgeschosse +
2 * this.masse_a * this.geschosshoehe * dachgeschossf +
(2 * this.masse_a +
2 * this.masse_b +
2 * this.masse_d +
2 * this.masse_e +
2 * this.masse_f) *
2.2 *
keller_beheizt) *
aussenwand_anteil -
this.fenster_flaeche_1 -
this.fenster_flaeche_2 -
this.haustuer_flaeche +
gaubenflaeche;
if (!this.tabellenwerte_aendern) {
this.aussenwand_flaeche = Math.round(aussenwand_flaeche);
}
var dachflaeche =
((this.masse_a * this.masse_b +
this.masse_c * this.masse_d +
(+this.masse_f + +this.masse_c) * this.masse_e) *
1.2 -
this.dachfenster_flaeche) *
dachgeschossf2;
if (!this.tabellenwerte_aendern) {
this.dachflaeche = Math.round(dachflaeche);
}
var deckenflaeche =
(this.masse_a * this.masse_b +
this.masse_c * this.masse_d +
(+this.masse_f + +this.masse_c) * this.masse_e -
this.dachfenster_flaeche) *
IOGdeckef;
if (!this.tabellenwerte_aendern) {
this.deckenflaeche = Math.round(deckenflaeche);
}
var fussboden_flaeche =
this.masse_a * this.masse_b +
this.masse_c * this.masse_d +
(+this.masse_f + +this.masse_c) * this.masse_e;
if (!this.tabellenwerte_aendern) {
this.fussboden_flaeche = Math.round(fussboden_flaeche);
}
var volumen =
fussboden_flaeche * this.geschosshoehe * this.anzahl_vollgeschosse +
fussboden_flaeche * 2.2 * keller_beheizt +
fussboden_flaeche * this.geschosshoehe * dachgeschossf +
gaubenvolumen;
if (!this.tabellenwerte_aendern) {
this.volumen = Math.round(volumen);
}
if (this.dicht) {
var Hv = 0.163 * volumen;
} else {
var Hv = 0.19 * volumen;
}
var AHF =
this.aussenwand_flaeche +
this.fussboden_flaeche +
this.dachflaeche +
this.deckenflaeche +
this.fenster_flaeche_2 +
this.haustuer_flaeche +
this.dachfenster_flaeche +
this.fenster_flaeche_1;
let AN = this.energetische_nutzfläche;
var Qi = 22 * AN;
// NOTE: Irgendwie sowas wie Gesamtwärmestrom der entweicht.
var Qs =
270 * this.fensterflaeche_so_sw * 0.567 * 0.75 +
100 * this.fensterflaeche_nw_no * 0.567 * 0.75 +
225 * this.dachfenster_flaeche * 0.567 * 0.75 +
155 *
(this.fenster_flaeche_2 +
this.dachfenster_flaeche +
this.fenster_flaeche_1 -
this.fensterflaeche_so_sw -
this.fensterflaeche_nw_no) *
0.567 *
0.75;
var Ht =
this.aussenwand_u_wert *
(this.aussenwand_flaeche - this.aussenwandflaeche_unbeheizt) +
this.aussenwand_u_wert * this.aussenwandflaeche_unbeheizt * 0.5 +
this.decke_u_wert * this.deckenflaeche * IOGdeckef +
this.fussboden_u_wert * this.fussboden_flaeche * 0.6 +
this.dach_u_wert * this.dachflaeche +
this.fenster_art_1 * this.fenster_flaeche_1 +
this.fenster_art_2 * this.fenster_flaeche_2 +
this.dachfenster_art * this.dachfenster_flaeche +
AHF * 0.05 +
this.haustuer_flaeche * this.haustuer_art;
var Qh = (66 * (Ht + Hv) - 0.95 * (Qs + Qi)) / AN;
var Solarsystem_WWbw = 0;
var Solarsystem_WWhb = 0;
if (AN < 500) {
if (this.versorgungssysteme[4]) {
var Solarsystem_WWbw = 11.3 - (3.3 / 350) * (AN - 150);
var Solarsystem_WWhb = 0.8 - (0.4 / 350) * (AN - 150);
}
if (this.kollektor_flaeche != 0) {
var Solarsystem_WWbw = (this.kollektor_flaeche * 280) / AN;
var Solarsystem_WWhb = 0.8 - (0.4 / 350) * (AN - 150);
}
} else if (AN > 500 && AN < 7000) {
if (this.versorgungssysteme[4]) {
var Solarsystem_WWbw = 8 - (2 / 2000) * (AN - 500);
var Solarsystem_WWhb = 0.4 - (0.1 / 2000) * (AN - 500);
}
if (this.kollektor_flaeche != 0) {
var Solarsystem_WWbw = (this.kollektor_flaeche * 280) / AN;
var Solarsystem_WWhb = 0.4 - (0.1 / 2000) * (AN - 500);
}
}
let hilfsenergie_lueftung = 0;
let waerme_gewinnung_lueftung = 0;
if (this.lueftungskonzept == "Lüftungsanlage mit Wärmerückgewinnung") {
hilfsenergie_lueftung = 0;
waerme_gewinnung_lueftung = 13.5;
}
if (this.lueftungskonzept == "Lüftungsanlage ohne Wärmerückgewinnung") {
if (this.baujahr_gebaeude < 1996) {
hilfsenergie_lueftung = 4;
waerme_gewinnung_lueftung = 3.5;
}
if (this.baujahr_gebaeude > 1996) {
hilfsenergie_lueftung = 2.6;
waerme_gewinnung_lueftung = 3.2;
}
}
let [
heizung_zentralwv,
verteilunghwv,
spheizungwv,
werzeugungheaz,
verteilungwwwv,
verteilungwwhg,
warmwasser_speicherungwv,
warmwasser_speicherunghg,
werzeugungwweaz,
verteilunghhb,
spheizunghb,
werzeugunghhb,
verteilungwwhb,
warmwasser_speicherunghb,
werzeugungwwhb,
BRSPrimärenergiefaktor,
BRSPrimärenergiefaktor1,
Coeffizienz,
] = getHeizungswerte(
this.energietraeger_1,
this.energietraeger_2,
AN,
this.warmwasser_verteilung,
this.warmwasser_speicherung,
this.warmwasser_erzeugung,
this.heizung_zentral,
this.heizung_verteilung,
this.heizung_speicherung,
this.waerme_erzeugung_heizung
);
var end_energie_heizung =
(Qh + heizung_zentralwv + verteilunghwv + spheizungwv) *
werzeugungheaz -
waerme_gewinnung_lueftung;
var end_energie_warmwasser =
(12 +
verteilungwwwv -
verteilungwwhg +
warmwasser_speicherungwv -
warmwasser_speicherunghg) *
werzeugungwweaz;
var hilfsenergie =
verteilunghhb +
spheizunghb +
werzeugunghhb +
verteilungwwhb +
warmwasser_speicherunghb +
werzeugungwwhb +
Solarsystem_WWhb +
hilfsenergie_lueftung;
var endenergiegesamt = end_energie_heizung + end_energie_warmwasser + hilfsenergie;
var primheizung =
end_energie_heizung *
(1 - this.anteil_zusatzheizung) *
BRSPrimärenergiefaktor +
end_energie_heizung * this.anteil_zusatzheizung * BRSPrimärenergiefaktor1;
var primaerenergiebedarf =
primheizung +
(end_energie_warmwasser - Solarsystem_WWbw) * BRSPrimärenergiefaktor +
hilfsenergie * 1.8;
return endenergiegesamt;
}
}

View File

@@ -1,154 +0,0 @@
import { getKlimafaktorenClient } from "../Klimafaktoren";
import { getHeizwertfaktor } from "../server/Heizwertfaktor";
import { Ausstellgrund, Ausweisart } from "./types";
import { Gebaeude } from "../Gebaeude";
import { User } from "#lib/User";
export class Verbrauchsausweis {
public id?: number;
public uid?: string;
public gebaeude_stammdaten: Gebaeude = new Gebaeude();
public benutzer?: User;
public rechnung?: any;
public erstellungsdatum: Date = new Date();
public ausstellgrund: Ausstellgrund = "Sonstiges";
public registriernummer: string = "";
public erledigt: boolean = false;
public baujahr_heizung: number[] = [];
public zusaetzliche_heizquelle: boolean = false;
public brennstoff_1: string = "Erdgas";
public einheit_1: string = "kWh";
public brennstoff_2: string = "Erdgas";
public einheit_2: string = "kWh";
public startdatum: Date = new Date();
public enddatum: Date = new Date();
public verbrauch_1: number = 0;
public verbrauch_2: number = 0;
public verbrauch_3: number = 0;
public verbrauch_4: number = 0;
public verbrauch_5: number = 0;
public verbrauch_6: number = 0;
public warmwasser_enthalten: boolean = false;
public anteil_warmwasser_1: number = 0;
public anteil_warmwasser_2: number = 0;
public get energetischeNutzflaeche(): number {
return (
this.gebaeude_stammdaten.wohnflaeche *
(this.gebaeude_stammdaten.keller_beheizt ? 1.35 : 1.2)
);
}
public constructor(initializer?: Verbrauchsausweis) {
}
public static fromBase64(base64: string): Verbrauchsausweis | null {
try {
const text = Buffer.from(base64, "base64");
const json = JSON.parse(text.toString());
return json;
} catch (e) {
return null;
}
}
public get primaerEnergieBedarf(): Promise<number> {
return (async () => {
const Endenergieverbrauch = await this.endEnergieVerbrauch;
const brennstoff_1 = getHeizwertfaktor(
this.brennstoff_1,
this.einheit_1
);
return Endenergieverbrauch * brennstoff_1.primaerenergiefaktor;
})();
}
public get endEnergieVerbrauch(): Promise<number> {
return (async () => {
const date = this.startdatum;
const klimafaktoren = await getKlimafaktorenClient(
date,
this.gebaeude_stammdaten.plz
);
// Endenergieverbrauch
// Um den EEV auszurechnen, müssen die Verbräuche zu kWh konvertiert werden.
let brennstoff_1 = getHeizwertfaktor(
this.brennstoff_1,
this.einheit_1
);
let brennstoff_2 = getHeizwertfaktor(
this.brennstoff_2,
this.einheit_2
);
let verbrauch_1_kwh =
this.verbrauch_1 * brennstoff_1.umrechnungsfaktor;
let verbrauch_2_kwh =
this.verbrauch_2 * brennstoff_1.umrechnungsfaktor;
let verbrauch_3_kwh =
this.verbrauch_3 * brennstoff_1.umrechnungsfaktor;
let verbrauch_4_kwh =
this.verbrauch_4 * brennstoff_2.umrechnungsfaktor;
let verbrauch_5_kwh =
this.verbrauch_5 * brennstoff_2.umrechnungsfaktor;
let verbrauch_6_kwh =
this.verbrauch_6 * brennstoff_2.umrechnungsfaktor;
let warmwasserZuschlag = 0;
let leerstandsZuschlag = 0;
let kuehlungsZuschlag = 0;
if (this.anteil_warmwasser_1 == 0) {
warmwasserZuschlag = 20 * this.energetischeNutzflaeche * 3;
}
if (this.gebaeude_stammdaten.leerstand > 0) {
let durchschnittsKlimafaktor =
klimafaktoren.reduce((a, b) => a + b, 0) / 3;
leerstandsZuschlag =
((verbrauch_1_kwh +
verbrauch_2_kwh +
verbrauch_3_kwh +
verbrauch_4_kwh +
verbrauch_5_kwh +
verbrauch_6_kwh) *
(this.gebaeude_stammdaten.leerstand / 100)) /
durchschnittsKlimafaktor;
}
if (this.gebaeude_stammdaten.energiequelle_2_nutzung[3]) {
kuehlungsZuschlag = 6 * this.energetischeNutzflaeche * 3;
}
let anteil_heizung = 1 - this.anteil_warmwasser_1 / 100;
let anteil_warmwasser = this.anteil_warmwasser_1 / 100;
let Energieverbrauchskennwert =
(anteil_heizung *
(verbrauch_1_kwh + verbrauch_4_kwh) *
klimafaktoren[0] +
anteil_warmwasser * (verbrauch_1_kwh + verbrauch_4_kwh) +
anteil_heizung *
(verbrauch_2_kwh + verbrauch_5_kwh) *
klimafaktoren[1] +
anteil_warmwasser * (verbrauch_2_kwh + verbrauch_5_kwh) +
anteil_heizung *
(verbrauch_3_kwh + verbrauch_6_kwh) *
klimafaktoren[2] +
anteil_warmwasser * (verbrauch_3_kwh + verbrauch_6_kwh) +
warmwasserZuschlag +
leerstandsZuschlag +
kuehlungsZuschlag) /
3 /
this.energetischeNutzflaeche;
return Energieverbrauchskennwert;
})();
}
}

View File

@@ -1,237 +0,0 @@
import { Moment } from "moment";
import { getKlimafaktorenClient } from "../Klimafaktoren";
import { getHeizwertfaktor } from "../server/Heizwertfaktor";
import moment from "moment";
import { BitChecker } from "../BitChecker";
import { Ausstellgrund, Ausweisart, Dachgeschoss, Lueftungskonzept } from "./types";
export class VerbrauchsausweisGewerbe {
public ausweisart: Ausweisart = "VA";
public id: number = 0;
public user_id: number = 0;
public rechnung_adresse: number = 0;
public versand_adresse: number = 0;
public objekt_typ: string = "";
public objekt_plz: string = "";
public objekt_ort: string = "";
public objekt_strasse: string = "";
public objekt_gebaeudeteil: string = "";
public objekt_saniert: boolean = false;
public baujahr_gebaeude: number = 0;
public baujahr_anlage: number[] = [];
public anzahl_einheiten: number = 0;
public erstellungsdatum: Date = new Date();
public ausstellgrund: Ausstellgrund = "Vermietung";
public energieverbrauch_zeitraum: Moment = moment();
public energieverbrauch_1_heizquelle_1: number = 0;
public energieverbrauch_2_heizquelle_1: number = 0;
public energieverbrauch_3_heizquelle_1: number = 0;
public energieverbrauch_1_heizquelle_2: number = 0;
public energieverbrauch_2_heizquelle_2: number = 0;
public energieverbrauch_3_heizquelle_2: number = 0;
public energietraeger_einheit_heizquelle_1: string = "";
public energietraeger_einheit_heizquelle_2: string = "";
public energietraeger_1: string = "";
public energietraeger_2: string = "";
public anteil_warmwasser_1: number = 0;
public anteil_warmwasser_2: number = 0;
public uid: string = "";
public wohnflaeche: number = 0;
public keller_beheizt: boolean = false;
public dachgeschoss: number = Dachgeschoss.UNBEHEIZT;
public zusaetzliche_heizquelle: boolean = false;
public warmwasser_enthalten: boolean = false;
public lueftungskonzept: Lueftungskonzept = "Fensterlüftung";
public wird_gekuehlt: boolean = false;
public leerstand: number = 0;
public images: string[] = [];
public versorgungssysteme: boolean[] = BitChecker(0);
public fenster_dach: boolean[] = BitChecker(0);
public energiequelle_2_nutzung: boolean[] = BitChecker(0);
public daemmung: boolean[] = BitChecker(0);
public get energetische_nutzfläche(): number {
return this.wohnflaeche * (this.keller_beheizt ? 1.35 : 1.2);
};
/**
* Bedarfsausweis spezifische Eigenschaften
*/
public anzahl_vollgeschosse: number = 0;
public geschosshoehe: number = 0;
public anzahl_gauben: number = 0;
public breite_gauben: number = 0;
public masse_a: number = 0;
public masse_b: number = 0;
public masse_c: number = 0;
public masse_d: number = 0;
public masse_e: number = 0;
public masse_f: number = 0;
public fensterflaeche_so_sw: number = 0;
public fensterflaeche_nw_no: number = 0;
public aussenwandflaeche_unbeheizt: number = 0;
public dachflaeche: number = 0;
public dach_u_wert: number = 0;
public deckenflaeche: number = 0;
public decke_u_wert: number = 0;
public aussenwand_flaeche: number = 0;
public aussenwand_u_wert: number = 0;
public fussboden_flaeche: number = 0;
public fussboden_u_wert: number = 0;
public volumen: number = 0;
public dicht: boolean = false;
public fenster_flaeche_1: number = 0;
public fenster_art_1: number = 0;
public fenster_flaeche_2: number = 0;
public fenster_art_2: number = 0;
public dachfenster_flaeche: number = 0;
public dachfenster_art: number = 0;
public haustuer_flaeche: number = 0;
public haustuer_art: number = 0;
public dach_bauart: string = "";
public dach_daemmung: number = 0;
public decke_bauart: string = "";
public decke_daemmung: number = 0;
public aussenwand_bauart: string = "";
public aussenwand_daemmung: number = 0;
public boden_bauart: string = "";
public boden_daemmung: number = 0;
public warmwasser_verteilung: string = "";
public warmwasser_speicherung: string = "";
public warmwasser_erzeugung: string = "";
public heizung_zentral: boolean = false;
public heizung_verteilung: string = "";
public heizung_speicherung: string = "";
public waerme_erzeugung_heizung: string = "";
public anteil_zusatzheizung: number = 0;
public kollektor_flaeche: number = 0;
// VANW
public vanw_stromverbrauch_enthalten: number = 0;
public vanw_stromverbrauch_sonstige: string = "";
public vanw_strom_1: number = 0;
public vanw_strom_2: number = 0;
public vanw_strom_3: number = 0;
public regnummer: string = "";
public erledigt: boolean = false;
public anrede: string = "";
public name: string = "";
public vorname: string = "";
public email: string = "";
public telefonnummer: string = "";
public gebaeude_uid?: string;
public constructor() {}
public static fromBase64(base64: string): VerbrauchsausweisGewerbe | null {
try {
const text = Buffer.from(base64, "base64");
const json = JSON.parse(text.toString());
return json;
} catch (e) {
return null;
}
}
public get primaerEnergieBedarf(): Promise<number> {
return (async () => {
const Endenergieverbrauch = await this.endEnergieVerbrauch;
const brennstoff_1 = getHeizwertfaktor(this.energietraeger_1, this.energietraeger_einheit_heizquelle_1);
return Endenergieverbrauch * brennstoff_1.primaerenergiefaktor;
})();
}
public get endEnergieVerbrauch(): Promise<number> {
return (async () => {
const date = this.energieverbrauch_zeitraum;
const klimafaktoren = await getKlimafaktorenClient(
date,
this.objekt_plz
);
// Endenergieverbrauch
// Um den EEV auszurechnen, müssen die Verbräuche zu kWh konvertiert werden.
let brennstoff_1 = getHeizwertfaktor(this.energietraeger_1, this.energietraeger_einheit_heizquelle_1);
let brennstoff_2 = getHeizwertfaktor(this.energietraeger_2, this.energietraeger_einheit_heizquelle_2);
let verbrauch_1_kwh =
(this.energieverbrauch_1_heizquelle_1 * brennstoff_1.umrechnungsfaktor)
let verbrauch_2_kwh =
(this.energieverbrauch_2_heizquelle_1 * brennstoff_1.umrechnungsfaktor)
let verbrauch_3_kwh =
(this.energieverbrauch_3_heizquelle_1 * brennstoff_1.umrechnungsfaktor)
let verbrauch_4_kwh =
(this.energieverbrauch_1_heizquelle_2 * brennstoff_2.umrechnungsfaktor)
let verbrauch_5_kwh =
(this.energieverbrauch_2_heizquelle_2 * brennstoff_2.umrechnungsfaktor)
let verbrauch_6_kwh =
(this.energieverbrauch_3_heizquelle_2 * brennstoff_2.umrechnungsfaktor)
let warmwasserZuschlag = 0;
let leerstandsZuschlag = 0;
let kuehlungsZuschlag = 0;
if (this.anteil_warmwasser_1 == 0) {
warmwasserZuschlag = 20 * this.energetische_nutzfläche * 3;
}
if (this.leerstand > 0) {
let durchschnittsKlimafaktor =
klimafaktoren.reduce((a, b) => a + b, 0) / 3;
leerstandsZuschlag =
((verbrauch_1_kwh +
verbrauch_2_kwh +
verbrauch_3_kwh +
verbrauch_4_kwh +
verbrauch_5_kwh +
verbrauch_6_kwh) *
(this.leerstand / 100)) /
durchschnittsKlimafaktor;
}
if (this.energiequelle_2_nutzung[3]) {
kuehlungsZuschlag = 6 * this.energetische_nutzfläche * 3;
}
let anteil_heizung = 1 - this.anteil_warmwasser_1 / 100;
let anteil_warmwasser = this.anteil_warmwasser_1 / 100;
let Energieverbrauchskennwert =
(anteil_heizung *
(verbrauch_1_kwh + verbrauch_4_kwh) *
klimafaktoren[0] +
anteil_warmwasser * (verbrauch_1_kwh + verbrauch_4_kwh) +
anteil_heizung *
(verbrauch_2_kwh + verbrauch_5_kwh) *
klimafaktoren[1] +
anteil_warmwasser * (verbrauch_2_kwh + verbrauch_5_kwh) +
anteil_heizung *
(verbrauch_3_kwh + verbrauch_6_kwh) *
klimafaktoren[2] +
anteil_warmwasser * (verbrauch_3_kwh + verbrauch_6_kwh) +
warmwasserZuschlag +
leerstandsZuschlag +
kuehlungsZuschlag) /
3 /
this.energetische_nutzfläche;
return Energieverbrauchskennwert;
})();
}
}

View File

@@ -1,25 +0,0 @@
export enum AusweisType {
VERBRAUCHSAUSWEIS,
VERBRAUCHSAUSWEIS_NICHT_WOHNGEBAEUDE,
BEDARFSAUSWEIS,
}
export type Lueftungskonzept =
| "Fensterlüftung"
| "Schachtlüftung"
| "Lüftungsanlage ohne Wärmerückgewinnung"
| "Lüftungsanlage mit Wärmerückgewinnung";
export type Ausweisart = "VA" | "BA" | "VANW";
export type Ausstellgrund =
| "Vermietung"
| "Neubau"
| "Verkauf"
| "Modernisierung"
| "Sonstiges";
export enum Dachgeschoss {
BEHEIZT,
UNBEHEIZT,
NICHT_VORHANDEN
}

View File

@@ -1,9 +1,10 @@
import { getKlimafaktoren } from "#lib/Klimafaktoren";
import { getHeizwertfaktor } from "#lib/server/Heizwertfaktor";
import {
GebaeudeStammdaten,
VerbrauchsausweisWohnen,
} from "@ibcornelsen/database";
import moment from "moment";
import trpc from "src/trpc";
export function energetischeNutzflaecheVerbrauchsausweisWohnen_2016(
ausweis: VerbrauchsausweisWohnen & {
@@ -23,11 +24,16 @@ export async function endEnergieVerbrauchVerbrauchsausweis_2016(
gebaeude_stammdaten: GebaeudeStammdaten;
}
) {
const date = ausweis.startdatum;
const klimafaktoren = await getKlimafaktoren(
date,
ausweis.gebaeude_stammdaten.plz
);
if (!ausweis.gebaeude_stammdaten.plz || !ausweis.startdatum) {
return null
}
const klimafaktoren = await trpc.klimafaktoren.query({
plz: ausweis.gebaeude_stammdaten.plz,
genauigkeit: "years",
startdatum: ausweis.startdatum,
enddatum: moment(ausweis.startdatum).add(2, "years").toDate()
})
// Endenergieverbrauch
// Um den EEV auszurechnen, müssen die Verbräuche zu kWh konvertiert werden.
@@ -104,7 +110,7 @@ export async function endEnergieVerbrauchVerbrauchsausweis_2016(
}
let durchschnittsKlimafaktor =
(klimafaktoren[0] + klimafaktoren[1] + klimafaktoren[2]) / 3 || 1;
(klimafaktoren[0].klimafaktor + klimafaktoren[1].klimafaktor + klimafaktoren[2].klimafaktor) / 3 || 1;
let energieVerbrauchHeizungBereinigt_1 =
energieVerbrauchHeizung_1 * durchschnittsKlimafaktor;

View File

@@ -1,56 +1,22 @@
import moment from "moment";
import { memoize } from "./Memoization";
import { prisma } from "@ibcornelsen/database";
import { l } from "astro-i18n";
import trpc from "src/trpc";
export const getKlimafaktorenClient = memoize<Promise<[number, number, number]>>(async (date: Date, plz: string) => {
export const getKlimafaktoren = memoize(async (date: Date, plz: string) => {
if (!plz || !date) {
return [0, 0, 0];
return null;
}
const response = await fetch(`/api/klimafaktor?date=${moment(date).format("YYYY-MM-DD")}&accuracy=years&zip=${plz}`, {
method: "GET",
headers: {
"Content-Type": "application/json"
}
});
const json = await response.json();
if (!json.success) {
return [0, 0, 0];
}
return Object.values(json.data) as [number, number, number];
});
export const getKlimafaktorenServer = memoize(async (date: Date, plz: string) => {
if (!plz || !date) {
return [0, 0, 0];
}
const klimafaktoren = await prisma.klimafaktoren.findMany({
where: {
const response = await trpc.klimafaktoren.query({
plz,
month: moment(date).month(),
OR: [
{
year: moment(date).year()
},
{
year: moment(date).year() + 1
},
{
year: moment(date).year() + 2
}
]
}
});
genauigkeit: "years",
startdatum: date,
enddatum: moment(date).add(2, "years").toDate()
})
if (klimafaktoren.length === 0) {
return [0, 0, 0];
if (!response) {
return null;
}
return klimafaktoren.map(klimafaktor => klimafaktor.klimafaktor) as [number, number, number];
return response;
});
export const getKlimafaktoren = typeof window === "undefined" ? getKlimafaktorenServer : getKlimafaktorenClient;

View File

@@ -1,33 +0,0 @@
import moment, { Moment } from "moment";
import { Klimafaktoren, prisma } from "@ibcornelsen/database";
export async function getClimateFactor(
dates: Moment[],
plz: string
): Promise<Klimafaktoren[] | null> {
if (dates.length == 0) {
return null;
}
if (plz.length !== 5 && plz.length !== 4) {
return null;
}
let result = await prisma.klimafaktoren.findMany({
where: {
plz: plz,
month: dates[0].month(),
OR: dates.map((date) => {
return {
year: date.year(),
};
}),
},
});
if (!result) {
return null;
}
return result;
}

View File

@@ -0,0 +1,347 @@
import { GebaeudeStammdaten, VerbrauchsausweisWohnen, prisma } from "@ibcornelsen/database";
import { getEmpfehlungen } from "./getEmpfehlungen";
export class AusweisBerechnungen2016 {
private ausweis: VerbrauchsausweisWohnen;
private gebaeude: GebaeudeStammdaten;
private _berechParameter: any;
public constructor(ausweis: VerbrauchsausweisWohnen, gebaeude: GebaeudeStammdaten, berechnungen: any) {
this.ausweis = ausweis;
this.gebaeude = gebaeude
this._berechParameter = berechnungen;
}
public getAusweisart() {
switch (this.ausweis.ausweisart.toLowerCase()) {
case ('va'):
return {'typ' : 'Wohngebaeude', 'art' : 'Verbrauchsausweis Wohngebäude', 'kuerzel' : 'va'};
case ('ba'):
return {'typ' : 'Wohngebaeude', 'art' : 'Bedarfsausweis Wohngebäude', 'kuerzel' : 'ba'};
case ('vanw'):
return {
'typ' : 'Nichtwohngebaeude',
'art' : 'Verbrauchsausweis Nichtwohngebäude',
'kuerzel' : 'vanw'
};
}
}
public altersKlasse(art: "baujahr_gebaeude" | "baujahr_heizung") {
const year = this.gebaeude[art][0] || 0;
switch (true) {
case (year <= 1918):
return 'bis 1918';
case (year > 1918 && year <= 1948):
return '1919...1948';
case (year > 1948 && year <= 1957):
return '1949...1957';
case (year > 1957 && year <= 1968):
return '1958...1968';
case (year > 1968 && year <= 1978):
return '1969...1978';
case (year > 1978 && year <= 1982):
return '1979...1982';
case (year > 1982 && year <= 1994):
return '1983...1994';
case (year > 1994 && year <= 2002):
return '1995...2002';
case (year > 2002 && year <= 2007):
return '2003...2007';
case (year > 2007 && year <= 2015):
return '2008...2015';
case (year > 2015):
return 'ab 2016';
default:
return '';
}
}
public getGebaeudeTeil() {
if (this.gebaeude.gebaeudeteil == "Gesamtgebäude") {
return "Ganzes Gebäude";
} else if (this.gebaeude.gebaeudeteil == "Wohnen" && this.ausweis.ausweisart == "VANW") {
return "Teil des Wohngebäudes";
} else {
return "Teil des Nichtwohngebäudes";
}
}
public getGebaeudeTyp(getAnbaugrad = false) {
let geTypes = {
'Einfamilienhaus' : {
'typ' : "Einfamilienhaus",
'anbaugrad' : 'freistehend'
},
'Freistehendes Einfamilienhaus' : {
'typ' : "Einfamilienhaus",
'anbaugrad' : 'freistehend'
},
'Freistehendes Zweifamilienhaus' : {
'typ' : "Zweifamilienhaus",
'anbaugrad' : 'freistehend'
},
'Doppelhaushälfte' : {
'typ' : "Einfamilienhaus",
'anbaugrad' : 'einseitig angebaut'
},
'Reihenendhaus' : {
'typ' : "Einfamilienhaus",
'anbaugrad' : 'einseitig angebaut'
},
'Reihenmittelhaus' : {
'typ' : "Einfamilienhaus",
'anbaugrad' : 'zweiseitig angebaut'
},
'Mehrfamilienhaus' : {
'typ' : "Mehrfamilienhaus",
'anbaugrad' : 'freistehend'
},
'Wohn- und Geschäftshaus' : {
'typ' : "Wohnteil gemischt genutztes Gebäude",
'anbaugrad' : 'zweiseitig angebaut'
},
'Stadthausdrittel' : {
'typ' : "Einfamilienhaus",
'anbaugrad' : 'zweiseitig angebaut'
},
'Bungalow' : {
'typ' : "Einfamilienhaus",
'anbaugrad' : 'freistehend'
},
'Winkelbungalow' : {
'typ' : "Einfamilienhaus",
'anbaugrad' : 'freistehend'
},
'Atrium-Bungalow' : {
'typ' : "Einfamilienhaus",
'anbaugrad' : 'freistehend'
},
};
if (getAnbaugrad) {
return geTypes[this.gebaeude.gebaeudetyp]['anbaugrad'];
}
return geTypes[this.gebaeude.gebaeudetyp]['typ'];
}
public getEnergietraegerBezeichnung(bezeichnung: string, einheit: string) {
let bez = bezeichnung.trim() + einheit.trim();
let retArr = {
'Heizöl ELl' : "Heizöl EL in Liter",
'Heizöl ELkWh' : "Heizöl EL in kWh Brennwert",
'HeizölkWh' : "Heizöl EL in kWh Brennwert",
3 : "Heizöl-Bioöl-Mischung in Liter",
4 : "Heizöl-Bioöl-Mischung in kWh Brennwert",
5 : "Heizöl-Bioöl-Mischung in kWh Brennwert",
6 : "Bioöl in Liter",
7 : "Bioöl in kWh Brennwert",
8 : "Bioöl in kWh Brennwert",
'Erdgas Hm³' : "Erdgas H in m³",
'Erdgas HkWh' : "Erdgas H in kWh Brennwert",
'ErdgaskWh' : "Erdgas H in kWh Brennwert",
12 : "Erdgas-Biogas-Mischung in m³",
13 : "Erdgas-Biogas-Mischung in kWh Brennwert",
14 : "Erdgas-Biogas-Mischung in kWh Brennwert",
15 : "Biogas in m³",
16 : "Biogas in kWh Brennwert",
17 : "Biogas in kWh Brennwert",
'Flüssiggasm³' : "Flüssiggas in m³ gasförmig",
'Flüssiggasl' : "Flüssiggas in Liter flüssig",
'Flüssiggaskg' : "Flüssiggas in kg",
'FlüssiggaskWh' : "Flüssiggas in kWh Brennwert",
22 : "Flüssiggas in kWh Brennwert",
23 : "Steinkohle in kg",
24 : "Steinkohle in kWh Brennwert",
'Kokskg' : "Koks in kg",
'KokskWh' : "Koks in kWh Brennwert",
'Braunkohlekg' : "Braunkohle in kg",
'BraunkohlekWh' : "Braunkohle in kWh Brennwert",
'Brennholzm³' : "Holz in Raummeter",
'BrennholzSRm' : "Holz in Schüttraummeter",
'Brennholzkg' : "Holz in kg",
'BrennholzkWh' : "Holz in kWh Brennwert",
32 : "Holz in kWh Brennwert",
'HolzhackschnitzelSRm' : "Holz in Schüttraummeter",
'Holzhackschnitzelkg' : "Holz in kg",
'HolzhackschnitzelkWh' : "Holz in kWh Brennwert",
36 : "Holz in kWh Brennwert",
'Holz-PelletsSRm' : "Holz in Schüttraummeter",
'Holz-Pelletskg' : "Holz in kg",
'Holz-PelletskWh' : "Holz in kWh Brennwert",
40 : "Holz in kWh Brennwert",
41 : "Wärme aus lokalem BHKW in kWh",
'Nahwärme HKW FBkWh' : "Nah-/Fernwärme aus Heizwerken - fossiler Brennstoff in kWh",
'Fernwärme HKW FBkWh' : "Nah-/Fernwärme aus Heizwerken - fossiler Brennstoff in kWh",
'StrommixkWh' : "allgemeiner Strommix in kWh",
'Erdgas LkWh' : "Erdgas H in kWh Brennwert",
'Erdgas Lm³' : "Erdgas H in m³",
'Erdgasm³' : "Erdgas H in m³",
'Heizöll' : "Heizöl EL in Liter",
'Nahwärme HKW EBkWh' : "Nah-/Fernwärme aus Heizwerken - erneuerbarer Brennstoff in kWh",
'Fernwärme HKW EBkWh' : "Nah-/Fernwärme aus Heizwerken - erneuerbarer Brennstoff in kWh",
'Nahwärme KWK EBkWh' : "Nah-/Fernwärme aus KWK - erneuerbarer Brennstoff in kWh",
'Fernwärme KWK EBkWh' : "Nah-/Fernwärme aus KWK - erneuerbarer Brennstoff in kWh",
'Nahwärme KWK FBkWh' : "Nah-/Fernwärme aus KWK - fossiler Brennstoff in kWh",
'Fernwärme KWK FBkWh' : "Nah-/Fernwärme aus KWK - fossiler Brennstoff in kWh"
};
return retArr[bez];
}
public getEmpfehlungen() {
let empfehlungen = getEmpfehlungen(this.ausweis, this.gebaeude);
if (empfehlungen.length > 0) {
return 'http://www.bbsr-energieeinsparung.de/EnEVPortal/DE/Home/home_node.html';
} else {
return 'Angabe hier nicht relevant';
}
}
public getLueftungsKonzept() {
let lueftungsKonzept: Record<string, string> = {}
lueftungsKonzept['fensterlueftung'] = (this.gebaeude.lueftung == "Fensterlüftung")
? "true" : "false";
lueftungsKonzept['schachtlueftung'] = (this.gebaeude.lueftung == "Schachtlüftung")
? "true" : "false";
lueftungsKonzept['ohneRueckgewinnung'] = (this.gebaeude.lueftung
== "Lüftungsanlage ohne Wärmerückgewinnung") ? "true" : "false";
lueftungsKonzept['mitRueckgewinnung'] = (this.gebaeude.lueftung
== "Lüftungsanlage mit Wärmerückgewinnung") ? "true" : "false";
return lueftungsKonzept;
}
public kellerBeheizt() {
return this.ausweis.keller_beheizt ? "true" : "false";
}
public anlass() {
let anlass = '';
if (this.ausweis.ausstellgrund == "Neubau") {
anlass = 'Neubau';
} else if (this.ausweis.ausstellgrund == "Modernisierung") {
anlass = 'Modernisierung-Erweiterung';
} else if (this.ausweis.ausstellgrund == "Vermietung") {
anlass = 'Vermietung-Verkauf';
} else if (this.ausweis.ausstellgrund == "Aushang") {
anlass = 'Aushangpflicht';
} else {
anlass = 'Sonstiges';
}
return anlass;
}
public async getOrt() {
if (!this.gebaeude.plz) {
return ""
}
const result = await prisma.postleitzahlen.findUnique({
where: {
plz: this.gebaeude.plz
}
})
return result?.bundesland || "";
}
public getBerechAusweis() {
return this._berechParameter;
}
/**
* function to check if several values are filled
*/
public emptyParams() {
let emptyParams: Record<string, string> = {};
emptyParams['wirdGekuehlt'] = this.ausweis.wird_gekuehlt ? 'true' : 'false';
emptyParams['datenErhebungEigentuemer'] = "true";
emptyParams['datenErhebungAussteller'] = "false";
emptyParams['nwheizung'] = this.gebaeude.zentralheizung
? 'true' : 'false';
emptyParams['nwwarmwasser'] = this.gebaeude.einzelofen
? 'true' : 'false';
emptyParams['nwlueftung'] = this.gebaeude.durchlauf_erhitzer
? 'true' : 'false';
emptyParams['nwbeleuchtung'] = this.gebaeude.standard_kessel
? 'true' : 'false';
emptyParams['nwkuehlung'] = this.gebaeude.solarsystem_warmwasser
? 'true' : 'false';
//emptyParams['nwsonstiges'] = this.gebaeude.nwsonstiges
// ? 'true' : 'false';
return emptyParams;
}
public getBauEmpfehlungen() {
let empfehlungen = getEmpfehlungen(this.ausweis, this.gebaeude);
return empfehlungen.map(empfehlung => {
return {
"anlagenteil" : empfehlung["anlagenteil"],
"massnahme" : empfehlung["description"]
}
})
}
public getEnergieEffizienzklasse() {
let param = this._berechParameter.endEnergieVerbrauchGesamt;
if (param < 30) {
return 'A+';
}else if (param < 50) {
return 'A';
}else if (param < 75) {
return 'B';
}else if (param < 100) {
return 'C';
}else if (param < 130) {
return 'D';
}else if (param < 160) {
return 'E';
}else if (param < 200) {
return 'F';
}else if (param < 250) {
return 'G';
}else if (param >= 250) {
return 'H';
}
return this._berechParameter.endEnergieVerbrauchGesamt;
}
public getAusweisParameter() {
return this.ausweis;
}
}

View File

@@ -0,0 +1,350 @@
import {
endEnergieVerbrauchVerbrauchsausweis_2016,
energetischeNutzflaecheVerbrauchsausweisWohnen_2016,
} from "#lib/Berechnungen/VerbrauchsausweisWohnen/VerbrauchsausweisWohnen_2016";
import { getKlimafaktoren } from "#lib/Klimafaktoren";
import { getHeizwertfaktor } from "#lib/server/Heizwertfaktor";
import {
GebaeudeStammdaten,
VerbrauchsausweisWohnen,
prisma,
} from "@ibcornelsen/database";
import { AusweisBerechnungen2016 } from "../AusweisBerechnungen2016";
import moment from "moment";
export async function xmlVerbrauchsausweisWohnen_2016(
ausweis: VerbrauchsausweisWohnen & {
gebaeude_stammdaten: GebaeudeStammdaten;
}
): Promise<string> {
const gebaeude = ausweis.gebaeude_stammdaten;
const bundesland = await prisma.postleitzahlen.findUnique({
where: {
plz: gebaeude.plz as string,
},
});
// Wir müssen die Postleitzahl unkenntlich machen.
let postleitzahl = gebaeude.plz?.substring(0, 3) + "XX";
const result = await endEnergieVerbrauchVerbrauchsausweis_2016(ausweis);
const berechnungen = new AusweisBerechnungen2016(
ausweis,
ausweis.gebaeude_stammdaten,
result
);
const klimafaktoren = await getKlimafaktoren(
ausweis.startdatum,
gebaeude.plz
);
// Berechnungen
let bauAltersKlasseAnlage = berechnungen.altersKlasse("baujahr_heizung");
let bauAltersKlasseGebaeude = berechnungen.altersKlasse("baujahr_gebaeude");
let kellerBeheizt = ausweis.keller_beheizt ? "true" : "false";
let Zeitraum1von = moment(ausweis.startdatum);
let Zeitraum1bis = Zeitraum1von.clone()
.add("12", "month")
.format("YYYY-MM-DD");
let Zeitraum2von = Zeitraum1von.clone()
.add("12", "month")
.add("1", "day")
.format("YYYY-MM-DD");
let Zeitraum2bis = Zeitraum1von.clone()
.add("24", "month")
.format("YYYY-MM-DD");
let Zeitraum3von = Zeitraum1von.clone()
.add("24", "month")
.add("1", "day")
.format("YYYY-MM-DD");
let Zeitraum3bis = Zeitraum1von.clone()
.add("36", "month")
.format("YYYY-MM-DD");
let lueftungsKonzept = berechnungen.getLueftungsKonzept();
let gebaeudeTyp = berechnungen.getGebaeudeTyp();
let erstellungsdatum = moment(ausweis.erstellungsdatum).format(
"YYYY-MM-DD"
);
let empfehlungen = berechnungen.getBauEmpfehlungen();
let empfehlungenMoeglich = empfehlungen.length > 0 ? "true" : "false";
let energieeffizienzKlasse = berechnungen.getEnergieEffizienzklasse();
let keineNutzungWarmwasser = ausweis.warmwasser_enthalten
? "false"
: "true";
let heizwertfaktor_1 = getHeizwertfaktor(
ausweis.brennstoff_1,
ausweis.einheit_1
);
let heizwertfaktor_2 = getHeizwertfaktor(
ausweis.brennstoff_2,
ausweis.einheit_2
);
let warmWasserErmittlung =
(ausweis.anteil_warmwasser_1 || 0) > 0
? "direkter Messwert Wärmemenge"
: "Rechenwert nach Heizkostenverordnung (Wohngebäude)";
let warmWasserErmittlung_2 =
(ausweis.anteil_warmwasser_2 || 0) > 0
? "direkter Messwert Wärmemenge"
: "Rechenwert nach Heizkostenverordnung (Wohngebäude)";
if (!ausweis.warmwasser_enthalten) {
warmWasserErmittlung =
"Pauschale für dezentrale Warmwasserbereitung (Wohngebäude)";
warmWasserErmittlung_2 =
"Pauschale für dezentrale Warmwasserbereitung (Wohngebäude)";
}
let anlageKuehlung = ausweis.wird_gekuehlt ? "true" : "false";
let verwalt = "";
let artalt = "";
if (ausweis.alternative_heizung) {
verwalt += "Heizung ";
}
if (ausweis.alternative_warmwasser) {
verwalt += "Warmwasser ";
}
if (ausweis.alternative_lueftung) {
verwalt += "Lüftung ";
}
if (ausweis.alternative_kuehlung) {
verwalt += "Kühlung ";
}
if (gebaeude.solarsystem_warmwasser) {
artalt += "Solar ";
}
if (gebaeude.waermepumpe) {
artalt += "Erdwärme oder Umgebungswärme ";
}
if (
ausweis.brennstoff_2 == "Holz-Pellets" ||
ausweis.brennstoff_2 == "Brennholz" ||
ausweis.brennstoff_2 == "Holzhackschnitzel" ||
ausweis.brennstoff_2 == "Nah/Fernwärme KWK EB" ||
ausweis.brennstoff_2 == "Nah/Fernwärme HKW EB" ||
ausweis.brennstoff_1 == "Holz-Pellets" ||
ausweis.brennstoff_1 == "Brennholz" ||
ausweis.brennstoff_1 == "Holzhackschnitzel" ||
ausweis.brennstoff_1 == "Nah/Fernwärme KWK EB" ||
ausweis.brennstoff_1 == "Nah/Fernwärme HKW EB"
) {
artalt += "Nachwachsend ";
}
artalt = artalt || "keine";
verwalt = verwalt || "keine";
let gebaeudeTeil = berechnungen.getGebaeudeTeil();
const energetischeNutzflaeche =
energetischeNutzflaecheVerbrauchsausweisWohnen_2016(ausweis);
let flaecheGekuehlt = ausweis.wird_gekuehlt ? energetischeNutzflaeche : 0;
let endEnergieVerbrauchGesamt = Math.round(
result.endEnergieVerbrauchGesamt
);
let primaerEnergieVerbrauchGesamt = Math.round(
result.primaerEnergieVerbrauchGesamt
);
let energieTraeger = berechnungen.getEnergietraegerBezeichnung(
ausweis.brennstoff_1,
ausweis.einheit_1
);
let energieTraeger_2 = berechnungen.getEnergietraegerBezeichnung(
ausweis.brennstoff_2,
ausweis.einheit_2
);
let warmwasserZuschlag = Math.round(result.energieVerbrauchWarmwasser_1);
let leerstandsZuschlagHeizung = Math.round(
result.leerstandsZuschlagHeizung
);
let Aussteller_ID_DIB = "jens.cornelsen@ib-cornelsen.de";
let Aussteller_PWD_DIBT = "62465E79F6A61F31C4DCA9E2AF788DD3";
let energieVerbrauch_1 = Math.round(result.verbrauch_1_kwh);
let energieVerbrauch_2 = Math.round(result.verbrauch_2_kwh);
let energieVerbrauch_3 = Math.round(result.verbrauch_3_kwh);
let xml = `<ZusatzdatenErfassung xmlns='http://energieausweis.dibt.de/WebServiceEnergie/DibtEnergieAusweisService'>
<doc>
<n1:EnEV-Energieausweis xmlns:n1=\"https://energieausweis.dibt.de/schema/Kontrollsystem_Versionsstand_2016-06-30.xsd\">
<n1:Energieausweis-Daten EnEV-Version=\"2013\" Rechtsstand=\"2016-01-01\">
<n1:Registriernummer>${ausweis.registriernummer}</n1:Registriernummer>
<n1:Ausstellungsdatum>${erstellungsdatum}</n1:Ausstellungsdatum>
<n1:Bundesland>${bundesland?.bundesland}</n1:Bundesland>
<n1:Postleitzahl>${postleitzahl}</n1:Postleitzahl>
<n1:Gebaeudeteil>${gebaeudeTeil}</n1:Gebaeudeteil>
<n1:Baujahr-Gebaeude>${gebaeude.baujahr_gebaeude}</n1:Baujahr-Gebaeude>
<n1:Altersklasse-Gebaeude>${bauAltersKlasseGebaeude}</n1:Altersklasse-Gebaeude>
<n1:Baujahr-Waermeerzeuger>${gebaeude.baujahr_heizung}</n1:Baujahr-Waermeerzeuger>
<n1:Altersklasse-Waermeerzeuger>${bauAltersKlasseAnlage}</n1:Altersklasse-Waermeerzeuger>
<n1:wesentliche-Energietraeger>${energieTraeger}</n1:wesentliche-Energietraeger>
<n1:Erneuerbare-Art>${artalt}</n1:Erneuerbare-Art>
<n1:Erneuerbare-Verwendung>${verwalt}</n1:Erneuerbare-Verwendung>
<n1:Lueftungsart-Fensterlueftung>${lueftungsKonzept["fensterlueftung"]}</n1:Lueftungsart-Fensterlueftung>
<n1:Lueftungsart-Schachtlueftung>${lueftungsKonzept["schachtlueftung"]}</n1:Lueftungsart-Schachtlueftung>
<n1:Lueftungsart-Anlage-o-WRG>${lueftungsKonzept["ohneRueckgewinnung"]}</n1:Lueftungsart-Anlage-o-WRG>
<n1:Lueftungsart-Anlage-m-WRG>${lueftungsKonzept["mitRueckgewinnung"]}</n1:Lueftungsart-Anlage-m-WRG>
<n1:Anlage-zur-Kuehlung>${anlageKuehlung}</n1:Anlage-zur-Kuehlung>
<n1:Ausstellungsanlass>{berechnungen.anlass()}</n1:Ausstellungsanlass>
<n1:Datenerhebung-Aussteller>false</n1:Datenerhebung-Aussteller>
<n1:Datenerhebung-Eigentuemer>true</n1:Datenerhebung-Eigentuemer>
<n1:Wohngebaeude>
<n1:Gebaeudetyp>${gebaeudeTyp}</n1:Gebaeudetyp>
<n1:Anzahl-Wohneinheiten>${gebaeude.einheiten}</n1:Anzahl-Wohneinheiten>
<n1:Gebaeudenutzflaeche>${energetischeNutzflaeche}</n1:Gebaeudenutzflaeche>
<n1:Verbrauchswerte>
<n1:Flaechenermittlung-AN-aus-Wohnflaeche>true</n1:Flaechenermittlung-AN-aus-Wohnflaeche>
<n1:Wohnflaeche>${gebaeude.flaeche}</n1:Wohnflaeche>
<n1:Keller-beheizt>${kellerBeheizt}</n1:Keller-beheizt>
<n1:Energietraeger>
<n1:Energietraeger-Verbrauch>${energieTraeger}</n1:Energietraeger-Verbrauch>
<n1:Unterer-Heizwert>${heizwertfaktor_1.umrechnungsfaktor}</n1:Unterer-Heizwert>
<n1:Primaerenergiefaktor>${heizwertfaktor_1.primaerenergiefaktor}</n1:Primaerenergiefaktor>
<n1:Zeitraum>
<n1:Startdatum>${Zeitraum1von}</n1:Startdatum>
<n1:Enddatum>${Zeitraum1bis}</n1:Enddatum>
<n1:Verbrauchte-Menge>${ausweis.verbrauch_1}</n1:Verbrauchte-Menge>
<n1:Energieverbrauch>${energieVerbrauch_1}</n1:Energieverbrauch>
<n1:Energieverbrauchsanteil-Warmwasser-zentral>${ausweis.anteil_warmwasser_1}</n1:Energieverbrauchsanteil-Warmwasser-zentral>
<n1:Warmwasserwertermittlung>${warmWasserErmittlung}</n1:Warmwasserwertermittlung>
<n1:Klimafaktor>${klimafaktoren[0]}</n1:Klimafaktor>
</n1:Zeitraum>
<n1:Zeitraum>
<n1:Startdatum>${Zeitraum2von}</n1:Startdatum>
<n1:Enddatum>${Zeitraum2bis}</n1:Enddatum>
<n1:Verbrauchte-Menge>${ausweis.verbrauch_2}</n1:Verbrauchte-Menge>
<n1:Energieverbrauch>${energieVerbrauch_2}</n1:Energieverbrauch>
<n1:Energieverbrauchsanteil-Warmwasser-zentral>${ausweis.anteil_warmwasser_1}</n1:Energieverbrauchsanteil-Warmwasser-zentral>
<n1:Warmwasserwertermittlung>${warmWasserErmittlung}</n1:Warmwasserwertermittlung>
<n1:Klimafaktor>${klimafaktoren[1]}</n1:Klimafaktor>
</n1:Zeitraum>
<n1:Zeitraum>
<n1:Startdatum>${Zeitraum3von}</n1:Startdatum>
<n1:Enddatum>${Zeitraum3bis}</n1:Enddatum>
<n1:Verbrauchte-Menge>${ausweis.verbrauch_3}</n1:Verbrauchte-Menge>
<n1:Energieverbrauch>${energieVerbrauch_3}</n1:Energieverbrauch>
<n1:Energieverbrauchsanteil-Warmwasser-zentral>${ausweis.anteil_warmwasser_1}</n1:Energieverbrauchsanteil-Warmwasser-zentral>
<n1:Warmwasserwertermittlung>${warmWasserErmittlung}</n1:Warmwasserwertermittlung>
<n1:Klimafaktor>${klimafaktoren[2]}</n1:Klimafaktor>
</n1:Zeitraum>
</n1:Energietraeger>`;
if (ausweis.zusaetzliche_heizquelle) {
xml += `<n1:Energietraeger>
<n1:Energietraeger-Verbrauch>${energieTraeger_2}</n1:Energietraeger-Verbrauch>
<n1:Unterer-Heizwert>${heizwertfaktor_2.umrechnungsfaktor}</n1:Unterer-Heizwert>
<n1:Primaerenergiefaktor>${heizwertfaktor_2.primaerenergiefaktor}</n1:Primaerenergiefaktor>
<n1:Zeitraum>
<n1:Startdatum>${Zeitraum1von}</n1:Startdatum>
<n1:Enddatum>${Zeitraum1bis}</n1:Enddatum>
<n1:Verbrauchte-Menge>${ausweis.verbrauch_4}</n1:Verbrauchte-Menge>
<n1:Energieverbrauch>${result.verbrauch_4_kwh}</n1:Energieverbrauch>
<n1:Energieverbrauchsanteil-Warmwasser-zentral>${ausweis.anteil_warmwasser_2}</n1:Energieverbrauchsanteil-Warmwasser-zentral>
<n1:Warmwasserwertermittlung>${warmWasserErmittlung_2}</n1:Warmwasserwertermittlung>
<n1:Klimafaktor>${klimafaktoren[0]}</n1:Klimafaktor>
</n1:Zeitraum>
<n1:Zeitraum>
<n1:Startdatum>${Zeitraum2von}</n1:Startdatum>
<n1:Enddatum>${Zeitraum2bis}</n1:Enddatum>
<n1:Verbrauchte-Menge>${ausweis.verbrauch_5}</n1:Verbrauchte-Menge>
<n1:Energieverbrauch>${result.verbrauch_5_kwh}</n1:Energieverbrauch>
<n1:Energieverbrauchsanteil-Warmwasser-zentral>${ausweis.anteil_warmwasser_2}</n1:Energieverbrauchsanteil-Warmwasser-zentral>
<n1:Warmwasserwertermittlung>${warmWasserErmittlung_2}</n1:Warmwasserwertermittlung>
<n1:Klimafaktor>${klimafaktoren[1]}</n1:Klimafaktor>
</n1:Zeitraum>
<n1:Zeitraum>
<n1:Startdatum>${Zeitraum3von}</n1:Startdatum>
<n1:Enddatum>${Zeitraum3bis}</n1:Enddatum>
<n1:Verbrauchte-Menge>${ausweis.verbrauch_6}</n1:Verbrauchte-Menge>
<n1:Energieverbrauch>${result.verbrauch_6_kwh}</n1:Energieverbrauch>
<n1:Energieverbrauchsanteil-Warmwasser-zentral>${ausweis.anteil_warmwasser_2}</n1:Energieverbrauchsanteil-Warmwasser-zentral>
<n1:Warmwasserwertermittlung>${warmWasserErmittlung_2}</n1:Warmwasserwertermittlung>
<n1:Klimafaktor>${klimafaktoren[2]}</n1:Klimafaktor>
</n1:Zeitraum>
</n1:Energietraeger>`;
}
xml += `<n1:Leerstandszuschlag-Heizung>
<n1:Leerstandszuschlag-nach-Bekanntmachung>
<n1:Leerstandsfaktor>${result.leerstand}</n1:Leerstandsfaktor>
<n1:Startdatum>${Zeitraum1von}</n1:Startdatum>
<n1:Enddatum>${Zeitraum3bis}</n1:Enddatum>
<n1:Leerstandszuschlag-kWh>${leerstandsZuschlagHeizung}</n1:Leerstandszuschlag-kWh>
<n1:Primaerenergiefaktor>${heizwertfaktor_1.primaerenergiefaktor}</n1:Primaerenergiefaktor>
</n1:Leerstandszuschlag-nach-Bekanntmachung>
</n1:Leerstandszuschlag-Heizung>
<n1:Leerstandszuschlag-Warmwasser>`;
if (
ausweis.warmwasser_enthalten &&
(gebaeude.leerstand || 0) > 0 &&
(ausweis.anteil_warmwasser_1 || 0) > 0
) {
xml += `<n1:keine-Nutzung-von-WW>${keineNutzungWarmwasser}</n1:keine-Nutzung-von-WW>
<n1:kein-Leerstand>Kein längerer Leerstand Warmwasser zu berücksichtigen.</n1:kein-Leerstand>`;
} else {
xml += `<n1:keine-Nutzung-von-WW>${keineNutzungWarmwasser}</n1:keine-Nutzung-von-WW>
<n1:kein-Leerstand>Kein längerer Leerstand Warmwasser zu berücksichtigen.</n1:kein-Leerstand>`;
}
xml += `</n1:Leerstandszuschlag-Warmwasser>
<n1:Warmwasserzuschlag>
<n1:Startdatum>${Zeitraum1von}</n1:Startdatum>
<n1:Enddatum>${Zeitraum3bis}</n1:Enddatum>
<n1:Primaerenergiefaktor>${heizwertfaktor_1.primaerenergiefaktor}</n1:Primaerenergiefaktor>
<n1:Warmwasserzuschlag-kWh>${warmwasserZuschlag}</n1:Warmwasserzuschlag-kWh>
</n1:Warmwasserzuschlag>
<n1:Kuehlzuschlag>
<n1:Startdatum>${Zeitraum1von}</n1:Startdatum>
<n1:Enddatum>${Zeitraum3bis}</n1:Enddatum>
<n1:Gebaeudenutzflaeche-gekuehlt>${flaecheGekuehlt}</n1:Gebaeudenutzflaeche-gekuehlt>
<n1:Primaerenergiefaktor>1.8</n1:Primaerenergiefaktor>
<n1:Kuehlzuschlag-kWh>${result.kuehlungsZuschlag}</n1:Kuehlzuschlag-kWh>
</n1:Kuehlzuschlag>
<n1:Mittlerer-Endenergieverbrauch>${endEnergieVerbrauchGesamt}</n1:Mittlerer-Endenergieverbrauch>
<n1:Mittlerer-Primaerenergieverbrauch>${primaerEnergieVerbrauchGesamt}</n1:Mittlerer-Primaerenergieverbrauch>
<n1:Energieeffizienzklasse>${energieeffizienzKlasse}</n1:Energieeffizienzklasse>
</n1:Verbrauchswerte>
</n1:Wohngebaeude>
<n1:Empfehlungen-moeglich>${empfehlungenMoeglich}</n1:Empfehlungen-moeglich>`;
let i = 1;
for (const empfehlung of empfehlungen) {
let description = empfehlung.massnahme.replace(/\n/g, "");
xml += `<n1:Modernisierungsempfehlungen>
<n1:Nummer>${i}</n1:Nummer>
<n1:Bauteil-Anlagenteil>${empfehlung["anlagenteil"]}</n1:Bauteil-Anlagenteil>
<n1:Massnahmenbeschreibung>${description}</n1:Massnahmenbeschreibung>
<n1:Modernisierungskombination>in Zusammenhang mit größerer Modernisierung</n1:Modernisierungskombination>
</n1:Modernisierungsempfehlungen>`;
i++;
}
xml += `<n1:Extrablatt-Modernisierung>false</n1:Extrablatt-Modernisierung>
<n1:Softwarehersteller-Programm-Version>Version 2.0</n1:Softwarehersteller-Programm-Version>
</n1:Energieausweis-Daten>
</n1:EnEV-Energieausweis>
</doc>
<ausweisnummer>${ausweis.registriernummer}</ausweisnummer>
<username>${Aussteller_ID_DIB}</username>
<passwort>${Aussteller_PWD_DIBT}</passwort>
</ZusatzdatenErfassung>
`;
return xml;
}

View File

@@ -0,0 +1,125 @@
import { GebaeudeStammdaten, VerbrauchsausweisWohnen } from "@ibcornelsen/database";
import moment from "moment";
export function getEmpfehlungen(ausweis: VerbrauchsausweisWohnen, gebaeude: GebaeudeStammdaten): {
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 empfehlungen = [];
if (gebaeude.einfach_verglasung || (Doppelfenster && Fenster_teilw_undicht)) {
empfehlungen.push({
"title" : "Erneuerung der Fenster",
"description" : "Alte und undichte Fenster mit Wärmeschutzfenstern auswechseln.",
"anlagenteil" : "Fenster"
});
}
if (gebaeude.dachgeschoss == "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) {
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.",
"anlagenteil" : "Dach"
});
}
if (!Aussenwand_gedaemmt) {
empfehlungen.push({
"title" : "Außenwand zusätzl. dämmen (z.B. Wärmedämmverbundsystem, Einblasdämmung, Dämmputz)",
"description" : "Beim WDVS sollte man mit Dämmstärken ab 12cm planen. Bei zweischaligem Mauerwerk Luftschicht mit Einblasdämmung füllen. Bei historischen Fassaden kommt u.U. eine Innendämmung in Betracht",
"anlagenteil" : "Außenwand gg. Außenluft"
});
}
let Relanlagenjahr = moment().year() - 35;
if ((!Brennwertkessel && !Waermepumpe) && baujahr_anlagesanlage <= Relanlagenjahr && Brennstoff != 'Fernwärme' && Brennstoff != 'Strommix') {
empfehlungen.push({
"title" : "Anlagentechnik",
"description" : "Prüfen Sie, ob Sie bei einer Umrüstung auf einen regenerativen Anteil von 65% kommen. Bei energetisch sanierten Gebäuden z.B. Wärmepumpe. Bei unsanieten Gebäuden Fernwärmeanschluss.",
"anlagenteil" : "Wärmeerzeuger"
});
}
if (!Kellerdecke_Kalraeume_gedaemmt && Keller == "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") {
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.",
"anlagenteil" : "Außenwand gg. Erdreich"
});
}
if (Zentralheizung) {
if (!Warmwasserrohre_gedaemmt && !Heizungsrohre_gedaemmt) {
empfehlungen.push({
"title" : "Anlagentechnik",
"description" : "Heizungsrohre und Warmwasserrohre dämmen",
"anlagenteil" : "Wärmeverteilung / -abgabe"
});
} else if (Warmwasserrohre_gedaemmt && !Heizungsrohre_gedaemmt) {
empfehlungen.push({
"title" : "Anlagentechnik",
"description" : "Heizungsrohre dämmen",
"anlagenteil" : "Wärmeverteilung / -abgabe"
});
} else if (!Warmwasserrohre_gedaemmt && Heizungsrohre_gedaemmt) {
empfehlungen.push({
"title" : "Anlagentechnik",
"description" : "Warmwasserrohre dämmen",
"anlagenteil" : "Wärmeverteilung / -abgabe"
});
}
}
if ((baujahr_anlagesanlage <= (moment().year() - 30)) && (Brennstoff == "Heizöl" || Brennstoff == "Erdgas") && !Waermepumpe) {
// Wärmepumpe
empfehlungen.push({
"title" : "Wärmeerzeuger",
"description" : "Prüfen Sie den zusätzlichen Einbau einer Luft-Wasser-Wärmepumpe. Mit einem Pufferspeicher und einer 75°C-Vorlauftemperatur-Wärmepumpe kann ein relevanter Anteil der Wärmeerzeugung abgedeckt werden.",
"anlagenteil" : "Wärmeerzeuger"
});
}
if (!photovoltaik && Brennstoff == "Strommix") {
// Wärmepumpe
empfehlungen.push({
"title" : "Wärmeerzeuger",
"description" : "PV-Anlage auf das Dach (für Energieunterstützung)",
"anlagenteil" : "Wärmeerzeuger"
});
}
return empfehlungen;
}

View File

@@ -1,47 +0,0 @@
import { db } from "../shared";
type DatabaseZIPInformation = {
zip: string,
city: string,
state: string
};
export class ZIPInformation {
public constructor(public zip: string, public city: string, public state: string) {
}
public static async fromZipCode(zip: string): Promise<null | ZIPInformation[]> {
if (zip.length > 5) {
return null;
}
let results = await db<DatabaseZIPInformation>("zip_codes").select("*").whereLike("zip", `${zip}%`).limit(10);
if (!results) {
return null;
}
return results.map(result => new ZIPInformation(result.zip, result.city, result.state))
}
public static async fromCity(city: string): Promise<null | ZIPInformation[]> {
let results = await db<DatabaseZIPInformation>("zip_codes").select("*").where("city", city);
if (!results) {
return null;
}
return results.map(result => new ZIPInformation(result.zip, result.city, result.state))
}
public static async fromState(state: string): Promise<null | ZIPInformation[]> {
let results = await db<DatabaseZIPInformation>("zip_codes").select("*").where("state", state);
if (!results) {
return null;
}
return results.map(result => new ZIPInformation(result.zip, result.city, result.state))
}
}

View File

@@ -1,145 +0,0 @@
import { Benutzer, Rechnungen, VerbrauchsausweisWohnen } from "@ibcornelsen/database";
import { Gebaeude } from "src/lib/Gebaeude";
import { getKlimafaktorenClient } from "src/lib/Klimafaktoren";
import { getHeizwertfaktor } from "src/lib/server/Heizwertfaktor";
export class Verbrauchsausweis implements Partial<VerbrauchsausweisWohnen & { benutzer: Benutzer, rechnung: Rechnungen }> {
rechnungen_id: number | null = null;
erstellungsdatum: Date | null = null;
ausstellgrund: string | null = null;
registriernummer: string | null = null;
erledigt: boolean | null = null;
baujahr_heizung: number[] = [];
zusaetzliche_heizquelle: boolean | null = null;
brennstoff_1: string | null = null;
einheit_1: string | null = null;
brennstoff_2: string | null = null;
einheit_2: string | null = null;
startdatum: Date | null = null;
enddatum: Date | null = null;
verbrauch_1: number | null = null;
verbrauch_2: number | null = null;
verbrauch_3: number | null = null;
verbrauch_4: number | null = null;
verbrauch_5: number | null = null;
verbrauch_6: number | null = null;
warmwasser_enthalten: boolean | null = null;
anteil_warmwasser_1: number | null = null;
anteil_warmwasser_2: number | null = null;
public get energetischeNutzflaeche(): number {
return (
this.gebaeude.wohnflaeche *
(this.gebaeude.keller_beheizt ? 1.35 : 1.2)
);
}
public regnummer?: string;
public gebaeude: Gebaeude = new Gebaeude();
public constructor(initializer?: VerbrauchsausweisWohnen) {
if (initializer) {
Object.assign(this, initializer)
}
}
public get primaerEnergieVerbrauch(): Promise<number> {
return (async () => {
const Endenergieverbrauch = await this.endEnergieVerbrauch;
const brennstoff_1 = getHeizwertfaktor(
this.brennstoff_1,
this.einheit_1
);
return Endenergieverbrauch * brennstoff_1.primaerenergiefaktor;
})();
}
public get endEnergieVerbrauch(): Promise<number> {
return (async () => {
const date = this.startdatum;
const klimafaktoren = await getKlimafaktorenClient(
date,
this.gebaeude.plz
);
// Endenergieverbrauch
// Um den EEV auszurechnen, müssen die Verbräuche zu kWh konvertiert werden.
let brennstoff_1 = getHeizwertfaktor(
this.brennstoff_1,
this.einheit_1
);
let brennstoff_2 = getHeizwertfaktor(
this.brennstoff_2,
this.einheit_2
);
let verbrauch_1_kwh =
this.verbrauch_1 * brennstoff_1.umrechnungsfaktor;
let verbrauch_2_kwh =
this.verbrauch_2 * brennstoff_1.umrechnungsfaktor;
let verbrauch_3_kwh =
this.verbrauch_3 * brennstoff_1.umrechnungsfaktor;
let verbrauch_4_kwh =
this.verbrauch_4 * brennstoff_2.umrechnungsfaktor;
let verbrauch_5_kwh =
this.verbrauch_5 * brennstoff_2.umrechnungsfaktor;
let verbrauch_6_kwh =
this.verbrauch_6 * brennstoff_2.umrechnungsfaktor;
let warmwasserZuschlag = 0;
let leerstandsZuschlag = 0;
let kuehlungsZuschlag = 0;
if (this.anteil_warmwasser_1 == 0) {
warmwasserZuschlag = 20 * this.energetischeNutzflaeche * 3;
}
if (this.gebaeude.leerstand > 0) {
let durchschnittsKlimafaktor =
klimafaktoren.reduce((a, b) => a + b, 0) / 3;
leerstandsZuschlag =
((verbrauch_1_kwh +
verbrauch_2_kwh +
verbrauch_3_kwh +
verbrauch_4_kwh +
verbrauch_5_kwh +
verbrauch_6_kwh) *
(this.gebaeude.leerstand / 100)) /
durchschnittsKlimafaktor;
}
if (this.gebaeude.energiequelle_2_nutzung[3]) {
kuehlungsZuschlag = 6 * this.energetischeNutzflaeche * 3;
}
let anteil_heizung = 1 - this.anteil_warmwasser_1 / 100;
let anteil_warmwasser = this.anteil_warmwasser_1 / 100;
let Energieverbrauchskennwert =
(anteil_heizung *
(verbrauch_1_kwh + verbrauch_4_kwh) *
klimafaktoren[0] +
anteil_warmwasser * (verbrauch_1_kwh + verbrauch_4_kwh) +
anteil_heizung *
(verbrauch_2_kwh + verbrauch_5_kwh) *
klimafaktoren[1] +
anteil_warmwasser * (verbrauch_2_kwh + verbrauch_5_kwh) +
anteil_heizung *
(verbrauch_3_kwh + verbrauch_6_kwh) *
klimafaktoren[2] +
anteil_warmwasser * (verbrauch_3_kwh + verbrauch_6_kwh) +
warmwasserZuschlag +
leerstandsZuschlag +
kuehlungsZuschlag) /
3 /
this.energetischeNutzflaeche;
return Energieverbrauchskennwert;
})();
}
}

View File

@@ -1 +0,0 @@
export { default as Verbrauchsausweis } from "./Verbrauchsausweis";

View File

@@ -1,36 +0,0 @@
import { Ausweis } from "src/lib/Ausweis/Ausweis";
import { Dachgeschoss, Lueftungskonzept } from "src/lib/Ausweis/types";
import { BitChecker } from "src/lib/BitChecker";
export class Gebaeude {
public typ: string = "";
public plz: string = "";
public ort: string = "";
public strasse: string = "";
public gebaeudeteil: string = "";
public saniert: boolean = false;
public baujahr: number = 0;
public einheiten: number = 0;
public wohnflaeche: number = 0;
public keller_beheizt: boolean = false;
public dachgeschoss_beheizt: Dachgeschoss = Dachgeschoss.UNBEHEIZT;
public lueftungskonzept: Lueftungskonzept = "Fensterlüftung";
public wird_gekuehlt: boolean = false;
public leerstand: number = 0;
public versorgungssysteme: boolean[] = BitChecker(0);
public fenster_dach: boolean[] = BitChecker(0);
public energiequelle_2_nutzung: boolean[] = BitChecker(0);
public daemmung: boolean[] = BitChecker(0);
public ausweis?: Ausweis;
public uid?: string;
public constructor(initializer?: Gebaeude) {
if (initializer) {
this.typ = initializer.typ;
this.plz = initializer.plz;
this.ort = initializer.ort;
}
}
}

View File

@@ -1,9 +0,0 @@
export async function fetch(resourceUri: string, options?: RequestInit): Promise<any> {
const response = await fetch(`/api/${resourceUri}`, options);
if (!response.ok) {
throw new Error("Fehler beim Abrufen der Daten.");
}
return response.json();
}

View File

@@ -15,6 +15,7 @@
import { auditBedarfsausweisBenoetigt } from "#components/Verbrauchsausweis/audits/BedarfsausweisBenoetigt";
import { auditVerbrauchAbweichung } from "#components/Verbrauchsausweis/audits/VerbrauchAbweichung";
import { GebaeudeStammdaten, VerbrauchsausweisWohnen } from "@ibcornelsen/database";
import trpc from "src/trpc";
export let uid: string = "";
@@ -58,8 +59,24 @@
gebaeude = gebaeude;
ausweis = ausweis;
}
async function ausweisAbschicken() {
overlay.ariaHidden = "false";
const response = await trpc.v1.verbrauchsausweisWohnen[2016].erstellen.mutate({
...ausweis,
gebaeude_stammdaten: gebaeude
})
}
let overlay: HTMLDivElement;
</script>
<div bind:this={overlay} aria-hidden="true" class="aria-hidden:hidden fixed top-0 left-0 w-[100vw] h-[100vh] flex items-center justify-center bg-[rgba(0,0,0,0.8)] z-50">
<p class="text-white font-semibold text-4xl">Bitte warten sie, ihr Ausweis wird nun erstellt.</p>
</div>
<div class="flex flex-row gap-8 items-center mb-8">
<div class="flex flex-col w-full">
<h1>Verbrauchsausweis erstellen - 45€</h1>
@@ -69,8 +86,8 @@
<PerformanceScore bind:ausweis bind:gebaeude />
</div>
<form method="post" action="/verbrauchsausweis/erstellen">
<fieldset
<div>
<div
class="bg-[rgba(252,234,187,0.2)] border-2 p-4 rounded-lg border-[#ffcc03]"
>
<div class="flex flex-row justify-between">
@@ -107,8 +124,7 @@
</HelpLabel>
<div>
<input
name="IGstrasse"
class=" strasse"
name="adresse"
type="text"
autocomplete="off"
required
@@ -128,14 +144,13 @@
/>
</div>
<!-- IGort: readonly entfernt - Nelson -->
<div class="form-group col-md-4">
<HelpLabel title="Ort *">
Ort des Gebäudes wird automatisch ermittelt.
</HelpLabel>
<div>
<input
name="IGort"
name="ort"
readonly={true}
bind:value={gebaeude.ort}
type="text"
@@ -152,7 +167,7 @@
</HelpLabel>
<div>
<input
name="IGflaeche"
name="flaeche"
maxlength="4"
type="number"
required
@@ -169,7 +184,7 @@
<Label>Keller *</Label>
<div>
<select
name="IGkeller"
name="keller_beheizt"
required
bind:value={ausweis.keller_beheizt}
>
@@ -185,7 +200,7 @@
<div class="form-group col-md-4">
<Label>Dachgeschoss *</Label>
<div>
<select name="IGdach" class="" required>
<select name="dachgeschoss" required>
<option>Bitte auswählen</option>
<option value="dnein">nicht vorhanden</option>
<option value="dub">unbeheizt</option>
@@ -217,8 +232,7 @@
<label class="radio-inline"
><input
type="checkbox"
class="IGwwbool"
name="IGwwbool"
name="warmwasser_enthalten"
bind:checked={ausweis
.warmwasser_enthalten}
/>Warmwasser im Verbrauch enthalten</label
@@ -234,7 +248,7 @@
</HelpLabel>
<input
name="IGwarmwasser"
name="anteil_warmwasser_1"
maxlength="2"
type="number"
bind:value={ausweis.anteil_warmwasser_1}
@@ -250,7 +264,7 @@
ein Anteil von 18% angenommen.
</HelpLabel>
<input
name="IGwarmwasser2"
name="anteil_warmwasser_2"
maxlength="3"
type="number"
autocomplete="off"
@@ -273,7 +287,7 @@
<label class="checkbox-inline"
><input
type="checkbox"
name="IGversorgungssysteme1"
name="alternative_heizung"
bind:checked={ausweis.alternative_heizung}
value="Heizung"
/>Heizung</label
@@ -281,7 +295,7 @@
<label class="checkbox-inline"
><input
type="checkbox"
name="IGversorgungssysteme2"
name="alternative_warmwasser"
bind:checked={ausweis.alternative_warmwasser}
value="Warmwasser"
/>Warmwasser</label
@@ -289,7 +303,7 @@
<label class="checkbox-inline"
><input
type="checkbox"
name="IGversorgungssysteme3"
name="alternative_lueftung"
bind:checked={ausweis.alternative_lueftung}
value="Lüftung"
/>Lüftung</label
@@ -297,7 +311,7 @@
<label class="checkbox-inline"
><input
type="checkbox"
name="IGversorgungssysteme4"
name="alternative_kuehlung "
bind:checked={ausweis.alternative_kuehlung}
value="Kühlung"
/>Kühlung</label
@@ -320,7 +334,7 @@
Bitte wählen Sie hier den Gebäudetyp aus.
</HelpLabel>
<div>
<select name="IGtyp" class="" required autocomplete="off">
<select name="gebaeudetyp" required autocomplete="off">
<option>Bitte auswählen</option>
<option value="Einfamilienhaus">Einfamilienhaus</option>
<option value="Freistehendes Einfamilienhaus"
@@ -359,7 +373,7 @@
'Gewerbe'.
</HelpLabel>
<div>
<select name="IGteil" class="" required autocomplete="off">
<select name="gebaeudeteil" class="" required autocomplete="off">
<option>Bitte auswählen</option>
<option value="Gesamtgebäude">Gesamtgebäude</option>
<option value="Wohnen">Wohnen</option>
@@ -375,10 +389,10 @@
</HelpLabel>
<div>
<select
name="IGlueftung"
class=""
name="lueftung"
required
autocomplete="off"
bind:value={gebaeude.lueftung}
>
<option>Bitte auswählen</option>
<option value="Fensterlüftung">Fensterlüftung</option>
@@ -401,10 +415,11 @@
</HelpLabel>
<div>
<select
name="IGkuehlung"
name="kuehlung"
class=""
required
autocomplete="off"
bind:value={gebaeude.kuehlung}
>
<option>Bitte auswählen</option>
<option value="1">vorhanden</option>
@@ -422,10 +437,11 @@
</HelpLabel>
<div>
<input
name="IGleer"
name="leerstand"
maxlength="2"
type="text"
autocomplete="off"
bind:value={gebaeude.leerstand}
/>
</div>
</div>
@@ -441,10 +457,10 @@
<hr />
<div class="flex flex-row justify-between">
<Hilfe />
<button class="button">Weiter</button>
<button class="button" on:click={ausweisAbschicken}>Weiter</button>
</div>
</fieldset>
</form>
</div>
</div>
<RawNotificationWrapper>

View File

@@ -1,137 +0,0 @@
import type { APIRoute } from "astro";
import { error, success } from "src/lib/APIResponse";
import { z } from "zod";
const AusweisUploadChecker = z.object({
typ: z.enum(["VA", "BA", "VANW"]),
objekt: z.object({
typ: z.string(),
plz: z.string().min(4).max(5),
ort: z.string(),
strasse: z.string(),
baujahr: z.number(),
saniert: z.boolean(),
gebaeudeteil: z.enum(["Gesamtgebäude", "Wohnen"]),
einheiten: z.number(),
}),
heizquellen: z
.array(
z.object({
verbrauch: z.array(z.number()).max(3).min(3),
einheit: z.string(),
brennstoff: z.string(),
anteil_warmwasser: z.number(),
})
)
.max(2)
.min(1),
energieverbrauch_zeitraum: z.date(),
wohnflaeche: z.number(),
keller_beheizt: z.boolean(),
dachgeschoss: z.number(),
zusaetzliche_heizquelle: z.boolean(),
warmwasser_enthalten: z.boolean(),
lueftungskonzept: z.enum([
"Fensterlüftung",
"Schachtlüftung",
"Lüftungsanlage ohne Wärmerückgewinnung",
"Lüftungsanlage mit Wärmerückgewinnung",
]),
wird_gekuehlt: z.boolean(),
leerstand: z.number(),
images: z.array(z.string()),
versorgungssysteme: z.number(),
fenster_dach: z.number(),
energiequelle_2_nutzung: z.number(),
daemmung: z.number(),
/**
* Bedarfsausweis spezifische Eigenschaften
*/
anzahl_vollgeschosse: z.number(),
geschosshoehe: z.number(),
anzahl_gauben: z.number(),
breite_gauben: z.number(),
masse_a: z.number(),
masse_b: z.number(),
masse_c: z.number(),
masse_d: z.number(),
masse_e: z.number(),
masse_f: z.number(),
fensterflaeche_so_sw: z.number(),
fensterflaeche_nw_no: z.number(),
aussenwandflaeche_unbeheizt: z.number(),
dachflaeche: z.number(),
dach_u_wert: z.number(),
deckenflaeche: z.number(),
decke_u_wert: z.number(),
aussenwand_flaeche: z.number(),
aussenwand_u_wert: z.number(),
fussboden_flaeche: z.number(),
fussboden_u_wert: z.number(),
volumen: z.number(),
dicht: z.boolean(),
fenster_flaeche_1: z.number(),
fenster_art_1: z.number(),
fenster_flaeche_2: z.number(),
fenster_art_2: z.number(),
dachfenster_flaeche: z.number(),
dachfenster_art: z.number(),
haustuer_flaeche: z.number(),
haustuer_art: z.number(),
dach_bauart: z.string(),
dach_daemmung: z.number(),
decke_bauart: z.string(),
decke_daemmung: z.number(),
aussenwand_bauart: z.string(),
aussenwand_daemmung: z.number(),
boden_bauart: z.string(),
boden_daemmung: z.number(),
warmwasser_verteilung: z.string(),
warmwasser_speicherung: z.string(),
warmwasser_erzeugung: z.string(),
heizung_zentral: z.boolean(),
heizung_verteilung: z.string(),
heizung_speicherung: z.string(),
waerme_erzeugung_heizung: z.string(),
anteil_zusatzheizung: z.number(),
kollektor_flaeche: z.number(),
// VANW
vanw_stromverbrauch_enthalten: z.number(),
vanw_stromverbrauch_sonstige: z.string(),
vanw_strom_1: z.number(),
vanw_strom_2: z.number(),
vanw_strom_3: z.number(),
erledigt: z.boolean(),
anrede: z.string(),
name: z.string(),
vorname: z.string(),
email: z.string(),
telefonnummer: z.string(),
});
/**
* Erstellt einen Verbrauchsausweis anhand der gegebenen Daten und trägt ihn in die Datenbank ein.
* @param param0
* @returns
*/
export const post: APIRoute = async ({ request }) => {
const body = await request.json();
const result = AusweisUploadChecker.safeParse(body);
if (!result.success) {
return error(result.error.issues);
}
return success({});
};

View File

@@ -1,149 +0,0 @@
import { prisma } from "@ibcornelsen/database";
import type { APIRoute } from "astro";
import { ActionFailedError, MissingEntityError, error, success } from "src/lib/APIResponse";
import { Ausweis } from "src/lib/Ausweis/Ausweis";
import { Gebaeude } from "src/lib/Gebaeude";
import { z } from "zod";
const AusweisUploadChecker = z.object({
ausweis: z.object({
ausweisart: z.enum(["VA", "BA", "VANW"]),
ausstellgrund: z.enum([
"Vermietung",
"Neubau",
"Verkauf",
"Modernisierung",
"Sonstiges",
]),
}),
gebaeude: z.object({
typ: z.string(),
plz: z.string(),
ort: z.string(),
strasse: z.string(),
gebaeudeteil: z.string(),
saniert: z.boolean(),
baujahr: z.number(),
einheiten: z.number(),
wohnflaeche: z.number(),
keller_beheizt: z.boolean(),
dachgeschoss_beheizt: z.number(),
lueftungskonzept: z.enum([
"Fensterlüftung",
"Schachtlüftung",
"Lüftungsanlage ohne Wärmerückgewinnung",
"Lüftungsanlage mit Wärmerückgewinnung",
]),
wird_gekuehlt: z.boolean(),
leerstand: z.number(),
versorgungssysteme: z.number(),
fenster_dach: z.number(),
energiequelle_2_nutzung: z.number(),
daemmung: z.number(),
}),
kennwerte: z.object({
zeitraum: z.string(),
verbrauch_1: z.number(),
verbrauch_2: z.number(),
verbrauch_3: z.number(),
verbrauch_4: z.number(),
verbrauch_5: z.number(),
verbrauch_6: z.number(),
einheit_1: z.string(),
einheit_2: z.string(),
energietraeger_1: z.string(),
energietraeger_2: z.string(),
anteil_warmwasser_1: z.number(),
anteil_warmwasser_2: z.number(),
}),
gebaeude_uid: z.string().optional(),
kennwerte_uid: z.string().optional(),
ausweis_uid: z.string().optional(),
});
const AusweisDownloadChecker = z.object({
uid: z.string()
})
/**
* Erstellt einen Verbrauchsausweis anhand der gegebenen Daten und trägt ihn in die Datenbank ein.
* @param param0
* @returns
*/
export const post: APIRoute = async ({ request }) => {
const body: z.infer<typeof AusweisUploadChecker> = await request.json();
const validation = AusweisUploadChecker.safeParse(body);
if (!validation.success) {
return error(validation.error.issues);
}
let gebaeude, ausweis;
if (body.gebaeude_uid) {
gebaeude = await prisma.gebaeudeStammdaten.update({
where: {
uid: body.gebaeude_uid,
},
data: body.gebaeude,
})
} else {
gebaeude = await prisma.gebaeudeStammdaten.create({
data: body.gebaeude,
})
}
if (!gebaeude) {
return ActionFailedError();
}
if (body.ausweis_uid) {
ausweis = await prisma.verbrauchsausweisWohnen.update({
where: {
uid: body.ausweis_uid,
},
data: body.ausweis,
})
} else {
ausweis = await prisma.verbrauchsausweisWohnen.create({
data: body.ausweis,
})
}
if (!ausweis) {
return ActionFailedError();
}
return success({
ausweis: ausweis,
gebaeude: gebaeude,
});
};
export const get: APIRoute = async ({ request }) => {
const body: z.infer<typeof AusweisDownloadChecker> = await request.json();
const validation = AusweisDownloadChecker.safeParse(body);
if (!validation.success) {
return error(validation.error.issues);
}
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
where: {
uid: body.uid,
},
include: {
gebaeude_stammdaten: true,
}
})
if (!ausweis) {
return MissingEntityError("gebäude");
}
return success(ausweis);
};

View File

@@ -1,39 +0,0 @@
import type { APIRoute } from "astro";
import {
MissingEntityError,
error,
success,
} from "src/lib/APIResponse";
import { prisma } from "@ibcornelsen/database";
export const get: APIRoute = async ({ url }) => {
const body = url.searchParams
const uid = body.get("uid")
if (!body.has("uid") || !uid) {
return error(["Missing 'uid' in request body."])
}
const gebaeude = await prisma.gebaeudeStammdaten.findUnique({
where: {
uid: uid
}
})
if (!gebaeude) {
return MissingEntityError("gebaeude")
}
const images = await prisma.gebaeudeBilder.findMany({
where: {
gebaeude_stammdaten_id: gebaeude.id
},
select: {
uid: true,
kategorie: true
}
})
return success(images);
};

View File

@@ -1,63 +0,0 @@
import type { APIRoute } from "astro";
import moment from "moment";
import { ActionFailedError, MissingPropertyError, error, success } from "src/lib/APIResponse";
import { getClimateFactor } from "src/lib/Klimafaktoren/getClimateFactor";
export const get: APIRoute = async function({ url }) {
const body = url.searchParams;
let zip = body.get("zip");
if (!body.get("date")) {
return MissingPropertyError(["date"]);
}
let accuracy = body.get("accuracy") || "months";
if (accuracy !== "months" && accuracy !== "years") {
return error(["Accuracy must be either 'months' or 'years'."])
}
if (!zip) {
return error(["Invalid ZIP Code, must be 4 or 5 characters long."])
}
let start = moment(body.get("date"));
let end = moment(body.get("date")).add("2", "years");
if (!start.isValid()) {
return error(["Invalid start date given."]);
}
if (!end.isValid()) {
return error(["Invalid end date given."]);
}
if (start.isSameOrAfter(end)) {
return error(["Start date not before end date."])
}
const intervals = [];
let currentDate = start.clone();
while (currentDate.isSameOrBefore(end)) {
let copy = currentDate.clone();
intervals.push(copy);
currentDate.add(1, accuracy);
}
const klimafaktoren = await getClimateFactor(intervals, zip);
if (!klimafaktoren) {
return ActionFailedError();
}
if (klimafaktoren.length !== intervals.length) {
return error(["Not all dates could be found."]);
}
return success(klimafaktoren.map(klimafaktor => ({
month: klimafaktor.month,
year: klimafaktor.year,
klimafaktor: klimafaktor.klimafaktor,
})));
}

View File

@@ -0,0 +1,31 @@
// NOTE: Öffentliche API benötigt OpenApiMeta. Das Package bräuchte momentan noch einen extra Server, deshalb nehmen wir es momentan noch nicht mit rein.
//import { OpenApiMeta } from "trpc-openapi";
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
import { APIRoute } from "astro";
import { t } from "./context";
import { v1Router } from "./procedures/v1";
export const AppRouter = t.router({
v1: v1Router,
})
export const all: APIRoute = ({ request }) => {
console.log(request);
return fetchRequestHandler({
req: request,
endpoint: "/api/trpc",
router: AppRouter,
createContext: async ({ req }) => {
return { uid: req.headers.get("X-Session") ?? undefined };
},
});
};
export function tRPCCaller(request: Request) {
const { uid } = { uid: request.headers.get("Authorization") || "" };
const createCaller = t.createCallerFactory(AppRouter);
return createCaller({ uid });
}
export type AppRouter = typeof AppRouter;

View File

@@ -0,0 +1,34 @@
import { TRPCError, initTRPC } from "@trpc/server";
import { ZodError } from "zod";
import { OpenApiMeta } from "trpc-openapi";
type Context = { uid?: string };
export const t = initTRPC.context<Context>().meta<OpenApiMeta>().create({
errorFormatter(opts) {
const { shape, error } = opts;
return {
success: false,
...shape,
data: {
zodError:
error.code === 'BAD_REQUEST' && error.cause instanceof ZodError
? error.cause.flatten()
: null,
},
};
}
});
export const publicProcedure = t.procedure
export const privateProcedure = t.procedure.use((opts) => {
if (!opts.ctx.uid) {
throw new TRPCError({
code: 'FORBIDDEN',
message: "Diese Ressource benötigt eine UID, welche im 'Authorization' Header gegeben sein muss.",
});
}
return opts.next();
});

View File

@@ -0,0 +1,42 @@
import { z } from "zod";
import { t } from "../../context";
import { tRPCKlimafaktorenProcedure } from "./klimafaktoren";
import { VerbrauchsausweisWohnen2016Erstellen } from "./verbrauchsausweis-wohnen/2016/erstellen";
const router = t.router;
export const v1Router = router({
verbrauchsausweisWohnen: router({
2016: router({
erstellen: VerbrauchsausweisWohnen2016Erstellen
}),
2023: router({
})
}),
verbrauchsausweisGewerbe: router({
2016: router({
}),
2023: router({
})
}),
bedarfsausweisWohen: router({
2016: router({
}),
2023: router({
})
}),
klimafaktoren: tRPCKlimafaktorenProcedure,
test: t.procedure.meta({
openapi: {
method: "GET",
path: "/v1/test",
}
}).input(z.void({})).output(z.string()).query(async (opts) => {
return "Hello World!";
})
})

View File

@@ -0,0 +1,78 @@
import { z } from "zod";
import { t } from "../../context";
import moment from "moment";
import { TRPCError } from "@trpc/server";
import { prisma } from "@ibcornelsen/database";
export const tRPCKlimafaktorenProcedure = t.procedure
.input(
z.object({
plz: z.string().min(4).max(5),
startdatum: z.coerce.date(),
enddatum: z.coerce.date(),
genauigkeit: z.enum(["months", "years"]),
})
)
.output(
z.array(
z.object({
month: z.number(),
year: z.number(),
klimafaktor: z.number(),
})
)
)
.query(async (opts) => {
const start = moment(opts.input.startdatum);
const end = moment(opts.input.enddatum);
if (start.isSameOrAfter(end)) {
throw new TRPCError({
code: "PRECONDITION_FAILED",
message: "Das Startdatum kann nicht vor dem Enddatum liegen.",
});
}
const intervals = [];
let currentDate = start.clone();
while (currentDate.isSameOrBefore(end)) {
let copy = currentDate.clone();
intervals.push(copy);
currentDate.add(1, opts.input.genauigkeit);
}
let klimafaktoren = await prisma.klimafaktoren.findMany({
where: {
plz: opts.input.plz,
month: intervals[0].month(),
OR: intervals.map((date) => {
return {
year: date.year(),
};
}),
},
});
if (!klimafaktoren) {
throw new TRPCError({
code: "NOT_FOUND",
message:
"Die Klimafaktoren konnten nicht geladen werden. Das kann daran liegen, dass sie für diesen Zeitraum oder Ort nicht verfügbar sind.",
});
}
if (klimafaktoren.length !== intervals.length) {
throw new TRPCError({
code: "NOT_FOUND",
message:
"Für diesen Zeitraum konnten nicht alle Klimafaktoren gefunden werden.",
});
}
return klimafaktoren.map((klimafaktor) => ({
month: klimafaktor.month,
year: klimafaktor.year,
klimafaktor: klimafaktor.klimafaktor,
}));
});

View File

@@ -0,0 +1,127 @@
import { ZodSchema, z } from "zod";
import { publicProcedure } from "../../../../context";
import { GebaeudeStammdaten, VerbrauchsausweisWohnen, prisma } from "@ibcornelsen/database";
export const VerbrauchsausweisWohnen2016Erstellen = publicProcedure
.meta({
openapi: {
method: "POST",
path: "/v1/verbrauchsausweis-wohnen/2016/erstellen",
contentTypes: ["application/json"],
description: "Erstellt einen neuen Verbrauchsausweis für Wohngebäude nach dem Schema der EnEV von 2016.",
tags: ["Verbrauchsausweis Wohnen"],
}
})
.input(z.object({
baujahr_heizung: z.array(z.number()).optional(),
zusaetzliche_heizquelle: z.boolean().optional(),
brennstoff_1: z.string().max(50).optional(),
einheit_1: z.string().max(10).optional(),
brennstoff_2: z.string().max(50).optional(),
einheit_2: z.string().max(10).optional(),
startdatum: z.date().optional(),
enddatum: z.date().optional(),
verbrauch_1: z.number().optional(),
verbrauch_2: z.number().optional(),
verbrauch_3: z.number().optional(),
verbrauch_4: z.number().optional(),
verbrauch_5: z.number().optional(),
verbrauch_6: z.number().optional(),
warmwasser_enthalten: z.boolean().optional(),
warmwasser_anteil_bekannt: z.boolean().optional(),
wird_gekuehlt: z.boolean().optional(),
keller_beheizt: z.boolean().optional(),
alternative_heizung: z.boolean().optional(),
alternative_warmwasser: z.boolean().optional(),
alternative_lueftung: z.boolean().optional(),
alternative_kuehlung: z.boolean().optional(),
anteil_warmwasser_1: z.number().optional(),
anteil_warmwasser_2: z.number().optional(),
gebaeude_stammdaten: z.string().uuid().or(z.object({
gebaeudetyp: z.string().max(255).optional(), // Adjust max length as needed
gebaeudeteil: z.string().max(255).optional(), // Adjust max length as needed
baujahr_gebaeude: z.array(z.number()).optional(),
baujahr_heizung: z.array(z.number()).optional(),
baujahr_klima: z.array(z.number()).optional(),
einheiten: z.number().optional(),
flaeche: z.number().optional(),
saniert: z.boolean().optional(),
keller: z.number().optional(),
dachgeschoss: z.number().optional(),
lueftung: z.string().max(50).optional(), // Adjust max length as needed
kuehlung: z.string().max(50).optional(), // Adjust max length as needed
leerstand: z.number().optional(),
plz: z.string().max(5).optional(), // Adjust max length as needed
ort: z.string().max(50).optional(), // Adjust max length as needed
adresse: z.string().max(100).optional(), // Adjust max length as needed
zentralheizung: z.boolean().optional(),
solarsystem_warmwasser: z.boolean().optional(),
warmwasser_rohre_gedaemmt: z.boolean().optional(),
niedertemperatur_kessel: z.boolean().optional(),
brennwert_kessel: z.boolean().optional(),
heizungsrohre_gedaemmt: z.boolean().optional(),
standard_kessel: z.boolean().optional(),
waermepumpe: z.boolean().optional(),
raum_temperatur_regler: z.boolean().optional(),
photovoltaik: z.boolean().optional(),
durchlauf_erhitzer: z.boolean().optional(),
einzelofen: z.boolean().optional(),
zirkulation: z.boolean().optional(),
einfach_verglasung: z.boolean().optional(),
dreifach_verglasung: z.boolean().optional(),
fenster_teilweise_undicht: z.boolean().optional(),
doppel_verglasung: z.boolean().optional(),
fenster_dicht: z.boolean().optional(),
rolllaeden_kaesten_gedaemmt: z.boolean().optional(),
isolier_verglasung: z.boolean().optional(),
tueren_undicht: z.boolean().optional(),
tueren_dicht: z.boolean().optional(),
dachgeschoss_gedaemmt: z.boolean().optional(),
keller_decke_gedaemmt: z.boolean().optional(),
keller_wand_gedaemmt: z.boolean().optional(),
aussenwand_gedaemmt: z.boolean().optional(),
oberste_geschossdecke_gedaemmt: z.boolean().optional(),
aussenwand_min_12cm_gedaemmt: z.boolean().optional(),
dachgeschoss_min_12cm_gedaemmt: z.boolean().optional(),
oberste_geschossdecke_min_12cm_gedaemmt: z.boolean().optional(),
} satisfies ZodSchema<GebaeudeStammdaten>))
} satisfies ZodSchema<VerbrauchsausweisWohnen>))
.output(
z.object({
uid: z.string().uuid(),
})
)
.mutation(async (opts) => {
// Es kann sein, dass ein Gebäude bereits existiert. In diesem Fall wird es nicht neu erstellt, sondern nur der Verbrauchsausweis.
// Das können wir ganz einfach überprüfen, indem wir schauen, ob eine UUID für das Gebäude übergeben wurde.
if (typeof opts.input.gebaeude_stammdaten === "string") {
// Gebäude existiert bereits
const gebaeude = await prisma.gebaeudeStammdaten.findUnique({
where: {
uid: opts.input.gebaeude_stammdaten
}
});
if (!gebaeude) {
throw new Error("Das Gebäude mit der übergebenen UUID existiert nicht.");
}
const verbrauchsausweis = await prisma.verbrauchsausweisWohnen.create({
data: {
...opts.input,
gebaeude_stammdaten: {
connect: {
uid: opts.input.gebaeude_stammdaten
}
}
}
});
return { uid: verbrauchsausweis.uid };
}
return { uid: "" };
});

View File

@@ -0,0 +1,41 @@
import type { APIRoute } from "astro";
import { MissingEntityError, error } from "src/lib/APIResponse";
import { prisma } from "@ibcornelsen/database";
import { xmlVerbrauchsausweisWohnen_2016 } from "#lib/XML/VerbrauchsausweisWohnen/xmlVerbrauchsausweisWohnen_2016";
import uuid from "uuid";
export const get: APIRoute = async ({ url }) => {
const body = url.searchParams;
const uid = body.get("uid");
if (!body.has("uid") || !uid) {
return error(["Missing 'uid' in request body."]);
}
if (!uuid.validate(uid)) {
return error(["'uid' in request body must follow the UUID v4 format."]);
}
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
where: {
uid,
},
include: {
gebaeude_stammdaten: true,
},
});
if (!ausweis) {
return MissingEntityError(uid);
}
const xml = await xmlVerbrauchsausweisWohnen_2016(ausweis);
const response = new Response(xml, {
headers: {
"Content-Type": "application/xml",
},
});
return response;
};

View File

@@ -1,7 +1,7 @@
import type { APIRoute } from "astro";
import { success, MissingPropertyError, MissingEntityError, ActionFailedError, InvalidDataError, error } from "../../lib/APIResponse";
import { User } from "../../lib/User";
import { UserRegisterValidator, UserType, UserTypeValidator } from "../../lib/User/type";
import { UserRegisterValidator, UserType } from "../../lib/User/type";
import { z } from "zod";
/**
@@ -36,7 +36,7 @@ export const put: APIRoute = async ({ request }) => {
const user = await User.fromEmail(body.email);
if (user) {
return error(["Email address is already being used."]);
return error(["Diese Email Adresse wird bereits verwendet."]);
}
const result = await User.create(body as UserType);

View File

@@ -1,7 +1,7 @@
import type { APIRoute } from "astro";
import { success, MissingPropertyError, MissingEntityError, InvalidDataError, error } from "../../lib/APIResponse";
import { ZIPInformation } from "src/lib/ZIPInformation";
import { success, MissingPropertyError, MissingEntityError, error } from "../../lib/APIResponse";
import { validateAuthorizationHeader } from "src/lib/server/Authorization";
import { prisma } from "@ibcornelsen/database";
/**
* Ruft einen Nutzer anhand seiner uid aus der Datenbank ab.
@@ -18,11 +18,23 @@ export const get: APIRoute = async ({ request }) => {
let result;
if (body.zip) {
result = await ZIPInformation.fromZipCode(body.zip)
result = await prisma.postleitzahlen.findUnique({
where: {
plz: body.zip,
},
})
} else if (body.city) {
result = await ZIPInformation.fromCity(body.city)
result = await prisma.postleitzahlen.findMany({
where: {
stadt: body.city,
},
})
} else if (body.state) {
result = await ZIPInformation.fromState(body.state)
result = await prisma.postleitzahlen.findMany({
where: {
bundesland: body.state,
},
})
} else {
return MissingPropertyError(["Either 'state', 'city' or 'zip' have to exist in request body."])
}

View File

@@ -1,8 +0,0 @@
---
import { changeLanguage } from "i18next";
changeLanguage("de");
console.log(Object.fromEntries(new URLSearchParams(await Astro.request.text())));
return Astro.redirect("/kundendaten");
---

View File

@@ -1,7 +1,7 @@
---
import { changeLanguage } from "i18next";
import AusweisLayout from "#layouts/AusweisLayout.astro";
import Verbrauchsausweis from "#modules/Ausweise/Verbrauchsausweis.svelte";
import VerbrauchsausweisWohnenModule from "#modules/Ausweise/VerbrauchsausweisWohnenModule.svelte";
changeLanguage("de");
@@ -9,5 +9,5 @@ const uid = Astro.cookies.get("ausweis_uid").value;
---
<AusweisLayout title="Verbrauchsausweis erstellen">
<Verbrauchsausweis client:load uid={uid} />
<VerbrauchsausweisWohnenModule client:load uid={uid} />
</AusweisLayout>

16
src/trpc.ts Normal file
View File

@@ -0,0 +1,16 @@
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import cookies from 'js-cookie';
import type { AppRouter } from 'src/pages/api/trpc/[trpc]';
export default createTRPCProxyClient<AppRouter>({
links: [
httpBatchLink({
url: 'http://localhost:3000/api/trpc',
headers() {
return {
'Authorization': `Bearer ${cookies.get('uid')}`,
};
},
}),
],
});

10
test.ts Normal file
View File

@@ -0,0 +1,10 @@
import { AppRouter } from "src/pages/api/trpc/[trpc]"
import { createOpenApiExpressMiddleware } from "trpc-openapi"
import express from 'express';
const app = express();
app.use(createOpenApiExpressMiddleware({ router: AppRouter }));
app.listen(5555);
console.log("Server listening on port 80");