Files
online-energieausweis/src/pages/api/rechnung/index.ts
Moritz Utcke 661a75ee9c Bugfixes
2025-03-16 22:22:34 -03:00

194 lines
4.8 KiB
TypeScript

import { z } from "zod";
import { Enums, prisma } from "#lib/server/prisma.js";
import { mollieClient } from "#lib/mollie.js";
import { PaymentMethod } from "@mollie/api-client";
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
import {
authorizationHeaders,
authorizationMiddleware,
} from "#lib/middleware/authorization.js";
import { UUidWithPrefix } from "#components/Ausweis/types.js";
import { getPrismaAusweisAdapter } from "#lib/server/ausweis.js";
import { PRICES, SERVICES } from "#lib/constants.js";
import { Rechnung } from "#lib/client/prisma.js";
import { RechnungSchema } from "src/generated/zod/rechnung.js";
export const PUT = defineApiRoute({
meta: {
contentTypes: ["application/json"],
description:
"Erstellt eine neue Rechnung mit der ein Energieausweis bezahlt werden kann. Gibt eine Checkout URL zurück, welche der Nutzer folgen muss, um zum Kaufabschluss zu gelangen.",
summary: "Erstellt eine neue Rechnung zu einem Energieausweis Vorgang.",
tags: ["Rechnungen"],
},
input: z
.object({
ausweisart: z.nativeEnum(Enums.Ausweisart),
ausweis_uid: UUidWithPrefix,
ausweistyp: z.nativeEnum(Enums.AusweisTyp)
})
.merge(
RechnungSchema.omit({
benutzer_id: true,
bezahlt_am: true,
erstellt_am: true,
id: true,
status: true,
uid: true,
betrag: true,
storniert_am: true,
transaktions_referenz: true,
})
),
output: z.object({
checkout_url: z.string().optional(),
uid: UUidWithPrefix,
}),
headers: authorizationHeaders,
middleware: authorizationMiddleware,
async fetch(input, ctx, user) {
// Wir erstellen eine Mollie Payment Referenz und eine neue Rechnung in unserer Datenbank, daraufhin geben
// wir eine Checkout URL zurück auf die der Nutzer weitergeleitet werden kann.
const { ausweis_uid, ausweisart, bezahlmethode, services, ausweistyp } = input;
let betrag = PRICES[ausweisart][ausweistyp]
const servicePriceList = SERVICES[ausweisart]
for (const service of input.services) {
betrag += servicePriceList[service]
}
const adapter = getPrismaAusweisAdapter(ausweis_uid);
if (!adapter) {
throw new APIError({
code: "BAD_REQUEST",
message: "Ungültige Ausweis UID"
})
}
const ausweis = await adapter.findUnique({
where: {
uid: ausweis_uid
}
})
if (!ausweis) {
throw new APIError({
code: "NOT_FOUND",
message: "Ausweis nicht gefunden.",
});
}
if (ausweis.benutzer_id !== user.id) {
throw new APIError({
code: "UNAUTHORIZED",
message: "Ausweis gehört nicht dem Nutzer.",
});
}
// Wir erstellen eine neue Rechnung in unserer Datenbank.
let rechnung: Rechnung | null = null;
if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) {
rechnung = await prisma.rechnung.create({
data: {
benutzer_id: user.id,
betrag,
bezahlmethode: bezahlmethode,
status: Enums.Rechnungsstatus.open,
verbrauchsausweis_wohnen: {
connect: {
uid: ausweis_uid
}
},
services,
ausweistyp
}
});
} else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) {
rechnung = await prisma.rechnung.create({
data: {
benutzer_id: user.id,
betrag,
bezahlmethode: bezahlmethode,
status: Enums.Rechnungsstatus.open,
verbrauchsausweis_gewerbe: {
connect: {
uid: ausweis_uid
}
},
services,
ausweistyp
}
});
} else if (ausweisart === Enums.Ausweisart.BedarfsausweisWohnen) {
rechnung = await prisma.rechnung.create({
data: {
benutzer_id: user.id,
betrag,
bezahlmethode: bezahlmethode,
status: Enums.Rechnungsstatus.open,
bedarfsausweis_wohnen: {
connect: {
uid: ausweis_uid
}
},
services,
ausweistyp
}
});
}
if (!rechnung) {
throw new APIError({
code: "INTERNAL_SERVER_ERROR",
message: "Rechnung konnte nicht erstellt werden.",
});
}
await adapter.update({
where: {
uid: ausweis_uid
},
data: {
bestellt: true
}
})
if (bezahlmethode === Enums.Bezahlmethoden.rechnung) {
return { uid: rechnung.uid }
}
// Wir erstellen eine Mollie Payment Referenz.
const payment = await mollieClient.payments.create({
amount: {
value: betrag.toFixed(2),
currency: "EUR",
},
metadata: {
rechnung_uid: rechnung.uid,
},
method: input.bezahlmethode as PaymentMethod,
description: "Verbrauchsausweis Wohnen 2016",
redirectUrl: `https://ibcornelsen.de/payment/success?a=${ausweis.uid}&r=${rechnung.uid}`,
webhookUrl: `http://ibcornelsen.de/api/webhooks/mollie?uid=${rechnung.uid}`,
});
const checkoutUrl = payment.getCheckoutUrl();
if (!checkoutUrl) {
throw new APIError({
code: "INTERNAL_SERVER_ERROR",
message: "Checkout URL konnte nicht erstellt werden.",
});
}
return {
uid: rechnung.uid,
checkout_url: checkoutUrl,
};
},
});