import { NextResponse, type NextRequest } from "next/server"; import { baueCornerstoneZeile, CORNERSTONE_CSV, cornerstoneSpalten, type CornerstoneKontext } from "@/lib/cornerstone"; import { loadKontierungen } from "@/lib/cost-centers"; import { exportFilename, exportResponseHeaders, toCsv, toXlsx } from "@/lib/export"; import { exportParameter, ladeExportMitarbeiter } from "@/lib/export-auswahl"; import { todayIso } from "@/lib/format"; import { requireHrUser } from "@/lib/auth/require-hr"; import { withUser } from "@/lib/db"; // Der Export für Cornerstone — Spalten und Zuordnung stehen in // lib/cornerstone.ts. // // Dieselben Personen wie im vollständigen Export daneben, mit denselben // Filtern (lib/export-auswahl.ts). Wer nur die Aktiven einspielen will, // stellt das auf der Berichtsseite ein, bevor er exportiert. export async function GET(request: NextRequest) { const gate = await requireHrUser(); if ("denied" in gate) return gate.denied; const { format, asOf, filters } = exportParameter(request.nextUrl.searchParams); const stichtag = asOf ?? todayIso(); const { zeilen } = await withUser(gate.userId, async (tx) => { const { rows, managerNummer } = await ladeExportMitarbeiter(tx, { asOf, filters }); // Die eine Angabe, die die gemeinsame Auswahl nicht mitbringt: die // Kostenstelle hängt an der Planstelle, nicht an der Person. Erst jetzt, // weil erst jetzt feststeht, um welche Planstellen es geht. const positionIds = [...new Set(rows.map((r) => r.position_id).filter((id): id is string => Boolean(id)))]; const kontext: CornerstoneKontext = { managerNummer, kostenstelle: await loadKontierungen(tx, { asOf: stichtag, positionIds }), }; return { zeilen: rows.map((r) => baueCornerstoneZeile(r, kontext)) }; }); const filename = exportFilename("cornerstone-export", format); // Form und Spalten kommen beide aus lib/cornerstone.ts — siehe dort. const body = format === "xlsx" ? await toXlsx(zeilen, cornerstoneSpalten(), "Worksheet") : toCsv(zeilen, cornerstoneSpalten(), CORNERSTONE_CSV); // Derselbe Umweg über Blob wie in den anderen Exporten (TS#59417). return new NextResponse(new Blob([body as BlobPart]), { headers: exportResponseHeaders(filename, format) }); }