Initial commit
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
import db from '../db/index.js';
|
||||
|
||||
const JOB_NAME = 'auto_statut_retard';
|
||||
|
||||
/** Persiste une entrée dans job_logs */
|
||||
function writeLog({ status, nbChanges, details, errorMsg }) {
|
||||
try {
|
||||
db.prepare(`
|
||||
INSERT INTO job_logs (job_name, status, nb_changes, details, error_msg)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
`).run(JOB_NAME, status, nbChanges ?? 0, details ?? null, errorMsg ?? null);
|
||||
} catch (e) {
|
||||
console.error('[autoStatut] Impossible d\'écrire dans job_logs :', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Passe automatiquement au statut "en_retard" les investissements dont :
|
||||
* - le statut est actuellement "en_cours"
|
||||
* - la date_cible est renseignée et strictement antérieure à aujourd'hui
|
||||
*
|
||||
* Chaque passage est tracé dans investissement_historique avec le
|
||||
* type_evenement 'passage_auto_retard' pour conserver l'auditabilité.
|
||||
*
|
||||
* @returns {number} nombre d'investissements mis à jour
|
||||
*/
|
||||
export function checkStatutsRetard() {
|
||||
const candidats = db.prepare(`
|
||||
SELECT id, nom_projet, date_cible
|
||||
FROM investissements
|
||||
WHERE statut = 'en_cours'
|
||||
AND date_cible IS NOT NULL
|
||||
AND date_cible < date('now')
|
||||
`).all();
|
||||
|
||||
if (candidats.length === 0) {
|
||||
writeLog({ status: 'ok', nbChanges: 0, details: 'Aucun investissement en retard détecté' });
|
||||
return 0;
|
||||
}
|
||||
|
||||
const updateStmt = db.prepare(`
|
||||
UPDATE investissements
|
||||
SET statut = 'en_retard', updated_at = datetime('now')
|
||||
WHERE id = ?
|
||||
`);
|
||||
|
||||
const histStmt = db.prepare(`
|
||||
INSERT INTO investissement_historique
|
||||
(investissement_id, type_evenement, changements, notes)
|
||||
VALUES (?, 'passage_auto_retard', ?, ?)
|
||||
`);
|
||||
|
||||
const tx = db.transaction(() => {
|
||||
for (const inv of candidats) {
|
||||
updateStmt.run(inv.id);
|
||||
histStmt.run(
|
||||
inv.id,
|
||||
JSON.stringify([{
|
||||
champ: 'statut',
|
||||
label: 'Statut',
|
||||
ancienne_valeur: 'en_cours',
|
||||
nouvelle_valeur: 'en_retard',
|
||||
}]),
|
||||
`Passage automatique : date cible (${inv.date_cible}) dépassée`
|
||||
);
|
||||
}
|
||||
});
|
||||
tx();
|
||||
|
||||
const details = candidats
|
||||
.map(i => `"${i.nom_projet}" (id=${i.id}, date_cible=${i.date_cible})`)
|
||||
.join('; ');
|
||||
|
||||
writeLog({
|
||||
status: 'ok',
|
||||
nbChanges: candidats.length,
|
||||
details: `Passé en retard : ${details}`,
|
||||
});
|
||||
|
||||
console.log(`[autoStatut] ${candidats.length} investissement(s) passé(s) en retard : ${details}`);
|
||||
return candidats.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Démarre le job de vérification automatique des statuts.
|
||||
*
|
||||
* - Exécution immédiate au démarrage (rattrape les retards accumulés
|
||||
* pendant que le serveur était éteint).
|
||||
* - Puis répétition quotidienne, calée sur la prochaine minuit locale
|
||||
* afin de ne pas dériver au fil des redémarrages.
|
||||
*/
|
||||
export function startAutoStatutJob() {
|
||||
// Exécution initiale
|
||||
try {
|
||||
checkStatutsRetard();
|
||||
} catch (err) {
|
||||
console.error('[autoStatut] Erreur lors de la vérification initiale :', err);
|
||||
writeLog({ status: 'error', nbChanges: 0, errorMsg: err.message });
|
||||
}
|
||||
|
||||
// Calcule le délai jusqu'à la prochaine minuit locale
|
||||
function msUntilMidnight() {
|
||||
const now = new Date();
|
||||
const next = new Date(now);
|
||||
next.setHours(24, 0, 0, 0);
|
||||
return next.getTime() - now.getTime();
|
||||
}
|
||||
|
||||
// Planifie la première échéance à minuit, puis toutes les 24h (sans dérive)
|
||||
function scheduleDailyRun() {
|
||||
setTimeout(() => {
|
||||
try {
|
||||
checkStatutsRetard();
|
||||
} catch (err) {
|
||||
console.error('[autoStatut] Erreur lors de la vérification quotidienne :', err);
|
||||
writeLog({ status: 'error', nbChanges: 0, errorMsg: err.message });
|
||||
}
|
||||
scheduleDailyRun();
|
||||
}, msUntilMidnight());
|
||||
}
|
||||
|
||||
scheduleDailyRun();
|
||||
console.log(`[autoStatut] Job démarré — prochaine vérification dans ${Math.round(msUntilMidnight() / 60000)} min (minuit)`);
|
||||
}
|
||||
Reference in New Issue
Block a user