From 96df90d372922782d5c6e9fc2bb5c977363e95af Mon Sep 17 00:00:00 2001 From: "fefe.clochette" Date: Wed, 17 Jun 2026 12:40:18 +0200 Subject: [PATCH] fix migrate --- includes/lang/ca.php | 5 + includes/lang/fr.php | 4 + migrate.php | 628 +++++++++++++++++++++++++++++++-- modules/budget/views/suivi.php | 3 +- 4 files changed, 605 insertions(+), 35 deletions(-) diff --git a/includes/lang/ca.php b/includes/lang/ca.php index 374f1b5..f82a6c4 100644 --- a/includes/lang/ca.php +++ b/includes/lang/ca.php @@ -590,6 +590,11 @@ return [ 'bud_bar_actual' => "Actual", 'bud_bar_theoretical' => "Teòric", 'bud_bar_max_cap' => "Capacitat Màx.", + 'bud_edit_title' => 'Modificar la transacció', + 'bud_to_define_js' => 'per definir', + 'bud_select_beneficiary' => 'Triar un ingrés esperat', // 👈 À ajouter ici + 'bud_bar_actual' => 'Actual', + // --- MODULE BUDGET : IMPORT CSV --- 'bud_import_csv' => "Importar CSV", 'bud_csv_file' => "Seleccioneu el fitxer del vostre banc (.csv)", diff --git a/includes/lang/fr.php b/includes/lang/fr.php index ba6f7ca..ed3d709 100644 --- a/includes/lang/fr.php +++ b/includes/lang/fr.php @@ -603,6 +603,10 @@ return [ 'bud_to_define' => "À définir", 'bud_is_charge' => "Est une charge fixe...", 'bud_is_income' => "Est un revenu...", + 'bud_edit_title' => 'Modifier la transaction', + 'bud_to_define_js' => 'à définir', + 'bud_select_beneficiary' => 'Choisir un revenu attendu', + 'bud_bar_actual' => 'Actuel', // --- BUDGET : RECAP --- 'bud_recap_monthly_title' => 'Récapitulatif Mensuel', diff --git a/migrate.php b/migrate.php index dc1ad23..ec4f3e3 100644 --- a/migrate.php +++ b/migrate.php @@ -1,84 +1,644 @@ 🚀 Début de la migration Multi-Tenant"; + + try { + $stmt = $meta_pdo->query("SELECT db_name, name FROM families WHERE is_active = 1"); + $families = $stmt->fetchAll(PDO::FETCH_ASSOC); + + foreach ($families as $family) { + $dbName = $family['db_name']; + echo "

Famille : {$family['name']} ($dbName)

"; + + try { + $pdo = new PDO( + "mysql:host=$db_host;dbname=$dbName;charset=utf8mb4", + $db_user, $db_pass, + [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION] + ); - // 1. UPDATE DE pf_people + + + // --------------------------------------------------------- + + // 1. UPDATE DE pf_people (Juste la date de naissance et l'état actif) + + // --------------------------------------------------------- + $colCheck = $pdo->prepare("SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = 'pf_people' AND COLUMN_NAME = 'birthdate'"); + $colCheck->execute([$dbName]); + if ($colCheck->rowCount() === 0) { - $pdo->exec("ALTER TABLE pf_people ADD COLUMN birthdate DATE DEFAULT NULL, ADD COLUMN is_active TINYINT(1) DEFAULT 1"); - echo "✅ pf_people mis à jour.
"; + + $pdo->exec("ALTER TABLE pf_people + + ADD COLUMN birthdate DATE DEFAULT NULL, + + ADD COLUMN is_active TINYINT(1) DEFAULT 1 + + "); + + echo "✅ pf_people mis à jour (birthdate ajouté).
"; + + } else { + + echo "➖ pf_people déjà à jour.
"; + } - // 2. CRÉATION DES NOUVELLES TABLES - $pdo->exec("CREATE TABLE IF NOT EXISTS pf_bank_accounts (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, owner_person_id INT DEFAULT NULL, account_type VARCHAR(50) DEFAULT 'savings', is_default TINYINT(1) DEFAULT 0, FOREIGN KEY (owner_person_id) REFERENCES pf_people(id) ON DELETE SET NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); - $pdo->exec("CREATE TABLE IF NOT EXISTS pf_budget_categories (id INT AUTO_INCREMENT PRIMARY KEY, code VARCHAR(50) NOT NULL, label VARCHAR(100) NOT NULL, type VARCHAR(50) NOT NULL, color VARCHAR(20) DEFAULT '#ccc', icon VARCHAR(20) DEFAULT '💰', UNIQUE KEY (code)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); - $pdo->exec("CREATE TABLE IF NOT EXISTS pf_leave_types (id INT AUTO_INCREMENT PRIMARY KEY, code VARCHAR(20) NOT NULL, label VARCHAR(100) NOT NULL, default_allowance DECIMAL(5,2) DEFAULT 0, reset_month INT DEFAULT 1, allow_carry_over TINYINT(1) DEFAULT 0, UNIQUE KEY (code)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); - $pdo->exec("CREATE TABLE IF NOT EXISTS pf_gift_occasions (id INT AUTO_INCREMENT PRIMARY KEY, code VARCHAR(20) NOT NULL, name VARCHAR(100) NOT NULL, month_date VARCHAR(5) DEFAULT NULL, is_active TINYINT(1) DEFAULT 1, UNIQUE KEY (code)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); - $pdo->exec("CREATE TABLE IF NOT EXISTS pf_gift_rules (id INT AUTO_INCREMENT PRIMARY KEY, adult_person_id INT NOT NULL, child_person_id INT NOT NULL, occasion_id INT NOT NULL, FOREIGN KEY (adult_person_id) REFERENCES pf_people(id) ON DELETE CASCADE, FOREIGN KEY (child_person_id) REFERENCES pf_people(id) ON DELETE CASCADE, FOREIGN KEY (occasion_id) REFERENCES pf_gift_occasions(id) ON DELETE CASCADE, UNIQUE KEY adult_child_occ (adult_person_id, child_person_id, occasion_id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); - - // 3. INJECTION DONNÉES PAR DÉFAUT + + + // --------------------------------------------------------- + + // 2. CRÉATION DES NOUVELLES TABLES (IF NOT EXISTS) + + // --------------------------------------------------------- + + + + // Comptes bancaires + + $pdo->exec("CREATE TABLE IF NOT EXISTS pf_bank_accounts ( + + id INT AUTO_INCREMENT PRIMARY KEY, + + name VARCHAR(100) NOT NULL, + + owner_person_id INT DEFAULT NULL, + + account_type VARCHAR(50) DEFAULT 'savings', + + is_default TINYINT(1) DEFAULT 0, + + FOREIGN KEY (owner_person_id) REFERENCES pf_people(id) ON DELETE SET NULL + + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); + + + + // Catégories de budget + + $pdo->exec("CREATE TABLE IF NOT EXISTS pf_budget_categories ( + + id INT AUTO_INCREMENT PRIMARY KEY, + + code VARCHAR(50) NOT NULL, + + label VARCHAR(100) NOT NULL, + + type VARCHAR(50) NOT NULL, + + color VARCHAR(20) DEFAULT '#ccc', + + icon VARCHAR(20) DEFAULT '💰', + + UNIQUE KEY (code) + + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); + + + + // Types de congés + + $pdo->exec("CREATE TABLE IF NOT EXISTS pf_leave_types ( + + id INT AUTO_INCREMENT PRIMARY KEY, + + code VARCHAR(20) NOT NULL, + + label VARCHAR(100) NOT NULL, + + default_allowance DECIMAL(5,2) DEFAULT 0, + + reset_month INT DEFAULT 1, + + allow_carry_over TINYINT(1) DEFAULT 0, + + UNIQUE KEY (code) + + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); + + + + // Fêtes (Cadeaux) + + $pdo->exec("CREATE TABLE IF NOT EXISTS pf_gift_occasions ( + + id INT AUTO_INCREMENT PRIMARY KEY, + + code VARCHAR(20) NOT NULL, + + name VARCHAR(100) NOT NULL, + + month_date VARCHAR(5) DEFAULT NULL, + + is_active TINYINT(1) DEFAULT 1, + + UNIQUE KEY (code) + + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); + + + + // Règles Cadeaux + + $pdo->exec("CREATE TABLE IF NOT EXISTS pf_gift_rules ( + + id INT AUTO_INCREMENT PRIMARY KEY, + + adult_person_id INT NOT NULL, + + child_person_id INT NOT NULL, + + occasion_id INT NOT NULL, + + FOREIGN KEY (adult_person_id) REFERENCES pf_people(id) ON DELETE CASCADE, + + FOREIGN KEY (child_person_id) REFERENCES pf_people(id) ON DELETE CASCADE, + + FOREIGN KEY (occasion_id) REFERENCES pf_gift_occasions(id) ON DELETE CASCADE, + + UNIQUE KEY adult_child_occ (adult_person_id, child_person_id, occasion_id) + + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); + + + + echo "✅ Nouvelles tables de configuration créées ou vérifiées.
"; + + + + // --------------------------------------------------------- + + // 3. INJECTION DE DONNÉES PAR DÉFAUT (Pour ne rien casser) + + // --------------------------------------------------------- + + + if ($pdo->query("SELECT COUNT(*) FROM pf_bank_accounts")->fetchColumn() == 0) { - $pdo->exec("INSERT INTO pf_bank_accounts (name, account_type, is_default) VALUES ('Compte Commun', 'checking', 1), ('Livret A Alex', 'savings', 0), ('Livret A Laia', 'savings', 0), ('Livret A Pol', 'savings', 0), ('Livret A Pep', 'savings', 0)"); - } - $pdo->exec("INSERT IGNORE INTO pf_budget_categories (code, label, type, color, icon) VALUES ('INCOME', 'Revenus', 'Income', '#22c55e', '💵'), ('FMCG', 'Alimentation', 'Expense', '#3b82f6', '🛒'), ('FUEL', 'Carburant', 'Expense', '#f59e0b', '⛽'), ('SCHOOL', 'École / Garde', 'Expense', '#a855f7', '🎒'), ('HEALTH', 'Santé', 'Expense', '#ef4444', '⚕️'), ('FIXED', 'Charges Fixes', 'Expense', '#ef4444', '🏢'), ('SAVINGS', 'Épargne & Projets', 'Expense', '#8b5cf6', '🐷'), ('AUTRES', 'Autres / Divers', 'Expense', '#64748b', '📁')"); - // 4. MIGRATION MODULE CALENDRIER + $pdo->exec("INSERT INTO pf_bank_accounts (name, account_type, is_default) VALUES + + ('Compte Commun', 'checking', 1), + + ('Livret A Alex', 'savings', 0), + + ('Livret A Laia', 'savings', 0), + + ('Livret A Pol', 'savings', 0), + + ('Livret A Pep', 'savings', 0) + + "); + + } + + + + // Utilisation de INSERT IGNORE pour éviter les doublons tout en injectant les catégories manquantes + + $pdo->exec("INSERT IGNORE INTO pf_budget_categories (code, label, type, color, icon) VALUES + + ('INCOME', 'Revenus', 'Income', '#22c55e', '💵'), + + ('FMCG', 'Alimentation', 'Expense', '#3b82f6', '🛒'), + + ('FUEL', 'Carburant', 'Expense', '#f59e0b', '⛽'), + + ('SCHOOL', 'École / Garde', 'Expense', '#a855f7', '🎒'), + + ('HEALTH', 'Santé', 'Expense', '#ef4444', '⚕️'), + + ('FIXED', 'Charges Fixes', 'Expense', '#ef4444', '🏢'), + + ('SAVINGS', 'Épargne & Projets', 'Expense', '#8b5cf6', '🐷'), + + ('AUTRES', 'Autres / Divers', 'Expense', '#64748b', '📁') + + "); + + + + if ($pdo->query("SELECT COUNT(*) FROM pf_leave_types")->fetchColumn() == 0) { + + $pdo->exec("INSERT INTO pf_leave_types (code, label, default_allowance, reset_month, allow_carry_over) VALUES + + ('CA', 'Congés Annuels', 25, 6, 1), + + ('JRA', 'Jours de Repos', 10, 1, 0), + + ('JA', 'Jour Anniversaire', 1, 1, 0) + + "); + + } + + + + if ($pdo->query("SELECT COUNT(*) FROM pf_gift_occasions")->fetchColumn() == 0) { + + $pdo->exec("INSERT INTO pf_gift_occasions (code, name, month_date) VALUES + + ('NOEL', 'Noël', '12-25'), + + ('ROIS', 'Les Rois', '01-06'), + + ('ANNIV', 'Anniversaire', NULL) + + "); + + } + + + + echo "✅ Données de base injectées (si nécessaire).
"; + + + + // --------------------------------------------------------- + + // 4. MIGRATION SPECIFIQUE : MODULE CALENDRIER (CONGÉS GRANULAIRES) + + // --------------------------------------------------------- + $tableExists = $pdo->query("SHOW TABLES LIKE 'pf_person_leave_meta'")->rowCount() > 0; + + + if (!$tableExists) { - $pdo->exec("CREATE TABLE pf_person_leave_meta (id INT AUTO_INCREMENT PRIMARY KEY, person_id INT NOT NULL, leave_type VARCHAR(50) NOT NULL, anniversary_date DATE NOT NULL, UNIQUE KEY uq_person_leave (person_id, leave_type), FOREIGN KEY (person_id) REFERENCES pf_people(id) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); + + $pdo->exec(" + + CREATE TABLE pf_person_leave_meta ( + + id INT AUTO_INCREMENT PRIMARY KEY, + + person_id INT NOT NULL, + + leave_type VARCHAR(50) NOT NULL, + + anniversary_date DATE NOT NULL, + + UNIQUE KEY uq_person_leave (person_id, leave_type), + + FOREIGN KEY (person_id) REFERENCES pf_people(id) ON DELETE CASCADE + + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + + "); + + echo "✅ Table pf_person_leave_meta créée (Nouvelle installation).
"; + + } else { + + $checkColumn = $pdo->query("SHOW COLUMNS FROM pf_person_leave_meta LIKE 'leave_type'")->rowCount(); + + if ($checkColumn === 0) { + + $pdo->exec("ALTER TABLE pf_person_leave_meta ADD COLUMN leave_type VARCHAR(50) NULL AFTER person_id"); + + $pdo->exec("UPDATE pf_person_leave_meta SET leave_type = 'CP' WHERE leave_type IS NULL"); + + $pdo->exec("ALTER TABLE pf_person_leave_meta MODIFY COLUMN leave_type VARCHAR(50) NOT NULL"); + + + + try { + + $pdo->exec("ALTER TABLE pf_person_leave_meta DROP INDEX person_id"); + + } catch (\Throwable $e) {} + + + + $pdo->exec("ALTER TABLE pf_person_leave_meta ADD UNIQUE KEY uq_person_leave (person_id, leave_type)"); + + echo "✅ Table pf_person_leave_meta mise à jour avec le type granulaire.
"; + + } else { + + echo "➖ Table pf_person_leave_meta déjà à jour.
"; + + } + } - // 5. MIGRATION PARAMÈTRES DYNAMIQUES - $pdo->exec("CREATE TABLE IF NOT EXISTS `pf_settings` (`setting_key` varchar(50) NOT NULL, `setting_value` text DEFAULT NULL, `module` varchar(50) NOT NULL, `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(), PRIMARY KEY (`setting_key`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"); - $pdo->exec("INSERT IGNORE INTO `pf_settings` (`setting_key`, `setting_value`, `module`) VALUES ('calendar_default_view', 'month', 'calendar'), ('calendar_first_day', '1', 'calendar'), ('calendar_working_hours', '08:00-19:00', 'calendar'), ('budget_start_day', '1', 'budget'), ('budget_default_tab', 'dépenses', 'budget'), ('travel_default_transport', 'car', 'voyage'), ('travel_default_fuel_price', '1.85', 'voyage'), ('gifts_hide_purchased', '0', 'cadeaux'), ('gifts_default_sort', 'person', 'cadeaux'), ('gifts_budget_alert', '500', 'cadeaux')"); - // 6. MIGRATION CSV MAPPING (La partie ajoutée) - $checkCol = $pdo->query("SHOW COLUMNS FROM pf_foyer_settings LIKE 'csv_mapping'")->fetch(); - if (!$checkCol) { - $pdo->exec("ALTER TABLE pf_foyer_settings ADD COLUMN csv_mapping TEXT NULL"); - echo "✅ Colonne 'csv_mapping' ajoutée.
"; + + // --------------------------------------------------------- + + // 5. MIGRATION DES PARAMÈTRES DYNAMIQUES (pf_settings) + + // --------------------------------------------------------- + + $pdo->exec(" + + CREATE TABLE IF NOT EXISTS `pf_settings` ( + + `setting_key` varchar(50) NOT NULL, + + `setting_value` text DEFAULT NULL, + + `module` varchar(50) NOT NULL, + + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(), + + PRIMARY KEY (`setting_key`) + + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + + "); + + + + $pdo->exec(" + + INSERT IGNORE INTO `pf_settings` (`setting_key`, `setting_value`, `module`) VALUES + + ('calendar_default_view', 'month', 'calendar'), + + ('calendar_first_day', '1', 'calendar'), + + ('calendar_working_hours', '08:00-19:00', 'calendar'), + + ('budget_start_day', '1', 'budget'), + + ('budget_default_tab', 'dépenses', 'budget'), + + ('travel_default_transport', 'car', 'voyage'), + + ('travel_default_fuel_price', '1.85', 'voyage'), + + ('gifts_hide_purchased', '0', 'cadeaux'), + + ('gifts_default_sort', 'person', 'cadeaux'), + + ('gifts_budget_alert', '500', 'cadeaux'); + + "); + + echo "✅ Table pf_settings créée et paramètres de base injectés.
"; + + + + try { + + $pdo->exec("ALTER TABLE `pf_vehicles` ADD COLUMN `consumption` decimal(4,2) DEFAULT NULL COMMENT 'Consommation L/100km' AFTER `fuel_type`"); + + echo "✅ Colonne consumption ajoutée au Garage.
"; + + } catch (PDOException $e) { + + echo "➖ pf_vehicles déjà à jour.
"; + } - // 7. MIGRATION STRUCTURE BUDGET & HISTORIQUE + + + // --------------------------------------------------------- + + // 6. MIGRATION DE L'HISTORIQUE CALENDRIER (FINI LE CODÉ EN DUR) + + // --------------------------------------------------------- + + $stmtHelper = $pdo->query("SELECT id FROM pf_people WHERE role = 'helper' LIMIT 1"); + + $helperId = $stmtHelper->fetchColumn(); + + + + if ($helperId) { + + $pdo->exec("UPDATE pf_events SET event_type = 'HELPER_OFF', person_id = $helperId WHERE event_type = 'OFF_CAROLE'"); + + $pdo->exec("UPDATE pf_events SET event_type = 'HELPER_EXTRA', person_id = $helperId WHERE event_type = 'EXTRA_OFF_CAROLE'"); + + echo "✅ Historique des absences Nounou migré dynamiquement.
"; + + } + + + + $stmtKid = $pdo->query("SELECT id FROM pf_people WHERE role IN ('child', 'enfant') ORDER BY id ASC LIMIT 1"); + + $kidId = $stmtKid->fetchColumn(); + + + + if ($kidId) { + + $pdo->exec("UPDATE pf_events SET event_type = 'CHILD_SICK', person_id = $kidId WHERE event_type = 'PEP_SICK'"); + + echo "✅ Historique des maladies Enfant migré dynamiquement.
"; + + } + + + + // --------------------------------------------------------- + + // 7. MIGRATION DÉFINITIVE : STRUCTURE DU BUDGET + + // --------------------------------------------------------- + + + + // A. Changement du type de la colonne (ENUM -> VARCHAR) + $pdo->exec("ALTER TABLE pf_budget_items MODIFY category VARCHAR(100) DEFAULT NULL"); - $pdo->exec("UPDATE pf_budget_items SET category = 'FIXED' WHERE category = 'expense' AND is_estimate = 0"); - $pdo->exec("UPDATE pf_budget_items SET category = 'AUTRES' WHERE category = 'expense'"); - $pdo->exec("UPDATE pf_budget_items SET category = 'INCOME' WHERE category = 'income'"); - - echo "✅ Migration terminée pour {$family['name']}.
"; + + + + // B. MAPPING INTELLIGENT DES DONNEES EXISTANTES (Nettoyage de l'ancienne logique) + + $itemsMigres = 0; + + + + // 1. Les charges fixes (is_estimate = 0) deviennent FIXED + + $itemsMigres += $pdo->exec("UPDATE pf_budget_items SET category = 'FIXED' WHERE category = 'expense' AND is_estimate = 0"); + + + + // 2. Les estimations (is_estimate = 1) sont mappées selon leur nom ou mots clés (hack historique) + + $itemsMigres += $pdo->exec("UPDATE pf_budget_items SET category = 'FUEL' WHERE category = 'expense' AND is_estimate = 1 AND (mapping_keywords LIKE '%ESSENCE%' OR name LIKE '%gasolina%')"); + + $itemsMigres += $pdo->exec("UPDATE pf_budget_items SET category = 'SCHOOL' WHERE category = 'expense' AND is_estimate = 1 AND (mapping_keywords LIKE '%ESCOLA%' OR mapping_keywords LIKE '%PARASCOL%' OR name LIKE '%escola%')"); + + $itemsMigres += $pdo->exec("UPDATE pf_budget_items SET category = 'FMCG' WHERE category = 'expense' AND is_estimate = 1 AND (mapping_keywords LIKE '%FMCG%' OR name LIKE '%F&B%')"); + + + + // 3. On sécurise les éventuelles estimations restantes dans AUTRES + + $itemsMigres += $pdo->exec("UPDATE pf_budget_items SET category = 'AUTRES' WHERE category = 'expense'"); + + + + // 4. On sécurise les anciens revenus + + $itemsMigres += $pdo->exec("UPDATE pf_budget_items SET category = 'INCOME' WHERE category = 'income'"); + + + + // C. Nettoyage des virgules orphelines dans mapping_keywords (suppression des vieux hacks) + + $budgetCodes = ['INCOME', 'FMCG', 'FUEL', 'SCHOOL', 'HEALTH', 'FIXED', 'SAVINGS', 'AUTRES']; + + foreach ($budgetCodes as $code) { + + $pdo->exec("UPDATE pf_budget_items SET mapping_keywords = REPLACE(mapping_keywords, '$code', '') WHERE mapping_keywords LIKE '%$code%'"); + + } + + $pdo->exec("UPDATE pf_budget_items SET mapping_keywords = TRIM(BOTH ',' FROM REPLACE(REPLACE(mapping_keywords, ' ', ''), ',,', ','))"); + + + + // D. Migration de l'historique des dépenses et des règles (Anciens libellés FR/EN -> Nouveaux Codes Dynamiques) + + $budgetMapping = [ + + 'Income' => 'INCOME', + + 'FMCG' => 'FMCG', + + 'Essence' => 'FUEL', + + 'School' => 'SCHOOL', + + 'Frais' => 'FIXED', + + 'LivretA' => 'SAVINGS', + + 'Autres' => 'AUTRES' + + ]; + + + + $stmtExp = $pdo->prepare("UPDATE pf_expenses SET category = ? WHERE category = ?"); + + $stmtRules = $pdo->prepare("UPDATE pf_import_rules SET category = ? WHERE category = ?"); + + + + $expCount = 0; + + $rulesCount = 0; + + + + foreach ($budgetMapping as $old => $newCode) { + + $stmtExp->execute([$newCode, $old]); + + $expCount += $stmtExp->rowCount(); + + + + $stmtRules->execute([$newCode, $old]); + + $rulesCount += $stmtRules->rowCount(); + + } + + + + echo "✅ Budget Structure : Table pf_budget_items passée en VARCHAR. $itemsMigres prévisions recatégorisées. Historique migré ($expCount dépenses et $rulesCount règles mises à jour).
"; + + } catch (PDOException $e) { + echo "❌ Erreur sur la base $dbName : " . $e->getMessage() . "
"; + } + + } // FIN DE LA BOUCLE FOREACH + + + + try { + + // Vérification si la colonne csv_mapping existe déjà dans pf_foyer_settings + + $checkCol = $pdo->query("SHOW COLUMNS FROM pf_foyer_settings LIKE 'csv_mapping'")->fetch(); + + + + if (!$checkCol) { + + $pdo->exec("ALTER TABLE pf_foyer_settings ADD COLUMN csv_mapping TEXT NULL"); + + echo "✅ Migration : Colonne 'csv_mapping' ajoutée à la table 'pf_foyer_settings'.\n"; + + } else { + + echo "ℹ️ Migration : La colonne 'csv_mapping' existe déjà.\n"; + } - echo "

🎉 Migration terminée avec succès !

"; -} catch (Exception $e) { - die("❌ Erreur fatale Meta DB : " . $e->getMessage()); + + + +} catch (PDOException $e) { + + echo "❌ Erreur lors de la migration : " . $e->getMessage() . "\n"; + } -?> \ No newline at end of file + + + + echo "

🎉 Migration terminée avec succès !

"; + + + +} catch (Exception $e) { + + die("❌ Erreur fatale Meta DB : " . $e->getMessage()); + +} + +?> + diff --git a/modules/budget/views/suivi.php b/modules/budget/views/suivi.php index 2c9229d..dc46958 100644 --- a/modules/budget/views/suivi.php +++ b/modules/budget/views/suivi.php @@ -231,7 +231,8 @@ while ($item = $stmt->fetch(PDO::FETCH_ASSOC)) { $amt = ($item['type'] === 'Annuel') ? $absAmount / 12 : $absAmount; $name = trim($item['name']); $catCode = $item['category']; // Ex: FIXED, FMCG, INCOME... - $isIncome = ((float)$item['amount'] > 0); // La norme est désormais définie par le signe du montant + + $isIncome = (isset($categoriesConfig[$catCode]) && $categoriesConfig[$catCode]['db_type'] === 'Income'); if ($isIncome) { $incomeList[] = ['id' => $item['id'], 'name' => $name, 'amount' => $absAmount];