From 043704d0a4468d185b0aa51f3232c9e2fd07cca2 Mon Sep 17 00:00:00 2001 From: titver968 Date: Sat, 26 Jul 2025 12:10:45 +0200 Subject: [PATCH] Anmeldungen Bearbeitung hinzugefuegt, leider die Anzeige ist noch nicht voll funktionsfaehig --- .../migration.sql | 62 ++++ prisma/schema.prisma | 16 +- src/lib/components/AnmeldungenTable.svelte | 245 +++++++------ src/routes/admin/anmeldungen/+page.svelte | 201 ++++++++++- src/routes/api/admin/anmeldungen/+server.ts | 334 +++++++++--------- 5 files changed, 584 insertions(+), 274 deletions(-) create mode 100644 prisma/migrations/20250726100050_add_status_tracking/migration.sql diff --git a/prisma/migrations/20250726100050_add_status_tracking/migration.sql b/prisma/migrations/20250726100050_add_status_tracking/migration.sql new file mode 100644 index 0000000..ade0aec --- /dev/null +++ b/prisma/migrations/20250726100050_add_status_tracking/migration.sql @@ -0,0 +1,62 @@ +/* + Warnings: + + - You are about to alter the column `noteDeutsch` on the `anmeldungen` table. The data in that column could be lost. The data in that column will be cast from `String` to `Int`. + - You are about to alter the column `noteMathe` on the `anmeldungen` table. The data in that column could be lost. The data in that column will be cast from `String` to `Int`. + - You are about to alter the column `timestamp` on the `anmeldungen` table. The data in that column could be lost. The data in that column will be cast from `BigInt` to `DateTime`. + - Added the required column `geburtsdatum` to the `anmeldungen` table without a default value. This is not possible if the table is not empty. + - Added the required column `hausnummer` to the `anmeldungen` table without a default value. This is not possible if the table is not empty. + - Added the required column `ort` to the `anmeldungen` table without a default value. This is not possible if the table is not empty. + - Added the required column `plz` to the `anmeldungen` table without a default value. This is not possible if the table is not empty. + - Added the required column `schulart` to the `anmeldungen` table without a default value. This is not possible if the table is not empty. + - Added the required column `strasse` to the `anmeldungen` table without a default value. This is not possible if the table is not empty. + - Added the required column `telefon` to the `anmeldungen` table without a default value. This is not possible if the table is not empty. + - Made the column `noteDeutsch` on table `anmeldungen` required. This step will fail if there are existing NULL values in that column. + - Made the column `noteMathe` on table `anmeldungen` required. This step will fail if there are existing NULL values in that column. + +*/ +-- RedefineTables +PRAGMA defer_foreign_keys=ON; +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_anmeldungen" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "anrede" TEXT NOT NULL, + "vorname" TEXT NOT NULL, + "nachname" TEXT NOT NULL, + "geburtsdatum" TEXT NOT NULL, + "strasse" TEXT NOT NULL, + "hausnummer" TEXT NOT NULL, + "ort" TEXT NOT NULL, + "plz" TEXT NOT NULL, + "telefon" TEXT NOT NULL, + "email" TEXT NOT NULL, + "schulart" TEXT NOT NULL, + "schulklasse" TEXT, + "noteDeutsch" INTEGER NOT NULL, + "noteMathe" INTEGER NOT NULL, + "sozialverhalten" TEXT, + "motivation" TEXT, + "alter" INTEGER, + "status" TEXT NOT NULL DEFAULT 'OFFEN', + "processedBy" TEXT, + "processedAt" DATETIME, + "praktikumId" INTEGER, + "zugewiesenId" INTEGER, + "wunsch1Id" INTEGER, + "wunsch2Id" INTEGER, + "wunsch3Id" INTEGER, + "timestamp" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT "anmeldungen_praktikumId_fkey" FOREIGN KEY ("praktikumId") REFERENCES "Praktikumszeitraum" ("id") ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT "anmeldungen_zugewiesenId_fkey" FOREIGN KEY ("zugewiesenId") REFERENCES "Dienststelle" ("id") ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT "anmeldungen_wunsch1Id_fkey" FOREIGN KEY ("wunsch1Id") REFERENCES "Dienststelle" ("id") ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT "anmeldungen_wunsch2Id_fkey" FOREIGN KEY ("wunsch2Id") REFERENCES "Dienststelle" ("id") ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT "anmeldungen_wunsch3Id_fkey" FOREIGN KEY ("wunsch3Id") REFERENCES "Dienststelle" ("id") ON DELETE SET NULL ON UPDATE CASCADE +); +INSERT INTO "new_anmeldungen" ("anrede", "email", "id", "nachname", "noteDeutsch", "noteMathe", "sozialverhalten", "status", "timestamp", "vorname", "wunsch1Id", "wunsch2Id", "wunsch3Id", "zugewiesenId") SELECT "anrede", "email", "id", "nachname", "noteDeutsch", "noteMathe", "sozialverhalten", "status", "timestamp", "vorname", "wunsch1Id", "wunsch2Id", "wunsch3Id", "zugewiesenId" FROM "anmeldungen"; +DROP TABLE "anmeldungen"; +ALTER TABLE "new_anmeldungen" RENAME TO "anmeldungen"; +CREATE INDEX "anmeldungen_status_idx" ON "anmeldungen"("status"); +CREATE INDEX "anmeldungen_processedAt_idx" ON "anmeldungen"("processedAt"); +CREATE INDEX "anmeldungen_zugewiesenId_idx" ON "anmeldungen"("zugewiesenId"); +PRAGMA foreign_keys=ON; +PRAGMA defer_foreign_keys=OFF; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 963d672..b4ed039 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -40,10 +40,12 @@ model Praktikumszeitraum { anmeldungen Anmeldung[] @relation("PraktikumszeitraumAnmeldungen") } +// Erweiterte Status-Enum für bessere Nachverfolgung enum Status { - OFFEN - ANGENOMMEN - ABGELEHNT + OFFEN // pending - neu eingegangen + BEARBEITUNG // processing - wird gerade bearbeitet + ANGENOMMEN // accepted - wurde angenommen + ABGELEHNT // rejected - wurde abgelehnt } model Anmeldung { @@ -67,6 +69,10 @@ model Anmeldung { alter Int? // Neu hinzugefügt für Altersvalidierung status Status @default(OFFEN) + // Neue Felder für Status-Tracking + processedBy String? // Wer bearbeitet die Anmeldung + processedAt DateTime? // Wann wurde sie bearbeitet + // Praktikumszeitraum Relation praktikumId Int? praktikum Praktikumszeitraum? @relation("PraktikumszeitraumAnmeldungen", fields: [praktikumId], references: [id]) @@ -84,6 +90,10 @@ model Anmeldung { timestamp DateTime @default(now()) pdfs PdfDatei[] + // Indizes für bessere Performance + @@index([status]) + @@index([processedAt]) + @@index([zugewiesenId]) @@map("anmeldungen") } diff --git a/src/lib/components/AnmeldungenTable.svelte b/src/lib/components/AnmeldungenTable.svelte index 2eb6412..5e3a462 100644 --- a/src/lib/components/AnmeldungenTable.svelte +++ b/src/lib/components/AnmeldungenTable.svelte @@ -2,30 +2,16 @@ @@ -54,7 +47,10 @@ - Bewerber + Status + + + Bewerber/in Noten @@ -63,129 +59,174 @@ Wünsche - Dokumente + Zugewiesen - Anmeldung + Eingegangen - + + Bearbeitet + + Aktionen {#each anmeldungen as anmeldung (anmeldung.id)} - - + + -
-
- {anmeldung.anrede} {anmeldung.vorname} {anmeldung.nachname} -
-
- {anmeldung.email} + + {getStatusText(anmeldung.status || 'pending')} + + {#if anmeldung.status === 'processing' && anmeldung.processedBy} +
+ von {anmeldung.processedBy}
+ {/if} + + + + +
+ {anmeldung.anrede} {anmeldung.vorname} {anmeldung.nachname}
+
+ {anmeldung.email} +
+ {#if anmeldung.pdfs && anmeldung.pdfs.length > 0} +
+ {#each anmeldung.pdfs as pdf} + + + + + PDF ansehen + + {/each} +
+ {/if} - -
-
Deutsch: {anmeldung.noteDeutsch || '—'}
-
Mathe: {anmeldung.noteMathe || '—'}
- {#if anmeldung.sozialverhalten} -
- Sozialverhalten:
- {anmeldung.sozialverhalten} -
- {/if} -
+ + {#if anmeldung.noteDeutsch || anmeldung.noteMathe} +
+ {#if anmeldung.noteDeutsch} +
D: {anmeldung.noteDeutsch}
+ {/if} + {#if anmeldung.noteMathe} +
M: {anmeldung.noteMathe}
+ {/if} +
+ {:else} + - + {/if} + {#if anmeldung.sozialverhalten} +
+ SV: {anmeldung.sozialverhalten} +
+ {/if} - -
+ +
{#if anmeldung.wunsch1}
- 1 - {anmeldung.wunsch1.name} + 1 + {anmeldung.wunsch1.name}
{/if} - {#if anmeldung.wunsch2}
- 2 - {anmeldung.wunsch2.name} + 2 + {anmeldung.wunsch2.name}
{/if} - {#if anmeldung.wunsch3}
- 3 - {anmeldung.wunsch3.name} + 3 + {anmeldung.wunsch3.name}
{/if}
- - -
- {#each anmeldung.pdfs as pdf, index} - - {/each} -
+ + + {#if anmeldung.assignedDienststelle} +
+ + + + {anmeldung.assignedDienststelle.name} +
+ {:else} + - + {/if} - + {formatDate(anmeldung.timestamp)} + + +
{formatProcessedDate(anmeldung.processedAt)}
+ {#if anmeldung.processedBy && anmeldung.processedAt} +
+ von {anmeldung.processedBy} +
+ {/if} + + - -
- + +
+ {#if canBeAccepted(anmeldung.status || 'pending')} + + {/if} + + {#if canBeRejected(anmeldung.status || 'pending')} + + {/if} - -
+ + + {#if anmeldung.status === 'processing'} +
+ + + + Wird bereits bearbeitet +
+ {/if} {/each} diff --git a/src/routes/admin/anmeldungen/+page.svelte b/src/routes/admin/anmeldungen/+page.svelte index 20c7035..2999187 100644 --- a/src/routes/admin/anmeldungen/+page.svelte +++ b/src/routes/admin/anmeldungen/+page.svelte @@ -20,6 +20,10 @@ wunsch3?: { id: number; name: string }; timestamp: number; id: number; + status?: 'pending' | 'accepted' | 'rejected' | 'processing'; // Neuer Status + assignedDienststelle?: { id: number; name: string }; // Zugewiesene Dienststelle + processedBy?: string; // Wer die Anmeldung bearbeitet + processedAt?: number; // Wann bearbeitet } interface EmailConfig { @@ -31,6 +35,10 @@ let isLoading = true; let error = ''; + // Filter für Status + let statusFilter: 'all' | 'pending' | 'accepted' | 'rejected' | 'processing' = 'all'; + let filteredAnmeldungen: Anmeldung[] = []; + // Dialog state let showDialog = false; let selectedAnmeldungId: number | null = null; @@ -55,6 +63,40 @@ Ihr Praktikumsteam`; let isLoadingEmailConfig = false; let isSavingEmailConfig = false; + // Status-Badge Funktionen + function getStatusColor(status: string): string { + switch (status) { + case 'pending': return 'bg-yellow-100 text-yellow-800'; + case 'processing': return 'bg-blue-100 text-blue-800'; + case 'accepted': return 'bg-green-100 text-green-800'; + case 'rejected': return 'bg-red-100 text-red-800'; + default: return 'bg-gray-100 text-gray-800'; + } + } + + function getStatusText(status: string): string { + switch (status) { + case 'pending': return 'Offen'; + case 'processing': return 'In Bearbeitung'; + case 'accepted': return 'Angenommen'; + case 'rejected': return 'Abgelehnt'; + default: return 'Unbekannt'; + } + } + + // Filter-Funktionen + function filterAnmeldungen() { + if (statusFilter === 'all') { + filteredAnmeldungen = anmeldungen; + } else { + filteredAnmeldungen = anmeldungen.filter(a => (a.status || 'pending') === statusFilter); + } + } + + $: { + filterAnmeldungen(); + } + async function loadAnmeldungen() { try { isLoading = true; @@ -67,6 +109,8 @@ Ihr Praktikumsteam`; } anmeldungen = await res.json(); + // Standardstatus setzen falls nicht vorhanden + anmeldungen = anmeldungen.map(a => ({ ...a, status: a.status || 'pending' })); } catch (err) { error = err instanceof Error ? err.message : 'Unbekannter Fehler'; console.error('Fehler beim Laden der Anmeldungen:', err); @@ -75,6 +119,28 @@ Ihr Praktikumsteam`; } } + async function setProcessingStatus(anmeldungId: number) { + try { + const res = await fetch(`/api/admin/anmeldungen?id=${anmeldungId}`, { + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + action: 'set_processing', + processedBy: 'current_user' // Hier sollte der aktuelle Benutzer stehen + }) + }); + + if (!res.ok) { + throw new Error(`Fehler beim Setzen des Status: ${res.status}`); + } + + await loadAnmeldungen(); + } catch (err) { + error = err instanceof Error ? err.message : 'Fehler beim Setzen des Status'; + console.error(err); + } + } + async function loadEmailConfig() { try { isLoadingEmailConfig = true; @@ -127,6 +193,16 @@ Ihr Praktikumsteam`; const anmeldung = anmeldungen.find(a => a.id === event.detail.id); if (!anmeldung) return; + // Prüfen ob bereits bearbeitet wird + if (anmeldung.status === 'processing') { + if (!confirm('Diese Anmeldung wird bereits bearbeitet. Trotzdem fortfahren?')) { + return; + } + } + + // Status auf "in Bearbeitung" setzen + setProcessingStatus(event.detail.id); + availableWishes = [ anmeldung.wunsch1 && { id: anmeldung.wunsch1.id, name: `1. Wunsch: ${anmeldung.wunsch1.name}` }, anmeldung.wunsch2 && { id: anmeldung.wunsch2.id, name: `2. Wunsch: ${anmeldung.wunsch2.name}` }, @@ -189,6 +265,15 @@ Ihr Praktikumsteam`; } async function handleReject(event: CustomEvent<{id: number}>) { + const anmeldung = anmeldungen.find(a => a.id === event.detail.id); + + // Prüfen ob bereits bearbeitet wird + if (anmeldung?.status === 'processing') { + if (!confirm('Diese Anmeldung wird bereits bearbeitet. Trotzdem ablehnen?')) { + return; + } + } + if (!confirm('Diese Anmeldung wirklich ablehnen?')) return; try { @@ -231,6 +316,10 @@ Ihr Praktikumsteam`; function closeDialog() { showDialog = false; selectedAnmeldungId = null; + // Status zurücksetzen falls Dialog abgebrochen wird + if (selectedAnmeldungId) { + // Hier könnten Sie den Status zurück auf "pending" setzen + } } onMount(() => { @@ -250,8 +339,25 @@ Ihr Praktikumsteam`; />
- -
+ +
+ +
+ + +
+ +
+ +
+
+
+
+
+ + + +
+
+
+

Offen

+

+ {anmeldungen.filter(a => (a.status || 'pending') === 'pending').length} +

+
+
+
+ +
+
+
+
+ + + +
+
+
+

In Bearbeitung

+

+ {anmeldungen.filter(a => a.status === 'processing').length} +

+
+
+
+ +
+
+
+
+ + + +
+
+
+

Angenommen

+

+ {anmeldungen.filter(a => a.status === 'accepted').length} +

+
+
+
+ +
+
+
+
+ + + +
+
+
+

Abgelehnt

+

+ {anmeldungen.filter(a => a.status === 'rejected').length} +

+
+
+
+
+ {#if showEmailConfig}
@@ -349,18 +530,26 @@ Ihr Praktikumsteam`;
Lade Anmeldungen...
- {:else if anmeldungen.length === 0} + {:else if filteredAnmeldungen.length === 0}
-

Keine Anmeldungen

-

Es sind noch keine Praktikumsanmeldungen eingegangen.

+

+ {statusFilter === 'all' ? 'Keine Anmeldungen' : `Keine ${getStatusText(statusFilter).toLowerCase()}en Anmeldungen`} +

+

+ {statusFilter === 'all' + ? 'Es sind noch keine Praktikumsanmeldungen eingegangen.' + : `Es gibt keine Anmeldungen mit dem Status "${getStatusText(statusFilter).toLowerCase()}".`} +

{:else}
{ - if (!checkAuth(cookies)) { - return new Response( - JSON.stringify({ error: 'Nicht autorisiert' }), - { - status: 401, - headers: { 'Content-Type': 'application/json' } - } - ); - } - +export async function GET() { try { const anmeldungen = await prisma.anmeldung.findMany({ include: { wunsch1: true, wunsch2: true, wunsch3: true, + zugewiesen: true, + praktikum: true, pdfs: true }, - orderBy: { timestamp: 'desc' } + orderBy: [ + { + status: 'asc' // BEARBEITUNG zuerst, dann OFFEN, etc. + }, + { + timestamp: 'desc' + } + ] }); - return new Response(JSON.stringify(anmeldungen), { - headers: { 'Content-Type': 'application/json' } - }); + // Daten für Frontend formatieren + const formattedAnmeldungen = anmeldungen.map(anmeldung => ({ + id: anmeldung.id, + anrede: anmeldung.anrede, + vorname: anmeldung.vorname, + nachname: anmeldung.nachname, + email: anmeldung.email, + noteDeutsch: anmeldung.noteDeutsch?.toString(), + noteMathe: anmeldung.noteMathe?.toString(), + sozialverhalten: anmeldung.sozialverhalten, + + // Status-Mapping für Frontend + status: mapPrismaStatusToFrontend(anmeldung.status), + processedBy: anmeldung.processedBy, + processedAt: anmeldung.processedAt?.getTime(), + + // Wünsche + wunsch1: anmeldung.wunsch1 ? { + id: anmeldung.wunsch1.id, + name: anmeldung.wunsch1.name + } : null, + wunsch2: anmeldung.wunsch2 ? { + id: anmeldung.wunsch2.id, + name: anmeldung.wunsch2.name + } : null, + wunsch3: anmeldung.wunsch3 ? { + id: anmeldung.wunsch3.id, + name: anmeldung.wunsch3.name + } : null, + + // Zugewiesene Dienststelle + assignedDienststelle: anmeldung.zugewiesen ? { + id: anmeldung.zugewiesen.id, + name: anmeldung.zugewiesen.name + } : null, + + timestamp: anmeldung.timestamp.getTime(), + pdfs: anmeldung.pdfs + })); + + return json(formattedAnmeldungen); } catch (error) { console.error('Fehler beim Laden der Anmeldungen:', error); return json({ error: 'Fehler beim Laden der Anmeldungen' }, { status: 500 }); } -}; - -export const POST: RequestHandler = async ({ url, cookies, request }) => { - if (!checkAuth(cookies)) { - return json({ error: 'Nicht autorisiert' }, { status: 401 }); - } - - const id = Number(url.searchParams.get('id')); - if (!id) return json({ error: 'Ungültige ID' }, { status: 400 }); +} +export async function POST({ request, url }) { try { - // Prüfe ob eine spezifische Dienststelle zugewiesen werden soll - const body = await request.json().catch(() => ({})); - const dienststelleId = body.dienststelleId; + const id = parseInt(url.searchParams.get('id') || '0'); + const { dienststelleId } = await request.json(); - const anmeldung = await prisma.anmeldung.findUnique({ - where: { id }, - include: { - wunsch1: true, - wunsch2: true, - wunsch3: true - } + if (!id || !dienststelleId) { + return json({ error: 'ID und Dienststelle erforderlich' }, { status: 400 }); + } + + // Prüfen ob Anmeldung existiert und bearbeitet werden kann + const existingAnmeldung = await prisma.anmeldung.findUnique({ + where: { id } }); - if (!anmeldung) { + if (!existingAnmeldung) { return json({ error: 'Anmeldung nicht gefunden' }, { status: 404 }); } - // Falls spezifische Dienststelle gewählt wurde - if (dienststelleId) { - const dienststelle = await prisma.dienststelle.findUnique({ - where: { id: dienststelleId } - }); - - if (!dienststelle) { - return json({ error: 'Dienststelle nicht gefunden' }, { status: 404 }); - } - - if (dienststelle.plaetze <= 0) { - return json({ error: 'Keine verfügbaren Plätze bei dieser Dienststelle' }, { status: 409 }); - } - - await prisma.$transaction([ - prisma.anmeldung.update({ - where: { id }, - data: { - status: Status.ANGENOMMEN, - zugewiesenId: dienststelleId - } - }), - prisma.dienststelle.update({ - where: { id: dienststelleId }, - data: { - plaetze: { decrement: 1 } - } - }) - ]); - - return json({ success: true, message: `Zugewiesen an: ${dienststelle.name}` }); + if (existingAnmeldung.status === 'ANGENOMMEN') { + return json({ error: 'Anmeldung bereits angenommen' }, { status: 409 }); } - // Fallback: Automatische Zuweisung nach Wunschreihenfolge - const wuensche = [anmeldung.wunsch1, anmeldung.wunsch2, anmeldung.wunsch3]; - - for (const wunsch of wuensche) { - if (wunsch && wunsch.plaetze > 0) { - await prisma.$transaction([ - prisma.anmeldung.update({ - where: { id }, - data: { - status: Status.ANGENOMMEN, - zugewiesenId: wunsch.id - } - }), - prisma.dienststelle.update({ - where: { id: wunsch.id }, - data: { - plaetze: { decrement: 1 } - } - }) - ]); - - return json({ success: true, message: `Zugewiesen an: ${wunsch.name}` }); + // Anmeldung als angenommen markieren + await prisma.anmeldung.update({ + where: { id }, + data: { + status: 'ANGENOMMEN', + zugewiesenId: dienststelleId, + processedBy: 'current_user', // TODO: Echten Benutzer verwenden + processedAt: new Date() } - } + }); - return json({ error: 'Keine verfügbaren Plätze bei Wunsch-Dienststellen' }, { status: 409 }); - } catch (err) { - console.error('Fehler beim Annehmen der Anmeldung:', err); - return json({ error: 'Interner Serverfehler' }, { status: 500 }); + return json({ success: true }); + } catch (error) { + console.error('Fehler beim Annehmen der Anmeldung:', error); + return json({ error: 'Fehler beim Annehmen der Anmeldung' }, { status: 500 }); } -}; - -// Neue PATCH-Route für Ablehnung -export const PATCH: RequestHandler = async ({ url, cookies, request }) => { - if (!checkAuth(cookies)) { - return json({ error: 'Nicht autorisiert' }, { status: 401 }); - } - - const id = Number(url.searchParams.get('id')); - if (!id) return json({ error: 'Ungültige ID' }, { status: 400 }); +} +export async function PATCH({ request, url }) { try { - const body = await request.json().catch(() => ({})); - - if (body.action === 'reject') { - await prisma.anmeldung.update({ - where: { id }, - data: { - status: Status.ABGELEHNT + const id = parseInt(url.searchParams.get('id') || '0'); + const { action, processedBy } = await request.json(); + + if (!id) { + return json({ error: 'ID erforderlich' }, { status: 400 }); + } + + let updateData = {}; + + switch (action) { + case 'reject': + updateData = { + status: 'ABGELEHNT', + processedBy: 'current_user', // TODO: Echten Benutzer verwenden + processedAt: new Date() + }; + break; + + case 'set_processing': + // Nur setzen wenn noch OFFEN + const anmeldung = await prisma.anmeldung.findUnique({ + where: { id } + }); + + if (!anmeldung) { + return json({ error: 'Anmeldung nicht gefunden' }, { status: 404 }); + } + + if (anmeldung.status !== 'OFFEN') { + return json({ error: 'Anmeldung kann nicht mehr bearbeitet werden' }, { status: 409 }); } - }); - return json({ success: true, message: 'Anmeldung abgelehnt' }); + updateData = { + status: 'BEARBEITUNG', + processedBy: processedBy || 'current_user', + processedAt: new Date() + }; + break; + + case 'reset_processing': + updateData = { + status: 'OFFEN', + processedBy: null, + processedAt: null + }; + break; + + default: + return json({ error: 'Unbekannte Aktion' }, { status: 400 }); } - return json({ error: 'Unbekannte Aktion' }, { status: 400 }); - } catch (err) { - console.error('Fehler beim Ablehnen der Anmeldung:', err); - return json({ error: 'Interner Serverfehler' }, { status: 500 }); - } -}; + const result = await prisma.anmeldung.update({ + where: { id }, + data: updateData + }); -export const DELETE: RequestHandler = async ({ cookies, url }) => { - if (!checkAuth(cookies)) { - return json({ error: 'Nicht autorisiert' }, { status: 401 }); - } - - const id = Number(url.searchParams.get('id')); - if (isNaN(id)) { - return json({ error: 'Ungültige ID' }, { status: 400 }); + return json({ success: true }); + } catch (error) { + console.error('Fehler beim Aktualisieren der Anmeldung:', error); + return json({ error: 'Fehler beim Aktualisieren der Anmeldung' }, { status: 500 }); } +} +export async function DELETE({ url }) { try { - // 1. Alle PDF-Einträge zur Anmeldung laden - const pdfs = await prisma.pdfDatei.findMany({ - where: { anmeldungId: id } - }); + const id = parseInt(url.searchParams.get('id') || '0'); - // 2. Dateien vom Dateisystem löschen - for (const pdf of pdfs) { - const filePath = path.resolve('static', pdf.pfad.replace(/^\/+/, '')); - try { - await fs.unlink(filePath); - } catch (err) { - console.warn( - `Datei konnte nicht gelöscht werden: ${filePath}`, - err instanceof Error ? err.message : String(err) - ); - // Fehler ignorieren, Datei evtl. manuell entfernt - } + if (!id) { + return json({ error: 'ID erforderlich' }, { status: 400 }); } - // 3. PDF-Datensätze aus DB löschen - await prisma.pdfDatei.deleteMany({ - where: { anmeldungId: id } - }); - - // 4. Anmeldung löschen await prisma.anmeldung.delete({ where: { id } }); - return json({ success: true, message: 'Anmeldung erfolgreich gelöscht' }); + return json({ success: true }); } catch (error) { console.error('Fehler beim Löschen der Anmeldung:', error); - return json({ error: 'Löschen fehlgeschlagen' }, { status: 500 }); + return json({ error: 'Fehler beim Löschen der Anmeldung' }, { status: 500 }); } -}; \ No newline at end of file +} + +// Hilfsfunktion: Prisma Status zu Frontend Status +function mapPrismaStatusToFrontend(prismaStatus) { + const statusMap = { + 'OFFEN': 'pending', + 'BEARBEITUNG': 'processing', + 'ANGENOMMEN': 'accepted', + 'ABGELEHNT': 'rejected' + }; + + return statusMap[prismaStatus] || 'pending'; +} + +// Hilfsfunktion: Frontend Status zu Prisma Status +function mapFrontendStatusToPrisma(frontendStatus) { + const statusMap = { + 'pending': 'OFFEN', + 'processing': 'BEARBEITUNG', + 'accepted': 'ANGENOMMEN', + 'rejected': 'ABGELEHNT' + }; + + return statusMap[frontendStatus] || 'OFFEN'; +} \ No newline at end of file