Compare commits
No commits in common. "c7019550c12372dc3d466c7882c70ae4485f84ac" and "a419a9f42a6e5fd033d55ce595950b2b528b24c6" have entirely different histories.
c7019550c1
...
a419a9f42a
42
package-lock.json
generated
42
package-lock.json
generated
|
|
@ -31,7 +31,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.39.0",
|
"@eslint/js": "^9.39.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^10.1.0",
|
||||||
"eslint": "^9.39.0",
|
"eslint": "^9.39.0",
|
||||||
"jest": "^30.2.0",
|
"jest": "^30.2.0",
|
||||||
"nodemon": "^3.1.10",
|
"nodemon": "^3.1.10",
|
||||||
|
|
@ -568,6 +568,13 @@
|
||||||
"tslib": "^2.4.0"
|
"tslib": "^2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@epic-web/invariant": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@eslint-community/eslint-utils": {
|
"node_modules/@eslint-community/eslint-utils": {
|
||||||
"version": "4.9.0",
|
"version": "4.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
|
||||||
|
|
@ -2629,22 +2636,21 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/cross-env": {
|
"node_modules/cross-env": {
|
||||||
"version": "7.0.3",
|
"version": "10.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz",
|
||||||
"integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
|
"integrity": "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cross-spawn": "^7.0.1"
|
"@epic-web/invariant": "^1.0.0",
|
||||||
|
"cross-spawn": "^7.0.6"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"cross-env": "src/bin/cross-env.js",
|
"cross-env": "dist/bin/cross-env.js",
|
||||||
"cross-env-shell": "src/bin/cross-env-shell.js"
|
"cross-env-shell": "dist/bin/cross-env-shell.js"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.14",
|
"node": ">=20"
|
||||||
"npm": ">=6",
|
|
||||||
"yarn": ">=1"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/cross-spawn": {
|
"node_modules/cross-spawn": {
|
||||||
|
|
@ -4910,12 +4916,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/jsonwebtoken/node_modules/jws": {
|
"node_modules/jsonwebtoken/node_modules/jws": {
|
||||||
"version": "3.2.3",
|
"version": "3.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
|
||||||
"integrity": "sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==",
|
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jwa": "^1.4.2",
|
"jwa": "^1.4.1",
|
||||||
"safe-buffer": "^5.0.1"
|
"safe-buffer": "^5.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -4943,12 +4949,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/jws": {
|
"node_modules/jws": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
|
||||||
"integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
|
"integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jwa": "^2.0.1",
|
"jwa": "^2.0.0",
|
||||||
"safe-buffer": "^5.0.1"
|
"safe-buffer": "^5.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.39.0",
|
"@eslint/js": "^9.39.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^10.1.0",
|
||||||
"eslint": "^9.39.0",
|
"eslint": "^9.39.0",
|
||||||
"jest": "^30.2.0",
|
"jest": "^30.2.0",
|
||||||
"nodemon": "^3.1.10",
|
"nodemon": "^3.1.10",
|
||||||
|
|
|
||||||
|
|
@ -1,369 +0,0 @@
|
||||||
/**
|
|
||||||
* Script d'auto-initialisation de la base de données
|
|
||||||
* Appelé automatiquement au démarrage du backend
|
|
||||||
*
|
|
||||||
* Ce script vérifie si les tables existent et les crée si nécessaire
|
|
||||||
* Il crée également les comptes admin/employé et génère les 500,000 tickets
|
|
||||||
*/
|
|
||||||
import { readFileSync } from 'fs';
|
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
import { dirname, join } from 'path';
|
|
||||||
import bcrypt from 'bcrypt';
|
|
||||||
import { pool } from '../db.js';
|
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
|
||||||
const __dirname = dirname(__filename);
|
|
||||||
|
|
||||||
const SALT_ROUNDS = 10;
|
|
||||||
const TOTAL_TICKETS = 500000;
|
|
||||||
const BATCH_SIZE = 5000;
|
|
||||||
|
|
||||||
const PRIZE_DISTRIBUTION = {
|
|
||||||
'INFUSEUR': { percentage: 0.60, name: 'Infuseur à thé' },
|
|
||||||
'THE_GRATUIT': { percentage: 0.20, name: 'Thé détox/infusion 100g' },
|
|
||||||
'THE_SIGNATURE': { percentage: 0.10, name: 'Thé signature 100g' },
|
|
||||||
'COFFRET_DECOUVERTE': { percentage: 0.06, name: 'Coffret découverte 39€' },
|
|
||||||
'COFFRET_PRESTIGE': { percentage: 0.04, name: 'Coffret prestige 69€' }
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Vérifie si les tables existent dans la base de données
|
|
||||||
*/
|
|
||||||
async function tablesExist() {
|
|
||||||
try {
|
|
||||||
const result = await pool.query(`
|
|
||||||
SELECT COUNT(*) as count
|
|
||||||
FROM information_schema.tables
|
|
||||||
WHERE table_schema = 'public'
|
|
||||||
AND table_name IN ('users', 'prizes', 'tickets', 'game_settings')
|
|
||||||
`);
|
|
||||||
return parseInt(result.rows[0].count) === 4;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('❌ Erreur lors de la vérification des tables:', error.message);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Vérifie si les tickets ont été générés
|
|
||||||
*/
|
|
||||||
async function ticketsExist() {
|
|
||||||
try {
|
|
||||||
const result = await pool.query('SELECT COUNT(*) as count FROM tickets');
|
|
||||||
return parseInt(result.rows[0].count) >= TOTAL_TICKETS;
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Vérifie si les utilisateurs admin/employé existent
|
|
||||||
*/
|
|
||||||
async function usersExist() {
|
|
||||||
try {
|
|
||||||
const result = await pool.query(`
|
|
||||||
SELECT COUNT(*) as count FROM users
|
|
||||||
WHERE email IN ('admin@thetiptop.com', 'employee1@thetiptop.com')
|
|
||||||
`);
|
|
||||||
return parseInt(result.rows[0].count) >= 2;
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crée les tables à partir du schema.sql
|
|
||||||
*/
|
|
||||||
async function createTables() {
|
|
||||||
console.log('📦 Création des tables...');
|
|
||||||
|
|
||||||
const schemaPath = join(__dirname, '..', 'database', 'schema.sql');
|
|
||||||
const schema = readFileSync(schemaPath, 'utf-8');
|
|
||||||
|
|
||||||
await pool.query(schema);
|
|
||||||
console.log('✅ Tables créées avec succès');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crée les utilisateurs par défaut (admin, employés)
|
|
||||||
*/
|
|
||||||
async function createDefaultUsers() {
|
|
||||||
console.log('👥 Création des utilisateurs par défaut...');
|
|
||||||
|
|
||||||
const adminPassword = await bcrypt.hash('Admin123!', SALT_ROUNDS);
|
|
||||||
const employeePassword = await bcrypt.hash('Employee123!', SALT_ROUNDS);
|
|
||||||
|
|
||||||
// Admin
|
|
||||||
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
|
|
||||||
password = EXCLUDED.password,
|
|
||||||
role = 'ADMIN',
|
|
||||||
is_verified = TRUE`,
|
|
||||||
['admin@thetiptop.com', adminPassword, 'Admin', 'Principal', '+33123456789']
|
|
||||||
);
|
|
||||||
console.log(' ✅ Admin créé: admin@thetiptop.com');
|
|
||||||
|
|
||||||
// Employé 1
|
|
||||||
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
|
|
||||||
password = EXCLUDED.password,
|
|
||||||
role = 'EMPLOYEE',
|
|
||||||
is_verified = TRUE`,
|
|
||||||
['employee1@thetiptop.com', employeePassword, 'Marie', 'Dupont', '+33198765432']
|
|
||||||
);
|
|
||||||
console.log(' ✅ Employé créé: employee1@thetiptop.com');
|
|
||||||
|
|
||||||
// Employé 2
|
|
||||||
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
|
|
||||||
password = EXCLUDED.password,
|
|
||||||
role = 'EMPLOYEE',
|
|
||||||
is_verified = TRUE`,
|
|
||||||
['employee2@thetiptop.com', employeePassword, 'Pierre', 'Martin', '+33187654321']
|
|
||||||
);
|
|
||||||
console.log(' ✅ Employé créé: employee2@thetiptop.com');
|
|
||||||
|
|
||||||
console.log('✅ Utilisateurs créés avec succès');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Génère un code de ticket unique
|
|
||||||
*/
|
|
||||||
function generateCode() {
|
|
||||||
const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
||||||
let code = 'TT';
|
|
||||||
for (let i = 0; i < 8; i++) {
|
|
||||||
code += chars[Math.floor(Math.random() * chars.length)];
|
|
||||||
}
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Génère les 500,000 tickets
|
|
||||||
*/
|
|
||||||
async function generateTickets() {
|
|
||||||
console.log('🎫 Génération des 500,000 tickets...');
|
|
||||||
|
|
||||||
const prizesResult = await pool.query('SELECT id, name, type FROM prizes');
|
|
||||||
const prizes = {};
|
|
||||||
prizesResult.rows.forEach(p => prizes[p.type] = p);
|
|
||||||
|
|
||||||
// Calculer la distribution
|
|
||||||
const distribution = {};
|
|
||||||
let total = 0;
|
|
||||||
|
|
||||||
for (const [type, config] of Object.entries(PRIZE_DISTRIBUTION)) {
|
|
||||||
const count = Math.floor(TOTAL_TICKETS * config.percentage);
|
|
||||||
distribution[type] = count;
|
|
||||||
total += count;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ajuster si nécessaire
|
|
||||||
if (total < TOTAL_TICKETS) {
|
|
||||||
distribution['INFUSEUR'] += (TOTAL_TICKETS - total);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Afficher la distribution
|
|
||||||
console.log(' 📊 Distribution:');
|
|
||||||
for (const [type, count] of Object.entries(distribution)) {
|
|
||||||
console.log(` - ${type}: ${count.toLocaleString('fr-FR')} tickets`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Générer les tickets
|
|
||||||
let generated = 0;
|
|
||||||
const start = Date.now();
|
|
||||||
|
|
||||||
for (const [type, count] of Object.entries(distribution)) {
|
|
||||||
const prize = prizes[type];
|
|
||||||
if (!prize) {
|
|
||||||
console.log(` ⚠️ Lot "${type}" introuvable, ignoré`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < count; i += BATCH_SIZE) {
|
|
||||||
const batch = Math.min(BATCH_SIZE, count - i);
|
|
||||||
const values = [];
|
|
||||||
|
|
||||||
for (let j = 0; j < batch; j++) {
|
|
||||||
const code = generateCode();
|
|
||||||
values.push(`('${code}', '${prize.id}', NULL)`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const query = `INSERT INTO tickets (code, prize_id, status) VALUES ${values.join(', ')}`;
|
|
||||||
await pool.query(query);
|
|
||||||
generated += batch;
|
|
||||||
|
|
||||||
// Afficher la progression tous les 50,000 tickets
|
|
||||||
if (generated % 50000 === 0) {
|
|
||||||
console.log(` 📈 Progression: ${generated.toLocaleString('fr-FR')} / ${TOTAL_TICKETS.toLocaleString('fr-FR')}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const duration = ((Date.now() - start) / 1000).toFixed(2);
|
|
||||||
console.log(`✅ ${generated.toLocaleString('fr-FR')} tickets générés en ${duration}s`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applique les migrations (newsletter, email campaigns, etc.)
|
|
||||||
*/
|
|
||||||
async function applyMigrations() {
|
|
||||||
console.log('🔄 Application des migrations...');
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Add is_active column to users if not exists
|
|
||||||
await pool.query(`
|
|
||||||
ALTER TABLE users ADD COLUMN IF NOT EXISTS is_active BOOLEAN DEFAULT TRUE
|
|
||||||
`);
|
|
||||||
console.log(' ✅ Colonne is_active ajoutée à users');
|
|
||||||
|
|
||||||
// Newsletter table
|
|
||||||
await pool.query(`
|
|
||||||
CREATE TABLE IF NOT EXISTS newsletters (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
email VARCHAR(255) UNIQUE NOT NULL,
|
|
||||||
is_subscribed BOOLEAN DEFAULT TRUE,
|
|
||||||
subscribed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
unsubscribed_at TIMESTAMP,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
||||||
)
|
|
||||||
`);
|
|
||||||
console.log(' ✅ Table newsletters créée');
|
|
||||||
|
|
||||||
// Email templates table
|
|
||||||
await pool.query(`
|
|
||||||
CREATE TABLE IF NOT EXISTS email_templates (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
name VARCHAR(255) NOT NULL,
|
|
||||||
subject VARCHAR(500) NOT NULL,
|
|
||||||
html_content TEXT NOT NULL,
|
|
||||||
text_content TEXT,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
||||||
)
|
|
||||||
`);
|
|
||||||
console.log(' ✅ Table email_templates créée');
|
|
||||||
|
|
||||||
// Email campaigns table
|
|
||||||
await pool.query(`
|
|
||||||
CREATE TABLE IF NOT EXISTS email_campaigns (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
name VARCHAR(255) NOT NULL,
|
|
||||||
template_id UUID REFERENCES email_templates(id),
|
|
||||||
status VARCHAR(50) DEFAULT 'DRAFT',
|
|
||||||
scheduled_at TIMESTAMP,
|
|
||||||
sent_at TIMESTAMP,
|
|
||||||
total_recipients INTEGER DEFAULT 0,
|
|
||||||
sent_count INTEGER DEFAULT 0,
|
|
||||||
failed_count INTEGER DEFAULT 0,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
||||||
)
|
|
||||||
`);
|
|
||||||
console.log(' ✅ Table email_campaigns créée');
|
|
||||||
|
|
||||||
// Email campaign recipients table
|
|
||||||
await pool.query(`
|
|
||||||
CREATE TABLE IF NOT EXISTS email_campaign_recipients (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
campaign_id UUID REFERENCES email_campaigns(id) ON DELETE CASCADE,
|
|
||||||
email VARCHAR(255) NOT NULL,
|
|
||||||
status VARCHAR(50) DEFAULT 'PENDING',
|
|
||||||
sent_at TIMESTAMP,
|
|
||||||
error_message TEXT,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
||||||
)
|
|
||||||
`);
|
|
||||||
console.log(' ✅ Table email_campaign_recipients créée');
|
|
||||||
|
|
||||||
// Grand prize draws table
|
|
||||||
await pool.query(`
|
|
||||||
CREATE TABLE IF NOT EXISTS grand_prize_draws (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
winner_id UUID REFERENCES users(id),
|
|
||||||
draw_date TIMESTAMP NOT NULL,
|
|
||||||
prize_description TEXT,
|
|
||||||
is_claimed BOOLEAN DEFAULT FALSE,
|
|
||||||
claimed_at TIMESTAMP,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
||||||
)
|
|
||||||
`);
|
|
||||||
console.log(' ✅ Table grand_prize_draws créée');
|
|
||||||
|
|
||||||
console.log('✅ Migrations appliquées avec succès');
|
|
||||||
} catch (error) {
|
|
||||||
console.log(' ⚠️ Certaines migrations existent déjà:', error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fonction principale d'initialisation
|
|
||||||
*/
|
|
||||||
export async function initDatabase() {
|
|
||||||
console.log('\n🚀 ========================================');
|
|
||||||
console.log(' AUTO-INITIALISATION DE LA BASE DE DONNÉES');
|
|
||||||
console.log(' ========================================\n');
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 1. Vérifier si les tables existent
|
|
||||||
const hasTables = await tablesExist();
|
|
||||||
|
|
||||||
if (!hasTables) {
|
|
||||||
console.log('📋 Tables non trouvées, création en cours...\n');
|
|
||||||
await createTables();
|
|
||||||
} else {
|
|
||||||
console.log('✅ Tables déjà existantes\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Vérifier si les utilisateurs existent
|
|
||||||
const hasUsers = await usersExist();
|
|
||||||
|
|
||||||
if (!hasUsers) {
|
|
||||||
console.log('👥 Utilisateurs non trouvés, création en cours...\n');
|
|
||||||
await createDefaultUsers();
|
|
||||||
} else {
|
|
||||||
console.log('✅ Utilisateurs déjà existants\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Vérifier si les tickets existent
|
|
||||||
const hasTickets = await ticketsExist();
|
|
||||||
|
|
||||||
if (!hasTickets) {
|
|
||||||
console.log('🎫 Tickets non trouvés, génération en cours...\n');
|
|
||||||
await generateTickets();
|
|
||||||
} else {
|
|
||||||
console.log('✅ Tickets déjà générés\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Appliquer les migrations
|
|
||||||
await applyMigrations();
|
|
||||||
|
|
||||||
console.log('\n✨ ========================================');
|
|
||||||
console.log(' BASE DE DONNÉES INITIALISÉE AVEC SUCCÈS');
|
|
||||||
console.log(' ========================================');
|
|
||||||
console.log('\n🔐 Comptes disponibles:');
|
|
||||||
console.log(' Admin: admin@thetiptop.com / Admin123!');
|
|
||||||
console.log(' Employé 1: employee1@thetiptop.com / Employee123!');
|
|
||||||
console.log(' Employé 2: employee2@thetiptop.com / Employee123!\n');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('\n❌ Erreur lors de l\'initialisation:', error.message);
|
|
||||||
console.error(error.stack);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si exécuté directement (pas importé)
|
|
||||||
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
||||||
initDatabase()
|
|
||||||
.then(() => process.exit(0))
|
|
||||||
.catch(() => process.exit(1));
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user