Files
geo/api/scripts/CORRECTIONS_MIGRATE.md
pierre 2f5946a184 feat: Version 3.5.2 - Configuration Stripe et gestion des immeubles
- Configuration complète Stripe pour les 3 environnements (DEV/REC/PROD)
  * DEV: Clés TEST Pierre (mode test)
  * REC: Clés TEST Client (mode test)
  * PROD: Clés LIVE Client (mode live)
- Ajout de la gestion des bases de données immeubles/bâtiments
  * Configuration buildings_database pour DEV/REC/PROD
  * Service BuildingService pour enrichissement des adresses
- Optimisations pages et améliorations ergonomie
- Mises à jour des dépendances Composer
- Nettoyage des fichiers obsolètes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-09 18:26:27 +01:00

12 KiB
Raw Permalink Blame History

🔧 CORRECTIONS CRITIQUES - migrate_from_backup.php

ERREURS DÉTECTÉES

1. migrateUsers (ligne 456)

-- 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)

-- 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)

-- 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)

-- 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)

-- ERREUR potentielle
m.support_rowid

-- CORRECTION
m.support_rowid AS support_id

6. migrateOperations (erreur NOT NULL)

-- 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 :

-- 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 :

// 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 :

// 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) :

// 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 :

// 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) :

# 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) :

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 :

# 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 :

mysql -u root -p pra_geo < scripts/sql/add_unique_constraints_ope_tables.sql

Puis re-migrer l'entité :

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