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>
This commit is contained in:
pierre
2025-11-09 18:26:27 +01:00
parent 21657a3820
commit 2f5946a184
812 changed files with 142105 additions and 25992 deletions

467
api/scripts/migrate_batch.sh Executable file
View File

@@ -0,0 +1,467 @@
#!/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