Ensure PostgreSQL tables are created and data is migrated

This commit modifies the database connection logic to prioritize PostgreSQL, introduces a new PostgreSQL initialization script with table creation and test data, and refactors announcement storage to use a global instance.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: e437ffed-c31b-44eb-9fd5-b6f9faa8e7ce
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/e437ffed-c31b-44eb-9fd5-b6f9faa8e7ce/zIqUatC
This commit is contained in:
michaelschal committed 2025-08-16 13:27:09 +00:00
1 parent a3889dd088
commit b1ea9dcc9b
4 files changed
+47 -39

No files matched your search

+25
View File
@@ -0,0 +1,25 @@
-- Script d'initialisation PostgreSQL pour les annonces
CREATE TABLE IF NOT EXISTS announcements (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
priority VARCHAR(20) DEFAULT 'normal' CHECK (priority IN ('normal', 'important', 'urgent')),
author_id VARCHAR(255) NOT NULL,
group_id INTEGER,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Index pour améliorer les performances
CREATE INDEX IF NOT EXISTS idx_announcements_priority ON announcements(priority);
CREATE INDEX IF NOT EXISTS idx_announcements_created_at ON announcements(created_at);
CREATE INDEX IF NOT EXISTS idx_announcements_group_id ON announcements(group_id);
-- Insertion de données de test
INSERT INTO announcements (title, content, priority, author_id, group_id) VALUES
('Bienvenue dans le système d''informations', 'Ce nouveau système remplace l''ancienne carte des commandes clients. Vous pouvez maintenant créer et gérer des annonces importantes.', 'important', 'admin', 1),
('Maintenance programmée', 'Une maintenance système aura lieu dimanche prochain de 2h à 4h du matin.', 'normal', 'admin', NULL)
ON CONFLICT DO NOTHING;
-- Afficher le résultat
SELECT COUNT(*) as total_announcements FROM announcements;
+11 -19
View File
@@ -103,6 +103,7 @@ class AnnouncementMemoryStorage {
const announcement: Announcement = {
id,
...announcementData,
priority: announcementData.priority || 'normal',
groupId: announcementData.groupId || null,
createdAt: new Date(),
updatedAt: new Date(),
@@ -178,27 +179,18 @@ class AnnouncementMemoryStorage {
return deleted;
}
// Méthode utilitaire pour obtenir le nombre d'annonces
getCount(): number {
return this.announcements.size;
}
// Méthode utilitaire pour nettoyer toutes les annonces (si nécessaire)
clear(): void {
this.announcements.clear();
this.idCounter = 1;
console.log('🧹 Toutes les annonces ont été supprimées');
}
}
// Instance singleton pour partager entre production et développement
let announcementStorage: AnnouncementMemoryStorage | null = null;
// Instance globale partagée
let globalAnnouncementStorage: AnnouncementMemoryStorage | null = null;
export function getAnnouncementStorage(usersGetter: () => Promise<User[]>, groupsGetter: () => Promise<Group[]>): AnnouncementMemoryStorage {
if (!announcementStorage) {
announcementStorage = new AnnouncementMemoryStorage(usersGetter, groupsGetter);
console.log('📢 Système d\'annonces en mémoire initialisé (max 5 annonces)');
export function getAnnouncementStorage(
usersGetter: () => Promise<User[]>,
groupsGetter: () => Promise<Group[]>
): AnnouncementMemoryStorage {
if (!globalAnnouncementStorage) {
globalAnnouncementStorage = new AnnouncementMemoryStorage(usersGetter, groupsGetter);
console.log('📢 Stockage mémoire des annonces initialisé');
}
return announcementStorage;
return globalAnnouncementStorage;
}
+10 -20
View File
@@ -14,15 +14,15 @@ console.log('🔗 Database initialization:', {
let db: any;
let pool: any;
if (isProduction && dbUrl && (dbUrl.includes('logiflow-db') || dbUrl.includes('localhost') || dbUrl.includes('127.0.0.1'))) {
// Standard PostgreSQL for production Docker
console.log('🐳 PRODUCTION: Using standard PostgreSQL');
if (dbUrl && (isProduction || process.env.FORCE_POSTGRES === 'true')) {
// Use PostgreSQL for production or when forced
console.log('🐘 Using PostgreSQL database');
const { Pool } = await import('pg');
const { drizzle } = await import('drizzle-orm/node-postgres');
pool = new Pool({
connectionString: dbUrl,
ssl: false,
ssl: dbUrl.includes('localhost') ? false : { rejectUnauthorized: false },
max: 10,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 5000,
@@ -38,25 +38,15 @@ if (isProduction && dbUrl && (dbUrl.includes('logiflow-db') || dbUrl.includes('l
});
} catch (error) {
console.error('❌ PostgreSQL connection test failed:', error);
}
} else {
// Fallback: use Neon for development (but will be overridden by MemStorage)
console.log('🔧 DEV: Using Neon (fallback, will use MemStorage)');
const { Pool, neonConfig } = await import('@neondatabase/serverless');
const { drizzle } = await import('drizzle-orm/neon-serverless');
const ws = await import('ws');
neonConfig.webSocketConstructor = ws.default;
if (dbUrl) {
pool = new Pool({ connectionString: dbUrl });
db = drizzle({ client: pool, schema });
} else {
// Create dummy instances for development
// Continue anyway, will use MemStorage as fallback
pool = null;
db = null;
console.log('🔧 DEV: No DATABASE_URL, using MemStorage');
}
} else {
// Development fallback: use MemStorage
console.log('🔧 DEV: Using MemStorage (development fallback)');
pool = null;
db = null;
}
export { db, pool };
+1
View File
@@ -68,6 +68,7 @@ import {
} from "@shared/schema";
import { db } from "./db";
import { eq, and, inArray, desc, sql, gte, lte, lt, or, isNull, isNotNull, asc } from "drizzle-orm";
import { getAnnouncementStorage } from "./announcementStorage";
export interface IStorage {