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 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
|
async function createTables() { |
||||
let dbPath = `./base/data.db`; |
const connection = await pool.getConnection() |
||||
|
|
||||
// Connect to SQLite database with the initial path
|
try { |
||||
let database = new sqlite(dbPath); |
// 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, |
||||
// Create the users table if it doesn't exist
|
password TEXT NOT NULL, |
||||
const createUserTableQuery = ` |
roles VARCHAR(250) NOT NULL, |
||||
CREATE TABLE IF NOT EXISTS users ( |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
||||
username VARCHAR(200) NOT NULL, |
) ENGINE=InnoDB; |
||||
email VARCHAR(250) NOT NULL UNIQUE, |
`)
|
||||
password TEXT NOT NULL, |
|
||||
roles VARCHAR(250) NOT NULL, |
// Status table
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
await connection.query(` |
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
CREATE TABLE IF NOT EXISTS status ( |
||||
); |
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
` |
nom VARCHAR(200) NOT NULL, |
||||
database.prepare(createUserTableQuery).run() |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
||||
// Insert a default admin user if not exists
|
) ENGINE=InnoDB; |
||||
const insertDefaultUserQuery = ` |
`)
|
||||
INSERT INTO users (username, email, password, roles) |
|
||||
SELECT 'admin', 'admin@example.com', ?, 'admin' |
// Mentions table
|
||||
WHERE NOT EXISTS (SELECT 1 FROM users WHERE username = 'admin'); |
await connection.query(` |
||||
` |
CREATE TABLE IF NOT EXISTS mentions ( |
||||
|
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
// Hash the password '1234' before storing
|
nom VARCHAR(250) NOT NULL, |
||||
const hashedPassword = bcrypt.hashSync('123456789', 10) |
uniter VARCHAR(50) NOT NULL, |
||||
database.prepare(insertDefaultUserQuery).run(hashedPassword) |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
||||
// create table for note status
|
) ENGINE=InnoDB; |
||||
const createStatusTableQuery = ` |
`)
|
||||
CREATE TABLE IF NOT EXISTS status ( |
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
await connection.query(` |
||||
nom VARCHAR(200) NOT NULL, |
CREATE TABLE IF NOT EXISTS niveaus ( |
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
nom VARCHAR(50) UNIQUE NOT NULL, |
||||
); |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
||||
` |
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
||||
database.prepare(createStatusTableQuery).run() |
) ENGINE=InnoDB; |
||||
|
`)
|
||||
// create table for mention
|
|
||||
const createMentionTableQuery = ` |
await connection.query(` |
||||
CREATE TABLE IF NOT EXISTS mentions ( |
CREATE TABLE IF NOT EXISTS etudiants ( |
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
nom VARCHAR(250) NOT NULL, |
nom VARCHAR(250) DEFAULT NULL, |
||||
uniter VARCHAR(50) NOT NULL, -- Abréviation du nom |
prenom VARCHAR(250) DEFAULT NULL, |
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
photos TEXT DEFAULT NULL, |
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
date_de_naissances DATE DEFAULT NULL, |
||||
); |
niveau VARCHAR(250) NOT NULL, |
||||
` |
annee_scolaire VARCHAR(20) NOT NULL, |
||||
database.prepare(createMentionTableQuery).run() |
status INT DEFAULT NULL, |
||||
|
mention_id INT NOT NULL, |
||||
// Create the niveau table if it doesn't exist
|
num_inscription TEXT UNIQUE NOT NULL, |
||||
const createNiveauTableQuery = ` |
sexe VARCHAR(20) DEFAULT NULL, |
||||
CREATE TABLE IF NOT EXISTS niveaus ( |
cin VARCHAR(250) DEFAULT NULL, |
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
date_delivrance TEXT DEFAULT NULL, |
||||
nom VARCHAR(50) NOT NULL, -- Exemple: L1, L2, L3, etc. |
nationalite VARCHAR(250) DEFAULT NULL, |
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
annee_bacc TEXT DEFAULT NULL, |
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
serie VARCHAR(20) DEFAULT NULL, |
||||
); |
boursier VARCHAR(20) DEFAULT NULL, |
||||
` |
domaine VARCHAR(250) DEFAULT NULL, |
||||
database.prepare(createNiveauTableQuery).run() |
contact VARCHAR(20) DEFAULT NULL, |
||||
|
parcours VARCHAR(250) DEFAULT NULL, |
||||
// Create the etudiants table if it doesn't exist
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
||||
const createEtudiantsTableQuery = ` |
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, |
||||
CREATE TABLE IF NOT EXISTS etudiants ( |
FOREIGN KEY (status) REFERENCES status(id), |
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
||||
nom VARCHAR(250) DEFAULT NULL, |
) ENGINE=InnoDB; |
||||
prenom VARCHAR(250) DEFAULT NULL, |
`)
|
||||
photos TEXT DEFAULT NULL, |
|
||||
date_de_naissances DATE DEFAULT NULL, |
await connection.query(` |
||||
niveau VARCHAR(250) NOT NULL, -- Clé étrangère vers niveaus |
CREATE TABLE IF NOT EXISTS matieres ( |
||||
annee_scolaire VARCHAR(20) NOT NULL, |
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
status INTEGER DEFAULT NULL, |
nom VARCHAR(250) UNIQUE NOT NULL, |
||||
mention_id INTEGER NOT NULL, -- Clé étrangère vers mentions |
unite_enseignement VARCHAR(250) NOT NULL, |
||||
num_inscription TEXT NOT NULL, |
credit INT NOT NULL, |
||||
sexe VARCHAR(20) DEFAULT NULL, |
heure INT NOT NULL, |
||||
cin VARCHAR(250) DEFAULT NULL, |
ue VARCHAR(10) NOT NULL, |
||||
date_delivrance DEFAULT NULL, |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
||||
nationalite DATE DEFAULT NULL, |
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
||||
annee_bacc DATE DEFAULT NULL, |
) ENGINE=InnoDB; |
||||
serie VARCHAR(20) DEFAULT NULL, |
`)
|
||||
boursier BOOLEAN DEFAULT FALSE, |
|
||||
domaine VARCHAR(250) DEFAULT NULL, |
await connection.query(` |
||||
contact VARCHAR(20) DEFAULT NULL, |
CREATE TABLE IF NOT EXISTS semestres ( |
||||
parcours VARCHAR(250) DEFAULT NULL, |
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
nom VARCHAR(30) NOT NULL, |
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
||||
FOREIGN KEY (status) REFERENCES status(id), |
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
||||
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
) ENGINE=InnoDB; |
||||
); |
`)
|
||||
` |
|
||||
database.prepare(createEtudiantsTableQuery).run() |
await connection.query(` |
||||
|
CREATE TABLE IF NOT EXISTS matiere_mention ( |
||||
// Create the notes table if it doesn't exist
|
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
const createMatiereTableQuery = ` |
matiere_id INT NOT NULL, |
||||
CREATE TABLE IF NOT EXISTS matieres ( |
mention_id INT NOT NULL, |
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
FOREIGN KEY (matiere_id) REFERENCES matieres(id), |
||||
nom VARCHAR(250) UNIQUE NOT NULL, |
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
||||
unite_enseignement VARCHAR(250) NOT NULL, |
) ENGINE=InnoDB; |
||||
credit INTEGER NOT NULL, |
`)
|
||||
heure INTEGER NOT NULL, |
|
||||
ue VARCHAR(10) NOT NULL, |
await connection.query(` |
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
CREATE TABLE IF NOT EXISTS matiere_semestre ( |
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
); |
matiere_id INT NOT NULL, |
||||
` |
semestre_id INT NOT NULL, |
||||
database.prepare(createMatiereTableQuery).run() |
mention_id INT NOT NULL, |
||||
|
FOREIGN KEY (matiere_id) REFERENCES matieres(id), |
||||
// Create the semestre table if it doesn't exist
|
FOREIGN KEY (semestre_id) REFERENCES semestres(id), |
||||
const createSemestreTableQuery = ` |
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
||||
CREATE TABLE IF NOT EXISTS semestres ( |
) ENGINE=InnoDB; |
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
`)
|
||||
nom VARCHAR(30) NOT NULL, -- Exemple: S1, S2, S3, etc. |
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
await connection.query(` |
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
CREATE TABLE IF NOT EXISTS notes ( |
||||
); |
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
` |
etudiant_id INT NOT NULL, |
||||
database.prepare(createSemestreTableQuery).run() |
matiere_id INT NOT NULL, |
||||
|
etudiant_niveau VARCHAR(50) NOT NULL, |
||||
// Create the semestre table if it doesn't exist
|
mention_id INT NOT NULL, |
||||
const createMatiere_mentionTableQuery = ` |
note FLOAT DEFAULT NULL, |
||||
CREATE TABLE IF NOT EXISTS matiere_mention ( |
annee_scolaire VARCHAR(50) NOT NULL, |
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
||||
matiere_id INTEGER NOT NULL, -- Clé étrangère vers matieres |
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, |
||||
mention_id INTEGER NOT NULL, -- Clé étrangère vers mentions |
FOREIGN KEY (etudiant_id) REFERENCES etudiants(id), |
||||
FOREIGN KEY (matiere_id) REFERENCES matieres(id), |
FOREIGN KEY (matiere_id) REFERENCES matieres(id), |
||||
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
||||
); |
) ENGINE=InnoDB; |
||||
` |
`)
|
||||
database.prepare(createMatiere_mentionTableQuery).run() |
|
||||
|
await connection.query(` |
||||
const createMatiere_semestreTableQuery = ` |
CREATE TABLE IF NOT EXISTS notesrepech ( |
||||
CREATE TABLE IF NOT EXISTS matiere_semestre ( |
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
etudiant_id INT NOT NULL, |
||||
matiere_id INTEGER NOT NULL, -- Clé étrangère vers matieres |
matiere_id INT NOT NULL, |
||||
semestre_id INTEGER NOT NULL, -- Clé étrangère vers semestres |
etudiant_niveau VARCHAR(50) NOT NULL, |
||||
mention_id INTEGER NOT NULL, -- Clé étrangère vers niveaus |
mention_id INT NOT NULL, |
||||
FOREIGN KEY (matiere_id) REFERENCES matieres(id), |
note FLOAT DEFAULT NULL, |
||||
FOREIGN KEY (semestre_id) REFERENCES semestres(id), |
annee_scolaire VARCHAR(50) NOT NULL, |
||||
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
||||
); |
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, |
||||
` |
FOREIGN KEY (etudiant_id) REFERENCES etudiants(id), |
||||
database.prepare(createMatiere_semestreTableQuery).run() |
FOREIGN KEY (matiere_id) REFERENCES matieres(id), |
||||
|
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
||||
// Create the notes table if it doesn't exist
|
) ENGINE=InnoDB; |
||||
const createNoteTableQuery = ` |
`)
|
||||
CREATE TABLE IF NOT EXISTS notes ( |
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
await connection.query(` |
||||
etudiant_id INTEGER NOT NULL, -- Clé étrangère vers etudiants |
CREATE TABLE IF NOT EXISTS notesystems ( |
||||
matiere_id INTEGER NOT NULL, -- Clé étrangère vers matieres |
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
etudiant_niveau VARCHAR(50) NOT NULL, |
admis FLOAT NOT NULL DEFAULT 10, |
||||
mention_id INTEGER NOT NULL, |
redouble FLOAT NOT NULL DEFAULT 9.99, |
||||
note FLOAT DEFAULT NULL, |
renvoyer FLOAT NOT NULL DEFAULT 7.99, |
||||
annee_scolaire VARCHAR(50) NOT NULL, |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
) ENGINE=InnoDB; |
||||
FOREIGN KEY (etudiant_id) REFERENCES etudiants(id), |
`)
|
||||
FOREIGN KEY (matiere_id) REFERENCES matieres(id) |
|
||||
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
await connection.query(` |
||||
); |
CREATE TABLE IF NOT EXISTS anneescolaire ( |
||||
` |
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
database.prepare(createNoteTableQuery).run() |
code VARCHAR(30) NOT NULL, |
||||
|
debut DATE NOT NULL, |
||||
// Create the notes second session table if it doesn't exist
|
fin DATE NOT NULL, |
||||
const createNoteRepechTableQuery = ` |
is_current TINYINT(1) DEFAULT 0, |
||||
CREATE TABLE IF NOT EXISTS notesrepech ( |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
||||
etudiant_id INTEGER NOT NULL, -- Clé étrangère vers etudiants |
) ENGINE=InnoDB; |
||||
matiere_id INTEGER NOT NULL, -- Clé étrangère vers matieres |
`)
|
||||
etudiant_niveau VARCHAR(50) NOT NULL, |
|
||||
mention_id INTEGER NOT NULL, |
await connection.query(` |
||||
note FLOAT DEFAULT NULL, |
CREATE TABLE IF NOT EXISTS traitmentsystem ( |
||||
annee_scolaire VARCHAR(50) NOT NULL, |
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
code VARCHAR(30) NOT NULL, |
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
debut DATE NOT NULL, |
||||
FOREIGN KEY (etudiant_id) REFERENCES etudiants(id), |
fin DATE NOT NULL, |
||||
FOREIGN KEY (matiere_id) REFERENCES matieres(id) |
is_finished TINYINT(1) DEFAULT 0, |
||||
FOREIGN KEY (mention_id) REFERENCES mentions(id) |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
||||
); |
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
||||
` |
) ENGINE=InnoDB; |
||||
database.prepare(createNoteRepechTableQuery).run() |
`)
|
||||
|
|
||||
// create table for note système
|
await connection.query(` |
||||
const createNoteSystemeTableQuery = ` |
CREATE TABLE IF NOT EXISTS nessesaryTable ( |
||||
CREATE TABLE IF NOT EXISTS notesystems ( |
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
uniter_heure INT NOT NULL, |
||||
admis FLOAT NOT NULL DEFAULT 10, |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
||||
redouble FLOAT NOT NULL DEFAULT 9.99, |
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
||||
renvoyer FLOAT NOT NULL DEFAULT 7.99, |
) ENGINE=InnoDB; |
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
`)
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
|
||||
); |
await connection.query(` |
||||
` |
CREATE TABLE IF NOT EXISTS matiereEnseignants ( |
||||
database.prepare(createNoteSystemeTableQuery).run() |
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
|
matiere_id INT NOT NULL, |
||||
// create table année scolaire
|
nom_enseignant VARCHAR(250) NOT NULL, |
||||
const createAnneeScolaireTableQuery = ` |
prenom_enseignant VARCHAR(250) NOT NULL, |
||||
CREATE TABLE IF NOT EXISTS anneescolaire ( |
contact VARCHAR(11) NOT NULL, |
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
date DATE NOT NULL, |
||||
code VARCHAR(30) NOT NULL, |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
||||
debut DATE NOT NULL, |
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, |
||||
fin DATE NOT NULL, |
FOREIGN KEY (matiere_id) REFERENCES matieres(id) |
||||
is_current INTEGER DEFAULT 0, |
) ENGINE=InnoDB; |
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
`)
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
|
||||
); |
await connection.query(` |
||||
` |
CREATE TABLE IF NOT EXISTS parcours ( |
||||
database.prepare(createAnneeScolaireTableQuery).run() |
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
|
nom VARCHAR(250) NOT NULL, |
||||
// create traitement systeme
|
uniter VARCHAR(250) NOT NULL, |
||||
const createTraitementSystemQuery = ` |
mention_id INT DEFAULT NULL, |
||||
CREATE TABLE IF NOT EXISTS traitmentsystem ( |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
||||
code VARCHAR(30) NOT NULL, |
) ENGINE=InnoDB; |
||||
debut DATE NOT NULL, |
`)
|
||||
fin DATE NOT NULL, |
|
||||
is_finished INTEGER DEFAULT 0, |
await connection.query(` |
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
CREATE TABLE IF NOT EXISTS parcoursmatiere ( |
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
); |
matiere_id INT NOT NULL, |
||||
` |
parcour_id INT NOT NULL, |
||||
database.prepare(createTraitementSystemQuery).run() |
FOREIGN KEY (matiere_id) REFERENCES matieres(id), |
||||
|
FOREIGN KEY (parcour_id) REFERENCES parcours(id) |
||||
const createNecessaryParameterTableQuery = ` |
) ENGINE=InnoDB; |
||||
CREATE TABLE IF NOT EXISTS nessesaryTable ( |
`)
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|
||||
uniter_heure INTEGER NOT NULL, |
await connection.query(` |
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
CREATE TABLE IF NOT EXISTS trancheecolage ( |
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
); |
etudiant_id INT NOT NULL, |
||||
` |
tranchename VARCHAR(255) NOT NULL, |
||||
database.prepare(createNecessaryParameterTableQuery).run() |
montant DOUBLE NOT NULL |
||||
|
) ENGINE=InnoDB; |
||||
const createMatiereEnseignantTableQuery = ` |
`)
|
||||
CREATE TABLE IF NOT EXISTS matiereEnseignants ( |
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
await connection.query(` |
||||
matiere_id INTEGER NOT NULL, |
CREATE TABLE IF NOT EXISTS ipconfig ( |
||||
nom_enseignant VARCHAR(250) NOT NULL, |
id INT AUTO_INCREMENT PRIMARY KEY, |
||||
prenom_enseignant VARCHAR(250) NOT NULL, |
ipname VARCHAR(255) NOT NULL |
||||
contact VARCHAR(11) NOT NULL, |
) ENGINE=InnoDB; |
||||
date DATE NOT NULL, |
`)
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
} finally { |
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
connection.release() |
||||
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) |
|
||||
} |
} |
||||
} |
} |
||||
|
|
||||
insertDefaultNoteSystemIfNotExist() |
async function insertDefaultAdmin() { |
||||
|
const conn = await pool.getConnection() |
||||
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; |
|
||||
`)
|
|
||||
|
|
||||
try { |
try { |
||||
let arraySemestre = [ |
const [rows] = await conn.query(`SELECT COUNT(*) as count FROM users WHERE username = ?`, [ |
||||
'S1', |
'admin' |
||||
'S2', |
]) |
||||
'S3', |
if (rows[0].count === 0) { |
||||
'S4', |
const hashedPassword = bcrypt.hashSync('123456789', 10) |
||||
'S5', |
await conn.query( |
||||
'S6', |
` |
||||
'S7', |
INSERT INTO users (username, email, password, roles) |
||||
'S8', |
VALUES (?, ?, ?, ?)`,
|
||||
'S9', |
['admin', 'admin@example.com', hashedPassword, 'admin'] |
||||
'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]) |
|
||||
} |
|
||||
})() |
|
||||
} |
} |
||||
} catch (error) { |
} finally { |
||||
console.log(error) |
conn.release() |
||||
} |
|
||||
} |
|
||||
|
|
||||
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() |
|
||||
} |
} |
||||
} |
} |
||||
|
|
||||
// Call the function when the app runs
|
async function insertStatusesIfNotExist() { |
||||
createNecessaryParameterTable() |
const conn = await pool.getConnection() |
||||
|
try { |
||||
semestreCreate() |
const statuses = ['Nouveau', 'Passant', 'Redoublant', 'Renvoyé', 'Ancien'] |
||||
|
for (let name of statuses) { |
||||
// Function to get the IP from the database
|
const [rows] = await conn.query(`SELECT COUNT(*) as count FROM status WHERE nom = ?`, [name]) |
||||
function getIP() { |
if (rows[0].count === 0) { |
||||
const data = database.prepare("SELECT * FROM ipconfig WHERE id = 1").get(); |
await conn.query(`INSERT INTO status (nom) VALUES (?)`, [name]) |
||||
|
} |
||||
if (data) { |
} |
||||
return data.ipname; |
} finally { |
||||
} else { |
conn.release() |
||||
return null; // Explicitly return `null` if no data is found
|
|
||||
} |
} |
||||
} |
} |
||||
|
|
||||
// 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 = { |
module.exports = { |
||||
database |
pool, |
||||
|
createTables, |
||||
|
insertDefaultAdmin, |
||||
|
insertStatusesIfNotExist |
||||
} |
} |
||||
|
|||||
@ -1,264 +1,316 @@ |
|||||
const fs = require('fs') |
const fs = require('fs'); |
||||
const path = require('path') |
const path = require('path'); |
||||
const XLSX = require('xlsx') |
const XLSX = require('xlsx'); |
||||
const { getCompressedDefaultImage } = require('../function/GetImageDefaault') |
const { getCompressedDefaultImage } = require('../function/GetImageDefaault'); |
||||
const { parse } = require('csv-parse/sync') |
const { parse } = require('csv-parse/sync'); |
||||
const { pool } = require('../database') |
const { pool } = require('../database'); |
||||
const dayjs = require('dayjs') |
const dayjs = require('dayjs'); |
||||
// const { getStatusMention } = require('../function/Helper')
|
const customParseFormat = require('dayjs/plugin/customParseFormat'); |
||||
const customParseFormat = require('dayjs/plugin/customParseFormat') |
dayjs.extend(customParseFormat); |
||||
// const { log } = require('console')
|
|
||||
// const customParseFormatt = require('dayjs/plu')
|
// ✅ Fonction de correction d'encodage
|
||||
dayjs.extend(customParseFormat) |
function fixEncoding(str) { |
||||
|
if (typeof str !== 'string') return str; |
||||
// Function to convert any date format to 'YYYY-MM-DD'
|
return str |
||||
|
.replace(/├®/g, 'é') |
||||
|
.replace(/├à/g, 'à') |
||||
|
.replace(/├©/g, 'é') |
||||
|
.replace(/├ô/g, 'ô') |
||||
|
.replace(/├ù/g, 'ù') |
||||
|
.replace(/’/g, "'") |
||||
|
.replace(/â€/g, '…') |
||||
|
.replace(/â€/g, '-'); |
||||
|
} |
||||
function convertToISODate(input) { |
function convertToISODate(input) { |
||||
// Try parsing the date with different formats
|
if (!input) return null; |
||||
const formats = [ |
|
||||
'DD/MM/YYYY', |
console.log('🔍 Input original:', input, 'Type:', typeof input); |
||||
'MM/DD/YYYY', |
|
||||
'YYYY-MM-DD', |
// Si input est un objet Date valide
|
||||
'DD-MM-YYYY', |
if (input instanceof Date && !isNaN(input)) { |
||||
'MM-DD-YYYY', |
const result = dayjs(input).format('YYYY-MM-DD'); |
||||
'DD/MM/YY', |
console.log('📅 Date object convertie:', result); |
||||
'MM/DD/YY', |
return result; |
||||
'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') |
|
||||
} |
} |
||||
|
|
||||
// Handle cases like "Vers 2000"
|
// Si input est un nombre (numéro de série Excel)
|
||||
const versMatch = typeof input === 'string' && input.match(/vers\s*(\d{4})/i); |
if (typeof input === 'number') { |
||||
if (versMatch) { |
// Formule Excel: (numéro - 25569) * 86400 * 1000
|
||||
return `${versMatch[1]}-01-01`; // Return in ISO format
|
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) { |
// Si input est une chaîne
|
||||
const utc_days = Math.floor(serial - 25569); // days from Jan 1, 1970
|
if (typeof input === 'string') { |
||||
const utc_value = utc_days * 86400; // seconds in a day
|
const cleanInput = input.trim(); |
||||
return new Date(utc_value * 1000); // JS Date uses milliseconds
|
|
||||
|
// 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'
|
// Fonction utilitaire pour vérifier les années bissextiles
|
||||
return jsDate |
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) { |
async function insertMultipleEtudiants(etudiants) { |
||||
const sql = ` |
const sql = ` |
||||
INSERT INTO etudiants ( |
INSERT INTO etudiants ( |
||||
nom, prenom, photos, date_de_naissances, niveau, annee_scolaire, status, |
nom, prenom, photos, date_de_naissances, niveau, annee_scolaire, status, |
||||
mention_id, num_inscription, sexe, cin, date_delivrance, nationalite, |
mention_id, num_inscription, sexe, cin, date_delivrance, nationalite, |
||||
annee_bacc, serie, boursier, domaine, contact, parcours |
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.nom, |
||||
row.prenom, |
row.prenom, |
||||
getCompressedDefaultImage(), // photos (you can adjust this if needed)
|
getCompressedDefaultImage(), |
||||
convertToISODate(row.date_naissance), |
convertToISODate(row.date_naissance), |
||||
row.niveau, |
row.niveau, |
||||
row.annee_scolaire, |
row.annee_scolaire, |
||||
row.code_redoublement, |
row.code_redoublement, |
||||
row.mention, |
row.mention, |
||||
row.num_inscription, |
row.num_inscription.toString(), |
||||
row.sexe, |
row.sexe, |
||||
row.cin, |
row.cin, |
||||
convertToISODate(row.date_de_delivrance), |
convertToISODate(row.date_de_delivrance), |
||||
row.nationaliter, |
row.nationaliter, |
||||
row.annee_baccalaureat, |
parseInt(row.annee_baccalaureat, 10), |
||||
row.serie, |
row.serie, |
||||
row.boursier, |
row.boursier, |
||||
row.domaine, |
fixEncoding(row.domaine), |
||||
row.contact, |
row.contact, |
||||
null // parcours
|
null |
||||
]) |
]); |
||||
|
|
||||
try { |
try { |
||||
const [result] = await pool.query(sql, [values]) |
const [result] = await pool.query(sql, [values]); |
||||
return { |
return { success: true, affectedRows: result.affectedRows }; |
||||
success: true, |
|
||||
affectedRows: result.affectedRows, |
|
||||
insertId: result.insertId |
|
||||
} |
|
||||
} catch (error) { |
} catch (error) { |
||||
return { success: false, error: error.message } |
console.error('❌ Erreur MySQL :', error.message); |
||||
|
return { success: false, error: error.message }; |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
/** |
// ✅ Import fichier vers base
|
||||
* Function to import data from XLSX or CSV file into SQLite database |
|
||||
* @param {string} filePath - Path to the file (either .xlsx or .csv) |
|
||||
*/ |
|
||||
async function importFileToDatabase(filePath) { |
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') { |
if (fileExtension === '.xlsx') { |
||||
// Read and parse XLSX file
|
const workbook = XLSX.readFile(filePath); |
||||
const workbook = XLSX.readFile(filePath) |
const worksheet = workbook.Sheets[workbook.SheetNames[0]]; |
||||
const worksheet = workbook.Sheets[workbook.SheetNames[0]] // Assuming data is in the first sheet
|
// raw: true pour garder les valeurs brutes, surtout pour les dates
|
||||
records = XLSX.utils.sheet_to_json(worksheet, { defval: '', raw: false }) |
records = XLSX.utils.sheet_to_json(worksheet, { defval: ''}); |
||||
} else if (fileExtension === '.csv') { |
} else if (fileExtension === '.csv') { |
||||
// Read and parse CSV file
|
const fileContent = fs.readFileSync(filePath, 'utf8'); |
||||
const fileContent = fs.readFileSync(filePath, 'utf8') |
records = parse(fileContent, { columns: true, skip_empty_lines: true }); |
||||
records = parse(fileContent, { |
}else { |
||||
columns: true, |
console.error('Unsupported file format.'); |
||||
skip_empty_lines: true |
return { error: true, message: 'Format de fichier non supporté.' }; |
||||
}) |
|
||||
} else { |
|
||||
console.error('Unsupported file format. Only .xlsx and .csv are allowed.') |
|
||||
return |
|
||||
} |
} |
||||
|
|
||||
// ✅ Count number of data rows
|
console.log(`📄 Nombre de lignes : ${records.length}`); |
||||
const numberOfLines = records.length |
|
||||
console.log(`Number of data rows: ${numberOfLines}`) |
|
||||
|
|
||||
try { |
// Vérifier champs obligatoires
|
||||
let error = true |
const requiredFields = [ |
||||
let message = '' |
'nom', 'date_naissance', 'niveau', 'annee_scolaire', |
||||
|
'mention', 'num_inscription', 'nationaliter', 'sexe', |
||||
// Vérifier les données en une seule boucle
|
'annee_baccalaureat', 'serie', 'code_redoublement', |
||||
let oldNum = '' |
'boursier', 'domaine' |
||||
for (const row of records) { |
]; |
||||
if ( |
|
||||
!row.nom || |
for (const [i, row] of records.entries()) { |
||||
// !row.prenom ||
|
for (const field of requiredFields) { |
||||
!row.date_naissance || |
if (!row[field]) { |
||||
!row.niveau || |
const msg = `Le champ '${field}' est manquant à la ligne ${i + 2}`; |
||||
!row.annee_scolaire || |
console.error(msg); |
||||
!row.mention || |
return { error: true, message: msg }; |
||||
!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 |
|
||||
} |
} |
||||
} |
} |
||||
|
} |
||||
|
|
||||
const query = 'SELECT * FROM mentions' |
const [mentionRows] = await pool.query('SELECT * FROM mentions'); |
||||
const [rows] = await pool.query(query) |
const [statusRows] = await pool.query('SELECT * FROM status'); |
||||
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 query = 'SELECT * FROM status' |
const etudiantsToInsert = []; |
||||
|
const doublons = []; |
||||
let [rows] = await pool.query(query) |
console.log(records); |
||||
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 |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
row.code_redoublement = statutCode |
for (const row of records) { |
||||
row.num_inscription = row.num_inscription.toString() |
// Mapping mention
|
||||
try { |
console.log('Avant conversion date_naissance:', row.date_naissance); |
||||
let compare = row.num_inscription |
row.date_naissance = convertToISODate(row.date_naissance); |
||||
if (compare == oldNum) { |
console.log('Après conversion date_naissance:', row.date_naissance); |
||||
row.num_inscription = String(row.num_inscription) |
const matchedMention = mentionRows.find( |
||||
} |
m => m.nom.toUpperCase() === row.mention.toUpperCase() || |
||||
console.log(row.code_redoublement) |
m.uniter.toUpperCase() === row.mention.toUpperCase() |
||||
newReccord.push(row) |
); |
||||
oldNum = compare |
if (matchedMention) row.mention = matchedMention.id; |
||||
} catch (error) { |
|
||||
console.log(error) |
// 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 } |
etudiantsToInsert.push(row); |
||||
} catch (error) { |
|
||||
console.error('Error inserting record:', error) |
|
||||
return { error: 'error' } |
|
||||
} |
} |
||||
} |
|
||||
|
|
||||
module.exports = { |
console.log(etudiantsToInsert); |
||||
importFileToDatabase |
|
||||
|
// 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