Checkpoint: Ajout de la projection annuelle prévisionnel-réel dans Masse salariale : import contrôlé du fichier modèle 2025-2027, réel 2026 provenant uniquement des liasses Salaires, ajustements administrateur limités aux primes et évolutions de l'année courante/future, conservation des centimes, modèle de calcul testé et documentation. 72 tests, TypeScript et build validés.

This commit is contained in:
Manus
2026-08-31 10:58:02 +00:00
parent 5c9618b204
commit 28570234d0
17 changed files with 2415 additions and 204 deletions

View File

@@ -230,10 +230,19 @@ export const masseSalarialeRemunerations = mysqlTable("masse_salariale_remunerat
id: int("id").autoincrement().primaryKey(),
salarieId: int("salarieId").notNull(),
annee: int("annee").notNull(),
/** Les lignes stockées constituent le prévisionnel ; le réel est dérivé des liasses mensuelles. */
nature: mysqlEnum("nature", ["previsionnel"]).notNull().default("previsionnel"),
salaireAnnuelBrutHorsPrimesCents: int("salaireAnnuelBrutHorsPrimesCents").notNull(),
salaireAnnuelBrutAvecPrimesCents: int("salaireAnnuelBrutAvecPrimesCents").notNull(),
salaireMensuelBrutHorsPrimesCents: int("salaireMensuelBrutHorsPrimesCents").notNull(),
tauxChargeBps: int("tauxChargeBps").notNull(),
tauxChargeBps: int("tauxChargeBps"),
/** Seules ces deux composantes de prévision sont éditables pour l'exercice courant ou futur. */
primeAstreinteCents: int("primeAstreinteCents").notNull().default(0),
primeCents: int("primeCents").notNull().default(0),
evolutionCents: int("evolutionCents").notNull().default(0),
/** Valeurs à l'import, utilisées pour recalculer le prévisionnel par différence lors d'une édition. */
primeReferenceCents: int("primeReferenceCents").notNull().default(0),
evolutionReferenceCents: int("evolutionReferenceCents").notNull().default(0),
/** Mois de paie ayant servi de référence, ex. 2025-12 ou 2026-08. */
periodeReference: varchar("periodeReference", { length: 7 }),
/** `annuel` pour un exercice clos ; `cumul_provisoire` pour une année en cours. */
@@ -242,8 +251,8 @@ export const masseSalarialeRemunerations = mysqlTable("masse_salariale_remunerat
createdAt: timestamp("createdAt").defaultNow().notNull(),
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
}, (t) => ({
/** Rend les imports idempotents pour un salarié et un exercice. */
uniqSalarieAnnee: uniqueIndex("masse_salariale_salarie_annee_idx").on(t.salarieId, t.annee),
/** Rend les imports idempotents pour un salarié, exercice et nature de donnée. */
uniqSalarieAnneeNature: uniqueIndex("masse_salariale_salarie_annee_nature_idx").on(t.salarieId, t.annee, t.nature),
}));
export type MasseSalarialeRemuneration = typeof masseSalarialeRemunerations.$inferSelect;