Files
itinova-budget-si/server/masseSalarialeHttp.ts

53 lines
2.1 KiB
TypeScript

import type { Express, Request, Response } from "express";
import multer from "multer";
import { sdk } from "./_core/sdk";
import { importMasseSalariale } from "./db";
import { parseMasseSalarialeWorkbookBuffer } from "./masseSalarialeWorkbookImport";
const MAX_WORKBOOK_BYTES = 5 * 1024 * 1024;
const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: MAX_WORKBOOK_BYTES, files: 1 } });
async function getAdminUser(req: Request, res: Response) {
try {
const user = await sdk.authenticateRequest(req);
if (user.role === "admin") return user;
res.status(403).json({ error: "Accès réservé aux administrateurs." });
} catch {
res.status(401).json({ error: "Authentification requise." });
}
return null;
}
function isXlsx(file: Express.Multer.File | undefined): file is Express.Multer.File {
if (!file) return false;
return file.originalname.toLowerCase().endsWith(".xlsx")
&& file.buffer.subarray(0, 2).toString("ascii") === "PK";
}
/**
* Cette route est volontairement limitée au transfert binaire du classeur.
* Elle ne renvoie jamais les lignes salariales : la page relit ensuite son
* agrégat tRPC administrateur.
*/
export function registerMasseSalarialeHttpRoutes(app: Express) {
app.post("/api/masse-salariale/previsionnels", upload.single("file"), async (req, res) => {
const user = await getAdminUser(req, res);
if (!user) return;
if (!isXlsx(req.file)) {
res.status(400).json({ error: "Transmettez un fichier .xlsx conforme (5 Mo maximum)." });
return;
}
try {
const parsed = parseMasseSalarialeWorkbookBuffer(req.file.buffer);
const result = await importMasseSalariale(parsed.salaries, parsed.remunerations, {
replaceForecastYears: [2025, 2026, 2027],
});
res.json({ salaries: result.salaries, remunerations: result.remunerations, years: [2025, 2026, 2027] });
} catch (error) {
console.error("[Masse salariale] Échec import prévisionnel", error instanceof Error ? error.message : "erreur inconnue");
res.status(422).json({ error: "Le fichier n'a pas pu être importé. Les prévisions existantes sont conservées." });
}
});
}