Checkpoint: Ajout du module Masse salariale SANTINOVA : tables de salariés, rémunérations et évolutions manuelles sécurisées par rôle administrateur ; import contrôlé des bulletins 2025 et janvier–août 2026 ; écran tableau 2025–2027 ; tests d'autorisations, d'agrégats et des quatre états UI ; documentation des sources et de la politique d'import.
This commit is contained in:
30
drizzle/0005_nasty_tattoo.sql
Normal file
30
drizzle/0005_nasty_tattoo.sql
Normal file
@@ -0,0 +1,30 @@
|
||||
CREATE TABLE `masse_salariale_remunerations` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`salarieId` int NOT NULL,
|
||||
`annee` int NOT NULL,
|
||||
`salaireAnnuelBrutHorsPrimesCents` int NOT NULL,
|
||||
`salaireAnnuelBrutAvecPrimesCents` int NOT NULL,
|
||||
`salaireMensuelBrutHorsPrimesCents` int NOT NULL,
|
||||
`tauxChargeBps` int NOT NULL,
|
||||
`evolutionSalarialeBps` int,
|
||||
`periodeReference` varchar(7),
|
||||
`source` varchar(64) NOT NULL DEFAULT 'bulletin',
|
||||
`createdAt` timestamp NOT NULL DEFAULT (now()),
|
||||
`updatedAt` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
|
||||
CONSTRAINT `masse_salariale_remunerations_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `masse_salariale_salarie_annee_idx` UNIQUE(`salarieId`,`annee`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `masse_salariale_salaries` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`matricule` varchar(32) NOT NULL,
|
||||
`nom` varchar(150) NOT NULL,
|
||||
`prenom` varchar(150) NOT NULL,
|
||||
`poste` varchar(255) NOT NULL,
|
||||
`dateEmbauche` varchar(10) NOT NULL,
|
||||
`actif` boolean NOT NULL DEFAULT true,
|
||||
`createdAt` timestamp NOT NULL DEFAULT (now()),
|
||||
`updatedAt` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
|
||||
CONSTRAINT `masse_salariale_salaries_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `masse_salariale_salaries_matricule_unique` UNIQUE(`matricule`)
|
||||
);
|
||||
1
drizzle/0006_ambitious_shen.sql
Normal file
1
drizzle/0006_ambitious_shen.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE `masse_salariale_remunerations` ADD `statut` varchar(32) DEFAULT 'annuel' NOT NULL;
|
||||
13
drizzle/0007_rich_tony_stark.sql
Normal file
13
drizzle/0007_rich_tony_stark.sql
Normal file
@@ -0,0 +1,13 @@
|
||||
CREATE TABLE `masse_salariale_evolutions` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`salarieId` int NOT NULL,
|
||||
`annee` int NOT NULL,
|
||||
`evolutionSalarialeBps` int NOT NULL,
|
||||
`createdBy` int NOT NULL,
|
||||
`createdAt` timestamp NOT NULL DEFAULT (now()),
|
||||
`updatedAt` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
|
||||
CONSTRAINT `masse_salariale_evolutions_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `masse_salariale_evolution_salarie_annee_idx` UNIQUE(`salarieId`,`annee`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `masse_salariale_remunerations` DROP COLUMN `evolutionSalarialeBps`;
|
||||
1123
drizzle/meta/0005_snapshot.json
Normal file
1123
drizzle/meta/0005_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1131
drizzle/meta/0006_snapshot.json
Normal file
1131
drizzle/meta/0006_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1202
drizzle/meta/0007_snapshot.json
Normal file
1202
drizzle/meta/0007_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -36,6 +36,27 @@
|
||||
"when": 1786998761879,
|
||||
"tag": "0004_known_shiva",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"version": "5",
|
||||
"when": 1787833569970,
|
||||
"tag": "0005_nasty_tattoo",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"version": "5",
|
||||
"when": 1787833802656,
|
||||
"tag": "0006_ambitious_shen",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"version": "5",
|
||||
"when": 1787833910943,
|
||||
"tag": "0007_rich_tony_stark",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -201,3 +201,67 @@ export const opexBasesRepartition = mysqlTable("opex_bases_repartition", {
|
||||
|
||||
export type OpexBaseRepartition = typeof opexBasesRepartition.$inferSelect;
|
||||
export type InsertOpexBaseRepartition = typeof opexBasesRepartition.$inferInsert;
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// MASSE SALARIALE SANTINOVA — Données sensibles, accès administrateur uniquement
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
export const masseSalarialeSalaries = mysqlTable("masse_salariale_salaries", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
/** Identifiant paie stable, distinct des données personnelles superflues. */
|
||||
matricule: varchar("matricule", { length: 32 }).notNull().unique(),
|
||||
nom: varchar("nom", { length: 150 }).notNull(),
|
||||
prenom: varchar("prenom", { length: 150 }).notNull(),
|
||||
poste: varchar("poste", { length: 255 }).notNull(),
|
||||
/** Date civile ISO (YYYY-MM-DD), sans fuseau horaire. */
|
||||
dateEmbauche: varchar("dateEmbauche", { length: 10 }).notNull(),
|
||||
actif: boolean("actif").default(true).notNull(),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
|
||||
});
|
||||
|
||||
export type MasseSalarialeSalarie = typeof masseSalarialeSalaries.$inferSelect;
|
||||
export type InsertMasseSalarialeSalarie = typeof masseSalarialeSalaries.$inferInsert;
|
||||
|
||||
/**
|
||||
* Une ligne par salarié et exercice. Tous les montants sont en centimes et les
|
||||
* taux en points de base (ex. 42,75 % = 4 275) pour éviter les erreurs d'arrondi.
|
||||
*/
|
||||
export const masseSalarialeRemunerations = mysqlTable("masse_salariale_remunerations", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
salarieId: int("salarieId").notNull(),
|
||||
annee: int("annee").notNull(),
|
||||
salaireAnnuelBrutHorsPrimesCents: int("salaireAnnuelBrutHorsPrimesCents").notNull(),
|
||||
salaireAnnuelBrutAvecPrimesCents: int("salaireAnnuelBrutAvecPrimesCents").notNull(),
|
||||
salaireMensuelBrutHorsPrimesCents: int("salaireMensuelBrutHorsPrimesCents").notNull(),
|
||||
tauxChargeBps: int("tauxChargeBps").notNull(),
|
||||
/** 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. */
|
||||
statut: varchar("statut", { length: 32 }).notNull().default("annuel"),
|
||||
source: varchar("source", { length: 64 }).notNull().default("bulletin"),
|
||||
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),
|
||||
}));
|
||||
|
||||
export type MasseSalarialeRemuneration = typeof masseSalarialeRemunerations.$inferSelect;
|
||||
export type InsertMasseSalarialeRemuneration = typeof masseSalarialeRemunerations.$inferInsert;
|
||||
|
||||
/** Évolution salariale manuelle, stockée même en l'absence de bulletin pour l'année concernée. */
|
||||
export const masseSalarialeEvolutions = mysqlTable("masse_salariale_evolutions", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
salarieId: int("salarieId").notNull(),
|
||||
annee: int("annee").notNull(),
|
||||
/** Pourcentage exprimé en points de base, ex. 1,50 % = 150. */
|
||||
evolutionSalarialeBps: int("evolutionSalarialeBps").notNull(),
|
||||
createdBy: int("createdBy").notNull(),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
|
||||
}, (t) => ({
|
||||
uniqSalarieAnnee: uniqueIndex("masse_salariale_evolution_salarie_annee_idx").on(t.salarieId, t.annee),
|
||||
}));
|
||||
|
||||
export type MasseSalarialeEvolution = typeof masseSalarialeEvolutions.$inferSelect;
|
||||
export type InsertMasseSalarialeEvolution = typeof masseSalarialeEvolutions.$inferInsert;
|
||||
|
||||
Reference in New Issue
Block a user