Bedarfsausweis Wohnen ausstellen
This commit is contained in:
@@ -5,30 +5,31 @@ export const createCaller = createCallerFactory({
|
|||||||
"klimafaktoren": await import("../src/pages/api/klimafaktoren.ts"),
|
"klimafaktoren": await import("../src/pages/api/klimafaktoren.ts"),
|
||||||
"postleitzahlen": await import("../src/pages/api/postleitzahlen.ts"),
|
"postleitzahlen": await import("../src/pages/api/postleitzahlen.ts"),
|
||||||
"unterlage": await import("../src/pages/api/unterlage.ts"),
|
"unterlage": await import("../src/pages/api/unterlage.ts"),
|
||||||
|
"aufnahme": await import("../src/pages/api/aufnahme/index.ts"),
|
||||||
|
"ausweise": await import("../src/pages/api/ausweise/index.ts"),
|
||||||
|
"bedarfsausweis-gewerbe/[id]": await import("../src/pages/api/bedarfsausweis-gewerbe/[id].ts"),
|
||||||
|
"bedarfsausweis-gewerbe": await import("../src/pages/api/bedarfsausweis-gewerbe/index.ts"),
|
||||||
"admin/ausstellen": await import("../src/pages/api/admin/ausstellen.ts"),
|
"admin/ausstellen": await import("../src/pages/api/admin/ausstellen.ts"),
|
||||||
|
"admin/bedarfsausweis-ausstellen": await import("../src/pages/api/admin/bedarfsausweis-ausstellen.ts"),
|
||||||
"admin/bestellbestaetigung": await import("../src/pages/api/admin/bestellbestaetigung.ts"),
|
"admin/bestellbestaetigung": await import("../src/pages/api/admin/bestellbestaetigung.ts"),
|
||||||
"admin/erinnern": await import("../src/pages/api/admin/erinnern.ts"),
|
"admin/erinnern": await import("../src/pages/api/admin/erinnern.ts"),
|
||||||
"admin/nicht-ausstellen": await import("../src/pages/api/admin/nicht-ausstellen.ts"),
|
"admin/nicht-ausstellen": await import("../src/pages/api/admin/nicht-ausstellen.ts"),
|
||||||
"admin/registriernummer": await import("../src/pages/api/admin/registriernummer.ts"),
|
"admin/registriernummer": await import("../src/pages/api/admin/registriernummer.ts"),
|
||||||
"admin/stornieren": await import("../src/pages/api/admin/stornieren.ts"),
|
"admin/stornieren": await import("../src/pages/api/admin/stornieren.ts"),
|
||||||
"aufnahme": await import("../src/pages/api/aufnahme/index.ts"),
|
"bedarfsausweis-wohnen/[id]": await import("../src/pages/api/bedarfsausweis-wohnen/[id].ts"),
|
||||||
"ausweise": await import("../src/pages/api/ausweise/index.ts"),
|
"bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"),
|
||||||
"auth/access-token": await import("../src/pages/api/auth/access-token.ts"),
|
"auth/access-token": await import("../src/pages/api/auth/access-token.ts"),
|
||||||
"auth/passwort-vergessen": await import("../src/pages/api/auth/passwort-vergessen.ts"),
|
"auth/passwort-vergessen": await import("../src/pages/api/auth/passwort-vergessen.ts"),
|
||||||
"auth/refresh-token": await import("../src/pages/api/auth/refresh-token.ts"),
|
"auth/refresh-token": await import("../src/pages/api/auth/refresh-token.ts"),
|
||||||
"bedarfsausweis-gewerbe/[id]": await import("../src/pages/api/bedarfsausweis-gewerbe/[id].ts"),
|
|
||||||
"bedarfsausweis-gewerbe": await import("../src/pages/api/bedarfsausweis-gewerbe/index.ts"),
|
|
||||||
"bedarfsausweis-wohnen/[id]": await import("../src/pages/api/bedarfsausweis-wohnen/[id].ts"),
|
|
||||||
"bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"),
|
|
||||||
"bilder/[id]": await import("../src/pages/api/bilder/[id].ts"),
|
"bilder/[id]": await import("../src/pages/api/bilder/[id].ts"),
|
||||||
"geg-nachweis-gewerbe/[id]": await import("../src/pages/api/geg-nachweis-gewerbe/[id].ts"),
|
"geg-nachweis-gewerbe/[id]": await import("../src/pages/api/geg-nachweis-gewerbe/[id].ts"),
|
||||||
"geg-nachweis-gewerbe": await import("../src/pages/api/geg-nachweis-gewerbe/index.ts"),
|
"geg-nachweis-gewerbe": await import("../src/pages/api/geg-nachweis-gewerbe/index.ts"),
|
||||||
"geg-nachweis-wohnen/[id]": await import("../src/pages/api/geg-nachweis-wohnen/[id].ts"),
|
"geg-nachweis-wohnen/[id]": await import("../src/pages/api/geg-nachweis-wohnen/[id].ts"),
|
||||||
"geg-nachweis-wohnen": await import("../src/pages/api/geg-nachweis-wohnen/index.ts"),
|
"geg-nachweis-wohnen": await import("../src/pages/api/geg-nachweis-wohnen/index.ts"),
|
||||||
"objekt": await import("../src/pages/api/objekt/index.ts"),
|
|
||||||
"rechnung/[id]": await import("../src/pages/api/rechnung/[id].ts"),
|
"rechnung/[id]": await import("../src/pages/api/rechnung/[id].ts"),
|
||||||
"rechnung/anfordern": await import("../src/pages/api/rechnung/anfordern.ts"),
|
"rechnung/anfordern": await import("../src/pages/api/rechnung/anfordern.ts"),
|
||||||
"rechnung": await import("../src/pages/api/rechnung/index.ts"),
|
"rechnung": await import("../src/pages/api/rechnung/index.ts"),
|
||||||
|
"objekt": await import("../src/pages/api/objekt/index.ts"),
|
||||||
"ticket": await import("../src/pages/api/ticket/index.ts"),
|
"ticket": await import("../src/pages/api/ticket/index.ts"),
|
||||||
"user": await import("../src/pages/api/user/index.ts"),
|
"user": await import("../src/pages/api/user/index.ts"),
|
||||||
"user/self": await import("../src/pages/api/user/self.ts"),
|
"user/self": await import("../src/pages/api/user/self.ts"),
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
import {
|
import {
|
||||||
CrossCircled,
|
CrossCircled,
|
||||||
DotsVertical,
|
DotsVertical,
|
||||||
Download,
|
|
||||||
Pencil2,
|
Pencil2,
|
||||||
QuestionMarkCircled,
|
QuestionMarkCircled,
|
||||||
} from "radix-svelte-icons";
|
} from "radix-svelte-icons";
|
||||||
@@ -28,10 +27,8 @@
|
|||||||
import DashboardNotification from "./DashboardNotification.svelte";
|
import DashboardNotification from "./DashboardNotification.svelte";
|
||||||
import { notifications } from "#components/NotificationProvider/shared.js";
|
import { notifications } from "#components/NotificationProvider/shared.js";
|
||||||
import { Bell } from "radix-svelte-icons";
|
import { Bell } from "radix-svelte-icons";
|
||||||
import { A13BerechnungRechnerischeLaufzeitHeizung } from "#lib/Berechnungen/BedarfsausweisWohnen/A13BerechnungRechnerischeLaufzeitHeizung.js";
|
import mime from "mime"
|
||||||
import mime from "mime"
|
|
||||||
import { getGEGNachweisGewerbe } from "#lib/server/db.js";
|
|
||||||
|
|
||||||
const progress = ausweis.ausgestellt ? 100 : ausweis.bestellt ? 66 : 33;
|
const progress = ausweis.ausgestellt ? 100 : ausweis.bestellt ? 66 : 33;
|
||||||
|
|
||||||
const ausweisart = getAusweisartFromId(ausweis.id);
|
const ausweisart = getAusweisartFromId(ausweis.id);
|
||||||
@@ -151,6 +148,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function ausstellen(post = false) {
|
async function ausstellen(post = false) {
|
||||||
const notification = addNotification({
|
const notification = addNotification({
|
||||||
message: "Ausweis wird ausgestellt.",
|
message: "Ausweis wird ausgestellt.",
|
||||||
@@ -158,33 +157,124 @@
|
|||||||
type: "info",
|
type: "info",
|
||||||
timeout: 0,
|
timeout: 0,
|
||||||
})
|
})
|
||||||
try {
|
|
||||||
await api.admin.ausstellen.GET.fetch({
|
if (ausweisart === Enums.Ausweisart.BedarfsausweisWohnen) {
|
||||||
id_ausweis: ausweis.id,
|
const results: {data: string, name: string, type: "Sonstiges" | "Ausweis"}[] = []
|
||||||
post
|
for (const file of bedarfsausweisAdditionalInput.files || []) {
|
||||||
}, {
|
const reader = new FileReader();
|
||||||
headers: {
|
|
||||||
"Authorization": `Bearer ${Cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)}`
|
reader.onload = (ev) => {
|
||||||
|
const result = reader.result;
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
addNotification({
|
||||||
|
message: `Die Datei ${file.name} konnte nicht verarbeitet werden.`,
|
||||||
|
timeout: 3000,
|
||||||
|
type: "error",
|
||||||
|
dismissable: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
results.push({
|
||||||
|
data: result as string,
|
||||||
|
name: file.name,
|
||||||
|
type: "Sonstiges"
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
reader.readAsDataURL(file)
|
||||||
|
}
|
||||||
|
|
||||||
ausweis.ausgestellt = true;
|
// Jetzt holen wir uns noch den Ausweis
|
||||||
|
const files = bedarfsausweisFileInput.files
|
||||||
|
const reader = new FileReader()
|
||||||
|
|
||||||
updateNotification(notification, {
|
if (files === null || (files.length === 0)) {
|
||||||
message: "Ausweis ausgestellt.",
|
addNotification({
|
||||||
subtext: "Der Ausweis wurde erfolgreich ausgestellt.",
|
message: "Bitte laden sie vor dem Ausstellen einen Ausweis hoch.",
|
||||||
timeout: 3000,
|
timeout: 3000,
|
||||||
type: "success",
|
type: "error",
|
||||||
})
|
dismissable: true
|
||||||
} catch(e) {
|
})
|
||||||
updateNotification(notification, {
|
return;
|
||||||
message: "Das hat nicht geklappt.",
|
}
|
||||||
subtext: e as string,
|
|
||||||
timeout: 3000,
|
reader.onload = (ev) => {
|
||||||
type: "error",
|
const result = reader.result;
|
||||||
})
|
|
||||||
|
if (!result) {
|
||||||
|
addNotification({
|
||||||
|
message: `Die Datei ${files[0].name} konnte nicht verarbeitet werden.`,
|
||||||
|
timeout: 3000,
|
||||||
|
type: "error",
|
||||||
|
dismissable: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
results.push({
|
||||||
|
data: result as string,
|
||||||
|
name: files[0].name,
|
||||||
|
type: "Ausweis"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.readAsDataURL(files[0])
|
||||||
|
|
||||||
|
try {
|
||||||
|
await api.admin["bedarfsausweis-ausstellen"].POST.fetch({
|
||||||
|
id_ausweis: ausweis.id,
|
||||||
|
post,
|
||||||
|
files: results
|
||||||
|
}, {
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Bearer ${Cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
updateNotification(notification, {
|
||||||
|
message: "Ausweis ausgestellt.",
|
||||||
|
subtext: "Der Ausweis wurde erfolgreich ausgestellt.",
|
||||||
|
timeout: 3000,
|
||||||
|
type: "success",
|
||||||
|
})
|
||||||
|
} catch(e) {
|
||||||
|
updateNotification(notification, {
|
||||||
|
message: "Das hat nicht geklappt.",
|
||||||
|
subtext: e as string,
|
||||||
|
timeout: 3000,
|
||||||
|
type: "error",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
await api.admin.ausstellen.GET.fetch({
|
||||||
|
id_ausweis: ausweis.id,
|
||||||
|
post
|
||||||
|
}, {
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Bearer ${Cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ausweis.ausgestellt = true;
|
||||||
|
|
||||||
|
updateNotification(notification, {
|
||||||
|
message: "Ausweis ausgestellt.",
|
||||||
|
subtext: "Der Ausweis wurde erfolgreich ausgestellt.",
|
||||||
|
timeout: 3000,
|
||||||
|
type: "success",
|
||||||
|
})
|
||||||
|
} catch(e) {
|
||||||
|
updateNotification(notification, {
|
||||||
|
message: "Das hat nicht geklappt.",
|
||||||
|
subtext: e as string,
|
||||||
|
timeout: 3000,
|
||||||
|
type: "error",
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let bedarfsausweisFileInput: HTMLInputElement;
|
||||||
|
let bedarfsausweisAdditionalInput: HTMLInputElement;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="relative bg-base-200 border border-base-300 rounded-lg p-4 m-2">
|
<div class="relative bg-base-200 border border-base-300 rounded-lg p-4 m-2">
|
||||||
@@ -310,6 +400,12 @@
|
|||||||
</div>
|
</div>
|
||||||
{/await}
|
{/await}
|
||||||
|
|
||||||
|
{#if benutzer.rolle === Enums.BenutzerRolle.ADMIN && ausweisart === Enums.Ausweisart.BedarfsausweisWohnen}
|
||||||
|
<span>Laden sie hier den Ausweis hoch</span>
|
||||||
|
<input type="file" bind:this={bedarfsausweisFileInput}>
|
||||||
|
<span>Laden sie hier zusätzliche Dokumente hoch</span>
|
||||||
|
<input type="file" bind:this={bedarfsausweisAdditionalInput} multiple>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<div class="flex flex-row justify-start items-center mb-4">
|
<div class="flex flex-row justify-start items-center mb-4">
|
||||||
<a
|
<a
|
||||||
@@ -406,6 +502,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if benutzer.rolle === Enums.BenutzerRolle.ADMIN}
|
{#if benutzer.rolle === Enums.BenutzerRolle.ADMIN}
|
||||||
|
|
||||||
<button class="button text-sm" title="Ausstellen" on:click={() => ausstellen(false)}>A</button>
|
<button class="button text-sm" title="Ausstellen" on:click={() => ausstellen(false)}>A</button>
|
||||||
<button class="button text-sm" title="Ausstellen mit Postversand" on:click={() => ausstellen(true)}>P</button>
|
<button class="button text-sm" title="Ausstellen mit Postversand" on:click={() => ausstellen(true)}>P</button>
|
||||||
<button class="button text-sm" title="Stornieren" on:click={stornieren}>S</button>
|
<button class="button text-sm" title="Stornieren" on:click={stornieren}>S</button>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
export let lightTheme: boolean;
|
export let lightTheme: boolean;
|
||||||
export let benutzer: Benutzer;
|
export let benutzer: Benutzer;
|
||||||
export let besteller: Benutzer;
|
export let besteller: Benutzer | null;
|
||||||
|
|
||||||
let id: string;
|
let id: string;
|
||||||
</script>
|
</script>
|
||||||
@@ -63,7 +63,8 @@
|
|||||||
|
|
||||||
<hr class="border-gray-600" />
|
<hr class="border-gray-600" />
|
||||||
|
|
||||||
Besteller
|
{#if besteller}
|
||||||
|
Besteller
|
||||||
|
|
||||||
<div class="flex flex-row mb-4">
|
<div class="flex flex-row mb-4">
|
||||||
<div class="item-center mr-4">
|
<div class="item-center mr-4">
|
||||||
@@ -82,8 +83,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr class="border-gray-600" />
|
<hr class="border-gray-600" />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Mitwirkende
|
Mitwirkende
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { Benutzer } from "#lib/server/prisma";
|
|||||||
export interface Props {
|
export interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
user: Benutzer;
|
user: Benutzer;
|
||||||
besteller: Benutzer;
|
besteller: Benutzer | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { title, user, besteller } = Astro.props;
|
const { title, user, besteller } = Astro.props;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import {
|
|||||||
VerbrauchsausweisGewerbe,
|
VerbrauchsausweisGewerbe,
|
||||||
VerbrauchsausweisWohnen,
|
VerbrauchsausweisWohnen,
|
||||||
} from "#lib/server/prisma.js";
|
} from "#lib/server/prisma.js";
|
||||||
import { join } from "path"
|
import { join } from "path";
|
||||||
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||||
import { z } from "astro:content";
|
import { z } from "astro:content";
|
||||||
import { transport } from "#lib/mail.js";
|
import { transport } from "#lib/mail.js";
|
||||||
@@ -20,9 +20,13 @@ import { BASE_URI } from "#lib/constants.js";
|
|||||||
import { getAnsichtsausweis, getDatenblatt } from "#lib/server/ausweis.js";
|
import { getAnsichtsausweis, getDatenblatt } from "#lib/server/ausweis.js";
|
||||||
import { PutObjectCommand } from "@aws-sdk/client-s3";
|
import { PutObjectCommand } from "@aws-sdk/client-s3";
|
||||||
import { s3Client } from "#lib/s3.js";
|
import { s3Client } from "#lib/s3.js";
|
||||||
import { createInvoice, getLexOfficeRechnung, getLexOfficeVoucherNumber } from "#lib/server/invoice.js";
|
import {
|
||||||
|
createInvoice,
|
||||||
|
getLexOfficeRechnung,
|
||||||
|
getLexOfficeVoucherNumber,
|
||||||
|
} from "#lib/server/invoice.js";
|
||||||
import { tryCatch } from "#lib/tryCatch.js";
|
import { tryCatch } from "#lib/tryCatch.js";
|
||||||
import SFTPClient from 'ssh2-sftp-client';
|
import SFTPClient from "ssh2-sftp-client";
|
||||||
import {
|
import {
|
||||||
getBedarfsausweisWohnenKomplett,
|
getBedarfsausweisWohnenKomplett,
|
||||||
getVerbrauchsausweisGewerbeKomplett,
|
getVerbrauchsausweisGewerbeKomplett,
|
||||||
@@ -33,7 +37,11 @@ import { PDFDocument } from "pdf-lib";
|
|||||||
export const GET = defineApiRoute({
|
export const GET = defineApiRoute({
|
||||||
input: z.object({
|
input: z.object({
|
||||||
id_ausweis: z.string(),
|
id_ausweis: z.string(),
|
||||||
post: z.boolean().describe("Ob der Ausweis auch per Post ausgestellt werden soll.").optional().default(false)
|
post: z
|
||||||
|
.boolean()
|
||||||
|
.describe("Ob der Ausweis auch per Post ausgestellt werden soll.")
|
||||||
|
.optional()
|
||||||
|
.default(false),
|
||||||
}),
|
}),
|
||||||
output: z.void(),
|
output: z.void(),
|
||||||
middleware: adminMiddleware,
|
middleware: adminMiddleware,
|
||||||
@@ -51,8 +59,8 @@ export const GET = defineApiRoute({
|
|||||||
objekt: Objekt & {
|
objekt: Objekt & {
|
||||||
benutzer: Benutzer | null;
|
benutzer: Benutzer | null;
|
||||||
};
|
};
|
||||||
},
|
};
|
||||||
rechnung: Rechnung
|
rechnung: Rechnung;
|
||||||
})
|
})
|
||||||
| null = null;
|
| null = null;
|
||||||
|
|
||||||
@@ -76,15 +84,15 @@ export const GET = defineApiRoute({
|
|||||||
OR: [
|
OR: [
|
||||||
{ bedarfsausweis_wohnen: { id: id_ausweis } },
|
{ bedarfsausweis_wohnen: { id: id_ausweis } },
|
||||||
{ verbrauchsausweis_wohnen: { id: id_ausweis } },
|
{ verbrauchsausweis_wohnen: { id: id_ausweis } },
|
||||||
{ verbrauchsausweis_gewerbe: { id: id_ausweis } }
|
{ verbrauchsausweis_gewerbe: { id: id_ausweis } },
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
orderBy: {
|
orderBy: {
|
||||||
erstellt_am: "desc",
|
erstellt_am: "desc",
|
||||||
},
|
},
|
||||||
include: {
|
include: {
|
||||||
benutzer: true
|
benutzer: true,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!rechnung) {
|
if (!rechnung) {
|
||||||
@@ -106,7 +114,7 @@ export const GET = defineApiRoute({
|
|||||||
code: "BAD_REQUEST",
|
code: "BAD_REQUEST",
|
||||||
message:
|
message:
|
||||||
"Die Rechnung konnte bei LexOffice nicht angelegt werden..",
|
"Die Rechnung konnte bei LexOffice nicht angelegt werden..",
|
||||||
cause: error
|
cause: error,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +131,7 @@ export const GET = defineApiRoute({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
voucherNumber = await getLexOfficeVoucherNumber(rechnung)
|
voucherNumber = await getLexOfficeVoucherNumber(rechnung);
|
||||||
}
|
}
|
||||||
|
|
||||||
const pdfAusweis = await getAnsichtsausweis(
|
const pdfAusweis = await getAnsichtsausweis(
|
||||||
@@ -146,73 +154,78 @@ export const GET = defineApiRoute({
|
|||||||
// TODO: Das ist immer noch scheiße, LexOffice ist doof
|
// TODO: Das ist immer noch scheiße, LexOffice ist doof
|
||||||
// Hier müssen wir warten, damit wir sichergehen können, dass die Rechnung bei LexOffice existiert.
|
// Hier müssen wir warten, damit wir sichergehen können, dass die Rechnung bei LexOffice existiert.
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
const [pdfRechnung, pdfRechnungError] = await tryCatch(getLexOfficeRechnung(rechnung));
|
const [pdfRechnung, pdfRechnungError] = await tryCatch(
|
||||||
|
getLexOfficeRechnung(rechnung)
|
||||||
|
);
|
||||||
|
|
||||||
if (pdfRechnungError) {
|
if (pdfRechnungError) {
|
||||||
throw new APIError({
|
throw new APIError({
|
||||||
code: "INTERNAL_SERVER_ERROR",
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
message: "Rechnungs PDF konnte nicht generiert werden."
|
message: "Rechnungs PDF konnte nicht generiert werden.",
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pdfAusweis) {
|
if (!pdfAusweis) {
|
||||||
throw new APIError({
|
throw new APIError({
|
||||||
code: "INTERNAL_SERVER_ERROR",
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
message: "Ausweis PDF konnte nicht generiert werden."
|
message: "Ausweis PDF konnte nicht generiert werden.",
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pdfDatenblatt) {
|
if (!pdfDatenblatt) {
|
||||||
throw new APIError({
|
throw new APIError({
|
||||||
code: "INTERNAL_SERVER_ERROR",
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
message: "Datenblatt PDF konnte nicht generiert werden."
|
message: "Datenblatt PDF konnte nicht generiert werden.",
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const ausweisCommand = new PutObjectCommand({
|
const ausweisCommand = new PutObjectCommand({
|
||||||
Bucket: "ibc-pdfs",
|
Bucket: "ibc-pdfs",
|
||||||
Key: `ID_${ausweis.id}_Energieausweis.pdf`,
|
Key: `ID_${ausweis.id}_Energieausweis.pdf`,
|
||||||
Body: pdfAusweis,
|
Body: pdfAusweis,
|
||||||
ACL: "private",
|
ACL: "private",
|
||||||
});
|
});
|
||||||
|
|
||||||
await s3Client.send(ausweisCommand);
|
await s3Client.send(ausweisCommand);
|
||||||
|
|
||||||
const datenblattCommand = new PutObjectCommand({
|
const datenblattCommand = new PutObjectCommand({
|
||||||
Bucket: "ibc-pdfs",
|
Bucket: "ibc-pdfs",
|
||||||
Key: `ID_${ausweis.id}_Datenblatt.pdf`,
|
Key: `ID_${ausweis.id}_Datenblatt.pdf`,
|
||||||
Body: pdfDatenblatt,
|
Body: pdfDatenblatt,
|
||||||
ACL: "private",
|
ACL: "private",
|
||||||
});
|
});
|
||||||
|
|
||||||
await s3Client.send(datenblattCommand);
|
await s3Client.send(datenblattCommand);
|
||||||
|
|
||||||
const rechnungsCommand = new PutObjectCommand({
|
const rechnungsCommand = new PutObjectCommand({
|
||||||
Bucket: "ibc-pdfs",
|
Bucket: "ibc-pdfs",
|
||||||
Key: `ID_${ausweis.id}_Rechnung.pdf`,
|
Key: `ID_${ausweis.id}_Rechnung.pdf`,
|
||||||
Body: pdfDatenblatt,
|
Body: Buffer.from(pdfRechnung),
|
||||||
ACL: "private",
|
ACL: "private",
|
||||||
});
|
});
|
||||||
|
|
||||||
await s3Client.send(rechnungsCommand);
|
await s3Client.send(rechnungsCommand);
|
||||||
|
|
||||||
// Falls Postversand angefragt wurde müssen wir die Dateien auf den Postserver hochladen
|
// Falls Postversand angefragt wurde müssen wir die Dateien auf den Postserver hochladen
|
||||||
if (post) {
|
if (post) {
|
||||||
const dateiNameDruck = `1011000000000-AW_ID_${ausweis.id}.pdf`;
|
const dateiNameDruck = `1011000000000-AW_ID_${ausweis.id}.pdf`;
|
||||||
|
|
||||||
const outputPdf = await PDFDocument.create();
|
const outputPdf = await PDFDocument.create();
|
||||||
|
|
||||||
async function appendPdf(buffer: Uint8Array<ArrayBufferLike>) {
|
async function appendPdf(buffer: Uint8Array<ArrayBufferLike>) {
|
||||||
const doc = await PDFDocument.load(buffer);
|
const doc = await PDFDocument.load(buffer);
|
||||||
const copiedPages = await outputPdf.copyPages(doc, doc.getPageIndices());
|
const copiedPages = await outputPdf.copyPages(
|
||||||
|
doc,
|
||||||
|
doc.getPageIndices()
|
||||||
|
);
|
||||||
for (const page of copiedPages) {
|
for (const page of copiedPages) {
|
||||||
outputPdf.addPage(page);
|
outputPdf.addPage(page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await appendPdf(pdfDatenblatt);
|
await appendPdf(pdfDatenblatt);
|
||||||
await appendPdf(pdfAusweis);
|
await appendPdf(pdfAusweis);
|
||||||
|
|
||||||
const pdfBytes = await outputPdf.save();
|
const pdfBytes = await outputPdf.save();
|
||||||
|
|
||||||
const pdfCommand = new PutObjectCommand({
|
const pdfCommand = new PutObjectCommand({
|
||||||
@@ -221,38 +234,44 @@ export const GET = defineApiRoute({
|
|||||||
Body: pdfBytes,
|
Body: pdfBytes,
|
||||||
ACL: "private",
|
ACL: "private",
|
||||||
});
|
});
|
||||||
|
|
||||||
await s3Client.send(pdfCommand);
|
await s3Client.send(pdfCommand);
|
||||||
|
|
||||||
const sftp = new SFTPClient();
|
const sftp = new SFTPClient();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await sftp.connect({
|
await sftp.connect({
|
||||||
host: 'api.ppost.de',
|
host: "api.ppost.de",
|
||||||
username: 'jens.cornelsen@ib-cornelsen.de',
|
username: "jens.cornelsen@ib-cornelsen.de",
|
||||||
password: 'ANTQesWYjd',
|
password: "ANTQesWYjd",
|
||||||
});
|
});
|
||||||
|
|
||||||
const cwd = await sftp.cwd();
|
const cwd = await sftp.cwd();
|
||||||
await sftp.put(Buffer.from(pdfBytes), join(cwd, "upload/api", dateiNameDruck));
|
await sftp.put(
|
||||||
|
Buffer.from(pdfBytes),
|
||||||
|
join(cwd, "upload/api", dateiNameDruck)
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('SFTP Upload failed:', err);
|
console.error("SFTP Upload failed:", err);
|
||||||
throw new APIError({
|
throw new APIError({
|
||||||
code: "INTERNAL_SERVER_ERROR",
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
message: "Login zum Postversand Server war nicht erfolgreich."
|
message:
|
||||||
|
"Login zum Postversand Server war nicht erfolgreich.",
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
sftp.end();
|
sftp.end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let html: string;
|
let html: string;
|
||||||
|
|
||||||
if (rechnung.status === Enums.Rechnungsstatus.paid) {
|
if (rechnung.status === Enums.Rechnungsstatus.paid) {
|
||||||
html = `
|
html = `
|
||||||
<p>Sehr geehrte*r ${rechnung.empfaenger},</p>
|
<p>Sehr geehrte*r ${rechnung.empfaenger},</p>
|
||||||
|
|
||||||
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : ""} Den Rechnungsbetrag haben Sie bereits bezahlt. Vielen Dank.</p>
|
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${
|
||||||
|
post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : ""
|
||||||
|
} Den Rechnungsbetrag haben Sie bereits bezahlt. Vielen Dank.</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Mit freundlichen Grüßen,
|
Mit freundlichen Grüßen,
|
||||||
@@ -279,7 +298,9 @@ export const GET = defineApiRoute({
|
|||||||
html = `
|
html = `
|
||||||
<p>Sehr geehrte*r ${rechnung.empfaenger},</p>
|
<p>Sehr geehrte*r ${rechnung.empfaenger},</p>
|
||||||
|
|
||||||
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : ""} Nachfolgend finden Sie unsere Bankverbindung. Bitte geben Sie als Verwendungszweck die Rechnungsnummer an (siehe unten). Vielen Dank.</p>
|
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${
|
||||||
|
post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : ""
|
||||||
|
} Nachfolgend finden Sie unsere Bankverbindung. Bitte geben Sie als Verwendungszweck die Rechnungsnummer an (siehe unten). Vielen Dank.</p>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<table>
|
<table>
|
||||||
@@ -316,34 +337,38 @@ export const GET = defineApiRoute({
|
|||||||
fax 040 · 209339859
|
fax 040 · 209339859
|
||||||
</p>`;
|
</p>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
await transport.sendMail({
|
await transport.sendMail({
|
||||||
from: `"IBCornelsen" <info@online-energieausweis.org>`,
|
from: `"IBCornelsen" <info@online-energieausweis.org>`,
|
||||||
to: rechnung.email || rechnung.benutzer.email,
|
to: rechnung.email || rechnung.benutzer.email,
|
||||||
bcc: "info@online-energieausweis.org",
|
bcc: "info@online-energieausweis.org",
|
||||||
subject: `Ihr Originalausweis vom Ingenieurbüro Cornelsen (ID: ${ausweis.id})`,
|
subject: `Ihr Originalausweis vom Ingenieurbüro Cornelsen (ID: ${ausweis.id})`,
|
||||||
html,
|
html,
|
||||||
attachments: [{
|
attachments: [
|
||||||
filename: `ID_${ausweis.id}_Energieausweis.pdf`,
|
{
|
||||||
encoding: "binary",
|
filename: `ID_${ausweis.id}_Energieausweis.pdf`,
|
||||||
content: Buffer.from(pdfAusweis),
|
encoding: "binary",
|
||||||
contentType: "application/pdf",
|
content: Buffer.from(pdfAusweis),
|
||||||
contentDisposition: "attachment",
|
contentType: "application/pdf",
|
||||||
}, {
|
contentDisposition: "attachment",
|
||||||
filename: `ID_${ausweis.id}_Datenblatt.pdf`,
|
},
|
||||||
encoding: "binary",
|
{
|
||||||
content: Buffer.from(pdfDatenblatt),
|
filename: `ID_${ausweis.id}_Datenblatt.pdf`,
|
||||||
contentType: "application/pdf",
|
encoding: "binary",
|
||||||
contentDisposition: "attachment",
|
content: Buffer.from(pdfDatenblatt),
|
||||||
}, {
|
contentType: "application/pdf",
|
||||||
filename: `ID_${ausweis.id}_Rechnung.pdf`,
|
contentDisposition: "attachment",
|
||||||
encoding: "binary",
|
},
|
||||||
content: Buffer.from(pdfRechnung),
|
{
|
||||||
contentType: "application/pdf",
|
filename: `ID_${ausweis.id}_Rechnung.pdf`,
|
||||||
contentDisposition: "attachment",
|
encoding: "binary",
|
||||||
}]
|
content: Buffer.from(pdfRechnung),
|
||||||
|
contentType: "application/pdf",
|
||||||
|
contentDisposition: "attachment",
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) {
|
if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) {
|
||||||
await prisma.verbrauchsausweisWohnen.update({
|
await prisma.verbrauchsausweisWohnen.update({
|
||||||
where: {
|
where: {
|
||||||
@@ -353,7 +378,9 @@ export const GET = defineApiRoute({
|
|||||||
ausgestellt: true,
|
ausgestellt: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) {
|
} else if (
|
||||||
|
ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe
|
||||||
|
) {
|
||||||
await prisma.verbrauchsausweisGewerbe.update({
|
await prisma.verbrauchsausweisGewerbe.update({
|
||||||
where: {
|
where: {
|
||||||
id: ausweis.id,
|
id: ausweis.id,
|
||||||
@@ -372,6 +399,6 @@ export const GET = defineApiRoute({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, 3000)
|
}, 3000);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
361
src/pages/api/admin/bedarfsausweis-ausstellen.ts
Normal file
361
src/pages/api/admin/bedarfsausweis-ausstellen.ts
Normal file
@@ -0,0 +1,361 @@
|
|||||||
|
import { getAusweisartFromId } from "#components/Ausweis/types.js";
|
||||||
|
import { adminMiddleware } from "#lib/middleware/authorization.js";
|
||||||
|
import {
|
||||||
|
Aufnahme,
|
||||||
|
BedarfsausweisWohnen,
|
||||||
|
Benutzer,
|
||||||
|
Bild,
|
||||||
|
Enums,
|
||||||
|
Objekt,
|
||||||
|
prisma,
|
||||||
|
Rechnung,
|
||||||
|
} from "#lib/server/prisma.js";
|
||||||
|
import { join } from "path";
|
||||||
|
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||||
|
import { z } from "astro:content";
|
||||||
|
import { transport } from "#lib/mail.js";
|
||||||
|
import { PutObjectCommand } from "@aws-sdk/client-s3";
|
||||||
|
import { s3Client } from "#lib/s3.js";
|
||||||
|
import {
|
||||||
|
createInvoice,
|
||||||
|
getLexOfficeRechnung,
|
||||||
|
getLexOfficeVoucherNumber,
|
||||||
|
} from "#lib/server/invoice.js";
|
||||||
|
import { tryCatch } from "#lib/tryCatch.js";
|
||||||
|
import SFTPClient from "ssh2-sftp-client";
|
||||||
|
import {
|
||||||
|
getBedarfsausweisWohnenKomplett,
|
||||||
|
} from "#lib/server/db.js";
|
||||||
|
import { PDFDocument } from "pdf-lib";
|
||||||
|
import isBase64 from "is-base64";
|
||||||
|
import Mail from "nodemailer/lib/mailer/index.js";
|
||||||
|
import mime from "mime"
|
||||||
|
|
||||||
|
|
||||||
|
export const POST = defineApiRoute({
|
||||||
|
input: z.object({
|
||||||
|
id_ausweis: z.string(),
|
||||||
|
post: z
|
||||||
|
.boolean()
|
||||||
|
.describe("Ob der Ausweis auch per Post ausgestellt werden soll.")
|
||||||
|
.optional()
|
||||||
|
.default(false),
|
||||||
|
files: z.object({
|
||||||
|
data: z.string(),
|
||||||
|
name: z.string(),
|
||||||
|
type: z.enum(["Ausweis", "Sonstiges"])
|
||||||
|
}).array()
|
||||||
|
}),
|
||||||
|
output: z.void(),
|
||||||
|
middleware: adminMiddleware,
|
||||||
|
async fetch({ id_ausweis, post, files }, context) {
|
||||||
|
const ausweisart = getAusweisartFromId(id_ausweis);
|
||||||
|
|
||||||
|
let ausweis:
|
||||||
|
| ((BedarfsausweisWohnen) & {
|
||||||
|
aufnahme: Aufnahme & {
|
||||||
|
bilder: Bild[];
|
||||||
|
objekt: Objekt & {
|
||||||
|
benutzer: Benutzer | null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
rechnung: Rechnung;
|
||||||
|
})
|
||||||
|
| null = null;
|
||||||
|
|
||||||
|
if (ausweisart === Enums.Ausweisart.BedarfsausweisWohnen) {
|
||||||
|
ausweis = await getBedarfsausweisWohnenKomplett(id_ausweis);
|
||||||
|
} else {
|
||||||
|
throw new APIError({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "Nur Bedarfsausweise werden von dieser Route unterstützt."
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ausweis) {
|
||||||
|
throw new APIError({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "Ausweis existiert nicht.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const rechnung = await prisma.rechnung.findFirst({
|
||||||
|
where: {
|
||||||
|
bedarfsausweis_wohnen: { id: id_ausweis }
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
erstellt_am: "desc",
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
benutzer: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!rechnung) {
|
||||||
|
throw new APIError({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message:
|
||||||
|
"Die Rechnung wurde noch nicht erstellt, wir können nicht fortfahren.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let voucherNumber: string = "";
|
||||||
|
if (!rechnung.lex_office_id) {
|
||||||
|
const [result, error] = await tryCatch(
|
||||||
|
createInvoice(ausweis, rechnung)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
throw new APIError({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message:
|
||||||
|
"Die Rechnung konnte bei LexOffice nicht angelegt werden..",
|
||||||
|
cause: error,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { id, voucherNumber: lexOfficeVoucherNumber } = result;
|
||||||
|
|
||||||
|
voucherNumber = lexOfficeVoucherNumber;
|
||||||
|
|
||||||
|
await prisma.rechnung.update({
|
||||||
|
where: {
|
||||||
|
id: rechnung.id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
lex_office_id: id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
voucherNumber = await getLexOfficeVoucherNumber(rechnung);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hier müssen wir warten, damit wir sichergehen können, dass die Rechnung bei LexOffice existiert.
|
||||||
|
setTimeout(async () => {
|
||||||
|
const [pdfRechnung, pdfRechnungError] = await tryCatch(
|
||||||
|
getLexOfficeRechnung(rechnung)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (pdfRechnungError) {
|
||||||
|
throw new APIError({
|
||||||
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
|
message: "Rechnungs PDF konnte nicht generiert werden.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const processedFiles: Mail.Attachment[] = []
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const { data, name, type } = file;
|
||||||
|
|
||||||
|
if (!isBase64(data, { mimeRequired: true })) {
|
||||||
|
throw new APIError({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: `Das Attachment '${name}' kann nicht gespeichert werden.`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataWithoutPrefix = data.replace(
|
||||||
|
/^data:image\/\w+;base64,/,
|
||||||
|
""
|
||||||
|
);
|
||||||
|
const buffer = Buffer.from(dataWithoutPrefix, "base64");
|
||||||
|
const mimeType = mime.getType(name.split(".").pop() as string)
|
||||||
|
|
||||||
|
if (!mimeType) {
|
||||||
|
throw new APIError({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: `Die Datei ${name} hat einen ungültigen MimeType`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let filename: string;
|
||||||
|
|
||||||
|
if (type === "Ausweis") {
|
||||||
|
filename = `ID_${ausweis.id}_Ausweis.pdf`
|
||||||
|
} else {
|
||||||
|
filename = `ID_${ausweis.id}_${name}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
processedFiles.push({
|
||||||
|
content: buffer,
|
||||||
|
contentDisposition: "attachment",
|
||||||
|
contentType: mimeType as string,
|
||||||
|
encoding: "binary",
|
||||||
|
filename
|
||||||
|
})
|
||||||
|
|
||||||
|
const command = new PutObjectCommand({
|
||||||
|
Bucket: "ibc-pdfs",
|
||||||
|
Key: name,
|
||||||
|
Body: buffer,
|
||||||
|
ACL: "private",
|
||||||
|
});
|
||||||
|
|
||||||
|
await s3Client.send(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rechnungsCommand = new PutObjectCommand({
|
||||||
|
Bucket: "ibc-pdfs",
|
||||||
|
Key: `ID_${ausweis.id}_Rechnung.pdf`,
|
||||||
|
Body: Buffer.from(pdfRechnung),
|
||||||
|
ACL: "private",
|
||||||
|
});
|
||||||
|
|
||||||
|
await s3Client.send(rechnungsCommand);
|
||||||
|
|
||||||
|
// Falls Postversand angefragt wurde müssen wir die Dateien auf den Postserver hochladen
|
||||||
|
if (post) {
|
||||||
|
const dateiNameDruck = `1011000000000-AW_ID_${ausweis.id}.pdf`;
|
||||||
|
|
||||||
|
const outputPdf = await PDFDocument.create();
|
||||||
|
|
||||||
|
async function appendPdf(buffer: Uint8Array<ArrayBufferLike>) {
|
||||||
|
const doc = await PDFDocument.load(buffer);
|
||||||
|
const copiedPages = await outputPdf.copyPages(
|
||||||
|
doc,
|
||||||
|
doc.getPageIndices()
|
||||||
|
);
|
||||||
|
for (const page of copiedPages) {
|
||||||
|
outputPdf.addPage(page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const file of processedFiles) {
|
||||||
|
await appendPdf(file.content as Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
const pdfBytes = await outputPdf.save();
|
||||||
|
|
||||||
|
const pdfCommand = new PutObjectCommand({
|
||||||
|
Bucket: "ibc-pdfs",
|
||||||
|
Key: dateiNameDruck,
|
||||||
|
Body: pdfBytes,
|
||||||
|
ACL: "private",
|
||||||
|
});
|
||||||
|
|
||||||
|
await s3Client.send(pdfCommand);
|
||||||
|
|
||||||
|
const sftp = new SFTPClient();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sftp.connect({
|
||||||
|
host: "api.ppost.de",
|
||||||
|
username: "jens.cornelsen@ib-cornelsen.de",
|
||||||
|
password: "ANTQesWYjd",
|
||||||
|
});
|
||||||
|
|
||||||
|
const cwd = await sftp.cwd();
|
||||||
|
await sftp.put(
|
||||||
|
Buffer.from(pdfBytes),
|
||||||
|
join(cwd, "upload/api", dateiNameDruck)
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("SFTP Upload failed:", err);
|
||||||
|
throw new APIError({
|
||||||
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
|
message:
|
||||||
|
"Login zum Postversand Server war nicht erfolgreich.",
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
sftp.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let html: string;
|
||||||
|
|
||||||
|
if (rechnung.status === Enums.Rechnungsstatus.paid) {
|
||||||
|
html = `
|
||||||
|
<p>Sehr geehrte*r ${rechnung.empfaenger},</p>
|
||||||
|
|
||||||
|
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${
|
||||||
|
post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : ""
|
||||||
|
} 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 {
|
||||||
|
html = `
|
||||||
|
<p>Sehr geehrte*r ${rechnung.empfaenger},</p>
|
||||||
|
|
||||||
|
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${
|
||||||
|
post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : ""
|
||||||
|
} 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>${voucherNumber}</b></td>
|
||||||
|
</table>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<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: rechnung.email || rechnung.benutzer.email,
|
||||||
|
bcc: "info@online-energieausweis.org",
|
||||||
|
subject: `Ihr Originalausweis vom Ingenieurbüro Cornelsen (ID: ${ausweis.id})`,
|
||||||
|
html,
|
||||||
|
attachments: processedFiles,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (ausweisart === Enums.Ausweisart.BedarfsausweisWohnen) {
|
||||||
|
await prisma.bedarfsausweisWohnen.update({
|
||||||
|
where: {
|
||||||
|
id: ausweis.id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
ausgestellt: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 3000);
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -1,21 +1,10 @@
|
|||||||
---
|
---
|
||||||
import DashboardLayout from "#layouts/DashboardLayout.astro";
|
import DashboardLayout from "#layouts/DashboardLayout.astro";
|
||||||
import UserLayout from "#layouts/DashboardLayout.astro";
|
import { Enums } from "#lib/server/prisma";
|
||||||
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants";
|
|
||||||
import { Enums, prisma } from "#lib/server/prisma";
|
|
||||||
import { createCaller } from "src/astro-typesafe-api-caller";
|
|
||||||
import DashboardModule from "#modules/Dashboard/DashboardModule.svelte";
|
|
||||||
import ImpersonateUserModule from "#modules/ImpersonateUserModule.svelte";
|
import ImpersonateUserModule from "#modules/ImpersonateUserModule.svelte";
|
||||||
|
import { getCurrentUser } from "#lib/server/user";
|
||||||
|
|
||||||
const caller = createCaller(Astro)
|
const user = await getCurrentUser(Astro)
|
||||||
|
|
||||||
const params = Astro.params;
|
|
||||||
|
|
||||||
const user = await caller.user.self.GET.fetch(undefined, {
|
|
||||||
headers: {
|
|
||||||
"Authorization": `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect("/auth/login")
|
return Astro.redirect("/auth/login")
|
||||||
@@ -27,6 +16,6 @@ if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<DashboardLayout title="Impersonate User" {user}>
|
<DashboardLayout title="Impersonate User" {user} besteller={null}>
|
||||||
<ImpersonateUserModule client:load></ImpersonateUserModule>
|
<ImpersonateUserModule client:load></ImpersonateUserModule>
|
||||||
</DashboardLayout>
|
</DashboardLayout>
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
---
|
---
|
||||||
import { Enums, prisma } from "#lib/server/prisma";
|
import { Enums, prisma } from "#lib/server/prisma";
|
||||||
|
import UserLayout from "#layouts/DashboardLayout.astro";
|
||||||
import { getCurrentUser } from "#lib/server/user";
|
import { getCurrentUser } from "#lib/server/user";
|
||||||
|
import moment from "moment";
|
||||||
|
|
||||||
const page = Number(Astro.url.searchParams.get("p"));
|
const page = Number(Astro.url.searchParams.get("p"));
|
||||||
|
|
||||||
@@ -38,6 +40,15 @@ if (user.rolle === Enums.BenutzerRolle.USER) {
|
|||||||
SELECT id, updated_at FROM "GEGNachweisGewerbe" WHERE benutzer_id = ${user.id}
|
SELECT id, updated_at FROM "GEGNachweisGewerbe" WHERE benutzer_id = ${user.id}
|
||||||
ORDER BY updated_at DESC LIMIT 1 OFFSET ${page - 1}`;
|
ORDER BY updated_at DESC LIMIT 1 OFFSET ${page - 1}`;
|
||||||
} else {
|
} else {
|
||||||
|
const date = moment().subtract(2, "hours").toDate()
|
||||||
|
|
||||||
|
// SELECT id, updated_at FROM "VerbrauchsausweisWohnen" WHERE created_at >= ${date} AND bestellt = ${true} UNION ALL
|
||||||
|
// SELECT id, updated_at FROM "VerbrauchsausweisGewerbe" WHERE created_at >= ${date} AND bestellt = ${true} UNION ALL
|
||||||
|
// SELECT id, updated_at FROM "BedarfsausweisWohnen" WHERE created_at >= ${date} AND bestellt = ${true} UNION ALL
|
||||||
|
// SELECT id, updated_at FROM "BedarfsausweisGewerbe" WHERE created_at >= ${date} AND bestellt = ${true} UNION ALL
|
||||||
|
// SELECT id, updated_at FROM "GEGNachweisWohnen" WHERE created_at >= ${date} AND bestellt = ${true} UNION ALL
|
||||||
|
// SELECT id, updated_at FROM "GEGNachweisGewerbe" WHERE created_at >= ${date} AND bestellt = ${true}
|
||||||
|
|
||||||
result =
|
result =
|
||||||
await prisma.$queryRaw`SELECT id, updated_at FROM "VerbrauchsausweisWohnen" UNION ALL
|
await prisma.$queryRaw`SELECT id, updated_at FROM "VerbrauchsausweisWohnen" UNION ALL
|
||||||
SELECT id, updated_at FROM "VerbrauchsausweisGewerbe" UNION ALL
|
SELECT id, updated_at FROM "VerbrauchsausweisGewerbe" UNION ALL
|
||||||
@@ -48,11 +59,11 @@ if (user.rolle === Enums.BenutzerRolle.USER) {
|
|||||||
ORDER BY updated_at DESC LIMIT 1 OFFSET ${page - 1}`;
|
ORDER BY updated_at DESC LIMIT 1 OFFSET ${page - 1}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result) {
|
if (result.length > 0) {
|
||||||
return Astro.redirect("/dashboard/objekte?p=1");
|
return Astro.redirect(`/dashboard/objekte/${result[0].id}?p=${page}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Astro.redirect(`/dashboard/objekte/${result[0].id}?p=${page}`)
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<script></script>
|
<UserLayout title="Objekte" {user} besteller={null}>
|
||||||
|
<p>Keine Ausweise konnten gefunden werden.</p>
|
||||||
|
</UserLayout>
|
||||||
|
|||||||
Reference in New Issue
Block a user