# 🔧 CORRECTIONS CRITIQUES - migrate_from_backup.php ## ❌ ERREURS DÉTECTÉES ### 1. **migrateUsers** (ligne 456) ```sql -- ERREUR u.nom, u.prenom, u.nom_sect, u.username, u.password, u.phone, u.mobile -- CORRECTION (noms rĂ©els dans geosector.users) u.libelle, u.prenom, u.nom_tournee, u.username, u.userpass, u.telephone, u.mobile ``` ### 2. **migrateOpePass** (ligne 1043) ```sql -- ERREUR p.passed_at, p.libelle, p.email, p.phone -- CORRECTION (noms rĂ©els dans geosector.ope_pass) p.date_eve AS passed_at, p.libelle AS encrypted_name, p.email, p.phone ``` ### 3. **migrateSectorsAdresses** (ligne 777) ```sql -- ERREUR sa.osm_id, sa.osm_name, sa.osm_date_creat -- CORRECTION (ces champs n'existent PAS dans geosector.sectors_adresses) -- Ces champs doivent ĂȘtre mis Ă  0 ou NULL dans la cible 0 AS osm_id, '' AS osm_name, NULL AS osm_date_creat ``` ### 4. **migrateOpeUsersSectors** (ligne 955) ```sql -- ERREUR ous.date_creat, ous.fk_user_creat, ous.date_modif, ous.fk_user_modif -- CORRECTION (geosector.ope_users_sectors n'a PAS ces champs) NULL AS created_at, NULL AS fk_user_creat, NULL AS updated_at, NULL AS fk_user_modif ``` ### 5. **migrateMedias** (Ă  vĂ©rifier) ```sql -- ERREUR potentielle m.support_rowid -- CORRECTION m.support_rowid AS support_id ``` ### 6. **migrateOperations** (erreur NOT NULL) ```sql -- PROBLÈME: Column 'fk_user_modif' cannot be null -- CORRECTION: Utiliser 0 au lieu de NULL 'fk_user_modif' => $row['fk_user_modif'] ?? 0 ``` --- ## ✅ SOLUTION RAPIDE CrĂ©ez un script `HOTFIX_migrate.sql` pour corriger rapidement : ```sql -- Permettre NULL sur les champs problĂ©matiques ALTER TABLE operations MODIFY COLUMN fk_user_modif INT(10) UNSIGNED NULL DEFAULT NULL; ALTER TABLE ope_sectors MODIFY COLUMN fk_user_modif INT(10) UNSIGNED NULL DEFAULT NULL; ALTER TABLE ope_users MODIFY COLUMN fk_user_creat INT(10) UNSIGNED NULL DEFAULT NULL; ALTER TABLE ope_users MODIFY COLUMN fk_user_modif INT(10) UNSIGNED NULL DEFAULT NULL; ALTER TABLE ope_users_sectors MODIFY COLUMN fk_user_creat INT(10) UNSIGNED NULL DEFAULT NULL; ALTER TABLE ope_users_sectors MODIFY COLUMN fk_user_modif INT(10) UNSIGNED NULL DEFAULT NULL; ``` OU utiliser `0` Ă  la place de `NULL` systĂ©matiquement dans le script PHP. --- ## 📋 STATUT DES CORRECTIONS (10/10/2025) 1. ✅ **migrateEntites** - CORRIGÉ (cp, tel1, tel2, demo) 2. ✅ **migrateUsers** - CORRIGÉ (libelle, nom_tournee, telephone, userpass, alert_email) - Lignes 455-537 3. ✅ **migrateOperations** - CORRIGÉ (fk_user_modif ?? 0, fk_user_creat ?? 0) - Lignes 614-625 4. ✅ **migrateOpeSectors** - CORRIGÉ (fk_user_modif ?? 0, fk_user_creat ?? 0) - Lignes 727-738 5. ✅ **migrateSectorsAdresses** - CORRIGÉ (osm_id=0, osm_name='', osm_date_creat=null, created_at/updated_at=null) - Lignes 776-855 6. ✅ **migrateOpeUsers** - CORRIGÉ (vĂ©rification existence user dans TARGET avant insertion) - Lignes 960-1020 7. ✅ **migrateOpeUsersSectors** - CORRIGÉ (date_creat, fk_user_creat, date_modif, fk_user_modif = null + vĂ©rification user) - Lignes 1054-1135 8. ✅ **migrateOpePass** - CORRIGÉ (date_eve, libelle, recu + fk_type_reglement forcĂ© Ă  4 si invalide + vĂ©rification user) - Lignes 1215-1330 9. ✅ **migrateMedias** - CORRIGÉ (support_rowid, type_fichier, hauteur/largeur) - Lignes 1281-1343 10. ✅ **countTargetRows()** - CORRIGÉ (requĂȘtes SQL spĂ©cifiques par table avec JOINs corrects) - Lignes 303-355 --- ## ✅ CORRECTIONS APPLIQUÉES **Toutes les erreurs ont Ă©tĂ© corrigĂ©es dans `migrate_from_backup.php`.** Les corrections incluent : - Utilisation des vrais noms de colonnes SOURCE (`geosector-structure.sql`) - Gestion des champs manquants dans SOURCE avec valeurs par dĂ©faut - Utilisation de `?? 0` au lieu de `?? null` pour les FK NOT NULL - Suppression des champs inexistants dans les requĂȘtes SELECT **ATTENTION** : Les noms de colonnes TARGET n'ont PAS Ă©tĂ© vĂ©rifiĂ©s contre `geo_app_structure.sql`. Le script utilise peut-ĂȘtre les mauvais noms TARGET (Ă  vĂ©rifier avec `migrate_users.php` et autres `migrate_*.php` de rĂ©fĂ©rence). --- ## 🔧 CORRECTIONS RÉCENTES (Session actuelle) ### 10. **VĂ©rification FK users** (lignes 1008-1015, 1117-1125, 1257-1266) **ProblĂšme** : Violations de contraintes FK car certains `fk_user` rĂ©fĂ©rencent des utilisateurs absents dans TARGET. **Solution** : Ajout de vĂ©rification d'existence avant insertion : ```php // VĂ©rifier que fk_user existe dans users de la TARGET $checkUser = $this->targetDb->prepare("SELECT id FROM users WHERE id = ?"); $checkUser->execute([$row['fk_user']]); if (!$checkUser->fetch()) { $this->log(" ⚠ Record {$row['rowid']}: user {$row['fk_user']} non trouvĂ©, ignorĂ©", 'WARNING'); continue; } ``` **AppliquĂ© sur** : - `migrateOpeUsers()` - ligne 1008 - `migrateOpeUsersSectors()` - ligne 1117 - `migrateOpePass()` - ligne 1257 **RĂ©sultat** : Les enregistrements avec FK invalides sont ignorĂ©s avec un WARNING au lieu de provoquer une erreur fatale. ### 11. **countTargetRows() - RequĂȘtes SQL spĂ©cifiques** (lignes 303-355) **ProblĂšme** : Erreurs SQL car toutes les tables n'ont pas les mĂȘmes colonnes/relations : - `Unknown column 'fk_entite' in 'WHERE'` pour `entites` - `Unknown column 't.fk_operation' in 'ON'` pour `operations`, `ope_pass_histo`, `medias` **Solution** : RequĂȘtes SQL personnalisĂ©es par table : ```php // Pour entites : pas de FK, juste l'ID if ($tableName === 'entites') { $sql = "SELECT COUNT(*) as count FROM $tableName WHERE id = :entity_id"; } // Pour operations : FK directe vers entites else if ($tableName === 'operations') { $sql = "SELECT COUNT(*) as count FROM $tableName WHERE fk_entite = :entity_id"; } // Pour sectors_adresses : JOIN via ope_sectors -> operations else if ($tableName === 'sectors_adresses') { $sql = "SELECT COUNT(*) as count FROM $tableName sa INNER JOIN ope_sectors s ON sa.fk_sector = s.id INNER JOIN operations o ON s.fk_operation = o.id WHERE o.fk_entite = :entity_id"; } // Pour tables avec fk_operation directe else if (in_array($tableName, ['ope_sectors', 'ope_users', 'ope_users_sectors', 'ope_pass', 'ope_pass_histo', 'medias'])) { $sql = "SELECT COUNT(*) as count FROM $tableName t INNER JOIN operations o ON t.fk_operation = o.id WHERE o.fk_entite = :entity_id"; } ``` **RĂ©sultat** : Comptages TARGET prĂ©cis et sans erreurs SQL pour toutes les tables. ### 12. **fk_type_reglement validation** (lignes 1237-1241) **ProblĂšme** : FK violations car certains `fk_type_reglement` rĂ©fĂ©rencent des IDs inexistants dans `x_types_reglements` (IDs valides : 1, 2, 3). **Solution** : Forcer Ă  4 ("-") si valeur invalide (comme dans `migrate_ope_pass.php`) : ```php // VĂ©rification et correction du type de rĂšglement $fkTypeReglement = $row['fk_type_reglement'] ?? 1; if (!in_array($fkTypeReglement, [1, 2, 3])) { $fkTypeReglement = 4; // Forcer Ă  4 ("-") si diffĂ©rent de 1, 2 ou 3 } ``` **RĂ©sultat** : Tous les `ope_pass` sont migrĂ©s sans violation de FK sur `fk_type_reglement`. ### 13. **Limitation aux 3 derniĂšres opĂ©rations** (lignes 646-647) ⚠ IMPORTANT **ProblĂšme** : Migration de TOUTES les opĂ©rations au lieu des 3 derniĂšres uniquement. **Solution** : Ajout de `ORDER BY rowid DESC LIMIT 3` dans la requĂȘte : ```php // Ne migrer que les 3 derniĂšres opĂ©rations (plus rĂ©centes) $sql .= " ORDER BY rowid DESC LIMIT 3"; ``` **RĂ©sultat** : Seules les 3 opĂ©rations les plus rĂ©centes (par rowid DESC) sont migrĂ©es par entitĂ©. **Impact** : RĂ©duit considĂ©rablement le volume de donnĂ©es migrĂ©es et toutes les tables liĂ©es (ope_sectors, ope_users, ope_users_sectors, ope_pass, medias, sectors_adresses). ### 14. **Option de suppression avant migration** (lignes 127-200, 1692, 1722, 1776) ⭐ NOUVELLE FONCTIONNALITÉ **Besoin** : Permettre de supprimer les donnĂ©es existantes d'une entitĂ© dans TARGET avant migration pour repartir Ă  zĂ©ro. **Solution** : Ajout du paramĂštre `--delete-before` : **Script bash** (lignes 174-183) : ```bash # Demander si suppression des donnĂ©es de l'entitĂ© avant migration echo -ne "${YELLOW}3ïžâƒŁ Supprimer les donnĂ©es existantes de cette entitĂ© dans la TARGET avant migration ? (y/N): ${NC}" read -r DELETE_BEFORE DELETE_FLAG="" if [[ $DELETE_BEFORE =~ ^[Yy]$ ]]; then echo -e "${GREEN}✓${NC} Les donnĂ©es seront supprimĂ©es avant migration" DELETE_FLAG="--delete-before" fi ``` **Script PHP** - MĂ©thode `deleteEntityData()` (lignes 127-200) : ```php private function deleteEntityData($entityId) { // Ordre de suppression inverse pour respecter les FK $deletionOrder = [ 'medias', 'ope_pass_histo', 'ope_pass', 'ope_users_sectors', 'ope_users', 'sectors_adresses', 'ope_sectors', 'operations', 'users' ]; foreach ($deletionOrder as $table) { // Suppression via JOIN avec operations pour respecter FK DELETE t FROM $table t INNER JOIN operations o ON t.fk_operation = o.id WHERE o.fk_entite = ? } } ``` **RĂ©sultat** : - En mode interactif, l'utilisateur peut choisir de supprimer les donnĂ©es existantes avant migration - Suppression propre dans l'ordre inverse des FK (pas d'erreur de contrainte) - L'entitĂ© elle-mĂȘme n'est PAS supprimĂ©e (car peut avoir d'autres donnĂ©es liĂ©es) - Transaction avec rollback en cas d'erreur **Usage** : ```bash # Interactif ./scripts/migrate_batch.sh # Choisir option d) puis rĂ©pondre 'y' Ă  la question de suppression # Direct php migrate_from_backup.php --source-db=geosector_20251008 --mode=entity --entity-id=5 --delete-before ``` --- ## 📊 RÉSULTATS MIGRATION TEST (EntitĂ© #5) DerniĂšre exĂ©cution avec toutes les corrections : - ✅ **EntitĂ©s** : 1 SOURCE → 1 TARGET - ✅ **Users** : 21 SOURCE → 21 TARGET (100%) - ✅ **Operations** : 4 SOURCE → 4 TARGET (100%) - ✅ **Ope_sectors** : 64 SOURCE → 64 TARGET (100%) - ⚠ **Sectors_adresses** : 1975 SOURCE → 1040 TARGET (diffĂ©rence de -935, Ă  investiguer) - ✅ **Ope_users** : 20 migrĂ©s (0 erreurs aprĂšs vĂ©rification FK) - ✅ **Ope_users_sectors** : 20 migrĂ©s (0 erreurs aprĂšs vĂ©rification FK) - ⚠ **Ope_pass** : 466 erreurs (users manquants - comportement attendu avec validation FK) - ✅ **Medias** : Migration rĂ©ussie ### 15. **Ajout de contraintes UNIQUE pour Ă©viter les doublons** (10/10/2025) ⭐ CONTRAINTES MANQUANTES **ProblĂšme** : Les tables `ope_users` et `ope_users_sectors` n'avaient PAS de contrainte UNIQUE sur leurs combinaisons de FK, permettant des doublons massifs. **Diagnostic** : - Table `ope_users` : 186+ doublons pour la mĂȘme paire (fk_operation, fk_user) - Table `ope_users_sectors` : Risque de doublons sur (fk_operation, fk_user, fk_sector) - Le `ON DUPLICATE KEY UPDATE` ne fonctionnait pas car aucune contrainte UNIQUE n'existait **Solution** : CrĂ©ation du script `scripts/sql/add_unique_constraints_ope_tables.sql` qui : 1. Supprime les doublons existants (garde la premiĂšre occurrence, supprime les duplicatas) 2. Ajoute `UNIQUE KEY idx_operation_user (fk_operation, fk_user)` sur `ope_users` 3. Ajoute `UNIQUE KEY idx_operation_user_sector (fk_operation, fk_user, fk_sector)` sur `ope_users_sectors` 4. VĂ©rifie les contraintes et compte les doublons restants **Fichiers modifiĂ©s** : - `scripts/sql/add_unique_constraints_ope_tables.sql` - Script SQL d'ajout des contraintes - `scripts/php/geo_app_structure.sql` - Documentation de la structure cible avec contraintes **À exĂ©cuter AVANT la prochaine migration** : ```bash mysql -u root -p pra_geo < scripts/sql/add_unique_constraints_ope_tables.sql ``` **Puis re-migrer l'entitĂ©** : ```bash php migrate_from_backup.php --source-db=geosector_20251008 --mode=entity --entity-id=5 --delete-before ``` --- **Prochaines Ă©tapes** : 1. ✅ ExĂ©cuter le script SQL pour ajouter les contraintes UNIQUE 2. ✅ Re-migrer l'entitĂ© #5 avec `--delete-before` pour vĂ©rifier l'absence de doublons 3. Investiguer la diffĂ©rence de -935 sur `sectors_adresses` 4. Analyser les 466 erreurs sur `ope_pass` (probablement des rĂ©fĂ©rences Ă  des users d'autres entitĂ©s) 5. Tester sur une autre entitĂ© pour valider la stabilitĂ© des corrections