From 506cd64a443e8d9c762e459ae130aa9872e19955 Mon Sep 17 00:00:00 2001 From: "fefe.clochette" Date: Sun, 21 Jun 2026 11:25:17 +0200 Subject: [PATCH] order cat --- migrate_categories_order.php | 64 ++++++++++++++++++++++++ modules/budget/includes/api/settings.php | 13 +++++ modules/budget/views/settings_modal.php | 40 ++++++++++++++- modules/budget/views/suivi.php | 2 +- 4 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 migrate_categories_order.php diff --git a/migrate_categories_order.php b/migrate_categories_order.php new file mode 100644 index 0000000..b7ae432 --- /dev/null +++ b/migrate_categories_order.php @@ -0,0 +1,64 @@ +🚀 Migration : Ajout de l'ordre des catégories"; + +try { + // Connexion au serveur MySQL (sans spécifier de base de données particulière) + $pdo = new PDO("mysql:host=$host;charset=utf8mb4", $user, $pass); + $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + // 1. Trouver toutes les bases de données de la famille HouseHub + $stmt = $pdo->query("SHOW DATABASES LIKE 'househub_f%'"); + $databases = $stmt->fetchAll(PDO::FETCH_COLUMN); + + if (empty($databases)) { + echo "

❌ Aucune base de données correspondant à 'househub_f*' n'a été trouvée.

"; + exit; + } + + echo "

🔍 " . count($databases) . " base(s) de données trouvée(s).

"; + + // 2. Boucler sur chaque base de données + foreach ($databases as $db) { + echo "
"; + echo "

📂 Traitement de la base : $db

"; + + // Sélectionner la base de données active + $pdo->exec("USE `$db`"); + + // Vérifier si la table pf_budget_categories existe dans cette DB + $tableExists = $pdo->query("SHOW TABLES LIKE 'pf_budget_categories'")->rowCount() > 0; + + if ($tableExists) { + // Vérifier si la colonne sort_order existe déjà (sécurité) + $columnExists = $pdo->query("SHOW COLUMNS FROM pf_budget_categories LIKE 'sort_order'")->rowCount() > 0; + + if (!$columnExists) { + // La colonne n'existe pas, on l'ajoute ! + $pdo->exec("ALTER TABLE pf_budget_categories ADD sort_order INT DEFAULT 0"); + echo "✅ Colonne 'sort_order' ajoutée avec succès !"; + } else { + // La colonne est déjà là + echo "ℹ️ La colonne 'sort_order' existe déjà (Ignoré)."; + } + } else { + echo "⚠️ La table 'pf_budget_categories' n'existe pas ici."; + } + echo "
"; + } + + echo "

🎉 Migration terminée avec succès !

"; + echo "

Tu peux maintenant supprimer ce fichier par mesure de sécurité.

"; + +} catch (PDOException $e) { + echo "

❌ Erreur fatale MySQL :

"; + echo "
" . $e->getMessage() . "
"; +} +?> \ No newline at end of file diff --git a/modules/budget/includes/api/settings.php b/modules/budget/includes/api/settings.php index 11535ce..cd75844 100644 --- a/modules/budget/includes/api/settings.php +++ b/modules/budget/includes/api/settings.php @@ -168,6 +168,19 @@ try { exit; } + // SAUVEGARDE DU NOUVEL ORDRE DES CATÉGORIES + if (isset($_POST['action']) && $_POST['action'] === 'save_categories_order') { + $ids = json_decode($_POST['order'], true); + if (is_array($ids)) { + $stmt = $pdo->prepare("UPDATE pf_budget_categories SET sort_order = ? WHERE id = ?"); + foreach ($ids as $index => $id) { + $stmt->execute([$index, (int)$id]); + } + } + echo json_encode(['success' => true]); + exit; + } + throw new Exception("Action API inconnue."); } catch (Exception $e) { diff --git a/modules/budget/views/settings_modal.php b/modules/budget/views/settings_modal.php index aa75322..d3c4ac4 100644 --- a/modules/budget/views/settings_modal.php +++ b/modules/budget/views/settings_modal.php @@ -305,16 +305,25 @@ function renderCategories(categories) { container.innerHTML = `${tr('bs_empty_categories')}`; return; } + + // Tri JS pour respecter l'ordre au chargement de la modale + categories.sort((a, b) => { + if (a.type !== b.type) return a.type === 'Income' ? -1 : 1; + return (a.sort_order || 0) - (b.sort_order || 0); + }); + let html = ''; categories.forEach(cat => { let typeLabel = cat.type === 'Income' ? tr('bs_type_income') : cat.type === 'Expense' ? tr('bs_type_expense') : tr('bs_type_savings_cat'); html += ` -
+
${cat.icon || '📌'} ${cat.label} (${cat.code} — ${typeLabel})
+ +
`; @@ -322,6 +331,35 @@ function renderCategories(categories) { container.innerHTML = html; } +// Nouvelles fonctions pour réordonner visuellement et sauvegarder +function moveCatUp(btn) { + let row = btn.closest('.bs-list-item'); + if (row.previousElementSibling) { + row.parentNode.insertBefore(row, row.previousElementSibling); + saveCategoriesOrder(); + } +} + +function moveCatDown(btn) { + let row = btn.closest('.bs-list-item'); + if (row.nextElementSibling) { + row.parentNode.insertBefore(row.nextElementSibling, row); + saveCategoriesOrder(); + } +} + +async function saveCategoriesOrder() { + let ids = Array.from(document.querySelectorAll('#bs-list-categories .bs-list-item')).map(el => el.dataset.id); + let fd = new FormData(); + fd.append('action', 'save_categories_order'); + fd.append('order', JSON.stringify(ids)); + try { + await pachaFetch('/modules/budget/includes/api/settings.php', { method: 'POST', body: fd }); + } catch (err) { + console.error("Erreur de sauvegarde de l'ordre :", err); + } +} + // 3. ONGLET : RÈGLES D'IMPORT function renderRules(rules) { const container = document.getElementById('bs-list-rules'); diff --git a/modules/budget/views/suivi.php b/modules/budget/views/suivi.php index 438695a..ed5361f 100644 --- a/modules/budget/views/suivi.php +++ b/modules/budget/views/suivi.php @@ -167,7 +167,7 @@ if (isset($_FILES['csv_file']) && $_FILES['csv_file']['error'] == 0) { // ============================================================================ // --- LECTURE DYNAMIQUE DES CATEGORIES --- -$stmtCats = $pdo->query("SELECT * FROM pf_budget_categories ORDER BY type DESC, label ASC"); +$stmtCats = $pdo->query("SELECT * FROM pf_budget_categories ORDER BY type DESC, sort_order ASC, label ASC"); $dbCategories = $stmtCats->fetchAll(PDO::FETCH_ASSOC); $categoriesConfig = [];