Ausweis und weitere Änderungen
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
---
|
||||
import AusweisLayout from "#layouts/AusweisLayoutDaten.astro";
|
||||
import { AufnahmeClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import { createCaller } from "../../../astro-typesafe-api-caller.js";
|
||||
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
||||
import { validateAccessTokenServer } from "#server/lib/validateAccessToken.js";
|
||||
import GEGNachweisVerbrauchsausweisWohnenModule from "#modules/angebot-anfragen/GEGNachweisVerbrauchsausweisWohnenModule.svelte";
|
||||
|
||||
const uid = Astro.url.searchParams.get("uid");
|
||||
let ausweis: VerbrauchsausweisWohnenClient = {} as VerbrauchsausweisWohnenClient;
|
||||
let aufnahme: AufnahmeClient = {} as AufnahmeClient;
|
||||
let objekt: ObjektClient = {} as ObjektClient;
|
||||
let bilder: UploadedGebaeudeBild[] = []
|
||||
|
||||
const valid = validateAccessTokenServer(Astro);
|
||||
|
||||
const caller = createCaller(Astro);
|
||||
|
||||
if (uid) {
|
||||
if (!valid) {
|
||||
return Astro.redirect(
|
||||
`/auth/login?redirect=${Astro.url.toString()}`
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
ausweis = await caller["verbrauchsausweis-wohnen"]._uid.GET.fetch(null, {
|
||||
headers: {
|
||||
authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||
},
|
||||
params: {
|
||||
uid
|
||||
}
|
||||
});
|
||||
|
||||
aufnahme = await caller.aufnahme._uid.GET.fetch(null, {
|
||||
headers: {
|
||||
authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||
},
|
||||
params: {
|
||||
uid: ausweis.uid_aufnahme
|
||||
}
|
||||
})
|
||||
|
||||
objekt = await caller.objekt._uid.GET.fetch(null, {
|
||||
headers: {
|
||||
authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||
},
|
||||
params: {
|
||||
uid: ausweis.uid_objekt
|
||||
}
|
||||
})
|
||||
|
||||
bilder = await caller.objekt._uid.bilder.GET.fetch(null, {
|
||||
headers: {
|
||||
authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||
},
|
||||
params: {
|
||||
uid: ausweis.uid_objekt
|
||||
}
|
||||
})
|
||||
|
||||
if (!ausweis) {
|
||||
// Der Ausweis scheint nicht zu existieren.
|
||||
// Wir leiten auf die generische Ausweisseite ohne UID weiter.
|
||||
return Astro.redirect(
|
||||
"/energieausweis-erstellen/verbrauchsausweis-wohnen"
|
||||
);
|
||||
}
|
||||
} catch(e) {
|
||||
return Astro.redirect(
|
||||
"/energieausweis-erstellen/verbrauchsausweis-wohnen"
|
||||
);
|
||||
}
|
||||
}
|
||||
---
|
||||
|
||||
<AusweisLayout title="Verbrauchsausweis erstellen">
|
||||
<GEGNachweisVerbrauchsausweisWohnenModule client:only {ausweis} {objekt} {aufnahme} {bilder} />
|
||||
</AusweisLayout>
|
||||
|
||||
209
src/pages/api/admin/ausstellen.ts
Normal file
209
src/pages/api/admin/ausstellen.ts
Normal file
@@ -0,0 +1,209 @@
|
||||
import { getAusweisartFromUUID } from "#components/Ausweis/types.js";
|
||||
import { adminMiddleware } from "#lib/middleware/authorization.js";
|
||||
import { pdfDatenblattVerbrauchsausweisWohnen } from "#lib/pdf/pdfDatenblattVerbrauchsausweisWohnen.js";
|
||||
import { pdfVerbrauchsausweisWohnen } from "#lib/pdf/pdfVerbrauchsausweisWohnen.js";
|
||||
import { Enums, prisma } from "@ibcornelsen/database/server";
|
||||
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||
import { z } from "astro:content";
|
||||
import { fileURLToPath } from "url";
|
||||
import * as fs from "fs";
|
||||
import { transport } from "#lib/mail.js";
|
||||
import { BASE_URI } from "#lib/constants.js";
|
||||
|
||||
export const GET = defineApiRoute({
|
||||
input: z.object({
|
||||
uid: z.string(),
|
||||
}),
|
||||
output: z.void(),
|
||||
middleware: adminMiddleware,
|
||||
async fetch({ uid }, context, user) {
|
||||
const ausweisart = getAusweisartFromUUID(uid);
|
||||
|
||||
if (ausweisart === "VerbrauchsausweisWohnen") {
|
||||
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
|
||||
where: {
|
||||
uid,
|
||||
},
|
||||
include: {
|
||||
aufnahme: {
|
||||
include: {
|
||||
objekt: {
|
||||
include: {
|
||||
gebaeude_bilder: true,
|
||||
benutzer: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!ausweis) {
|
||||
throw new APIError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Ausweis existiert nicht.",
|
||||
});
|
||||
}
|
||||
|
||||
const rechnung = await prisma.rechnung.findFirst({
|
||||
where: {
|
||||
aufnahme_id: ausweis.aufnahme.id,
|
||||
},
|
||||
orderBy: {
|
||||
erstellt_am: "desc",
|
||||
},
|
||||
});
|
||||
|
||||
if (!rechnung) {
|
||||
throw new APIError({
|
||||
code: "BAD_REQUEST",
|
||||
message:
|
||||
"Die Rechnung wurde noch nicht erstellt, wir können nicht fortfahren.",
|
||||
});
|
||||
}
|
||||
|
||||
// TODO
|
||||
// SECTION: Rechnung erstellen (LexOffice)
|
||||
// Wir wollen die Rechnung an lex office versenden, und uns die ID von da holen.
|
||||
// Falls die Rechnung bereits existiert ist das nicht nötig.
|
||||
// if (!$rechnung->lex_office_id) {
|
||||
// [$lex_office_id, $renr] = createInvoice($ausweis, $rechnung);
|
||||
// sleep(1); // TODO: Nach der Umstellung von LexOffice auf etwas anderes MUSS das hier unbedingt entfernt werden!
|
||||
|
||||
// if (!$lex_office_id || !$renr) {
|
||||
// die("Bei der Erstellung der Rechnung ist etwas schiefgelaufen - Möglicherweise ist etwas mit LexOffice?");
|
||||
// }
|
||||
|
||||
// $rechnung->lex_office_id = $lex_office_id;
|
||||
// $rechnung->rechnungsnummer = $renr;
|
||||
// $rechnung->save();
|
||||
// }
|
||||
|
||||
// TODO
|
||||
// if ($ausweis->erledigt != 2) {$ausweis->erstellungsdatum = date("Y-m-d H:i:s");}
|
||||
// $ausweis->erledigt = 2;
|
||||
// $ausweis->save();
|
||||
|
||||
const pdfAusweis = await pdfVerbrauchsausweisWohnen(
|
||||
ausweis,
|
||||
ausweis.aufnahme,
|
||||
ausweis.aufnahme.objekt,
|
||||
ausweis.aufnahme.objekt.gebaeude_bilder,
|
||||
ausweis.aufnahme.objekt.benutzer
|
||||
);
|
||||
const pdfDatenblatt = await pdfDatenblattVerbrauchsausweisWohnen(
|
||||
ausweis,
|
||||
ausweis.aufnahme,
|
||||
ausweis.aufnahme.objekt,
|
||||
ausweis.aufnahme.objekt.benutzer
|
||||
);
|
||||
|
||||
const pdfAusweisPath = fileURLToPath(
|
||||
new URL(
|
||||
`../../../../persistent/generated/Ausweis-${ausweis.uid}.pdf`,
|
||||
import.meta.url
|
||||
)
|
||||
);
|
||||
const pdfDatenblattPath = fileURLToPath(
|
||||
new URL(
|
||||
`../../../../persistent/generated/Datenblatt-${ausweis.uid}.pdf`,
|
||||
import.meta.url
|
||||
)
|
||||
);
|
||||
|
||||
fs.writeFileSync(pdfAusweisPath, pdfAusweis);
|
||||
fs.writeFileSync(pdfDatenblattPath, pdfDatenblatt);
|
||||
|
||||
let text: string;
|
||||
|
||||
if (rechnung.status === Enums.Rechnungsstatus.paid) {
|
||||
text = `
|
||||
<p>Sehr geehrte*r ${user.vorname} ${user.name},</p>
|
||||
|
||||
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. Den Rechnungsbetrag haben Sie bereits bezahlt. Vielen Dank.</p>
|
||||
|
||||
<p>
|
||||
Mit freundlichen Grüßen,
|
||||
<br>
|
||||
Dipl.-Ing. Jens Cornelsen
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<strong>IB Cornelsen</strong>
|
||||
<br>
|
||||
Katendeich 5A
|
||||
<br>
|
||||
21035 Hamburg
|
||||
<br>
|
||||
www.online-energieausweis.org
|
||||
<br>
|
||||
<br>
|
||||
|
||||
fon 040 · 209339850
|
||||
<br>
|
||||
fax 040 · 209339859
|
||||
</p>`;
|
||||
} else {
|
||||
text = `
|
||||
<p>Sehr geehrte*r ${user.vorname} ${user.name},</p>
|
||||
|
||||
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. Nachfolgend finden Sie unsere Bankverbindung. Bitte geben Sie als Verwendungszweck die Rechnungsnummer an (siehe unten). Vielen Dank.</p>
|
||||
|
||||
<br>
|
||||
<table>
|
||||
<tr><td>Kreditinstitut</td><td>:</td><td>\t Commerzbank AG</td>
|
||||
<tr><td>Empfänger</td><td>:</td><td>\t IB Cornelsen</td>
|
||||
<tr><td>IBAN</td><td>:<td>\t DE81 2004 0000 0348 6008 00</td>
|
||||
<tr><td>BIC</td><td>:</td><td>\t COBADEFFXXX</td>
|
||||
<tr><td>Betrag</td><td>:</td><td>\t <b>${rechnung.betrag}€</b></td>
|
||||
<tr><td>Verwendungszweck</td><td>:</td><td>\t <b>${rechnung.uid}</b></td>
|
||||
</table>
|
||||
<br>
|
||||
|
||||
<p>
|
||||
Alternativ können Sie auch direkt online zahlen indem Sie auf den entsprechenden Link klicken:
|
||||
</p>
|
||||
<br>
|
||||
|
||||
<table>
|
||||
<tr><td>Per Einzuglastschrift zahlen</td> <td>:</td> <td><a href='${BASE_URI}/energieausweis-erstellen/kaufabschluss-fortsetzen?uid=${ausweis.uid}&p=SEPA'>jetzt per ELV bezahlen</a></td></tr>
|
||||
<tr><td>Per Sofortüberweisung zahlen</td> <td>:</td> <td><a href='${BASE_URI}/energieausweis-erstellen/kaufabschluss-fortsetzen?uid=${ausweis.uid}&p=Sofort'>jetzt per Sofortüberweisung bezahlen</a></td></tr>
|
||||
<tr><td>Über PayPal zahlen</td> <td>:</td> <td><a href='${BASE_URI}/energieausweis-erstellen/kaufabschluss-fortsetzen?uid=${ausweis.uid}&p=PayPal'>jetzt per Paypal bezahlen</a></td></tr>
|
||||
<tr><td>Per Giropay zahlen</td> <td>:</td> <td><a href='${BASE_URI}/energieausweis-erstellen/kaufabschluss-fortsetzen?uid=${ausweis.uid}&p=Giropay'>jetzt per Giropay bezahlen</a></td></tr>
|
||||
<tr><td>Per Visa oder MasterCard zahlen</td> <td>:</td> <td><a href='${BASE_URI}/energieausweis-erstellen/kaufabschluss-fortsetzen?uid=${ausweis.uid}&p=Kreditkarte'>jetzt per Kreditkarte bezahlen</a></td></tr>
|
||||
</table>
|
||||
<br>
|
||||
|
||||
<p>
|
||||
Mit freundlichen Grüßen,
|
||||
<br>
|
||||
Dipl.-Ing. Jens Cornelsen
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<strong>IB Cornelsen</strong>
|
||||
<br>
|
||||
Katendeich 5A
|
||||
<br>
|
||||
21035 Hamburg
|
||||
<br>
|
||||
www.online-energieausweis.org
|
||||
<br>
|
||||
<br>
|
||||
|
||||
fon 040 · 209339850
|
||||
<br>
|
||||
fax 040 · 209339859
|
||||
</p>`;
|
||||
}
|
||||
|
||||
await transport.sendMail({
|
||||
from: `"IBCornelsen" <info@online-energieausweis.org>`,
|
||||
to: user.email,
|
||||
subject: `Ihr Originalausweis vom Ingenieurbüro Cornelsen (ID: ${ausweis.uid})`,
|
||||
text,
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -5,6 +5,7 @@ import { prisma } from "@ibcornelsen/database/server";
|
||||
import { decodeToken, encodeToken } from "#lib/auth/token.js";
|
||||
import { TokenType } from "#lib/auth/types.js";
|
||||
import { hashPassword } from "#lib/password.js";
|
||||
import { transport } from "#lib/mail.js";
|
||||
|
||||
export const GET = defineApiRoute({
|
||||
input: z.object({
|
||||
@@ -33,16 +34,6 @@ export const GET = defineApiRoute({
|
||||
uid: user.uid
|
||||
})
|
||||
|
||||
const transport = nodemailer.createTransport({
|
||||
host: "smtp.ionos.de",
|
||||
port: 465,
|
||||
secure: true,
|
||||
auth: {
|
||||
user: "info@online-energieausweis.org",
|
||||
pass: "Katendeich5a2024!"
|
||||
}
|
||||
})
|
||||
|
||||
const info = await transport.sendMail({
|
||||
from: `"IBCornelsen" <info@online-energieausweis.org>`,
|
||||
to: input.email,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { BedarfsausweisWohnenClient, OptionalNullable, UUidWithPrefix, ZodOverlap } from "#components/Ausweis/types.js";
|
||||
import { BedarfsausweisWohnenClient, OptionalNullable, UUidWithPrefix, VerbrauchsausweisWohnenClient, ZodOverlap } from "#components/Ausweis/types.js";
|
||||
import { exclude } from "#lib/exclude.js";
|
||||
import { authorizationHeaders, authorizationMiddleware } from "#lib/middleware/authorization.js";
|
||||
import { BedarfsausweisWohnenSchema, prisma } from "@ibcornelsen/database/server";
|
||||
import { BedarfsausweisWohnenSchema, prisma, VerbrauchsausweisWohnenSchema } from "@ibcornelsen/database/server";
|
||||
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||
import { z } from "zod";
|
||||
|
||||
export const PATCH = defineApiRoute({
|
||||
input: BedarfsausweisWohnenSchema.omit({
|
||||
input: VerbrauchsausweisWohnenSchema.omit({
|
||||
uid: true,
|
||||
id: true,
|
||||
benutzer_id: true,
|
||||
@@ -18,7 +18,7 @@ export const PATCH = defineApiRoute({
|
||||
},
|
||||
middleware: authorizationMiddleware,
|
||||
async fetch(input, ctx, user) {
|
||||
const objekt = await prisma.bedarfsausweisWohnen.findUnique({
|
||||
const objekt = await prisma.verbrauchsausweisWohnen.findUnique({
|
||||
where: {
|
||||
uid: ctx.params.uid,
|
||||
benutzer: {
|
||||
@@ -34,7 +34,7 @@ export const PATCH = defineApiRoute({
|
||||
})
|
||||
}
|
||||
|
||||
await prisma.bedarfsausweisWohnen.update({
|
||||
await prisma.verbrauchsausweisWohnen.update({
|
||||
where: {
|
||||
uid: ctx.params.uid
|
||||
},
|
||||
@@ -61,7 +61,7 @@ export const DELETE = defineApiRoute({
|
||||
|
||||
// Wir holen uns den Bedarfsausweis
|
||||
// Dieser MUSS mit dem Nutzer verknüpft sein.
|
||||
const ausweis = await prisma.bedarfsausweisWohnen.findUnique({
|
||||
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
|
||||
where: {
|
||||
uid,
|
||||
},
|
||||
@@ -155,7 +155,7 @@ export const GET = defineApiRoute({
|
||||
}
|
||||
}
|
||||
},
|
||||
output: ZodOverlap<OptionalNullable<BedarfsausweisWohnenClient>>(BedarfsausweisWohnenSchema.merge(z.object({
|
||||
output: ZodOverlap<OptionalNullable<VerbrauchsausweisWohnenClient>>(VerbrauchsausweisWohnenSchema.merge(z.object({
|
||||
uid_aufnahme: UUidWithPrefix,
|
||||
uid_objekt: UUidWithPrefix,
|
||||
uid_benutzer: UUidWithPrefix.optional()
|
||||
@@ -175,7 +175,7 @@ export const GET = defineApiRoute({
|
||||
})
|
||||
}
|
||||
|
||||
const ausweis = await prisma.bedarfsausweisWohnen.findUnique({
|
||||
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
|
||||
where: {
|
||||
uid,
|
||||
benutzer_id: user.id
|
||||
|
||||
217
src/pages/api/geg-nachweis-verbrauchsausweis-wohnen/[uid].ts
Normal file
217
src/pages/api/geg-nachweis-verbrauchsausweis-wohnen/[uid].ts
Normal file
@@ -0,0 +1,217 @@
|
||||
import { BedarfsausweisWohnenClient, OptionalNullable, UUidWithPrefix, ZodOverlap } from "#components/Ausweis/types.js";
|
||||
import { exclude } from "#lib/exclude.js";
|
||||
import { authorizationHeaders, authorizationMiddleware } from "#lib/middleware/authorization.js";
|
||||
import { BedarfsausweisWohnenSchema, prisma } from "@ibcornelsen/database/server";
|
||||
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||
import { z } from "zod";
|
||||
|
||||
export const PATCH = defineApiRoute({
|
||||
input: BedarfsausweisWohnenSchema.omit({
|
||||
uid: true,
|
||||
id: true,
|
||||
benutzer_id: true,
|
||||
aufnahme_id: true,
|
||||
}),
|
||||
output: z.void(),
|
||||
headers: {
|
||||
"Authorization": z.string()
|
||||
},
|
||||
middleware: authorizationMiddleware,
|
||||
async fetch(input, ctx, user) {
|
||||
const objekt = await prisma.bedarfsausweisWohnen.findUnique({
|
||||
where: {
|
||||
uid: ctx.params.uid,
|
||||
benutzer: {
|
||||
id: user.id
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (!objekt) {
|
||||
throw new APIError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Ausweis konnte nicht gefunden werden oder gehört einem anderen Benutzer."
|
||||
})
|
||||
}
|
||||
|
||||
await prisma.bedarfsausweisWohnen.update({
|
||||
where: {
|
||||
uid: ctx.params.uid
|
||||
},
|
||||
data: input
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
export const DELETE = defineApiRoute({
|
||||
meta: {
|
||||
description: "Storniert einen Ausweis"
|
||||
},
|
||||
headers: authorizationHeaders,
|
||||
middleware: authorizationMiddleware,
|
||||
async fetch(input, ctx, user) {
|
||||
const { uid } = ctx.params;
|
||||
|
||||
if (!UUidWithPrefix.safeParse(uid).success) {
|
||||
throw new APIError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "UID konnte nicht verifiziert werden."
|
||||
})
|
||||
}
|
||||
|
||||
// Wir holen uns den Bedarfsausweis
|
||||
// Dieser MUSS mit dem Nutzer verknüpft sein.
|
||||
const ausweis = await prisma.bedarfsausweisWohnen.findUnique({
|
||||
where: {
|
||||
uid,
|
||||
},
|
||||
include: {
|
||||
aufnahme: {
|
||||
select: {
|
||||
storniert: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!ausweis) {
|
||||
// Falls wir den Ausweis nicht finden können, werfen wir einen Fehler
|
||||
throw new APIError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Ausweis konnte nicht gefunden werden.",
|
||||
});
|
||||
}
|
||||
|
||||
// Wir dürfen den Ausweis nur stornieren, wenn er noch nicht ausgestellt wurde
|
||||
// Außerdem müssen wir schauen, ob wir Admin oder der Besitzer des Ausweises sind.
|
||||
if ((ausweis.benutzer_id !== user.id) && user.rolle !== "ADMIN") {
|
||||
// Falls der Ausweis nicht dem Nutzer gehört, werfen wir einen Fehler
|
||||
throw new APIError({
|
||||
code: "FORBIDDEN",
|
||||
message: "Ausweis gehört nicht dem Nutzer.",
|
||||
});
|
||||
}
|
||||
|
||||
// if (ausweis.erledigt) {
|
||||
// // Falls der Ausweis bereits ausgestellt wurde, werfen wir einen Fehler
|
||||
// throw new TRPCError({
|
||||
// code: "BAD_REQUEST",
|
||||
// message: "Ausweis wurde bereits ausgestellt.",
|
||||
// });
|
||||
// }
|
||||
|
||||
if (ausweis.aufnahme.storniert) {
|
||||
// Falls der Ausweis bereits storniert ist, werfen wir einen Fehler
|
||||
throw new APIError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Ausweis wurde bereits storniert.",
|
||||
});
|
||||
}
|
||||
|
||||
await prisma.aufnahme.update({
|
||||
where: {
|
||||
id: ausweis.aufnahme_id
|
||||
},
|
||||
data: {
|
||||
storniert: true
|
||||
}
|
||||
})
|
||||
|
||||
// Wir erstellen ein Event, dass der Ausweis storniert wurde
|
||||
// Dann können wir das in der Historie anzeigen
|
||||
await prisma.event.create({
|
||||
data: {
|
||||
title: "Ausweis storniert",
|
||||
description: ((user.rolle === "ADMIN") && (ausweis.benutzer_id !== user.id)) ? "Ausweis wurde von einem Administrator storniert." : "Ausweis wurde vom Besitzer storniert.",
|
||||
benutzer: {
|
||||
connect: {
|
||||
id: user.id
|
||||
}
|
||||
},
|
||||
aufnahme: {
|
||||
connect: {
|
||||
id: ausweis.aufnahme_id
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
export const GET = defineApiRoute({
|
||||
meta: {
|
||||
description: "Gibt ein spezifisches Gebäude des Benutzers zurück.",
|
||||
tags: ["Gebäude"],
|
||||
headers: {
|
||||
"Authorization": {
|
||||
description: "Ein gültiger Authentifizierungstoken",
|
||||
required: true,
|
||||
allowEmptyValue: false,
|
||||
examples: {
|
||||
Bearer: {
|
||||
value: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
output: ZodOverlap<OptionalNullable<BedarfsausweisWohnenClient>>(BedarfsausweisWohnenSchema.merge(z.object({
|
||||
uid_aufnahme: UUidWithPrefix,
|
||||
uid_objekt: UUidWithPrefix,
|
||||
uid_benutzer: UUidWithPrefix.optional()
|
||||
})).omit({
|
||||
id: true,
|
||||
aufnahme_id: true,
|
||||
benutzer_id: true
|
||||
})),
|
||||
middleware: authorizationMiddleware,
|
||||
async fetch(input, context, user) {
|
||||
const { uid } = context.params;
|
||||
|
||||
if (!uid) {
|
||||
throw new APIError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Missing uid in request params"
|
||||
})
|
||||
}
|
||||
|
||||
const ausweis = await prisma.bedarfsausweisWohnen.findUnique({
|
||||
where: {
|
||||
uid,
|
||||
benutzer_id: user.id
|
||||
},
|
||||
include: {
|
||||
benutzer: {
|
||||
select: {
|
||||
uid: true
|
||||
}
|
||||
},
|
||||
aufnahme: {
|
||||
select: {
|
||||
uid: true,
|
||||
objekt: {
|
||||
select: {
|
||||
uid: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!ausweis) {
|
||||
// Falls wir den Ausweis nicht finden können, werfen wir einen Fehler
|
||||
throw new APIError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Ausweis konnte nicht gefunden werden.",
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
uid_aufnahme: ausweis.aufnahme.uid,
|
||||
uid_objekt: ausweis.aufnahme.objekt.uid,
|
||||
uid_benutzer: ausweis.benutzer?.uid,
|
||||
...exclude(ausweis, ["id", "aufnahme_id", "benutzer_id", "aufnahme"])
|
||||
}
|
||||
},
|
||||
});
|
||||
146
src/pages/api/geg-nachweis-verbrauchsausweis-wohnen/index.ts
Normal file
146
src/pages/api/geg-nachweis-verbrauchsausweis-wohnen/index.ts
Normal file
@@ -0,0 +1,146 @@
|
||||
import { UUidWithPrefix } from "#components/Ausweis/types.js";
|
||||
import { authorizationHeaders, authorizationMiddleware } from "#lib/middleware/authorization.js";
|
||||
import { BedarfsausweisWohnenSchema, prisma, VerbrauchsausweisWohnenSchema } from "@ibcornelsen/database/server";
|
||||
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||
import { z } from "zod";
|
||||
|
||||
export const PUT = defineApiRoute({
|
||||
meta: {
|
||||
contentTypes: ["application/json"],
|
||||
description:
|
||||
"Erstellt einen neuen GEG Nachweis für Wohngebäude.",
|
||||
tags: ["GEG Nachweis", "Verbrauchsausweis Wohnen"],
|
||||
},
|
||||
input: z.object({
|
||||
ausweis: VerbrauchsausweisWohnenSchema.omit({
|
||||
id: true,
|
||||
benutzer_id: true,
|
||||
uid: true,
|
||||
aufnahme_id: true
|
||||
}),
|
||||
uid_aufnahme: UUidWithPrefix
|
||||
}),
|
||||
output: z.object({
|
||||
uid: UUidWithPrefix,
|
||||
objekt_uid: UUidWithPrefix,
|
||||
aufnahme_uid: UUidWithPrefix,
|
||||
}),
|
||||
headers: authorizationHeaders,
|
||||
middleware: authorizationMiddleware,
|
||||
async fetch(input, ctx, user) {
|
||||
const aufnahme = await prisma.aufnahme.findUnique({
|
||||
where: {
|
||||
uid: input.uid_aufnahme
|
||||
}
|
||||
})
|
||||
|
||||
if (!aufnahme || aufnahme.benutzer_id !== user.id) {
|
||||
throw new APIError({
|
||||
code: "FORBIDDEN",
|
||||
message: "Aufnahme konnte nicht gefunden werden oder gehört nicht zu diesem Benutzer."
|
||||
})
|
||||
}
|
||||
|
||||
const createdAusweis = await prisma.verbrauchsausweisWohnen.create({
|
||||
data: {
|
||||
...input.ausweis,
|
||||
benutzer: {
|
||||
connect: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
aufnahme: {
|
||||
connect: {
|
||||
uid: aufnahme.uid,
|
||||
},
|
||||
},
|
||||
},
|
||||
select: {
|
||||
uid: true,
|
||||
aufnahme: {
|
||||
select: {
|
||||
uid: true,
|
||||
objekt: {
|
||||
select: {
|
||||
uid: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
uid: createdAusweis.uid,
|
||||
objekt_uid: createdAusweis.aufnahme.objekt.uid,
|
||||
aufnahme_uid: createdAusweis.aufnahme.uid,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const GET = defineApiRoute({
|
||||
meta: {
|
||||
description: "Gibt ein spezifisches Gebäude des Benutzers zurück.",
|
||||
tags: ["Gebäude"],
|
||||
headers: {
|
||||
Authorization: {
|
||||
description: "Ein gültiger Authentifizierungstoken",
|
||||
required: true,
|
||||
allowEmptyValue: false,
|
||||
examples: {
|
||||
Bearer: {
|
||||
value: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
middleware: authorizationMiddleware,
|
||||
async fetch(input, context, user) {
|
||||
const { uid } = context.params;
|
||||
|
||||
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
|
||||
where: {
|
||||
uid,
|
||||
},
|
||||
include: {
|
||||
benutzer: true,
|
||||
aufnahme: {
|
||||
include: {
|
||||
objekt: {
|
||||
include: {
|
||||
gebaeude_bilder: true,
|
||||
},
|
||||
},
|
||||
rechnungen: true,
|
||||
events: {
|
||||
include: {
|
||||
benutzer: {
|
||||
select: {
|
||||
uid: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: {
|
||||
date: "asc",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (
|
||||
!ausweis ||
|
||||
(ausweis.benutzer_id !== null && ausweis.benutzer_id !== user.id)
|
||||
) {
|
||||
// Falls wir den Ausweis nicht finden können, werfen wir einen Fehler
|
||||
throw new APIError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Ausweis konnte nicht gefunden werden.",
|
||||
});
|
||||
}
|
||||
|
||||
return ausweis;
|
||||
},
|
||||
});
|
||||
116
src/pages/api/objekt/[uid]/unterlagen.ts
Normal file
116
src/pages/api/objekt/[uid]/unterlagen.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
|
||||
import { prisma, UnterlageSchema } from "@ibcornelsen/database/server";
|
||||
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||
import { z } from "zod";
|
||||
import { fileURLToPath } from "url";
|
||||
import { writeFileSync } from "fs";
|
||||
|
||||
export const PUT = defineApiRoute({
|
||||
input: UnterlageSchema.omit({
|
||||
objekt_id: true,
|
||||
id: true,
|
||||
uid: true
|
||||
}).merge(z.object({
|
||||
data: z.string(),
|
||||
})),
|
||||
output: z.object({
|
||||
uid: z.string({ description: "Die UID der Unterlage." })
|
||||
}),
|
||||
middleware: authorizationMiddleware,
|
||||
async fetch({ data, name, kategorie, mime }, ctx, user) {
|
||||
if (mime !== "application/pdf" && mime !== "image/png" && mime !== "image/jpeg") {
|
||||
throw new APIError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Nicht unterstützter mimetype, unterstützt werden 'image/jpeg', 'image/png', 'application/pdf'."
|
||||
})
|
||||
}
|
||||
|
||||
let objekt = await prisma.objekt.findUnique({
|
||||
where: {
|
||||
uid: ctx.params.uid,
|
||||
benutzer_id: user.id
|
||||
},
|
||||
});
|
||||
|
||||
if (!objekt) {
|
||||
throw new APIError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Objekt nicht gefunden oder gehört einem anderen Benutzer.",
|
||||
});
|
||||
}
|
||||
|
||||
const buffer = Buffer.from(data, "base64");
|
||||
|
||||
const unterlage = await prisma.unterlage.create({
|
||||
data: {
|
||||
kategorie: kategorie,
|
||||
objekt: {
|
||||
connect: {
|
||||
id: objekt.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
select: {
|
||||
uid: true,
|
||||
},
|
||||
});
|
||||
|
||||
const filePath = fileURLToPath(new URL(`../../../../../persistent/unterlagen/${unterlage.uid}`, import.meta.url));
|
||||
|
||||
try {
|
||||
writeFileSync(filePath, buffer)
|
||||
} catch(e) {
|
||||
// Unterlage wurde nicht gespeichert, wir löschen den Eintrag wieder
|
||||
await prisma.unterlage.delete({
|
||||
where: {
|
||||
uid: unterlage.uid
|
||||
}
|
||||
})
|
||||
// Und geben einen Fehler zurück
|
||||
throw new APIError({
|
||||
code: "INTERNAL_SERVER_ERROR",
|
||||
message: "Unterlage konnte nicht gespeichert werden.",
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
uid: unterlage.uid
|
||||
};
|
||||
},
|
||||
})
|
||||
|
||||
export const GET = defineApiRoute({
|
||||
middleware: authorizationMiddleware,
|
||||
output: z.array(UnterlageSchema.pick({
|
||||
kategorie: true,
|
||||
uid: true
|
||||
})),
|
||||
async fetch(input, ctx, user) {
|
||||
const { uid } = ctx.params;
|
||||
|
||||
const objekt = await prisma.objekt.findUnique({
|
||||
where: {
|
||||
uid,
|
||||
benutzer_id: user.id
|
||||
},
|
||||
select: {
|
||||
benutzer_id: true,
|
||||
unterlagen: {
|
||||
select: {
|
||||
kategorie: true,
|
||||
uid: true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (!objekt) {
|
||||
throw new APIError({
|
||||
code: "FORBIDDEN",
|
||||
message: "Objekt existiert nicht oder gehört einem anderen Benutzer."
|
||||
})
|
||||
}
|
||||
|
||||
return objekt.unterlagen
|
||||
},
|
||||
})
|
||||
@@ -3,8 +3,8 @@ import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
||||
import { validateAccessTokenServer } from "#server/lib/validateAccessToken.js";
|
||||
import { prisma } from "@ibcornelsen/database/server";
|
||||
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||
import { fileURLToPath } from "bun";
|
||||
import * as fs from "fs";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
export const GET = defineApiRoute({
|
||||
async fetch(input, context, transfer) {
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
---
|
||||
import UserLayout from "../../../layouts/UserLayout.astro";
|
||||
import { validateAccessTokenServer } from "#server/lib/validateAccessToken";
|
||||
import DashboardAusweisePruefenModule from "#modules/Dashboard/DashboardAusweisePruefenModule.svelte";
|
||||
import { prisma } from "@ibcornelsen/database/server";
|
||||
import { createCaller } from "#lib/caller";
|
||||
|
||||
const accessTokenValid = await validateAccessTokenServer(Astro);
|
||||
|
||||
if (!accessTokenValid) {
|
||||
return Astro.redirect("/auth/login")
|
||||
}
|
||||
|
||||
// TODO: Nutzer darf nur auf diese Seite, wenn er die Rolle "admin" hat
|
||||
|
||||
const caller = createCaller(Astro);
|
||||
|
||||
const ausweise = await caller.v1.verbrauchsausweisWohnen.getMany({
|
||||
limit: 25,
|
||||
});
|
||||
---
|
||||
|
||||
<UserLayout title="Dashboard">
|
||||
<DashboardAusweisePruefenModule ausweise={ausweise} client:load></DashboardAusweisePruefenModule>
|
||||
</UserLayout>
|
||||
@@ -3,7 +3,7 @@ import { AufnahmeClient, BenutzerClient, ObjektClient, UploadedGebaeudeBild, Ver
|
||||
import UserLayout from "#layouts/UserLayout.astro";
|
||||
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants";
|
||||
import DashboardAusweisePruefenModule from "#modules/Dashboard/DashboardAusweisePruefenModule.svelte";
|
||||
import { prisma } from "@ibcornelsen/database/server";
|
||||
import { Enums, prisma } from "@ibcornelsen/database/server";
|
||||
import { createCaller } from "src/astro-typesafe-api-caller";
|
||||
|
||||
const caller = createCaller(Astro)
|
||||
@@ -20,6 +20,10 @@ try {
|
||||
return Astro.redirect("/auth/login")
|
||||
}
|
||||
|
||||
if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
||||
return Astro.redirect("/dashboard")
|
||||
}
|
||||
|
||||
const ausweise = await prisma.verbrauchsausweisWohnen.findMany({
|
||||
where: {
|
||||
benutzer: {
|
||||
|
||||
@@ -74,9 +74,9 @@ export const GET: APIRoute = async (Astro) => {
|
||||
|
||||
let pdf: Uint8Array<ArrayBufferLike> | null = null;
|
||||
if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) {
|
||||
pdf = await pdfVerbrauchsausweisWohnen(ausweis, aufnahme, objekt, bilder, user);
|
||||
pdf = await pdfVerbrauchsausweisWohnen(ausweis as VerbrauchsausweisWohnenClient, aufnahme, objekt, bilder, user);
|
||||
} else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) {
|
||||
pdf = await pdfVerbrauchsausweisGewerbe(ausweis, aufnahme, objekt, bilder, user);
|
||||
pdf = await pdfVerbrauchsausweisGewerbe(ausweis as VerbrauchsausweisGewerbeClient, aufnahme, objekt, bilder, user);
|
||||
}
|
||||
|
||||
return new Response(pdf, {
|
||||
@@ -92,10 +92,10 @@ export const POST: APIRoute = async (Astro) => {
|
||||
|
||||
const caller = createCaller(Astro);
|
||||
|
||||
const ausweis = JSON.parse(params.get("ausweis"));
|
||||
const aufnahme = JSON.parse(params.get("aufnahme"));
|
||||
const objekt = JSON.parse(params.get("objekt"));
|
||||
const bilder = JSON.parse(params.get("bilder"));
|
||||
const ausweis = JSON.parse(params.get("ausweis") || "{}");
|
||||
const aufnahme = JSON.parse(params.get("aufnahme") || "{}");
|
||||
const objekt = JSON.parse(params.get("objekt") || "{}");
|
||||
const bilder = JSON.parse(params.get("bilder") || "{}");
|
||||
const ausweisart: Enums.Ausweisart = params.get("ausweisart")
|
||||
|
||||
let user: BenutzerClient = {};
|
||||
|
||||
Reference in New Issue
Block a user