diff --git a/client/src/hooks/useAuthUnified.ts b/client/src/hooks/useAuthUnified.ts
index f83f0d5..39e9b76 100644
--- a/client/src/hooks/useAuthUnified.ts
+++ b/client/src/hooks/useAuthUnified.ts
@@ -1,5 +1,5 @@
import { useState, useEffect } from 'react';
-import { useQuery } from "@tanstack/react-query";
+import { useQuery, useQueryClient } from "@tanstack/react-query";
// Hook d'authentification unifié qui s'adapte automatiquement
// En production utilise fetch direct, en développement utilise React Query
@@ -104,6 +104,7 @@ export function useAuthUnified() {
} else {
// En développement, forcer un refetch avec invalidation du cache
console.log('🔄 Development mode - invalidating cache and refetching');
+ const queryClient = useQueryClient();
queryClient.invalidateQueries({ queryKey: ['/api/user'] });
// Attendre un court délai pour la propagation
diff --git a/replit.md b/replit.md
index f59bd7a..df1e0ce 100644
--- a/replit.md
+++ b/replit.md
@@ -34,7 +34,7 @@ The platform is built with a clear separation of concerns, utilizing a modern fu
- **Reconciliation:** Functionality for reconciling Bills of Lading (BL) and invoices with immediate UI updates.
- **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). **MAJOR BUG FIX (August 2025)**: Resolved critical cache system failure - MemStorage was returning `undefined` for all cache lookups, preventing cache functionality entirely. Implemented working in-memory cache with Map-based storage and expiration logic. Fixed development mode to properly save verification results to cache. Added comprehensive cache operation logging for debugging. Verified complete cache workflow: miss → save → hit cycle working perfectly. **CRITICAL PRODUCTION FIX (August 2025)**: Fixed DatabaseStorage cache expiration bug - production was returning expired cache entries instead of checking expiration dates, causing repeated API calls despite existing cache. Added proper expiration verification and automatic cleanup of expired cache entries in PostgreSQL, matching MemStorage behavior.
- **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é. **SÉLECTION DATE ÉCHÉANCE FIX (Août 2025)** : Correction du problème empêchant la sélection de dates d'échéance autres que le jour courant - suppression de la restriction `disabled` dans le calendrier, uniformisation du format d'envoi des dates, et alignement du schéma Drizzle (date au lieu de timestamp) avec la structure PostgreSQL production. **DATES DE DÉPART IMPLÉMENTÉES (Août 2025)** : Système complet de dates de départ avec logique de visibilité basée sur les rôles - Managers/Employés ne voient les tâches qu'à partir de leur date de départ, Admin/Directeur voient toutes les tâches avec styles visuels différents pour les tâches futures (fond gris, bordures pointillées, texte italique, badge "Future"). Interface utilisateur refonte complète avec NewTaskForm.tsx présentant clairement les deux dates (📅 départ, ⏰ échéance) avec règles de validation et explications des rôles de visibilité. **DESIGN ANGULAR (Août 2025)** : Suppression de tous les angles arrondis dans le formulaire de création/édition de tâches (NewTaskForm.tsx) - design plus épuré avec bordures droites pour un aspect plus professionnel. **FIX PRODUCTION (Août 2025)** : Correction du champ "Assigné à" qui avait par défaut "admin" en production (Tasks.tsx ligne 283) - maintenant vide par défaut comme attendu. Suppression complète des angles arrondis dans tous les composants de formulaires et modales (`rounded-none` ajouté aux Dialog, `borderRadius: '0px'` dans TaskFormInline). **UX AMÉLIORATION (Août 2025)** : Suppression du bouton "Annuler" redondant en haut du modal de création/modification des tâches - conservation uniquement du bouton en bas pour une interface plus épurée.
+- **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é. **SÉLECTION DATE ÉCHÉANCE FIX (Août 2025)** : Correction du problème empêchant la sélection de dates d'échéance autres que le jour courant - suppression de la restriction `disabled` dans le calendrier, uniformisation du format d'envoi des dates, et alignement du schéma Drizzle (date au lieu de timestamp) avec la structure PostgreSQL production. **DATES DE DÉPART IMPLÉMENTÉES (Août 2025)** : Système complet de dates de départ avec logique de visibilité basée sur les rôles - Managers/Employés ne voient les tâches qu'à partir de leur date de départ, Admin/Directeur voient toutes les tâches avec styles visuels différents pour les tâches futures (fond gris, bordures pointillées, texte italique, badge "Future"). Interface utilisateur refonte complète avec NewTaskForm.tsx présentant clairement les deux dates (📅 départ, ⏰ échéance) avec règles de validation et explications des rôles de visibilité. **DESIGN ANGULAR (Août 2025)** : Suppression de tous les angles arrondis dans le formulaire de création/édition de tâches (NewTaskForm.tsx) - design plus épuré avec bordures droites pour un aspect plus professionnel. **FIX PRODUCTION (Août 2025)** : Correction du champ "Assigné à" qui avait par défaut "admin" en production (Tasks.tsx ligne 283) - maintenant vide par défaut comme attendu. Suppression complète des angles arrondis dans tous les composants de formulaires et modales (`rounded-none` ajouté aux Dialog, `borderRadius: '0px'` dans TaskFormInline). **UX AMÉLIORATION (Août 2025)** : Suppression du bouton "Annuler" redondant en haut du modal de création/modification des tâches - conservation uniquement du bouton en bas pour une interface plus épurée. **FIX CRITIQUE FILTRAGE GROUPES (Août 2025)** : Résolution définitive du problème de filtrage des groupes pour directeurs et managers - quand aucun groupe spécifique n'est sélectionné, les APIs renvoient maintenant un résultat vide au lieu d'afficher les données de tous les groupes assignés. Force la sélection explicite d'un groupe pour éviter l'affichage erroné de données multiples après rechargement de page. Ajout du sélecteur de groupe dans l'interface pour directeurs/managers avec auto-sélection si un seul groupe disponible.
- **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. **SUPPRESSION FIX (Août 2025)** : Correction du problème de suppression en production - ajout de la logique PostgreSQL manquante dans la route DELETE, les annonces peuvent maintenant être supprimées correctement en production. **MODAL DASHBOARD (Août 2025)** : Ajout d'un modal automatique dans le dashboard qui affiche la dernière annonce créée il y a moins de 2 jours - système de mémorisation localStorage pour éviter les re-affichages, interface avec priorités colorées, formatage français des dates, filtrage par magasin pour admins. **UTILISATEUR INCONNU FIX (Août 2025)** : Correction critique du problème "utilisateur inconnu" en production - création de la table `dashboard_messages` manquante, correction des noms de colonnes (`first_name` au lieu de `firstName`), amélioration de la logique de récupération des noms d'utilisateur avec fallback intelligent. **AFFICHAGE SIMPLIFIÉ (Août 2025)** : Suppression de l'affichage du nom de l'auteur des annonces pour simplifier l'interface - seul le nom du magasin/groupe est affiché si applicable. **FIX MODIFICATION PRODUCTION (Août 2025)** : Correction critique du problème de modification des annonces en production - la jointure PostgreSQL utilisait incorrectement `users.id` au lieu de `users.username` pour la relation avec `createdBy`, causant des erreurs 500. Fix appliqué avec correction de la jointure et ajout de logs de debug dans `announcementStorage.ts`. **MÉTHODE MANQUANTE FIX (Août 2025)** : Identification et correction de l'erreur "getAnnouncement is not a function" - ajout de la méthode `getAnnouncement` manquante dans l'interface `IAnnouncementStorage` et ses implémentations `AnnouncementDatabaseStorage` et `AnnouncementMemoryStorage` pour résoudre définitivement les erreurs 500 en production.
- **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).
- **DLC UX Enhancement:** Ajout de tooltips explicatifs sur les icônes stock épuisé (PackageX) et restauration (RotateCcw) pour clarifier la différence entre "périmé" et "stock épuisé" et améliorer l'expérience utilisateur (Août 2025).
diff --git a/server/routes.ts b/server/routes.ts
index 569ef0e..acbc736 100644
--- a/server/routes.ts
+++ b/server/routes.ts
@@ -345,10 +345,11 @@ export async function registerRoutes(app: Express): Promise {
// If admin selected a specific store, filter by it
if (storeId) {
groupIds = [parseInt(storeId as string)];
+ console.log('🔍 Admin orders filtering by store:', { storeId, groupIds });
+ } else {
+ console.log('🔍 Admin orders - showing all stores');
}
- console.log('Admin filtering with groupIds:', groupIds);
-
// Only filter by date if both startDate and endDate are provided
if (startDate && endDate) {
console.log('Fetching orders by date range:', startDate, 'to', endDate);
@@ -359,8 +360,39 @@ export async function registerRoutes(app: Express): Promise {
}
} else {
// For all non-admin roles (manager, employee, directeur), filter by their assigned groups
- const groupIds = (user as any).userGroups?.map((ug: any) => ug.groupId) || [];
- console.log('Non-admin filtering with groupIds:', groupIds);
+ const userGroupIds = (user as any).userGroups?.map((ug: any) => ug.groupId) || [];
+ let groupIds: number[] | undefined;
+
+ if (storeId) {
+ // If a specific store is requested, verify user has access to it
+ const requestedStoreId = parseInt(storeId as string);
+ if (userGroupIds.includes(requestedStoreId)) {
+ groupIds = [requestedStoreId];
+ console.log('🔍 Non-admin orders - filtering by accessible store:', {
+ userId: user.id,
+ role: user.role,
+ requestedStoreId
+ });
+ } else {
+ // User doesn't have access to this store, return empty array
+ console.log('🚫 Non-admin orders - user has no access to requested store:', {
+ userId: user.id,
+ role: user.role,
+ requestedStoreId,
+ userGroups: userGroupIds
+ });
+ return res.json([]);
+ }
+ } else {
+ // IMPORTANT FIX: For directeur/manager roles, when no specific store is selected,
+ // return empty result to force explicit store selection
+ console.log('🔍 Non-admin orders - no store selection, returning empty:', {
+ userId: user.id,
+ role: user.role,
+ userGroups: userGroupIds
+ });
+ return res.json([]);
+ }
// Only filter by date if both startDate and endDate are provided
if (startDate && endDate) {
@@ -626,10 +658,11 @@ export async function registerRoutes(app: Express): Promise {
// If admin selected a specific store, filter by it
if (storeId) {
groupIds = [parseInt(storeId as string)];
+ console.log('🔍 Admin deliveries filtering by store:', { storeId, groupIds });
+ } else {
+ console.log('🔍 Admin deliveries - showing all stores');
}
- console.log('Admin filtering deliveries with groupIds:', groupIds);
-
// Only filter by date if both startDate and endDate are provided
if (startDate && endDate) {
console.log('Fetching deliveries by date range:', startDate, 'to', endDate);
@@ -639,9 +672,40 @@ export async function registerRoutes(app: Express): Promise {
deliveries = await storage.getDeliveries(groupIds);
}
} else {
- // For non-admin users (managers, employees, directeurs), only show their assigned stores
- const groupIds = (user as any).userGroups?.map((ug: any) => ug.groupId) || [];
- console.log('Non-admin filtering deliveries with groupIds:', groupIds);
+ // For non-admin users (managers, employees, directeurs), filter by their assigned groups
+ const userGroupIds = (user as any).userGroups?.map((ug: any) => ug.groupId) || [];
+ let groupIds: number[] | undefined;
+
+ if (storeId) {
+ // If a specific store is requested, verify user has access to it
+ const requestedStoreId = parseInt(storeId as string);
+ if (userGroupIds.includes(requestedStoreId)) {
+ groupIds = [requestedStoreId];
+ console.log('🔍 Non-admin deliveries - filtering by accessible store:', {
+ userId: user.id,
+ role: user.role,
+ requestedStoreId
+ });
+ } else {
+ // User doesn't have access to this store, return empty array
+ console.log('🚫 Non-admin deliveries - user has no access to requested store:', {
+ userId: user.id,
+ role: user.role,
+ requestedStoreId,
+ userGroups: userGroupIds
+ });
+ return res.json([]);
+ }
+ } else {
+ // IMPORTANT FIX: For directeur/manager roles, when no specific store is selected,
+ // return empty result to force explicit store selection
+ console.log('🔍 Non-admin deliveries - no store selection, returning empty:', {
+ userId: user.id,
+ role: user.role,
+ userGroups: userGroupIds
+ });
+ return res.json([]);
+ }
// Only filter by date if both startDate and endDate are provided
if (startDate && endDate) {
@@ -1334,8 +1398,13 @@ export async function registerRoutes(app: Express): Promise {
if (user.role === 'admin') {
// Admin can see all tasks or filter by specific store
groupIds = storeId ? [parseInt(storeId as string)] : undefined;
+ console.log('🔍 Admin tasks filtering:', {
+ storeId,
+ groupIds,
+ message: storeId ? `Filtering by store ${storeId}` : 'Showing all stores'
+ });
} else {
- // Non-admin users can only see tasks from their assigned groups
+ // For directeur and other non-admin users: always restrict to their assigned groups
const userGroupIds = user.userGroups.map(ug => ug.groupId);
if (storeId) {
@@ -1343,13 +1412,35 @@ export async function registerRoutes(app: Express): Promise {
const requestedStoreId = parseInt(storeId as string);
if (userGroupIds.includes(requestedStoreId)) {
groupIds = [requestedStoreId];
+ console.log('🔍 Non-admin user requesting specific accessible store:', {
+ userId: user.id,
+ role: user.role,
+ requestedStoreId,
+ hasAccess: true
+ });
} else {
// User doesn't have access to this store, return empty array
+ console.log('🚫 Non-admin user requesting inaccessible store:', {
+ userId: user.id,
+ role: user.role,
+ requestedStoreId,
+ userGroups: userGroupIds,
+ hasAccess: false
+ });
return res.json([]);
}
} else {
- // No specific store requested, return tasks from user's groups only
- groupIds = userGroupIds;
+ // IMPORTANT FIX: For directeur/manager roles, when no specific store is selected,
+ // we should NOT show data from all their groups. This was causing the issue
+ // where after page refresh, data from multiple groups was displayed.
+ // Return empty result to force explicit store selection for non-admin users.
+ console.log('🔍 Non-admin user with no store selection - returning empty result:', {
+ userId: user.id,
+ role: user.role,
+ userGroups: userGroupIds,
+ message: 'Forcing explicit store selection'
+ });
+ return res.json([]);
}
}