Fix announcement display issues and improve user data association

Address critical production bug in the announcement system by ensuring correct filtering for global and store-specific announcements, and fix author association by using username instead of ID for PostgreSQL compatibility.

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/dnQ3tT8
This commit is contained in:
michaelschal committed 2025-08-17 09:22:36 +00:00
1 parent 243240701c
commit cefa4b7c22
5 files changed
+230 -9

No files matched your search

@@ -0,0 +1,209 @@
ctions
Admin filtering deliveries with groupIds: [ 1 ]
Fetching all deliveries
📢 [SERVER] Fetching announcements for user: admin_local environment: production
📢 [SERVER] User found: { username: 'admin', role: 'admin' }
🎯 [PRODUCTION] Using PostgreSQL DASHBOARD_MESSAGES table
Orders API called with: {
startDate: undefined,
endDate: undefined,
storeId: '1',
userRole: 'admin'
}
Admin filtering with groupIds: [ 1 ]
Fetching all orders
Customer Orders API called with: { groupIds: [ 1 ], userRole: 'admin' }
GET /api/publicities 200 in 191ms
🎯 [PRODUCTION] Found announcements: 0
Customer Orders returned: 10 items
🔗 PRODUCTION: getDeliveries() récupéré 48 livraisons avec relations
Deliveries returned: 48 items
GET /api/announcements 200 in 265ms
GET /api/customer-orders 200 in 180ms
GET /api/deliveries 200 in 187ms
🔗 PRODUCTION: getOrders() récupéré 33 commandes avec relations
Orders returned: 33 items
GET /api/orders 200 in 241ms
🎯 [SERVER] POST /api/announcements endpoint hit
🎯 [SERVER] Request body: {
"title": "test",
"content": "test",
"type": "info",
"storeId": 1,
"createdBy": "admin"
}
🎯 [SERVER] User object: { hasClaims: false, hasId: true, userId: 'admin_local' }
🎯 [SERVER] Extracted userId: admin_local
🎯 [SERVER] User found: { username: 'admin', role: 'admin', id: 'admin_local' }
🎯 [SERVER] User is admin, proceeding with validation
🎯 [SERVER] Announcement data validated: {
title: 'test',
content: 'test',
type: 'info',
storeId: null,
createdBy: 'admin_local'
}
🎯 [PRODUCTION] Creating in PostgreSQL DASHBOARD_MESSAGES table
🎯 [PRODUCTION] Announcement created successfully in DB: {

,
title: 'test',
content: 'test',
type: 'info',
storeId: null,
createdBy: 'admin',
createdAt: 2025-08-17T09:19:30.102Z,
author: { id: 'admin_local', firstName: 'Administrateur', lastName: '' },
group: null
}
POST /api/announcements 201 in 19ms
📢 [SERVER] Fetching announcements for user: admin_local environment: production
📢 [SERVER] User found: { username: 'admin', role: 'admin' }
🎯 [PRODUCTION] Using PostgreSQL DASHBOARD_MESSAGES table
🎯 [PRODUCTION] Found announcements: 0
GET /api/announcements 200 in 8ms
HEAD /api/health 200 in 0ms
🎯 [SERVER] POST /api/announcements endpoint hit
🎯 [SERVER] Request body: {
"title": "rzqr",
"content": "etset",
"type": "info",
"storeId": 1,
"createdBy": "admin"
}
🎯 [SERVER] User object: { hasClaims: false, hasId: true, userId: 'admin_local' }
🎯 [SERVER] Extracted userId: admin_local
🎯 [SERVER] User found: { username: 'admin', role: 'admin', id: 'admin_local' }
🎯 [SERVER] User is admin, proceeding with validation
🎯 [SERVER] Announcement data validated: {
title: 'rzqr',
content: 'etset',
type: 'info',
storeId: null,
createdBy: 'admin_local'
}
🎯 [PRODUCTION] Creating in PostgreSQL DASHBOARD_MESSAGES table
🎯 [PRODUCTION] Announcement created successfully in DB: {

,
title: 'rzqr',
content: 'etset',
type: 'info',
storeId: null,
createdBy: 'admin',
createdAt: 2025-08-17T09:19:37.509Z,
author: { id: 'admin_local', firstName: 'Administrateur', lastName: '' },
group: null
}
POST /api/announcements 201 in 10ms
📢 [SERVER] Fetching announcements for user: admin_local environment: production
📢 [SERVER] User found: { username: 'admin', role: 'admin' }
🎯 [PRODUCTION] Using PostgreSQL DASHBOARD_MESSAGES table
🎯 [PRODUCTION] Found announcements: 0
GET /api/announcements 200 in 11ms
Binary file not shown.

After

Width:  |  Height:  |  Size: 470 KiB

