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, lookups, orgMaps, managerNummer } = await ladeExportMitarbeiter(tx, { asOf, filters }); // Die beiden Angaben, die die gemeinsame Auswahl nicht mitbringt: die // Kostenstelle hängt an der Planstelle, der Wiedereintritt an der // Historie. Beide erst jetzt, weil erst jetzt feststeht, um wen es geht. const positionIds = [...new Set(rows.map((r) => r.position_id).filter((id): id is string => Boolean(id)))]; const [kostenstelle, wiedereintritte] = await Promise.all([ loadKontierungen(tx, { asOf: stichtag, positionIds }), tx .selectFrom("employee_history") .select("employee_id") .where("event_type", "=", "Wiedereintritt") .distinct() .execute(), ]); const kontext: CornerstoneKontext = { orgMaps, standortName: lookups.locationName, managerNummer, kostenstelle, wiedereingestellt: new Set(wiedereintritte.map((w) => w.employee_id)), stichtag, }; 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) }); }