fix import
Deploy HouseHub / deploy (push) Successful in 2s

This commit is contained in:
FeFeClochette committed 2026-10-11 19:10:23 +02:00
1 parent 165a0b371c
commit 7c25513336
1 file changed
+76 -15
+76 -15
View File
@@ -116,11 +116,27 @@ if (isset($_POST['action']) && $_POST['action'] === 'save_snapshot') {
// ============================================================================ // ============================================================================
$csvData = []; $csvData = [];
$showPreview = false; $showPreview = false;
$importError = null;
if (isset($_FILES['csv_file']) && $_FILES['csv_file']['error'] == 0) { if (isset($_FILES['csv_file'])) {
if ($_FILES['csv_file']['error'] == 0) {
$file = $_FILES['csv_file']['tmp_name']; $file = $_FILES['csv_file']['tmp_name'];
$handle = fopen($file, "r"); $handle = fopen($file, "r");
// 1. Récupération dynamique du mapping configuré dans les paramètres
$stmtMap = $pdo->query("SELECT csv_mapping FROM pf_foyer_settings LIMIT 1");
$csvMapRaw = $stmtMap->fetchColumn();
$mapping = $csvMapRaw ? json_decode($csvMapRaw, true) : null;
$delimiter = $mapping['delimiter'] ?? ';';
$colDate = isset($mapping['col_date']) ? (int)$mapping['col_date'] : 0;
$colLabel = isset($mapping['col_label']) ? (int)$mapping['col_label'] : 1;
$amountType = $mapping['amount_type'] ?? 'split';
$colDebit = isset($mapping['col_debit']) ? (int)$mapping['col_debit'] : 8;
$colCredit = isset($mapping['col_credit']) ? (int)$mapping['col_credit'] : 9;
$colRef = isset($mapping['col_ref']) ? (int)$mapping['col_ref'] : 3;
$dateFormat = $mapping['date_format'] ?? 'd/m/Y';
$rules = []; $rules = [];
try { try {
$stmtRules = $pdo->query("SELECT keyword, category, budget_item_id FROM pf_import_rules"); $stmtRules = $pdo->query("SELECT keyword, category, budget_item_id FROM pf_import_rules");
@@ -129,20 +145,55 @@ if (isset($_FILES['csv_file']) && $_FILES['csv_file']['error'] == 0) {
} }
} catch(Exception $e){} } 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){} $existingRefs = [];
fgetcsv($handle, 1000, ";", "\"", "\\"); try {
$existingRefs = $pdo->query("SELECT import_ref FROM pf_expenses WHERE import_ref IS NOT NULL")->fetchAll(PDO::FETCH_COLUMN);
} catch(Exception $e){}
while (($data = fgetcsv($handle, 1000, ";", "\"", "\\")) !== FALSE) { fgetcsv($handle, 1000, $delimiter, "\"", "\\"); // Skip header
$rawDebit = $data[8] ?? ''; $rawCredit = $data[9] ?? '';
$amount = 0; $isCredit = 0;
if (!empty(trim($rawCredit))) { $amount = abs((float)str_replace(',', '.', str_replace(' ', '', $rawCredit))); $isCredit = 1; }
elseif (!empty(trim($rawDebit))) { $amount = abs((float)str_replace(',', '.', str_replace(' ', '', $rawDebit))); }
else continue;
$dateParts = explode('/', $data[0]); while (($data = fgetcsv($handle, 1000, $delimiter, "\"", "\\")) !== FALSE) {
$dateSql = (count($dateParts) == 3) ? $dateParts[2].'-'.$dateParts[1].'-'.$dateParts[0] : date('Y-m-d'); $amount = 0;
$label = trim($data[1]) ?: trim($data[2]); $isCredit = 0;
$refCSV = trim($data[3]);
// 2. Traitement dynamique du montant (Une seule colonne ou Débit/Crédit séparés)
if ($amountType === 'single') {
$val = $data[$colDebit] ?? '';
if (!empty(trim($val))) {
$floatVal = (float)str_replace([' ', ','], ['', '.'], $val);
$amount = abs($floatVal);
$isCredit = $floatVal > 0 ? 1 : 0;
} else {
continue;
}
} else {
$rawDebit = $data[$colDebit] ?? '';
$rawCredit = $data[$colCredit] ?? '';
if (!empty(trim($rawCredit))) {
$amount = abs((float)str_replace([' ', ','], ['', '.'], $rawCredit));
$isCredit = 1;
} elseif (!empty(trim($rawDebit))) {
$amount = abs((float)str_replace([' ', ','], ['', '.'], $rawDebit));
} else {
continue;
}
}
// 3. Traitement dynamique de la date
$rawDate = $data[$colDate] ?? '';
$dateSql = date('Y-m-d');
if ($dateFormat === 'd/m/Y') {
$dateParts = explode('/', $rawDate);
if (count($dateParts) == 3) {
$dateSql = $dateParts[2].'-'.$dateParts[1].'-'.$dateParts[0];
}
} else {
$ts = strtotime($rawDate);
if ($ts) $dateSql = date('Y-m-d', $ts);
}
$label = trim($data[$colLabel] ?? '');
$refCSV = trim($data[$colRef] ?? '');
$uniqueKey = !empty($refCSV) ? "REF_".$refCSV : "HASH_".md5($dateSql.$label.number_format($amount, 2).$isCredit); $uniqueKey = !empty($refCSV) ? "REF_".$refCSV : "HASH_".md5($dateSql.$label.number_format($amount, 2).$isCredit);
$isDuplicate = in_array($uniqueKey, $existingRefs); $isDuplicate = in_array($uniqueKey, $existingRefs);
@@ -160,6 +211,9 @@ if (isset($_FILES['csv_file']) && $_FILES['csv_file']['error'] == 0) {
} }
fclose($handle); fclose($handle);
$showPreview = true; $showPreview = true;
} else {
$importError = "Erreur lors de l'upload du fichier (Code d'erreur PHP : " . $_FILES['csv_file']['error'] . "). Le fichier est peut-être trop volumineux.";
}
} }
// ============================================================================ // ============================================================================
@@ -750,8 +804,15 @@ $monthName = $monthNames[(int)$viewM] . ' ' . $viewY;
<button type="button" onclick="closeSuiviModal('importCsvModal')" class="pf-modal-close" style="background:none; border:none; font-size:1.5rem; cursor:pointer;">&times;</button> <button type="button" onclick="closeSuiviModal('importCsvModal')" class="pf-modal-close" style="background:none; border:none; font-size:1.5rem; cursor:pointer;">&times;</button>
</div> </div>
<?php if (!empty($importError)): ?>
<div class="pf-alert pf-alert--error" style="margin-bottom: 15px;">
<?= htmlspecialchars($importError) ?>
</div>
<?php endif; ?>
<?php if (!$showPreview): ?> <?php if (!$showPreview): ?>
<form method="POST" enctype="multipart/form-data"> <!-- L'action sécurise le fait qu'on poste bien sur le mois et la vue actuels -->
<form method="POST" enctype="multipart/form-data" action="?tab=suivi&m=<?= htmlspecialchars($viewM) ?>&y=<?= htmlspecialchars($viewY) ?>">
<div class="import-dropzone"> <div class="import-dropzone">
<div style="font-size: 2.5rem; margin-bottom: 10px;">📄</div> <div style="font-size: 2.5rem; margin-bottom: 10px;">📄</div>
<label class="pf-label"><?= tr('bud_csv_file') ?></label> <label class="pf-label"><?= tr('bud_csv_file') ?></label>
@@ -763,7 +824,7 @@ $monthName = $monthNames[(int)$viewM] . ' ' . $viewY;
</div> </div>
</form> </form>
<?php else: ?> <?php else: ?>
<form method="POST" id="formMapping"> <form method="POST" id="formMapping" action="?tab=suivi&m=<?= htmlspecialchars($viewM) ?>&y=<?= htmlspecialchars($viewY) ?>">
<input type="hidden" name="action" value="save_import"> <input type="hidden" name="action" value="save_import">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:15px; flex-wrap:wrap; gap:10px;"> <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:15px; flex-wrap:wrap; gap:10px;">