- 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>
291 lines
12 KiB
Markdown
291 lines
12 KiB
Markdown
# 🔧 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
|