/** * Script de seed pour insérer des données de test * Usage: node database/seed.js */ import bcrypt from 'bcrypt'; import { pool } from '../db.js'; import { randomUUID } from 'crypto'; const SALT_ROUNDS = 10; async function seedDatabase() { try { console.log('🌱 Démarrage du seed de la base de données...\n'); // ============================================ // 1. SEED USERS // ============================================ console.log('👥 Création des utilisateurs...'); // Hash des mots de passe const adminPassword = await bcrypt.hash('Admin123!', SALT_ROUNDS); const employeePassword = await bcrypt.hash('Employee123!', SALT_ROUNDS); const clientPassword = await bcrypt.hash('Client123!', SALT_ROUNDS); // Admin const adminResult = await pool.query( `INSERT INTO users (email, password, first_name, last_name, phone, role, is_verified) VALUES ($1, $2, $3, $4, $5, 'ADMIN', TRUE) ON CONFLICT (email) DO UPDATE SET role = 'ADMIN' RETURNING id, email, role`, ['admin@thetiptop.com', adminPassword, 'Admin', 'Principal', '+33123456789'] ); console.log('✅ Admin créé:', adminResult.rows[0].email); // Employé 1 const employee1Result = await pool.query( `INSERT INTO users (email, password, first_name, last_name, phone, role, is_verified) VALUES ($1, $2, $3, $4, $5, 'EMPLOYEE', TRUE) ON CONFLICT (email) DO UPDATE SET role = 'EMPLOYEE' RETURNING id, email, role`, ['employee1@thetiptop.com', employeePassword, 'Marie', 'Dupont', '+33198765432'] ); console.log('✅ Employé 1 créé:', employee1Result.rows[0].email); // Employé 2 const employee2Result = await pool.query( `INSERT INTO users (email, password, first_name, last_name, phone, role, is_verified) VALUES ($1, $2, $3, $4, $5, 'EMPLOYEE', TRUE) ON CONFLICT (email) DO UPDATE SET role = 'EMPLOYEE' RETURNING id, email, role`, ['employee2@thetiptop.com', employeePassword, 'Pierre', 'Martin', '+33187654321'] ); console.log('✅ Employé 2 créé:', employee2Result.rows[0].email); // Clients const clients = [ { email: 'client1@example.com', firstName: 'Jean', lastName: 'Dupuis', phone: '+33612345678', }, { email: 'client2@example.com', firstName: 'Sophie', lastName: 'Bernard', phone: '+33623456789', }, { email: 'client3@example.com', firstName: 'Luc', lastName: 'Lefevre', phone: '+33634567890', }, { email: 'client4@example.com', firstName: 'Emma', lastName: 'Petit', phone: '+33645678901', }, { email: 'client5@example.com', firstName: 'Thomas', lastName: 'Robert', phone: '+33656789012', }, ]; const clientIds = []; for (const client of clients) { const result = await pool.query( `INSERT INTO users (email, password, first_name, last_name, phone, role, is_verified) VALUES ($1, $2, $3, $4, $5, 'CLIENT', TRUE) ON CONFLICT (email) DO UPDATE SET role = 'CLIENT' RETURNING id`, [ client.email, clientPassword, client.firstName, client.lastName, client.phone, ] ); clientIds.push(result.rows[0].id); console.log(`✅ Client créé: ${client.email}`); } console.log(`\n✅ ${clients.length + 3} utilisateurs créés avec succès\n`); // ============================================ // 2. SEED TICKETS // ============================================ console.log('🎟️ Création des tickets de test...'); // Récupérer les IDs des prix const prizesResult = await pool.query( 'SELECT id, type FROM prizes ORDER BY type' ); const prizes = prizesResult.rows; if (prizes.length === 0) { console.log('⚠️ Aucun prix trouvé. Exécutez d\'abord le schema.sql'); return; } // Créer des tickets avec différents statuts pour chaque client const ticketStatuses = ['PENDING', 'CLAIMED', 'REJECTED']; let ticketCount = 0; for (let i = 0; i < clientIds.length; i++) { const clientId = clientIds[i]; // Chaque client obtient 3-5 tickets const numTickets = Math.floor(Math.random() * 3) + 3; for (let j = 0; j < numTickets; j++) { // Sélectionner un prix aléatoire const randomPrize = prizes[Math.floor(Math.random() * prizes.length)]; // Sélectionner un statut (80% PENDING, 10% CLAIMED, 10% REJECTED) const rand = Math.random(); let status; if (rand < 0.8) { status = 'PENDING'; } else if (rand < 0.9) { status = 'CLAIMED'; } else { status = 'REJECTED'; } // Générer un code unique const ticketCode = `TT-${Date.now()}-${randomUUID().substring(0, 8).toUpperCase()}`; // Créer le ticket const insertQuery = ` INSERT INTO tickets (code, user_id, prize_id, status, played_at, claimed_at, validated_by, validated_at, rejection_reason) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) `; const playedAt = new Date(Date.now() - Math.random() * 30 * 24 * 60 * 60 * 1000); // Dans les 30 derniers jours let claimedAt = null; let validatedBy = null; let validatedAt = null; let rejectionReason = null; if (status === 'CLAIMED') { claimedAt = new Date(playedAt.getTime() + Math.random() * 7 * 24 * 60 * 60 * 1000); // 0-7 jours après validatedBy = employee1Result.rows[0].id; validatedAt = claimedAt; } else if (status === 'REJECTED') { claimedAt = new Date(playedAt.getTime() + Math.random() * 7 * 24 * 60 * 60 * 1000); validatedBy = employee1Result.rows[0].id; validatedAt = claimedAt; rejectionReason = 'Ticket non conforme ou expiré'; } await pool.query(insertQuery, [ ticketCode, clientId, randomPrize.id, status, playedAt, claimedAt, validatedBy, validatedAt, rejectionReason, ]); ticketCount++; } } console.log(`✅ ${ticketCount} tickets créés avec succès\n`); // ============================================ // 3. AFFICHER LES STATISTIQUES // ============================================ console.log('📊 Statistiques de la base de données:\n'); const usersStats = await pool.query(` SELECT COUNT(*) as total, COUNT(CASE WHEN role = 'ADMIN' THEN 1 END) as admins, COUNT(CASE WHEN role = 'EMPLOYEE' THEN 1 END) as employees, COUNT(CASE WHEN role = 'CLIENT' THEN 1 END) as clients FROM users `); const ticketsStats = await pool.query(` SELECT COUNT(*) as total, COUNT(CASE WHEN status = 'PENDING' THEN 1 END) as pending, COUNT(CASE WHEN status = 'CLAIMED' THEN 1 END) as claimed, COUNT(CASE WHEN status = 'REJECTED' THEN 1 END) as rejected FROM tickets `); console.log('👥 Utilisateurs:'); console.log(` Total: ${usersStats.rows[0].total}`); console.log(` Admins: ${usersStats.rows[0].admins}`); console.log(` Employés: ${usersStats.rows[0].employees}`); console.log(` Clients: ${usersStats.rows[0].clients}`); console.log('\n🎟️ Tickets:'); console.log(` Total: ${ticketsStats.rows[0].total}`); console.log(` En attente: ${ticketsStats.rows[0].pending}`); console.log(` Réclamés: ${ticketsStats.rows[0].claimed}`); console.log(` Rejetés: ${ticketsStats.rows[0].rejected}`); console.log('\n✅ Seed terminé avec succès!'); console.log('\n🔐 Comptes de test créés:'); console.log(' Admin: admin@thetiptop.com / Admin123!'); console.log(' Employé 1: employee1@thetiptop.com / Employee123!'); console.log(' Employé 2: employee2@thetiptop.com / Employee123!'); console.log(' Clients: client1@example.com à client5@example.com / Client123!'); } catch (error) { console.error('❌ Erreur lors du seed:', error); throw error; } finally { // Fermer la connexion await pool.end(); } } // Exécuter le seed seedDatabase();