mirror of
https://github.com/R0m1k3/Regisflow.git
synced 2026-10-11 17:29:48 +02:00
Set up database initialization process using SQL scripts and Drizzle ORM
Adds init.sql and init-db.sh for database initialization, and enhances Docker setup. Replit-Commit-Author: Agent Replit-Commit-Session-Id: dec54137-d5a2-4406-8ad4-5f2f9fb110bf Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/0715008c-7244-40f4-befc-26c014852236/438ba2d5-c119-4a74-9474-438eed8b3141.jpg
This commit is contained in:
1 parent
9cc28ddc93
commit
77d77ab658
5 files changed
+357
-4
No files matched your search
@@ -47,6 +47,7 @@ COPY --from=builder --chown=regisflow:nodejs /build/shared ./shared
|
||||
COPY --from=builder --chown=regisflow:nodejs /build/server/prod-start.js ./server/
|
||||
COPY --from=builder --chown=regisflow:nodejs /build/drizzle.config.ts ./
|
||||
COPY --from=builder --chown=regisflow:nodejs /build/node_modules ./node_modules
|
||||
COPY --from=builder --chown=regisflow:nodejs /build/init.sql ./
|
||||
|
||||
# Copier les assets client au bon endroit pour serveStatic
|
||||
COPY --from=builder --chown=regisflow:nodejs /build/dist/public ./public
|
||||
|
||||
+16
-1
@@ -40,9 +40,13 @@ MAX_BACKUP_COUNT=20
|
||||
### 3. Déploiement immédiat
|
||||
|
||||
```bash
|
||||
# Démarrer l'application
|
||||
# Option A: Démarrer avec Docker Compose
|
||||
docker-compose up -d --build
|
||||
|
||||
# Option B: Utiliser le script automatisé
|
||||
chmod +x deploy-production.sh
|
||||
./deploy-production.sh
|
||||
|
||||
# Vérifier le fonctionnement
|
||||
curl http://localhost:5000/health
|
||||
|
||||
@@ -50,6 +54,17 @@ curl http://localhost:5000/health
|
||||
docker-compose logs -f regisflow
|
||||
```
|
||||
|
||||
### 3.1 Initialisation manuelle de la base (si nécessaire)
|
||||
|
||||
```bash
|
||||
# Si les tables ne se créent pas automatiquement
|
||||
chmod +x init-db.sh
|
||||
./init-db.sh
|
||||
|
||||
# Ou avec une DATABASE_URL spécifique
|
||||
./init-db.sh "postgresql://regisflow:password@localhost:5433/regisflow"
|
||||
```
|
||||
|
||||
### 4. Accès initial
|
||||
|
||||
- **URL** : http://votre-serveur:5000
|
||||
|
||||
@@ -27,11 +27,26 @@ mkdir -p /app/backups /app/logs
|
||||
|
||||
# Créer les tables de la base de données
|
||||
echo "📦 Création des tables de la base de données..."
|
||||
|
||||
# Méthode 1: Utiliser Drizzle Kit (recommandé)
|
||||
if npx drizzle-kit push --config=./drizzle.config.ts; then
|
||||
echo "✅ Tables créées avec succès"
|
||||
echo "✅ Tables créées avec succès via Drizzle"
|
||||
else
|
||||
echo "❌ Erreur lors de la création des tables"
|
||||
exit 1
|
||||
echo "⚠️ Drizzle Kit failed, essai avec init.sql..."
|
||||
|
||||
# Méthode 2: Fallback avec init.sql si Drizzle échoue
|
||||
if [ -f "/app/init.sql" ]; then
|
||||
export PGPASSWORD="$POSTGRES_PASSWORD"
|
||||
if psql -h regisflow-db -p 5432 -U regisflow -d regisflow -f /app/init.sql; then
|
||||
echo "✅ Tables créées avec succès via init.sql"
|
||||
else
|
||||
echo "❌ Erreur lors de la création des tables"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "❌ Aucune méthode d'initialisation disponible"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "✅ Base de données configurée"
|
||||
|
||||
Executable
+151
@@ -0,0 +1,151 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script d'initialisation de la base de données RegisFlow
|
||||
# Usage: ./init-db.sh [DATABASE_URL]
|
||||
|
||||
set -e
|
||||
|
||||
# Configuration par défaut
|
||||
DEFAULT_DB_HOST="localhost"
|
||||
DEFAULT_DB_PORT="5433"
|
||||
DEFAULT_DB_NAME="regisflow"
|
||||
DEFAULT_DB_USER="regisflow"
|
||||
DEFAULT_DB_PASSWORD="RegisFlow2024!PostgreSQL"
|
||||
|
||||
# Couleurs pour les messages
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
log_info() {
|
||||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}✅ $1${NC}"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}❌ $1${NC}"
|
||||
}
|
||||
|
||||
# Fonction pour extraire les informations de DATABASE_URL
|
||||
parse_database_url() {
|
||||
local url="$1"
|
||||
|
||||
# Extraire les composants de l'URL PostgreSQL
|
||||
if [[ $url =~ postgresql://([^:]+):([^@]+)@([^:]+):([^/]+)/(.+) ]]; then
|
||||
DB_USER="${BASH_REMATCH[1]}"
|
||||
DB_PASSWORD="${BASH_REMATCH[2]}"
|
||||
DB_HOST="${BASH_REMATCH[3]}"
|
||||
DB_PORT="${BASH_REMATCH[4]}"
|
||||
DB_NAME="${BASH_REMATCH[5]}"
|
||||
else
|
||||
log_error "Format DATABASE_URL invalide. Utilisez: postgresql://user:password@host:port/database"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Déterminer la configuration de la base de données
|
||||
if [ -n "$1" ]; then
|
||||
log_info "Utilisation de DATABASE_URL fournie: $1"
|
||||
parse_database_url "$1"
|
||||
elif [ -n "$DATABASE_URL" ]; then
|
||||
log_info "Utilisation de DATABASE_URL depuis l'environnement"
|
||||
parse_database_url "$DATABASE_URL"
|
||||
else
|
||||
log_info "Utilisation de la configuration par défaut"
|
||||
DB_HOST="$DEFAULT_DB_HOST"
|
||||
DB_PORT="$DEFAULT_DB_PORT"
|
||||
DB_NAME="$DEFAULT_DB_NAME"
|
||||
DB_USER="$DEFAULT_DB_USER"
|
||||
DB_PASSWORD="$DEFAULT_DB_PASSWORD"
|
||||
fi
|
||||
|
||||
log_info "Configuration de la base de données:"
|
||||
log_info " Host: $DB_HOST"
|
||||
log_info " Port: $DB_PORT"
|
||||
log_info " Database: $DB_NAME"
|
||||
log_info " User: $DB_USER"
|
||||
|
||||
# Vérifier que psql est installé
|
||||
if ! command -v psql &> /dev/null; then
|
||||
log_error "psql n'est pas installé. Installez PostgreSQL client."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Vérifier la connexion à PostgreSQL
|
||||
log_info "Test de connexion à PostgreSQL..."
|
||||
export PGPASSWORD="$DB_PASSWORD"
|
||||
|
||||
if ! psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "\q" 2>/dev/null; then
|
||||
log_error "Impossible de se connecter à PostgreSQL"
|
||||
log_info "Vérifiez que PostgreSQL est démarré et accessible"
|
||||
log_info "Commande de test: psql -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_success "Connexion PostgreSQL réussie"
|
||||
|
||||
# Exécuter le script d'initialisation
|
||||
log_info "Exécution du script d'initialisation..."
|
||||
|
||||
if [ -f "init.sql" ]; then
|
||||
if psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -f init.sql; then
|
||||
log_success "Script d'initialisation exécuté avec succès"
|
||||
else
|
||||
log_error "Erreur lors de l'exécution du script d'initialisation"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
log_error "Fichier init.sql non trouvé"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Vérifier que les tables ont été créées
|
||||
log_info "Vérification des tables créées..."
|
||||
TABLES=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT tablename FROM pg_tables WHERE schemaname='public';" | tr -d ' ' | grep -v '^$')
|
||||
|
||||
if echo "$TABLES" | grep -q "users\|stores\|sales\|sessions"; then
|
||||
log_success "Tables principales créées:"
|
||||
echo "$TABLES" | while read -r table; do
|
||||
if [ -n "$table" ]; then
|
||||
log_info " - $table"
|
||||
fi
|
||||
done
|
||||
else
|
||||
log_error "Les tables principales n'ont pas été créées correctement"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Vérifier l'utilisateur admin
|
||||
log_info "Vérification de l'utilisateur administrateur..."
|
||||
ADMIN_COUNT=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT COUNT(*) FROM users WHERE username='admin';" | tr -d ' ')
|
||||
|
||||
if [ "$ADMIN_COUNT" = "1" ]; then
|
||||
log_success "Utilisateur admin créé avec succès"
|
||||
else
|
||||
log_warning "Problème avec la création de l'utilisateur admin"
|
||||
fi
|
||||
|
||||
# Afficher le résumé
|
||||
echo ""
|
||||
log_success "🎉 Initialisation de la base de données terminée!"
|
||||
echo "======================================================"
|
||||
log_info "Base de données: $DB_NAME sur $DB_HOST:$DB_PORT"
|
||||
log_info "Utilisateur administrateur:"
|
||||
log_info " - Username: admin"
|
||||
log_info " - Password: admin123"
|
||||
log_warning "IMPORTANT: Changez le mot de passe admin après la première connexion!"
|
||||
echo ""
|
||||
|
||||
# Nettoyer les variables d'environnement
|
||||
unset PGPASSWORD
|
||||
|
||||
log_success "Prêt pour le déploiement!"
|
||||
@@ -0,0 +1,171 @@
|
||||
-- Script d'initialisation PostgreSQL pour RegisFlow
|
||||
-- Ce script crée toutes les tables nécessaires et les données de base
|
||||
|
||||
-- Configuration initiale
|
||||
SET client_encoding = 'UTF8';
|
||||
SET standard_conforming_strings = on;
|
||||
SET check_function_bodies = false;
|
||||
SET xmloption = content;
|
||||
SET client_min_messages = warning;
|
||||
SET row_security = off;
|
||||
|
||||
-- Création de la base de données (si elle n'existe pas déjà)
|
||||
-- CREATE DATABASE regisflow WITH ENCODING 'UTF8' LC_COLLATE='fr_FR.UTF-8' LC_CTYPE='fr_FR.UTF-8';
|
||||
|
||||
-- Extension pour les UUID si nécessaire
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
|
||||
-- Table des sessions (pour l'authentification)
|
||||
CREATE TABLE IF NOT EXISTS sessions (
|
||||
sid VARCHAR PRIMARY KEY,
|
||||
sess JSONB NOT NULL,
|
||||
expire TIMESTAMP NOT NULL
|
||||
);
|
||||
|
||||
-- Index sur la date d'expiration des sessions
|
||||
CREATE INDEX IF NOT EXISTS "IDX_session_expire" ON sessions (expire);
|
||||
|
||||
-- Table des magasins
|
||||
CREATE TABLE IF NOT EXISTS stores (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
address TEXT,
|
||||
phone VARCHAR(20),
|
||||
email VARCHAR(255),
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Table des utilisateurs avec authentification
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
username VARCHAR(50) UNIQUE NOT NULL,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(255) UNIQUE,
|
||||
first_name VARCHAR(100),
|
||||
last_name VARCHAR(100),
|
||||
role VARCHAR(20) NOT NULL DEFAULT 'employee',
|
||||
store_id INTEGER REFERENCES stores(id),
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Table des ventes
|
||||
CREATE TABLE IF NOT EXISTS sales (
|
||||
id SERIAL PRIMARY KEY,
|
||||
store_id INTEGER REFERENCES stores(id) NOT NULL,
|
||||
user_id INTEGER REFERENCES users(id) NOT NULL,
|
||||
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
-- Informations vendeur
|
||||
vendeur VARCHAR(255) NOT NULL,
|
||||
|
||||
-- Informations produit
|
||||
type_article VARCHAR(255) NOT NULL,
|
||||
categorie VARCHAR(2) NOT NULL,
|
||||
quantite INTEGER NOT NULL,
|
||||
gencode VARCHAR(13) NOT NULL,
|
||||
|
||||
-- Informations client
|
||||
nom VARCHAR(255) NOT NULL,
|
||||
prenom VARCHAR(255) NOT NULL,
|
||||
date_naissance VARCHAR(10) NOT NULL,
|
||||
lieu_naissance VARCHAR(255),
|
||||
mode_paiement VARCHAR(50) NOT NULL DEFAULT 'Espèce',
|
||||
|
||||
-- Informations pièce d'identité
|
||||
type_identite VARCHAR(100) NOT NULL,
|
||||
numero_identite VARCHAR(100) NOT NULL,
|
||||
autorite_delivrance VARCHAR(255),
|
||||
date_delivrance VARCHAR(10) NOT NULL,
|
||||
|
||||
-- Photos (Base64)
|
||||
photo_recto TEXT,
|
||||
photo_verso TEXT
|
||||
);
|
||||
|
||||
-- Index pour optimiser les recherches
|
||||
CREATE INDEX IF NOT EXISTS idx_sales_store_id ON sales(store_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_sales_user_id ON sales(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_sales_timestamp ON sales(timestamp);
|
||||
CREATE INDEX IF NOT EXISTS idx_sales_nom ON sales(nom);
|
||||
CREATE INDEX IF NOT EXISTS idx_sales_prenom ON sales(prenom);
|
||||
CREATE INDEX IF NOT EXISTS idx_sales_gencode ON sales(gencode);
|
||||
|
||||
-- Relations et contraintes
|
||||
ALTER TABLE users ADD CONSTRAINT chk_user_role
|
||||
CHECK (role IN ('admin', 'manager', 'employee'));
|
||||
|
||||
ALTER TABLE sales ADD CONSTRAINT chk_sales_categorie
|
||||
CHECK (categorie IN ('F2', 'F3'));
|
||||
|
||||
-- Trigger pour mettre à jour updated_at automatiquement
|
||||
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = CURRENT_TIMESTAMP;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ language 'plpgsql';
|
||||
|
||||
CREATE TRIGGER update_stores_updated_at
|
||||
BEFORE UPDATE ON stores
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
CREATE TRIGGER update_users_updated_at
|
||||
BEFORE UPDATE ON users
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- Insertion des données de base
|
||||
|
||||
-- Magasin par défaut
|
||||
INSERT INTO stores (id, name, address, phone, email)
|
||||
VALUES (1, 'Magasin Principal', '', '', '')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
-- Utilisateur administrateur par défaut
|
||||
-- Mot de passe: admin123 (hashé avec bcrypt)
|
||||
INSERT INTO users (id, username, password, email, first_name, last_name, role, store_id)
|
||||
VALUES (1, 'admin', '$2a$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'admin@regisflow.com', 'Admin', 'RegisFlow', 'admin', 1)
|
||||
ON CONFLICT (username) DO NOTHING;
|
||||
|
||||
-- Séquences pour l'auto-increment
|
||||
SELECT setval('stores_id_seq', (SELECT COALESCE(MAX(id), 1) FROM stores));
|
||||
SELECT setval('users_id_seq', (SELECT COALESCE(MAX(id), 1) FROM users));
|
||||
SELECT setval('sales_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sales));
|
||||
|
||||
-- Permissions et sécurité
|
||||
GRANT CONNECT ON DATABASE regisflow TO regisflow;
|
||||
GRANT USAGE ON SCHEMA public TO regisflow;
|
||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO regisflow;
|
||||
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO regisflow;
|
||||
|
||||
-- Vue pour les statistiques (optionnelle)
|
||||
CREATE OR REPLACE VIEW sales_stats AS
|
||||
SELECT
|
||||
s.store_id,
|
||||
st.name as store_name,
|
||||
COUNT(*) as total_sales,
|
||||
DATE_TRUNC('month', s.timestamp) as month_year,
|
||||
s.categorie,
|
||||
COUNT(*) as category_count
|
||||
FROM sales s
|
||||
LEFT JOIN stores st ON s.store_id = st.id
|
||||
GROUP BY s.store_id, st.name, DATE_TRUNC('month', s.timestamp), s.categorie
|
||||
ORDER BY month_year DESC;
|
||||
|
||||
-- Commentaires pour la documentation
|
||||
COMMENT ON TABLE sessions IS 'Table des sessions utilisateur pour l''authentification';
|
||||
COMMENT ON TABLE stores IS 'Table des magasins/points de vente';
|
||||
COMMENT ON TABLE users IS 'Table des utilisateurs avec rôles et authentification';
|
||||
COMMENT ON TABLE sales IS 'Table principale des ventes de feux d''artifice';
|
||||
COMMENT ON COLUMN sales.categorie IS 'Catégorie F2 ou F3 selon la réglementation française';
|
||||
COMMENT ON COLUMN sales.photo_recto IS 'Photo recto de la pièce d''identité (Base64)';
|
||||
COMMENT ON COLUMN sales.photo_verso IS 'Photo verso de la pièce d''identité (Base64)';
|
||||
|
||||
-- Affichage des informations de fin
|
||||
\echo 'Base de données RegisFlow initialisée avec succès!'
|
||||
\echo 'Utilisateur admin créé: username=admin, password=admin123'
|
||||
\echo 'Magasin par défaut créé: Magasin Principal'
|
||||
Reference in new issue
Block a user