- 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>
468 lines
16 KiB
Bash
Executable File
468 lines
16 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
###############################################################################
|
||
# Script de migration en batch des entités depuis geosector_20251008
|
||
#
|
||
# Usage: ./migrate_batch.sh [options]
|
||
#
|
||
# Options:
|
||
# --start N Commencer à partir de l'entité N (défaut: 1)
|
||
# --limit N Migrer seulement N entités (défaut: toutes)
|
||
# --dry-run Simuler sans exécuter
|
||
# --continue Continuer après une erreur (défaut: s'arrêter)
|
||
# --interactive Mode interactif (défaut si aucune option)
|
||
#
|
||
# Exemple:
|
||
# ./migrate_batch.sh --start 10 --limit 5
|
||
# ./migrate_batch.sh --continue
|
||
# ./migrate_batch.sh --interactive
|
||
###############################################################################
|
||
|
||
# Configuration
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
JSON_FILE="${SCRIPT_DIR}/migrations_entites.json"
|
||
LOG_DIR="/var/www/geosector/api/logs/migrations"
|
||
MIGRATION_SCRIPT="${SCRIPT_DIR}/php/migrate_from_backup.php"
|
||
SOURCE_DB="geosector_20251013_13"
|
||
TARGET_DB="pra_geo"
|
||
|
||
# Paramètres par défaut
|
||
START_INDEX=1
|
||
LIMIT=0
|
||
DRY_RUN=0
|
||
CONTINUE_ON_ERROR=0
|
||
INTERACTIVE_MODE=0
|
||
SPECIFIC_ENTITY_ID=""
|
||
SPECIFIC_CP=""
|
||
|
||
# Couleurs
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
CYAN='\033[0;36m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Sauvegarder le nombre d'arguments avant le parsing
|
||
INITIAL_ARGS=$#
|
||
|
||
# Parse des arguments
|
||
while [[ $# -gt 0 ]]; do
|
||
case $1 in
|
||
--start)
|
||
START_INDEX="$2"
|
||
shift 2
|
||
;;
|
||
--limit)
|
||
LIMIT="$2"
|
||
shift 2
|
||
;;
|
||
--dry-run)
|
||
DRY_RUN=1
|
||
shift
|
||
;;
|
||
--continue)
|
||
CONTINUE_ON_ERROR=1
|
||
shift
|
||
;;
|
||
--interactive|-i)
|
||
INTERACTIVE_MODE=1
|
||
shift
|
||
;;
|
||
--help)
|
||
grep "^#" "$0" | grep -v "^#!/bin/bash" | sed 's/^# //'
|
||
exit 0
|
||
;;
|
||
*)
|
||
echo "Option inconnue: $1"
|
||
echo "Utilisez --help pour l'aide"
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
|
||
# Activer le mode interactif si aucun argument n'a été fourni
|
||
if [ $INITIAL_ARGS -eq 0 ]; then
|
||
INTERACTIVE_MODE=1
|
||
fi
|
||
|
||
# Vérifications préalables
|
||
if [ ! -f "$JSON_FILE" ]; then
|
||
echo -e "${RED}❌ Fichier JSON introuvable: $JSON_FILE${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
if [ ! -f "$MIGRATION_SCRIPT" ]; then
|
||
echo -e "${RED}❌ Script de migration introuvable: $MIGRATION_SCRIPT${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
# Créer le répertoire de logs
|
||
mkdir -p "$LOG_DIR"
|
||
|
||
# Fichiers de log
|
||
BATCH_LOG="${LOG_DIR}/batch_$(date +%Y%m%d_%H%M%S).log"
|
||
SUCCESS_LOG="${LOG_DIR}/success.log"
|
||
ERROR_LOG="${LOG_DIR}/errors.log"
|
||
|
||
# MODE INTERACTIF
|
||
if [ $INTERACTIVE_MODE -eq 1 ]; then
|
||
echo ""
|
||
echo -e "${CYAN}═══════════════════════════════════════════════════════════${NC}"
|
||
echo -e "${CYAN} 🔧 Mode interactif - Migration d'entités GeoSector${NC}"
|
||
echo -e "${CYAN}═══════════════════════════════════════════════════════════${NC}"
|
||
echo ""
|
||
|
||
# Question 1: Migration globale ou ciblée ?
|
||
echo -e "${YELLOW}1️⃣ Type de migration :${NC}"
|
||
echo -e " ${CYAN}a)${NC} Migration globale (toutes les entités)"
|
||
echo -e " ${CYAN}b)${NC} Migration par lot (plage d'entités)"
|
||
echo -e " ${CYAN}c)${NC} Migration par code postal"
|
||
echo -e " ${CYAN}d)${NC} Migration d'une entité spécifique (ID)"
|
||
echo ""
|
||
echo -ne "${YELLOW}Votre choix (a/b/c/d) : ${NC}"
|
||
read -r MIGRATION_TYPE
|
||
echo ""
|
||
|
||
case $MIGRATION_TYPE in
|
||
a|A)
|
||
# Migration globale - garder les valeurs par défaut
|
||
START_INDEX=1
|
||
LIMIT=0
|
||
echo -e "${GREEN}✓${NC} Migration globale sélectionnée"
|
||
;;
|
||
b|B)
|
||
# Migration par lot
|
||
echo -e "${YELLOW}2️⃣ Configuration du lot :${NC}"
|
||
echo -ne " Première entité (index, défaut=1) : "
|
||
read -r USER_START
|
||
if [ -n "$USER_START" ]; then
|
||
START_INDEX=$USER_START
|
||
fi
|
||
|
||
echo -ne " Limite (nombre d'entités, défaut=toutes) : "
|
||
read -r USER_LIMIT
|
||
if [ -n "$USER_LIMIT" ]; then
|
||
LIMIT=$USER_LIMIT
|
||
fi
|
||
echo ""
|
||
echo -e "${GREEN}✓${NC} Migration par lot : de l'index $START_INDEX, limite de $LIMIT entités"
|
||
;;
|
||
c|C)
|
||
# Migration par code postal
|
||
echo -ne "${YELLOW}2️⃣ Code postal à migrer : ${NC}"
|
||
read -r SPECIFIC_CP
|
||
echo ""
|
||
if [ -z "$SPECIFIC_CP" ]; then
|
||
echo -e "${RED}❌ Code postal requis${NC}"
|
||
exit 1
|
||
fi
|
||
echo -e "${GREEN}✓${NC} Migration pour le code postal : $SPECIFIC_CP"
|
||
;;
|
||
d|D)
|
||
# Migration d'une entité spécifique - bypass complet du JSON
|
||
echo -ne "${YELLOW}2️⃣ ID de l'entité à migrer : ${NC}"
|
||
read -r SPECIFIC_ENTITY_ID
|
||
echo ""
|
||
if [ -z "$SPECIFIC_ENTITY_ID" ]; then
|
||
echo -e "${RED}❌ ID d'entité requis${NC}"
|
||
exit 1
|
||
fi
|
||
echo -e "${GREEN}✓${NC} Migration de l'entité ID : $SPECIFIC_ENTITY_ID"
|
||
echo ""
|
||
|
||
# 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"
|
||
else
|
||
echo -e "${BLUE}ℹ${NC} Les données seront conservées (ON DUPLICATE KEY UPDATE)"
|
||
fi
|
||
echo ""
|
||
|
||
# Confirmer la migration
|
||
echo -ne "${YELLOW}⚠️ Confirmer la migration de l'entité #${SPECIFIC_ENTITY_ID} ? (y/N): ${NC}"
|
||
read -r CONFIRM
|
||
if [[ ! $CONFIRM =~ ^[Yy]$ ]]; then
|
||
echo -e "${RED}❌ Migration annulée${NC}"
|
||
exit 0
|
||
fi
|
||
|
||
# Exécuter directement la migration sans passer par le JSON
|
||
ENTITY_LOG="${LOG_DIR}/entity_${SPECIFIC_ENTITY_ID}_$(date +%Y%m%d_%H%M%S).log"
|
||
|
||
echo ""
|
||
echo -e "${BLUE}⏳ Migration de l'entité #${SPECIFIC_ENTITY_ID} en cours...${NC}"
|
||
|
||
php "$MIGRATION_SCRIPT" \
|
||
--source-db="$SOURCE_DB" \
|
||
--target-db="$TARGET_DB" \
|
||
--mode=entity \
|
||
--entity-id="$SPECIFIC_ENTITY_ID" \
|
||
--log="$ENTITY_LOG" \
|
||
$DELETE_FLAG
|
||
|
||
EXIT_CODE=$?
|
||
|
||
if [ $EXIT_CODE -eq 0 ]; then
|
||
echo -e "${GREEN}✅ Entité #${SPECIFIC_ENTITY_ID} migrée avec succès${NC}"
|
||
echo -e "${BLUE}📋 Log détaillé : $ENTITY_LOG${NC}"
|
||
else
|
||
echo -e "${RED}❌ Erreur lors de la migration de l'entité #${SPECIFIC_ENTITY_ID}${NC}"
|
||
echo -e "${RED}📋 Voir le log : $ENTITY_LOG${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
exit 0
|
||
;;
|
||
*)
|
||
echo -e "${RED}❌ Choix invalide${NC}"
|
||
exit 1
|
||
;;
|
||
esac
|
||
|
||
echo ""
|
||
fi
|
||
|
||
# Fonctions utilitaires
|
||
log() {
|
||
echo -e "$1" | tee -a "$BATCH_LOG"
|
||
}
|
||
|
||
log_success() {
|
||
echo "$1" >> "$SUCCESS_LOG"
|
||
log "${GREEN}✓${NC} $1"
|
||
}
|
||
|
||
log_error() {
|
||
echo "$1" >> "$ERROR_LOG"
|
||
log "${RED}✗${NC} $1"
|
||
}
|
||
|
||
# Extraire les entity_id du JSON (compatible sans jq)
|
||
get_entity_ids() {
|
||
if [ -n "$SPECIFIC_ENTITY_ID" ]; then
|
||
# Entité spécifique par ID - chercher exactement "entity_id" : ID,
|
||
grep "\"entity_id\" : ${SPECIFIC_ENTITY_ID}," "$JSON_FILE" | sed 's/.*: \([0-9]*\).*/\1/'
|
||
elif [ -n "$SPECIFIC_CP" ]; then
|
||
# Entités par code postal
|
||
grep -B 2 "\"code_postal\" : \"$SPECIFIC_CP\"" "$JSON_FILE" | grep '"entity_id"' | sed 's/.*: \([0-9]*\).*/\1/'
|
||
else
|
||
# Toutes les entités
|
||
grep '"entity_id"' "$JSON_FILE" | sed 's/.*: \([0-9]*\).*/\1/'
|
||
fi
|
||
}
|
||
|
||
# Compter le nombre total d'entités
|
||
TOTAL_ENTITIES=$(get_entity_ids | wc -l)
|
||
|
||
# Vérifier si des entités ont été trouvées
|
||
if [ $TOTAL_ENTITIES -eq 0 ]; then
|
||
if [ -n "$SPECIFIC_ENTITY_ID" ]; then
|
||
echo -e "${RED}❌ Entité #${SPECIFIC_ENTITY_ID} introuvable dans le fichier JSON${NC}"
|
||
elif [ -n "$SPECIFIC_CP" ]; then
|
||
echo -e "${RED}❌ Aucune entité trouvée pour le code postal ${SPECIFIC_CP}${NC}"
|
||
else
|
||
echo -e "${RED}❌ Aucune entité trouvée${NC}"
|
||
fi
|
||
exit 1
|
||
fi
|
||
|
||
# Calculer le nombre d'entités à migrer
|
||
if [ $LIMIT -gt 0 ]; then
|
||
END_INDEX=$((START_INDEX + LIMIT - 1))
|
||
if [ $END_INDEX -gt $TOTAL_ENTITIES ]; then
|
||
END_INDEX=$TOTAL_ENTITIES
|
||
fi
|
||
else
|
||
END_INDEX=$TOTAL_ENTITIES
|
||
fi
|
||
|
||
# Bannière de démarrage
|
||
echo ""
|
||
log "${BLUE}═══════════════════════════════════════════════════════════${NC}"
|
||
log "${BLUE} Migration en batch des entités GeoSector${NC}"
|
||
log "${BLUE}═══════════════════════════════════════════════════════════${NC}"
|
||
log "📅 Date: $(date '+%Y-%m-%d %H:%M:%S')"
|
||
log "📁 Source: $SOURCE_DB"
|
||
log "📁 Cible: $TARGET_DB"
|
||
|
||
# Afficher les informations selon le mode
|
||
if [ -n "$SPECIFIC_ENTITY_ID" ]; then
|
||
log "🎯 Mode: Migration d'une entité spécifique"
|
||
log "📊 Entité ID: $SPECIFIC_ENTITY_ID"
|
||
elif [ -n "$SPECIFIC_CP" ]; then
|
||
log "🎯 Mode: Migration par code postal"
|
||
log "📮 Code postal: $SPECIFIC_CP"
|
||
log "📊 Entités trouvées: $TOTAL_ENTITIES"
|
||
else
|
||
TOTAL_AVAILABLE=$(grep '"entity_id"' "$JSON_FILE" | wc -l)
|
||
log "📊 Total entités disponibles: $TOTAL_AVAILABLE"
|
||
log "🎯 Entités à migrer: $START_INDEX à $END_INDEX"
|
||
fi
|
||
|
||
if [ $DRY_RUN -eq 1 ]; then
|
||
log "${YELLOW}🔍 Mode DRY-RUN (simulation)${NC}"
|
||
fi
|
||
log "${BLUE}═══════════════════════════════════════════════════════════${NC}"
|
||
echo ""
|
||
|
||
# Confirmation utilisateur
|
||
if [ $DRY_RUN -eq 0 ]; then
|
||
echo -ne "${YELLOW}⚠️ Confirmer la migration ? (y/N): ${NC}"
|
||
read -r CONFIRM
|
||
if [[ ! $CONFIRM =~ ^[Yy]$ ]]; then
|
||
log "❌ Migration annulée par l'utilisateur"
|
||
exit 0
|
||
fi
|
||
echo ""
|
||
fi
|
||
|
||
# Compteurs
|
||
SUCCESS_COUNT=0
|
||
ERROR_COUNT=0
|
||
SKIPPED_COUNT=0
|
||
CURRENT_INDEX=0
|
||
|
||
# Début de la migration
|
||
START_TIME=$(date +%s)
|
||
|
||
# Lire les entity_id et migrer
|
||
get_entity_ids | while read -r ENTITY_ID; do
|
||
CURRENT_INDEX=$((CURRENT_INDEX + 1))
|
||
|
||
# Filtrer par index
|
||
if [ $CURRENT_INDEX -lt $START_INDEX ]; then
|
||
continue
|
||
fi
|
||
|
||
if [ $CURRENT_INDEX -gt $END_INDEX ]; then
|
||
break
|
||
fi
|
||
|
||
# Récupérer les détails de l'entité depuis le JSON (match exact avec la virgule)
|
||
ENTITY_INFO=$(grep -A 8 "\"entity_id\" : ${ENTITY_ID}," "$JSON_FILE")
|
||
ENTITY_NAME=$(echo "$ENTITY_INFO" | grep '"nom"' | sed 's/.*: "\(.*\)".*/\1/')
|
||
ENTITY_CP=$(echo "$ENTITY_INFO" | grep '"code_postal"' | sed 's/.*: "\(.*\)".*/\1/')
|
||
NB_USERS=$(echo "$ENTITY_INFO" | grep '"nb_users"' | sed 's/.*: \([0-9]*\).*/\1/')
|
||
NB_PASSAGES=$(echo "$ENTITY_INFO" | grep '"nb_passages"' | sed 's/.*: \([0-9]*\).*/\1/')
|
||
|
||
# Afficher la progression
|
||
PROGRESS=$((CURRENT_INDEX - START_INDEX + 1))
|
||
TOTAL=$((END_INDEX - START_INDEX + 1))
|
||
PERCENT=$((PROGRESS * 100 / TOTAL))
|
||
|
||
log ""
|
||
log "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||
log "${BLUE}[$PROGRESS/$TOTAL - ${PERCENT}%]${NC} Entité #${ENTITY_ID}: ${ENTITY_NAME} (${ENTITY_CP})"
|
||
log " 👥 Users: ${NB_USERS} | 📍 Passages: ${NB_PASSAGES}"
|
||
|
||
# Mode dry-run
|
||
if [ $DRY_RUN -eq 1 ]; then
|
||
log "${YELLOW} 🔍 [DRY-RUN] Simulation de la migration${NC}"
|
||
SKIPPED_COUNT=$((SKIPPED_COUNT + 1))
|
||
continue
|
||
fi
|
||
|
||
# Exécuter la migration
|
||
ENTITY_LOG="${LOG_DIR}/entity_${ENTITY_ID}_$(date +%Y%m%d_%H%M%S).log"
|
||
|
||
log " ⏳ Migration en cours..."
|
||
php "$MIGRATION_SCRIPT" \
|
||
--source-db="$SOURCE_DB" \
|
||
--target-db="$TARGET_DB" \
|
||
--mode=entity \
|
||
--entity-id="$ENTITY_ID" \
|
||
--log="$ENTITY_LOG" > /tmp/migration_output_$$.txt 2>&1
|
||
|
||
EXIT_CODE=$?
|
||
|
||
if [ $EXIT_CODE -eq 0 ]; then
|
||
# Succès
|
||
SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
|
||
log_success "Entité #${ENTITY_ID} (${ENTITY_NAME}) migrée avec succès"
|
||
|
||
# Afficher un résumé du log avec détails
|
||
if [ -f "$ENTITY_LOG" ]; then
|
||
# Chercher la ligne avec les marqueurs #STATS#
|
||
STATS_LINE=$(grep "#STATS#" "$ENTITY_LOG" 2>/dev/null)
|
||
|
||
if [ -n "$STATS_LINE" ]; then
|
||
# Extraire chaque compteur
|
||
OPE=$(echo "$STATS_LINE" | grep -oE 'OPE:[0-9]+' | cut -d: -f2)
|
||
USERS=$(echo "$STATS_LINE" | grep -oE 'USER:[0-9]+' | cut -d: -f2)
|
||
SECTORS=$(echo "$STATS_LINE" | grep -oE 'SECTOR:[0-9]+' | cut -d: -f2)
|
||
PASSAGES=$(echo "$STATS_LINE" | grep -oE 'PASS:[0-9]+' | cut -d: -f2)
|
||
|
||
# Valeurs par défaut si extraction échoue
|
||
OPE=${OPE:-0}
|
||
USERS=${USERS:-0}
|
||
SECTORS=${SECTORS:-0}
|
||
PASSAGES=${PASSAGES:-0}
|
||
|
||
log " 📊 ope: ${OPE} | users: ${USERS} | sectors: ${SECTORS} | passages: ${PASSAGES}"
|
||
else
|
||
log " 📊 Statistiques non disponibles"
|
||
fi
|
||
fi
|
||
else
|
||
# Erreur
|
||
ERROR_COUNT=$((ERROR_COUNT + 1))
|
||
log_error "Entité #${ENTITY_ID} (${ENTITY_NAME}) - Erreur code $EXIT_CODE"
|
||
|
||
# Afficher les dernières lignes du log d'erreur
|
||
if [ -f "/tmp/migration_output_$$.txt" ]; then
|
||
log "${RED} 📋 Dernières erreurs:${NC}"
|
||
tail -5 "/tmp/migration_output_$$.txt" | sed 's/^/ /' | tee -a "$BATCH_LOG"
|
||
fi
|
||
|
||
# Arrêter ou continuer ?
|
||
if [ $CONTINUE_ON_ERROR -eq 0 ]; then
|
||
log ""
|
||
log "${RED}❌ Migration interrompue suite à une erreur${NC}"
|
||
log " Utilisez --continue pour continuer malgré les erreurs"
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# Nettoyage
|
||
rm -f "/tmp/migration_output_$$.txt"
|
||
|
||
# Pause entre les migrations (pour éviter de surcharger)
|
||
sleep 1
|
||
done
|
||
|
||
# Fin de la migration
|
||
END_TIME=$(date +%s)
|
||
DURATION=$((END_TIME - START_TIME))
|
||
HOURS=$((DURATION / 3600))
|
||
MINUTES=$(((DURATION % 3600) / 60))
|
||
SECONDS=$((DURATION % 60))
|
||
|
||
# Résumé final
|
||
log ""
|
||
log "${BLUE}═══════════════════════════════════════════════════════════${NC}"
|
||
log "${BLUE} Résumé de la migration${NC}"
|
||
log "${BLUE}═══════════════════════════════════════════════════════════${NC}"
|
||
log "✅ Succès: ${GREEN}${SUCCESS_COUNT}${NC}"
|
||
log "❌ Erreurs: ${RED}${ERROR_COUNT}${NC}"
|
||
log "⏭️ Ignorées: ${YELLOW}${SKIPPED_COUNT}${NC}"
|
||
log "⏱️ Durée: ${HOURS}h ${MINUTES}m ${SECONDS}s"
|
||
log ""
|
||
log "📋 Logs détaillés:"
|
||
log " - Batch: $BATCH_LOG"
|
||
log " - Succès: $SUCCESS_LOG"
|
||
log " - Erreurs: $ERROR_LOG"
|
||
log " - Individuels: $LOG_DIR/entity_*.log"
|
||
log "${BLUE}═══════════════════════════════════════════════════════════${NC}"
|
||
|
||
# Code de sortie
|
||
if [ $ERROR_COUNT -gt 0 ]; then
|
||
exit 1
|
||
else
|
||
exit 0
|
||
fi
|