tRPC Hinzugefügt
This commit is contained in:
@@ -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({});
|
||||
};
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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,
|
||||
})));
|
||||
}
|
||||
31
src/pages/api/trpc/[trpc].ts
Normal file
31
src/pages/api/trpc/[trpc].ts
Normal 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;
|
||||
34
src/pages/api/trpc/context.ts
Normal file
34
src/pages/api/trpc/context.ts
Normal 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();
|
||||
});
|
||||
42
src/pages/api/trpc/procedures/v1/index.ts
Normal file
42
src/pages/api/trpc/procedures/v1/index.ts
Normal 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!";
|
||||
})
|
||||
})
|
||||
78
src/pages/api/trpc/procedures/v1/klimafaktoren.ts
Normal file
78
src/pages/api/trpc/procedures/v1/klimafaktoren.ts
Normal 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,
|
||||
}));
|
||||
});
|
||||
@@ -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: "" };
|
||||
});
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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);
|
||||
|
||||
@@ -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."])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user