mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-11 17:27:31 +02:00
Enable automatic database updates for production environments
Adds automatic execution of database migrations, including schema modifications for the Service After-Sales (SAV) module, upon server startup. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 31f9bd88-0285-4787-81b3-31ceeea5a08b Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/31f9bd88-0285-4787-81b3-31ceeea5a08b/EXHO0Ia
This commit is contained in:
1 parent
45abdc5973
commit
37092a95ba
3 files changed
+177
No files matched your search
@@ -1,6 +1,7 @@
|
||||
import { Pool } from 'pg';
|
||||
import { drizzle } from 'drizzle-orm/node-postgres';
|
||||
import * as schema from "@shared/schema";
|
||||
import { runProductionMigrations } from './migrations.production.js';
|
||||
|
||||
console.log('🐳 PRODUCTION: Configuring standard PostgreSQL database');
|
||||
|
||||
@@ -36,4 +37,16 @@ pool.on('error', (err) => {
|
||||
console.error('❌ PostgreSQL connection error:', err);
|
||||
});
|
||||
|
||||
// Run migrations automatically when database is configured
|
||||
(async () => {
|
||||
try {
|
||||
console.log('🔄 Running automatic database migrations...');
|
||||
await runProductionMigrations();
|
||||
console.log('✅ Database migrations completed');
|
||||
} catch (error) {
|
||||
console.error('❌ Database migrations failed:', error);
|
||||
// Don't fail the application startup for migration errors
|
||||
}
|
||||
})();
|
||||
|
||||
console.log('✅ Production PostgreSQL database configured');
|
||||
@@ -6,6 +6,7 @@ import { dirname, join } from 'path';
|
||||
// Database will be configured in storage.js
|
||||
import { storage } from "./storage.js";
|
||||
import { setupLocalAuth, requireAuth } from "./localAuth.production.js";
|
||||
import { runProductionMigrations } from "./migrations.production.js";
|
||||
|
||||
// Get directory paths
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
@@ -43,6 +44,10 @@ import { registerRoutes } from "./routes.js";
|
||||
async function registerProductionRoutes(app: Express): Promise<void> {
|
||||
console.log('🔧 Registering all production routes...');
|
||||
|
||||
// Run automatic migrations before registering routes
|
||||
console.log('🔄 Running automatic production migrations...');
|
||||
await runProductionMigrations();
|
||||
|
||||
// Register ALL API routes (same as development)
|
||||
await registerRoutes(app);
|
||||
console.log('✅ All routes registered successfully for production');
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
import { neon } from '@neondatabase/serverless';
|
||||
|
||||
export async function runProductionMigrations() {
|
||||
const databaseUrl = process.env.DATABASE_URL;
|
||||
if (!databaseUrl) {
|
||||
console.error('❌ DATABASE_URL not found for migrations');
|
||||
return;
|
||||
}
|
||||
|
||||
const sql = neon(databaseUrl);
|
||||
|
||||
try {
|
||||
console.log('🔄 Checking and running SAV production migrations...');
|
||||
|
||||
// Vérifier si la colonne priority existe
|
||||
const checkPriorityColumn = await sql`
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_name='sav_tickets' AND column_name='priority'
|
||||
`;
|
||||
|
||||
if (checkPriorityColumn.length === 0) {
|
||||
console.log('📝 Running SAV table migrations...');
|
||||
|
||||
// Exécuter la migration complète SAV
|
||||
await sql`
|
||||
-- Ajouter la colonne priority si elle n'existe pas
|
||||
DO $$
|
||||
BEGIN
|
||||
-- Ajouter la colonne priority si elle n'existe pas
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='sav_tickets' AND column_name='priority') THEN
|
||||
ALTER TABLE sav_tickets ADD COLUMN priority varchar(50) NOT NULL DEFAULT 'normale';
|
||||
RAISE NOTICE 'Colonne priority ajoutée';
|
||||
END IF;
|
||||
|
||||
-- Ajouter la colonne problem_type si elle n'existe pas
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='sav_tickets' AND column_name='problem_type') THEN
|
||||
ALTER TABLE sav_tickets ADD COLUMN problem_type varchar(100) NOT NULL DEFAULT 'defectueux';
|
||||
RAISE NOTICE 'Colonne problem_type ajoutée';
|
||||
END IF;
|
||||
|
||||
-- Ajouter la colonne resolution_description si elle n'existe pas
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='sav_tickets' AND column_name='resolution_description') THEN
|
||||
ALTER TABLE sav_tickets ADD COLUMN resolution_description text;
|
||||
RAISE NOTICE 'Colonne resolution_description ajoutée';
|
||||
END IF;
|
||||
|
||||
-- Ajouter la colonne resolved_at si elle n'existe pas
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='sav_tickets' AND column_name='resolved_at') THEN
|
||||
ALTER TABLE sav_tickets ADD COLUMN resolved_at timestamp;
|
||||
RAISE NOTICE 'Colonne resolved_at ajoutée';
|
||||
END IF;
|
||||
|
||||
-- Ajouter la colonne closed_at si elle n'existe pas
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='sav_tickets' AND column_name='closed_at') THEN
|
||||
ALTER TABLE sav_tickets ADD COLUMN closed_at timestamp;
|
||||
RAISE NOTICE 'Colonne closed_at ajoutée';
|
||||
END IF;
|
||||
|
||||
-- Vérifier si la colonne status existe, sinon l'ajouter
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='sav_tickets' AND column_name='status') THEN
|
||||
ALTER TABLE sav_tickets ADD COLUMN status varchar(50) NOT NULL DEFAULT 'nouveau';
|
||||
RAISE NOTICE 'Colonne status ajoutée';
|
||||
END IF;
|
||||
|
||||
END $$;
|
||||
`;
|
||||
|
||||
// Créer la table sav_ticket_history si elle n'existe pas
|
||||
await sql`
|
||||
CREATE TABLE IF NOT EXISTS sav_ticket_history (
|
||||
id serial PRIMARY KEY,
|
||||
ticket_id integer NOT NULL,
|
||||
action varchar(100) NOT NULL,
|
||||
description text,
|
||||
created_by varchar(255) NOT NULL,
|
||||
created_at timestamp DEFAULT NOW()
|
||||
);
|
||||
`;
|
||||
|
||||
// Ajouter les contraintes de clé étrangère si elles n'existent pas
|
||||
await sql`
|
||||
DO $$
|
||||
BEGIN
|
||||
-- Vérifier et ajouter la contrainte FK vers suppliers
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name='sav_tickets_supplier_id_fkey') THEN
|
||||
ALTER TABLE sav_tickets ADD CONSTRAINT sav_tickets_supplier_id_fkey
|
||||
FOREIGN KEY (supplier_id) REFERENCES suppliers(id);
|
||||
RAISE NOTICE 'Contrainte FK supplier_id ajoutée';
|
||||
END IF;
|
||||
|
||||
-- Vérifier et ajouter la contrainte FK vers groups
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name='sav_tickets_group_id_fkey') THEN
|
||||
ALTER TABLE sav_tickets ADD CONSTRAINT sav_tickets_group_id_fkey
|
||||
FOREIGN KEY (group_id) REFERENCES groups(id);
|
||||
RAISE NOTICE 'Contrainte FK group_id ajoutée';
|
||||
END IF;
|
||||
|
||||
-- Vérifier et ajouter la contrainte FK pour sav_ticket_history
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name='sav_ticket_history_ticket_id_fkey') THEN
|
||||
ALTER TABLE sav_ticket_history ADD CONSTRAINT sav_ticket_history_ticket_id_fkey
|
||||
FOREIGN KEY (ticket_id) REFERENCES sav_tickets(id) ON DELETE CASCADE;
|
||||
RAISE NOTICE 'Contrainte FK history ticket_id ajoutée';
|
||||
END IF;
|
||||
|
||||
END $$;
|
||||
`;
|
||||
|
||||
// Créer les index pour optimiser les performances
|
||||
await sql`
|
||||
CREATE INDEX IF NOT EXISTS idx_sav_tickets_status ON sav_tickets(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_sav_tickets_priority ON sav_tickets(priority);
|
||||
CREATE INDEX IF NOT EXISTS idx_sav_tickets_supplier_id ON sav_tickets(supplier_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_sav_tickets_group_id ON sav_tickets(group_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_sav_tickets_created_at ON sav_tickets(created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_sav_ticket_history_ticket_id ON sav_ticket_history(ticket_id);
|
||||
`;
|
||||
|
||||
// Mettre à jour les valeurs existantes si nécessaire
|
||||
await sql`
|
||||
UPDATE sav_tickets
|
||||
SET priority = 'normale'
|
||||
WHERE priority IS NULL OR priority = '';
|
||||
`;
|
||||
|
||||
await sql`
|
||||
UPDATE sav_tickets
|
||||
SET problem_type = 'defectueux'
|
||||
WHERE problem_type IS NULL OR problem_type = '';
|
||||
`;
|
||||
|
||||
console.log('✅ SAV production migrations completed successfully!');
|
||||
|
||||
// Vérification finale
|
||||
const verificationResult = await sql`
|
||||
SELECT
|
||||
'sav_tickets' as table_name,
|
||||
COUNT(*) as record_count,
|
||||
COUNT(CASE WHEN priority IS NOT NULL THEN 1 END) as records_with_priority
|
||||
FROM sav_tickets
|
||||
UNION ALL
|
||||
SELECT
|
||||
'sav_ticket_history' as table_name,
|
||||
COUNT(*) as record_count,
|
||||
NULL as records_with_priority
|
||||
FROM sav_ticket_history;
|
||||
`;
|
||||
|
||||
console.log('📊 SAV tables status:', verificationResult);
|
||||
|
||||
} else {
|
||||
console.log('✅ SAV migrations already applied, skipping');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error running SAV production migrations:', error);
|
||||
// Ne pas faire échouer le démarrage du serveur pour les erreurs de migration
|
||||
// L'application peut continuer à fonctionner même si la migration échoue
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user