feat: Version 3.3.5 - Optimisations pages, améliorations ergonomie et affichages dynamiques stats

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
pierre
2025-10-06 15:32:32 +02:00
parent b6584c83fa
commit 2b3d05c981
31 changed files with 1982 additions and 1442 deletions

View File

@@ -0,0 +1,165 @@
#!/bin/bash
##############################################################################
# Script de mise à jour des paramètres PHP-FPM pour GeoSector
#
# Usage:
# ./update_php_fpm_settings.sh dev # Pour DVA
# ./update_php_fpm_settings.sh rec # Pour RCA
# ./update_php_fpm_settings.sh prod # Pour PRA
##############################################################################
set -e
# Couleurs
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Déterminer l'environnement
ENV=${1:-dev}
case $ENV in
dev)
CONTAINER="dva-geo"
TIMEOUT=180
MAX_REQUESTS=1000
MEMORY_LIMIT=512M
;;
rec)
CONTAINER="rca-geo"
TIMEOUT=120
MAX_REQUESTS=2000
MEMORY_LIMIT=256M
;;
prod)
CONTAINER="pra-geo"
TIMEOUT=120
MAX_REQUESTS=2000
MEMORY_LIMIT=256M
;;
*)
echo -e "${RED}Erreur: Environnement invalide '$ENV'${NC}"
echo "Usage: $0 [dev|rec|prod]"
exit 1
;;
esac
echo -e "${GREEN}=== Mise à jour PHP-FPM pour $ENV ($CONTAINER) ===${NC}"
echo ""
# Vérifier que le container existe
if ! incus list | grep -q "$CONTAINER"; then
echo -e "${RED}Erreur: Container $CONTAINER non trouvé${NC}"
exit 1
fi
# Trouver le fichier de configuration
echo "Recherche du fichier de configuration PHP-FPM..."
POOL_FILE=$(incus exec $CONTAINER -- find /etc/php* -name "www.conf" 2>/dev/null | grep fpm/pool | head -1)
if [ -z "$POOL_FILE" ]; then
echo -e "${RED}Erreur: Fichier pool PHP-FPM non trouvé${NC}"
exit 1
fi
echo -e "${GREEN}✓ Fichier trouvé: $POOL_FILE${NC}"
echo ""
# Sauvegarder le fichier original
BACKUP_FILE="${POOL_FILE}.backup.$(date +%Y%m%d_%H%M%S)"
echo "Création d'une sauvegarde..."
incus exec $CONTAINER -- cp "$POOL_FILE" "$BACKUP_FILE"
echo -e "${GREEN}✓ Sauvegarde créée: $BACKUP_FILE${NC}"
echo ""
# Afficher les valeurs actuelles
echo "Valeurs actuelles:"
incus exec $CONTAINER -- grep -E "^(request_terminate_timeout|pm.max_requests|memory_limit)" "$POOL_FILE" || echo " (non définies)"
echo ""
# Créer un fichier temporaire avec les nouvelles valeurs
TMP_FILE="/tmp/php_fpm_update_$$.conf"
cat > $TMP_FILE << EOF
; === Configuration GeoSector - Modifié le $(date +%Y-%m-%d) ===
; Timeout des requêtes
request_terminate_timeout = ${TIMEOUT}s
; Nombre max de requêtes avant recyclage du worker
pm.max_requests = ${MAX_REQUESTS}
; Limite mémoire PHP
php_admin_value[memory_limit] = ${MEMORY_LIMIT}
; Log des requêtes lentes
slowlog = /var/log/php8.3-fpm-slow.log
request_slowlog_timeout = 10s
EOF
echo "Nouvelles valeurs à appliquer:"
cat $TMP_FILE
echo ""
# Demander confirmation
read -p "Appliquer ces modifications ? (y/N) " -n 1 -r
echo ""
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Annulé."
rm $TMP_FILE
exit 0
fi
# Supprimer les anciennes valeurs si présentes
echo "Suppression des anciennes valeurs..."
incus exec $CONTAINER -- sed -i '/^request_terminate_timeout/d' "$POOL_FILE"
incus exec $CONTAINER -- sed -i '/^pm.max_requests/d' "$POOL_FILE"
incus exec $CONTAINER -- sed -i '/^php_admin_value\[memory_limit\]/d' "$POOL_FILE"
incus exec $CONTAINER -- sed -i '/^slowlog/d' "$POOL_FILE"
incus exec $CONTAINER -- sed -i '/^request_slowlog_timeout/d' "$POOL_FILE"
# Ajouter les nouvelles valeurs à la fin du fichier
echo "Ajout des nouvelles valeurs..."
incus file push $TMP_FILE $CONTAINER/tmp/php_fpm_settings.conf
incus exec $CONTAINER -- bash -c "cat /tmp/php_fpm_settings.conf >> $POOL_FILE"
incus exec $CONTAINER -- rm /tmp/php_fpm_settings.conf
rm $TMP_FILE
echo -e "${GREEN}✓ Configuration mise à jour${NC}"
echo ""
# Tester la configuration
echo "Test de la configuration PHP-FPM..."
if incus exec $CONTAINER -- php-fpm8.3 -t; then
echo -e "${GREEN}✓ Configuration valide${NC}"
else
echo -e "${RED}✗ Configuration invalide !${NC}"
echo "Restauration de la sauvegarde..."
incus exec $CONTAINER -- cp "$BACKUP_FILE" "$POOL_FILE"
exit 1
fi
echo ""
echo "Redémarrage de PHP-FPM..."
incus exec $CONTAINER -- rc-service php-fpm8.3 restart
if [ $? -eq 0 ]; then
echo -e "${GREEN}✓ PHP-FPM redémarré avec succès${NC}"
else
echo -e "${RED}✗ Erreur lors du redémarrage${NC}"
echo "Restauration de la sauvegarde..."
incus exec $CONTAINER -- cp "$BACKUP_FILE" "$POOL_FILE"
incus exec $CONTAINER -- rc-service php-fpm8.3 restart
exit 1
fi
echo ""
echo -e "${GREEN}=== Mise à jour terminée avec succès ===${NC}"
echo ""
echo "Vérification des nouvelles valeurs:"
incus exec $CONTAINER -- grep -E "^(request_terminate_timeout|pm.max_requests|php_admin_value\[memory_limit\])" "$POOL_FILE"
echo ""
echo "Sauvegarde disponible: $BACKUP_FILE"

