Version 4.2.8 — Corrections cumulées 4.2.4-8

This commit is contained in:
2026-04-19 15:00:00 +02:00
parent 7f78493859
commit 565075933e
5 changed files with 1691 additions and 118 deletions
+173
View File
@@ -285,6 +285,144 @@ async function fetchCurrentUser(origin, phpsessid) {
return { name, login, service };
}
// ============================================================================
// v4.2.6 : Création d'absence
// ============================================================================
/**
* Envoie un POST vers plan_set_holidays_popup.php pour créer une absence.
* Format attendu (analysé depuis le HTML EasyVista) :
* Query params : PHPSESSID, MAIN_DIRECTORY, ROOT_DIRECTORY, current_date,
* empl_ids, begin_hour, end_hour, plagehoraire
* Body : start_date, start_time, end_date, end_time, label_guid, dialog_action
*
* @param {string} origin - "https://itsma.vd.ch" ou similaire
* @param {string} phpsessid
* @param {Object} opts - { techIds: string[], startDate: "DD/MM/YYYY",
* startTime: "HH:MM:SS", endDate, endTime,
* typeGuid, currentDate }
*/
async function submitAbsence(origin, phpsessid, opts) {
const emplIds = (opts.techIds || []).join(",");
if (!emplIds) throw new Error("Aucun technicien sélectionné");
const internalurltime = Math.floor(Date.now() / 1000);
const url = `${origin}/include/components/staff/planning/plan_set_holidays_popup.php`
+ `?PHPSESSID=${encodeURIComponent(phpsessid)}`
+ `&internalurltime=${internalurltime}`
+ `&MAIN_DIRECTORY=${encodeURIComponent("/")}`
+ `&ROOT_DIRECTORY=${encodeURIComponent("/ccv/data/www/itsma/htdocs/")}`
+ `&current_date=${encodeURIComponent(opts.currentDate)}`
+ `&empl_ids=${encodeURIComponent(emplIds)}`
+ `&begin_hour=8`
+ `&end_hour=18`
+ `&plagehoraire=0`;
const body = new URLSearchParams();
body.set("start_date", opts.startDate);
body.set("start_time", opts.startTime);
body.set("end_date", opts.endDate);
body.set("end_time", opts.endTime);
body.set("label_guid", opts.typeGuid);
body.set("dialog_action", "save_holidays");
console.log("[bg] submitAbsence →", url.substring(0, 140));
console.log("[bg] body:", body.toString());
const r = await fetch(url, {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: body.toString()
});
console.log("[bg] status =", r.status);
if (!r.ok) {
throw new Error("HTTP " + r.status);
}
const responseText = await r.text();
if (looksLikeLoginPage(responseText)) {
throw new Error("session_expired");
}
// Succès : on ne sait pas le format exact de la réponse EasyVista, on
// considère qu'un HTTP 200 non-login signifie succès.
return { status: r.status };
}
// ============================================================================
// v4.2.6 : Envoi sur douchette
// ============================================================================
/**
* Envoie la planification du jour sur la douchette des techs sélectionnés.
*
* Endpoint identifié (via l'inspection de la page EasyVista) :
* POST /include/components/staff/planning/plan_set_tech_planif_popup.php
* Query : PHPSESSID, current_date, empl_ids (CSV), begin_hour, end_hour,
* plagehoraire
* Body : dialog_action=save_planif
*
* Contrairement à l'absence, un seul POST suffit pour tous les techs (empl_ids
* est une CSV), pas besoin de boucler.
*
* @param {string} origin
* @param {string} phpsessid
* @param {Object} opts - { techIds, currentDate }
* @returns {{ okCount, errors }}
*/
async function submitDouchette(origin, phpsessid, opts) {
const techIds = opts.techIds || [];
if (techIds.length === 0) throw new Error("Aucun technicien sélectionné");
const emplIds = techIds.join(",");
const internalurltime = Math.floor(Date.now() / 1000);
const url = `${origin}/include/components/staff/planning/plan_set_tech_planif_popup.php`
+ `?PHPSESSID=${encodeURIComponent(phpsessid)}`
+ `&internalurltime=${internalurltime}`
+ `&MAIN_DIRECTORY=${encodeURIComponent("/")}`
+ `&ROOT_DIRECTORY=${encodeURIComponent("/ccv/data/www/itsma/htdocs/")}`
+ `&current_date=${encodeURIComponent(opts.currentDate)}`
+ `&empl_ids=${encodeURIComponent(emplIds)}`
+ `&begin_hour=8`
+ `&end_hour=18`
+ `&plagehoraire=0`;
const body = new URLSearchParams();
body.set("dialog_action", "save_planif");
console.log("[bg] submitDouchette →", url.substring(0, 160));
console.log("[bg] body:", body.toString());
console.log("[bg] techs:", emplIds);
try {
const r = await fetch(url, {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: body.toString()
});
console.log("[bg] status =", r.status);
if (r.status === 401 || r.status === 403) {
return { okCount: 0, errors: techIds.map(t => ({ techId: t, error: "session_expired" })) };
}
if (!r.ok) {
return { okCount: 0, errors: techIds.map(t => ({ techId: t, error: "HTTP " + r.status })) };
}
const responseText = await r.text();
if (looksLikeLoginPage(responseText)) {
return { okCount: 0, errors: techIds.map(t => ({ techId: t, error: "session_expired" })) };
}
return { okCount: techIds.length, errors: [] };
} catch (err) {
const msg = err && err.message ? err.message : String(err);
return { okCount: 0, errors: techIds.map(t => ({ techId: t, error: msg })) };
}
}
// ============================================================================
// Messages du viewer
// ============================================================================
@@ -412,6 +550,41 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
return;
}
if (msg.type === "submitAbsence") {
// v4.2.6 : crée une absence dans EasyVista via POST vers
// /include/components/staff/planning/plan_set_holidays_popup.php
const session = await findEasyVistaSession();
if (!session) {
sendResponse({ ok: false, error: "no_session" });
return;
}
try {
const result = await submitAbsence(session.origin, session.phpsessid, msg);
sendResponse({ ok: true, result });
} catch (err) {
sendResponse({ ok: false, error: err.message || String(err) });
}
return;
}
if (msg.type === "submitDouchette") {
// v4.2.6 : envoie la planification sur la douchette de chaque tech.
// On teste plusieurs URLs possibles (l'endpoint exact n'est pas dans
// le HTML statique que nous avons analysé).
const session = await findEasyVistaSession();
if (!session) {
sendResponse({ ok: false, error: "no_session" });
return;
}
try {
const result = await submitDouchette(session.origin, session.phpsessid, msg);
sendResponse({ ok: true, okCount: result.okCount, errors: result.errors });
} catch (err) {
sendResponse({ ok: false, error: err.message || String(err) });
}
return;
}
if (msg.type === "cleanupOldCaches") {
const removed = await cleanupOldCaches(msg.daysToKeep || 7);
sendResponse({ ok: true, removed });