All checks were successful
Validation applicative / TypeScript, tests et build (push) Successful in 5m21s
53 lines
2.1 KiB
TypeScript
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." });
|
|
}
|
|
});
|
|
}
|