fix bêtises et update schema sql
This commit is contained in:
@@ -60,59 +60,85 @@ if ($action === 'update_salary_config') {
|
||||
|
||||
// 2. MISE A JOUR TABLEAU REPARTITION (AJAX)
|
||||
if ($action === 'update_allocation') {
|
||||
header('Content-Type: application/json');
|
||||
$date = $_POST['month_date'];
|
||||
$catId = $_POST['cat_id'];
|
||||
$person = $_POST['person']; // 'amount_alex' ou 'amount_laia'
|
||||
$value = floatval($_POST['value']);
|
||||
header('Content-Type: application/json');
|
||||
$date = $_POST['month_date'];
|
||||
$catId = (int)$_POST['cat_id'];
|
||||
$personId = (int)$_POST['person_id']; // 🟢 Reçoit l'ID de la personne directement !
|
||||
$value = floatval($_POST['value']);
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO pf_alloc_values (month_date, cat_id, $person) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE $person = VALUES($person)");
|
||||
$stmt->execute([$date, $catId, $value]);
|
||||
if ($catId <= 0 || $personId <= 0) {
|
||||
echo json_encode(['success' => false, 'error' => 'Données invalides.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO pf_alloc_values (month_date, cat_id, person_id, amount)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE amount = VALUES(amount)");
|
||||
$stmt->execute([$date, $catId, $personId, $value]);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 3. GESTION DES CATEGORIES (Ajout)
|
||||
if ($action === 'add_category') {
|
||||
$name = trim($_POST['name']);
|
||||
$target = trim($_POST['target']);
|
||||
$holiday_id = !empty($_POST['holiday_id']) ? (int)$_POST['holiday_id'] : null;
|
||||
|
||||
if (!empty($name)) {
|
||||
$stmt = $pdo->prepare("INSERT INTO pf_alloc_categories (name, target, holiday_id) VALUES (?, ?, ?)");
|
||||
$stmt->execute([$name, $target, $holiday_id]);
|
||||
}
|
||||
|
||||
// --- NOUVEAU : Réponse AJAX ---
|
||||
if (isset($_POST['ajax'])) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['success' => true]);
|
||||
try {
|
||||
$name = trim($_POST['name']);
|
||||
$transfer_dest = trim($_POST['transfer_dest'] ?? '');
|
||||
$target = floatval($_POST['target'] ?? 0);
|
||||
$holiday_id = !empty($_POST['holiday_id']) ? (int)$_POST['holiday_id'] : null;
|
||||
|
||||
if (!empty($name)) {
|
||||
$stmt = $pdo->prepare("INSERT INTO pf_alloc_categories (name, target, transfer_dest, holiday_id) VALUES (?, ?, ?, ?)");
|
||||
$stmt->execute([$name, $target, $transfer_dest, $holiday_id]);
|
||||
}
|
||||
|
||||
if (isset($_POST['ajax'])) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
header("Location: " . $_SERVER['HTTP_REFERER']);
|
||||
exit;
|
||||
} catch (Exception $e) {
|
||||
if (isset($_POST['ajax'])) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
die($e->getMessage());
|
||||
}
|
||||
header("Location: " . $_SERVER['HTTP_REFERER']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 4. MODIFICATION D'UNE CATEGORIE
|
||||
if ($action === 'update_category') {
|
||||
$id = (int)$_POST['cat_id'];
|
||||
$name = trim($_POST['name']);
|
||||
$target = trim($_POST['target']);
|
||||
$holiday_id = !empty($_POST['holiday_id']) ? (int)$_POST['holiday_id'] : null;
|
||||
try {
|
||||
$id = (int)$_POST['cat_id'];
|
||||
$name = trim($_POST['name']);
|
||||
$transfer_dest = trim($_POST['transfer_dest'] ?? '');
|
||||
$target = floatval($_POST['target'] ?? 0);
|
||||
$holiday_id = !empty($_POST['holiday_id']) ? (int)$_POST['holiday_id'] : null;
|
||||
|
||||
if ($id > 0 && !empty($name)) {
|
||||
$stmt = $pdo->prepare("UPDATE pf_alloc_categories SET name = ?, target = ?, holiday_id = ? WHERE id = ?");
|
||||
$stmt->execute([$name, $target, $holiday_id, $id]);
|
||||
}
|
||||
if ($id > 0 && !empty($name)) {
|
||||
$stmt = $pdo->prepare("UPDATE pf_alloc_categories SET name = ?, target = ?, transfer_dest = ?, holiday_id = ? WHERE id = ?");
|
||||
$stmt->execute([$name, $target, $transfer_dest, $holiday_id, $id]);
|
||||
}
|
||||
|
||||
// --- NOUVEAU : Réponse AJAX ---
|
||||
if (isset($_POST['ajax'])) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['success' => true]);
|
||||
if (isset($_POST['ajax'])) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
header("Location: " . $_SERVER['HTTP_REFERER']);
|
||||
exit;
|
||||
} catch (Exception $e) {
|
||||
if (isset($_POST['ajax'])) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
die($e->getMessage());
|
||||
}
|
||||
header("Location: " . $_SERVER['HTTP_REFERER']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 5. SUPPRESSION CATEGORIE
|
||||
@@ -136,43 +162,48 @@ if ($action === 'delete_category') {
|
||||
// 6. VALIDATION DES VIREMENTS (Complex Business Logic)
|
||||
if ($action === 'validate_transfers') {
|
||||
header('Content-Type: application/json');
|
||||
$person = $_POST['person'];
|
||||
$personId = (int)$_POST['person_id']; // Reçoit l'ID parent
|
||||
$monthDate = $_POST['month_date'];
|
||||
|
||||
try {
|
||||
$pdo->beginTransaction();
|
||||
|
||||
$stmtP = $pdo->prepare("SELECT name FROM pf_people WHERE id = ?");
|
||||
$stmtP->execute([$personId]);
|
||||
$dbPersonName = $stmtP->fetchColumn();
|
||||
if (!$dbPersonName) throw new Exception("Parent introuvable.");
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT v.*, c.name as cat_name, c.target, c.holiday_id
|
||||
FROM pf_alloc_values v
|
||||
SELECT v.amount, c.name as cat_name, c.transfer_dest, c.holiday_id
|
||||
FROM pf_alloc_values v
|
||||
JOIN pf_alloc_categories c ON v.cat_id = c.id
|
||||
WHERE v.month_date = ?
|
||||
WHERE v.month_date = ? AND v.person_id = ?
|
||||
");
|
||||
$stmt->execute([$monthDate]);
|
||||
$stmt->execute([$monthDate, $personId]);
|
||||
$budgetLines = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$transfersToDo = [];
|
||||
|
||||
foreach ($budgetLines as $line) {
|
||||
$amount = ($person === 'Alex') ? $line['amount_alex'] : $line['amount_laia'];
|
||||
if ($amount <= 0) continue;
|
||||
$amount = (float)$line['amount'];
|
||||
if ($amount <= 0) continue;
|
||||
|
||||
$target = trim($line['target']);
|
||||
$dest = trim($line['transfer_dest']);
|
||||
$catName = trim($line['cat_name']);
|
||||
$holidayId = $line['holiday_id'];
|
||||
$holidayId = $line['holiday_id'];
|
||||
|
||||
$targetOwner = null;
|
||||
if ($target === 'vers L.Perso') { $targetOwner = $person; }
|
||||
elseif ($target === 'vers L.Pol') { $targetOwner = 'Pol'; }
|
||||
elseif ($target === 'vers L.Pep') { $targetOwner = 'Pep'; }
|
||||
elseif ($target === 'vers commune') { continue; }
|
||||
if ($dest === 'vers L.Perso') { $targetOwner = $dbPersonName; }
|
||||
elseif ($dest === 'vers L.Pol') { $targetOwner = 'Pol'; }
|
||||
elseif ($dest === 'vers L.Pep') { $targetOwner = 'Pep'; }
|
||||
elseif ($dest === 'vers commune') { continue; }
|
||||
|
||||
if ($targetOwner) {
|
||||
if (!isset($transfersToDo[$targetOwner])) {
|
||||
$transfersToDo[$targetOwner] = ['total_add' => 0, 'cats' => []];
|
||||
}
|
||||
$transfersToDo[$targetOwner]['total_add'] += $amount;
|
||||
|
||||
|
||||
if (!isset($transfersToDo[$targetOwner]['cats'][$catName])) {
|
||||
$transfersToDo[$targetOwner]['cats'][$catName] = ['amount' => 0, 'holiday_id' => $holidayId];
|
||||
}
|
||||
@@ -181,7 +212,6 @@ if ($action === 'validate_transfers') {
|
||||
}
|
||||
|
||||
foreach ($transfersToDo as $owner => $data) {
|
||||
// A. VERIFIER EXISTENCE (Inchangé)
|
||||
$stmtCheck = $pdo->prepare("SELECT COUNT(*) FROM pf_savings WHERE owner = ? AND month_date = ? AND category = 'TOTAL_BANQUE'");
|
||||
$stmtCheck->execute([$owner, $monthDate]);
|
||||
$exists = $stmtCheck->fetchColumn() > 0;
|
||||
@@ -200,54 +230,38 @@ if ($action === 'validate_transfers') {
|
||||
}
|
||||
}
|
||||
|
||||
// B. UPDATE TOTAL (Inchangé)
|
||||
$stmtUpdTotal = $pdo->prepare("UPDATE pf_savings SET amount = amount + ? WHERE owner = ? AND month_date = ? AND category = 'TOTAL_BANQUE'");
|
||||
$stmtUpdTotal->execute([$data['total_add'], $owner, $monthDate]);
|
||||
|
||||
// C. UPDATE CATÉGORIES (Modifié pour gérer le holiday_id)
|
||||
foreach ($data['cats'] as $catName => $catInfo) {
|
||||
$catAmount = $catInfo['amount'];
|
||||
$catHolidayId = $catInfo['holiday_id']; // NOUVEAU
|
||||
$catHolidayId = $catInfo['holiday_id'];
|
||||
|
||||
if ($catName === 'Eco Alex' || $catName === 'Eco Laia') { continue; }
|
||||
if (strpos($catName, 'Eco P') === 0) { continue; }
|
||||
|
||||
$stmtCheckCat = $pdo->prepare("SELECT id FROM pf_savings WHERE owner = ? AND month_date = ? AND category = ?");
|
||||
$stmtCheckCat->execute([$owner, $monthDate, $catName]);
|
||||
$catId = $stmtCheckCat->fetchColumn();
|
||||
|
||||
if ($catId) {
|
||||
// Update : On actualise aussi le holiday_id au cas où il aurait changé
|
||||
$stmtUpdateCat = $pdo->prepare("UPDATE pf_savings SET amount = amount + ?, holiday_id = ? WHERE id = ?");
|
||||
$stmtUpdateCat->execute([$catAmount, $catHolidayId, $catId]);
|
||||
} else {
|
||||
// Insert
|
||||
$stmtInsertCat = $pdo->prepare("INSERT INTO pf_savings (month_date, owner, category, amount, holiday_id) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmtInsertCat->execute([$monthDate, $owner, $catName, $catAmount, $catHolidayId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. ENREGISTRER LA VALIDATION (Mise à jour table existante)
|
||||
|
||||
// a. Trouver l'ID de la catégorie système
|
||||
$stmtSys = $pdo->prepare("SELECT id FROM pf_alloc_categories WHERE name = 'SYSTEM_VALIDATION' LIMIT 1");
|
||||
$stmtSys->execute();
|
||||
$sysCatId = $stmtSys->fetchColumn();
|
||||
|
||||
if ($sysCatId) {
|
||||
|
||||
if ($person === 'Alex') {
|
||||
$sql = "INSERT INTO pf_alloc_values (month_date, cat_id, amount_alex, amount_laia)
|
||||
VALUES (?, ?, 1, 0)
|
||||
ON DUPLICATE KEY UPDATE amount_alex = 1";
|
||||
} else {
|
||||
$sql = "INSERT INTO pf_alloc_values (month_date, cat_id, amount_alex, amount_laia)
|
||||
VALUES (?, ?, 0, 1)
|
||||
ON DUPLICATE KEY UPDATE amount_laia = 1";
|
||||
}
|
||||
|
||||
$stmtVal = $pdo->prepare($sql);
|
||||
$stmtVal->execute([$monthDate, $sysCatId]);
|
||||
$stmtVal = $pdo->prepare("INSERT INTO pf_alloc_values (month_date, cat_id, person_id, amount)
|
||||
VALUES (?, ?, ?, 1)
|
||||
ON DUPLICATE KEY UPDATE amount = 1");
|
||||
$stmtVal->execute([$monthDate, $sysCatId, $personId]);
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
@@ -258,6 +272,4 @@ if ($action === 'validate_transfers') {
|
||||
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
||||
}
|
||||
exit;
|
||||
|
||||
|
||||
}
|
||||
@@ -16,7 +16,6 @@ foreach ($budgetParents as $index => $parent) {
|
||||
$parentMapping[] = [
|
||||
'id' => (int)$parent['id'],
|
||||
'name' => $parent['name'],
|
||||
'db_field' => 'amount_p' . $num,
|
||||
'css' => 'p' . $num,
|
||||
'color' => $parent['color'] ?? (($num === 1) ? '#0891b2' : '#f59e0b')
|
||||
];
|
||||
@@ -52,7 +51,6 @@ for ($i = 0; $i < 6; $i++) {
|
||||
$prevMonthLink = date('Y-m-01', strtotime("-1 month", $focusTs));
|
||||
$nextMonthLink = date('Y-m-01', strtotime("+1 month", $focusTs));
|
||||
|
||||
// Récupération des Cycles configurés dans pf_notes
|
||||
$cycleConfigs = [];
|
||||
$stmtNotes = $pdo->query("SELECT reference_id, content FROM pf_notes WHERE note_type = 'month_config'");
|
||||
while ($row = $stmtNotes->fetch(PDO::FETCH_ASSOC)) {
|
||||
@@ -63,14 +61,14 @@ while ($row = $stmtNotes->fetch(PDO::FETCH_ASSOC)) {
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Récupération Valeurs Répartition
|
||||
// 5. Récupération Valeurs Répartition Relationnelles
|
||||
$inQuery = implode(',', array_fill(0, count($months), '?'));
|
||||
$stmt = $pdo->prepare("SELECT * FROM pf_alloc_values WHERE month_date IN ($inQuery)");
|
||||
$stmt->execute($months);
|
||||
|
||||
$allocs = [];
|
||||
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$allocs[$row['month_date']][$row['cat_id']] = $row;
|
||||
$allocs[$row['month_date']][$row['cat_id']][$row['person_id']] = (float)$row['amount'];
|
||||
}
|
||||
|
||||
// 6. Récupération de l'ID de la catégorie système
|
||||
@@ -78,7 +76,7 @@ $sysCatId = null;
|
||||
foreach ($cats as $key => $c) {
|
||||
if ($c['name'] === 'SYSTEM_VALIDATION') {
|
||||
$sysCatId = $c['id'];
|
||||
unset($cats[$key]);
|
||||
unset($cats[$key]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -86,14 +84,10 @@ foreach ($cats as $key => $c) {
|
||||
// Statuts de validation
|
||||
$focusDate = $months[0];
|
||||
$isValidated = [];
|
||||
if ($sysCatId && isset($allocs[$focusDate][$sysCatId])) {
|
||||
$row = $allocs[$focusDate][$sysCatId];
|
||||
foreach ($parentMapping as $map) {
|
||||
$isValidated[$map['css']] = ($row[$map['db_field']] == 1);
|
||||
}
|
||||
} else {
|
||||
foreach ($parentMapping as $map) {
|
||||
$isValidated[$map['css']] = false;
|
||||
foreach ($parentMapping as $map) {
|
||||
$isValidated[$map['css']] = false;
|
||||
if ($sysCatId && isset($allocs[$focusDate][$sysCatId][$map['id']])) {
|
||||
$isValidated[$map['css']] = ($allocs[$focusDate][$sysCatId][$map['id']] == 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,13 +104,13 @@ function getTranslatedMonthName($dateString) {
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="prev-container" style="--p1-main: <?= $parentMapping[0]['color'] ?>; --p2-main: <?= $parentMapping[1]['color'] ?>;">
|
||||
<div class="prev-container" style="--p1-main: <?= $parentMapping[0]['color'] ?>; --p2-main: <?= $parentMapping[1]['color'] ?? '#f59e0b' ?>;">
|
||||
|
||||
<div>
|
||||
<div class="prev-section-header">
|
||||
<h2><?= tr('bud_prev_incomes') ?> <?= $currentYear ?></h2>
|
||||
</div>
|
||||
|
||||
|
||||
<table class="prev-salary-table">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -130,9 +124,9 @@ function getTranslatedMonthName($dateString) {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
foreach ($parentMapping as $map):
|
||||
$d = $salaryConfig[$map['name']];
|
||||
<?php
|
||||
foreach ($parentMapping as $map):
|
||||
$d = $salaryConfig[$map['name']];
|
||||
$restant = $d['salary'] - ($d['mensualite'] + $d['frais_func'] + $d['eco_perso'] + $d['eco_family']);
|
||||
?>
|
||||
<tr data-person="<?= htmlspecialchars($map['name']) ?>">
|
||||
@@ -180,14 +174,14 @@ function getTranslatedMonthName($dateString) {
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-sticky header-cell"></th>
|
||||
<?php foreach ($months as $month):
|
||||
<?php foreach ($months as $month):
|
||||
$isCurrent = ($month == date('Y-m-01'));
|
||||
$cls = $isCurrent ? 'current' : '';
|
||||
$colspan = count($parentMapping) + 1;
|
||||
?>
|
||||
<th colspan="<?= $colspan ?>" class="th-month <?= $cls ?>">
|
||||
<span><?= getTranslatedMonthName($month) ?></span>
|
||||
<?php
|
||||
<?php
|
||||
if (isset($cycleConfigs[$month]) && !empty($cycleConfigs[$month]['start_date'])) {
|
||||
$cStart = date('d/m', strtotime($cycleConfigs[$month]['start_date']));
|
||||
echo "<div class='cycle-start-label'>" . sprintf(tr('bud_sav_from_date'), $cStart) . "</div>";
|
||||
@@ -227,11 +221,11 @@ function getTranslatedMonthName($dateString) {
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
|
||||
<?php foreach ($cats as $cat):
|
||||
<?php foreach ($cats as $cat):
|
||||
$isIndicative = (strpos($cat['name'], 'Eco P') === 0);
|
||||
$rowClass = $isIndicative ? 'row-indicative' : '';
|
||||
$inputClass = $isIndicative ? 'ignore-calc' : '';
|
||||
|
||||
$inputClass = $isIndicative ? 'ignore-calc' : '';
|
||||
|
||||
$catDisplayName = $cat['name'];
|
||||
if ($catDisplayName === 'Eco P1') $catDisplayName = 'Eco ' . $p1_name;
|
||||
if ($catDisplayName === 'Eco P2') $catDisplayName = 'Eco ' . $p2_name;
|
||||
@@ -239,34 +233,38 @@ function getTranslatedMonthName($dateString) {
|
||||
<tr class="<?= $rowClass ?>">
|
||||
<td class="col-sticky">
|
||||
<div class="cat-name-label">
|
||||
<?= htmlspecialchars($catDisplayName) ?>
|
||||
<?= htmlspecialchars($catDisplayName) ?>
|
||||
<?php if(!empty($cat['holiday_id'])) echo " 🌴"; ?>
|
||||
<?php if($isIndicative): ?><span>Info</span><?php endif; ?>
|
||||
</div>
|
||||
<div class="cat-target-label">
|
||||
<?= htmlspecialchars($cat['target']) ?>
|
||||
<?php if((float)$cat['target'] > 0) echo 'Obj: ' . round((float)$cat['target']) . '€ '; ?>
|
||||
<?php if(!empty($cat['transfer_dest'])) echo '➔ ' . htmlspecialchars($cat['transfer_dest']); ?>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row-actions">
|
||||
<button type="button" class="btn-icon-action edit" title="<?= tr('edit') ?>" data-id="<?= $cat['id'] ?>" data-name="<?= htmlspecialchars($cat['name']) ?>" data-target="<?= htmlspecialchars($cat['target']) ?>" data-holiday="<?= $cat['holiday_id'] ?? '' ?>" onclick="openEditModal(this)">✎</button>
|
||||
<button type="button" class="btn-icon-action edit" title="<?= tr('edit') ?>"
|
||||
data-id="<?= $cat['id'] ?>"
|
||||
data-name="<?= htmlspecialchars($cat['name']) ?>"
|
||||
data-target="<?= htmlspecialchars($cat['target'] ?? 0) ?>"
|
||||
data-transfer-dest="<?= htmlspecialchars($cat['transfer_dest'] ?? '') ?>"
|
||||
data-holiday="<?= $cat['holiday_id'] ?? '' ?>"
|
||||
onclick="openEditModal(this)">✎</button>
|
||||
<button type="button" onclick="deleteCategory(<?= $cat['id'] ?>)" class="btn-icon-action delete" title="<?= tr('delete') ?>">🗑️</button>
|
||||
</div>
|
||||
</td>
|
||||
<?php foreach ($months as $m):
|
||||
$val = $allocs[$m][$cat['id']] ?? [];
|
||||
?>
|
||||
<?php foreach ($months as $m): ?>
|
||||
<td class="txt-global sum-target" id="g_<?= $m ?>_<?= $cat['id'] ?>">0</td>
|
||||
|
||||
<?php foreach ($parentMapping as $map):
|
||||
$dbField = $map['db_field'];
|
||||
$cellValue = isset($val[$dbField]) ? $val[$dbField] : 0;
|
||||
|
||||
<?php foreach ($parentMapping as $map):
|
||||
$cellValue = $allocs[$m][$cat['id']][$map['id']] ?? 0;
|
||||
?>
|
||||
<td>
|
||||
<input type="number" step="1" class="prev-input txt-<?= $map['css'] ?> inp-<?= $map['css'] ?>-<?= $m ?> <?= $inputClass ?>"
|
||||
value="<?= $cellValue == 0 ? '' : round($cellValue) ?>"
|
||||
<input type="number" step="1" class="prev-input txt-<?= $map['css'] ?> inp-<?= $map['css'] ?>-<?= $m ?> <?= $inputClass ?>"
|
||||
value="<?= $cellValue == 0 ? '' : round($cellValue) ?>"
|
||||
placeholder="-"
|
||||
data-target="<?= htmlspecialchars($cat['target']) ?>"
|
||||
onchange="updateAlloc('<?= $m ?>', <?= $cat['id'] ?>, '<?= $dbField ?>', this)">
|
||||
data-transfer-dest="<?= htmlspecialchars($cat['transfer_dest'] ?? '') ?>"
|
||||
onchange="updateAlloc('<?= $m ?>', <?= $cat['id'] ?>, <?= $map['id'] ?>, this)">
|
||||
</td>
|
||||
<?php endforeach; ?>
|
||||
<?php endforeach; ?>
|
||||
@@ -282,21 +280,24 @@ function getTranslatedMonthName($dateString) {
|
||||
<h3>📝 <?= tr('bud_prev_notes_for') ?> <span><?= getTranslatedMonthName($focusDate) ?></span></h3>
|
||||
<span id="note-save-indicator" class="note-save-indicator">✓ <?= tr('bud_prev_saved') ?></span>
|
||||
</div>
|
||||
|
||||
|
||||
<textarea id="monthNoteArea" class="pf-input" rows="3" placeholder="<?= tr('bud_prev_notes_ph') ?>"><?= htmlspecialchars((string)$currentNote) ?></textarea>
|
||||
|
||||
|
||||
<div class="notes-footer">
|
||||
<button type="button" class="pf-btn" onclick="saveGenericNote('budget_prev', '<?= $focusDate ?>', document.getElementById('monthNoteArea').value)"><?= tr('bud_prev_save_note') ?></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
$focusMonth = $months[0];
|
||||
$focusMonth = $months[0];
|
||||
$targetsOrder = ['vers commune', 'vers L.Pol', 'vers L.Pep', 'vers L.Perso'];
|
||||
|
||||
$allTargets = $targetsOrder;
|
||||
foreach($cats as $c) {
|
||||
$t = trim($c['target']);
|
||||
if(!empty($t) && !in_array($t, $allTargets)) { $allTargets[] = $t; }
|
||||
$t = trim($c['transfer_dest'] ?? '');
|
||||
if(!empty($t) && !in_array($t, $allTargets)) {
|
||||
$allTargets[] = $t;
|
||||
}
|
||||
}
|
||||
$allTargets = array_unique($allTargets);
|
||||
?>
|
||||
@@ -306,7 +307,7 @@ function getTranslatedMonthName($dateString) {
|
||||
<div class="recap-header">
|
||||
<?= tr('bud_prev_transfers_to_make') ?> - <span><?= getTranslatedMonthName($focusMonth) ?></span>
|
||||
</div>
|
||||
|
||||
|
||||
<table class="recap-table">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -364,9 +365,13 @@ function getTranslatedMonthName($dateString) {
|
||||
<input type="text" name="name" class="pf-input" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="pf-label"><?= tr('bud_prev_label_target') ?></label>
|
||||
<select name="target" class="pf-input" required>
|
||||
<option value="" disabled selected>-- <?= tr('bud_prev_choose') ?> --</option>
|
||||
<label class="pf-label">Objectif Mensuel (€)</label>
|
||||
<input type="number" step="1" name="target" class="pf-input" placeholder="Ex: 150">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="pf-label">Destination Virement (Optionnel)</label>
|
||||
<select name="transfer_dest" class="pf-input">
|
||||
<option value="" selected>-- Aucune --</option>
|
||||
<option value="vers L.Pol">vers L.Pol</option>
|
||||
<option value="vers L.Pep">vers L.Pep</option>
|
||||
<option value="vers L.Perso">vers L.Perso</option>
|
||||
@@ -404,8 +409,13 @@ function getTranslatedMonthName($dateString) {
|
||||
<input type="text" name="name" id="edit_cat_name" class="pf-input" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="pf-label"><?= tr('bud_prev_label_target') ?></label>
|
||||
<select name="target" id="edit_cat_target" class="pf-input" required>
|
||||
<label class="pf-label">Objectif Mensuel (€)</label>
|
||||
<input type="number" step="1" name="target" id="edit_cat_target" class="pf-input" placeholder="Ex: 150">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="pf-label">Destination Virement (Optionnel)</label>
|
||||
<select name="transfer_dest" id="edit_cat_transfer_dest" class="pf-input">
|
||||
<option value="">-- Aucune --</option>
|
||||
<option value="vers L.Pol">vers L.Pol</option>
|
||||
<option value="vers L.Pep">vers L.Pep</option>
|
||||
<option value="vers L.Perso">vers L.Perso</option>
|
||||
@@ -452,6 +462,7 @@ window.I18N = {
|
||||
|
||||
window.CONFIG = window.CONFIG || {};
|
||||
window.CONFIG.parentMapping = <?= json_encode($parentMapping) ?>;
|
||||
window.CONFIG.CURRENCY = '<?= defined('CURRENCY') ? CURRENCY : "€" ?>';
|
||||
|
||||
const currentYear = <?= $currentYear ?>;
|
||||
const months = <?= json_encode($months) ?>;
|
||||
@@ -460,7 +471,8 @@ function openEditModal(btn) {
|
||||
document.getElementById('edit_cat_id').value = btn.getAttribute('data-id');
|
||||
document.getElementById('edit_cat_name').value = btn.getAttribute('data-name');
|
||||
document.getElementById('edit_cat_target').value = btn.getAttribute('data-target');
|
||||
document.getElementById('edit_cat_holiday').value = btn.getAttribute('data-holiday');
|
||||
document.getElementById('edit_cat_transfer_dest').value = btn.getAttribute('data-transfer-dest');
|
||||
document.getElementById('edit_cat_holiday').value = btn.getAttribute('data-holiday');
|
||||
document.getElementById('editCatModal').style.display = 'flex';
|
||||
document.body.classList.add('no-scroll');
|
||||
}
|
||||
@@ -474,7 +486,7 @@ function updateSalary(person, input) {
|
||||
const ecoF = parseFloat(row.querySelector('[data-field="eco_family"]').value) || 0;
|
||||
|
||||
const restant = salary - (mens + frais + ecoP + ecoF);
|
||||
|
||||
|
||||
const parentMap = window.CONFIG.parentMapping.find(m => m.name === person);
|
||||
if(parentMap) {
|
||||
document.getElementById('restant_' + parentMap.css).innerText = Math.round(restant).toLocaleString(window.appLang) + ' €';
|
||||
@@ -484,8 +496,8 @@ function updateSalary(person, input) {
|
||||
recalcAllAllocations();
|
||||
}
|
||||
|
||||
function updateAlloc(month, catId, personField, input) {
|
||||
saveData('update_allocation', { month_date: month, cat_id: catId, person: personField, value: input.value || 0 });
|
||||
function updateAlloc(month, catId, personId, input) {
|
||||
saveData('update_allocation', { month_date: month, cat_id: catId, person_id: personId, value: input.value || 0 });
|
||||
recalcAllAllocations();
|
||||
}
|
||||
|
||||
@@ -504,12 +516,12 @@ function duplicateMonth() {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
};
|
||||
|
||||
const sourceName = formatMonth(sourceDateStr);
|
||||
const targetName = formatMonth(targetDateStr);
|
||||
const sourceName = formatMonth(sourceDateStr);
|
||||
const targetName = formatMonth(targetDateStr);
|
||||
const message = window.I18N['bud_prev_confirm_copy'].replace('%s', sourceName).replace('%t', targetName);
|
||||
|
||||
if(!confirm(message)) return;
|
||||
|
||||
|
||||
const firstCss = parentMap[0].css;
|
||||
document.querySelectorAll('.inp-' + firstCss + '-' + sourceDateStr).forEach(sourceInput => {
|
||||
const catIdMatch = sourceInput.getAttribute('onchange').match(/, (\d+),/);
|
||||
@@ -520,9 +532,9 @@ function duplicateMonth() {
|
||||
parentMap.forEach(map => {
|
||||
const sInp = row.querySelector('.inp-' + map.css + '-' + sourceDateStr);
|
||||
const tInp = row.querySelector('.inp-' + map.css + '-' + targetDateStr);
|
||||
if(sInp && tInp) {
|
||||
tInp.value = sInp.value;
|
||||
updateAlloc(targetDateStr, catId, map.db_field, tInp);
|
||||
if(sInp && tInp) {
|
||||
tInp.value = sInp.value;
|
||||
updateAlloc(targetDateStr, catId, map.id, tInp);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -548,7 +560,7 @@ function recalcAllAllocations() {
|
||||
}
|
||||
globalSum += val;
|
||||
});
|
||||
|
||||
|
||||
const onchangeStr = inp.getAttribute('onchange');
|
||||
const matches = onchangeStr.match(/, (\d+),/);
|
||||
if(matches && matches[1]) {
|
||||
@@ -561,7 +573,7 @@ function recalcAllAllocations() {
|
||||
parentMap.forEach(map => {
|
||||
const sumEl = document.getElementById('total_' + map.css + '_' + m);
|
||||
if(sumEl) sumEl.innerText = Math.round(sums[map.css]) + ' €';
|
||||
|
||||
|
||||
totalGlobal += sums[map.css];
|
||||
|
||||
const budget = parseFloat(document.getElementById('eco_family_' + map.css).value) || 0;
|
||||
@@ -570,16 +582,16 @@ function recalcAllAllocations() {
|
||||
const elRest = document.getElementById('restant_alloc_' + map.css + '_' + m);
|
||||
if (elRest) {
|
||||
elRest.innerText = Math.round(rest) + ' €';
|
||||
elRest.className = 'val-' + (rest >= 0 ? 'ok' : 'ko') + ' sum-target';
|
||||
elRest.className = 'val-' + (rest >= 0 ? 'ok' : 'ko') + ' sum-target';
|
||||
}
|
||||
});
|
||||
|
||||
const globEl = document.getElementById('total_global_' + m);
|
||||
if(globEl) globEl.innerText = Math.round(totalGlobal) + ' €';
|
||||
});
|
||||
|
||||
|
||||
updateSummaryTable();
|
||||
if(isSumModeActive) updateSumResult();
|
||||
if(isSumModeActive) updateSumResult();
|
||||
}
|
||||
|
||||
function updateSummaryTable() {
|
||||
@@ -591,12 +603,12 @@ function updateSummaryTable() {
|
||||
parentMap.forEach(map => {
|
||||
grandTotals[map.css] = 0;
|
||||
dataByTarget[map.css] = {};
|
||||
|
||||
|
||||
document.querySelectorAll('.inp-' + map.css + '-' + focusMonth).forEach(inp => {
|
||||
const target = inp.getAttribute('data-target');
|
||||
if(target) {
|
||||
if(!dataByTarget[map.css][target]) dataByTarget[map.css][target] = 0;
|
||||
dataByTarget[map.css][target] += (parseFloat(inp.value) || 0);
|
||||
const dest = inp.getAttribute('data-transfer-dest');
|
||||
if(dest) {
|
||||
if(!dataByTarget[map.css][dest]) dataByTarget[map.css][dest] = 0;
|
||||
dataByTarget[map.css][dest] += (parseFloat(inp.value) || 0);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -604,7 +616,7 @@ function updateSummaryTable() {
|
||||
const tbody = document.querySelector('.recap-table tbody');
|
||||
if(tbody) {
|
||||
Array.from(tbody.rows).forEach(row => {
|
||||
const targetName = row.cells[0].innerText.trim();
|
||||
const targetName = row.cells[0].innerText.trim();
|
||||
let globalSum = 0;
|
||||
|
||||
parentMap.forEach((map, idx) => {
|
||||
@@ -624,7 +636,7 @@ function updateSummaryTable() {
|
||||
if(grandEl) grandEl.innerText = Math.round(grandTotals[map.css]).toLocaleString(window.appLang) + ' ' + window.CONFIG.CURRENCY;
|
||||
totalGrandGlobal += grandTotals[map.css];
|
||||
});
|
||||
|
||||
|
||||
const globGrandEl = document.getElementById('grand_total_global');
|
||||
if(globGrandEl) globGrandEl.innerText = Math.round(totalGrandGlobal).toLocaleString(window.appLang) + ' ' + window.CONFIG.CURRENCY;
|
||||
}
|
||||
@@ -637,17 +649,17 @@ function saveData(action, data) {
|
||||
}
|
||||
|
||||
function validateTransfers(personCss, month) {
|
||||
const msg = window.I18N['bud_prev_confirm_transfers'].replace('%p', personCss).replace('%m', month);
|
||||
if (!confirm(msg)) return;
|
||||
|
||||
const parentMap = window.CONFIG.parentMapping.find(m => m.css === personCss);
|
||||
const dbPersonName = parentMap ? parentMap.name : personCss;
|
||||
if (!parentMap) return;
|
||||
|
||||
const msg = window.I18N['bud_prev_confirm_transfers'].replace('%p', parentMap.name).replace('%m', month);
|
||||
if (!confirm(msg)) return;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'validate_transfers');
|
||||
formData.append('person', dbPersonName);
|
||||
formData.append('person_id', parentMap.id);
|
||||
formData.append('month_date', month);
|
||||
|
||||
|
||||
fetch('modules/budget/includes/api/save-budget.php', { method: 'POST', body: formData })
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
@@ -660,9 +672,9 @@ function validateTransfers(personCss, month) {
|
||||
function saveGenericNote(noteType, refId, content) {
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'save_note');
|
||||
formData.append('note_type', noteType);
|
||||
formData.append('reference_id', refId);
|
||||
formData.append('content', content);
|
||||
formData.append('note_type', noteType);
|
||||
formData.append('reference_id', refId);
|
||||
formData.append('content', content);
|
||||
|
||||
fetch('modules/budget/includes/api/save-budget.php', { method: 'POST', body: formData })
|
||||
.then(async r => {
|
||||
@@ -723,10 +735,10 @@ async function deleteCategory(id) {
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'delete_category');
|
||||
formData.append('id', id);
|
||||
formData.append('ajax', '1');
|
||||
formData.append('ajax', '1');
|
||||
try {
|
||||
const result = await pachaFetch('modules/budget/includes/api/save-budget.php', { method: 'POST', body: formData });
|
||||
if (result.success) window.location.reload();
|
||||
if (result.success) window.location.reload();
|
||||
} catch(e) { console.error(e); }
|
||||
}
|
||||
|
||||
@@ -734,7 +746,7 @@ document.addEventListener('click', function(e) {
|
||||
if (!isSumModeActive) return;
|
||||
const targetElement = e.target.closest('input[type="number"], .sum-target');
|
||||
if (targetElement) {
|
||||
e.preventDefault();
|
||||
e.preventDefault();
|
||||
if (selectedElementsForSum.has(targetElement)) {
|
||||
selectedElementsForSum.delete(targetElement);
|
||||
targetElement.classList.remove('sum-selected');
|
||||
@@ -758,12 +770,12 @@ document.querySelectorAll('#addCatModal form, #editCatModal form').forEach(form
|
||||
submitBtn.innerText = '⏳ ...';
|
||||
const formData = new FormData(form);
|
||||
formData.append('ajax', '1');
|
||||
const actionUrl = form.getAttribute('action');
|
||||
const actionUrl = form.getAttribute('action');
|
||||
const result = await pachaFetch(actionUrl, { method: 'POST', body: formData });
|
||||
if (result.success) {
|
||||
form.closest('.pf-modal').style.display = 'none';
|
||||
document.body.classList.remove('no-scroll');
|
||||
window.location.reload();
|
||||
window.location.reload();
|
||||
} else {
|
||||
alert((window.I18N['bud_err_tech'] || 'Erreur') + " : " + (result.error || "Inconnue"));
|
||||
}
|
||||
|
||||
@@ -57,12 +57,11 @@ if (isset($_POST['action']) && $_POST['action'] === 'reopen_month') {
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (isset($_POST['action']) && $_POST['action'] === 'save_import') {
|
||||
$count = 0;
|
||||
$stmtExp = $pdo->prepare("INSERT INTO pf_expenses (date_exp, gestion_month, category, label, amount, import_ref, budget_item_id, holiday_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmtRule = $pdo->prepare("INSERT INTO pf_import_rules (keyword, category) VALUES (?, ?) ON DUPLICATE KEY UPDATE category = VALUES(category)");
|
||||
// Mémorisation du mapping étendu (incluant budget_item_id)
|
||||
$stmtRule = $pdo->prepare("INSERT INTO pf_import_rules (keyword, category, budget_item_id) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE category = VALUES(category), budget_item_id = VALUES(budget_item_id)");
|
||||
|
||||
if (isset($_POST['lines']) && is_array($_POST['lines'])) {
|
||||
foreach ($_POST['lines'] as $line) {
|
||||
@@ -81,7 +80,7 @@ if (isset($_POST['action']) && $_POST['action'] === 'save_import') {
|
||||
|
||||
try {
|
||||
$stmtExp->execute([$dateToSave, $gestionMonthLine, $cat, $line['label'], $finalAmount, $line['ref'], $budgetItemId, $holidayId]);
|
||||
$stmtRule->execute([$line['label'], $cat]);
|
||||
$stmtRule->execute([$line['label'], $cat, $budgetItemId]);
|
||||
$count++;
|
||||
} catch (Exception $e) { continue; }
|
||||
}
|
||||
@@ -110,7 +109,15 @@ $showPreview = false;
|
||||
if (isset($_FILES['csv_file']) && $_FILES['csv_file']['error'] == 0) {
|
||||
$file = $_FILES['csv_file']['tmp_name'];
|
||||
$handle = fopen($file, "r");
|
||||
$rules = []; try { $rules = $pdo->query("SELECT keyword, category FROM pf_import_rules")->fetchAll(PDO::FETCH_KEY_PAIR); } catch(Exception $e){}
|
||||
|
||||
$rules = [];
|
||||
try {
|
||||
$stmtRules = $pdo->query("SELECT keyword, category, budget_item_id FROM pf_import_rules");
|
||||
while ($r = $stmtRules->fetch(PDO::FETCH_ASSOC)) {
|
||||
$rules[$r['keyword']] = ['cat' => $r['category'], 'budget_item_id' => $r['budget_item_id']];
|
||||
}
|
||||
} catch(Exception $e){}
|
||||
|
||||
$existingRefs = []; try { $existingRefs = $pdo->query("SELECT import_ref FROM pf_expenses WHERE import_ref IS NOT NULL")->fetchAll(PDO::FETCH_COLUMN); } catch(Exception $e){}
|
||||
fgetcsv($handle, 1000, ";", "\"", "\\");
|
||||
|
||||
@@ -129,9 +136,16 @@ if (isset($_FILES['csv_file']) && $_FILES['csv_file']['error'] == 0) {
|
||||
$isDuplicate = in_array($uniqueKey, $existingRefs);
|
||||
|
||||
$suggestedCat = '';
|
||||
foreach ($rules as $kw => $c) { if (stripos($label, $kw) !== false) { $suggestedCat = $c; break; } }
|
||||
$suggestedItemId = null;
|
||||
foreach ($rules as $kw => $ruleData) {
|
||||
if (stripos($label, $kw) !== false) {
|
||||
$suggestedCat = $ruleData['cat'];
|
||||
$suggestedItemId = $ruleData['budget_item_id'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$csvData[] = ['date'=>$dateSql, 'label'=>$label, 'amount'=>$amount, 'cat'=>$suggestedCat, 'ref'=>$uniqueKey, 'is_duplicate'=>$isDuplicate, 'is_credit'=>$isCredit];
|
||||
$csvData[] = ['date'=>$dateSql, 'label'=>$label, 'amount'=>$amount, 'cat'=>$suggestedCat, 'suggested_item_id'=>$suggestedItemId, 'ref'=>$uniqueKey, 'is_duplicate'=>$isDuplicate, 'is_credit'=>$isCredit];
|
||||
}
|
||||
fclose($handle);
|
||||
$showPreview = true;
|
||||
@@ -224,6 +238,7 @@ $categoriesConfig = [
|
||||
'School' => ['type'=>'debit', 'label'=>tr('cat_school'), 'budget'=>$budget_school, 'color'=>'#10b981', 'suggestions'=>[]],
|
||||
'Frais' => ['type'=>'debit', 'label'=>tr('cat_fixed'), 'budget'=>$budget_frais, 'color'=>'#ef4444', 'suggestions'=>[]],
|
||||
'Autres' => ['type'=>'debit', 'label'=>tr('cat_others'), 'budget'=>$budget_autres, 'color'=>'#64748b', 'suggestions'=>['Restaurant', 'Cadeau']],
|
||||
'Apports' => ['type'=>'debit', 'label'=>tr('cat_contributions') ?? 'Apports & Projets', 'budget'=>0, 'color'=>'#0ea5e9', 'suggestions'=>['Alex', 'Laia', 'Remboursement']],
|
||||
'LivretA' => ['type'=>'debit', 'label'=>tr('cat_savings'),'budget'=>0, 'color'=>'#8b5cf6', 'suggestions'=>['Virement']]
|
||||
];
|
||||
|
||||
@@ -695,11 +710,15 @@ $monthName = $monthNames[(int)$viewM] . ' ' . $viewY;
|
||||
</select>
|
||||
<select name="lines[<?= $idx ?>][budget_item_id]" class="pf-input select-frais" onchange="checkValidation()" style="display:none; padding:4px; font-size:0.85rem; flex:1;" disabled>
|
||||
<option value="">-- <?= tr('bud_is_charge') ?> --</option>
|
||||
<?php foreach ($fixedChargesList as $fc): ?><option value="<?= $fc['id'] ?>"><?= htmlspecialchars($fc['name']) ?></option><?php endforeach; ?>
|
||||
<?php foreach ($fixedChargesList as $fc): ?>
|
||||
<option value="<?= $fc['id'] ?>" <?= ($row['suggested_item_id'] == $fc['id']) ? 'selected' : '' ?>><?= htmlspecialchars($fc['name']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<select name="lines[<?= $idx ?>][budget_item_id]" class="pf-input select-income" onchange="checkValidation()" style="display:none; padding:4px; font-size:0.85rem; flex:1;" disabled>
|
||||
<option value="">-- <?= tr('bud_is_income') ?> --</option>
|
||||
<?php foreach ($incomeList as $inc): ?><option value="<?= $inc['id'] ?>"><?= htmlspecialchars($inc['name']) ?></option><?php endforeach; ?>
|
||||
<?php foreach ($incomeList as $inc): ?>
|
||||
<option value="<?= $inc['id'] ?>" <?= ($row['suggested_item_id'] == $inc['id']) ? 'selected' : '' ?>><?= htmlspecialchars($inc['name']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
@@ -792,10 +811,14 @@ function openEditModal(e) {
|
||||
else if (e.category === 'Income') document.getElementById('incomeSelect').value = e.budget_item_id;
|
||||
}
|
||||
|
||||
function handleLineCatChange(select) {
|
||||
function handleLineCatChange(select, isInit = false) {
|
||||
const row = select.closest('tr');
|
||||
const fSel = row.querySelector('.select-frais'); const iSel = row.querySelector('.select-income');
|
||||
fSel.style.display = 'none'; iSel.style.display = 'none'; fSel.value = ''; iSel.value = ''; fSel.disabled = true; iSel.disabled = true;
|
||||
|
||||
fSel.style.display = 'none'; iSel.style.display = 'none';
|
||||
if (!isInit) { fSel.value = ''; iSel.value = ''; }
|
||||
fSel.disabled = true; iSel.disabled = true;
|
||||
|
||||
if (select.value === 'Frais') { fSel.style.display = 'block'; fSel.disabled = false; }
|
||||
else if (select.value === 'Income') { iSel.style.display = 'block'; iSel.disabled = false; }
|
||||
checkValidation();
|
||||
@@ -815,7 +838,10 @@ function checkValidation() {
|
||||
else { btn.disabled = false; btn.style.opacity=1; msg.style.display='none'; }
|
||||
}
|
||||
|
||||
if(document.getElementById('formMapping')) { document.querySelectorAll('.line-select').forEach(s => handleLineCatChange(s)); checkValidation(); }
|
||||
if(document.getElementById('formMapping')) {
|
||||
document.querySelectorAll('.line-select').forEach(s => handleLineCatChange(s, true));
|
||||
checkValidation();
|
||||
}
|
||||
|
||||
window.addEventListener('click', (e) => {
|
||||
if (e.target.classList.contains('pf-modal')) {
|
||||
@@ -826,7 +852,7 @@ window.addEventListener('click', (e) => {
|
||||
|
||||
// --- 2. SUPPRESSION ASYNCHRONE ---
|
||||
async function deleteExpense(id) {
|
||||
const confirmed = await pachaConfirm("Suppression", tr('bud_confirm_delete'));
|
||||
const confirmed = await pachaConfirm("Suppression", window.I18N['bud_confirm_delete']);
|
||||
if (!confirmed) return;
|
||||
|
||||
const formData = new FormData();
|
||||
|
||||
Reference in New Issue
Block a user