@@ -12,7 +12,7 @@ $stmtSalaries->execute([$currentYear]);
|
|||||||
$salaries = $stmtSalaries->fetchAll(PDO::FETCH_ASSOC);
|
$salaries = $stmtSalaries->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// 3. Récupération des Items du Budget (Charges Fixes et Estimations)
|
// 3. Récupération des Items du Budget (Charges Fixes et Estimations)
|
||||||
$stmt = $pdo->query("SELECT * FROM pf_budget_items ORDER BY is_estimate ASC, sort_order ASC, name ASC");
|
$stmt = $pdo->query("SELECT * FROM pf_budget_items WHERE category != 'SAVINGS' ORDER BY is_estimate ASC, sort_order ASC, name ASC");
|
||||||
$items = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
$items = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// 4. Gestion du mois actif
|
// 4. Gestion du mois actif
|
||||||
@@ -21,22 +21,36 @@ $defaultActiveMonth = $stmtActive->fetchColumn() ?: date('Y-m-01');
|
|||||||
$currentMonth = isset($_GET['m']) ? str_pad((int)$_GET['m'], 2, '0', STR_PAD_LEFT) : date('m', strtotime($defaultActiveMonth));
|
$currentMonth = isset($_GET['m']) ? str_pad((int)$_GET['m'], 2, '0', STR_PAD_LEFT) : date('m', strtotime($defaultActiveMonth));
|
||||||
$viewMonthDate = "$currentYear-$currentMonth-01";
|
$viewMonthDate = "$currentYear-$currentMonth-01";
|
||||||
|
|
||||||
// 5. Récupération du Réel (Dépenses)
|
// 5. Récupération optimisée et unifiée du Réel
|
||||||
$stmtReal = $pdo->prepare("SELECT budget_item_id, SUM(amount) as total_real FROM pf_expenses WHERE gestion_month = ? AND budget_item_id IS NOT NULL GROUP BY budget_item_id");
|
// On récupère tout en une seule requête pour éviter les décalages entre ID et Catégorie
|
||||||
|
$stmtReal = $pdo->prepare("
|
||||||
|
SELECT budget_item_id, category, SUM(amount) as total_real
|
||||||
|
FROM pf_expenses
|
||||||
|
WHERE gestion_month = ?
|
||||||
|
GROUP BY budget_item_id, category
|
||||||
|
");
|
||||||
$stmtReal->execute([$viewMonthDate]);
|
$stmtReal->execute([$viewMonthDate]);
|
||||||
$realTotals = $stmtReal->fetchAll(PDO::FETCH_KEY_PAIR);
|
$allExpenses = $stmtReal->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
$stmtCatReal = $pdo->prepare("SELECT category, SUM(amount) as total_real FROM pf_expenses WHERE gestion_month = ? AND budget_item_id IS NULL GROUP BY category");
|
// On initialise les tableaux de correspondance
|
||||||
$stmtCatReal->execute([$viewMonthDate]);
|
$realTotalsById = []; // Pour les lignes liées par ID
|
||||||
$catTotals = $stmtCatReal->fetchAll(PDO::FETCH_KEY_PAIR);
|
$realTotalsByCat = []; // Pour les lignes orphelines (NULL) liées par Catégorie
|
||||||
|
|
||||||
$stmtLabels = $pdo->prepare("SELECT label, amount FROM pf_expenses WHERE gestion_month = ? AND budget_item_id IS NULL");
|
foreach ($allExpenses as $row) {
|
||||||
|
if (!empty($row['budget_item_id'])) {
|
||||||
|
$realTotalsById[$row['budget_item_id']] = (float)$row['total_real'];
|
||||||
|
} else {
|
||||||
|
$realTotalsByCat[$row['category']] = (float)$row['total_real'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Récupération des détails pour le mapping par mots-clés (si besoin de précision)
|
||||||
|
$stmtLabels = $pdo->prepare("SELECT label, amount, category FROM pf_expenses WHERE gestion_month = ? AND budget_item_id IS NULL");
|
||||||
$stmtLabels->execute([$viewMonthDate]);
|
$stmtLabels->execute([$viewMonthDate]);
|
||||||
$unlinkedExpenses = $stmtLabels->fetchAll(PDO::FETCH_ASSOC);
|
$unlinkedExpenses = $stmtLabels->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
$moisFr = ['', 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'];
|
// Gestion des libellés et totaux
|
||||||
$currentMonthName = tr('month_' . str_pad((int)$currentMonth, 2, '0', STR_PAD_LEFT)) . ' ' . $currentYear;
|
$currentMonthName = tr('month_' . str_pad((int)$currentMonth, 2, '0', STR_PAD_LEFT)) . ' ' . $currentYear;
|
||||||
|
|
||||||
$totalDepenses = 0;
|
$totalDepenses = 0;
|
||||||
$totalRevenus = 0;
|
$totalRevenus = 0;
|
||||||
?>
|
?>
|
||||||
@@ -88,24 +102,26 @@ $totalRevenus = 0;
|
|||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
|
|
||||||
<?php foreach ($items as $item):
|
<?php foreach ($items as $item):
|
||||||
|
// 1. Calculs de base
|
||||||
$targetAbs = abs((float)$item['amount']);
|
$targetAbs = abs((float)$item['amount']);
|
||||||
$amountToAdd = ($item['type'] === 'Annuel') ? $targetAbs / 12 : $targetAbs;
|
$amountToAdd = ($item['type'] === 'Annuel') ? $targetAbs / 12 : $targetAbs;
|
||||||
$totalDepenses += $amountToAdd;
|
$totalDepenses += $amountToAdd;
|
||||||
|
|
||||||
|
// 2. RÉINITIALISATION STRICTE ET CALCUL DU RÉEL
|
||||||
$realSum = 0;
|
$realSum = 0;
|
||||||
$hasMatchingExpense = false;
|
$hasMatchingExpense = false;
|
||||||
|
|
||||||
// A. Correspondance par ID direct
|
// A. Correspondance par ID direct (Priorité 1)
|
||||||
if (isset($realTotals[$item['id']])) {
|
if (isset($realTotalsById[$item['id']])) {
|
||||||
$realSum = $realTotals[$item['id']];
|
$realSum = (float)$realTotalsById[$item['id']];
|
||||||
$hasMatchingExpense = true;
|
$hasMatchingExpense = true;
|
||||||
}
|
}
|
||||||
// B. Correspondance par Catégorie système
|
// B. Correspondance par Catégorie système (Priorité 2 : rattrape les NULL de Juin)
|
||||||
elseif (!empty($item['category']) && isset($catTotals[$item['category']])) {
|
elseif (!empty($item['category']) && isset($realTotalsByCat[$item['category']])) {
|
||||||
$realSum = $catTotals[$item['category']];
|
$realSum = (float)$realTotalsByCat[$item['category']];
|
||||||
$hasMatchingExpense = true;
|
$hasMatchingExpense = true;
|
||||||
}
|
}
|
||||||
// C. Correspondance par mots-clés bancaires
|
// C. Correspondance par mots-clés bancaires (Priorité 3 : affinement manuel)
|
||||||
elseif (!empty($item['mapping_keywords'])) {
|
elseif (!empty($item['mapping_keywords'])) {
|
||||||
$keywords = array_map('trim', explode(',', $item['mapping_keywords']));
|
$keywords = array_map('trim', explode(',', $item['mapping_keywords']));
|
||||||
foreach ($unlinkedExpenses as $uexp) {
|
foreach ($unlinkedExpenses as $uexp) {
|
||||||
@@ -119,10 +135,12 @@ $totalRevenus = 0;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3. Finalisation de la ligne
|
||||||
$realAbs = abs($realSum);
|
$realAbs = abs($realSum);
|
||||||
|
// Un item est validé si le montant réel est proche du prévu
|
||||||
$isAutoChecked = ($hasMatchingExpense && ($realAbs >= ($targetAbs - 0.10)));
|
$isAutoChecked = ($hasMatchingExpense && ($realAbs >= ($targetAbs - 0.10)));
|
||||||
$rowClass = 'row-expense' . ($item['is_estimate'] ? ' row-estimate' : '');
|
$rowClass = 'row-expense' . ($item['is_estimate'] ? ' row-estimate' : '');
|
||||||
?>
|
?>
|
||||||
<tr class="<?= $rowClass ?>" style="border-bottom:1px solid var(--border-light);">
|
<tr class="<?= $rowClass ?>" style="border-bottom:1px solid var(--border-light);">
|
||||||
<td style="padding:15px;">
|
<td style="padding:15px;">
|
||||||
<strong><?= htmlspecialchars($item['name']) ?></strong>
|
<strong><?= htmlspecialchars($item['name']) ?></strong>
|
||||||
|
|||||||
@@ -230,9 +230,9 @@ while ($item = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
|||||||
$absAmount = abs((float)$item['amount']);
|
$absAmount = abs((float)$item['amount']);
|
||||||
$amt = ($item['type'] === 'Annuel') ? $absAmount / 12 : $absAmount;
|
$amt = ($item['type'] === 'Annuel') ? $absAmount / 12 : $absAmount;
|
||||||
$name = trim($item['name']);
|
$name = trim($item['name']);
|
||||||
$catCode = $item['category']; // Ex: FIXED, FMCG, INCOME...
|
$catCode = $item['category']; // Ex: FIXED, FMCG, INCOME ou income
|
||||||
|
|
||||||
$isIncome = (isset($categoriesConfig[$catCode]) && $categoriesConfig[$catCode]['db_type'] === 'Income');
|
$isIncome = (strtoupper($catCode) === 'INCOME' || (float)$item['amount'] > 0);
|
||||||
|
|
||||||
if ($isIncome) {
|
if ($isIncome) {
|
||||||
$incomeList[] = ['id' => $item['id'], 'name' => $name, 'amount' => $absAmount];
|
$incomeList[] = ['id' => $item['id'], 'name' => $name, 'amount' => $absAmount];
|
||||||
@@ -621,10 +621,11 @@ $monthName = $monthNames[(int)$viewM] . ' ' . $viewY;
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 🛠️ FIX VISUEL : On demande la personne concernée (Bénéficiaire) -->
|
||||||
<div class="form-group" id="blockInputIncome" style="margin-bottom:15px; display:none;">
|
<div class="form-group" id="blockInputIncome" style="margin-bottom:15px; display:none;">
|
||||||
<label class="pf-label"><?= tr('bud_expected_income') ?></label>
|
<label class="pf-label"><?= tr('bud_beneficiary') ?></label>
|
||||||
<select name="budget_item_id" id="incomeSelect" class="pf-input" disabled>
|
<select name="budget_item_id" id="incomeSelect" class="pf-input" disabled>
|
||||||
<option value=""><?= tr('bud_select_beneficiary') ?> </option>
|
<option value=""><?= tr('gift_filter_all_adults') ?></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'] ?>"><?= htmlspecialchars($inc['name']) ?></option><?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user