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

291 lines
12 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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