Browse Source

add file

master
andrymodeste 4 months ago
parent
commit
f1aefc3073
  1. 8
      database/Models/AnneeScolaire.js
  2. 13
      database/Models/Etudiants.backup.js
  3. 49
      database/Models/Etudiants.js
  4. 32
      database/Models/Matieres.backup.js
  5. 55
      database/Models/Matieres.js
  6. 8
      database/Models/Mentions.js
  7. 7
      database/Models/Niveau.js
  8. 4
      database/Models/NoteSysrem.js
  9. 10
      database/Models/Parcours.js
  10. 717
      database/database.backup.js
  11. 10
      database/database.js
  12. 7
      database/database2.js
  13. 2
      database/function/DownloadReleverNote.js
  14. 4
      database/function/System.js
  15. 470
      database/import/Etudiants.js
  16. 27
      electron.vite.config.1754936034364.mjs
  17. 20
      src/main/backup.js
  18. 20
      src/main/index.js
  19. 2
      src/preload/index.backup.js
  20. 6
      src/preload/index.js
  21. 2
      src/renderer/src/assets/AllStyleComponents.module.css
  22. 8
      src/renderer/src/components/AddAnneeScolaire.jsx
  23. 5
      src/renderer/src/components/AddNotes.jsx
  24. 6
      src/renderer/src/components/AddStudent.jsx
  25. 4
      src/renderer/src/components/AnneeScolaire.jsx
  26. 2
      src/renderer/src/components/Apropos.jsx
  27. 38
      src/renderer/src/components/ExportEtudiants.jsx
  28. 78
      src/renderer/src/components/Matieres.jsx
  29. 2
      src/renderer/src/components/ModalExportFichr.jsx
  30. 132
      src/renderer/src/components/NiveauMatiere.jsx
  31. 2
      src/renderer/src/components/ParcourMatiere.jsx
  32. 2
      src/renderer/src/components/Parcours.jsx
  33. 4
      src/renderer/src/components/Resultat.jsx
  34. 2
      src/renderer/src/components/Sidenav.jsx
  35. 6
      src/renderer/src/components/SingleAnneeScolaire.jsx
  36. 2
      src/renderer/src/components/SingleEtudiant.jsx
  37. 36
      src/renderer/src/components/Student.jsx
  38. 2
      src/renderer/src/components/TesteDatagrid.jsx
  39. 1
      src/renderer/src/components/UpdateTranche.jsx
  40. 2
      src/renderer/src/components/function/GenerateFiche.js
  41. 2
      src/renderer/src/components/function/PDFEditor.js
  42. 2
      src/renderer/src/components/function/PDFEditorV2.js
  43. 2
      src/renderer/src/test/qr.html
  44. 2
      src/renderer/src/test/relever.html
  45. 2
      text.txt

8
database/Models/AnneeScolaire.js

@ -71,13 +71,13 @@ async function deleteAnneeScolaire(id) {
if (result.affectedRows === 0) {
return {
success: false,
message: 'Année universitaire non trouvé.'
message: 'Année Scolaire non trouvé.'
}
}
return {
success: true,
message: 'Année universitaire supprimé avec succès.'
message: 'Année Scolaire supprimé avec succès.'
}
} catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' }
@ -93,13 +93,13 @@ async function updateAnneeScolaire(id, code, debut, fin) {
if (result.affectedRows === 0) {
return {
success: false,
message: 'Année universitaire non trouvé ou aucune modification effectuée.'
message: 'Année Scolaire non trouvé ou aucune modification effectuée.'
}
}
return {
success: true,
message: 'Année universitaire mis à jour avec succès.'
message: 'Année Scolaire mis à jour avec succès.'
}
} catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' }

13
database/Models/Etudiants.backup.js

