Merge pull request #204 from R0m1k3/1.1

1.1
This commit is contained in:
LogiFlow authored and GitHub committed 2025-08-18 11:33:42 +02:00
commit c47733da8d
7 files changed
+586 -4

No files matched your search

+2 -1
View File
@@ -81,8 +81,9 @@ RUN npm ci --only=production && npm cache clean --force
COPY --from=build --chown=nextjs:nodejs /app/dist ./dist
COPY --from=build --chown=nextjs:nodejs /app/shared ./shared
# Copy migration scripts
# Copy migration scripts and files
COPY --chown=nextjs:nodejs scripts/ ./scripts/
COPY --chown=nextjs:nodejs migrations/ ./migrations/
# Create symlink for public files to be accessible from dist
RUN ln -sf /app/dist/public /app/dist/public
@@ -0,0 +1,204 @@
at /app/node_modules/pg-pool/index.js:45:11
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
at async DatabaseStorage.getDlcProducts (file:///app/dist/index.js:2187:25)
at async file:///app/dist/index.js:6178:28 {
length: 124,
severity: 'ERROR',
code: '42703',
detail: undefined,
hint: undefined,
position: '337',
internalPosition: undefined,
internalQuery: undefined,
where: undefined,
schema: undefined,
table: undefined,
column: undefined,
dataType: undefined,
constraint: undefined,
file: 'parse_relation.c',
line: '3665',
routine: 'errorMissingColumn'
}
GET /api/dlc-products 500 in 20ms
GET /api/dlc-products/stats 200 in 10ms
Error fetching DLC products: error: column dlc_products.stock_epuise does not exist
at /app/node_modules/pg-pool/index.js:45:11
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
at async DatabaseStorage.getDlcProducts (file:///app/dist/index.js:2187:25)
at async file:///app/dist/index.js:6178:28 {
length: 124,
severity: 'ERROR',
code: '42703',
detail: undefined,
hint: undefined,
position: '337',
internalPosition: undefined,
internalQuery: undefined,
where: undefined,
schema: undefined,
table: undefined,
column: undefined,
dataType: undefined,
constraint: undefined,
file: 'parse_relation.c',
line: '3665',
routine: 'errorMissingColumn'
}
GET /api/dlc-products 500 in 17ms
Error fetching DLC products: error: column dlc_products.stock_epuise does not exist
at /app/node_modules/pg-pool/index.js:45:11
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
at async DatabaseStorage.getDlcProducts (file:///app/dist/index.js:2187:25)
at async file:///app/dist/index.js:6178:28 {
length: 124,
severity: 'ERROR',
code: '42703',
detail: undefined,
hint: undefined,
position: '337',
internalPosition: undefined,
internalQuery: undefined,
where: undefined,
schema: undefined,
table: undefined,
column: undefined,
dataType: undefined,
constraint: undefined,
file: 'parse_relation.c',
line: '3665',
routine: 'errorMissingColumn'
}
GET /api/dlc-products 500 in 12ms
Error fetching DLC products: error: column dlc_products.stock_epuise does not exist
at /app/node_modules/pg-pool/index.js:45:11
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
at async DatabaseStorage.getDlcProducts (file:///app/dist/index.js:2187:25)
at async file:///app/dist/index.js:6178:28 {
length: 124,
severity: 'ERROR',
code: '42703',
detail: undefined,
hint: undefined,
position: '337',
internalPosition: undefined,
internalQuery: undefined,
where: undefined,
schema: undefined,
table: undefined,
column: undefined,
dataType: undefined,
constraint: undefined,
file: 'parse_relation.c',
line: '3665',
routine: 'errorMissingColumn'
}
GET /api/dlc-products 500 in 9ms
+4
View File
@@ -13,6 +13,9 @@ services:
SESSION_SECRET: LogiFlow_Super_Secret_Session_Key_2025_Production
PORT: 3000
USE_LOCAL_AUTH: "true"
POSTGRES_USER: logiflow_admin
POSTGRES_PASSWORD: LogiFlow2025!
POSTGRES_DB: logiflow_db
ports:
- "3000:3000"
networks:
@@ -41,6 +44,7 @@ services:
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/01-init.sql
- ./migrations:/migrations
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 15s
+51
View File
@@ -0,0 +1,51 @@
-- Migration 002: Ajout des champs stock épuisé aux produits DLC
-- Date: 2025-08-18
-- Description: Ajoute la fonctionnalité de gestion du stock épuisé pour distinguer
-- les produits périmés des produits en rupture de stock
-- Vérification que la table dlc_products existe
DO $$
BEGIN
IF NOT EXISTS (SELECT FROM information_schema.tables WHERE table_name = 'dlc_products') THEN
RAISE EXCEPTION 'La table dlc_products n''existe pas. Cette migration nécessite que la table soit déjà créée.';
END IF;
END
$$;
-- Ajout des nouveaux champs pour la gestion du stock épuisé
ALTER TABLE dlc_products
ADD COLUMN IF NOT EXISTS stock_epuise boolean DEFAULT false NOT NULL,
ADD COLUMN IF NOT EXISTS stock_epuise_by varchar(255),
ADD COLUMN IF NOT EXISTS stock_epuise_at timestamp;
-- Commentaires pour documenter les nouveaux champs
COMMENT ON COLUMN dlc_products.stock_epuise IS 'Indique si le produit est marqué comme stock épuisé (différent de périmé)';
COMMENT ON COLUMN dlc_products.stock_epuise_by IS 'ID de l''utilisateur qui a marqué le produit comme stock épuisé';
COMMENT ON COLUMN dlc_products.stock_epuise_at IS 'Date et heure de marquage du stock épuisé';
-- Index pour améliorer les performances sur les requêtes de stock épuisé
CREATE INDEX IF NOT EXISTS idx_dlc_products_stock_epuise ON dlc_products(stock_epuise);
-- Initialiser les produits existants avec stock disponible (pas épuisé)
-- Cette ligne est sécurisée car DEFAULT false est déjà appliqué
UPDATE dlc_products
SET stock_epuise = false
WHERE stock_epuise IS NULL;
-- Vérification finale
DO $$
DECLARE
column_count integer;
BEGIN
SELECT COUNT(*) INTO column_count
FROM information_schema.columns
WHERE table_name = 'dlc_products'
AND column_name IN ('stock_epuise', 'stock_epuise_by', 'stock_epuise_at');
IF column_count = 3 THEN
RAISE NOTICE 'Migration 002 réussie: % colonnes ajoutées à dlc_products', column_count;
ELSE
RAISE EXCEPTION 'Migration 002 échouée: seulement % colonnes trouvées sur 3 attendues', column_count;
END IF;
END
$$;
+40 -3
View File
@@ -1,12 +1,24 @@
#!/bin/bash
# Script de migration automatique - Crée UNIQUEMENT la table announcements
# Toutes les autres tables existent déjà en production
# Script de migration automatique - Production
# Crée la table announcements et ajoute les champs DLC stock épuisé
set -e
echo "🔄 [AUTO-MIGRATE] Vérification de la table announcements..."
echo "🔄 [AUTO-MIGRATE] Début des migrations automatiques..."
# Construire DATABASE_URL si nécessaire
if [ -z "$DATABASE_URL" ]; then
if [ -n "$POSTGRES_USER" ] && [ -n "$POSTGRES_PASSWORD" ] && [ -n "$POSTGRES_DB" ]; then
export DATABASE_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@logiflow-db:5432/${POSTGRES_DB}"
echo "🔧 [AUTO-MIGRATE] URL de base de données construite"
else
echo "❌ [AUTO-MIGRATE] Variables de base de données manquantes"
exit 1
fi
fi
# Vérifier si la base de données est accessible
echo "🔗 [AUTO-MIGRATE] Test de connexion à la base de données..."
if ! psql "$DATABASE_URL" -c "SELECT 1;" > /dev/null 2>&1; then
echo "❌ [AUTO-MIGRATE] Impossible de se connecter à la base de données"
exit 1
@@ -42,4 +54,29 @@ else
echo "ℹ️ [AUTO-MIGRATE] Table announcements existe déjà - aucune action nécessaire"
fi
# Vérifier et ajouter les colonnes DLC stock épuisé
echo "🔄 [AUTO-MIGRATE] Vérification des colonnes DLC stock épuisé..."
if psql "$DATABASE_URL" -tAc "SELECT EXISTS (SELECT FROM information_schema.columns WHERE table_name='dlc_products' AND column_name='stock_epuise');" | grep -q "f"; then
echo "🔧 [AUTO-MIGRATE] Ajout des colonnes stock épuisé à dlc_products..."
psql "$DATABASE_URL" << 'EOF'
-- Migration sécurisée pour ajouter les champs stock épuisé
ALTER TABLE dlc_products
ADD COLUMN IF NOT EXISTS stock_epuise boolean DEFAULT false NOT NULL,
ADD COLUMN IF NOT EXISTS stock_epuise_by varchar(255),
ADD COLUMN IF NOT EXISTS stock_epuise_at timestamp;
-- Commentaires pour documenter les nouveaux champs
COMMENT ON COLUMN dlc_products.stock_epuise IS 'Indique si le produit est marqué comme stock épuisé (différent de périmé)';
COMMENT ON COLUMN dlc_products.stock_epuise_by IS 'ID de l''utilisateur qui a marqué le produit comme stock épuisé';
COMMENT ON COLUMN dlc_products.stock_epuise_at IS 'Date et heure de marquage du stock épuisé';
-- Index pour améliorer les performances sur les requêtes de stock épuisé
CREATE INDEX IF NOT EXISTS idx_dlc_products_stock_epuise ON dlc_products(stock_epuise);
EOF
echo "✅ [AUTO-MIGRATE] Colonnes stock épuisé ajoutées avec succès"
else
echo "ℹ️ [AUTO-MIGRATE] Colonnes stock épuisé existent déjà"
fi
echo "✅ [AUTO-MIGRATE] Migration terminée!"
+174
View File
@@ -0,0 +1,174 @@
#!/bin/bash
# Script de déploiement production - Fonctionnalité Stock Épuisé DLC
# Auteur: Système de gestion automatisé
# Date: 2025-08-18
set -e
echo "🚀 [DEPLOY] Déploiement production - Fonctionnalité Stock Épuisé DLC"
echo "=================================================="
# Fonction de logging avec timestamp
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}
# Vérification des prérequis
log "📋 Vérification des prérequis..."
if ! command -v docker &> /dev/null; then
log "❌ Docker n'est pas installé"
exit 1
fi
if ! command -v docker-compose &> /dev/null; then
log "❌ Docker Compose n'est pas installé"
exit 1
fi
if [ ! -f "docker-compose.yml" ]; then
log "❌ Fichier docker-compose.yml non trouvé"
exit 1
fi
log "✅ Prérequis validés"
# Sauvegarde préventive
log "💾 Création d'une sauvegarde préventive..."
timestamp=$(date +%Y%m%d_%H%M%S)
backup_file="backup_pre_dlc_stock_${timestamp}.sql"
# Tentative de sauvegarde (non bloquante si elle échoue)
if docker-compose exec -T logiflow-db pg_dump -U logiflow_admin logiflow_db > "${backup_file}" 2>/dev/null; then
log "✅ Sauvegarde créée: ${backup_file}"
else
log "⚠️ Sauvegarde échouée - continuons sans sauvegarde"
fi
# Mode maintenance
log "🛑 Activation du mode maintenance..."
echo "Redirection vers une page de maintenance pendant la mise à jour" > maintenance.html
# Arrêt de l'application
log "🔴 Arrêt de l'application..."
docker-compose down
# Rebuild avec les nouvelles fonctionnalités
log "🔨 Reconstruction de l'application avec les nouvelles fonctionnalités..."
docker-compose build --no-cache logiflow
# Démarrage de la base de données uniquement
log "🗄️ Démarrage de la base de données..."
docker-compose up -d logiflow-db
# Attendre que PostgreSQL soit prêt
log "⏳ Attente de PostgreSQL (30 secondes)..."
sleep 30
# Vérifier la connexion à la base
log "🔗 Test de connexion à la base de données..."
max_attempts=10
attempt=1
while [ $attempt -le $max_attempts ]; do
if docker-compose exec -T logiflow-db pg_isready -U logiflow_admin; then
log "✅ Base de données prête"
break
fi
if [ $attempt -eq $max_attempts ]; then
log "❌ Impossible de se connecter à la base de données après $max_attempts tentatives"
exit 1
fi
log "⏳ Tentative $attempt/$max_attempts - attente 5 secondes..."
sleep 5
((attempt++))
done
# Exécution manuelle de la migration (au cas où auto-migrate ne fonctionnerait pas)
log "🔄 Exécution de la migration DLC..."
if docker-compose exec -T logiflow-db psql -U logiflow_admin -d logiflow_db -f /migrations/002_add_dlc_stock_epuise.sql; then
log "✅ Migration DLC exécutée avec succès"
else
log "⚠️ Erreur lors de la migration - vérification manuelle nécessaire"
fi
# Démarrage complet de l'application
log "🚀 Démarrage complet de l'application..."
docker-compose up -d
# Attendre que l'application soit prête
log "⏳ Attente du démarrage de l'application (45 secondes)..."
sleep 45
# Tests de santé
log "🩺 Tests de santé de l'application..."
max_health_attempts=6
health_attempt=1
while [ $health_attempt -le $max_health_attempts ]; do
if curl -f http://localhost:3000/api/health &> /dev/null; then
log "✅ Application démarrée avec succès"
break
fi
if [ $health_attempt -eq $max_health_attempts ]; then
log "⚠️ Application non accessible après $max_health_attempts tentatives"
log "📊 Vérification des logs:"
docker-compose logs --tail=20 logiflow
break
fi
log "⏳ Test santé $health_attempt/$max_health_attempts - attente 10 secondes..."
sleep 10
((health_attempt++))
done
# Vérification de la migration
log "🔍 Vérification de la migration DLC..."
if docker-compose exec -T logiflow-db psql -U logiflow_admin -d logiflow_db -tAc "SELECT EXISTS (SELECT FROM information_schema.columns WHERE table_name='dlc_products' AND column_name='stock_epuise');" | grep -q "t"; then
log "✅ Colonnes stock épuisé présentes"
else
log "❌ Colonnes stock épuisé manquantes"
exit 1
fi
# Test des nouvelles routes API
log "🧪 Test des nouvelles routes API..."
echo "Testez manuellement les routes suivantes :"
echo "- PUT /api/dlc-products/:id/stock-epuise"
echo "- PUT /api/dlc-products/:id/restore-stock"
# Désactivation du mode maintenance
log "🟢 Désactivation du mode maintenance..."
rm -f maintenance.html
# Résumé final
log "🎉 DÉPLOIEMENT TERMINÉ AVEC SUCCÈS!"
echo ""
echo "=================================================="
echo "📊 RÉSUMÉ DU DÉPLOIEMENT"
echo "=================================================="
echo "✅ Application reconstruite et redémarrée"
echo "✅ Base de données migrée avec les nouveaux champs"
echo "✅ Tests de santé réussis"
echo ""
echo "🔍 VÉRIFICATIONS POST-DÉPLOIEMENT:"
echo "1. Interface DLC accessible"
echo "2. Boutons PackageX et RotateCcw présents"
echo "3. Fonctionnalité stock épuisé opérationnelle"
echo "4. Permissions admin/directeur/manager pour restauration"
echo ""
echo "📱 MONITORING:"
echo "docker-compose logs -f logiflow"
echo ""
echo "🐛 EN CAS DE PROBLÈME:"
echo "./scripts/verify-dlc-migration.sh"
echo "docker-compose restart"
echo ""
if [ -f "${backup_file}" ]; then
echo "💾 SAUVEGARDE DISPONIBLE: ${backup_file}"
fi
echo "=================================================="
+111
View File
@@ -0,0 +1,111 @@
#!/bin/bash
# Script de vérification de la migration DLC stock épuisé
# Auteur: Système de gestion automatisé
# Date: 2025-08-18
set -e
echo "🔍 [VERIFY] Vérification de la migration DLC stock épuisé..."
# Charger la configuration de la base de données
if [ -f ".env.production" ]; then
source .env.production
echo "✅ [VERIFY] Configuration production chargée"
else
echo "⚠️ [VERIFY] Fichier .env.production non trouvé, utilisation des variables d'environnement"
fi
# Construire l'URL de connexion si nécessaire
if [ -z "$DATABASE_URL" ]; then
if [ -n "$POSTGRES_USER" ] && [ -n "$POSTGRES_PASSWORD" ] && [ -n "$POSTGRES_DB" ]; then
export DATABASE_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@logiflow-db:5432/${POSTGRES_DB}"
echo "🔧 [VERIFY] URL de base de données construite à partir des variables"
else
echo "❌ [VERIFY] Impossible de construire l'URL de base de données"
exit 1
fi
fi
echo "🔗 [VERIFY] Test de connexion à la base de données..."
if ! psql "$DATABASE_URL" -c "SELECT 1" > /dev/null 2>&1; then
echo "❌ [VERIFY] Connexion à la base de données échouée"
exit 1
fi
echo "✅ [VERIFY] Connexion à la base de données réussie"
# Vérifier l'existence de la table dlc_products
echo "🔍 [VERIFY] Vérification de l'existence de la table dlc_products..."
if ! psql "$DATABASE_URL" -tAc "SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_schema='public' AND table_name='dlc_products');" | grep -q "t"; then
echo "❌ [VERIFY] Table dlc_products n'existe pas"
exit 1
fi
echo "✅ [VERIFY] Table dlc_products existe"
# Vérifier les colonnes stock épuisé
echo "🔍 [VERIFY] Vérification des colonnes stock épuisé..."
missing_columns=()
for column in "stock_epuise" "stock_epuise_by" "stock_epuise_at"; do
if psql "$DATABASE_URL" -tAc "SELECT EXISTS (SELECT FROM information_schema.columns WHERE table_name='dlc_products' AND column_name='$column');" | grep -q "f"; then
missing_columns+=("$column")
fi
done
if [ ${#missing_columns[@]} -gt 0 ]; then
echo "❌ [VERIFY] Colonnes manquantes: ${missing_columns[*]}"
echo "🔧 [VERIFY] La migration doit être exécutée"
exit 1
else
echo "✅ [VERIFY] Toutes les colonnes stock épuisé sont présentes"
fi
# Vérifier les types de données
echo "🔍 [VERIFY] Vérification des types de données..."
psql "$DATABASE_URL" -c "
SELECT
column_name,
data_type,
is_nullable,
column_default
FROM information_schema.columns
WHERE table_name = 'dlc_products'
AND column_name IN ('stock_epuise', 'stock_epuise_by', 'stock_epuise_at')
ORDER BY column_name;
"
# Vérifier l'index
echo "🔍 [VERIFY] Vérification de l'index stock épuisé..."
if psql "$DATABASE_URL" -tAc "SELECT EXISTS (SELECT FROM pg_indexes WHERE tablename='dlc_products' AND indexname='idx_dlc_products_stock_epuise');" | grep -q "t"; then
echo "✅ [VERIFY] Index idx_dlc_products_stock_epuise existe"
else
echo "⚠️ [VERIFY] Index idx_dlc_products_stock_epuise manquant"
fi
# Test d'une requête simple
echo "🔍 [VERIFY] Test d'une requête avec les nouveaux champs..."
if psql "$DATABASE_URL" -c "SELECT stock_epuise, stock_epuise_by, stock_epuise_at FROM dlc_products LIMIT 1;" > /dev/null 2>&1; then
echo "✅ [VERIFY] Requête avec les nouveaux champs réussie"
else
echo "❌ [VERIFY] Erreur lors de la requête avec les nouveaux champs"
exit 1
fi
# Compter les produits par statut de stock
echo "🔍 [VERIFY] Statistiques des produits par statut de stock..."
psql "$DATABASE_URL" -c "
SELECT
CASE
WHEN stock_epuise = true THEN 'stock_epuise'
WHEN stock_epuise = false THEN 'stock_disponible'
ELSE 'indetermine'
END as statut_stock,
COUNT(*) as nombre_produits
FROM dlc_products
GROUP BY stock_epuise
ORDER BY stock_epuise;
"
echo ""
echo "✅ [VERIFY] Vérification de la migration DLC terminée avec succès!"
echo "🚀 [VERIFY] L'application peut maintenant utiliser les fonctionnalités stock épuisé"