mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-12 01:37:40 +02:00
Add stock depletion tracking for products
Introduce new columns to the products table to track stock depletion status, including who depleted it and when. This enhances product management by distinguishing between expired and out-of-stock items. This change includes database migrations, Docker updates, and deployment scripts to ensure a smooth rollout. Replit-Commit-Author: Agent Replit-Commit-Session-Id: f9197b9b-a5b3-4469-a27d-930a9e9ee736 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/f9197b9b-a5b3-4469-a27d-930a9e9ee736/JKfj3tT
This commit is contained in:
1 parent
20f7c977ff
commit
785105814a
5 files changed
+362
No files matched your search
@@ -41,6 +41,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
|
||||
|
||||
@@ -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
|
||||
$$;
|
||||
@@ -42,4 +42,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!"
|
||||
Executable
+174
@@ -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 "=================================================="
|
||||
Executable
+111
@@ -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é"
|
||||
Reference in new issue
Block a user