@ -280,6 +280,18 @@ async function deleteTranche(id) {
}
}
async function deleteEtudiant(id) {
const query = database.prepare('DELETE FROM etudiants WHERE id = ?')
try {
let response = query.run(id)
return response
} catch (error) {
return error
}
}
async function getSingleTranche(id) {
try {
return await database.prepare('SELECT * FROM trancheecolage WHERE id = ?').get(id)
@ -301,5 +313,6 @@ module.exports = {
getTranche,
updateTranche,
deleteTranche,
deleteEtudiant,
getSingleTranche
}

49
database/Models/Etudiants.js

@ -176,13 +176,13 @@ async function updateEtudiant(
if (result.affectedRows === 0) {
return {
success: false,
message: 'Année universitaire non trouvé.'
message: 'Année Scolaire non trouvé.'
}
}
return {
success: true,
message: 'Année universitaire supprimé avec succès.'
message: 'Année Scolaire supprimé avec succès.'
}
} catch (error) {
return error
@ -222,13 +222,13 @@ async function changePDP(photos, id) {
if (result.affectedRows === 0) {
return {
success: false,
message: 'Année universitaire non trouvé.'
message: 'Année Scolaire non trouvé.'
}
}
return {
success: true,
message: 'Année universitaire supprimé avec succès.'
message: 'Année Scolaire supprimé avec succès.'
}
} catch (error) {
return error
@ -244,13 +244,13 @@ async function updateParcours(parcours, id) {
if (result.affectedRows === 0) {
return {
success: false,
message: 'Année universitaire non trouvé.'
message: 'Année Scolaire non trouvé.'
}
}
return {
success: true,
message: 'Année universitaire supprimé avec succès.'
message: 'Année Scolaire supprimé avec succès.'
}
} catch (error) {
return error
@ -289,19 +289,21 @@ async function updateTranche(id, tranchename, montant) {
try {
const [result] = await pool.query(sql, [tranchename, montant, id])
console.log('resultat tranche:',result);
if (result.affectedRows === 0) {
return {
success: false,
message: 'Année universitaire non trouvé.'
message: 'Année Scolaire non trouvé.'
}
}
return {
success: true,
message: 'Année universitaire supprimé avec succès.'
message: 'Année Scolaire supprimé avec succès.'
}
} catch (error) {
console.log('resultat error:',error);
return error
}
}
@ -315,19 +317,45 @@ async function deleteTranche(id) {
if (result.affectedRows === 0) {
return {
success: false,
message: 'Année universitaire non trouvé.'
message: 'Année Scolaire non trouvé.'
}
}
return {
success: true,
message: 'Année universitaire supprimé avec succès.'
message: 'Année Scolaire supprimé avec succès.'
}
} catch (error) {
return error
}
}
async function deleteEtudiant(id) {
console.log("id: ", id);
const sql = 'DELETE FROM etudiants WHERE id = ?';
try {
let [result] = await pool.query(sql, [id]);
console.log("Résultat DELETE:", result);
if (result.affectedRows === 0) {
return {
success: false,
message: 'Etudiant non trouvée.'
};
}
return {
success: true,
message: 'Matière supprimée avec succès.'
};
} catch (error) {
console.log("err: ",+ error)
return { success: false, error: 'Erreur, veuillez réessayer: ' + error };
}
}
async function getSingleTranche(id) {
const sql = 'SELECT * FROM trancheecolage WHERE id = ?'
try {
@ -351,5 +379,6 @@ module.exports = {
getTranche,
updateTranche,
deleteTranche,
deleteEtudiant,
getSingleTranche
}

32
database/Models/Matieres.backup.js

@ -29,7 +29,7 @@ async function createMatiere(nom, credit, uniter, ue) {
* @returns Promise
*/
async function getMatiere() {
const query = database.prepare('SELECT * FROM matieres ORDER BY id DESC')
const query = database.prepare('SELECT m.*, n.nom AS niveau_nom FROM matieres m LEFT JOIN niveaus n ON m.niveau_id = n.id ORDER BY m.id DESC')
try {
let response = await query.all()
@ -141,6 +141,35 @@ async function updateMatiere(nom, id, credit, uniter, ue) {
}
}
async function updateMatiereNiveau(formData) {
console.log('formdata:', formData);
const { niveau_id, id } = formData;
const sql = 'UPDATE matieres SET niveau_id = ? WHERE id = ?';
try {
const [result] = await pool.query(sql, [niveau_id, id]);
if (result.affectedRows === 0) {
return {
success: false,
message: 'Matière non trouvée ou aucune modification effectuée.'
};
}
return {
success: true,
message: 'Niveau mis à jour avec succès.'
};
} catch (error) {
console.error(error);
return {
success: false,
error: 'Erreur lors de la mise à jour du niveau : ' + error.message
};
}
}
async function deleteMatiere(id) {
const query = database.prepare('DELETE FROM matieres WHERE id = ?')
@ -340,6 +369,7 @@ module.exports = {
getMatiere,
getSingleMatiere,
updateMatiere,
updateMatiereNiveau,
displayMatiereFromForm,
deleteMatiere,
asygnationToMention,

55
database/Models/Matieres.js

@ -31,7 +31,7 @@ async function createMatiere(nom, credit, uniter, ue) {
* @returns Promise
*/
async function getMatiere() {
const sql = 'SELECT * FROM matieres ORDER BY id DESC'
const sql = 'SELECT m.*, n.nom AS niveau_nom FROM matieres m LEFT JOIN niveaus n ON m.niveau_id = n.id ORDER BY m.id DESC'
try {
let [rows] = await pool.query(sql)
@ -149,41 +149,71 @@ async function updateMatiere(nom, id, credit, uniter, ue) {
if (result.affectedRows === 0) {
return {
success: false,
message: 'Année universitaire non trouvé ou aucune modification effectuée.'
message: 'Année Scolaire non trouvé ou aucune modification effectuée.'
}
}
return {
success: true,
message: 'Année universitaire mis à jour avec succès.'
message: 'Année Scolaire mis à jour avec succès.'
}
} catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' + error }
}
}
async function updateMatiereNiveau(formData) {
const { niveau_id, id } = formData; // ici id sera bien défini
const sql = 'UPDATE matieres SET niveau_id = ? WHERE id = ?';
try {
const [result] = await pool.query(sql, [niveau_id, id]);
if (result.affectedRows === 0) {
return {
success: false,
message: `Matière avec id ${id} non trouvée ou niveau déjà attribué.`
};
}
return {
success: true,
message: `Niveau de la matière ${id} mis à jour avec succès.`
};
} catch (error) {
return {
success: false,
error: 'Erreur lors de la mise à jour : ' + error.message
};
}
}
async function deleteMatiere(id) {
const sql = 'DELETE FROM matieres WHERE id = ?'
console.log("id: ", id);
const sql = 'DELETE FROM matieres WHERE id = ?';
try {
let [result] = await pool.query(sql, [id])
let [result] = await pool.query(sql, [id]);
console.log("Résultat DELETE:", result);
if (result.affectedRows === 0) {
return {
success: false,
message: 'Année universitaire non trouvé.'
}
message: 'Matière non trouvée.'
};
}
return {
success: true,
message: 'Année universitaire supprimé avec succès.'
}
message: 'Matière supprimée avec succès.'
};
} catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' + error }
console.log("err: ",+ error)
return { success: false, error: 'Erreur, veuillez réessayer: ' + error };
}
}
/**
* Assign mentions to a matiere
* @param {Object} formData - keys = mention_ids, values = true/false
@ -444,13 +474,13 @@ async function updateProf(matiere_id, nom, prenom, contact, date) {
if (result.affectedRows === 0) {
return {
success: false,
message: 'Année universitaire non trouvé.'
message: 'Année Scolaire non trouvé.'
}
}
return {
success: true,
message: 'Année universitaire supprimé avec succès.'
message: 'Année Scolaire supprimé avec succès.'
}
} catch (error) {
console.error(error)
@ -464,6 +494,7 @@ module.exports = {
getMatiere,
getSingleMatiere,
updateMatiere,
updateMatiereNiveau,
displayMatiereFromForm,
deleteMatiere,
asygnationToMention,

8
database/Models/Mentions.js

@ -24,13 +24,13 @@ async function deleteMention(id) {
if (result.affectedRows === 0) {
return {
success: false,
message: 'Année universitaire non trouvé.'
message: 'Année Scolaire non trouvé.'
}
}
return {
success: true,
message: 'Année universitaire supprimé avec succès.'
message: 'Année Scolaire supprimé avec succès.'
}
} catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' + error }
@ -70,13 +70,13 @@ async function updateMention(nom, uniter, id) {
if (result.affectedRows === 0) {
return {
success: false,
message: 'Année universitaire non trouvé ou aucune modification effectuée.'
message: 'Année Scolaire non trouvé ou aucune modification effectuée.'
}
}
return {
success: true,
message: 'Année universitaire mis à jour avec succès.'
message: 'Année Scolaire mis à jour avec succès.'
}
} catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' + error }

7
database/Models/Niveau.js

@ -89,17 +89,18 @@ async function updateNiveau(nom, id) {
* function to get all niveau
*/
async function getNiveau() {
const sql = 'SELECT * FROM niveaus'
const sql = 'SELECT niveaus.*,niveaus.id AS niveau_id FROM niveaus'
try {
let [rows] = await pool.query(sql)
console.log("maka niveau: ", rows);
return rows
} catch (error) {
return { success: false, error: 'Erreur veullez réeseyer' }
}
}
async function deleteNiveau(id) {
const sql = 'DELETE FROM niveaus WHERE id = ?'
@ -130,5 +131,5 @@ module.exports = {
insertNiveau,
getSingleNiveau,
updateNiveau,
deleteNiveau
deleteNiveau,
}

4
database/Models/NoteSysrem.js

@ -33,13 +33,13 @@ async function updateSysteme(id, admis, redouble, renvoyer) {
if (result.affectedRows === 0) {
return {
success: false,
message: 'Année universitaire non trouvé.'
message: 'Année Scolaire non trouvé.'
}
}
return {
success: true,
message: 'Année universitaire supprimé avec succès.'
message: 'Année Scolaire supprimé avec succès.'
}
} catch (error) {
return error

10
database/Models/Parcours.js

@ -30,7 +30,7 @@ async function getParcourMatiere(id) {
}
async function getParcours() {
const sql = 'SELECT * FROM parcours ORDER BY id DESC'
const sql = 'SELECT parcours.*, mentions.nom AS mention_nom FROM parcours LEFT JOIN mentions ON parcours.mention_id = mentions.id ORDER BY parcours.id DESC'
try {
let [rows] = await pool.query(sql)
@ -62,13 +62,13 @@ async function deletes(id) {
if (result.affectedRows === 0) {
return {
success: false,
message: 'Année universitaire non trouvé.'
message: 'Année Scolaire non trouvé.'
}
}
return {
success: true,
message: 'Année universitaire supprimé avec succès.'
message: 'Année Scolaire supprimé avec succès.'
}
} catch (error) {
return error
@ -84,13 +84,13 @@ async function updateparcour(id, nom, uniter, mention_id) {
if (result.affectedRows === 0) {
return {
success: false,
message: 'Année universitaire non trouvé ou aucune modification effectuée.'
message: 'Année Scolaire non trouvé ou aucune modification effectuée.'
}
}
return {
success: true,
message: 'Année universitaire mis à jour avec succès.'
message: 'Année Scolaire mis à jour avec succès.'
}
} catch (error) {
return error

717
database/database.backup.js

@ -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
}

10
database/database.js

@ -1,11 +1,11 @@
const mysql = require('mysql2/promise')
const bcrypt = require('bcryptjs')
const pool = mysql.createPool({
host: '127.0.0.1',
user: 'root',
password: '',
database: 'university',
const pool = mysql.createPool({
host: '127.0.0.1',
user: 'root',
password: '',
database: 'university',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0

7
database/database2.js

@ -6,11 +6,12 @@ const pool = mysql.createPool({
user: 'root',
password: '',
database: 'university',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
})
async function createTables() {
const connection = await pool.getConnection()

2
database/function/DownloadReleverNote.js

@ -14,7 +14,7 @@ async function modifyPDF(filepath) {
const firstPage = pages[0]
// Replace text based on your data object
const data = { f1: 'Nom', f2: 'Prénom', f3: 23 }
const data = { f1: 'Nom', f2: 'Prenom', f3: 23 }
// Example of replacing placeholders
firstPage.drawText(data.f1, { x: 120, y: 700, size: 12 })

4
database/function/System.js

@ -287,13 +287,13 @@ async function updateNessesaryTable(id, multiplicateur) {
if (result.affectedRows === 0) {
return {
success: false,
message: 'Année universitaire non trouvé.'
message: 'Année Scolaire non trouvé.'
}
}
return {
success: true,
message: 'Année universitaire supprimé avec succès.'
message: 'Année Scolaire supprimé avec succès.'
}
} catch (error) {
return error

470
database/import/Etudiants.js

@ -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 };

27
electron.vite.config.1754936034364.mjs

@ -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
};

20
src/main/backup.js

@ -25,6 +25,7 @@ const {
getTranche,
updateTranche,
deleteTranche,
deleteEtudiant,
getSingleTranche
} = require('../../database/Models/Etudiants')
const {
@ -45,6 +46,7 @@ const {
createMatiere,
getSingleMatiere,
updateMatiere,
updateMatiereNiveau,
displayMatiereFromForm,
deleteMatiere,
asygnationToMention,
@ -537,6 +539,12 @@ ipcMain.handle('updateMatiere', async (event, credentials) => {
return update
})
ipcMain.handle('updateMatiereNiveau', async (event, credentials) => {
// credentials = { niveau_id, id }
const update = await updateMatiereNiveau(credentials) // ✅ on passe id + niveau_id
return update
})
// event for importExcel
ipcMain.handle('importexcel', async (event, credentials) => {
const files = credentials
@ -672,12 +680,10 @@ ipcMain.handle('deleteNiveaus', async (event, credentials) => {
return get
})
ipcMain.handle('deleteMatiere', async (event, credentials) => {
const { id } = credentials
ipcMain.handle('deleteMatiere', async (event, id) => {
return await deleteMatiere(id);
});
const get = deleteMatiere(id)
return get
})
ipcMain.handle('asign', async (event, credentials) => {
const { formData, id } = credentials
@ -887,6 +893,10 @@ ipcMain.handle('deleteTranche', async (event, credentials) => {
return get
})
ipcMain.handle('deleteEtudiant', async (event, id) => {
return await deleteEtudiant(id);
});
ipcMain.handle('getSingleTranche', async (event, credentials) => {
const { id } = credentials
// console.log(formData, id);

20
src/main/index.js

@ -45,8 +45,10 @@ const {
createMatiere,
getSingleMatiere,
updateMatiere,
updateMatiereNiveau,
displayMatiereFromForm,
deleteMatiere,
deleteEtudiant,
asygnationToMention,
getMentionMatiere,
getMentionMatiereChecked,
@ -520,6 +522,12 @@ ipcMain.handle('updateMatiere', async (event, credentials) => {
return update
})
ipcMain.handle('updateMatiereNiveau', async (event, credentials) => {
// credentials = { niveau_id, id }
const update = await updateMatiereNiveau(credentials) // ✅ on passe id + niveau_id
return update
})
// event for importExcel
ipcMain.handle('importexcel', async (event, credentials) => {
const files = credentials
@ -654,13 +662,13 @@ ipcMain.handle('deleteNiveaus', async (event, credentials) => {
const get = deleteNiveau(id)
return get
})
ipcMain.handle('deleteMatiere', async (event, id) => {
return await deleteMatiere(id);
});
ipcMain.handle('deleteEtudiant', async (event, id) => {
return await deleteEtudiant(id);
});
ipcMain.handle('deleteMatiere', async (event, credentials) => {
const { id } = credentials
const get = deleteMatiere(id)
return get
})
ipcMain.handle('asign', async (event, credentials) => {
const { formData, id } = credentials

2
src/preload/index.backup.js

@ -132,10 +132,12 @@ if (process.contextIsolated) {
createMatiere: (credentials) => ipcRenderer.invoke('createMatiere', credentials),
getMatiereByID: (credentials) => ipcRenderer.invoke('getMatiereByID', credentials),
updateMatiere: (credentials) => ipcRenderer.invoke('updateMatiere', credentials),
updateMatiereNiveau: (credentials) => ipcRenderer.invoke('updateMatiereNiveau', credentials),
importExcel: (credentials) => ipcRenderer.invoke('importExcelMatiere', credentials),
displayMatiereFromForm: (credentials) =>
ipcRenderer.invoke('displayMatiereFromForm', credentials),
deleteMatiere: (credentials) => ipcRenderer.invoke('deleteMatiere', credentials),
deleteEtudiant: (credentials) => ipcRenderer.invoke('deleteEtudiant', credentials),
asign: (credentials) => ipcRenderer.invoke('asign', credentials),
getAsign: (credentials) => ipcRenderer.invoke('getAsign', credentials),
asignSemestre: (credentials) => ipcRenderer.invoke('asignSemestre', credentials),

6
src/preload/index.js

@ -1,7 +1,6 @@
import { contextBridge, ipcRenderer } from 'electron'
import { electronAPI } from '@electron-toolkit/preload'
const { getNessesarytable } = require('../../database/function/System')
const { getNiveau } = require('../../database/Models/Niveau')
const { getAllUsers } = require('../../database/Models/Users')
const { getAllEtudiants, getDataToDashboard } = require('../../database/Models/Etudiants')
const { verifyEtudiantIfHeHasNotes, blockShowMoyene } = require('../../database/Models/Notes')
@ -12,6 +11,7 @@ const { getAnneeScolaire, getInterval } = require('../../database/Models/AnneeSc
const { getMentions } = require('../../database/Models/Mentions')
const { getAll } = require('../../database/api/Get')
const { getParcours } = require('../../database/Models/Parcours')
const { getNiveau } = require('../../database/Models/Niveau')
const { getIPConfig } = require('../../database/Models/IpConfig')
// Custom APIs for renderer
@ -128,10 +128,12 @@ if (process.contextIsolated) {
createMatiere: (credentials) => ipcRenderer.invoke('createMatiere', credentials),
getMatiereByID: (credentials) => ipcRenderer.invoke('getMatiereByID', credentials),
updateMatiere: (credentials) => ipcRenderer.invoke('updateMatiere', credentials),
updateMatiereNiveau: (credentials) => ipcRenderer.invoke('updateMatiereNiveau', credentials),
importExcel: (credentials) => ipcRenderer.invoke('importExcelMatiere', credentials),
displayMatiereFromForm: (credentials) =>
ipcRenderer.invoke('displayMatiereFromForm', credentials),
deleteMatiere: (credentials) => ipcRenderer.invoke('deleteMatiere', credentials),
deleteMatiere: (id) => ipcRenderer.invoke('deleteMatiere', id),
deleteEtudiant: (id) => ipcRenderer.invoke('deleteEtudiant', id),
asign: (credentials) => ipcRenderer.invoke('asign', credentials),
getAsign: (credentials) => ipcRenderer.invoke('getAsign', credentials),
asignSemestre: (credentials) => ipcRenderer.invoke('asignSemestre', credentials),

2
src/renderer/src/assets/AllStyleComponents.module.css

@ -1,5 +1,5 @@
.h1style {
text-transform: uppercase;
/* text-transform: uppercase; */
font-weight: 900;
/* 6636af4a 6636af ffae01 */
border-left: 10px solid #ffff;

8
src/renderer/src/components/AddAnneeScolaire.jsx

@ -98,7 +98,7 @@ const AddAnneeScolaire = () => {
{status === 200 ? (
<Typography style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
<img src={svgSuccess} alt="" width={50} height={50} />{' '}
<span>Année universitaire insérer avec succes</span>
<span>Année Scolaire insérer avec succes</span>
</Typography>
) : (
<Typography style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
@ -136,7 +136,7 @@ const AddAnneeScolaire = () => {
<div className={classe.h1style}>
<div className={classeHome.blockTitle}>
<h1 style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
<FaCalendarPlus /> Ajout Année universitaire
<FaCalendarPlus /> Ajout Année Scolaire
</h1>
<Link to={'#'} onClick={() => window.history.back()}>
<Button color="warning" variant="contained">
@ -170,12 +170,12 @@ const AddAnneeScolaire = () => {
}}
>
<h4 style={{ textAlign: 'center', padding: '0 0 3% 0' }}>
Creation de nouvelle année universitaire
Creation de nouvelle Année Scolaire
</h4>
<Grid container spacing={2}>
<Grid item xs={12} sm={6}>
<TextField
label={'Année universitaire'}
label={'Année Scolaire'}
name={'code'}
placeholder="2024-2025"
color="warning"

5
src/renderer/src/components/AddNotes.jsx

@ -52,6 +52,9 @@ const AddNotes = () => {
window.matieres.displayMatiereFromForm({ niveau, mention_id, parcours }).then((response) => {
setMatieres(response)
console.log("resulat teste:1", response);
console.log("resulat teste:2", mention_id);
console.log("resulat teste:3", parcours);
})
setIsSubmitted(false)
}
@ -109,6 +112,8 @@ const AddNotes = () => {
}
}
console.log('matiere: ',matieres);
const [statut, setStatut] = useState(200)
/**

6
src/renderer/src/components/AddStudent.jsx

@ -503,13 +503,13 @@ const AddStudent = () => {
variant="outlined"
>
<InputLabel id="demo-select-small-label" color="warning">
Année Universitaire
Année Scolaire
</InputLabel>
<Select
labelId="demo-select-small-label"
id="demo-select-small"
value={formData.annee_scolaire}
label="Année Universitaire"
label="Année Scolaire"
color="warning"
size="small"
onChange={handleInputChange}
@ -521,7 +521,7 @@ const AddStudent = () => {
<FaCalendarAlt />
</InputAdornment>
}
label="Année Universitaire"
label="Année Scolaire"
/>
}
sx={{

4
src/renderer/src/components/AnneeScolaire.jsx

@ -48,7 +48,7 @@ const AnneeScolaire = () => {
const [ids, setIds] = useState(0)
const column = [
{ field: 'code', headerName: 'Année universitaire', width: 130 },
{ field: 'code', headerName: 'Année Scolaire', width: 130 },
{ field: 'debut', headerName: 'Date de début', width: 130 },
{ field: 'fin', headerName: 'Date de fin', width: 130 },
{
@ -259,7 +259,7 @@ const AnneeScolaire = () => {
<div className={classe.h1style}>
<div className={classeHome.blockTitle}>
<h1 style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
<BsCalendar2Date /> Année Universitaire
<BsCalendar2Date /> Année Scolaire
</h1>
<Link to={'/addanneescolaire'}>
<Button color="warning" variant="contained">

2
src/renderer/src/components/Apropos.jsx

@ -47,7 +47,7 @@ const Apropos = () => {
<p style={{ color: 'black' }}>
Nom du Logiciel: CUniversity <br />
<br /> Description : logiciel de gestion d'universiter <br /> <br />
<br /> Description : logiciel de gestion d'espt <br /> <br />
Createur: CPAY COMPANY FOR MADAGASCAR <br />
<br /> Licence: A vie <br />
<br /> Contact: 0348415301

38
src/renderer/src/components/ExportEtudiants.jsx

@ -142,25 +142,35 @@ const ExportEtudiants = () => {
* fonction qui envoye dans le back
*/
const handleImport = async () => {
// Code to handle file import (can open a file dialog or call handleFileChange)
let response = await window.etudiants.importExcel(files.path)
console.log(response)
if (response.message) {
setMessage(response.message)
if (!files) {
setError("Veuillez choisir un fichier d'abord.")
return
}
if (response.error) {
setIsinserted(true)
setOpen(true)
setTableData([])
} else {
try {
let response = await window.etudiants.importExcel(files.path)
console.log(response)
if (response.message) {
setMessage(response.message)
}
if (response.error) {
setIsinserted(false)
setOpen(true)
// Ne vide pas tableData, ça permet à l'utilisateur de corriger le fichier
} else {
setIsinserted(true)
setOpen(true)
setTableData([]) // vider seulement si insertion réussie
}
} catch (err) {
setMessage('Erreur inattendue lors de l’import')
setIsinserted(false)
setOpen(true)
}
}
/**
* hook to open modal

78
src/renderer/src/components/Matieres.jsx

@ -28,9 +28,12 @@ import ParcourMatiere from './ParcourMatiere'
import UpdateModalProf from './UpdateModalProf'
import ModalProcessFichePresence from './ModalProcessFichePresence'
import ModalExportFichr from './ModalExportFichr'
import NiveauMatiere from './NiveauMatiere'
const Matieres = () => {
const [matiere, setMatiere] = useState([])
const [openAssignNiveau, setOpenAssignNiveau] = useState(false)
const [matiereIdAssign, setMatiereIdAssign] = useState(null)
const [Enseignants, setEnseignants] = useState([])
useEffect(() => {
@ -62,6 +65,29 @@ const Matieres = () => {
}
})
const openAssignNiveauModal = (id) => {
setMatiereIdAssign(id)
setOpenAssignNiveau(true)
}
const closeAssignNiveauModal = () => {
setOpenAssignNiveau(false)
setMatiereIdAssign(null)
}
const handleNiveauAssignSuccess = (status) => {
if (status) {
// Rafraîchir les données des matières et enseignants
window.matieres.getMatiere().then((response) => {
setMatiere(response)
})
window.matieres.getENseignant().then((response) => {
setEnseignants(response)
})
}
}
const [isDeleted, setIsDeleted] = useState(false)
const [ids, setIds] = useState(0)
@ -71,6 +97,7 @@ const Matieres = () => {
{ field: 'heure', headerName: 'Heure', width: 80 },
{ field: 'uniter', headerName: "Unité d'enseignement", width: 180 },
{ field: 'ue', headerName: 'UE', width: 80 },
{ field: 'niveau_id', headerName: 'Niveau', width: 80 },
{ field: 'enseignant', headerName: 'Professeur actuele', width: 230 },
{
field: 'action',
@ -109,23 +136,47 @@ const Matieres = () => {
</Button>
</Link>
<Link
to={`/asignmatieresemestre/${params.value}`}
className={`sem${params.value}`}
to={`/asignmatieresemestre/${params.value}`}
className={`sem${params.value}`}
style={{ textDecoration: 'none' }}
>
<Tooltip
anchorSelect={`.sem${params.value}`}
style={{ fontSize: '15px', zIndex: 9 }}
place="top"
>
Assigner à un semestre
</Tooltip>
<Button color="warning" variant="contained">
<FaS style={{ fontSize: '20px', color: 'white' }} />
</Button>
</Link>
{/* ----------- BOUTON ASSIGNER NIVEAU ----------- */}
<Link
to="#"
className={`niveau${params.value}`}
style={{ textDecoration: 'none' }}
onClick={(e) => {
e.preventDefault(); // empêche le # de provoquer un scroll
openAssignNiveauModal(params.value);
}}
>
<Tooltip
anchorSelect={`.sem${params.value}`}
anchorSelect={`.niveau${params.value}`}
style={{ fontSize: '15px', zIndex: 9 }}
place="top"
>
Assigner à un semestre
Assigner à un niveau
</Tooltip>
<Button color="warning" variant="contained">
<FaS style={{ fontSize: '20px', color: 'white' }} />
{/* Icône de ton choix, ici FaRegPlusSquare par exemple */}
<FaRegPlusSquare style={{ fontSize: '20px', color: 'white' }} />
</Button>
</Link>
<Link
to={`#`}
to="#"
style={{ textDecoration: 'none' }}
className={`parcour${params.value}`}
onClick={() => openParcoursFunction(params.value)}
@ -141,6 +192,7 @@ const Matieres = () => {
<FaP style={{ fontSize: '20px', color: 'white' }} />
</Button>
</Link>
<Link to={`#`}>
<Button color="warning" variant="contained">
<GiTeacher
@ -253,13 +305,14 @@ const Matieres = () => {
heure: mat.heure,
uniter: mat.unite_enseignement,
ue: mat.ue,
niveau_id: mat.niveau_nom ?? 'pas de niveau',
enseignant:
compareMatieres(mat.id) != '' ? compareMatieres(mat.id) : 'Veuillez assigner un professeur',
action: mat.id // Ensure this is a valid URL for the image
}))
const deleteButton = async (id) => {
let response = await window.matieres.deleteMatiere({ id })
let response = await window.matieres.deleteMatiere(id);
if (response.success) {
const updatedMatieres = matiere.filter((matiere) => matiere.id !== id)
setMatiere(updatedMatieres)
@ -431,6 +484,15 @@ const Matieres = () => {
open={openUppdateProf}
/>
<ModalProcessFichePresence matiere_id={matiereId} onClose={onCloseFiche} open={openFiche} />
{/* Modal NiveauMatiere */}
<NiveauMatiere
open={openAssignNiveau}
onClose={closeAssignNiveauModal}
matiere_id={matiereIdAssign}
onSubmitSuccess={handleNiveauAssignSuccess}
/>
<div className={classeAdd.header}>
<div className={classe.h1style}>
<div className={classeHome.blockTitle}>
@ -499,4 +561,4 @@ const Matieres = () => {
)
}
export default Matieres
export default Matieres

2
src/renderer/src/components/ModalExportFichr.jsx

@ -170,7 +170,7 @@ const ModalExportFichr = () => {
</tr>
<tr style={{ borderBottom: 'solid 1px gray' }}>
<th style={{ borderRight: 'solid 1px gray' }}>N°</th>
<th style={{ borderRight: 'solid 1px gray' }}>Nom et Prénom</th>
<th style={{ borderRight: 'solid 1px gray' }}>Nom et Prenom</th>
<th style={{ borderRight: 'solid 1px gray' }}>Mention</th>
<th>Emergement</th>
</tr>

132
src/renderer/src/components/NiveauMatiere.jsx

@ -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

2
src/renderer/src/components/ParcourMatiere.jsx

@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react'
import React, { useEffect, useState } from 'react';
import {
Dialog,
DialogActions,

2
src/renderer/src/components/Parcours.jsx

@ -81,7 +81,7 @@ const Parcours = () => {
id: parc.id,
nom: parc.nom,
uniter: parc.uniter,
mention: parc.mention_id,
mention: parc.mention_nom || parc.mention || 'Mention non trouvée',
action: parc.id
}))

4
src/renderer/src/components/Resultat.jsx

@ -187,13 +187,13 @@ const Resultat = () => {
<tr>
<td colSpan={4} className="py-3">
<h6>
Niveau {niveau} | Année universitaire {scolaire}
Niveau {niveau} | Année Scolaire {scolaire}
</h6>
</td>
</tr>
<tr>
<th>Nom</th>
<th>Prénom</th>
<th>Prenom</th>
<th>Mention</th>
<th>Moyenne</th>
</tr>

2
src/renderer/src/components/Sidenav.jsx

@ -153,7 +153,7 @@ const Sidenav = () => {
>
<BsCalendar2Date className="anneescolaire" style={{ outline: 'none' }} />
<Tooltip anchorSelect=".anneescolaire" className="custom-tooltip" place="top">
Année Universitaire
Année Scolaire
</Tooltip>
</Link>
</li>

6
src/renderer/src/components/SingleAnneeScolaire.jsx

@ -121,7 +121,7 @@ const SingleAnneeScolaire = () => {
<div className={classeHome.blockTitle}>
<h1 style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
<BsCalendar2Date />
Mise a jour Année universitaire
Mise a jour Année Scolaire
</h1>
<Link to={'#'} onClick={() => window.history.back()}>
<Button color="warning" variant="contained">
@ -155,12 +155,12 @@ const SingleAnneeScolaire = () => {
onSubmit={formSubmit}
>
<h4 style={{ textAlign: 'center', padding: '0 0 3% 0' }}>
mise a jour année universitaire
mise a jour Année Scolaire
</h4>
<Grid container spacing={2}>
<Grid item xs={12} sm={6}>
<TextField
label={'Année universitaire'}
label={'Année Scolaire'}
name={'code'}
placeholder="2024-2025"
color="warning"

2
src/renderer/src/components/SingleEtudiant.jsx

@ -540,7 +540,7 @@ const SingleEtudiant = () => {
<Grid item xs={6}>
<TextField
fullWidth
label="Année Universitaire"
label="Année Scolaire"
name="annee_scolaire"
color="warning"
defaultValue={etudiant.annee_scolaire} // Controlled component value

36
src/renderer/src/components/Student.jsx

@ -227,7 +227,7 @@ const Student = () => {
<Link style={{ display: 'flex', gap: '10px' }}>
<SeeNote params={params} />
<Link>
<Button
<Button
onClick={() => handleOpen(params.value)}
color="warning"
variant="contained"
@ -309,16 +309,22 @@ const Student = () => {
}
}
// const paginationModel = { page: 0, pageSize: 20 }
const [pageSize, setPageSize] = useState(20)
// PAGINATION CORRIGÉE - États pour la pagination complète
const [paginationModel, setPaginationModel] = useState({
page: 0,
pageSize: 20
})
const [pageSizeOptions, setPageSizeOptions] = useState([20, 40, 60])
const handlePageSizeChange = (newPageSize) => {
setPageSize(newPageSize)
// If the user picked the largest value, add next +20
// Gestionnaire complet pour les changements de pagination (page ET pageSize)
const handlePaginationModelChange = (newModel) => {
console.log('📊 Pagination changed:', newModel) // Pour debug
setPaginationModel(newModel)
// Si l'utilisateur choisit la plus grande option, ajouter +20
const maxOption = Math.max(...pageSizeOptions)
if (newPageSize === maxOption) {
if (newModel.pageSize === maxOption) {
setPageSizeOptions((prev) => [...prev, maxOption + 20])
}
}
@ -360,16 +366,20 @@ const Student = () => {
}
/**
* function to filter the data in dataGrid by Niveau
* Fonction de filtrage avec reset de pagination
*/
const FilterData = async (e) => {
let niveau = e.target.value
if (niveau !== '') {
let data = await window.etudiants.FilterDataByNiveau({ niveau })
setEtudiants(data)
// Reset vers la première page après filtrage
setPaginationModel(prev => ({ ...prev, page: 0 }))
} else {
window.etudiants.getEtudiants().then((response) => {
setEtudiants(response)
// Reset vers la première page
setPaginationModel(prev => ({ ...prev, page: 0 }))
})
}
}
@ -541,11 +551,9 @@ const Student = () => {
<DataGrid
rows={dataRow}
columns={columns}
// initialState={{ pagination: { paginationModel } }}
// pageSizeOptions={[20, 40, 60]}
pageSizeOptions={pageSizeOptions}
paginationModel={{ pageSize, page: 0 }}
onPaginationModelChange={(model) => handlePageSizeChange(model.pageSize)}
paginationModel={paginationModel} // Utilise l'état complet
onPaginationModelChange={handlePaginationModelChange} // Gère page ET pageSize
sx={{
border: 0,
width: 'auto', // Ensures the DataGrid takes full width
@ -573,4 +581,4 @@ const Student = () => {
)
}
export default Student
export default Student

2
src/renderer/src/components/TesteDatagrid.jsx

@ -248,7 +248,7 @@ const TesteDatagrid = ({ id, niveau, annee_scolaire, nomPrenom, inscription, ref
</div>
</div>
<div style={{ fontSize: '13px', margin: '1%' }}>
<span>Nom & Prénoms: </span>
<span>Nom & Prenoms: </span>
<span>{nomPrenom}</span>
<br />
<div style={{ display: 'flex', justifyContent: 'space-between' }}>

1
src/renderer/src/components/UpdateTranche.jsx

@ -47,7 +47,6 @@ const UpdateTranche = ({ open, onClose, onSubmitSuccess, id }) => {
const handleSubmit = async (e) => {
e.preventDefault()
console.log(formData)
let response = await window.etudiants.updateTranche(formData)
if (response.changes) {

2
src/renderer/src/components/function/GenerateFiche.js

@ -40,7 +40,7 @@ export const generatePDF = async (students) => {
y -= 30
const headers = ['N°', 'Nom et Prénom', 'Mention', 'Émergement']
const headers = ['N°', 'Nom et Prenom', 'Mention', 'Émergement']
const columnWidths = [50, 200, 100, 100]
const xPositions = [
margin,

2
src/renderer/src/components/function/PDFEditor.js

@ -73,7 +73,7 @@ const PDFEditor = async (data) => {
// ----------------------------------------------- carte arriere -------------------------------------------
const paperContent = `
CUniversity
Nom et prénom: ${data.f1}
Nom et prenom: ${data.f1}
Date de naissance: ${data.f2}
Niveau: ${data.f3}
Année scolaire: ${data.f4}

2
src/renderer/src/components/function/PDFEditorV2.js

@ -79,7 +79,7 @@ async function fillPdfFields(jsonData) {
const paperContent = `
C-University
Nom et prénom: ${jsonData.f1}
Nom et prenom: ${jsonData.f1}
Date de naissance: ${jsonData.f2}
Niveau: ${jsonData.f3}
Année scolaire: ${jsonData.f4}

2
src/renderer/src/test/qr.html

@ -23,7 +23,7 @@
</div>
<div class="cart-info">
<p><b>Nom</b> : BE</p>
<p><b>Prénom</b> : Joseph Fabrice</p>
<p><b>Prenom</b> : Joseph Fabrice</p>
<p><b>Date de naissance</b> : 11-12-2001</p>
<p><b>Niveau</b> : L3</p>
<p><b>Année scolaire</b> : 2023-2024</p>

2
src/renderer/src/test/relever.html

@ -19,7 +19,7 @@
<div class="releve">
<h3>RELEVÉE DE NOTE</h3>
<p><strong>Nom & Prénoms :</strong> F3</p>
<p><strong>Nom & Prenoms :</strong> F3</p>
<p>
<strong>Niveau :</strong> L1 <span><strong>Année scolaire :</strong> 2022-2023</span>
</p>

2
text.txt

@ -244,7 +244,7 @@ const FileUploader = () => {
<thead>
<tr>
<th>Nom</th>
<th>Prénom</th>
<th>Prenom</th>
<th>Photos</th>
<th>Date de Naissances</th>
<th>Niveau</th>

Loading…
Cancel
Save