feat(migration): reset DB to match new schema
This commit is contained in:
parent
eeaf8daf4a
commit
b714a460f0
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- You are about to drop the column `dark_mode` on the `preferences` table. All the data in the column will be lost.
|
||||||
|
- You are about to drop the column `employee_list_display` on the `preferences` table. All the data in the column will be lost.
|
||||||
|
- You are about to drop the column `lang_switch` on the `preferences` table. All the data in the column will be lost.
|
||||||
|
- You are about to drop the column `lefty_mode` on the `preferences` table. All the data in the column will be lost.
|
||||||
|
- You are about to drop the column `timesheet_display` on the `preferences` table. All the data in the column will be lost.
|
||||||
|
- You are about to drop the column `validation_display` on the `preferences` table. All the data in the column will be lost.
|
||||||
|
- The `notifications` column on the `preferences` table would be dropped and recreated. This will lead to data loss if there is data in the column.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "preferences" DROP COLUMN "dark_mode",
|
||||||
|
DROP COLUMN "employee_list_display",
|
||||||
|
DROP COLUMN "lang_switch",
|
||||||
|
DROP COLUMN "lefty_mode",
|
||||||
|
DROP COLUMN "timesheet_display",
|
||||||
|
DROP COLUMN "validation_display",
|
||||||
|
ADD COLUMN "display_language" TEXT NOT NULL DEFAULT 'fr-FR',
|
||||||
|
ADD COLUMN "is_dark_mode" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
ADD COLUMN "is_employee_list_grid" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
ADD COLUMN "is_lefty_mode" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
ADD COLUMN "is_timesheet_approval_grid" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
DROP COLUMN "notifications",
|
||||||
|
ADD COLUMN "notifications" BOOLEAN NOT NULL DEFAULT true;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "user_module_access" (
|
||||||
|
"id" SERIAL NOT NULL,
|
||||||
|
"user_id" UUID NOT NULL,
|
||||||
|
"timesheets" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"timesheets_approval" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"employee_list" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"employee_management" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"personal_profile" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"dashboard" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
|
||||||
|
CONSTRAINT "user_module_access_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "user_module_access_user_id_key" ON "user_module_access"("user_id");
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "user_module_access" ADD CONSTRAINT "user_module_access_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
@ -249,6 +249,7 @@ model Expenses {
|
||||||
|
|
||||||
archive ExpensesArchive[] @relation("ExpensesToArchive")
|
archive ExpensesArchive[] @relation("ExpensesToArchive")
|
||||||
|
|
||||||
|
@@unique([timesheet_id, date, amount, mileage], name: "unique_ts_id_date_amount_mileage")
|
||||||
@@map("expenses")
|
@@map("expenses")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -346,7 +347,7 @@ model Preferences {
|
||||||
user Users @relation("UserPreferences", fields: [user_id], references: [id])
|
user Users @relation("UserPreferences", fields: [user_id], references: [id])
|
||||||
user_id String @unique @db.Uuid
|
user_id String @unique @db.Uuid
|
||||||
|
|
||||||
notifications Int @default(0)
|
notifications Boolean @default(true)
|
||||||
is_dark_mode Boolean @default(false)
|
is_dark_mode Boolean @default(false)
|
||||||
display_language String @default("fr-FR") //'fr-FR' | 'en-CA';
|
display_language String @default("fr-FR") //'fr-FR' | 'en-CA';
|
||||||
is_lefty_mode Boolean @default(false)
|
is_lefty_mode Boolean @default(false)
|
||||||
|
|
|
||||||
63
scripts/data/export_employee_table.csv
Normal file
63
scripts/data/export_employee_table.csv
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
"email","first_name","last_name","phone_number"
|
||||||
|
"mickaelp@targointernet.com","Mickael","Poulin","(514) 825 - 9730"
|
||||||
|
"simon@targointernet.com","Simon","Clot-Gagnon","(514) 894 - 3632"
|
||||||
|
"eric@targointernet.com","Eric","Wilson","(438) 229 - 4086"
|
||||||
|
"jonathanlussier1@gmail.com","Jonathan","Soulières","(514) 461 - 3716"
|
||||||
|
"Carmen@targointernet.com","Carmen","Ouellet","(514) 448 - 0773"
|
||||||
|
"patrickm@targointernet.com","Patrick","Moise","(514) 949 - 3082"
|
||||||
|
"malika@targointernet.com","Malika","Charest","(819) 609 - 3894"
|
||||||
|
"marcandre@targointernet.com","Marc-Andre","Henrico","(514) 448 - 0773"
|
||||||
|
"maxim@targointernet.com","Maxim","Murray Gendron","(514) 705 - 8208"
|
||||||
|
"philips@targointernet.com","Philip","St-Amour","(450) 601 - 8112"
|
||||||
|
"jeanpierre@targointernet.com","Jean-Pierre","Bourdon","(514) 863 - 7414"
|
||||||
|
"jayson@targointernet.com","Jayson","Blais-Vallières","(438) 390 - 3679"
|
||||||
|
"jonathans@targointernet.com","Jonathan","Soulard","(514) 714 - 2647"
|
||||||
|
"louism@targointernet.com","Louis","Morneau","(514) 715 - 1182"
|
||||||
|
"joseeannes@targointernet.com","Josée-Anne","Soulard","(438) 410 - 1779"
|
||||||
|
"louisgs@targointernet.com","Louis Gabriel","Soulard","(438) 528 - 4486"
|
||||||
|
"david@targointernet.com","David","Richer","(514) 448 - 0773"
|
||||||
|
"laurence@targointernet.com","Laurence","Gobeil","(438) 884 - 7125"
|
||||||
|
"antoinewg@targointernet.com","Antoine","Wilson-Guay","(438) 341 - 9266"
|
||||||
|
"michel@targointernet.com","Michel","Blais","(514) 448 - 0773"
|
||||||
|
"gilles@targointernet.com","Gilles","Drolet","(514) 296 - 2773"
|
||||||
|
"sofiane@targointernet.com","Sofiane","Ameziane","(514) 224 - 3329"
|
||||||
|
"jessy@targointernet.com","Jessy","Sharock","(514) 922 - 7880"
|
||||||
|
"anthonyd@targointernet.com","Anthony","Dion","(438) 872 - 2432"
|
||||||
|
"dahlia@targointernet.com","Dahlia","Tremblay","(438) 867 - 9115"
|
||||||
|
"mathys.renaud00@gmail.com","Mathys","Renaud","(514) 894 - 3632"
|
||||||
|
"pierre@targointernet.com","Pierre","Brodeur","(514) 608 - 4758"
|
||||||
|
"Louis@targointernet.com","Louis-Paul","Bourdon","(514) 448 - 0773"
|
||||||
|
"paulr@targointernet.com","Paul Rommel","Douanla Zebaze","(450) 801 - 2013"
|
||||||
|
"benjamin@targointernet.com","Benjamin","Djanpou","(514) 663 - 9890"
|
||||||
|
"nathanb@targointernet.com","Nathan","Boucher","(514) 929 - 3145"
|
||||||
|
"sylvain@targointernet.com","Sylvain","Delaunais","(438) 408 - 0197"
|
||||||
|
"simong@targointernet.com","Simon","Goyette","(873) 662 - 4408"
|
||||||
|
"patrick@targointernet.com","Patrick","Doucet","(514) 919 - 7102"
|
||||||
|
"robinson@targointernet.com","Robinson","Viaud","(514) 649 - 3063"
|
||||||
|
"frederique@targointernet.com","Frédérique","Soulard","(438) 408 - 6998"
|
||||||
|
"genevieveb@targointernet.com","Geneviève","Bourdon","(514) 607 - 7084"
|
||||||
|
"philippe@targointernet.com","Philippe","Bourdon","(438) 529 - 1940"
|
||||||
|
"aurelieb@targointernet.com","Aurelie","Bourdon","(438) 357 - 5392"
|
||||||
|
"tommy@targointernet.com","Tommy","Larouche Dionne","(514) 949 - 0762"
|
||||||
|
"jeremyb@targointernet.com","Jérémy","Blais","(367) 348 - 2276"
|
||||||
|
"stephane@targointernet.com","Stéphane","Moïse","(514) 949 - 0587"
|
||||||
|
"thaiz@targointernet.com","Thaiz ","Menezes Costa","(514) 915 - 0959"
|
||||||
|
"frederick@targointernet.com","Frederick","Pruneau","(514) 949 - 0340"
|
||||||
|
"stephaneb@targointernet.com","Stéphane","Beaudoin","(438) 524 - 2556"
|
||||||
|
"kadi@targointernet.com","Kadi","Nongtodbo","(514) 621 - 2762"
|
||||||
|
"chantal.blanchette6@gmail.com","Chantal","Blanchette","(514) 889 - 8004"
|
||||||
|
"dominiquel@targointernet.com","Dominique","Liaud","(514) 949 - 0230"
|
||||||
|
"brandonf@targointernet.com","Brandon","Fortin","(438) 828 - 4732"
|
||||||
|
"nicolasd@targointernet.com","Nicolas","Drolet","(514) 951 - 4750"
|
||||||
|
"matthieuh@targointernet.com","Matthieu","Haineault Gervais","(514) 708 - 2974"
|
||||||
|
"mathieug@targointernet.com","Mathieu","Gagné","(514) 448 - 0773"
|
||||||
|
"marcantoineg@targointernet.com","Marc-Antoine","Girard","(514) 641 - 7676"
|
||||||
|
"djanpoub@targointernet.com","Benjamin (a suprimmer)","Djanpou","(514) 663 - 9890"
|
||||||
|
"samuel@targointernet.com","Samuel","Rolo","(514) 578 - 0324"
|
||||||
|
"mathieu@targointernet.com","Mathieu","Lussier","(438) 889 - 4324"
|
||||||
|
"alexandreg@targointernet.com","Alexandre","Germain","(438) 502 - 1801"
|
||||||
|
"fanny@targointernet.com","Fanny","Laroche","(514) 771 - 3341"
|
||||||
|
"samuelr@targointernet.com","Samuel","Rolo","(514) 578 - 0324"
|
||||||
|
"joseph@targointernet.com","Joseph","Muzowindanga","(514)604-3734"
|
||||||
|
"nathanm@targointernet.com","Nathan","Morrisseau","(514) 452 - 0543"
|
||||||
|
"lion@targointernet.com","Lion","Arar","(438) 877 - 9783"
|
||||||
|
63
scripts/data/export_new_employee_table.csv
Normal file
63
scripts/data/export_new_employee_table.csv
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
"employee_number","email","job_title","company","is_supervisor","onboarding","offboarding"
|
||||||
|
"49","mickaelp@targointernet.com","Fusionneur",271585,False,"1656907200000","1724990400000"
|
||||||
|
"54","simon@targointernet.com","Fusionneur",271585,True,"1566446400000",NULL
|
||||||
|
"39","eric@targointernet.com","Fusionneur",271585,False,"1531886400000","1724990400000"
|
||||||
|
"43","jonathanlussier1@gmail.com","Mécanicien",271585,False,"1679284800000","1728014400000"
|
||||||
|
"29","Carmen@targointernet.com","Responsable aux comptes payables",271583,False,"1181880000000",NULL
|
||||||
|
"25","patrickm@targointernet.com","Technicien",271583,True,"1249358400000",NULL
|
||||||
|
"10","malika@targointernet.com","Compte Recevable",271583,False,"1664856000000","1723176000000"
|
||||||
|
"18","marcandre@targointernet.com","Support technique -senior",271583,True,"1497326400000",NULL
|
||||||
|
"28","maxim@targointernet.com","Administrateur réseau",271583,False,"1659931200000",NULL
|
||||||
|
"51","philips@targointernet.com","Fusionneur",271585,False,"1656907200000",NULL
|
||||||
|
"58","jeanpierre@targointernet.com","Technicien",271585,False,"1548216000000",NULL
|
||||||
|
"4","jayson@targointernet.com","Monteur",271583,False,"1564977600000","1720756800000"
|
||||||
|
"44","jonathans@targointernet.com","Responsable des ressources matérielles",271585,False,"1664164800000","1717473600000"
|
||||||
|
"27","louism@targointernet.com","Sysadmin",271583,False,"1392091200000",NULL
|
||||||
|
"45","joseeannes@targointernet.com","Technicien",271585,False,"1665979200000",NULL
|
||||||
|
"46","louisgs@targointernet.com","Technicien",271585,False,"1661745600000","1723176000000"
|
||||||
|
"32","david@targointernet.com","Développeur",271583,False,"1262664000000",NULL
|
||||||
|
"15","laurence@targointernet.com","Responsable du service à la clientèle",271583,True,"1635739200000","1725595200000"
|
||||||
|
"37","antoinewg@targointernet.com","Concepteur",271585,False,"1643688000000",NULL
|
||||||
|
"5","michel@targointernet.com","netadmin / sysadmin",271583,True,"1203393600000",NULL
|
||||||
|
"42","gilles@targointernet.com","Fusionneur",271585,False,"1357531200000",NULL
|
||||||
|
"2","sofiane@targointernet.com","developpeur web",271583,False,"1696219200000","1728014400000"
|
||||||
|
"33","jessy@targointernet.com","Administrateur réseau",271583,False,"1679889600000","1755230400000"
|
||||||
|
"60","anthonyd@targointernet.com","Fusionneur",271585,False,"1713844800000",NULL
|
||||||
|
"35","dahlia@targointernet.com","Agent service à la clientèle",271583,False,"1684900800000","1734667200000"
|
||||||
|
"31","mathys.renaud00@gmail.com","Manoeuvre",271583,False,"1688529600000","1724472000000"
|
||||||
|
"53","pierre@targointernet.com","gestionnaire de projet",271585,True,"1557374400000",NULL
|
||||||
|
"7","Louis@targointernet.com","Président",271583,False,"1104638400000",NULL
|
||||||
|
"49","paulr@targointernet.com","Netadmin",271583,False,"1747022400000","1747800000000"
|
||||||
|
"50","benjamin@targointernet.com","Technicien",271583,False,"1747022400000",NULL
|
||||||
|
"50","nathanb@targointernet.com","Technicien",271585,False,"1653278400000",NULL
|
||||||
|
"55","sylvain@targointernet.com","Fusionneur",271585,False,"1661140800000","1724385600000"
|
||||||
|
"59","simong@targointernet.com","Mécanicien",271585,False,"1712203200000",NULL
|
||||||
|
"13","patrick@targointernet.com","Support Technique",271583,False,"1527652800000",NULL
|
||||||
|
"36","robinson@targointernet.com","Service Clientèle",271583,False,"1694059200000",NULL
|
||||||
|
"41","frederique@targointernet.com","commis à la facturation",271583,False,"1724644800000",NULL
|
||||||
|
"42","genevieveb@targointernet.com","commis à la facturation",271583,False,"1726459200000",NULL
|
||||||
|
"52","philippe@targointernet.com","Fusionneur",271585,False,"1637640000000",NULL
|
||||||
|
"6","aurelieb@targointernet.com","Technicien telecom",271583,False,"1652068800000",NULL
|
||||||
|
"20","tommy@targointernet.com","Technicien",271583,False,"1462766400000",NULL
|
||||||
|
"39","jeremyb@targointernet.com","Tech/Installateur ",271583,False,"1721016000000","1724990400000"
|
||||||
|
"26","stephane@targointernet.com","Technicien télécom",271583,False,"1260936000000",NULL
|
||||||
|
"24","thaiz@targointernet.com","Agente organisationnel",271583,False,"1539316800000",NULL
|
||||||
|
"30","frederick@targointernet.com","Net/Sys/VoIP admin",271583,False,"1295323200000",NULL
|
||||||
|
"37","stephaneb@targointernet.com","Magasinier",271583,False,"1716955200000",NULL
|
||||||
|
"43","kadi@targointernet.com","RH et vente",271583,True,"1726459200000",NULL
|
||||||
|
"46","chantal.blanchette6@gmail.com","Agente au bien-être et service interne",271583,False,"1732507200000",NULL
|
||||||
|
"48","dominiquel@targointernet.com","Vendeur",271583,False,"1746417600000",NULL
|
||||||
|
"45","brandonf@targointernet.com","Technicien",271583,False,"1731556800000","1744948800000"
|
||||||
|
"52","nicolasd@targointernet.com","Programmeur",271583,False,"1748923200000",NULL
|
||||||
|
"51","matthieuh@targointernet.com","Programmeur",271583,False,"1748836800000",NULL
|
||||||
|
"44","mathieug@targointernet.com","Support technique",271583,False,"1728446400000","1734494400000"
|
||||||
|
"47","marcantoineg@targointernet.com","Vendeur",271583,False,"1737950400000","1743048000000"
|
||||||
|
"50","djanpoub@targointernet.com","Technicien",271583,False,"1747713600000","1747800000000"
|
||||||
|
"53","samuel@targointernet.com","Technicien",271583,False,"1749614400000","1749614400000"
|
||||||
|
"38","mathieu@targointernet.com","Dévelopeur",271583,False,"1719288000000","1750305600000"
|
||||||
|
"54","alexandreg@targointernet.com","support",271583,False,"1750651200000","1757649600000"
|
||||||
|
"19","fanny@targointernet.com","Comptable",271583,False,"1751860800000",NULL
|
||||||
|
"53","samuelr@targointernet.com","Technicien",271583,False,"1749614400000","1749614400000"
|
||||||
|
"56","joseph@targointernet.com","Resp. service clients et opérations commerciales",271583,True,"1754395200000",NULL
|
||||||
|
"55","nathanm@targointernet.com","Technicien",271583,False,"1751860800000",NULL
|
||||||
|
"58","lion@targointernet.com","Programmeur",271583,False,"1758513600000",NULL
|
||||||
|
|
|
@ -1,270 +0,0 @@
|
||||||
// // src/scripts/import-employees-from-csv.ts
|
|
||||||
// import { PrismaClient, Roles } from '@prisma/client';
|
|
||||||
// import * as fs from 'fs';
|
|
||||||
// import * as path from 'path';
|
|
||||||
|
|
||||||
// const prisma = new PrismaClient();
|
|
||||||
|
|
||||||
// // ⚙️ Chemin vers ton CSV employees
|
|
||||||
// const CSV_PATH = path.resolve(__dirname, '../../data/export_new_employee_table.csv');
|
|
||||||
|
|
||||||
// // Rôles éligibles pour la table Employees
|
|
||||||
// const ELIGIBLE_ROLES: Roles[] = [
|
|
||||||
// Roles.EMPLOYEE,
|
|
||||||
// Roles.SUPERVISOR,
|
|
||||||
// Roles.HR,
|
|
||||||
// Roles.ACCOUNTING,
|
|
||||||
// Roles.ADMIN,
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// // Type correspondant EXACT aux colonnes de ton CSV
|
|
||||||
// type EmployeeCsvRow = {
|
|
||||||
// employee_number: string;
|
|
||||||
// email: string;
|
|
||||||
// job_title: string;
|
|
||||||
// company: string; // sera converti en number
|
|
||||||
// is_supervisor: string; // "True"/"False" (ou variantes)
|
|
||||||
// onboarding: string; // millis
|
|
||||||
// offboarding: string; // millis ou "NULL"
|
|
||||||
// };
|
|
||||||
|
|
||||||
// // Représentation minimale d'un user
|
|
||||||
// type UserSummary = {
|
|
||||||
// id: string; // UUID
|
|
||||||
// email: string;
|
|
||||||
// role: Roles;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// // ============ Helpers CSV ============
|
|
||||||
|
|
||||||
// function splitCsvLine(line: string): string[] {
|
|
||||||
// const result: string[] = [];
|
|
||||||
// let current = '';
|
|
||||||
// let inQuotes = false;
|
|
||||||
|
|
||||||
// for (let i = 0; i < line.length; i++) {
|
|
||||||
// const char = line[i];
|
|
||||||
|
|
||||||
// if (char === '"') {
|
|
||||||
// // guillemet échappé ""
|
|
||||||
// if (inQuotes && line[i + 1] === '"') {
|
|
||||||
// current += '"';
|
|
||||||
// i++;
|
|
||||||
// } else {
|
|
||||||
// inQuotes = !inQuotes;
|
|
||||||
// }
|
|
||||||
// } else if (char === ',' && !inQuotes) {
|
|
||||||
// result.push(current);
|
|
||||||
// current = '';
|
|
||||||
// } else {
|
|
||||||
// current += char;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// result.push(current);
|
|
||||||
// return result.map((v) => v.trim());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // ============ Helpers de parsing ============
|
|
||||||
|
|
||||||
// function parseBoolean(value: string): boolean {
|
|
||||||
// const v = value.trim().toLowerCase();
|
|
||||||
// return v === 'true' || v === '1' || v === 'yes' || v === 'y' || v === 'oui';
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function parseIntSafe(value: string, fieldName: string): number | null {
|
|
||||||
// const trimmed = value.trim();
|
|
||||||
// if (!trimmed || trimmed.toUpperCase() === 'NULL') return null;
|
|
||||||
|
|
||||||
// const n = Number.parseInt(trimmed, 10);
|
|
||||||
// if (Number.isNaN(n)) {
|
|
||||||
// console.warn(`⚠️ Impossible de parser "${value}" en entier pour le champ ${fieldName}`);
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// return n;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function millisToDate(value: string): Date | null {
|
|
||||||
// const trimmed = value.trim().toUpperCase();
|
|
||||||
// if (!trimmed || trimmed === 'NULL') return null;
|
|
||||||
|
|
||||||
// const ms = Number(trimmed);
|
|
||||||
// if (!Number.isFinite(ms)) {
|
|
||||||
// console.warn(`⚠️ Impossible de parser "${value}" en millis pour une Date`);
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const d = new Date(ms);
|
|
||||||
// // On normalise au jour (minuit UTC)
|
|
||||||
// const normalized = new Date(Date.UTC(
|
|
||||||
// d.getUTCFullYear(),
|
|
||||||
// d.getUTCMonth(),
|
|
||||||
// d.getUTCDate(),
|
|
||||||
// ));
|
|
||||||
|
|
||||||
// return normalized;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // ============ MAIN ============
|
|
||||||
|
|
||||||
// async function main() {
|
|
||||||
// // 1. Lecture du CSV
|
|
||||||
// const fileContent = fs.readFileSync(CSV_PATH, 'utf-8');
|
|
||||||
|
|
||||||
// const lines = fileContent
|
|
||||||
// .split(/\r?\n/)
|
|
||||||
// .map((l) => l.trim())
|
|
||||||
// .filter((l) => l.length > 0);
|
|
||||||
|
|
||||||
// if (lines.length <= 1) {
|
|
||||||
// console.error('CSV vide ou seulement un header');
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const header = splitCsvLine(lines[0]); // ["employee_number","email",...]
|
|
||||||
// const dataLines = lines.slice(1);
|
|
||||||
|
|
||||||
// const csvRows: EmployeeCsvRow[] = dataLines.map((line) => {
|
|
||||||
// const values = splitCsvLine(line);
|
|
||||||
// const row: any = {};
|
|
||||||
|
|
||||||
// header.forEach((col, idx) => {
|
|
||||||
// row[col] = values[idx] ?? '';
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return row as EmployeeCsvRow;
|
|
||||||
// });
|
|
||||||
|
|
||||||
// console.log(`➡️ ${csvRows.length} lignes trouvées dans le CSV employees`);
|
|
||||||
|
|
||||||
// // 2. Récupérer tous les emails du CSV
|
|
||||||
// const emails = Array.from(
|
|
||||||
// new Set(
|
|
||||||
// csvRows
|
|
||||||
// .map((r) => r.email.trim())
|
|
||||||
// .filter((e) => e.length > 0),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
|
|
||||||
// console.log(`➡️ ${emails.length} emails uniques trouvés dans le CSV`);
|
|
||||||
|
|
||||||
// // 3. Charger les users correspondants avec les bons rôles
|
|
||||||
// const users = (await prisma.users.findMany({
|
|
||||||
// where: {
|
|
||||||
// email: { in: emails },
|
|
||||||
// role: { in: ELIGIBLE_ROLES },
|
|
||||||
// },
|
|
||||||
// select: {
|
|
||||||
// id: true,
|
|
||||||
// email: true,
|
|
||||||
// role: true,
|
|
||||||
// },
|
|
||||||
// })) as UserSummary[];
|
|
||||||
|
|
||||||
// console.log(`➡️ ${users.length} users éligibles trouvés dans la DB`);
|
|
||||||
|
|
||||||
// // Map email → user
|
|
||||||
// const userByEmail = new Map<string, UserSummary>();
|
|
||||||
// for (const user of users) {
|
|
||||||
// const key = user.email.trim().toLowerCase();
|
|
||||||
// userByEmail.set(key, user);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 4. Construire les données pour employees.createMany
|
|
||||||
// const employeesToCreate: {
|
|
||||||
// user_id: string;
|
|
||||||
// external_payroll_id: number;
|
|
||||||
// company_code: number;
|
|
||||||
// first_work_day: Date;
|
|
||||||
// last_work_day: Date | null;
|
|
||||||
// job_title: string | null;
|
|
||||||
// is_supervisor: boolean;
|
|
||||||
// supervisor_id?: number | null;
|
|
||||||
// }[] = [];
|
|
||||||
|
|
||||||
// const rowsWithoutUser: EmployeeCsvRow[] = [];
|
|
||||||
// const rowsWithInvalidNumbers: EmployeeCsvRow[] = [];
|
|
||||||
|
|
||||||
// for (const row of csvRows) {
|
|
||||||
// const emailKey = row.email.trim().toLowerCase();
|
|
||||||
// const user = userByEmail.get(emailKey);
|
|
||||||
|
|
||||||
// if (!user) {
|
|
||||||
// rowsWithoutUser.push(row);
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const external_payroll_id = parseIntSafe(row.employee_number, 'external_payroll_id');
|
|
||||||
// const company_code = parseIntSafe(String(row.company), 'company_code');
|
|
||||||
|
|
||||||
// if (external_payroll_id === null || company_code === null) {
|
|
||||||
// rowsWithInvalidNumbers.push(row);
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const first_work_day = millisToDate(row.onboarding);
|
|
||||||
// const last_work_day = millisToDate(row.offboarding);
|
|
||||||
// const is_supervisor = parseBoolean(row.is_supervisor);
|
|
||||||
// const job_title = row.job_title?.trim() || null;
|
|
||||||
|
|
||||||
// if (!first_work_day) {
|
|
||||||
// console.warn(
|
|
||||||
// `⚠️ Date d'onboarding invalide pour ${row.email} (employee_number=${row.employee_number})`,
|
|
||||||
// );
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// employeesToCreate.push({
|
|
||||||
// user_id: user.id,
|
|
||||||
// external_payroll_id,
|
|
||||||
// company_code,
|
|
||||||
// first_work_day,
|
|
||||||
// last_work_day,
|
|
||||||
// job_title,
|
|
||||||
// is_supervisor,
|
|
||||||
// supervisor_id: null, // on pourra gérer ça plus tard si tu as les infos
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// console.log(`➡️ ${employeesToCreate.length} entrées Employees prêtes à être insérées`);
|
|
||||||
|
|
||||||
// if (rowsWithoutUser.length > 0) {
|
|
||||||
// console.warn(`⚠️ ${rowsWithoutUser.length} lignes CSV sans user correspondant (email / rôle) :`);
|
|
||||||
// for (const row of rowsWithoutUser) {
|
|
||||||
// console.warn(
|
|
||||||
// ` - email=${row.email}, employee_number=${row.employee_number}, company=${row.company}`,
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (rowsWithInvalidNumbers.length > 0) {
|
|
||||||
// console.warn(`⚠️ ${rowsWithInvalidNumbers.length} lignes CSV avec ids/compagnies invalides :`);
|
|
||||||
// for (const row of rowsWithInvalidNumbers) {
|
|
||||||
// console.warn(
|
|
||||||
// ` - email=${row.email}, employee_number="${row.employee_number}", company="${row.company}"`,
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (employeesToCreate.length === 0) {
|
|
||||||
// console.warn('⚠️ Aucun Employees à créer, arrêt.');
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 5. Insert en batch
|
|
||||||
// const result = await prisma.employees.createMany({
|
|
||||||
// data: employeesToCreate,
|
|
||||||
// skipDuplicates: true, // évite les erreurs si tu relances le script
|
|
||||||
// });
|
|
||||||
|
|
||||||
// console.log(`✅ ${result.count} employees insérés dans la DB`);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// main()
|
|
||||||
// .catch((err) => {
|
|
||||||
// console.error('❌ Erreur pendant l’import CSV → Employees', err);
|
|
||||||
// process.exit(1);
|
|
||||||
// })
|
|
||||||
// .finally(async () => {
|
|
||||||
// await prisma.$disconnect();
|
|
||||||
// });
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
// // src/scripts/init-preferences.ts
|
|
||||||
// import { PrismaClient } from '@prisma/client';
|
|
||||||
|
|
||||||
// const prisma = new PrismaClient();
|
|
||||||
|
|
||||||
// type UserSummary = {
|
|
||||||
// id: string; // UUID
|
|
||||||
// email: string;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// async function main() {
|
|
||||||
// console.log('➡️ Initialisation des préférences utilisateurs…');
|
|
||||||
|
|
||||||
// // 1. Récupérer tous les users
|
|
||||||
// const users = (await prisma.users.findMany({
|
|
||||||
// select: {
|
|
||||||
// id: true,
|
|
||||||
// email: true,
|
|
||||||
// },
|
|
||||||
// })) as UserSummary[];
|
|
||||||
|
|
||||||
// console.log(`➡️ ${users.length} users trouvés dans la DB`);
|
|
||||||
|
|
||||||
// // 2. Récupérer toutes les préférences existantes
|
|
||||||
// const existingPrefs = await prisma.preferences.findMany({
|
|
||||||
// select: {
|
|
||||||
// user_id: true,
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
|
|
||||||
// const userIdsWithPrefs = new Set(existingPrefs.map((p) => p.user_id));
|
|
||||||
|
|
||||||
// console.log(`➡️ ${existingPrefs.length} users ont déjà des préférences`);
|
|
||||||
|
|
||||||
// // 3. Filtrer les users qui n'ont pas encore de preferences
|
|
||||||
// const usersWithoutPrefs = users.filter((u) => !userIdsWithPrefs.has(u.id));
|
|
||||||
|
|
||||||
// console.log(`➡️ ${usersWithoutPrefs.length} users n'ont pas encore de préférences`);
|
|
||||||
|
|
||||||
// if (usersWithoutPrefs.length === 0) {
|
|
||||||
// console.log('✅ Rien à faire, toutes les préférences sont déjà créées.');
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 4. Préparer les entrées pour createMany
|
|
||||||
// const prefsToCreate = usersWithoutPrefs.map((u) => ({
|
|
||||||
// user_id: u.id,
|
|
||||||
// // tous les autres champs prendront leurs valeurs par défaut (0)
|
|
||||||
// }));
|
|
||||||
|
|
||||||
// // 5. Insertion en batch
|
|
||||||
// const result = await prisma.preferences.createMany({
|
|
||||||
// data: prefsToCreate,
|
|
||||||
// skipDuplicates: true, // sécurité si jamais le script est relancé
|
|
||||||
// });
|
|
||||||
|
|
||||||
// console.log(`✅ ${result.count} préférences créées dans la DB`);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// main()
|
|
||||||
// .catch((err) => {
|
|
||||||
// console.error('❌ Erreur pendant l’initialisation des préférences', err);
|
|
||||||
// process.exit(1);
|
|
||||||
// })
|
|
||||||
// .finally(async () => {
|
|
||||||
// await prisma.$disconnect();
|
|
||||||
// });
|
|
||||||
270
scripts/import-employees-from-csv.ts
Normal file
270
scripts/import-employees-from-csv.ts
Normal file
|
|
@ -0,0 +1,270 @@
|
||||||
|
// src/scripts/import-employees-from-csv.ts
|
||||||
|
import { PrismaClient, Roles } from '@prisma/client';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
const prisma = new PrismaClient();
|
||||||
|
|
||||||
|
// ⚙️ Chemin vers ton CSV employees
|
||||||
|
const CSV_PATH = path.resolve(__dirname, 'data/export_new_employee_table.csv');
|
||||||
|
|
||||||
|
// Rôles éligibles pour la table Employees
|
||||||
|
const ELIGIBLE_ROLES: Roles[] = [
|
||||||
|
Roles.EMPLOYEE,
|
||||||
|
Roles.SUPERVISOR,
|
||||||
|
Roles.HR,
|
||||||
|
Roles.ACCOUNTING,
|
||||||
|
Roles.ADMIN,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Type correspondant EXACT aux colonnes de ton CSV
|
||||||
|
type EmployeeCsvRow = {
|
||||||
|
employee_number: string;
|
||||||
|
email: string;
|
||||||
|
job_title: string;
|
||||||
|
company: string; // sera converti en number
|
||||||
|
is_supervisor: string; // "True"/"False" (ou variantes)
|
||||||
|
onboarding: string; // millis
|
||||||
|
offboarding: string; // millis ou "NULL"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Représentation minimale d'un user
|
||||||
|
type UserSummary = {
|
||||||
|
id: string; // UUID
|
||||||
|
email: string;
|
||||||
|
role: Roles;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============ Helpers CSV ============
|
||||||
|
|
||||||
|
function splitCsvLine(line: string): string[] {
|
||||||
|
const result: string[] = [];
|
||||||
|
let current = '';
|
||||||
|
let inQuotes = false;
|
||||||
|
|
||||||
|
for (let i = 0; i < line.length; i++) {
|
||||||
|
const char = line[i];
|
||||||
|
|
||||||
|
if (char === '"') {
|
||||||
|
// guillemet échappé ""
|
||||||
|
if (inQuotes && line[i + 1] === '"') {
|
||||||
|
current += '"';
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
inQuotes = !inQuotes;
|
||||||
|
}
|
||||||
|
} else if (char === ',' && !inQuotes) {
|
||||||
|
result.push(current);
|
||||||
|
current = '';
|
||||||
|
} else {
|
||||||
|
current += char;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.push(current);
|
||||||
|
return result.map((v) => v.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============ Helpers de parsing ============
|
||||||
|
|
||||||
|
function parseBoolean(value: string): boolean {
|
||||||
|
const v = value.trim().toLowerCase();
|
||||||
|
return v === 'true' || v === '1' || v === 'yes' || v === 'y' || v === 'oui';
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseIntSafe(value: string, fieldName: string): number | null {
|
||||||
|
const trimmed = value.trim();
|
||||||
|
if (!trimmed || trimmed.toUpperCase() === 'NULL') return null;
|
||||||
|
|
||||||
|
const n = Number.parseInt(trimmed, 10);
|
||||||
|
if (Number.isNaN(n)) {
|
||||||
|
console.warn(`⚠️ Impossible de parser "${value}" en entier pour le champ ${fieldName}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
function millisToDate(value: string): Date | null {
|
||||||
|
const trimmed = value.trim().toUpperCase();
|
||||||
|
if (!trimmed || trimmed === 'NULL') return null;
|
||||||
|
|
||||||
|
const ms = Number(trimmed);
|
||||||
|
if (!Number.isFinite(ms)) {
|
||||||
|
console.warn(`⚠️ Impossible de parser "${value}" en millis pour une Date`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const d = new Date(ms);
|
||||||
|
// On normalise au jour (minuit UTC)
|
||||||
|
const normalized = new Date(Date.UTC(
|
||||||
|
d.getUTCFullYear(),
|
||||||
|
d.getUTCMonth(),
|
||||||
|
d.getUTCDate(),
|
||||||
|
));
|
||||||
|
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============ MAIN ============
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
// 1. Lecture du CSV
|
||||||
|
const fileContent = fs.readFileSync(CSV_PATH, 'utf-8');
|
||||||
|
|
||||||
|
const lines = fileContent
|
||||||
|
.split(/\r?\n/)
|
||||||
|
.map((l) => l.trim())
|
||||||
|
.filter((l) => l.length > 0);
|
||||||
|
|
||||||
|
if (lines.length <= 1) {
|
||||||
|
console.error('CSV vide ou seulement un header');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const header = splitCsvLine(lines[0]); // ["employee_number","email",...]
|
||||||
|
const dataLines = lines.slice(1);
|
||||||
|
|
||||||
|
const csvRows: EmployeeCsvRow[] = dataLines.map((line) => {
|
||||||
|
const values = splitCsvLine(line);
|
||||||
|
const row: any = {};
|
||||||
|
|
||||||
|
header.forEach((col, idx) => {
|
||||||
|
row[col] = values[idx] ?? '';
|
||||||
|
});
|
||||||
|
|
||||||
|
return row as EmployeeCsvRow;
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`➡️ ${csvRows.length} lignes trouvées dans le CSV employees`);
|
||||||
|
|
||||||
|
// 2. Récupérer tous les emails du CSV
|
||||||
|
const emails = Array.from(
|
||||||
|
new Set(
|
||||||
|
csvRows
|
||||||
|
.map((r) => r.email.trim())
|
||||||
|
.filter((e) => e.length > 0),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(`➡️ ${emails.length} emails uniques trouvés dans le CSV`);
|
||||||
|
|
||||||
|
// 3. Charger les users correspondants avec les bons rôles
|
||||||
|
const users = (await prisma.users.findMany({
|
||||||
|
where: {
|
||||||
|
email: { in: emails },
|
||||||
|
role: { in: ELIGIBLE_ROLES },
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
email: true,
|
||||||
|
role: true,
|
||||||
|
},
|
||||||
|
})) as UserSummary[];
|
||||||
|
|
||||||
|
console.log(`➡️ ${users.length} users éligibles trouvés dans la DB`);
|
||||||
|
|
||||||
|
// Map email → user
|
||||||
|
const userByEmail = new Map<string, UserSummary>();
|
||||||
|
for (const user of users) {
|
||||||
|
const key = user.email.trim().toLowerCase();
|
||||||
|
userByEmail.set(key, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Construire les données pour employees.createMany
|
||||||
|
const employeesToCreate: {
|
||||||
|
user_id: string;
|
||||||
|
external_payroll_id: number;
|
||||||
|
company_code: number;
|
||||||
|
first_work_day: Date;
|
||||||
|
last_work_day: Date | null;
|
||||||
|
job_title: string | null;
|
||||||
|
is_supervisor: boolean;
|
||||||
|
supervisor_id?: number | null;
|
||||||
|
}[] = [];
|
||||||
|
|
||||||
|
const rowsWithoutUser: EmployeeCsvRow[] = [];
|
||||||
|
const rowsWithInvalidNumbers: EmployeeCsvRow[] = [];
|
||||||
|
|
||||||
|
for (const row of csvRows) {
|
||||||
|
const emailKey = row.email.trim().toLowerCase();
|
||||||
|
const user = userByEmail.get(emailKey);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
rowsWithoutUser.push(row);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const external_payroll_id = parseIntSafe(row.employee_number, 'external_payroll_id');
|
||||||
|
const company_code = parseIntSafe(String(row.company), 'company_code');
|
||||||
|
|
||||||
|
if (external_payroll_id === null || company_code === null) {
|
||||||
|
rowsWithInvalidNumbers.push(row);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const first_work_day = millisToDate(row.onboarding);
|
||||||
|
const last_work_day = millisToDate(row.offboarding);
|
||||||
|
const is_supervisor = parseBoolean(row.is_supervisor);
|
||||||
|
const job_title = row.job_title?.trim() || null;
|
||||||
|
|
||||||
|
if (!first_work_day) {
|
||||||
|
console.warn(
|
||||||
|
`⚠️ Date d'onboarding invalide pour ${row.email} (employee_number=${row.employee_number})`,
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
employeesToCreate.push({
|
||||||
|
user_id: user.id,
|
||||||
|
external_payroll_id,
|
||||||
|
company_code,
|
||||||
|
first_work_day,
|
||||||
|
last_work_day,
|
||||||
|
job_title,
|
||||||
|
is_supervisor,
|
||||||
|
supervisor_id: null, // on pourra gérer ça plus tard si tu as les infos
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`➡️ ${employeesToCreate.length} entrées Employees prêtes à être insérées`);
|
||||||
|
|
||||||
|
if (rowsWithoutUser.length > 0) {
|
||||||
|
console.warn(`⚠️ ${rowsWithoutUser.length} lignes CSV sans user correspondant (email / rôle) :`);
|
||||||
|
for (const row of rowsWithoutUser) {
|
||||||
|
console.warn(
|
||||||
|
` - email=${row.email}, employee_number=${row.employee_number}, company=${row.company}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rowsWithInvalidNumbers.length > 0) {
|
||||||
|
console.warn(`⚠️ ${rowsWithInvalidNumbers.length} lignes CSV avec ids/compagnies invalides :`);
|
||||||
|
for (const row of rowsWithInvalidNumbers) {
|
||||||
|
console.warn(
|
||||||
|
` - email=${row.email}, employee_number="${row.employee_number}", company="${row.company}"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (employeesToCreate.length === 0) {
|
||||||
|
console.warn('⚠️ Aucun Employees à créer, arrêt.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Insert en batch
|
||||||
|
const result = await prisma.employees.createMany({
|
||||||
|
data: employeesToCreate,
|
||||||
|
skipDuplicates: true, // évite les erreurs si tu relances le script
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`✅ ${result.count} employees insérés dans la DB`);
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
|
.catch((err) => {
|
||||||
|
console.error('❌ Erreur pendant l’import CSV → Employees', err);
|
||||||
|
process.exit(1);
|
||||||
|
})
|
||||||
|
.finally(async () => {
|
||||||
|
await prisma.$disconnect();
|
||||||
|
});
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
// const prisma = new PrismaClient();
|
// const prisma = new PrismaClient();
|
||||||
|
|
||||||
// // ⚙️ Chemin vers ton CSV (à adapter selon où tu le mets)
|
// // ⚙️ Chemin vers ton CSV (à adapter selon où tu le mets)
|
||||||
// const CSV_PATH = path.resolve(__dirname, '../../data/export_employee_table.csv');
|
// const CSV_PATH = path.resolve(__dirname, 'data/export_employee_table.csv');
|
||||||
|
|
||||||
// // Type aligné sur les colonnes du CSV
|
// // Type aligné sur les colonnes du CSV
|
||||||
// type CsvUserRow = {
|
// type CsvUserRow = {
|
||||||
67
scripts/init-preferences.ts
Normal file
67
scripts/init-preferences.ts
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
// src/scripts/init-preferences.ts
|
||||||
|
import { PrismaClient } from '@prisma/client';
|
||||||
|
|
||||||
|
const prisma = new PrismaClient();
|
||||||
|
|
||||||
|
type UserSummary = {
|
||||||
|
id: string; // UUID
|
||||||
|
email: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
console.log('➡️ Initialisation des préférences utilisateurs…');
|
||||||
|
|
||||||
|
// 1. Récupérer tous les users
|
||||||
|
const users = (await prisma.users.findMany({
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
email: true,
|
||||||
|
},
|
||||||
|
})) as UserSummary[];
|
||||||
|
|
||||||
|
console.log(`➡️ ${users.length} users trouvés dans la DB`);
|
||||||
|
|
||||||
|
// 2. Récupérer toutes les préférences existantes
|
||||||
|
const existingPrefs = await prisma.preferences.findMany({
|
||||||
|
select: {
|
||||||
|
user_id: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const userIdsWithPrefs = new Set(existingPrefs.map((p) => p.user_id));
|
||||||
|
|
||||||
|
console.log(`➡️ ${existingPrefs.length} users ont déjà des préférences`);
|
||||||
|
|
||||||
|
// 3. Filtrer les users qui n'ont pas encore de preferences
|
||||||
|
const usersWithoutPrefs = users.filter((u) => !userIdsWithPrefs.has(u.id));
|
||||||
|
|
||||||
|
console.log(`➡️ ${usersWithoutPrefs.length} users n'ont pas encore de préférences`);
|
||||||
|
|
||||||
|
if (usersWithoutPrefs.length === 0) {
|
||||||
|
console.log('✅ Rien à faire, toutes les préférences sont déjà créées.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Préparer les entrées pour createMany
|
||||||
|
const prefsToCreate = usersWithoutPrefs.map((u) => ({
|
||||||
|
user_id: u.id,
|
||||||
|
// tous les autres champs prendront leurs valeurs par défaut (0)
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 5. Insertion en batch
|
||||||
|
const result = await prisma.preferences.createMany({
|
||||||
|
data: prefsToCreate,
|
||||||
|
skipDuplicates: true, // sécurité si jamais le script est relancé
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`✅ ${result.count} préférences créées dans la DB`);
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
|
.catch((err) => {
|
||||||
|
console.error('❌ Erreur pendant l’initialisation des préférences', err);
|
||||||
|
process.exit(1);
|
||||||
|
})
|
||||||
|
.finally(async () => {
|
||||||
|
await prisma.$disconnect();
|
||||||
|
});
|
||||||
|
|
@ -1,165 +1,165 @@
|
||||||
// import { PrismaClient as Prisma } from "@prisma/client";
|
import { PrismaClient as Prisma } from "@prisma/client";
|
||||||
// import { PrismaClient as PrismaLegacy } from "@prisma/client-legacy"
|
import { PrismaClient as PrismaLegacy } from "@prisma/client-legacy"
|
||||||
// import { toDateFromString, toHHmmFromDate, toStringFromDate } from "src/common/utils/date-utils";
|
import { toDateFromString, toHHmmFromDate, toStringFromDate } from "src/common/utils/date-utils";
|
||||||
|
|
||||||
// const prisma_legacy = new PrismaLegacy({});
|
const prisma_legacy = new PrismaLegacy({});
|
||||||
// const prisma = new Prisma({});
|
const prisma = new Prisma({});
|
||||||
|
|
||||||
// type NewEmployee = {
|
type NewEmployee = {
|
||||||
// id: number;
|
id: number;
|
||||||
// company_code: number;
|
company_code: number;
|
||||||
// external_payroll_id: number;
|
external_payroll_id: number;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// type OldExpense = {
|
type OldExpense = {
|
||||||
// time_sheet_id: string | null;
|
time_sheet_id: string | null;
|
||||||
// date: string | null;
|
date: string | null;
|
||||||
// code: string | null;
|
code: string | null;
|
||||||
// description: string | null;
|
description: string | null;
|
||||||
// value: number | null;
|
value: number | null;
|
||||||
// status: boolean | null;
|
status: boolean | null;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// export const extractOldExpenses = async () => {
|
export const extractOldExpenses = async () => {
|
||||||
// for (let id = 1; id <= 61; id++) {
|
for (let id = 1; id <= 61; id++) {
|
||||||
|
|
||||||
// console.log(`Start of Expense migration ***************************************************************`);
|
console.log(`Start of Expense migration ***************************************************************`);
|
||||||
|
|
||||||
// const new_employee = await findOneNewEmployee(id);
|
const new_employee = await findOneNewEmployee(id);
|
||||||
// console.log(`Employee ${id} found in new DB`);
|
console.log(`Employee ${id} found in new DB`);
|
||||||
|
|
||||||
// const new_timesheets = await findManyNewTimesheets(new_employee.id);
|
const new_timesheets = await findManyNewTimesheets(new_employee.id);
|
||||||
// console.log(`New Timesheets found for employee ${id}`);
|
console.log(`New Timesheets found for employee ${id}`);
|
||||||
|
|
||||||
// const old_employee_id = await findOneOldEmployee(new_employee);
|
const old_employee_id = await findOneOldEmployee(new_employee);
|
||||||
// console.log(`Employee ${new_employee.id} found in old DB`);
|
console.log(`Employee ${new_employee.id} found in old DB`);
|
||||||
|
|
||||||
// const old_timesheets = await findManyOldTimesheets(old_employee_id);
|
const old_timesheets = await findManyOldTimesheets(old_employee_id);
|
||||||
// console.log(`Timesheets for employee ${old_employee_id}/${new_employee.id} found in old DB`);
|
console.log(`Timesheets for employee ${old_employee_id}/${new_employee.id} found in old DB`);
|
||||||
|
|
||||||
// console.log('Start of Expense creation*****************************************************************');
|
console.log('Start of Expense creation*****************************************************************');
|
||||||
// for (const old_timesheet of old_timesheets) {
|
for (const old_timesheet of old_timesheets) {
|
||||||
// if (!old_timesheet.start_date) continue;
|
if (!old_timesheet.start_date) continue;
|
||||||
// const new_timesheet = new_timesheets.find((ts) => ts.start_date.getTime() === old_timesheet.start_date!.getTime());
|
const new_timesheet = new_timesheets.find((ts) => ts.start_date.getTime() === old_timesheet.start_date!.getTime());
|
||||||
// if (!new_timesheet) {
|
if (!new_timesheet) {
|
||||||
// console.warn(`No new timesheet matching legacy timesheet ${old_timesheet.id}`);
|
console.warn(`No new timesheet matching legacy timesheet ${old_timesheet.id}`);
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
// const old_expenses = await prisma_legacy.expenses.findMany({
|
const old_expenses = await prisma_legacy.expenses.findMany({
|
||||||
// where: { time_sheet_id: old_timesheet.id },
|
where: { time_sheet_id: old_timesheet.id },
|
||||||
// select: {
|
select: {
|
||||||
// time_sheet_id: true,
|
time_sheet_id: true,
|
||||||
// date: true,
|
date: true,
|
||||||
// code: true,
|
code: true,
|
||||||
// description: true,
|
description: true,
|
||||||
// value: true,
|
value: true,
|
||||||
// status: true,
|
status: true,
|
||||||
|
|
||||||
// },
|
},
|
||||||
// });
|
});
|
||||||
// await createManyNewExpenses(new_timesheet.id, old_expenses);
|
await createManyNewExpenses(new_timesheet.id, old_expenses);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// }
|
}
|
||||||
// await prisma_legacy.$disconnect();
|
await prisma_legacy.$disconnect();
|
||||||
// await prisma.$disconnect();
|
await prisma.$disconnect();
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const findOneNewEmployee = async (id: number): Promise<NewEmployee> => {
|
const findOneNewEmployee = async (id: number): Promise<NewEmployee> => {
|
||||||
// const new_employee = await prisma.employees.findUnique({
|
const new_employee = await prisma.employees.findUnique({
|
||||||
// where: { id: id },
|
where: { id: id },
|
||||||
// select: {
|
select: {
|
||||||
// id: true,
|
id: true,
|
||||||
// company_code: true,
|
company_code: true,
|
||||||
// external_payroll_id: true,
|
external_payroll_id: true,
|
||||||
// },
|
},
|
||||||
// });
|
});
|
||||||
// if (!new_employee) throw new Error(`New Employee with id ${id} not found`)
|
if (!new_employee) throw new Error(`New Employee with id ${id} not found`)
|
||||||
// return new_employee;
|
return new_employee;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const findOneOldEmployee = async (new_employee: NewEmployee): Promise<string> => {
|
const findOneOldEmployee = async (new_employee: NewEmployee): Promise<string> => {
|
||||||
// const old_employee = await prisma_legacy.employees.findFirst({
|
const old_employee = await prisma_legacy.employees.findFirst({
|
||||||
// where: {
|
where: {
|
||||||
// company: new_employee.company_code,
|
company: new_employee.company_code,
|
||||||
// employee_number: new_employee.external_payroll_id.toString(),
|
employee_number: new_employee.external_payroll_id.toString(),
|
||||||
// },
|
},
|
||||||
// select: {
|
select: {
|
||||||
// id: true,
|
id: true,
|
||||||
// },
|
},
|
||||||
// });
|
});
|
||||||
// if (!old_employee) throw new Error(`Old Employee not found`);
|
if (!old_employee) throw new Error(`Old Employee not found`);
|
||||||
// return old_employee.id;
|
return old_employee.id;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const findManyOldTimesheets = async (old_employee_id: string) => {
|
const findManyOldTimesheets = async (old_employee_id: string) => {
|
||||||
// const old_timesheets = await prisma_legacy.time_sheets.findMany({
|
const old_timesheets = await prisma_legacy.time_sheets.findMany({
|
||||||
// where: { employee_id: old_employee_id },
|
where: { employee_id: old_employee_id },
|
||||||
// select: { id: true, start_date: true, status: true }
|
select: { id: true, start_date: true, status: true }
|
||||||
// });
|
});
|
||||||
// return old_timesheets;
|
return old_timesheets;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const findManyNewTimesheets = async (employee_id: number) => {
|
const findManyNewTimesheets = async (employee_id: number) => {
|
||||||
// const timesheets = await prisma.timesheets.findMany({
|
const timesheets = await prisma.timesheets.findMany({
|
||||||
// where: { employee_id: employee_id },
|
where: { employee_id: employee_id },
|
||||||
// select: { id: true, start_date: true }
|
select: { id: true, start_date: true }
|
||||||
// })
|
})
|
||||||
// return timesheets;
|
return timesheets;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const createManyNewExpenses = async (timesheet_id: number, old_expenses: OldExpense[]) => {
|
const createManyNewExpenses = async (timesheet_id: number, old_expenses: OldExpense[]) => {
|
||||||
// for (const old_expense of old_expenses) {
|
for (const old_expense of old_expenses) {
|
||||||
// let mileage: number = 0;
|
let mileage: number = 0;
|
||||||
// let amount: number = old_expense.value ?? 0;
|
let amount: number = old_expense.value ?? 0;
|
||||||
// if (old_expense.code === 'G503') {
|
if (old_expense.code === 'G503') {
|
||||||
// mileage = old_expense.value!;
|
mileage = old_expense.value!;
|
||||||
// amount = mileage * 0.72;
|
amount = mileage * 0.72;
|
||||||
// }
|
}
|
||||||
// if (mileage < 0 || amount < 0) {
|
if (mileage < 0 || amount < 0) {
|
||||||
// console.warn(`expense of value less than '0' found`)
|
console.warn(`expense of value less than '0' found`)
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if (old_expense.date == null) {
|
if (old_expense.date == null) {
|
||||||
// console.warn(`Expense date invalid ${old_expense.date}`);
|
console.warn(`Expense date invalid ${old_expense.date}`);
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
// const date = toDateFromString(old_expense.date);
|
const date = toDateFromString(old_expense.date);
|
||||||
|
|
||||||
// if (old_expense.status == null) {
|
if (old_expense.status == null) {
|
||||||
// console.warn(`status null for legacy expense ${old_expense}`);
|
console.warn(`status null for legacy expense ${old_expense}`);
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if (old_expense.code == null) {
|
if (old_expense.code == null) {
|
||||||
// console.warn(`Code null for legacy expense ${old_expense.code}`);
|
console.warn(`Code null for legacy expense ${old_expense.code}`);
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
// const bank_code_id = await findBankCodeIdUsingOldCode(old_expense.code);
|
const bank_code_id = await findBankCodeIdUsingOldCode(old_expense.code);
|
||||||
|
|
||||||
// await prisma.expenses.create({
|
await prisma.expenses.upsert({
|
||||||
// // where: { unique_ts_id_date_amount_mileage: { timesheet_id: timesheet_id, date, amount, mileage } },
|
where: { unique_ts_id_date_amount_mileage: { timesheet_id: timesheet_id, date, amount, mileage } },
|
||||||
// // update: {
|
update: {
|
||||||
// // is_approved: old_expense.status,
|
is_approved: old_expense.status,
|
||||||
// // },
|
},
|
||||||
// data: {
|
create: {
|
||||||
// date: date,
|
date: date,
|
||||||
// comment: old_expense.description ?? '',
|
comment: old_expense.description ?? '',
|
||||||
// timesheet_id: timesheet_id,
|
timesheet_id: timesheet_id,
|
||||||
// bank_code_id: bank_code_id,
|
bank_code_id: bank_code_id,
|
||||||
// amount: amount,
|
amount: amount,
|
||||||
// mileage: mileage,
|
mileage: mileage,
|
||||||
// }
|
}
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const findBankCodeIdUsingOldCode = async (code: string): Promise<number> => {
|
const findBankCodeIdUsingOldCode = async (code: string): Promise<number> => {
|
||||||
// const bank_code = await prisma.bankCodes.findFirst({
|
const bank_code = await prisma.bankCodes.findFirst({
|
||||||
// where: { bank_code: code },
|
where: { bank_code: code },
|
||||||
// select: { id: true },
|
select: { id: true },
|
||||||
// });
|
});
|
||||||
// if (!bank_code) throw new Error(`Bank_code_id not found for Code ${code}`)
|
if (!bank_code) throw new Error(`Bank_code_id not found for Code ${code}`)
|
||||||
// return bank_code.id;
|
return bank_code.id;
|
||||||
// }
|
}
|
||||||
|
|
@ -1,210 +1,210 @@
|
||||||
// import { PrismaClient as PrismaNew } from "@prisma/client";
|
import { PrismaClient as PrismaNew } from "@prisma/client";
|
||||||
// import { PrismaClient as PrismaLegacy } from "@prisma/client-legacy"
|
import { PrismaClient as PrismaLegacy } from "@prisma/client-legacy"
|
||||||
|
|
||||||
// const prisma_legacy = new PrismaLegacy({});
|
const prisma_legacy = new PrismaLegacy({});
|
||||||
// const prisma = new PrismaNew({});
|
const prisma = new PrismaNew({});
|
||||||
|
|
||||||
// type NewEmployee = {
|
type NewEmployee = {
|
||||||
// id: number;
|
id: number;
|
||||||
// company_code: number;
|
company_code: number;
|
||||||
// external_payroll_id: number;
|
external_payroll_id: number;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// type OldShifts = {
|
type OldShifts = {
|
||||||
// time_sheet_id: string | null;
|
time_sheet_id: string | null;
|
||||||
// code: string | null;
|
code: string | null;
|
||||||
// type: string | null;
|
type: string | null;
|
||||||
// date: Date | null;
|
date: Date | null;
|
||||||
// start_time: bigint | null;
|
start_time: bigint | null;
|
||||||
// end_time: bigint | null;
|
end_time: bigint | null;
|
||||||
// comment: string | null;
|
comment: string | null;
|
||||||
// status: boolean | null;
|
status: boolean | null;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// export const extractOldShifts = async () => {
|
export const extractOldShifts = async () => {
|
||||||
// // for (let id = 1; id <= 61; id++) {
|
for (let id = 1; id <= 61; id++) {
|
||||||
// console.log(`Start of shift migration ***************************************************************`);
|
console.log(`Start of shift migration ***************************************************************`);
|
||||||
// const new_employee = await findOneNewEmployee(50);
|
const new_employee = await findOneNewEmployee(id);
|
||||||
// console.log(`Employee ${50} found in new DB`);
|
console.log(`Employee ${id} found in new DB`);
|
||||||
|
|
||||||
// const new_timesheets = await findManyNewTimesheets(new_employee.id);
|
const new_timesheets = await findManyNewTimesheets(new_employee.id);
|
||||||
// console.log(`New Timesheets found for employee ${50}`);
|
console.log(`New Timesheets found for employee ${id}`);
|
||||||
// for (const ts of new_timesheets) {
|
for (const ts of new_timesheets) {
|
||||||
// console.log(`start_date = ${ts.start_date} timesheet_id = ${ts.id}`)
|
console.log(`start_date = ${ts.start_date} timesheet_id = ${ts.id}`)
|
||||||
|
|
||||||
// }
|
}
|
||||||
// console.log('***************************************************************');
|
console.log('***************************************************************');
|
||||||
// const old_employee_id = await findOneOldEmployee(new_employee);
|
const old_employee_id = await findOneOldEmployee(new_employee);
|
||||||
// console.log(`Employee ${new_employee.id} found in old DB`);
|
console.log(`Employee ${new_employee.id} found in old DB`);
|
||||||
|
|
||||||
// const old_timesheets = await findManyOldTimesheets(old_employee_id);
|
const old_timesheets = await findManyOldTimesheets(old_employee_id);
|
||||||
// console.log(`Timesheets for employee ${old_employee_id}/${new_employee.id} found in old DB`);
|
console.log(`Timesheets for employee ${old_employee_id}/${new_employee.id} found in old DB`);
|
||||||
|
|
||||||
// for (const old_timesheet of old_timesheets) {
|
for (const old_timesheet of old_timesheets) {
|
||||||
// if (!old_timesheet.start_date) continue;
|
if (!old_timesheet.start_date) continue;
|
||||||
// const new_timesheet = new_timesheets.find((ts) => ts.start_date.getTime() === old_timesheet.start_date!.getTime());
|
const new_timesheet = new_timesheets.find((ts) => ts.start_date.getTime() === old_timesheet.start_date!.getTime());
|
||||||
// if (!new_timesheet) {
|
if (!new_timesheet) {
|
||||||
// console.warn(`No new timesheet ${new_timesheet} matching legacy timesheet ${old_timesheet.id}`);
|
console.warn(`No new timesheet ${new_timesheet} matching legacy timesheet ${old_timesheet.id}`);
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
// const old_shifts = await prisma_legacy.shifts.findMany({
|
const old_shifts = await prisma_legacy.shifts.findMany({
|
||||||
// where: { time_sheet_id: old_timesheet.id },
|
where: { time_sheet_id: old_timesheet.id },
|
||||||
// select: {
|
select: {
|
||||||
// time_sheet_id: true,
|
time_sheet_id: true,
|
||||||
// code: true,
|
code: true,
|
||||||
// type: true,
|
type: true,
|
||||||
// date: true,
|
date: true,
|
||||||
// start_time: true,
|
start_time: true,
|
||||||
// end_time: true,
|
end_time: true,
|
||||||
// comment: true,
|
comment: true,
|
||||||
// status: true,
|
status: true,
|
||||||
// },
|
},
|
||||||
// });
|
});
|
||||||
// await createManyNewShifts(new_timesheet.id, old_shifts);
|
await createManyNewShifts(new_timesheet.id, old_shifts);
|
||||||
// }
|
}
|
||||||
// // }
|
}
|
||||||
// await prisma_legacy.$disconnect();
|
await prisma_legacy.$disconnect();
|
||||||
// await prisma.$disconnect();
|
await prisma.$disconnect();
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const findOneNewEmployee = async (id: number): Promise<NewEmployee> => {
|
const findOneNewEmployee = async (id: number): Promise<NewEmployee> => {
|
||||||
// const new_employee = await prisma.employees.findUnique({
|
const new_employee = await prisma.employees.findUnique({
|
||||||
// where: { id: id },
|
where: { id: id },
|
||||||
// select: {
|
select: {
|
||||||
// id: true,
|
id: true,
|
||||||
// company_code: true,
|
company_code: true,
|
||||||
// external_payroll_id: true,
|
external_payroll_id: true,
|
||||||
// },
|
},
|
||||||
// });
|
});
|
||||||
// if (!new_employee) throw new Error(`New Employee with id ${id} not found`)
|
if (!new_employee) throw new Error(`New Employee with id ${id} not found`)
|
||||||
// return new_employee;
|
return new_employee;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const findOneOldEmployee = async (new_employee: NewEmployee): Promise<string> => {
|
const findOneOldEmployee = async (new_employee: NewEmployee): Promise<string> => {
|
||||||
// const old_employee = await prisma_legacy.employees.findFirst({
|
const old_employee = await prisma_legacy.employees.findFirst({
|
||||||
// where: {
|
where: {
|
||||||
// company: new_employee.company_code,
|
company: new_employee.company_code,
|
||||||
// employee_number: new_employee.external_payroll_id.toString(),
|
employee_number: new_employee.external_payroll_id.toString(),
|
||||||
// },
|
},
|
||||||
// select: {
|
select: {
|
||||||
// id: true,
|
id: true,
|
||||||
// },
|
},
|
||||||
// });
|
});
|
||||||
// if (!old_employee) throw new Error(`Old Employee not found`);
|
if (!old_employee) throw new Error(`Old Employee not found`);
|
||||||
// return old_employee.id;
|
return old_employee.id;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const findManyOldTimesheets = async (old_employee_id: string) => {
|
const findManyOldTimesheets = async (old_employee_id: string) => {
|
||||||
// const old_timesheets = await prisma_legacy.time_sheets.findMany({
|
const old_timesheets = await prisma_legacy.time_sheets.findMany({
|
||||||
// where: { employee_id: old_employee_id },
|
where: { employee_id: old_employee_id },
|
||||||
// select: { id: true, start_date: true, status: true }
|
select: { id: true, start_date: true, status: true }
|
||||||
// });
|
});
|
||||||
// return old_timesheets;
|
return old_timesheets;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const findManyNewTimesheets = async (employee_id: number) => {
|
const findManyNewTimesheets = async (employee_id: number) => {
|
||||||
// const timesheets = await prisma.timesheets.findMany({
|
const timesheets = await prisma.timesheets.findMany({
|
||||||
// where: { employee_id: employee_id },
|
where: { employee_id: employee_id },
|
||||||
// select: { id: true, start_date: true }
|
select: { id: true, start_date: true }
|
||||||
// })
|
})
|
||||||
// return timesheets;
|
return timesheets;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const createManyNewShifts = async (timesheet_id: number, old_shifts: OldShifts[]) => {
|
const createManyNewShifts = async (timesheet_id: number, old_shifts: OldShifts[]) => {
|
||||||
// for (const old_shift of old_shifts) {
|
for (const old_shift of old_shifts) {
|
||||||
// let is_remote = true;
|
let is_remote = true;
|
||||||
|
|
||||||
// const start = toHHmmfromLegacyTimestamp(old_shift.start_time);
|
const start = toHHmmfromLegacyTimestamp(old_shift.start_time);
|
||||||
// if (old_shift.start_time == null || !start) {
|
if (old_shift.start_time == null || !start) {
|
||||||
// console.warn(`Shift start invalid ${old_shift.start_time}`);
|
console.warn(`Shift start invalid ${old_shift.start_time}`);
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const end = toHHmmfromLegacyTimestamp(old_shift.end_time);
|
const end = toHHmmfromLegacyTimestamp(old_shift.end_time);
|
||||||
// if (old_shift.end_time == null || !end) {
|
if (old_shift.end_time == null || !end) {
|
||||||
// console.warn(`Shift end invalid ${old_shift.end_time}`);
|
console.warn(`Shift end invalid ${old_shift.end_time}`);
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if (old_shift.date == null) {
|
if (old_shift.date == null) {
|
||||||
// console.warn(`Shift date invalid ${old_shift.date}`);
|
console.warn(`Shift date invalid ${old_shift.date}`);
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if (old_shift.status == null) {
|
if (old_shift.status == null) {
|
||||||
// console.warn(`status null for legacy shift ${old_shift}`);
|
console.warn(`status null for legacy shift ${old_shift}`);
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
// if (old_shift.type == null) {
|
if (old_shift.type == null) {
|
||||||
// console.warn(`type null for legacy shift ${old_shift.type}`);
|
console.warn(`type null for legacy shift ${old_shift.type}`);
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if (old_shift.type === 'office') {
|
if (old_shift.type === 'office') {
|
||||||
// is_remote = false;
|
is_remote = false;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if (old_shift.code == null) {
|
if (old_shift.code == null) {
|
||||||
// console.warn(`Code null for legacy shift ${old_shift.code}`);
|
console.warn(`Code null for legacy shift ${old_shift.code}`);
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
// const bank_code_id = await findBankCodeIdUsingOldCode(old_shift.code);
|
const bank_code_id = await findBankCodeIdUsingOldCode(old_shift.code);
|
||||||
// try {
|
try {
|
||||||
// await prisma.shifts.create({
|
await prisma.shifts.create({
|
||||||
// // where: { unique_ts_id_date_start_time: {
|
// where: { unique_ts_id_date_start_time: {
|
||||||
// // timesheet_id,
|
// timesheet_id,
|
||||||
// // date: old_shift.date,
|
// date: old_shift.date,
|
||||||
// // start_time: toDateFromHHmm(start) }},
|
// start_time: toDateFromHHmm(start) }},
|
||||||
// // update: {
|
// update: {
|
||||||
// // start_time: toDateFromHHmm(start),
|
// start_time: toDateFromHHmm(start),
|
||||||
// // end_time: toDateFromHHmm(end),
|
// end_time: toDateFromHHmm(end),
|
||||||
// // comment: old_shift.comment,
|
// comment: old_shift.comment,
|
||||||
// // is_approved: old_shift.status,
|
// is_approved: old_shift.status,
|
||||||
// // is_remote: is_remote,
|
// is_remote: is_remote,
|
||||||
// // bank_code_id: bank_code_id,
|
// bank_code_id: bank_code_id,
|
||||||
// // },
|
// },
|
||||||
// data: {
|
data: {
|
||||||
// date: old_shift.date,
|
date: old_shift.date,
|
||||||
// start_time: toDateFromHHmm(start),
|
start_time: toDateFromHHmm(start),
|
||||||
// end_time: toDateFromHHmm(end),
|
end_time: toDateFromHHmm(end),
|
||||||
// comment: old_shift.comment,
|
comment: old_shift.comment,
|
||||||
// is_approved: old_shift.status,
|
is_approved: old_shift.status,
|
||||||
// is_remote: is_remote,
|
is_remote: is_remote,
|
||||||
// timesheet_id: timesheet_id,
|
timesheet_id: timesheet_id,
|
||||||
// bank_code_id: bank_code_id,
|
bank_code_id: bank_code_id,
|
||||||
// },
|
},
|
||||||
// });
|
});
|
||||||
// } catch (error) {
|
} catch (error) {
|
||||||
// console.log('An error occured during shifts creation');
|
console.log('An error occured during shifts creation');
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const toHHmmfromLegacyTimestamp = (value: bigint | null): string | null => {
|
const toHHmmfromLegacyTimestamp = (value: bigint | null): string | null => {
|
||||||
// if (value == null) return null;
|
if (value == null) return null;
|
||||||
// const date = new Date(Number(value));
|
const date = new Date(Number(value));
|
||||||
// const hh = String(date.getHours()).padStart(2, '0');
|
const hh = String(date.getHours()).padStart(2, '0');
|
||||||
// const mm = String(date.getMinutes()).padStart(2, '0');
|
const mm = String(date.getMinutes()).padStart(2, '0');
|
||||||
// return `${hh}:${mm}`;
|
return `${hh}:${mm}`;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const toDateFromHHmm = (hhmm: string): Date => {
|
const toDateFromHHmm = (hhmm: string): Date => {
|
||||||
// const [hh, mm] = hhmm.split(':');
|
const [hh, mm] = hhmm.split(':');
|
||||||
// const hours = Number(hh);
|
const hours = Number(hh);
|
||||||
// const minutes = Number(mm);
|
const minutes = Number(mm);
|
||||||
// return new Date(Date.UTC(1970, 0, 1, hours, minutes, 0, 0));
|
return new Date(Date.UTC(1970, 0, 1, hours, minutes, 0, 0));
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const findBankCodeIdUsingOldCode = async (code: string): Promise<number> => {
|
const findBankCodeIdUsingOldCode = async (code: string): Promise<number> => {
|
||||||
// if (code === 'G700') {
|
if (code === 'G700') {
|
||||||
// code = 'G104';
|
code = 'G104';
|
||||||
// } else if (code === 'G140') {
|
} else if (code === 'G140') {
|
||||||
// code = 'G56'
|
code = 'G56'
|
||||||
// }
|
}
|
||||||
// const bank_code = await prisma.bankCodes.findFirst({
|
const bank_code = await prisma.bankCodes.findFirst({
|
||||||
// where: { bank_code: code },
|
where: { bank_code: code },
|
||||||
// select: { id: true, bank_code: true },
|
select: { id: true, bank_code: true },
|
||||||
// });
|
});
|
||||||
// if (!bank_code) throw new Error(`Bank_code_id not found for Code ${code}`)
|
if (!bank_code) throw new Error(`Bank_code_id not found for Code ${code}`)
|
||||||
// return bank_code.id;
|
return bank_code.id;
|
||||||
// }
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,118 +1,118 @@
|
||||||
// import { PrismaClient as Prisma } from "@prisma/client";
|
import { PrismaClient as Prisma } from "@prisma/client";
|
||||||
// import { PrismaClient as PrismaLegacy } from "@prisma/client-legacy"
|
import { PrismaClient as PrismaLegacy } from "@prisma/client-legacy"
|
||||||
// import { toStringFromDate } from "src/common/utils/date-utils";
|
import { toStringFromDate } from "src/common/utils/date-utils";
|
||||||
|
|
||||||
|
|
||||||
// type NewEmployee = {
|
type NewEmployee = {
|
||||||
// id: number;
|
id: number;
|
||||||
// company_code: number;
|
company_code: number;
|
||||||
// external_payroll_id: number;
|
external_payroll_id: number;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// type OldTimesheets = {
|
type OldTimesheets = {
|
||||||
// id: string;
|
id: string;
|
||||||
// start_date: Date | null;
|
start_date: Date | null;
|
||||||
// status: boolean | null;
|
status: boolean | null;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const prisma_legacy = new PrismaLegacy({});
|
const prisma_legacy = new PrismaLegacy({});
|
||||||
// const prisma_new = new Prisma({});
|
const prisma_new = new Prisma({});
|
||||||
|
|
||||||
// export const extractOldTimesheets = async () => {
|
export const extractOldTimesheets = async () => {
|
||||||
// for (let id = 1; id <= 61; id++) {
|
for (let id = 1; id <= 61; id++) {
|
||||||
// const new_employee = await findOneNewEmployee(id);
|
const new_employee = await findOneNewEmployee(id);
|
||||||
// console.log(`Employee ${id} found in new DB ${new_employee.external_payroll_id}`);
|
console.log(`Employee ${id} found in new DB ${new_employee.external_payroll_id}`);
|
||||||
|
|
||||||
// const old_employee_id = await findOneOldEmployee(new_employee);
|
const old_employee_id = await findOneOldEmployee(new_employee);
|
||||||
// console.log(`Employee ${new_employee.id} found in old DB`);
|
console.log(`Employee ${new_employee.id} found in old DB`);
|
||||||
|
|
||||||
// const old_timesheets = await findManyOldTimesheets(old_employee_id);
|
const old_timesheets = await findManyOldTimesheets(old_employee_id);
|
||||||
// console.log(` ${old_timesheets.length} Timesheets for employee ${old_employee_id}/${new_employee.id} found in old DB`);
|
console.log(` ${old_timesheets.length} Timesheets for employee ${old_employee_id}/${new_employee.id} found in old DB`);
|
||||||
|
|
||||||
// await createManyNewTimesheets(old_timesheets, new_employee);
|
await createManyNewTimesheets(old_timesheets, new_employee);
|
||||||
// console.log(`${old_timesheets.length} New Timesheets created in new DB for employee ${new_employee.id}`);
|
console.log(`${old_timesheets.length} New Timesheets created in new DB for employee ${new_employee.id}`);
|
||||||
// }
|
}
|
||||||
// await prisma_legacy.$disconnect();
|
await prisma_legacy.$disconnect();
|
||||||
// await prisma_new.$disconnect();
|
await prisma_new.$disconnect();
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const findOneNewEmployee = async (id: number): Promise<NewEmployee> => {
|
const findOneNewEmployee = async (id: number): Promise<NewEmployee> => {
|
||||||
// const new_employee = await prisma_new.employees.findUnique({
|
const new_employee = await prisma_new.employees.findUnique({
|
||||||
// where: { id: id },
|
where: { id: id },
|
||||||
// select: {
|
select: {
|
||||||
// id: true,
|
id: true,
|
||||||
// company_code: true,
|
company_code: true,
|
||||||
// external_payroll_id: true,
|
external_payroll_id: true,
|
||||||
// },
|
},
|
||||||
// });
|
});
|
||||||
// if (!new_employee) throw new Error(`New Employee with id ${id} not found`)
|
if (!new_employee) throw new Error(`New Employee with id ${id} not found`)
|
||||||
// return new_employee;
|
return new_employee;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const findOneOldEmployee = async (new_employee: NewEmployee): Promise<string> => {
|
const findOneOldEmployee = async (new_employee: NewEmployee): Promise<string> => {
|
||||||
// const employee_number = new_employee.external_payroll_id.toString()
|
const employee_number = new_employee.external_payroll_id.toString()
|
||||||
// const old_employee = await prisma_legacy.employees.findFirst({
|
const old_employee = await prisma_legacy.employees.findFirst({
|
||||||
// where: {
|
where: {
|
||||||
// company: new_employee.company_code,
|
company: new_employee.company_code,
|
||||||
// employee_number: employee_number,
|
employee_number: employee_number,
|
||||||
// },
|
},
|
||||||
// select: {
|
select: {
|
||||||
// id: true,
|
id: true,
|
||||||
// },
|
},
|
||||||
// });
|
});
|
||||||
// if (!old_employee) throw new Error(`Old Employee not found`);
|
if (!old_employee) throw new Error(`Old Employee not found`);
|
||||||
// return old_employee.id;
|
return old_employee.id;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const findManyOldTimesheets = async (old_employee_id: string) => {
|
const findManyOldTimesheets = async (old_employee_id: string) => {
|
||||||
// const old_timesheets = await prisma_legacy.time_sheets.findMany({
|
const old_timesheets = await prisma_legacy.time_sheets.findMany({
|
||||||
// where: { employee_id: old_employee_id },
|
where: { employee_id: old_employee_id },
|
||||||
// select: { id: true, start_date: true, status: true }
|
select: { id: true, start_date: true, status: true }
|
||||||
// });
|
});
|
||||||
// if (!old_timesheets) throw new Error(`old Timesheets not found for employee_id ${old_employee_id}`)
|
if (!old_timesheets) throw new Error(`old Timesheets not found for employee_id ${old_employee_id}`)
|
||||||
// return old_timesheets;
|
return old_timesheets;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const createManyNewTimesheets = async (old_timesheets: OldTimesheets[], new_employee: NewEmployee) => {
|
const createManyNewTimesheets = async (old_timesheets: OldTimesheets[], new_employee: NewEmployee) => {
|
||||||
// for (const timesheet of old_timesheets) {
|
for (const timesheet of old_timesheets) {
|
||||||
// if (timesheet.start_date == null) {
|
if (timesheet.start_date == null) {
|
||||||
// console.warn(`start_date invalid for legacy timesheet ${timesheet.id}`);
|
console.warn(`start_date invalid for legacy timesheet ${timesheet.id}`);
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
// if (timesheet.status == null) {
|
if (timesheet.status == null) {
|
||||||
// console.warn(`status null for legacy timesheet ${timesheet.id}`);
|
console.warn(`status null for legacy timesheet ${timesheet.id}`);
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// try {
|
try {
|
||||||
// const new_timesheet = await prisma_new.timesheets.upsert({
|
const new_timesheet = await prisma_new.timesheets.upsert({
|
||||||
// where: { employee_id_start_date: { employee_id: new_employee.id, start_date: timesheet.start_date } },
|
where: { employee_id_start_date: { employee_id: new_employee.id, start_date: timesheet.start_date } },
|
||||||
// update: {
|
update: {
|
||||||
// is_approved: timesheet.status,
|
is_approved: timesheet.status,
|
||||||
// },
|
},
|
||||||
// create: {
|
create: {
|
||||||
// employee_id: new_employee.id,
|
employee_id: new_employee.id,
|
||||||
// start_date: timesheet.start_date,
|
start_date: timesheet.start_date,
|
||||||
// is_approved: timesheet.status,
|
is_approved: timesheet.status,
|
||||||
// },
|
},
|
||||||
// });
|
});
|
||||||
// if (!new_timesheet) throw new Error(
|
if (!new_timesheet) throw new Error(
|
||||||
// `Timesheet with start_date: ${toStringFromDate(timesheet.start_date!)} for employee ${new_employee.id} not created`
|
`Timesheet with start_date: ${toStringFromDate(timesheet.start_date!)} for employee ${new_employee.id} not created`
|
||||||
// );
|
);
|
||||||
// } catch (error) {
|
} catch (error) {
|
||||||
// throw new Error('An error occured during timesheets creation');
|
throw new Error('An error occured during timesheets creation');
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// extractOldTimesheets()
|
extractOldTimesheets()
|
||||||
// .then(() => {
|
.then(() => {
|
||||||
// console.log("Migration completed");
|
console.log("Migration completed");
|
||||||
// })
|
})
|
||||||
// .catch((error) => {
|
.catch((error) => {
|
||||||
// console.error("Migration failed:", error);
|
console.error("Migration failed:", error);
|
||||||
// })
|
})
|
||||||
// .finally(async () => {
|
.finally(async () => {
|
||||||
// await prisma_legacy.$disconnect();
|
await prisma_legacy.$disconnect();
|
||||||
// await prisma_new.$disconnect();
|
await prisma_new.$disconnect();
|
||||||
// });
|
});
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
// // import { extractOldTimesheets } from "scripts/migrate-timesheets";
|
// import { extractOldTimesheets } from "scripts/migrate-timesheets";
|
||||||
// // import { extractOldExpenses } from "scripts/migrate-expenses";
|
// import { extractOldExpenses } from "scripts/migrate-expenses";
|
||||||
// // import { extractOldShifts } from "scripts/migrate-shifts";
|
// import { extractOldShifts } from "scripts/migrate-shifts";
|
||||||
// import { Injectable } from "@nestjs/common";
|
import { Injectable } from "@nestjs/common";
|
||||||
|
|
||||||
// @Injectable()
|
@Injectable()
|
||||||
// export class MigrationService {
|
export class MigrationService {
|
||||||
// constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
// async migrateTimesheets() {
|
async migrateTimesheets() {
|
||||||
// // extractOldTimesheets();
|
// extractOldTimesheets();
|
||||||
// };
|
};
|
||||||
|
|
||||||
// async migrateShifts() {
|
async migrateShifts() {
|
||||||
// // extractOldShifts();
|
// extractOldShifts();
|
||||||
// }
|
}
|
||||||
|
|
||||||
// async migrateExpenses() {
|
async migrateExpenses() {
|
||||||
// // extractOldExpenses();
|
// extractOldExpenses();
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { IsBoolean, IsEnum, IsInt, IsOptional } from "class-validator";
|
import { IsBoolean, IsEnum, IsOptional } from "class-validator";
|
||||||
|
|
||||||
export enum DisplayLanguage {
|
export enum DisplayLanguage {
|
||||||
FR = 'fr-FR',
|
FR = 'fr-FR',
|
||||||
|
|
@ -6,7 +6,7 @@ export enum DisplayLanguage {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PreferencesDto {
|
export class PreferencesDto {
|
||||||
@IsInt() notifications: number;
|
@IsBoolean() notifications: boolean;
|
||||||
@IsOptional() @IsBoolean() is_dark_mode?: boolean;
|
@IsOptional() @IsBoolean() is_dark_mode?: boolean;
|
||||||
@IsEnum(DisplayLanguage) display_language: string;
|
@IsEnum(DisplayLanguage) display_language: string;
|
||||||
@IsBoolean() is_lefty_mode: boolean;
|
@IsBoolean() is_lefty_mode: boolean;
|
||||||
|
|
|
||||||
|
|
@ -6,5 +6,5 @@ export class ModuleAccess {
|
||||||
@IsBoolean() employee_list!: boolean;
|
@IsBoolean() employee_list!: boolean;
|
||||||
@IsBoolean() employee_management!: boolean;
|
@IsBoolean() employee_management!: boolean;
|
||||||
@IsBoolean() personnal_profile!: boolean;
|
@IsBoolean() personnal_profile!: boolean;
|
||||||
@IsBoolean() blocked!: boolean;
|
@IsBoolean() dashboard!: boolean;
|
||||||
}
|
}
|
||||||
|
|
@ -23,8 +23,8 @@ export class AccessGetService {
|
||||||
timesheets_approval: true,
|
timesheets_approval: true,
|
||||||
employee_list: true,
|
employee_list: true,
|
||||||
employee_management: true,
|
employee_management: true,
|
||||||
personnal_profile: true,
|
personal_profile: true,
|
||||||
blocked: true,
|
dashboard: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (!access) return { success: false, error: 'MODULE_ACCESS_NOT_FOUND' };
|
if (!access) return { success: false, error: 'MODULE_ACCESS_NOT_FOUND' };
|
||||||
|
|
@ -34,8 +34,8 @@ export class AccessGetService {
|
||||||
timesheets_approval: access.timesheets_approval,
|
timesheets_approval: access.timesheets_approval,
|
||||||
employee_list: access.employee_list,
|
employee_list: access.employee_list,
|
||||||
employee_management: access.employee_management,
|
employee_management: access.employee_management,
|
||||||
personnal_profile: access.personnal_profile,
|
personnal_profile: access.personal_profile,
|
||||||
blocked: access.blocked,
|
dashboard: access.dashboard,
|
||||||
};
|
};
|
||||||
return { success: true, data: granted_access }
|
return { success: true, data: granted_access }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@ export class AccessUpdateService {
|
||||||
timesheets_approval: true,
|
timesheets_approval: true,
|
||||||
employee_list: true,
|
employee_list: true,
|
||||||
employee_management: true,
|
employee_management: true,
|
||||||
personnal_profile: true,
|
personal_profile: true,
|
||||||
|
dashboard: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (!orignal_access) return { success: false, error: 'MODULE_ACCESS_NOT_FOUND' };
|
if (!orignal_access) return { success: false, error: 'MODULE_ACCESS_NOT_FOUND' };
|
||||||
|
|
@ -36,7 +37,8 @@ export class AccessUpdateService {
|
||||||
timesheets_approval: dto.timesheets_approval,
|
timesheets_approval: dto.timesheets_approval,
|
||||||
employee_list: dto.employee_list,
|
employee_list: dto.employee_list,
|
||||||
employee_management: dto.employee_management,
|
employee_management: dto.employee_management,
|
||||||
personnal_profile: dto.personnal_profile,
|
personal_profile: dto.personnal_profile,
|
||||||
|
dashboard: dto.dashboard,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return { success: true, data: true };
|
return { success: true, data: true };
|
||||||
|
|
@ -60,8 +62,8 @@ export class AccessUpdateService {
|
||||||
timesheets_approval: false,
|
timesheets_approval: false,
|
||||||
employee_list: false,
|
employee_list: false,
|
||||||
employee_management: false,
|
employee_management: false,
|
||||||
personnal_profile: false,
|
personal_profile: false,
|
||||||
blocked: true,
|
dashboard: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user