+1 -1
View File
@@ -2,4 +2,4 @@
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
#HttpOnly_localhost FALSE / FALSE 1755508518 connect.sid s%3A2H06I9RjaU2RHqAtgys18vROWYhhcdKw.StlcmCQB97ez7pxB4FWYVSv83LR9nxAxXRWu7do9v7E
#HttpOnly_localhost FALSE / FALSE 1755508872 connect.sid s%3A8siCpVkhgJFOCC-2efxz0Unao-G6QlnM.tzp77gMurWDDtFyYuwjNUy3wTm2X22lcdk%2F3rm4H2UE
+1 -1
View File
@@ -35,7 +35,7 @@ The platform is built with a clear separation of concerns, utilizing a modern fu
- **Invoice Verification Cache:** Robust caching system for invoice verification results with automatic expiration and conflict resolution. Enhanced with unique constraint handling and graceful error management for production stability (August 2025). Fixed production SSL certificate errors and fetch timeout loops with enhanced error handling, network timeout protection, and error result caching to prevent infinite retry loops (August 2025).
- **UI Scrollbar Optimization:** Eliminated redundant vertical scrollbar on the right side of the screen while preserving necessary internal page scrolling. Implemented global CSS rules with `overflow: hidden` on html/body/root and Layout height management to prevent vertical overflow issues in production (August 2025).
- **Task Management:** Système complet de gestion des tâches avec fonctionnalités temporelles avancées - tri intelligent (pending > priorité > date), dates d'échéance avec sélecteur calendrier, indicateurs visuels pour tâches en retard/urgentes, filtres par échéance (aujourd'hui, cette semaine, en retard, sans échéance), vue Kanban et liste, badges colorés pour statut temporel. Interface optimisée pour suivi prioritaire des tâches non validées. Correction critique de l'isolation des données : chaque magasin ne voit maintenant que ses propres tâches (Août 2025). **PRODUCTION FIX (Août 2025)** : Résolution du problème de rechargements multiples nécessaires pour l'administrateur - le cache des tâches s'invalide maintenant automatiquement lors du changement de magasin sélectionné.
- **Information System (Announcements):** Système d'informations complet remplaçant la carte commandes clients dans le dashboard - gestion d'annonces avec niveaux de priorité (normal, important, urgent), contrôle d'accès basé sur les rôles (admin : CRUD complet, autres rôles : lecture seule), tri intelligent par priorité et date, filtrage par magasin pour administrateurs, interface moderne avec badges colorés et indicateurs visuels. **STOCKAGE MÉMOIRE (Août 2025)** : Migration du stockage SQL vers stockage en mémoire partagé avec limite de 5 annonces maximum pour éviter tout problème de base de données et simplifier l'architecture.
- **Information System (Announcements):** Système d'informations complet remplaçant la carte commandes clients dans le dashboard - gestion d'annonces avec niveaux de priorité (normal, important, urgent), contrôle d'accès basé sur les rôles (admin : CRUD complet, autres rôles : lecture seule), tri intelligent par priorité et date, filtrage par magasin pour administrateurs, interface moderne avec badges colorés et indicateurs visuels. **PRODUCTION FIX MAJEUR (Août 2025)** : Correction critique du problème d'affichage en production PostgreSQL - fix du filtrage pour inclure annonces globales + magasin sélectionné, correction des relations d'auteur avec username au lieu d'ID, design adapté pour correspondre exactement aux autres cartes du dashboard.
- **DLC Module Permissions:** Correction des permissions de validation DLC pour permettre aux admin, directeur et manager de valider les produits DLC. Ajout de logs de debug pour traçabilité des validations (Août 2025).
- **User and Permission Management:** Granular access controls ensuring that users (e.g., employees) have appropriate permissions for tasks like creating customer orders.
- **Reporting:** Statistical reporting, including monthly summaries of deliveries based on `deliveredDate`.
+19 -7
View File
@@ -45,7 +45,7 @@ import {
} from "@shared/schema";
import { hasPermission } from "@shared/permissions";
import { z } from "zod";
import { eq, desc } from "drizzle-orm";
import { eq, desc, or, isNull } from "drizzle-orm";
import { invoiceVerificationService } from "./invoiceVerification";
import { backupService } from "./backupService";
import { weatherService } from "./weatherService.js";
@@ -3032,26 +3032,38 @@ RÉSUMÉ DU SCAN
createdAt: dashboardMessages.createdAt,
}).from(dashboardMessages);
// Filtrage par magasin pour admin
// Filtrage par magasin pour admin : inclure les annonces globales + annonces du magasin
if (user.role === 'admin' && req.query.storeId) {
query = query.where(eq(dashboardMessages.storeId, parseInt(req.query.storeId as string)));
const storeId = parseInt(req.query.storeId as string);
// Inclure les annonces globales (storeId = null) ET les annonces du magasin sélectionné
query = query.where(
or(
eq(dashboardMessages.storeId, storeId),
isNull(dashboardMessages.storeId)
)
);
}
const messages = await query.orderBy(desc(dashboardMessages.createdAt)).limit(5);
console.log('🔍 [PRODUCTION] Raw messages from DB:', messages.length, 'items:', messages);
// Ajouter les relations manuellement
const announcements = await Promise.all(
messages.map(async (message) => {
// Récupérer l'auteur
let author = { id: message.createdBy, firstName: 'Utilisateur', lastName: 'Inconnu' };
let author = { id: message.createdBy, firstName: 'Utilisateur', lastName: 'Inconnu', username: message.createdBy };
try {
// En production, createdBy est varchar, donc chercher par username
console.log('🔍 [PRODUCTION] Looking for user with username:', message.createdBy);
const [userResult] = await db.select().from(users).where(eq(users.username, message.createdBy));
console.log('🔍 [PRODUCTION] User search result:', userResult ? 'Found' : 'Not found');
if (userResult) {
author = {
id: userResult.id,
firstName: userResult.firstName || 'Utilisateur',
lastName: userResult.lastName || 'Inconnu'
lastName: userResult.lastName || 'Inconnu',
username: userResult.username
};
}
} catch (e) {
@@ -3138,8 +3150,8 @@ RÉSUMÉ DU SCAN
title: req.body.title,
content: req.body.content,
type: req.body.type || 'info',
storeId: null, // Toutes les annonces sont globales
createdBy: user.id,
storeId: req.body.storeId || null, // Permettre les annonces par magasin OU globales
createdBy: user.username, // Utiliser username pour PostgreSQL
});
console.log('🎯 [SERVER] Announcement data validated:', announcementData);