View File

@@ -0,0 +1,57 @@
-- Migration : Ajout des champs manquants dans email_queue
-- Date : 2025-01-06
-- Description : Ajoute sent_at et error_message pour le bon fonctionnement du CRON
USE geo_app;
-- Vérifier si les champs existent déjà avant de les ajouter
SET @db_name = DATABASE();
SET @table_name = 'email_queue';
-- Ajouter sent_at si n'existe pas
SET @column_exists = (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db_name
AND TABLE_NAME = @table_name
AND COLUMN_NAME = 'sent_at'
);
SET @sql = IF(@column_exists = 0,
'ALTER TABLE email_queue ADD COLUMN sent_at TIMESTAMP NULL DEFAULT NULL AFTER status',
'SELECT "Column sent_at already exists" AS message'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Ajouter error_message si n'existe pas
SET @column_exists = (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db_name
AND TABLE_NAME = @table_name
AND COLUMN_NAME = 'error_message'
);
SET @sql = IF(@column_exists = 0,
'ALTER TABLE email_queue ADD COLUMN error_message TEXT NULL DEFAULT NULL AFTER attempts',
'SELECT "Column error_message already exists" AS message'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Vérifier le résultat
SELECT
'Migration terminée' AS status,
COLUMN_NAME,
COLUMN_TYPE,
IS_NULLABLE,
COLUMN_DEFAULT
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db_name
AND TABLE_NAME = @table_name
AND COLUMN_NAME IN ('sent_at', 'error_message');

View File

@@ -0,0 +1,112 @@
#!/usr/bin/env php
<?php
/**
* Script de test pour générer manuellement un reçu
* Usage: php generate_receipt_manual.php <passage_id>
*/
declare(strict_types=1);
// Simuler l'environnement web pour AppConfig en CLI
if (php_sapi_name() === 'cli') {
$_SERVER['SERVER_NAME'] = 'dapp.geosector.fr'; // DEV
$_SERVER['HTTP_HOST'] = $_SERVER['SERVER_NAME'];
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
if (!function_exists('getallheaders')) {
function getallheaders() {
return [];
}
}
}
// Chargement de l'environnement
require_once __DIR__ . '/../../vendor/autoload.php';
require_once __DIR__ . '/../../src/Config/AppConfig.php';
require_once __DIR__ . '/../../src/Core/Database.php';
require_once __DIR__ . '/../../src/Services/LogService.php';
require_once __DIR__ . '/../../src/Services/ReceiptService.php';
// Vérifier qu'un ID de passage est fourni
if ($argc < 2) {
echo "Usage: php generate_receipt_manual.php <passage_id>\n";
exit(1);
}
$passageId = (int)$argv[1];
try {
echo "=== Test de génération de reçu ===\n";
echo "Passage ID: $passageId\n\n";
// Initialisation de la configuration
$appConfig = AppConfig::getInstance();
$dbConfig = $appConfig->getDatabaseConfig();
// Initialiser la base de données
Database::init($dbConfig);
$db = Database::getInstance();
echo "✓ Connexion à la base de données OK\n";
// Vérifier le passage
$stmt = $db->prepare('SELECT id, fk_type, encrypted_email, nom_recu FROM ope_pass WHERE id = ?');
$stmt->execute([$passageId]);
$passage = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$passage) {
echo "✗ Passage $passageId non trouvé\n";
exit(1);
}
echo "✓ Passage trouvé\n";
echo " - fk_type: " . $passage['fk_type'] . "\n";
echo " - encrypted_email: " . (!empty($passage['encrypted_email']) ? 'OUI' : 'NON') . "\n";
echo " - nom_recu: " . ($passage['nom_recu'] ?: 'vide') . "\n\n";
// Déchiffrer l'email
if (!empty($passage['encrypted_email'])) {
$email = \ApiService::decryptSearchableData($passage['encrypted_email']);
echo " - Email déchiffré: $email\n";
echo " - Email valide: " . (filter_var($email, FILTER_VALIDATE_EMAIL) ? 'OUI' : 'NON') . "\n\n";
} else {
echo "✗ Aucun email chiffré trouvé\n";
exit(1);
}
// Générer le reçu
echo "Génération du reçu...\n";
$receiptService = new \App\Services\ReceiptService();
$result = $receiptService->generateReceiptForPassage($passageId);
if ($result) {
echo "✓ Reçu généré avec succès !\n\n";
// Vérifier l'email dans la queue
$stmt = $db->prepare('SELECT id, to_email, status, created_at FROM email_queue WHERE fk_pass = ? ORDER BY created_at DESC LIMIT 1');
$stmt->execute([$passageId]);
$queueEmail = $stmt->fetch(PDO::FETCH_ASSOC);
if ($queueEmail) {
echo "✓ Email ajouté à la queue\n";
echo " - Queue ID: " . $queueEmail['id'] . "\n";
echo " - Destinataire: " . $queueEmail['to_email'] . "\n";
echo " - Status: " . $queueEmail['status'] . "\n";
echo " - Créé: " . $queueEmail['created_at'] . "\n";
} else {
echo "✗ Aucun email trouvé dans la queue\n";
}
} else {
echo "✗ Échec de la génération du reçu\n";
echo "Consultez /var/www/geosector/api/logs/api.log pour plus de détails\n";
}
} catch (Exception $e) {
echo "✗ ERREUR: " . $e->getMessage() . "\n";
echo $e->getTraceAsString() . "\n";
exit(1);
}
echo "\n=== Fin du test ===\n";
exit(0);