Checkpoint: Audit de robustesse et maintenabilité : calcul dynamique des tendances OPEX par véritable année N-1, filtrage/validation centralisés des codes établissement, transactions d'import et d'écriture, contraintes uniques CAPEX/OPEX avec déduplication, suppression effective de postes OPEX, nettoyage des gabarits et scripts morts, chargement différé XLSX, documentation métier et 22 tests passants.
This commit is contained in:
23
shared/opexValidation.test.ts
Normal file
23
shared/opexValidation.test.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { isOpexEtablissementCode, normalizeOpexEtablissementCode } from "./opexValidation";
|
||||
|
||||
describe("validation des codes établissement OPEX", () => {
|
||||
it("normalise les codes réels, y compris les codes composés", () => {
|
||||
expect(normalizeOpexEtablissementCode(" 1001bpt ")).toBe("1001BPT");
|
||||
expect(normalizeOpexEtablissementCode("1084CAS + CAC")).toBe("1084CAS + CAC");
|
||||
expect(isOpexEtablissementCode("1083MIS+MIC")).toBe(true);
|
||||
});
|
||||
|
||||
it("rejette les libellés de catégories et de synthèse importés par erreur", () => {
|
||||
for (const invalidCode of [
|
||||
"Infogérance",
|
||||
"Sécurité",
|
||||
"Applicatifs HEP",
|
||||
"Téléphonie",
|
||||
"TOTAL",
|
||||
"Appicatifs commmuns",
|
||||
]) {
|
||||
expect(isOpexEtablissementCode(invalidCode)).toBe(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
22
shared/opexValidation.ts
Normal file
22
shared/opexValidation.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Règles communes aux imports et écritures de bases de répartition OPEX.
|
||||
*
|
||||
* Les fichiers sources mélangent parfois des lignes d'établissement avec des
|
||||
* en-têtes de catégories ou des totaux. Cette validation est appliquée côté
|
||||
* client pour guider l'utilisateur et côté serveur pour protéger la BDD.
|
||||
*/
|
||||
const OPEX_SUMMARY_LABEL = /^(?:infog|s.curit|t.l.phonie|app(?:licatifs)?(?:\s|$)|total|ventilation|r.partition|nouveaut)/i;
|
||||
|
||||
/** Préserve l'affichage du code, tout en stabilisant casse et espaces. */
|
||||
export function normalizeOpexEtablissementCode(value: string): string {
|
||||
return value.trim().replace(/\s+/g, " ").toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Un code établissement OPEX débute toujours par son code numérique d'entité.
|
||||
* Les suffixes composites historiques (« + CAC », « +MIC ») restent admis.
|
||||
*/
|
||||
export function isOpexEtablissementCode(value: string): boolean {
|
||||
const code = normalizeOpexEtablissementCode(value);
|
||||
return code.length > 0 && /^\d{4}[A-Z0-9 +]*$/.test(code) && !OPEX_SUMMARY_LABEL.test(code);
|
||||
}
|
||||
Reference in New Issue
Block a user