45 changed files with 1051 additions and 766 deletions
@ -1,444 +1,307 @@ |
|||
const sqlite = require('better-sqlite3') |
|||
const mysql = require('mysql2/promise') |
|||
const bcrypt = require('bcryptjs') |
|||
|
|||
const pool = mysql.createPool({ |
|||
host: '127.0.0.1', |
|||
user: 'root', |
|||
password: '', |
|||
database: 'university', |
|||
waitForConnections: true, |
|||
connectionLimit: 10, |
|||
queueLimit: 0 |
|||
}) |
|||
|
|||
// Construct the database path using the detected IP
|
|||
let dbPath = `./base/data.db`; |
|||
async function createTables() { |
|||
const connection = await pool.getConnection() |
|||
|
|||
// Connect to SQLite database with the initial path
|
|||
let database = new sqlite(dbPath); |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
// Create the users table if it doesn't exist
|
|||
const createUserTableQuery = ` |
|||
CREATE TABLE IF NOT EXISTS users ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
username VARCHAR(200) NOT NULL, |
|||
email VARCHAR(250) NOT NULL UNIQUE, |
|||
password TEXT NOT NULL, |
|||
roles VARCHAR(250) NOT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
|||
); |
|||
` |
|||
database.prepare(createUserTableQuery).run() |
|||
|
|||
// Insert a default admin user if not exists
|
|||
const insertDefaultUserQuery = ` |
|||
INSERT INTO users (username, email, password, roles) |
|||
SELECT 'admin', 'admin@example.com', ?, 'admin' |
|||
WHERE NOT EXISTS (SELECT 1 FROM users WHERE username = 'admin'); |
|||
` |
|||
|
|||
// Hash the password '1234' before storing
|
|||
const hashedPassword = bcrypt.hashSync('123456789', 10) |
|||
database.prepare(insertDefaultUserQuery).run(hashedPassword) |
|||
|
|||
// create table for note status
|
|||
const createStatusTableQuery = ` |
|||
CREATE TABLE IF NOT EXISTS status ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
nom VARCHAR(200) NOT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
|||
); |
|||
` |
|||
database.prepare(createStatusTableQuery).run() |
|||
|
|||
// create table for mention
|
|||
const createMentionTableQuery = ` |
|||
CREATE TABLE IF NOT EXISTS mentions ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
nom VARCHAR(250) NOT NULL, |
|||
uniter VARCHAR(50) NOT NULL, -- Abréviation du nom |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
|||
); |
|||
` |
|||
database.prepare(createMentionTableQuery).run() |
|||
|
|||
// Create the niveau table if it doesn't exist
|
|||
const createNiveauTableQuery = ` |
|||
CREATE TABLE IF NOT EXISTS niveaus ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
nom VARCHAR(50) NOT NULL, -- Exemple: L1, L2, L3, etc. |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
|||
); |
|||
` |
|||
database.prepare(createNiveauTableQuery).run() |
|||
|
|||
// Create the etudiants table if it doesn't exist
|
|||
const createEtudiantsTableQuery = ` |
|||
CREATE TABLE IF NOT EXISTS etudiants ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
nom VARCHAR(250) DEFAULT NULL, |
|||
prenom VARCHAR(250) DEFAULT NULL, |
|||
photos TEXT DEFAULT NULL, |
|||
date_de_naissances DATE DEFAULT NULL, |
|||
niveau VARCHAR(250) NOT NULL, -- Clé étrangère vers niveaus |
|||
annee_scolaire VARCHAR(20) NOT NULL, |
|||
status INTEGER DEFAULT NULL, |
|||
mention_id INTEGER NOT NULL, -- Clé étrangère vers mentions |
|||
num_inscription TEXT NOT NULL, |
|||
sexe VARCHAR(20) DEFAULT NULL, |
|||
cin VARCHAR(250) DEFAULT NULL, |
|||
date_delivrance DEFAULT NULL, |
|||
nationalite DATE DEFAULT NULL, |
|||
annee_bacc DATE DEFAULT NULL, |
|||
serie VARCHAR(20) DEFAULT NULL, |
|||
boursier BOOLEAN DEFAULT FALSE, |
|||
domaine VARCHAR(250) DEFAULT NULL, |
|||
contact VARCHAR(20) DEFAULT NULL, |
|||
parcours VARCHAR(250) DEFAULT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
FOREIGN KEY (status) REFERENCES status(id), |
|||
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
|||
); |
|||
` |
|||
database.prepare(createEtudiantsTableQuery).run() |
|||
|
|||
// Create the notes table if it doesn't exist
|
|||
const createMatiereTableQuery = ` |
|||
CREATE TABLE IF NOT EXISTS matieres ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
nom VARCHAR(250) UNIQUE NOT NULL, |
|||
unite_enseignement VARCHAR(250) NOT NULL, |
|||
credit INTEGER NOT NULL, |
|||
heure INTEGER NOT NULL, |
|||
ue VARCHAR(10) NOT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
|||
); |
|||
` |
|||
database.prepare(createMatiereTableQuery).run() |
|||
|
|||
// Create the semestre table if it doesn't exist
|
|||
const createSemestreTableQuery = ` |
|||
CREATE TABLE IF NOT EXISTS semestres ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
nom VARCHAR(30) NOT NULL, -- Exemple: S1, S2, S3, etc. |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
|||
); |
|||
` |
|||
database.prepare(createSemestreTableQuery).run() |
|||
|
|||
// Create the semestre table if it doesn't exist
|
|||
const createMatiere_mentionTableQuery = ` |
|||
CREATE TABLE IF NOT EXISTS matiere_mention ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
matiere_id INTEGER NOT NULL, -- Clé étrangère vers matieres |
|||
mention_id INTEGER NOT NULL, -- Clé étrangère vers mentions |
|||
FOREIGN KEY (matiere_id) REFERENCES matieres(id), |
|||
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
|||
); |
|||
` |
|||
database.prepare(createMatiere_mentionTableQuery).run() |
|||
|
|||
const createMatiere_semestreTableQuery = ` |
|||
CREATE TABLE IF NOT EXISTS matiere_semestre ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
matiere_id INTEGER NOT NULL, -- Clé étrangère vers matieres |
|||
semestre_id INTEGER NOT NULL, -- Clé étrangère vers semestres |
|||
mention_id INTEGER NOT NULL, -- Clé étrangère vers niveaus |
|||
FOREIGN KEY (matiere_id) REFERENCES matieres(id), |
|||
FOREIGN KEY (semestre_id) REFERENCES semestres(id), |
|||
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
|||
); |
|||
` |
|||
database.prepare(createMatiere_semestreTableQuery).run() |
|||
|
|||
// Create the notes table if it doesn't exist
|
|||
const createNoteTableQuery = ` |
|||
CREATE TABLE IF NOT EXISTS notes ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
etudiant_id INTEGER NOT NULL, -- Clé étrangère vers etudiants |
|||
matiere_id INTEGER NOT NULL, -- Clé étrangère vers matieres |
|||
etudiant_niveau VARCHAR(50) NOT NULL, |
|||
mention_id INTEGER NOT NULL, |
|||
note FLOAT DEFAULT NULL, |
|||
annee_scolaire VARCHAR(50) NOT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
FOREIGN KEY (etudiant_id) REFERENCES etudiants(id), |
|||
FOREIGN KEY (matiere_id) REFERENCES matieres(id) |
|||
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
|||
); |
|||
` |
|||
database.prepare(createNoteTableQuery).run() |
|||
|
|||
// Create the notes second session table if it doesn't exist
|
|||
const createNoteRepechTableQuery = ` |
|||
CREATE TABLE IF NOT EXISTS notesrepech ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
etudiant_id INTEGER NOT NULL, -- Clé étrangère vers etudiants |
|||
matiere_id INTEGER NOT NULL, -- Clé étrangère vers matieres |
|||
etudiant_niveau VARCHAR(50) NOT NULL, |
|||
mention_id INTEGER NOT NULL, |
|||
note FLOAT DEFAULT NULL, |
|||
annee_scolaire VARCHAR(50) NOT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
FOREIGN KEY (etudiant_id) REFERENCES etudiants(id), |
|||
FOREIGN KEY (matiere_id) REFERENCES matieres(id) |
|||
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
|||
); |
|||
` |
|||
database.prepare(createNoteRepechTableQuery).run() |
|||
|
|||
// create table for note système
|
|||
const createNoteSystemeTableQuery = ` |
|||
CREATE TABLE IF NOT EXISTS notesystems ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
admis FLOAT NOT NULL DEFAULT 10, |
|||
redouble FLOAT NOT NULL DEFAULT 9.99, |
|||
renvoyer FLOAT NOT NULL DEFAULT 7.99, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
|||
); |
|||
` |
|||
database.prepare(createNoteSystemeTableQuery).run() |
|||
|
|||
// create table année scolaire
|
|||
const createAnneeScolaireTableQuery = ` |
|||
CREATE TABLE IF NOT EXISTS anneescolaire ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
code VARCHAR(30) NOT NULL, |
|||
debut DATE NOT NULL, |
|||
fin DATE NOT NULL, |
|||
is_current INTEGER DEFAULT 0, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
|||
); |
|||
` |
|||
database.prepare(createAnneeScolaireTableQuery).run() |
|||
|
|||
// create traitement systeme
|
|||
const createTraitementSystemQuery = ` |
|||
CREATE TABLE IF NOT EXISTS traitmentsystem ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
code VARCHAR(30) NOT NULL, |
|||
debut DATE NOT NULL, |
|||
fin DATE NOT NULL, |
|||
is_finished INTEGER DEFAULT 0, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
|||
); |
|||
` |
|||
database.prepare(createTraitementSystemQuery).run() |
|||
|
|||
const createNecessaryParameterTableQuery = ` |
|||
CREATE TABLE IF NOT EXISTS nessesaryTable ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
uniter_heure INTEGER NOT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
|||
); |
|||
` |
|||
database.prepare(createNecessaryParameterTableQuery).run() |
|||
|
|||
const createMatiereEnseignantTableQuery = ` |
|||
CREATE TABLE IF NOT EXISTS matiereEnseignants ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
matiere_id INTEGER NOT NULL, |
|||
nom_enseignant VARCHAR(250) NOT NULL, |
|||
prenom_enseignant VARCHAR(250) NOT NULL, |
|||
contact VARCHAR(11) NOT NULL, |
|||
date DATE NOT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
FOREIGN KEY (matiere_id) REFERENCES matieres(id) |
|||
); |
|||
` |
|||
database.prepare(createMatiereEnseignantTableQuery).run() |
|||
|
|||
const createParcourTableQuery = ` |
|||
CREATE TABLE IF NOT EXISTS parcours ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
nom VARCHAR(250) NOT NULL, |
|||
uniter VARCHAR(250) NOT NULL, |
|||
mention_id INTEGER DEFAULT NULL, -- Clé étrangère vers mentions |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
|||
); |
|||
` |
|||
database.prepare(createParcourTableQuery).run() |
|||
|
|||
const createParcourSemestreTableQuery = ` |
|||
CREATE TABLE IF NOT EXISTS parcoursmatiere ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
matiere_id INTEGER NOT NULL, |
|||
parcour_id INTEGER NOT NULL, |
|||
FOREIGN KEY (matiere_id) REFERENCES matieres(id), |
|||
FOREIGN KEY (parcour_id) REFERENCES parcours(id) |
|||
); |
|||
` |
|||
database.prepare(createParcourSemestreTableQuery).run() |
|||
|
|||
const createTableEcolageQuery = ` |
|||
CREATE TABLE IF NOT EXISTS trancheecolage ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
etudiant_id INTEGER NOT NULL, |
|||
tranchename VARCHAR(255) NOT NULL, |
|||
montant DOUBLE NOT NULL |
|||
); |
|||
` |
|||
database.prepare(createTableEcolageQuery).run() |
|||
|
|||
const createTableStoreIP = ` |
|||
CREATE TABLE IF NOT EXISTS ipconfig ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|||
ipname VARCHAR(255) NOT NULL |
|||
); |
|||
`;
|
|||
database.prepare(createTableStoreIP).run() |
|||
|
|||
// -------------------------------------- function pre-excuter --------------------------------------------
|
|||
|
|||
async function insertStatusesIfNotExist() { |
|||
// Préparation des requêtes
|
|||
const checkStatusQuery = database.prepare(` |
|||
SELECT COUNT(*) AS count FROM status WHERE nom = ?; |
|||
`)
|
|||
const insertStatusQuery = database.prepare(` |
|||
INSERT INTO status (nom) VALUES (?); |
|||
`)
|
|||
|
|||
// Tableau des statuts à vérifier/insérer
|
|||
const arrayStatus = ['Nouveau', 'Passant', 'Redoublant', 'Renvoyé', 'Ancien'] |
|||
|
|||
for (let index = 0; index < arrayStatus.length; index++) { |
|||
const statusName = arrayStatus[index] |
|||
|
|||
// Vérification si le statut existe déjà
|
|||
const result = checkStatusQuery.get(statusName) |
|||
|
|||
// Si le statut n'existe pas, on l'insère
|
|||
if (result.count === 0) { |
|||
insertStatusQuery.run(statusName) |
|||
} |
|||
} |
|||
} |
|||
// execute the function
|
|||
insertStatusesIfNotExist() |
|||
|
|||
async function insertDefaultNoteSystemIfNotExist() { |
|||
// Préparation de la requête pour vérifier si une entrée existe déjà
|
|||
const checkNoteSystemQuery = database.prepare(` |
|||
SELECT COUNT(*) AS count FROM notesystems; |
|||
`)
|
|||
|
|||
// Préparation de la requête pour insérer une entrée par défaut
|
|||
const insertNoteSystemQuery = database.prepare(` |
|||
INSERT INTO notesystems (admis, redouble, renvoyer) |
|||
VALUES (?, ?, ?); |
|||
`)
|
|||
|
|||
// Valeurs par défaut à insérer
|
|||
const defaultValues = { |
|||
admis: 10.0, |
|||
redouble: 9.99, |
|||
renvoyer: 7.99 |
|||
} |
|||
|
|||
// Vérification si une entrée existe déjà
|
|||
const result = checkNoteSystemQuery.get() |
|||
|
|||
if (result.count === 0) { |
|||
// Insérer les valeurs par défaut si aucune entrée n'existe
|
|||
insertNoteSystemQuery.run(defaultValues.admis, defaultValues.redouble, defaultValues.renvoyer) |
|||
try { |
|||
// Users table
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS users ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
username VARCHAR(200) NOT NULL, |
|||
email VARCHAR(250) NOT NULL UNIQUE, |
|||
password TEXT NOT NULL, |
|||
roles VARCHAR(250) NOT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
// Status table
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS status ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
nom VARCHAR(200) NOT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
// Mentions table
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS mentions ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
nom VARCHAR(250) NOT NULL, |
|||
uniter VARCHAR(50) NOT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS niveaus ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
nom VARCHAR(50) UNIQUE NOT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS etudiants ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
nom VARCHAR(250) DEFAULT NULL, |
|||
prenom VARCHAR(250) DEFAULT NULL, |
|||
photos TEXT DEFAULT NULL, |
|||
date_de_naissances DATE DEFAULT NULL, |
|||
niveau VARCHAR(250) NOT NULL, |
|||
annee_scolaire VARCHAR(20) NOT NULL, |
|||
status INT DEFAULT NULL, |
|||
mention_id INT NOT NULL, |
|||
num_inscription TEXT UNIQUE NOT NULL, |
|||
sexe VARCHAR(20) DEFAULT NULL, |
|||
cin VARCHAR(250) DEFAULT NULL, |
|||
date_delivrance TEXT DEFAULT NULL, |
|||
nationalite VARCHAR(250) DEFAULT NULL, |
|||
annee_bacc TEXT DEFAULT NULL, |
|||
serie VARCHAR(20) DEFAULT NULL, |
|||
boursier VARCHAR(20) DEFAULT NULL, |
|||
domaine VARCHAR(250) DEFAULT NULL, |
|||
contact VARCHAR(20) DEFAULT NULL, |
|||
parcours VARCHAR(250) DEFAULT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, |
|||
FOREIGN KEY (status) REFERENCES status(id), |
|||
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS matieres ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
nom VARCHAR(250) UNIQUE NOT NULL, |
|||
unite_enseignement VARCHAR(250) NOT NULL, |
|||
credit INT NOT NULL, |
|||
heure INT NOT NULL, |
|||
ue VARCHAR(10) NOT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS semestres ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
nom VARCHAR(30) NOT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS matiere_mention ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
matiere_id INT NOT NULL, |
|||
mention_id INT NOT NULL, |
|||
FOREIGN KEY (matiere_id) REFERENCES matieres(id), |
|||
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS matiere_semestre ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
matiere_id INT NOT NULL, |
|||
semestre_id INT NOT NULL, |
|||
mention_id INT NOT NULL, |
|||
FOREIGN KEY (matiere_id) REFERENCES matieres(id), |
|||
FOREIGN KEY (semestre_id) REFERENCES semestres(id), |
|||
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS notes ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
etudiant_id INT NOT NULL, |
|||
matiere_id INT NOT NULL, |
|||
etudiant_niveau VARCHAR(50) NOT NULL, |
|||
mention_id INT NOT NULL, |
|||
note FLOAT DEFAULT NULL, |
|||
annee_scolaire VARCHAR(50) NOT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, |
|||
FOREIGN KEY (etudiant_id) REFERENCES etudiants(id), |
|||
FOREIGN KEY (matiere_id) REFERENCES matieres(id), |
|||
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS notesrepech ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
etudiant_id INT NOT NULL, |
|||
matiere_id INT NOT NULL, |
|||
etudiant_niveau VARCHAR(50) NOT NULL, |
|||
mention_id INT NOT NULL, |
|||
note FLOAT DEFAULT NULL, |
|||
annee_scolaire VARCHAR(50) NOT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, |
|||
FOREIGN KEY (etudiant_id) REFERENCES etudiants(id), |
|||
FOREIGN KEY (matiere_id) REFERENCES matieres(id), |
|||
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS notesystems ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
admis FLOAT NOT NULL DEFAULT 10, |
|||
redouble FLOAT NOT NULL DEFAULT 9.99, |
|||
renvoyer FLOAT NOT NULL DEFAULT 7.99, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS anneescolaire ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
code VARCHAR(30) NOT NULL, |
|||
debut DATE NOT NULL, |
|||
fin DATE NOT NULL, |
|||
is_current TINYINT(1) DEFAULT 0, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS traitmentsystem ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
code VARCHAR(30) NOT NULL, |
|||
debut DATE NOT NULL, |
|||
fin DATE NOT NULL, |
|||
is_finished TINYINT(1) DEFAULT 0, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS nessesaryTable ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
uniter_heure INT NOT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS matiereEnseignants ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
matiere_id INT NOT NULL, |
|||
nom_enseignant VARCHAR(250) NOT NULL, |
|||
prenom_enseignant VARCHAR(250) NOT NULL, |
|||
contact VARCHAR(11) NOT NULL, |
|||
date DATE NOT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, |
|||
FOREIGN KEY (matiere_id) REFERENCES matieres(id) |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS parcours ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
nom VARCHAR(250) NOT NULL, |
|||
uniter VARCHAR(250) NOT NULL, |
|||
mention_id INT DEFAULT NULL, |
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS parcoursmatiere ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
matiere_id INT NOT NULL, |
|||
parcour_id INT NOT NULL, |
|||
FOREIGN KEY (matiere_id) REFERENCES matieres(id), |
|||
FOREIGN KEY (parcour_id) REFERENCES parcours(id) |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS trancheecolage ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
etudiant_id INT NOT NULL, |
|||
tranchename VARCHAR(255) NOT NULL, |
|||
montant DOUBLE NOT NULL |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
|
|||
await connection.query(` |
|||
CREATE TABLE IF NOT EXISTS ipconfig ( |
|||
id INT AUTO_INCREMENT PRIMARY KEY, |
|||
ipname VARCHAR(255) NOT NULL |
|||
) ENGINE=InnoDB; |
|||
`)
|
|||
} finally { |
|||
connection.release() |
|||
} |
|||
} |
|||
|
|||
insertDefaultNoteSystemIfNotExist() |
|||
|
|||
async function semestreCreate() { |
|||
const query = database.prepare('INSERT INTO semestres (nom) VALUES (?)') |
|||
// Préparation de la requête pour vérifier si une entrée existe déjà
|
|||
const checkSemestreQuery = database.prepare(` |
|||
SELECT COUNT(*) AS count FROM semestres; |
|||
`)
|
|||
|
|||
async function insertDefaultAdmin() { |
|||
const conn = await pool.getConnection() |
|||
try { |
|||
let arraySemestre = [ |
|||
'S1', |
|||
'S2', |
|||
'S3', |
|||
'S4', |
|||
'S5', |
|||
'S6', |
|||
'S7', |
|||
'S8', |
|||
'S9', |
|||
'S10', |
|||
'S11', |
|||
'S12', |
|||
'S13', |
|||
'S14', |
|||
'S14', |
|||
'S16' |
|||
] |
|||
// Vérification si une entrée existe déjà
|
|||
const result = checkSemestreQuery.get() |
|||
|
|||
if (result.count === 0) { |
|||
database.transaction(() => { |
|||
for (let index = 0; index < arraySemestre.length; index++) { |
|||
query.run(arraySemestre[index]) |
|||
} |
|||
})() |
|||
const [rows] = await conn.query(`SELECT COUNT(*) as count FROM users WHERE username = ?`, [ |
|||
'admin' |
|||
]) |
|||
if (rows[0].count === 0) { |
|||
const hashedPassword = bcrypt.hashSync('123456789', 10) |
|||
await conn.query( |
|||
` |
|||
INSERT INTO users (username, email, password, roles) |
|||
VALUES (?, ?, ?, ?)`,
|
|||
['admin', 'admin@example.com', hashedPassword, 'admin'] |
|||
) |
|||
} |
|||
} catch (error) { |
|||
console.log(error) |
|||
} |
|||
} |
|||
|
|||
const createNecessaryParameterTable = () => { |
|||
// Check if the table is empty
|
|||
const rowCount = database.prepare(`SELECT COUNT(*) AS count FROM nessesaryTable`).get().count |
|||
|
|||
// If the table is empty, insert the default value
|
|||
if (rowCount === 0) { |
|||
const insertDefaultQuery = ` |
|||
INSERT INTO nessesaryTable (uniter_heure) VALUES (15); |
|||
` |
|||
database.prepare(insertDefaultQuery).run() |
|||
} finally { |
|||
conn.release() |
|||
} |
|||
} |
|||
|
|||
// Call the function when the app runs
|
|||
createNecessaryParameterTable() |
|||
|
|||
semestreCreate() |
|||
|
|||
// Function to get the IP from the database
|
|||
function getIP() { |
|||
const data = database.prepare("SELECT * FROM ipconfig WHERE id = 1").get(); |
|||
|
|||
if (data) { |
|||
return data.ipname; |
|||
} else { |
|||
return null; // Explicitly return `null` if no data is found
|
|||
async function insertStatusesIfNotExist() { |
|||
const conn = await pool.getConnection() |
|||
try { |
|||
const statuses = ['Nouveau', 'Passant', 'Redoublant', 'Renvoyé', 'Ancien'] |
|||
for (let name of statuses) { |
|||
const [rows] = await conn.query(`SELECT COUNT(*) as count FROM status WHERE nom = ?`, [name]) |
|||
if (rows[0].count === 0) { |
|||
await conn.query(`INSERT INTO status (nom) VALUES (?)`, [name]) |
|||
} |
|||
} |
|||
} finally { |
|||
conn.release() |
|||
} |
|||
} |
|||
|
|||
// Get the new IP from the database
|
|||
let newIP = getIP(); |
|||
|
|||
if (newIP) { |
|||
// Construct the database path using the new IP from the database
|
|||
dbPath = `\\\\${newIP}\\base\\data.db`; |
|||
|
|||
// Reconnect to SQLite database with the updated path
|
|||
database = new sqlite(dbPath); // Re-initialize database connection with new path
|
|||
console.log("now COnnect to the ", dbPath); |
|||
} |
|||
|
|||
module.exports = { |
|||
database |
|||
pool, |
|||
createTables, |
|||
insertDefaultAdmin, |
|||
insertStatusesIfNotExist |
|||
} |
|||
|
|||
@ -1,264 +1,316 @@ |
|||
const fs = require('fs') |
|||
const path = require('path') |
|||
const XLSX = require('xlsx') |
|||
const { getCompressedDefaultImage } = require('../function/GetImageDefaault') |
|||
const { parse } = require('csv-parse/sync') |
|||
const { pool } = require('../database') |
|||
const dayjs = require('dayjs') |
|||
// const { getStatusMention } = require('../function/Helper')
|
|||
const customParseFormat = require('dayjs/plugin/customParseFormat') |
|||
// const { log } = require('console')
|
|||
// const customParseFormatt = require('dayjs/plu')
|
|||
dayjs.extend(customParseFormat) |
|||
|
|||
// Function to convert any date format to 'YYYY-MM-DD'
|
|||
const fs = require('fs'); |
|||
const path = require('path'); |
|||
const XLSX = require('xlsx'); |
|||
const { getCompressedDefaultImage } = require('../function/GetImageDefaault'); |
|||
const { parse } = require('csv-parse/sync'); |
|||
const { pool } = require('../database'); |
|||
const dayjs = require('dayjs'); |
|||
const customParseFormat = require('dayjs/plugin/customParseFormat'); |
|||
dayjs.extend(customParseFormat); |
|||
|
|||
// ✅ Fonction de correction d'encodage
|
|||
function fixEncoding(str) { |
|||
if (typeof str !== 'string') return str; |
|||
return str |
|||
.replace(/├®/g, 'é') |
|||
.replace(/├à/g, 'à') |
|||
.replace(/├©/g, 'é') |
|||
.replace(/├ô/g, 'ô') |
|||
.replace(/├ù/g, 'ù') |
|||
.replace(/’/g, "'") |
|||
.replace(/â€/g, '…') |
|||
.replace(/â€/g, '-'); |
|||
} |
|||
function convertToISODate(input) { |
|||
// Try parsing the date with different formats
|
|||
const formats = [ |
|||
'DD/MM/YYYY', |
|||
'MM/DD/YYYY', |
|||
'YYYY-MM-DD', |
|||
'DD-MM-YYYY', |
|||
'MM-DD-YYYY', |
|||
'DD/MM/YY', |
|||
'MM/DD/YY', |
|||
'DD-MMM-YY' |
|||
] |
|||
const parsedDate = dayjs(input, formats, true) // Strict parsing to ensure formats are matched correctly
|
|||
|
|||
// If the date is valid, return it in the YYYY-MM-DD format
|
|||
if (parsedDate.isValid()) { |
|||
return parsedDate.format('YYYY-MM-DD') |
|||
if (!input) return null; |
|||
|
|||
console.log('🔍 Input original:', input, 'Type:', typeof input); |
|||
|
|||
// Si input est un objet Date valide
|
|||
if (input instanceof Date && !isNaN(input)) { |
|||
const result = dayjs(input).format('YYYY-MM-DD'); |
|||
console.log('📅 Date object convertie:', result); |
|||
return result; |
|||
} |
|||
|
|||
// Handle cases like "Vers 2000"
|
|||
const versMatch = typeof input === 'string' && input.match(/vers\s*(\d{4})/i); |
|||
if (versMatch) { |
|||
return `${versMatch[1]}-01-01`; // Return in ISO format
|
|||
// Si input est un nombre (numéro de série Excel)
|
|||
if (typeof input === 'number') { |
|||
// Formule Excel: (numéro - 25569) * 86400 * 1000
|
|||
const excelDate = new Date((input - 25569) * 86400 * 1000); |
|||
const result = dayjs(excelDate).format('YYYY-MM-DD'); |
|||
console.log('📊 Numéro Excel', input, 'converti en:', result); |
|||
return result; |
|||
} |
|||
|
|||
function excelDateToJSDate(serial) { |
|||
const utc_days = Math.floor(serial - 25569); // days from Jan 1, 1970
|
|||
const utc_value = utc_days * 86400; // seconds in a day
|
|||
return new Date(utc_value * 1000); // JS Date uses milliseconds
|
|||
// Si input est une chaîne
|
|||
if (typeof input === 'string') { |
|||
const cleanInput = input.trim(); |
|||
|
|||
// Cas spécial "vers YYYY"
|
|||
const versMatch = cleanInput.match(/vers\s*(\d{4})/i); |
|||
if (versMatch) { |
|||
const result = `${versMatch[1]}-01-01`; |
|||
console.log('📝 "Vers" détecté:', result); |
|||
return result; |
|||
} |
|||
|
|||
// Formats à tester dans l'ordre de priorité
|
|||
const formats = [ |
|||
'DD/MM/YYYY', 'D/M/YYYY', // Format français prioritaire
|
|||
'YYYY-MM-DD', // Format ISO
|
|||
'DD-MM-YYYY', 'D-M-YYYY', // Format français avec tirets
|
|||
'MM/DD/YYYY', 'M/D/YYYY', // Format américain
|
|||
'MM-DD-YYYY', 'M-D-YYYY', // Format américain avec tirets
|
|||
'DD/MM/YY', 'D/M/YY', // Années courtes
|
|||
'MM/DD/YY', 'M/D/YY', |
|||
'DD-MM-YY', 'D-M-YY', |
|||
'MM-DD-YY', 'M-D-YY' |
|||
]; |
|||
|
|||
// Test avec parsing strict pour éviter les interprétations erronées
|
|||
for (const format of formats) { |
|||
const parsedDate = dayjs(cleanInput, format, true); // true = strict parsing
|
|||
if (parsedDate.isValid()) { |
|||
const result = parsedDate.format('YYYY-MM-DD'); |
|||
console.log(`✅ Format "${format}" réussi:`, cleanInput, '->', result); |
|||
|
|||
// Vérification supplémentaire pour les dates invalides comme 29/02 en année non-bissextile
|
|||
if (format.includes('DD/MM') || format.includes('D/M')) { |
|||
const day = parsedDate.date(); |
|||
const month = parsedDate.month() + 1; // dayjs month is 0-indexed
|
|||
const year = parsedDate.year(); |
|||
|
|||
// Vérifier si c'est le 29 février d'une année non-bissextile
|
|||
if (month === 2 && day === 29 && !isLeapYear(year)) { |
|||
console.warn('⚠️ Date invalide détectée: 29 février en année non-bissextile'); |
|||
return null; // ou retourner une date par défaut
|
|||
} |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
|
|||
// Si aucun format strict ne fonctionne, essayer le parsing libre en dernier recours
|
|||
const freeParseDate = dayjs(cleanInput); |
|||
if (freeParseDate.isValid()) { |
|||
const result = freeParseDate.format('YYYY-MM-DD'); |
|||
console.log('🆓 Parsing libre réussi:', cleanInput, '->', result); |
|||
return result; |
|||
} |
|||
} |
|||
|
|||
let jsDate = excelDateToJSDate(input); |
|||
console.error('❌ Impossible de convertir:', input); |
|||
return null; |
|||
} |
|||
|
|||
// If the input is not a valid date, return 'Invalid Date'
|
|||
return jsDate |
|||
// Fonction utilitaire pour vérifier les années bissextiles
|
|||
function isLeapYear(year) { |
|||
return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0); |
|||
} |
|||
|
|||
// ✅ Mise à jour d'un étudiant existant
|
|||
async function updateEtudiant(row) { |
|||
const sql = ` |
|||
UPDATE etudiants SET |
|||
nom = ?, |
|||
prenom = ?, |
|||
photos = ?, |
|||
date_de_naissances = ?, |
|||
niveau = ?, |
|||
annee_scolaire = ?, |
|||
status = ?, |
|||
mention_id = ?, |
|||
num_inscription = ?, |
|||
sexe = ?, |
|||
date_delivrance = ?, |
|||
nationalite = ?, |
|||
annee_bacc = ?, |
|||
serie = ?, |
|||
boursier = ?, |
|||
domaine = ?, |
|||
contact = ?, |
|||
parcours = ? |
|||
WHERE cin = ? OR (LOWER(nom) = ? AND LOWER(prenom) = ?) |
|||
`;
|
|||
|
|||
const params = [ |
|||
row.nom, |
|||
row.prenom, |
|||
getCompressedDefaultImage(), |
|||
convertToISODate(row.date_naissance), |
|||
row.niveau, |
|||
row.annee_scolaire, |
|||
row.code_redoublement, |
|||
row.mention, |
|||
row.num_inscription.toString(), |
|||
row.sexe, |
|||
convertToISODate(row.date_de_delivrance), |
|||
row.nationaliter, |
|||
parseInt(row.annee_baccalaureat, 10), |
|||
row.serie, |
|||
row.boursier, |
|||
fixEncoding(row.domaine), |
|||
row.contact, |
|||
null, |
|||
row.cin, |
|||
row.nom.toLowerCase().trim(), |
|||
row.prenom.toLowerCase().trim() |
|||
]; |
|||
|
|||
try { |
|||
const [result] = await pool.query(sql, params); |
|||
console.log(`Update effectué pour CIN ${row.cin} ou nom ${row.nom} ${row.prenom}, affectedRows=${result.affectedRows}`); |
|||
return { success: true, affectedRows: result.affectedRows }; |
|||
} catch (error) { |
|||
console.error('❌ Erreur MySQL update :', error.message); |
|||
return { success: false, error: error.message }; |
|||
} |
|||
} |
|||
|
|||
|
|||
// ✅ Insertion réelle multiple
|
|||
async function insertMultipleEtudiants(etudiants) { |
|||
const sql = ` |
|||
INSERT INTO etudiants ( |
|||
nom, prenom, photos, date_de_naissances, niveau, annee_scolaire, status, |
|||
mention_id, num_inscription, sexe, cin, date_delivrance, nationalite, |
|||
annee_bacc, serie, boursier, domaine, contact, parcours |
|||
) |
|||
VALUES ? |
|||
` |
|||
) VALUES ? |
|||
`;
|
|||
|
|||
// Prepare values as array of arrays
|
|||
const values = etudiants.map((row) => [ |
|||
const values = etudiants.map(row => [ |
|||
row.nom, |
|||
row.prenom, |
|||
getCompressedDefaultImage(), // photos (you can adjust this if needed)
|
|||
getCompressedDefaultImage(), |
|||
convertToISODate(row.date_naissance), |
|||
row.niveau, |
|||
row.annee_scolaire, |
|||
row.code_redoublement, |
|||
row.mention, |
|||
row.num_inscription, |
|||
row.num_inscription.toString(), |
|||
row.sexe, |
|||
row.cin, |
|||
convertToISODate(row.date_de_delivrance), |
|||
row.nationaliter, |
|||
row.annee_baccalaureat, |
|||
parseInt(row.annee_baccalaureat, 10), |
|||
row.serie, |
|||
row.boursier, |
|||
row.domaine, |
|||
fixEncoding(row.domaine), |
|||
row.contact, |
|||
null // parcours
|
|||
]) |
|||
null |
|||
]); |
|||
|
|||
try { |
|||
const [result] = await pool.query(sql, [values]) |
|||
return { |
|||
success: true, |
|||
affectedRows: result.affectedRows, |
|||
insertId: result.insertId |
|||
} |
|||
const [result] = await pool.query(sql, [values]); |
|||
return { success: true, affectedRows: result.affectedRows }; |
|||
} catch (error) { |
|||
return { success: false, error: error.message } |
|||
console.error('❌ Erreur MySQL :', error.message); |
|||
return { success: false, error: error.message }; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Function to import data from XLSX or CSV file into SQLite database |
|||
* @param {string} filePath - Path to the file (either .xlsx or .csv) |
|||
*/ |
|||
// ✅ Import fichier vers base
|
|||
async function importFileToDatabase(filePath) { |
|||
const fileExtension = path.extname(filePath).toLowerCase() |
|||
const fileExtension = path.extname(filePath).toLowerCase(); |
|||
let records; |
|||
|
|||
// Determine the file type and parse accordingly
|
|||
let records |
|||
if (fileExtension === '.xlsx') { |
|||
// Read and parse XLSX file
|
|||
const workbook = XLSX.readFile(filePath) |
|||
const worksheet = workbook.Sheets[workbook.SheetNames[0]] // Assuming data is in the first sheet
|
|||
records = XLSX.utils.sheet_to_json(worksheet, { defval: '', raw: false }) |
|||
const workbook = XLSX.readFile(filePath); |
|||
const worksheet = workbook.Sheets[workbook.SheetNames[0]]; |
|||
// raw: true pour garder les valeurs brutes, surtout pour les dates
|
|||
records = XLSX.utils.sheet_to_json(worksheet, { defval: ''}); |
|||
} else if (fileExtension === '.csv') { |
|||
// Read and parse CSV file
|
|||
const fileContent = fs.readFileSync(filePath, 'utf8') |
|||
records = parse(fileContent, { |
|||
columns: true, |
|||
skip_empty_lines: true |
|||
}) |
|||
} else { |
|||
console.error('Unsupported file format. Only .xlsx and .csv are allowed.') |
|||
return |
|||
const fileContent = fs.readFileSync(filePath, 'utf8'); |
|||
records = parse(fileContent, { columns: true, skip_empty_lines: true }); |
|||
}else { |
|||
console.error('Unsupported file format.'); |
|||
return { error: true, message: 'Format de fichier non supporté.' }; |
|||
} |
|||
|
|||
// ✅ Count number of data rows
|
|||
const numberOfLines = records.length |
|||
console.log(`Number of data rows: ${numberOfLines}`) |
|||
console.log(`📄 Nombre de lignes : ${records.length}`); |
|||
|
|||
try { |
|||
let error = true |
|||
let message = '' |
|||
|
|||
// Vérifier les données en une seule boucle
|
|||
let oldNum = '' |
|||
for (const row of records) { |
|||
if ( |
|||
!row.nom || |
|||
// !row.prenom ||
|
|||
!row.date_naissance || |
|||
!row.niveau || |
|||
!row.annee_scolaire || |
|||
!row.mention || |
|||
!row.num_inscription || |
|||
!row.nationaliter || |
|||
!row.sexe || |
|||
// !row.cin ||
|
|||
// !row.date_de_delivrance ||
|
|||
!row.annee_baccalaureat || |
|||
!row.serie || |
|||
!row.code_redoublement || |
|||
!row.boursier || |
|||
!row.domaine |
|||
// ||
|
|||
// !row.contact
|
|||
) { |
|||
if (!row.nom) { |
|||
message = "Le champ 'nom' est inconnu" |
|||
} |
|||
// else if (!row.prenom) {
|
|||
// message = "Le champ 'prenom' est inconnu"
|
|||
// }
|
|||
else if (!row.date_naissance) { |
|||
message = "Le champ 'date_naissance' est inconnu" |
|||
} else if (!row.niveau) { |
|||
message = "Le champ 'niveau' est inconnu" |
|||
} else if (!row.annee_scolaire) { |
|||
message = "Le champ 'annee_scolaire' est inconnu" |
|||
} else if (!row.mention) { |
|||
message = "Le champ 'mention' est inconnu" |
|||
} else if (!row.num_inscription) { |
|||
message = "Le champ 'num_inscription' est inconnu" |
|||
} else if (!row.nationaliter) { |
|||
message = "Le champ 'nationaliter' est inconnu" |
|||
} else if (!row.sexe) { |
|||
message = "Le champ 'sexe' est inconnu" |
|||
} |
|||
// else if (!row.cin) {
|
|||
// message = "Le champ 'cin' est inconnu"
|
|||
// } else if (!row.date_de_delivrance) {
|
|||
// message = "Le champ 'date_de_delivrance' est inconnu"
|
|||
// }
|
|||
else if (!row.annee_baccalaureat) { |
|||
message = "Le champ 'annee_baccalaureat' est inconnu" |
|||
} else if (!row.serie) { |
|||
message = "Le champ 'serie' est inconnu" |
|||
} else if (!row.code_redoublement) { |
|||
message = "Le champ 'code_redoublement' est inconnu" |
|||
} else if (!row.boursier) { |
|||
message = "Le champ 'boursier' est inconnu" |
|||
} else if (!row.domaine) { |
|||
message = "Le champ 'domaine' est inconnu" |
|||
} |
|||
// else if (!row.contact) {
|
|||
// message = "Le champ 'contact' est inconnu"
|
|||
// }
|
|||
error = false |
|||
break |
|||
// Vérifier champs obligatoires
|
|||
const requiredFields = [ |
|||
'nom', 'date_naissance', 'niveau', 'annee_scolaire', |
|||
'mention', 'num_inscription', 'nationaliter', 'sexe', |
|||
'annee_baccalaureat', 'serie', 'code_redoublement', |
|||
'boursier', 'domaine' |
|||
]; |
|||
|
|||
for (const [i, row] of records.entries()) { |
|||
for (const field of requiredFields) { |
|||
if (!row[field]) { |
|||
const msg = `Le champ '${field}' est manquant à la ligne ${i + 2}`; |
|||
console.error(msg); |
|||
return { error: true, message: msg }; |
|||
} |
|||
} |
|||
} |
|||
|
|||
const query = 'SELECT * FROM mentions' |
|||
const [rows] = await pool.query(query) |
|||
const MentionList = rows |
|||
console.log(MentionList) |
|||
|
|||
if (error !== false) { |
|||
let newReccord = [] |
|||
// Utiliser transaction pour éviter une latence si l'insertion dépasse 100
|
|||
for (const row of records) { |
|||
// Convert row.mention to uppercase and compare with ListMention.nom and ListMention.uniter (also converted to uppercase)
|
|||
const matchedMention = MentionList.find( |
|||
(mention) => |
|||
mention.nom.toUpperCase() === row.mention.toUpperCase() || |
|||
mention.uniter.toUpperCase() === row.mention.toUpperCase() |
|||
) |
|||
|
|||
// If a match is found, update row.mention with ListMention.id
|
|||
if (matchedMention) { |
|||
row.mention = matchedMention.id |
|||
} |
|||
const [mentionRows] = await pool.query('SELECT * FROM mentions'); |
|||
const [statusRows] = await pool.query('SELECT * FROM status'); |
|||
|
|||
const query = 'SELECT * FROM status' |
|||
|
|||
let [rows] = await pool.query(query) |
|||
let response = rows |
|||
let statutCode |
|||
for (let index = 0; index < response.length; index++) { |
|||
let nom = response[index].nom |
|||
let nomLower = nom.toLowerCase() // Correct method
|
|||
let find1 = row.code_redoublement.slice(0, 1) |
|||
let find2 = row.code_redoublement.slice(0, 3) |
|||
|
|||
if (nomLower.slice(0, 1) == find1.toLowerCase()) { |
|||
statutCode = response[index].id |
|||
} else if (nomLower.slice(0, 3) == find2.toLowerCase()) { |
|||
statutCode = response[index].id |
|||
} |
|||
} |
|||
const etudiantsToInsert = []; |
|||
const doublons = []; |
|||
console.log(records); |
|||
|
|||
row.code_redoublement = statutCode |
|||
row.num_inscription = row.num_inscription.toString() |
|||
try { |
|||
let compare = row.num_inscription |
|||
if (compare == oldNum) { |
|||
row.num_inscription = String(row.num_inscription) |
|||
} |
|||
console.log(row.code_redoublement) |
|||
newReccord.push(row) |
|||
oldNum = compare |
|||
} catch (error) { |
|||
console.log(error) |
|||
} |
|||
for (const row of records) { |
|||
// Mapping mention
|
|||
console.log('Avant conversion date_naissance:', row.date_naissance); |
|||
row.date_naissance = convertToISODate(row.date_naissance); |
|||
console.log('Après conversion date_naissance:', row.date_naissance); |
|||
const matchedMention = mentionRows.find( |
|||
m => m.nom.toUpperCase() === row.mention.toUpperCase() || |
|||
m.uniter.toUpperCase() === row.mention.toUpperCase() |
|||
); |
|||
if (matchedMention) row.mention = matchedMention.id; |
|||
|
|||
// Gestion code_redoublement -> status id
|
|||
if (row.code_redoublement) { |
|||
row.code_redoublement = row.code_redoublement.trim().substring(0, 1); |
|||
} else { |
|||
row.code_redoublement = 'N'; |
|||
} |
|||
const statusMatch = statusRows.find( |
|||
s => s.nom.toLowerCase().startsWith(row.code_redoublement.toLowerCase()) |
|||
); |
|||
if (statusMatch) row.code_redoublement = statusMatch.id; |
|||
|
|||
// Vérification doublons (extraction complet)
|
|||
const nomComplet = (row.nom + ' ' + row.prenom).toLowerCase().trim(); |
|||
|
|||
const [existing] = await pool.query( |
|||
'SELECT * FROM etudiants WHERE LOWER(CONCAT(nom, " ", prenom)) = ? OR cin = ?', |
|||
[nomComplet, row.cin] |
|||
); |
|||
|
|||
if (existing.length > 0) { |
|||
doublons.push({ nom: row.nom, prenom: row.prenom, cin: row.cin }); |
|||
// Mise à jour
|
|||
const updateResult = await updateEtudiant(row); |
|||
if (!updateResult.success) { |
|||
return { error: true, message: `Erreur lors de la mise à jour de ${row.nom} ${row.prenom} : ${updateResult.error}` }; |
|||
} |
|||
console.log(insertMultipleEtudiants(newReccord)) |
|||
continue; |
|||
} |
|||
|
|||
return { error, message } |
|||
} catch (error) { |
|||
console.error('Error inserting record:', error) |
|||
return { error: 'error' } |
|||
etudiantsToInsert.push(row); |
|||
} |
|||
} |
|||
|
|||
module.exports = { |
|||
importFileToDatabase |
|||
console.log(etudiantsToInsert); |
|||
|
|||
// Insertion des nouveaux
|
|||
let insertResult = { success: true, affectedRows: 0 }; |
|||
if (etudiantsToInsert.length > 0) { |
|||
insertResult = await insertMultipleEtudiants(etudiantsToInsert); |
|||
if (!insertResult.success) { |
|||
return { error: true, message: `Erreur lors de l'insertion : ${insertResult.error}` }; |
|||
} |
|||
} |
|||
|
|||
let msg = `Importation réussie. ${etudiantsToInsert.length} nouvel(le)(s) étudiant(s) inséré(s). ${doublons.length} étudiant(s) mis à jour.`; |
|||
return { error: false, message: msg }; |
|||
} |
|||
|
|||
module.exports = { importFileToDatabase }; |
|||
|
|||
@ -0,0 +1,27 @@ |
|||
// electron.vite.config.mjs
|
|||
import { resolve } from "path"; |
|||
import { defineConfig, externalizeDepsPlugin } from "electron-vite"; |
|||
import react from "@vitejs/plugin-react"; |
|||
var electron_vite_config_default = defineConfig({ |
|||
main: { |
|||
plugins: [externalizeDepsPlugin()] |
|||
}, |
|||
preload: { |
|||
plugins: [externalizeDepsPlugin()] |
|||
}, |
|||
renderer: { |
|||
resolve: { |
|||
alias: { |
|||
"@renderer": resolve("src/renderer/src") |
|||
} |
|||
}, |
|||
plugins: [react()] |
|||
}, |
|||
worker: { |
|||
format: "es" |
|||
// Use ES module for worker (you can also use 'iife')
|
|||
} |
|||
}); |
|||
export { |
|||
electron_vite_config_default as default |
|||
}; |
|||
@ -0,0 +1,132 @@ |
|||
import React, { useEffect, useState } from 'react'; |
|||
import { |
|||
Dialog, |
|||
DialogActions, |
|||
DialogContent, |
|||
DialogTitle, |
|||
Button, |
|||
Box, |
|||
Grid, |
|||
FormControl, |
|||
InputLabel, |
|||
Select, |
|||
OutlinedInput, |
|||
MenuItem |
|||
} from '@mui/material' |
|||
|
|||
const NiveauMatiere = ({ open, onClose, matiere_id }) => { |
|||
const [formData, setFormData] = useState({ |
|||
niveau_id: '', |
|||
id: '' |
|||
}) |
|||
|
|||
const [niveaux, setNiveaux] = useState([]) |
|||
const [niveauxMatiere, setNiveauxMatiere] = useState([]) |
|||
console.log(niveaux); |
|||
|
|||
useEffect(() => { |
|||
window.niveaus.getNiveau().then((response) => { |
|||
setNiveaux(response) |
|||
}) |
|||
}, []) |
|||
|
|||
|
|||
useEffect(() => { |
|||
if (niveauxMatiere.length !== 0) { |
|||
const niveauIds = niveauxMatiere.map((item) => item.niveau_id) |
|||
|
|||
setFormData((prevState) => ({ |
|||
...prevState, |
|||
niveau_id: niveauIds |
|||
})) |
|||
} |
|||
}, [niveauxMatiere]) |
|||
|
|||
useEffect(() => { |
|||
if (matiere_id) { |
|||
setFormData(prev => ({ |
|||
...prev, |
|||
id: matiere_id |
|||
})); |
|||
} |
|||
}, [matiere_id]); |
|||
|
|||
|
|||
|
|||
const handleChange = (event) => { |
|||
const { name, value } = event.target |
|||
|
|||
setFormData(prevState => ({ |
|||
...prevState, |
|||
niveau_id: value // pas de tableau |
|||
})); |
|||
|
|||
} |
|||
|
|||
const formSubmit = async (e) => { |
|||
e.preventDefault(); |
|||
console.log("Form envoyé côté front:", formData); |
|||
let response = await window.matieres.updateMatiereNiveau(formData); |
|||
console.log("Réponse backend:", response); |
|||
if (response.success) { |
|||
onClose(); |
|||
} |
|||
}; |
|||
|
|||
|
|||
return ( |
|||
<Dialog open={open} onClose={onClose}> |
|||
<form action="" onSubmit={formSubmit}> |
|||
<DialogTitle>Assignation à des niveaux</DialogTitle> |
|||
<DialogContent> |
|||
<Box sx={{ flexGrow: 1 }}> |
|||
<Grid container spacing={2}> |
|||
<Grid item xs={12} sm={6}> |
|||
<FormControl sx={{ m: 1, width: 300 }}> |
|||
<InputLabel id="niveaux-select-label" color="warning"> |
|||
Niveaux |
|||
</InputLabel> |
|||
<Select |
|||
labelId="niveaux-select-label" |
|||
id="niveaux-select" |
|||
name="niveau_id" |
|||
value={formData.niveau_id || ''} |
|||
onChange={handleChange} |
|||
color="warning" |
|||
size="small" |
|||
required |
|||
input={<OutlinedInput label="Niveaux" />} |
|||
MenuProps={{ |
|||
PaperProps: { |
|||
style: { |
|||
maxHeight: 200, |
|||
width: 250 |
|||
} |
|||
} |
|||
}} |
|||
> |
|||
{niveaux.map((niveau) => ( |
|||
<MenuItem key={niveau.niveau_id} value={niveau.niveau_id}> |
|||
{niveau.nom} |
|||
</MenuItem> |
|||
))} |
|||
</Select> |
|||
</FormControl> |
|||
</Grid> |
|||
</Grid> |
|||
</Box> |
|||
</DialogContent> |
|||
<DialogActions> |
|||
<Button onClick={onClose} color="error"> |
|||
Annuler |
|||
</Button> |
|||
<Button type="submit" color="warning"> |
|||
Soumettre |
|||
</Button> |
|||
</DialogActions> |
|||
</form> |
|||
</Dialog> |
|||
) |
|||
} |
|||
|
|||
export default NiveauMatiere |
|||
Loading…
Reference in new issue