Checkpoint: Migration complète vers authentification locale (JWT + bcrypt) : schéma DB (10 tables), routes tRPC (auth, users, etablissements, inventaire, capex, opex, parametres), page de login avec branding Itinova/Santinova, protection des routes, onglets Établissements et Utilisateurs branchés sur tRPC, import inventaire/établissements/utilisateurs via tRPC, 14 tests Vitest passants.
This commit is contained in:
123
drizzle/0000_fat_falcon.sql
Normal file
123
drizzle/0000_fat_falcon.sql
Normal file
@@ -0,0 +1,123 @@
|
||||
CREATE TABLE `capex_lignes` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`annee` int NOT NULL,
|
||||
`etablissementCode` varchar(50) NOT NULL,
|
||||
`cle` varchar(100) NOT NULL,
|
||||
`montant` decimal(12,2),
|
||||
`createdAt` timestamp NOT NULL DEFAULT (now()),
|
||||
`updatedAt` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
|
||||
CONSTRAINT `capex_lignes_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `etablissements` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`code` varchar(50) NOT NULL,
|
||||
`nom` varchar(255) NOT NULL,
|
||||
`groupe` varchar(100),
|
||||
`ville` varchar(100),
|
||||
`actif` boolean NOT NULL DEFAULT true,
|
||||
`createdAt` timestamp NOT NULL DEFAULT (now()),
|
||||
`updatedAt` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
|
||||
CONSTRAINT `etablissements_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `etablissements_code_unique` UNIQUE(`code`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `inventaire_meta` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`annee` int NOT NULL,
|
||||
`filename` varchar(255),
|
||||
`dateImport` timestamp NOT NULL DEFAULT (now()),
|
||||
`nbEtablissements` int DEFAULT 0,
|
||||
`nbFixes` int DEFAULT 0,
|
||||
`nbPortables` int DEFAULT 0,
|
||||
CONSTRAINT `inventaire_meta_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `inventaire_meta_annee_unique` UNIQUE(`annee`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `inventaire_postes` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`annee` int NOT NULL,
|
||||
`etablissementCode` varchar(50) NOT NULL,
|
||||
`libelle` varchar(255),
|
||||
`typePoste` enum('fixe','portable') NOT NULL,
|
||||
`dateRef` varchar(20),
|
||||
`ageAns` decimal(5,2),
|
||||
`modele` varchar(255),
|
||||
`fabricant` varchar(100),
|
||||
`createdAt` timestamp NOT NULL DEFAULT (now()),
|
||||
CONSTRAINT `inventaire_postes_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `opex_montants_etab` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`annee` int NOT NULL,
|
||||
`etablissementCode` varchar(50) NOT NULL,
|
||||
`libellePoste` varchar(255) NOT NULL,
|
||||
`montant` decimal(12,2),
|
||||
`createdAt` timestamp NOT NULL DEFAULT (now()),
|
||||
`updatedAt` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
|
||||
CONSTRAINT `opex_montants_etab_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `opex_postes` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`annee` int NOT NULL,
|
||||
`colIdx` int NOT NULL,
|
||||
`libelle` varchar(255) NOT NULL,
|
||||
`libelleCourt` varchar(100),
|
||||
`libelleDetail` varchar(255),
|
||||
`fournisseur` varchar(255),
|
||||
`categorie` varchar(100),
|
||||
`type` varchar(100),
|
||||
`facturation` varchar(100),
|
||||
`modeVentilation` varchar(50) DEFAULT 'Prorata C 6',
|
||||
`compte` varchar(50),
|
||||
`detail` text,
|
||||
`budgetN1` decimal(12,2),
|
||||
`montant` decimal(12,2),
|
||||
`isCustom` boolean DEFAULT false,
|
||||
`createdAt` timestamp NOT NULL DEFAULT (now()),
|
||||
`updatedAt` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
|
||||
CONSTRAINT `opex_postes_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `opex_validated` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`annee` int NOT NULL,
|
||||
`validatedAt` timestamp NOT NULL DEFAULT (now()),
|
||||
`validatedBy` int,
|
||||
CONSTRAINT `opex_validated_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `opex_validated_annee_unique` UNIQUE(`annee`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `parametres_app` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`cle` varchar(100) NOT NULL,
|
||||
`valeur` text,
|
||||
`updatedAt` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
|
||||
CONSTRAINT `parametres_app_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `parametres_app_cle_unique` UNIQUE(`cle`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `user_etablissements` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`userId` int NOT NULL,
|
||||
`etablissementCode` varchar(50) NOT NULL,
|
||||
CONSTRAINT `user_etablissements_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `users` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`login` varchar(255) NOT NULL,
|
||||
`email` varchar(320),
|
||||
`passwordHash` varchar(255) NOT NULL,
|
||||
`firstName` varchar(100),
|
||||
`lastName` varchar(100),
|
||||
`role` enum('admin','standard','readonly') NOT NULL DEFAULT 'standard',
|
||||
`isActive` boolean NOT NULL DEFAULT true,
|
||||
`createdAt` timestamp NOT NULL DEFAULT (now()),
|
||||
`updatedAt` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
|
||||
`lastSignedIn` timestamp,
|
||||
CONSTRAINT `users_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `users_login_unique` UNIQUE(`login`)
|
||||
);
|
||||
804
drizzle/meta/0000_snapshot.json
Normal file
804
drizzle/meta/0000_snapshot.json
Normal file
@@ -0,0 +1,804 @@
|
||||
{
|
||||
"version": "5",
|
||||
"dialect": "mysql",
|
||||
"id": "973efedb-ae3f-4e9d-b1e4-fb7ab4115377",
|
||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||
"tables": {
|
||||
"capex_lignes": {
|
||||
"name": "capex_lignes",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"annee": {
|
||||
"name": "annee",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"etablissementCode": {
|
||||
"name": "etablissementCode",
|
||||
"type": "varchar(50)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"cle": {
|
||||
"name": "cle",
|
||||
"type": "varchar(100)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"montant": {
|
||||
"name": "montant",
|
||||
"type": "decimal(12,2)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"createdAt": {
|
||||
"name": "createdAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"updatedAt": {
|
||||
"name": "updatedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"onUpdate": true,
|
||||
"default": "(now())"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"capex_lignes_id": {
|
||||
"name": "capex_lignes_id",
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"etablissements": {
|
||||
"name": "etablissements",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"code": {
|
||||
"name": "code",
|
||||
"type": "varchar(50)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"nom": {
|
||||
"name": "nom",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"groupe": {
|
||||
"name": "groupe",
|
||||
"type": "varchar(100)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"ville": {
|
||||
"name": "ville",
|
||||
"type": "varchar(100)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"actif": {
|
||||
"name": "actif",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": true
|
||||
},
|
||||
"createdAt": {
|
||||
"name": "createdAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"updatedAt": {
|
||||
"name": "updatedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"onUpdate": true,
|
||||
"default": "(now())"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"etablissements_id": {
|
||||
"name": "etablissements_id",
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {
|
||||
"etablissements_code_unique": {
|
||||
"name": "etablissements_code_unique",
|
||||
"columns": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"inventaire_meta": {
|
||||
"name": "inventaire_meta",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"annee": {
|
||||
"name": "annee",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"filename": {
|
||||
"name": "filename",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"dateImport": {
|
||||
"name": "dateImport",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"nbEtablissements": {
|
||||
"name": "nbEtablissements",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": 0
|
||||
},
|
||||
"nbFixes": {
|
||||
"name": "nbFixes",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": 0
|
||||
},
|
||||
"nbPortables": {
|
||||
"name": "nbPortables",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": 0
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"inventaire_meta_id": {
|
||||
"name": "inventaire_meta_id",
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {
|
||||
"inventaire_meta_annee_unique": {
|
||||
"name": "inventaire_meta_annee_unique",
|
||||
"columns": [
|
||||
"annee"
|
||||
]
|
||||
}
|
||||
},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"inventaire_postes": {
|
||||
"name": "inventaire_postes",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"annee": {
|
||||
"name": "annee",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"etablissementCode": {
|
||||
"name": "etablissementCode",
|
||||
"type": "varchar(50)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"libelle": {
|
||||
"name": "libelle",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"typePoste": {
|
||||
"name": "typePoste",
|
||||
"type": "enum('fixe','portable')",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"dateRef": {
|
||||
"name": "dateRef",
|
||||
"type": "varchar(20)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"ageAns": {
|
||||
"name": "ageAns",
|
||||
"type": "decimal(5,2)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"modele": {
|
||||
"name": "modele",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"fabricant": {
|
||||
"name": "fabricant",
|
||||
"type": "varchar(100)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"createdAt": {
|
||||
"name": "createdAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"inventaire_postes_id": {
|
||||
"name": "inventaire_postes_id",
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"opex_montants_etab": {
|
||||
"name": "opex_montants_etab",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"annee": {
|
||||
"name": "annee",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"etablissementCode": {
|
||||
"name": "etablissementCode",
|
||||
"type": "varchar(50)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"libellePoste": {
|
||||
"name": "libellePoste",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"montant": {
|
||||
"name": "montant",
|
||||
"type": "decimal(12,2)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"createdAt": {
|
||||
"name": "createdAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"updatedAt": {
|
||||
"name": "updatedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"onUpdate": true,
|
||||
"default": "(now())"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"opex_montants_etab_id": {
|
||||
"name": "opex_montants_etab_id",
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"opex_postes": {
|
||||
"name": "opex_postes",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"annee": {
|
||||
"name": "annee",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"colIdx": {
|
||||
"name": "colIdx",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"libelle": {
|
||||
"name": "libelle",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"libelleCourt": {
|
||||
"name": "libelleCourt",
|
||||
"type": "varchar(100)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"libelleDetail": {
|
||||
"name": "libelleDetail",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"fournisseur": {
|
||||
"name": "fournisseur",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"categorie": {
|
||||
"name": "categorie",
|
||||
"type": "varchar(100)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"type": {
|
||||
"name": "type",
|
||||
"type": "varchar(100)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"facturation": {
|
||||
"name": "facturation",
|
||||
"type": "varchar(100)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"modeVentilation": {
|
||||
"name": "modeVentilation",
|
||||
"type": "varchar(50)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": "'Prorata C 6'"
|
||||
},
|
||||
"compte": {
|
||||
"name": "compte",
|
||||
"type": "varchar(50)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"detail": {
|
||||
"name": "detail",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"budgetN1": {
|
||||
"name": "budgetN1",
|
||||
"type": "decimal(12,2)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"montant": {
|
||||
"name": "montant",
|
||||
"type": "decimal(12,2)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"isCustom": {
|
||||
"name": "isCustom",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": false
|
||||
},
|
||||
"createdAt": {
|
||||
"name": "createdAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"updatedAt": {
|
||||
"name": "updatedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"onUpdate": true,
|
||||
"default": "(now())"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"opex_postes_id": {
|
||||
"name": "opex_postes_id",
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"opex_validated": {
|
||||
"name": "opex_validated",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"annee": {
|
||||
"name": "annee",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"validatedAt": {
|
||||
"name": "validatedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"validatedBy": {
|
||||
"name": "validatedBy",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"opex_validated_id": {
|
||||
"name": "opex_validated_id",
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {
|
||||
"opex_validated_annee_unique": {
|
||||
"name": "opex_validated_annee_unique",
|
||||
"columns": [
|
||||
"annee"
|
||||
]
|
||||
}
|
||||
},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"parametres_app": {
|
||||
"name": "parametres_app",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"cle": {
|
||||
"name": "cle",
|
||||
"type": "varchar(100)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"valeur": {
|
||||
"name": "valeur",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"updatedAt": {
|
||||
"name": "updatedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"onUpdate": true,
|
||||
"default": "(now())"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"parametres_app_id": {
|
||||
"name": "parametres_app_id",
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {
|
||||
"parametres_app_cle_unique": {
|
||||
"name": "parametres_app_cle_unique",
|
||||
"columns": [
|
||||
"cle"
|
||||
]
|
||||
}
|
||||
},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"user_etablissements": {
|
||||
"name": "user_etablissements",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"userId": {
|
||||
"name": "userId",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"etablissementCode": {
|
||||
"name": "etablissementCode",
|
||||
"type": "varchar(50)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"user_etablissements_id": {
|
||||
"name": "user_etablissements_id",
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"users": {
|
||||
"name": "users",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"login": {
|
||||
"name": "login",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"type": "varchar(320)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"passwordHash": {
|
||||
"name": "passwordHash",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"firstName": {
|
||||
"name": "firstName",
|
||||
"type": "varchar(100)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"lastName": {
|
||||
"name": "lastName",
|
||||
"type": "varchar(100)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"role": {
|
||||
"name": "role",
|
||||
"type": "enum('admin','standard','readonly')",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "'standard'"
|
||||
},
|
||||
"isActive": {
|
||||
"name": "isActive",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": true
|
||||
},
|
||||
"createdAt": {
|
||||
"name": "createdAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"updatedAt": {
|
||||
"name": "updatedAt",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"onUpdate": true,
|
||||
"default": "(now())"
|
||||
},
|
||||
"lastSignedIn": {
|
||||
"name": "lastSignedIn",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"users_id": {
|
||||
"name": "users_id",
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {
|
||||
"users_login_unique": {
|
||||
"name": "users_login_unique",
|
||||
"columns": [
|
||||
"login"
|
||||
]
|
||||
}
|
||||
},
|
||||
"checkConstraint": {}
|
||||
}
|
||||
},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"schemas": {},
|
||||
"tables": {},
|
||||
"columns": {}
|
||||
},
|
||||
"internal": {
|
||||
"tables": {},
|
||||
"indexes": {}
|
||||
}
|
||||
}
|
||||
13
drizzle/meta/_journal.json
Normal file
13
drizzle/meta/_journal.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": "7",
|
||||
"dialect": "mysql",
|
||||
"entries": [
|
||||
{
|
||||
"idx": 0,
|
||||
"version": "5",
|
||||
"when": 1781092850222,
|
||||
"tag": "0000_fat_falcon",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
0
drizzle/migrations/.gitkeep
Normal file
0
drizzle/migrations/.gitkeep
Normal file
1
drizzle/relations.ts
Normal file
1
drizzle/relations.ts
Normal file
@@ -0,0 +1 @@
|
||||
import {} from "./schema";
|
||||
162
drizzle/schema.ts
Normal file
162
drizzle/schema.ts
Normal file
@@ -0,0 +1,162 @@
|
||||
import {
|
||||
boolean,
|
||||
decimal,
|
||||
int,
|
||||
mysqlEnum,
|
||||
mysqlTable,
|
||||
text,
|
||||
timestamp,
|
||||
varchar,
|
||||
} from "drizzle-orm/mysql-core";
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// USERS — Auth locale (email/password), 3 profils : admin | standard | readonly
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
export const users = mysqlTable("users", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
/** Identifiant de connexion (email ou login court comme adminItinova) */
|
||||
login: varchar("login", { length: 255 }).notNull().unique(),
|
||||
email: varchar("email", { length: 320 }),
|
||||
passwordHash: varchar("passwordHash", { length: 255 }).notNull(),
|
||||
firstName: varchar("firstName", { length: 100 }),
|
||||
lastName: varchar("lastName", { length: 100 }),
|
||||
role: mysqlEnum("role", ["admin", "standard", "readonly"]).default("standard").notNull(),
|
||||
isActive: boolean("isActive").default(true).notNull(),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
|
||||
lastSignedIn: timestamp("lastSignedIn"),
|
||||
});
|
||||
|
||||
export type User = typeof users.$inferSelect;
|
||||
export type InsertUser = typeof users.$inferInsert;
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// ÉTABLISSEMENTS
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
export const etablissements = mysqlTable("etablissements", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
code: varchar("code", { length: 50 }).notNull().unique(),
|
||||
nom: varchar("nom", { length: 255 }).notNull(),
|
||||
groupe: varchar("groupe", { length: 100 }),
|
||||
ville: varchar("ville", { length: 100 }),
|
||||
actif: boolean("actif").default(true).notNull(),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
|
||||
});
|
||||
|
||||
export type Etablissement = typeof etablissements.$inferSelect;
|
||||
export type InsertEtablissement = typeof etablissements.$inferInsert;
|
||||
|
||||
// Rattachement utilisateur ↔ établissements (pour profil standard/readonly)
|
||||
export const userEtablissements = mysqlTable("user_etablissements", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
userId: int("userId").notNull(),
|
||||
etablissementCode: varchar("etablissementCode", { length: 50 }).notNull(),
|
||||
});
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// PARAMÈTRES APPLICATION
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
export const parametresApp = mysqlTable("parametres_app", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
cle: varchar("cle", { length: 100 }).notNull().unique(),
|
||||
valeur: text("valeur"),
|
||||
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
|
||||
});
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// OPEX — Postes budgétaires
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
export const opexPostes = mysqlTable("opex_postes", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
annee: int("annee").notNull(),
|
||||
colIdx: int("colIdx").notNull(),
|
||||
libelle: varchar("libelle", { length: 255 }).notNull(),
|
||||
libelleCourt: varchar("libelleCourt", { length: 100 }),
|
||||
libelleDetail: varchar("libelleDetail", { length: 255 }),
|
||||
fournisseur: varchar("fournisseur", { length: 255 }),
|
||||
categorie: varchar("categorie", { length: 100 }),
|
||||
type: varchar("type", { length: 100 }),
|
||||
facturation: varchar("facturation", { length: 100 }),
|
||||
modeVentilation: varchar("modeVentilation", { length: 50 }).default("Prorata C 6"),
|
||||
compte: varchar("compte", { length: 50 }),
|
||||
detail: text("detail"),
|
||||
budgetN1: decimal("budgetN1", { precision: 12, scale: 2 }),
|
||||
montant: decimal("montant", { precision: 12, scale: 2 }),
|
||||
isCustom: boolean("isCustom").default(false),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
|
||||
});
|
||||
|
||||
export type OpexPoste = typeof opexPostes.$inferSelect;
|
||||
export type InsertOpexPoste = typeof opexPostes.$inferInsert;
|
||||
|
||||
// Overrides manuels par établissement × poste × année
|
||||
export const opexMontantsEtab = mysqlTable("opex_montants_etab", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
annee: int("annee").notNull(),
|
||||
etablissementCode: varchar("etablissementCode", { length: 50 }).notNull(),
|
||||
libellePoste: varchar("libellePoste", { length: 255 }).notNull(),
|
||||
montant: decimal("montant", { precision: 12, scale: 2 }),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
|
||||
});
|
||||
|
||||
export type OpexMontantEtab = typeof opexMontantsEtab.$inferSelect;
|
||||
export type InsertOpexMontantEtab = typeof opexMontantsEtab.$inferInsert;
|
||||
|
||||
// Validation définitive par année
|
||||
export const opexValidated = mysqlTable("opex_validated", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
annee: int("annee").notNull().unique(),
|
||||
validatedAt: timestamp("validatedAt").defaultNow().notNull(),
|
||||
validatedBy: int("validatedBy"),
|
||||
});
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// INVENTAIRE PC
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
export const inventairePostes = mysqlTable("inventaire_postes", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
annee: int("annee").notNull(),
|
||||
etablissementCode: varchar("etablissementCode", { length: 50 }).notNull(),
|
||||
libelle: varchar("libelle", { length: 255 }),
|
||||
typePoste: mysqlEnum("typePoste", ["fixe", "portable"]).notNull(),
|
||||
dateRef: varchar("dateRef", { length: 20 }),
|
||||
ageAns: decimal("ageAns", { precision: 5, scale: 2 }),
|
||||
modele: varchar("modele", { length: 255 }),
|
||||
fabricant: varchar("fabricant", { length: 100 }),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
});
|
||||
|
||||
export type InventairePoste = typeof inventairePostes.$inferSelect;
|
||||
export type InsertInventairePoste = typeof inventairePostes.$inferInsert;
|
||||
|
||||
// Métadonnées d'import inventaire
|
||||
export const inventaireMeta = mysqlTable("inventaire_meta", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
annee: int("annee").notNull().unique(),
|
||||
filename: varchar("filename", { length: 255 }),
|
||||
dateImport: timestamp("dateImport").defaultNow().notNull(),
|
||||
nbEtablissements: int("nbEtablissements").default(0),
|
||||
nbFixes: int("nbFixes").default(0),
|
||||
nbPortables: int("nbPortables").default(0),
|
||||
});
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// CAPEX — Lignes budgétaires par établissement
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
export const capexLignes = mysqlTable("capex_lignes", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
annee: int("annee").notNull(),
|
||||
etablissementCode: varchar("etablissementCode", { length: 50 }).notNull(),
|
||||
cle: varchar("cle", { length: 100 }).notNull(),
|
||||
// cles possibles: renouvellement_2027 | machines_supplementaires | appel_malade
|
||||
// | telephonie | wifi | video_surveillance | copieurs | visio | autres | commentaires
|
||||
montant: decimal("montant", { precision: 12, scale: 2 }),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
|
||||
});
|
||||
|
||||
export type CapexLigne = typeof capexLignes.$inferSelect;
|
||||
export type InsertCapexLigne = typeof capexLignes.$inferInsert;
|
||||
Reference in New Issue
Block a user