|
|
|
|
const { pool } = require('../database')
|
|
|
|
|
const dayjs = require('dayjs')
|
|
|
|
|
|
|
|
|
|
async function updateCurrentYears() {
|
|
|
|
|
const fullDate = dayjs().format('YYYY-MM-DD')
|
|
|
|
|
|
|
|
|
|
// Clear current year flag
|
|
|
|
|
const clearCurrent = 'UPDATE anneescolaire SET is_Current = 0 WHERE id > 0'
|
|
|
|
|
pool.query(clearCurrent)
|
|
|
|
|
|
|
|
|
|
// Set the new current year
|
|
|
|
|
const updateCurrent = `
|
|
|
|
|
UPDATE anneescolaire
|
|
|
|
|
SET is_Current = 1
|
|
|
|
|
WHERE ? >= debut AND ? <= fin
|
|
|
|
|
`
|
|
|
|
|
// console.log();
|
|
|
|
|
pool.query(updateCurrent, [fullDate, fullDate])
|
|
|
|
|
|
|
|
|
|
// Check if the update was successful
|
|
|
|
|
const sql = `
|
|
|
|
|
SELECT * FROM anneescolaire
|
|
|
|
|
WHERE ? >= debut AND ? <= fin
|
|
|
|
|
`
|
|
|
|
|
const [rows] = await pool.query(sql, [fullDate, fullDate])
|
|
|
|
|
|
|
|
|
|
const check = rows[0]
|
|
|
|
|
if (!check) return
|
|
|
|
|
|
|
|
|
|
// 2. Check if already in traitmentsystem
|
|
|
|
|
const searchSql = `SELECT * FROM traitmentsystem WHERE code = ?`
|
|
|
|
|
const [searchRows] = await pool.query(searchSql, [check.code])
|
|
|
|
|
|
|
|
|
|
if (searchRows.length === 0) {
|
|
|
|
|
// 3. Insert into traitmentsystem
|
|
|
|
|
const insertSql = `
|
|
|
|
|
INSERT INTO traitmentsystem (code, debut, fin)
|
|
|
|
|
VALUES (?, ?, ?)
|
|
|
|
|
`
|
|
|
|
|
await pool.query(insertSql, [check.code, check.debut, check.fin])
|
|
|
|
|
} else {
|
|
|
|
|
console.log('No active school year found for the current date.')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Helper functions (unchanged)
|
|
|
|
|
function checkNull(params) {
|
|
|
|
|
if (params === null || params === undefined) return null
|
|
|
|
|
return params
|
|
|
|
|
}
|
|
|
|
|
function compareSessionNotes(session1, session2) {
|
|
|
|
|
if (session2) {
|
|
|
|
|
return session1 < session2.note ? session2.note : session1
|
|
|
|
|
}
|
|
|
|
|
return session1
|
|
|
|
|
}
|
|
|
|
|
function nextLevel(niveau) {
|
|
|
|
|
const levels = ['L1', 'L2', 'L3', 'M1', 'M2', 'D1', 'D2', 'D3', 'PHD']
|
|
|
|
|
const idx = levels.indexOf(niveau)
|
|
|
|
|
return idx === -1 || idx === levels.length - 1 ? niveau : levels[idx + 1]
|
|
|
|
|
}
|
|
|
|
|
function updateSchoolYear(year) {
|
|
|
|
|
const [startYear, endYear] = year.split('-').map(Number)
|
|
|
|
|
return `${startYear + 1}-${endYear + 1}`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function updateStudents() {
|
|
|
|
|
const connection = await pool.getConnection()
|
|
|
|
|
try {
|
|
|
|
|
await connection.beginTransaction()
|
|
|
|
|
const today = dayjs().format('YYYY-MM-DD')
|
|
|
|
|
|
|
|
|
|
// 1. Récupérer toutes les années scolaires triées par debut
|
|
|
|
|
const [allYears] = await connection.query(
|
|
|
|
|
'SELECT * FROM anneescolaire ORDER BY debut ASC'
|
|
|
|
|
)
|
|
|
|
|
if (allYears.length < 2) {
|
|
|
|
|
await connection.rollback()
|
|
|
|
|
connection.release()
|
|
|
|
|
return { message: 'Pas assez d\'années scolaires configurées.' }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. Seuils de notes
|
|
|
|
|
const [noteSystemRows] = await connection.query('SELECT * FROM notesystems LIMIT 1')
|
|
|
|
|
const noteSystem = noteSystemRows[0]
|
|
|
|
|
|
|
|
|
|
let totalProcessed = 0
|
|
|
|
|
|
|
|
|
|
// 3. Pour chaque paire d'années consécutives (annéeN → annéeN+1)
|
|
|
|
|
for (let i = 0; i < allYears.length - 1; i++) {
|
|
|
|
|
const prevYear = allYears[i]
|
|
|
|
|
const nextYear = allYears[i + 1]
|
|
|
|
|
|
|
|
|
|
// Traiter uniquement si l'année suivante a déjà commencé
|
|
|
|
|
if (nextYear.debut > today) continue
|
|
|
|
|
|
|
|
|
|
// Trouver les étudiants inscrits en annéeN mais PAS encore en annéeN+1
|
|
|
|
|
const [studentsToProcess] = await connection.query(
|
|
|
|
|
`SELECT i.*, e.nom, e.prenom, e.photos
|
|
|
|
|
FROM inscriptions i
|
|
|
|
|
JOIN etudiants e ON i.etudiant_id = e.id
|
|
|
|
|
WHERE i.annee_scolaire_id = ?
|
|
|
|
|
AND i.etudiant_id NOT IN (
|
|
|
|
|
SELECT etudiant_id FROM inscriptions WHERE annee_scolaire_id = ?
|
|
|
|
|
)`,
|
|
|
|
|
[prevYear.id, nextYear.id]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if (studentsToProcess.length === 0) continue
|
|
|
|
|
|
|
|
|
|
for (const inscription of studentsToProcess) {
|
|
|
|
|
const inscStatus = parseInt(inscription.status)
|
|
|
|
|
|
|
|
|
|
// Renvoyé → pas de nouvelle inscription
|
|
|
|
|
if (inscStatus === 4) continue
|
|
|
|
|
|
|
|
|
|
let newNiveau, newStatus
|
|
|
|
|
|
|
|
|
|
// Vérifier si l'étudiant a des notes pour l'année précédente
|
|
|
|
|
const [notesRows] = await connection.query(
|
|
|
|
|
`SELECT n.note, n.matiere_id, m.credit
|
|
|
|
|
FROM notes n
|
|
|
|
|
JOIN matieres m ON n.matiere_id = m.id
|
|
|
|
|
WHERE n.etudiant_id = ? AND n.annee_scolaire = ?`,
|
|
|
|
|
[inscription.etudiant_id, prevYear.code]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if (notesRows.length > 0) {
|
|
|
|
|
// Calculer la moyenne avec prise en compte du rattrapage
|
|
|
|
|
const [repechRows] = await connection.query(
|
|
|
|
|
`SELECT n.note, n.matiere_id, m.credit
|
|
|
|
|
FROM notesrepech n
|
|
|
|
|
JOIN matieres m ON n.matiere_id = m.id
|
|
|
|
|
WHERE n.etudiant_id = ? AND n.annee_scolaire = ?`,
|
|
|
|
|
[inscription.etudiant_id, prevYear.code]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
let total = 0
|
|
|
|
|
let totalCredit = 0
|
|
|
|
|
for (const note of notesRows) {
|
|
|
|
|
const repNote = repechRows.find(r => r.matiere_id === note.matiere_id)
|
|
|
|
|
const noteToUse = compareSessionNotes(note.note, checkNull(repNote))
|
|
|
|
|
total += (noteToUse ?? 0) * note.credit
|
|
|
|
|
totalCredit += note.credit
|
|
|
|
|
}
|
|
|
|
|
const moyenne = totalCredit > 0 ? total / totalCredit : 0
|
|
|
|
|
|
|
|
|
|
if (moyenne >= noteSystem.admis) {
|
|
|
|
|
newNiveau = nextLevel(inscription.niveau)
|
|
|
|
|
newStatus = 2 // Passant
|
|
|
|
|
} else if (moyenne >= noteSystem.renvoyer) {
|
|
|
|
|
newNiveau = inscription.niveau
|
|
|
|
|
newStatus = 3 // Redoublant
|
|
|
|
|
} else {
|
|
|
|
|
newNiveau = inscription.niveau
|
|
|
|
|
newStatus = 4 // Renvoyé
|
|
|
|
|
continue // Pas de nouvelle inscription pour les renvoyés
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Pas de notes → utiliser le statut de l'inscription
|
|
|
|
|
if (inscStatus === 2) {
|
|
|
|
|
// Passant → niveau supérieur
|
|
|
|
|
newNiveau = nextLevel(inscription.niveau)
|
|
|
|
|
newStatus = 2
|
|
|
|
|
} else {
|
|
|
|
|
// Redoublant, Nouveau, Ancien → même niveau
|
|
|
|
|
newNiveau = inscription.niveau
|
|
|
|
|
newStatus = 3
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Créer l'inscription pour l'année suivante
|
|
|
|
|
await connection.query(
|
|
|
|
|
`INSERT INTO inscriptions
|
|
|
|
|
(etudiant_id, annee_scolaire_id, niveau, mention_id, parcours, status, num_inscription)
|
|
|
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
|
|
|
[
|
|
|
|
|
inscription.etudiant_id, nextYear.id, newNiveau,
|
|
|
|
|
inscription.mention_id, inscription.parcours, newStatus,
|
|
|
|
|
inscription.num_inscription
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Pour les redoublants, copier les notes de l'année précédente (seulement si pas encore copiées)
|
|
|
|
|
if (newStatus === 3) {
|
|
|
|
|
const [existingNotes] = await connection.query(
|
|
|
|
|
`SELECT COUNT(*) as cnt FROM notes WHERE etudiant_id = ? AND annee_scolaire = ?`,
|
|
|
|
|
[inscription.etudiant_id, nextYear.code]
|
|
|
|
|
)
|
|
|
|
|
if (existingNotes[0].cnt === 0) {
|
|
|
|
|
await connection.query(
|
|
|
|
|
`INSERT INTO notes (etudiant_id, matiere_id, etudiant_niveau, mention_id, note, annee_scolaire)
|
|
|
|
|
SELECT etudiant_id, matiere_id, etudiant_niveau, mention_id, note, ?
|
|
|
|
|
FROM notes
|
|
|
|
|
WHERE etudiant_id = ? AND annee_scolaire = ?`,
|
|
|
|
|
[nextYear.code, inscription.etudiant_id, prevYear.code]
|
|
|
|
|
)
|
|
|
|
|
await connection.query(
|
|
|
|
|
`INSERT INTO notesrepech (etudiant_id, matiere_id, etudiant_niveau, mention_id, note, annee_scolaire)
|
|
|
|
|
SELECT etudiant_id, matiere_id, etudiant_niveau, mention_id, note, ?
|
|
|
|
|
FROM notesrepech
|
|
|
|
|
WHERE etudiant_id = ? AND annee_scolaire = ?`,
|
|
|
|
|
[nextYear.code, inscription.etudiant_id, prevYear.code]
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
totalProcessed++
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. Mettre à jour traitmentsystem (nettoyage)
|
|
|
|
|
await connection.query(
|
|
|
|
|
'UPDATE traitmentsystem SET is_finished = 1 WHERE is_finished = 0'
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
await connection.commit()
|
|
|
|
|
connection.release()
|
|
|
|
|
|
|
|
|
|
console.log(`✅ updateStudents: ${totalProcessed} inscription(s) créée(s).`)
|
|
|
|
|
return { success: true, message: `${totalProcessed} inscription(s) créée(s).`, totalProcessed }
|
|
|
|
|
} catch (error) {
|
|
|
|
|
await connection.rollback()
|
|
|
|
|
connection.release()
|
|
|
|
|
console.error('❌ updateStudents error:', error)
|
|
|
|
|
throw error
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function matiereSysteme(etudiant_niveau) {
|
|
|
|
|
let systeme
|
|
|
|
|
if (etudiant_niveau == 'L1') {
|
|
|
|
|
systeme = ['S1', 'S2']
|
|
|
|
|
} else if (etudiant_niveau == 'L2') {
|
|
|
|
|
systeme = ['S3', 'S4']
|
|
|
|
|
} else if (etudiant_niveau == 'L3') {
|
|
|
|
|
systeme = ['S5', 'S6']
|
|
|
|
|
} else if (etudiant_niveau == 'M1') {
|
|
|
|
|
systeme = ['S7', 'S8']
|
|
|
|
|
} else if (etudiant_niveau == 'M2') {
|
|
|
|
|
systeme = ['S9', 'S10']
|
|
|
|
|
} else if (etudiant_niveau == 'D1') {
|
|
|
|
|
systeme = ['S11', 'S12']
|
|
|
|
|
} else if (etudiant_niveau == 'D2') {
|
|
|
|
|
systeme = ['S13', 'S14']
|
|
|
|
|
} else if (etudiant_niveau == 'D3') {
|
|
|
|
|
systeme = ['S15', 'S16']
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return systeme
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function matiereSystemReverse(semestre) {
|
|
|
|
|
if (semestre == 'S1' || semestre == 'S2') {
|
|
|
|
|
return 'L1'
|
|
|
|
|
} else if (semestre == 'S3' || semestre == 'S4') {
|
|
|
|
|
return 'L2'
|
|
|
|
|
} else if (semestre == 'S5' || semestre == 'S6') {
|
|
|
|
|
return 'L3'
|
|
|
|
|
} else if (semestre == 'S7' || semestre == 'S8') {
|
|
|
|
|
return 'M1'
|
|
|
|
|
} else if (semestre == 'S9' || semestre == 'S10') {
|
|
|
|
|
return 'M2'
|
|
|
|
|
} else if (semestre == 'S11' || semestre == 'S12') {
|
|
|
|
|
return 'D1'
|
|
|
|
|
} else if (semestre == 'S13' || semestre == 'S14') {
|
|
|
|
|
return 'D2'
|
|
|
|
|
} else if (semestre == 'S15' || semestre == 'S16') {
|
|
|
|
|
return 'D3'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function getNessesarytable() {
|
|
|
|
|
try {
|
|
|
|
|
const sql = 'SELECT * FROM nessesaryTable'
|
|
|
|
|
const [rows] = await pool.query(sql)
|
|
|
|
|
return rows[0]
|
|
|
|
|
} catch (error) {
|
|
|
|
|
return error
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function updateNessesaryTable(id, multiplicateur) {
|
|
|
|
|
const sql = 'UPDATE nessesaryTable SET uniter_heure = ? WHERE id = ?'
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const [result] = await pool.query(sql, [multiplicateur, id])
|
|
|
|
|
|
|
|
|
|
if (result.affectedRows === 0) {
|
|
|
|
|
return {
|
|
|
|
|
success: false,
|
|
|
|
|
message: 'Année universitaire non trouvé.'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
success: true,
|
|
|
|
|
message: 'Année universitaire supprimé avec succès.'
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
return error
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
|
matiereSysteme,
|
|
|
|
|
updateCurrentYears,
|
|
|
|
|
updateStudents,
|
|
|
|
|
getNessesarytable,
|
|
|
|
|
updateNessesaryTable,
|
|
|
|
|
matiereSystemReverse
|
|
|
|
|
}
|