@@ -444,6 +444,13 @@ function renderMemberLeavesView(personId, memberLeaves) {
|
||||
<option value="12">${tr("month_dec") || "Décembre"}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="flex: 0 0 90px;">
|
||||
<label class="pf-label" style="font-size: 0.8rem;">Acquisition</label>
|
||||
<select id="new-member-leave-method" class="pf-input" style="width: 100%;">
|
||||
<option value="FIXED">Fixe</option>
|
||||
<option value="ACCUMULATED">Graduel</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="pf-btn pf-btn-primary" onclick="addMemberLeave(${personId})">Ajouter</button>
|
||||
</div>
|
||||
`;
|
||||
@@ -455,6 +462,8 @@ async function addMemberLeave(personId) {
|
||||
const leaveCode = document.getElementById("new-member-leave-type").value;
|
||||
const allowance = document.getElementById("new-member-leave-allowance").value;
|
||||
const resetMonth = document.getElementById("new-member-leave-reset").value;
|
||||
const method = document.getElementById("new-member-leave-method").value; // <-- Ajout
|
||||
fd.append("method", method);
|
||||
|
||||
if (!leaveCode) return showToast("Veuillez sélectionner un type", "error");
|
||||
|
||||
@@ -1265,15 +1274,16 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
|
||||
let alertHtml = "";
|
||||
const cMonth = parseInt(monthsToDisplay[0].split("-")[1]);
|
||||
if (endBal > 0) {
|
||||
if (type === "CP" && (cMonth === 5 || cMonth === 6))
|
||||
alertHtml = `<div class="fc-burn-alert" title="Alerte perte">🔥</div>`;
|
||||
else if (
|
||||
type === "JRA" &&
|
||||
(cMonth === 1 || cMonth === 12) &&
|
||||
endBal > 2
|
||||
)
|
||||
alertHtml = `<div class="fc-burn-alert" title="Perte imminente">🔥</div>`;
|
||||
|
||||
// On récupère le mois de renouvellement depuis la date (ex: "2000-06-01" -> 6)
|
||||
if (endBal > 0 && conf.date) {
|
||||
const resetMonth = parseInt(conf.date.split("-")[1]);
|
||||
// On alerte le mois même, ou le mois juste avant !
|
||||
const alertMonth = resetMonth - 1 === 0 ? 12 : resetMonth - 1;
|
||||
|
||||
if (cMonth === alertMonth || cMonth === resetMonth) {
|
||||
alertHtml = `<div class="fc-burn-alert" title="Alerte : Perte imminente !">🔥</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
cards += `<div class="fc-min-chip" title="Solde: ${fmt(startBal)}"><span class="type">${type}</span><span class="val">${fmt(endBal)}</span>${totalUsed > 0 ? `<span class="fc-used-badge">-${fmt(totalUsed)}</span>` : ""}${alertHtml}</div>`;
|
||||
|
||||
@@ -154,9 +154,12 @@ try {
|
||||
$type = strtoupper(trim($_POST['leave_type'] ?? ''));
|
||||
$allowance = (float)($_POST['allowance'] ?? 0);
|
||||
$resetMonth = (int)($_POST['reset_month'] ?? 1);
|
||||
|
||||
$method = in_array($_POST['method'] ?? '', ['FIXED', 'ACCUMULATED']) ? $_POST['method'] : 'FIXED';
|
||||
|
||||
if ($personId <= 0 || empty($type)) throw new Exception("Données invalides.");
|
||||
|
||||
// Vérification des doublons
|
||||
$check = $pdo->prepare("SELECT id FROM pf_person_leave_meta WHERE person_id = ? AND leave_type = ?");
|
||||
$check->execute([$personId, $type]);
|
||||
if ($check->rowCount() > 0) throw new Exception("Ce congé est déjà attribué à cette personne.");
|
||||
@@ -164,8 +167,8 @@ try {
|
||||
// On construit la date anniversaire avec le mois choisi par l'utilisateur
|
||||
$anniversaryDate = "2000-" . str_pad((string)$resetMonth, 2, "0", STR_PAD_LEFT) . "-01";
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO pf_person_leave_meta (person_id, leave_type, allowance, method, anniversary_date) VALUES (?, ?, ?, 'FIXED', ?)");
|
||||
$stmt->execute([$personId, $type, $allowance, $anniversaryDate]);
|
||||
$stmt = $pdo->prepare("INSERT INTO pf_person_leave_meta (person_id, leave_type, allowance, method, anniversary_date) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$personId, $type, $allowance, $method, $anniversaryDate]);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
|
||||
@@ -20,9 +20,12 @@ try {
|
||||
$inserted = [];
|
||||
|
||||
foreach ($eventsToSave as $event) {
|
||||
// 🔥 LE CORRECTIF : On initialise à 0 (car NOT NULL en base)
|
||||
$person_id = 0;
|
||||
// 🔥 SÉCURITÉ : On ignore l'itération si les données vitales manquent (évite le crash SQL)
|
||||
if (empty($event['date']) || empty($event['type'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$person_id = 0;
|
||||
if (!empty($event['person_id']) && is_numeric($event['person_id'])) {
|
||||
$person_id = (int)$event['person_id'];
|
||||
} elseif (!empty($event['person']) && is_numeric($event['person'])) {
|
||||
@@ -55,7 +58,7 @@ try {
|
||||
'inserted' => $inserted,
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
} catch (\Throwable $e) { // 🔥 LE CORRECTIF PRINCIPAL : \Throwable attrape AUSSI les erreurs fatales PHP !
|
||||
if (isset($pdo) && $pdo->inTransaction()) {
|
||||
$pdo->rollBack();
|
||||
}
|
||||
@@ -63,7 +66,7 @@ try {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'status' => 'error',
|
||||
'message' => 'Erreur SQL : ' . $e->getMessage()
|
||||
'message' => 'Erreur Serveur/SQL : ' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
?>
|
||||
Reference in New Issue
Block a user