Checkpoint: Ajout de l'onglet 'Clés de répartition' dans DSI OPEX : tableau éditable avec base de répartition standard et base /HEP par établissement, import fichier Excel/CSV, info année (OPEX N → base N-2). Calcul automatique du poste SAAS DUI Pôle HEP branché sur la colonne /HEP. Nouvelle table opex_bases_repartition avec colonne baseRepartitionHep. Seed 2026 : 64 établissements dont 19 HEP. 14 tests passants, 0 erreur TypeScript.

This commit is contained in:
Manus
2026-06-11 07:20:24 +00:00
parent 14a660892a
commit 841ff1bd09
9 changed files with 1310 additions and 21 deletions

View File

@@ -179,11 +179,33 @@ export const appRouter = router({
.input(z.object({ annee: z.number() }))
.query(async ({ input }) => db.getOpexBasesRepartition(input.annee)),
// Upsert une base de répartition pour un établissement
// Upsert une base de répartition pour un établissement (standard + HEP)
setBaseRepartition: writeProcedure
.input(z.object({ annee: z.number(), etablissementCode: z.string(), etablissementNom: z.string().optional().nullable(), baseRepartition: z.number() }))
.input(z.object({
annee: z.number(),
etablissementCode: z.string(),
etablissementNom: z.string().optional().nullable(),
baseRepartition: z.number(),
baseRepartitionHep: z.number().optional().default(0),
}))
.mutation(async ({ input }) => { await db.upsertOpexBaseRepartition(input); return { success: true }; }),
// Import en masse des bases de répartition (depuis fichier Excel/CSV)
importBasesRepartition: writeProcedure
.input(z.object({
annee: z.number(),
rows: z.array(z.object({
etablissementCode: z.string(),
etablissementNom: z.string().optional().nullable(),
baseRepartition: z.number(),
baseRepartitionHep: z.number().optional().default(0),
})),
}))
.mutation(async ({ input }) => {
await db.importOpexBasesRepartition(input.annee, input.rows);
return { success: true, count: input.rows.length };
}),
// Supprimer toutes les lignes OPEX d'une année
deleteAll: writeProcedure
.input(z.object({ annee: z.number() }))