diff --git a/CALENDAR-PRODUCTION-FIX.md b/CALENDAR-PRODUCTION-FIX.md
deleted file mode 100644
index ebfc1d1..0000000
--- a/CALENDAR-PRODUCTION-FIX.md
+++ /dev/null
@@ -1,77 +0,0 @@
-# Solution - Problème Calendrier Directeur en Production
-
-## Problème Identifié
-Le rôle directeur rencontre une erreur réseau lors de l'accès au module calendrier en production.
-
-## Diagnostic Effectué
-
-### ✅ Corrections Appliquées
-1. **Permissions côté serveur ajoutées** pour tous les modules:
- - `GET /api/orders` utilise maintenant `requirePermission('orders', 'view')`
- - `GET /api/deliveries` utilise maintenant `requirePermission('deliveries', 'view')`
- - `POST /api/customer-orders` utilise `requirePermission('customer-orders', 'create')`
- - `PUT /api/customer-orders/:id` utilise `requirePermission('customer-orders', 'edit')`
- - `DELETE /api/customer-orders/:id` utilise `requirePermission('customer-orders', 'delete')`
- - Toutes les routes DLC utilisent les bonnes permissions (`view`, `create`, `edit`, `delete`, `validate`)
-
-2. **Permissions directeur vérifiées** dans `shared/permissions.ts`:
- - ✅ Directeur a `view` pour `orders` (ligne 38)
- - ✅ Directeur a `view` pour `deliveries` (ligne 46)
- - ✅ Directeur a toutes les permissions pour `customer-orders` (ligne 70)
-
-### 🔍 Analyse du Problème
-Le problème n'est **PAS** lié aux permissions côté serveur. Les permissions sont correctement configurées pour le rôle directeur.
-
-### 🚨 Cause Probable
-L'erreur réseau indique un problème de **connectivité** ou de **configuration serveur** en production:
-
-1. **Timeout réseau** - Les APIs `/api/orders` et `/api/deliveries` prennent trop de temps à répondre
-2. **Problème de load balancer** - Les requêtes ne parviennent pas au serveur d'applications
-3. **Configuration firewall** - Certaines requêtes sont bloquées
-4. **Problème de base de données** - Lenteur ou indisponibilité temporaire
-
-## 🛠️ Script de Diagnostic
-Un script de diagnostic a été créé: `debug-calendar-production.js`
-
-### Utilisation:
-```bash
-# 1. Configurez les variables d'environnement
-export PRODUCTION_URL="https://votre-serveur-production.com"
-export PROD_USERNAME="votre-directeur-username"
-export PROD_PASSWORD="votre-directeur-password"
-
-# 2. Exécutez le diagnostic
-node debug-calendar-production.js --run
-```
-
-### Le script teste:
-- ✅ Connexion au serveur
-- ✅ Authentification directeur
-- ✅ Récupération du profil utilisateur
-- ✅ API `/api/orders` (utilisée par le calendrier)
-- ✅ API `/api/deliveries` (utilisée par le calendrier)
-- ✅ Temps de réponse réseau
-
-## 📋 Actions Recommandées
-
-### 1. Vérifications Immédiates
-- [ ] Vérifier que le serveur de production est démarré
-- [ ] Tester la connectivité réseau depuis le navigateur du directeur
-- [ ] Vérifier les logs serveur pour erreurs de timeout
-
-### 2. Diagnostic Approfondi
-- [ ] Exécuter `debug-calendar-production.js` pour identifier l'API défaillante
-- [ ] Vérifier les performances de la base de données en production
-- [ ] Contrôler la configuration du load balancer/reverse proxy
-
-### 3. Solutions selon le diagnostic
-- **Si timeout réseau**: Augmenter les timeouts du serveur web
-- **Si problème DB**: Optimiser les requêtes ou redémarrer la DB
-- **Si load balancer**: Vérifier la configuration du proxy
-
-## 📊 État du Projet
-- ✅ **Permissions employé** - Customer Orders et DLC fonctionnent
-- ✅ **Permissions directeur** - Système de permissions correct
-- 🔄 **Connectivité production** - Diagnostic en cours avec script
-
-Le système de permissions est maintenant entièrement cohérent entre côté client et serveur pour tous les rôles.
\ No newline at end of file
diff --git a/CLEAN-VALIDATE-ORDER-BUTTON.md b/CLEAN-VALIDATE-ORDER-BUTTON.md
deleted file mode 100644
index 0d4cc09..0000000
--- a/CLEAN-VALIDATE-ORDER-BUTTON.md
+++ /dev/null
@@ -1,65 +0,0 @@
-# Bouton de Validation Propre - Dans le Modal de Détail
-
-## Modifications Apportées
-
-J'ai nettoyé le code et déplacé le bouton de validation dans le modal de détail de commande pour une interface plus propre.
-
-### 1. Nettoyage du CalendarGrid
-- ✅ Supprimé tout le code de debug (textes rouges, boutons de test)
-- ✅ Retiré les props `user` et `onOrderValidated` non nécessaires
-- ✅ Interface calendrier propre et sans encombrement
-
-### 2. Ajout du Bouton dans OrderDetailModal
-- ✅ Nouveau bouton "Valider Commande" vert dans les actions du modal
-- ✅ Visible uniquement pour les admins (`user?.role === 'admin'`)
-- ✅ Apparaît seulement sur les commandes non-delivered (`item?.status !== 'delivered'`)
-- ✅ État de chargement pendant la validation
-- ✅ Toasts de confirmation/erreur
-
-### 3. Fonctionnement
-Quand vous cliquez sur une commande dans le calendrier :
-1. **Modal s'ouvre** avec les détails de la commande
-2. **Si vous êtes admin** et que la commande n'est pas delivered
-3. **Bouton vert "Valider Commande"** apparaît en bas à droite
-4. **Un clic** marque la commande comme delivered
-5. **Modal se ferme** automatiquement après validation
-
-### 4. Avantages de cette Approche
-- **Interface propre** : Le calendrier n'est pas encombré
-- **Actions centralisées** : Toutes les actions (modifier, supprimer, valider) au même endroit
-- **Plus visible** : Le bouton est bien visible dans le modal
-- **Meilleure UX** : L'utilisateur voit les détails avant de valider
-
-## Déploiement en Production
-
-### Fichiers Modifiés :
-1. **`client/src/components/CalendarGrid.tsx`** - Nettoyé, code de debug supprimé
-2. **`client/src/pages/Calendar.tsx`** - Props simplifiées
-3. **`client/src/components/modals/OrderDetailModal.tsx`** - Bouton de validation ajouté
-
-### Commandes :
-```bash
-# Sauvegarder
-cp -r client/src client/src.backup.clean
-
-# Appliquer les modifications
-# (copiez le contenu des fichiers modifiés)
-
-# Reconstruire
-npm run build
-
-# Redémarrer
-pm2 restart your-app-name
-```
-
-## Test Final
-
-1. **Connectez-vous en admin**
-2. **Cliquez sur CMD-55** dans le calendrier
-3. **Vérifiez** que le bouton vert "Valider Commande" apparaît dans le modal
-4. **Cliquez** sur le bouton pour valider
-5. **Confirmez** que CMD-55 devient gris (delivered) dans le calendrier
-
----
-
-**Résultat** : Interface propre avec bouton de validation facilement accessible dans le modal de détail des commandes.
\ No newline at end of file
diff --git a/CUSTOMER-ORDER-GROUPID-FINAL-FIX.md b/CUSTOMER-ORDER-GROUPID-FINAL-FIX.md
deleted file mode 100644
index a76a7b2..0000000
--- a/CUSTOMER-ORDER-GROUPID-FINAL-FIX.md
+++ /dev/null
@@ -1,59 +0,0 @@
-# Fix Final - Problème GroupId Commandes Client Production
-
-## Problème Identifié
-
-**DLC** ✅ → `groupId: 2` (fonctionne)
-**Commandes Client** ❌ → `groupId: 1` (ne fonctionne pas)
-
-## Cause Racine
-
-Les `defaultValues` du formulaire sont calculés avant que `user.userGroups` soit complètement chargé depuis `/api/user`.
-
-**Séquence problématique :**
-1. Formulaire se render → `user.userGroups` = `undefined`
-2. `getDefaultGroupId()` → retourne `1` (fallback)
-3. `/api/user` charge → `user.userGroups` = `[{groupId: 2}]`
-4. Mais `defaultValues` déjà fixés à `1` ❌
-
-## Solution Appliquée
-
-### 1. Double Sécurité (DefaultValues + Override)
-```javascript
-// ÉTAPE 1: defaultValues avec priorité groupe assigné
-const getDefaultGroupId = () => {
- if (user?.userGroups?.[0]?.groupId) {
- return user.userGroups[0].groupId; // Priorité absolue
- }
- return 1; // Fallback temporaire
-};
-
-// ÉTAPE 2: Override dans handleSubmit si besoin
-if (!groupId || groupId === 1) {
- if (user?.userGroups?.[0]?.groupId) {
- groupId = user.userGroups[0].groupId; // ✅ Force groupId correct
- }
-}
-```
-
-### 2. Logique de Priorité Unifiée
-**PARTOUT (DLC + Commandes Client) :**
-1. 🎯 **Groupe assigné utilisateur** - PRIORITÉ ABSOLUE
-2. 🏪 **Admin store selection** - Si pas de groupe assigné
-3. 🚨 **Fallback** `1` - Urgence seulement
-
-## Résultat Attendu
-
-Employé magasin #2 (Houdemont) :
-- ✅ **DLC** → `groupId: 2` (déjà fixé)
-- ✅ **Commandes Client** → `groupId: 2` (maintenant fixé avec override)
-
-**Test de Validation :**
-```javascript
-🎯 CustomerOrderForm defaultValue: Using user's assigned group: 2
-🔧 Customer Order Override: Using user's assigned group: 2 // ✅ Double sécurité
-✅ Final groupId after override check: 2
-```
-
-## Déploiement
-
-**PRÊT POUR PRODUCTION** - Fix double sécurité garantit le bon groupId même si defaultValues ne sont pas corrects au moment du render initial.
\ No newline at end of file
diff --git a/DEBUG-BUTTON-VISIBILITY.md b/DEBUG-BUTTON-VISIBILITY.md
deleted file mode 100644
index 3a217bd..0000000
--- a/DEBUG-BUTTON-VISIBILITY.md
+++ /dev/null
@@ -1,55 +0,0 @@
-# Debug - Bouton de Validation Non Visible
-
-## Modifications de Debug Ajoutées
-
-J'ai ajouté du code de debug temporaire pour identifier pourquoi le bouton de validation n'est pas visible :
-
-### 1. Informations Utilisateur
-Un petit texte rouge s'affiche au-dessus de la première commande montrant :
-- Le rôle de l'utilisateur connecté
-- Le statut de cette commande
-
-### 2. Bouton de Validation en Rouge
-Le bouton de validation est maintenant **TOUJOURS VISIBLE** avec un fond rouge vif au lieu d'être masqué
-
-### 3. Indicateur de Test Jaune
-Un petit "V" jaune apparaît sur toutes les commandes non-delivered pour confirmer que la condition fonctionne
-
-### 4. Logs de Debug
-Quand vous cliquez sur le bouton, des logs détaillés s'affichent dans la console
-
-## Comment Diagnostiquer
-
-1. **Ouvrez la console du navigateur** (F12)
-2. **Connectez-vous en admin** sur votre serveur de production
-3. **Allez au calendrier** et regardez :
- - Le texte rouge au-dessus de la première commande (rôle utilisateur)
- - Les petits "V" jaunes sur les commandes non-delivered
- - Le bouton rouge de validation s'il apparaît
-
-4. **Testez le bouton rouge** et vérifiez les logs dans la console
-
-## Résultats Possibles
-
-### Si vous voyez le texte rouge "User: admin"
-✅ L'utilisateur est bien connecté en admin
-
-### Si vous voyez le texte rouge "User: null" ou autre
-❌ Problème de connexion admin ou de passage des props
-
-### Si vous voyez les "V" jaunes mais pas le bouton rouge
-❌ Problème avec la condition `user?.role === 'admin'`
-
-### Si vous ne voyez rien du tout
-❌ Le code n'a pas été déployé correctement sur le serveur
-
-## Prochaines Étapes
-
-Une fois le diagnostic fait, je pourrai :
-1. Corriger le problème identifié
-2. Retirer le code de debug
-3. Remettre le bouton normal qui apparaît au survol
-
----
-
-**Important** : Ce code de debug est temporaire et très visible. Il faut le retirer une fois le problème résolu.
\ No newline at end of file
diff --git a/DEPLOYMENT-FIX.md b/DEPLOYMENT-FIX.md
deleted file mode 100644
index 93e1cb5..0000000
--- a/DEPLOYMENT-FIX.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# Fix de Production - LogiFlow
-
-## Problème résolu
-- ❌ Erreur `column user_groups.created_at does not exist` lors de getUserWithGroups
-- ✅ Authentification admin fonctionne (admin/admin)
-- ✅ Code corrigé et compilé avec succès
-
-## Action requise
-**REDÉPLOYER l'application MAINTENANT** pour résoudre le problème des livraisons vides.
-
-**Commandes de déploiement :**
-```bash
-# Sur votre serveur de production
-docker-compose up --build -d
-```
-
-**Vérification post-déploiement :**
-```bash
-# Tester que les données remontent
-curl -u admin:admin https://logiflow.ffnancy.fr/api/deliveries
-```
-
-## Vérifications post-déploiement
-1. Connexion admin/admin doit fonctionner
-2. Plus d'erreur `user_groups.created_at` dans les logs
-3. L'API `/api/user` doit fonctionner après connexion
-
-## Corrections incluses
-- ✅ **Routes manquantes ajoutées** : /api/users, /api/roles, /api/deliveries maintenant disponibles en production
-- ✅ getUserWithGroups() utilise des requêtes SQL manuelles (plus d'erreur userGroups.created_at)
-- ✅ Système d'authentification robuste avec support multi-format
-- ✅ Endpoint d'urgence pour reset admin si nécessaire
-- ✅ Routage amélioré pour la page principale (fix 502)
-- ✅ Taille bundle: 198.5kb (vs 85kb) - toutes les routes incluses
\ No newline at end of file
diff --git a/DLC-GROUPID-FIX.md b/DLC-GROUPID-FIX.md
deleted file mode 100644
index 797f2de..0000000
--- a/DLC-GROUPID-FIX.md
+++ /dev/null
@@ -1,70 +0,0 @@
-# Fix DLC GroupId - Production
-
-## Problème Identifié
-
-**Utilisateurs assignés au magasin #2 créent des DLC pour le magasin #1**
-
-## Cause du Problème
-
-Dans `client/src/pages/DlcPage.tsx` ligne 208, la logique était incorrecte :
-
-```javascript
-// AVANT (Problématique)
-groupId: selectedStoreId || stores[0]?.id || 2
-```
-
-**Problème** : Pour un utilisateur non-admin assigné au magasin #2 :
-- `selectedStoreId` = undefined (pas admin)
-- `stores[0]?.id` = 1 (premier magasin de la liste)
-- Résultat : DLC créée pour magasin #1 au lieu de #2
-
-## Solution Appliquée
-
-**Nouvelle logique de sélection groupId :**
-
-```javascript
-// APRÈS (Corrigé)
-let groupId;
-if (user?.role === 'admin' && selectedStoreId) {
- // Admin avec magasin sélectionné
- groupId = selectedStoreId;
-} else if (user?.userGroups?.[0]?.groupId) {
- // Utilisateur non-admin : utiliser son groupe assigné ✅
- groupId = user.userGroups[0].groupId;
-} else if (user?.role === 'admin') {
- // Admin sans sélection : premier magasin disponible
- groupId = stores[0]?.id || 1;
-} else {
- // Fallback par défaut
- groupId = 1;
-}
-```
-
-## Priorité de Sélection
-
-1. **Admin avec magasin sélectionné** → `selectedStoreId`
-2. **Utilisateur avec groupe assigné** → `user.userGroups[0].groupId` ✅ **FIX PRINCIPAL**
-3. **Admin sans sélection** → Premier magasin disponible
-4. **Fallback** → Magasin #1
-
-## Log de Debug Ajouté
-
-```javascript
-console.log("🏪 DLC GroupId Selection:", {
- userRole: user?.role,
- selectedStoreId,
- userGroups: user?.userGroups?.map(ug => ({groupId: ug.groupId, groupName: ug.group?.name})),
- finalGroupId: groupId
-});
-```
-
-## Test Production
-
-Maintenant un employé assigné au magasin #2 devrait créer des DLC avec `groupId: 2` au lieu de `groupId: 1`.
-
-## Déploiement
-
-1. ✅ Logique groupId corrigée dans `DlcPage.tsx`
-2. ✅ Debug logs ajoutés pour traçabilité
-3. 🔄 **Redémarrer serveur production**
-4. 🧪 **Tester création DLC avec employé magasin #2**
\ No newline at end of file
diff --git a/DLC-PRODUCTION-FIX-FINAL.md b/DLC-PRODUCTION-FIX-FINAL.md
deleted file mode 100644
index 9ad48ea..0000000
--- a/DLC-PRODUCTION-FIX-FINAL.md
+++ /dev/null
@@ -1,81 +0,0 @@
-# Fix Final Production - Problème UserGroups
-
-## Problème Identifié en Production
-
-Les logs frontend montraient :
-```javascript
-Customer Order Frontend Debug: {
- userRole: 'employee',
- selectedStoreId: 1,
- userGroups: undefined, // ❌ PROBLÈME ICI !
- initialGroupId: undefined,
- availableGroups: [...]
-}
-Final groupId selected: 1 // ❌ Fallback utilisé au lieu du groupe assigné
-```
-
-## Cause Racine Trouvée
-
-### ✅ Backend fonctionne correctement
-- `storage.getUserWithGroups(id)` retourne bien les groupes
-- `passport.deserializeUser` charge les `userGroups`
-
-### ❌ Route `/api/user` manquait userGroups
-```javascript
-// AVANT (Production cassée)
-app.get("/api/user", (req: any, res) => {
- res.json({
- id: req.user.id,
- role: req.user.role,
- // userGroups: MANQUANT ! ❌
- });
-});
-
-// APRÈS (Production fixée)
-app.get("/api/user", (req: any, res) => {
- res.json({
- id: req.user.id,
- role: req.user.role,
- userGroups: req.user.userGroups || [] // ✅ AJOUTÉ !
- });
-});
-```
-
-## Fix Appliqué
-
-### 1. Route `/api/user` corrigée
-- ✅ Ajout de `userGroups` dans la réponse JSON
-- ✅ Logs debug pour tracer les données utilisateur
-
-### 2. Logique Frontend maintenant fonctionnelle
-```javascript
-// Avec userGroups maintenant disponible :
-if (user?.userGroups?.[0]?.groupId) {
- // ✅ Utilisera le groupe assigné (groupId: 2)
- groupId = user.userGroups[0].groupId;
-}
-```
-
-## Résultat Attendu Production
-
-Employé assigné magasin #2 (Houdemont) :
-1. **Login** → `/api/user` retourne `userGroups: [{ groupId: 2, group: { name: 'Houdemont' } }]`
-2. **Frontend** → Détecte `user.userGroups[0].groupId = 2`
-3. **Création DLC** → `groupId: 2` (groupe assigné prioritaire)
-4. **Création commande** → `groupId: 2` (groupe assigné prioritaire)
-5. **Résultat** → DLC et commandes apparaissent dans magasin #2 ✅
-
-## Logs Debug Production
-
-Les nouveaux logs vont confirmer :
-```
-🔍 PRODUCTION /api/user - req.user: {
- id: '_1753266816257',
- role: 'employee',
- hasUserGroups: true,
- userGroupsLength: 1,
- userGroups: [{ groupId: 2, groupName: 'Houdemont' }]
-}
-```
-
-**DÉPLOIEMENT IMMÉDIAT REQUIS - FIX DEFINITIF**
\ No newline at end of file
diff --git a/ECART-COLUMN-FEATURE.md b/ECART-COLUMN-FEATURE.md
deleted file mode 100644
index bdd7124..0000000
--- a/ECART-COLUMN-FEATURE.md
+++ /dev/null
@@ -1,154 +0,0 @@
-# Ajout Colonne Écart - Module Rapprochement
-
-## 🎯 Demande Utilisateur
-
-Ajouter une colonne **"Écart"** dans le module rapprochement qui calcule la différence entre le montant BL et le montant Facture.
-
-## ✅ Implementation
-
-### 1. **Structure des Tableaux**
-
-#### **Onglet Manuel**
-```
-| Fournisseur | N° BL | Date Livr. | Montant BL | Ref. Facture | Montant Fact. | **Écart** | Magasin | Actions |
-```
-
-#### **Onglet Automatique**
-```
-| Fournisseur | N° BL | Date Livr. | Date Valid. | Montant BL | Ref. Facture | Montant Fact. | **Écart** | Magasin | Actions |
-```
-
-### 2. **Logique de Calcul**
-
-```typescript
-const blAmount = delivery.blAmount ? parseFloat(delivery.blAmount) : 0;
-const invoiceAmount = delivery.invoiceAmount ? parseFloat(delivery.invoiceAmount) : 0;
-
-if (blAmount && invoiceAmount) {
- const diff = blAmount - invoiceAmount;
- // BL > Facture = +XX.XX€ (positif)
- // BL < Facture = -XX.XX€ (négatif)
- // BL = Facture = 0.00€ (équilibré)
-}
-```
-
-### 3. **Couleurs Indicatives**
-
-```css
-/* Aucun écart - Parfait */
-diff === 0 → text-green-600
-
-/* Écart faible (≤ 10€) - Attention */
-diffAbs ≤ 10 → text-orange-600
-
-/* Écart important (> 10€) - Problème */
-diffAbs > 10 → text-red-600
-```
-
-### 4. **Affichage par Cas**
-
-#### **Cas Complet** (BL + Facture renseignés)
-- `+15.50€` (BL supérieur de 15.50€)
-- `-8.25€` (Facture supérieure de 8.25€)
-- `0.00€` (Montants identiques)
-
-#### **Cas Incomplet** (données manquantes)
-- `-` (grisé, données insuffisantes)
-
-### 5. **Headers de Colonnes**
-
-```typescript
-// Manuel
-
Écart
-
-// Automatique
-Écart
-```
-
-## 🎨 Rendu Visuel
-
-### Exemples d'Affichage
-
-| Montant BL | Montant Fact. | Écart | Couleur |
-|------------|---------------|--------|---------|
-| 150.00€ | 150.00€ | `0.00€` | 🟢 Vert |
-| 155.50€ | 150.00€ | `+5.50€` | 🟠 Orange |
-| 140.00€ | 165.75€ | `-25.75€` | 🔴 Rouge |
-| 100.00€ | - | `-` | ⚪ Gris |
-
-### États Visuels par Seuil
-
-```css
-/* Équilibré - Vert */
-.text-green-600 { color: #16a34a; }
-
-/* Écart modéré - Orange */
-.text-orange-600 { color: #ea580c; }
-
-/* Écart important - Rouge */
-.text-red-600 { color: #dc2626; }
-
-/* Non applicable - Gris */
-.text-gray-400 { color: #9ca3af; }
-```
-
-## 🔧 Code Implementation
-
-### Header (Manuel)
-```typescript
-
- Écart
-
-```
-
-### Cellule Data
-```typescript
-
- {(() => {
- const blAmount = delivery.blAmount ? parseFloat(delivery.blAmount) : 0;
- const invoiceAmount = delivery.invoiceAmount ? parseFloat(delivery.invoiceAmount) : 0;
- if (blAmount && invoiceAmount) {
- const diff = blAmount - invoiceAmount;
- const diffAbs = Math.abs(diff);
- return (
- 10 ? 'text-red-600' : 'text-orange-600'
- }`}>
- {diff > 0 ? '+' : ''}{diff.toFixed(2)}€
-
- );
- }
- return - ;
- })()}
-
-```
-
-## 🧪 Tests de Validation
-
-### Test 1 : Calcul d'Écart
-1. BL: 100.00€, Facture: 95.00€
-2. **Vérifier** : Écart = `+5.00€` (orange)
-
-### Test 2 : Équilibre
-1. BL: 150.00€, Facture: 150.00€
-2. **Vérifier** : Écart = `0.00€` (vert)
-
-### Test 3 : Écart Important
-1. BL: 200.00€, Facture: 185.00€
-2. **Vérifier** : Écart = `+15.00€` (rouge)
-
-### Test 4 : Données Manquantes
-1. BL: 100.00€, Facture: non renseigné
-2. **Vérifier** : Écart = `-` (gris)
-
-## 📊 Status
-
-- ✅ Colonne Écart ajoutée sur onglet Manuel
-- ✅ Colonne Écart ajoutée sur onglet Automatique
-- ✅ Calcul automatique (BL - Facture)
-- ✅ Couleurs indicatives par seuil
-- ✅ Gestion des cas de données manquantes
-- ✅ Format d'affichage cohérent (+/-XX.XX€)
-
-**La colonne Écart permet maintenant de visualiser instantanément les différences entre BL et factures !**
\ No newline at end of file
diff --git a/EMPLOYEE-403-FIXES-SUMMARY.md b/EMPLOYEE-403-FIXES-SUMMARY.md
deleted file mode 100644
index d5d955e..0000000
--- a/EMPLOYEE-403-FIXES-SUMMARY.md
+++ /dev/null
@@ -1,134 +0,0 @@
-# EMPLOYEE 403 FIXES - RÉSUMÉ COMPLET
-
-## 🎯 Problème Identifié
-
-**Issue**: Les employés étaient bloqués pour créer des commandes client et des DLC, malgré des permissions définies dans `shared/permissions.ts` qui l'autorisaient.
-
-## 🔍 Diagnostic Root Cause
-
-### 1. **Permissions Définies (Théoriques)**
-Dans `shared/permissions.ts`:
-```typescript
-// Commandes client - Employé autorisé
-'customer-orders': {
- employee: ['view', 'create'] // ✅ AUTORISÉ
-},
-
-// DLC - Employé autorisé
-dlc: {
- employee: ['view', 'create'] // ✅ AUTORISÉ
-}
-```
-
-### 2. **Contradictions Server-Side (Réelles)**
-Dans `server/routes.ts`, des vérifications hardcodées contredisaient le système de permissions:
-
-#### **A) Routes Publicités (Corrigées)**
-```typescript
-// AVANT - Hardcodé
-if (user.role === 'employee') {
- return res.status(403).json({ message: "Insufficient permissions" });
-}
-
-// APRÈS - Utilise le système de permissions
-if (!hasPermission(user.role, 'publicity', 'create')) {
- return res.status(403).json({ message: "Insufficient permissions" });
-}
-```
-
-#### **B) Route Suppression Commandes Client (Corrigée)**
-```typescript
-// AVANT - Hardcodé
-if (user.role !== 'admin') {
- return res.status(403).json({ message: "Only admins can delete customer orders" });
-}
-
-// APRÈS - Utilise le système de permissions
-if (!hasPermission(user.role, 'customer-orders', 'delete')) {
- return res.status(403).json({ message: "Insufficient permissions to delete customer orders" });
-}
-```
-
-#### **C) Route Validation DLC (Corrigée)**
-```typescript
-// AVANT - Array hardcodé
-if (!user || !['admin', 'manager', 'directeur'].includes(user.role)) {
- return res.status(403).json({ message: "Insufficient permissions to validate products" });
-}
-
-// APRÈS - Utilise le système de permissions
-if (!user || !hasPermission(user.role, 'dlc', 'validate')) {
- return res.status(403).json({ message: "Insufficient permissions to validate products" });
-}
-```
-
-## ✅ Corrections Appliquées
-
-### 1. **Import Missing ajouté**
-```typescript
-// Dans server/routes.ts
-import { hasPermission } from "@shared/permissions";
-```
-
-### 2. **Standardisation des Vérifications**
-- ✅ `POST /api/publicities` - Utilise `hasPermission(user.role, 'publicity', 'create')`
-- ✅ `PUT /api/publicities/:id` - Utilise `hasPermission(user.role, 'publicity', 'edit')`
-- ✅ `DELETE /api/customer-orders/:id` - Utilise `hasPermission(user.role, 'customer-orders', 'delete')`
-- ✅ `POST /api/dlc-products/:id/validate` - Utilise `hasPermission(user.role, 'dlc', 'validate')`
-
-### 3. **Vérification des Routes DLC/Customer Orders**
-- ✅ `POST /api/dlc-products` - ✅ **AUCUNE RESTRICTION HARDCODÉE** - Les employés peuvent créer
-- ✅ `POST /api/customer-orders` - ✅ **AUCUNE RESTRICTION HARDCODÉE** - Les employés peuvent créer
-
-## 🧪 Impact des Corrections
-
-### **Employés PEUVENT maintenant:**
-- ✅ Créer des commandes client (`customer-orders: create`)
-- ✅ Créer des produits DLC (`dlc: create`)
-- ✅ Voir les publicités (`publicity: view`)
-
-### **Employés NE PEUVENT PAS:**
-- ❌ Créer/modifier des publicités (`publicity: create/edit`)
-- ❌ Supprimer des commandes client (`customer-orders: delete`)
-- ❌ Valider des DLC (`dlc: validate`)
-- ❌ Supprimer des DLC (`dlc: delete`)
-
-## 🔧 Architecture Améliorée
-
-### **Avant (Incohérent)**
-```
-shared/permissions.ts ← Définit les permissions
- ↓
-server/routes.ts ← Ignore et hardcode d'autres règles
- ↓
-❌ CONFLIT & ERREURS 403
-```
-
-### **Après (Cohérent)**
-```
-shared/permissions.ts ← Source unique de vérité
- ↓
-server/routes.ts ← Utilise hasPermission() partout
- ↓
-✅ COHÉRENCE & ACCÈS CORRECT
-```
-
-## 🎯 Test de Validation
-
-### **Commandes Client**
-1. **Test Employé CREATE**: ✅ `POST /api/customer-orders` (autorisé)
-2. **Test Employé DELETE**: ❌ `DELETE /api/customer-orders/:id` (bloqué)
-
-### **DLC Products**
-1. **Test Employé CREATE**: ✅ `POST /api/dlc-products` (autorisé)
-2. **Test Employé VALIDATE**: ❌ `POST /api/dlc-products/:id/validate` (bloqué)
-
-## 📋 Status Final
-
-- ✅ **Import hasPermission ajouté**
-- ✅ **4 routes corrigées pour utiliser le système de permissions**
-- ✅ **Cohérence rétablie entre shared/permissions.ts et server/routes.ts**
-- ✅ **Employés peuvent maintenant créer commandes client et DLC**
-- ✅ **Restrictions appropriées maintenues pour les actions sensibles**
-
-**PROBLÈME RÉSOLU** : Les employés ont maintenant les accès corrects selon les permissions définies dans le système centralisé.
\ No newline at end of file
diff --git a/FORCE_DEPLOY_v2.txt b/FORCE_DEPLOY_v2.txt
deleted file mode 100644
index e5a0a67..0000000
--- a/FORCE_DEPLOY_v2.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-Force deploy version 2 - Critical task completion fix
-
-This file forces a redeploy of the production application to apply the critical
-fix for task completion functionality that was added to initDatabase.production.ts
-
-Changes:
-- Added CRITICAL FIX v2 in initDatabase.production.ts
-- Forces recreation of completed_at and completed_by columns on startup
-- Should resolve persistent "column completed_at does not exist" error in production
-
-Deploy timestamp: 2025-07-18 20:05:00 UTC
\ No newline at end of file
diff --git a/PRODUCTION-AUTO-SYNC-DEPLOY.md b/PRODUCTION-AUTO-SYNC-DEPLOY.md
deleted file mode 100644
index b2947f8..0000000
--- a/PRODUCTION-AUTO-SYNC-DEPLOY.md
+++ /dev/null
@@ -1,119 +0,0 @@
-# Déploiement de la Synchronisation Automatique - Production
-
-## Résumé des Modifications
-
-Le système de synchronisation automatique permet aux commandes de passer automatiquement en statut "delivered" quand leurs livraisons sont validées ou mises à jour vers "delivered".
-
-## Fichiers à Modifier en Production
-
-### 1. server/routes.ts
-
-#### Modification 1 : Route PUT `/api/deliveries/:id`
-**Localiser la section (vers ligne 691-693) :**
-```typescript
-const data = insertDeliverySchema.partial().parse(req.body);
-const updatedDelivery = await storage.updateDelivery(id, data);
-res.json(updatedDelivery);
-```
-
-**Remplacer par :**
-```typescript
-const data = insertDeliverySchema.partial().parse(req.body);
-const updatedDelivery = await storage.updateDelivery(id, data);
-
-// SYNCHRONISATION AUTOMATIQUE : Si livraison devient "delivered", marquer la commande associée comme "delivered"
-if (data.status === 'delivered' && updatedDelivery.orderId) {
- try {
- console.log(`🔄 Auto-sync: Delivery #${id} marked as delivered, updating order #${updatedDelivery.orderId}`);
- await storage.updateOrder(updatedDelivery.orderId, { status: 'delivered' });
- console.log(`✅ Auto-sync: Order #${updatedDelivery.orderId} automatically marked as delivered`);
- } catch (error) {
- console.error(`❌ Auto-sync failed for order #${updatedDelivery.orderId}:`, error);
- }
-}
-
-res.json(updatedDelivery);
-```
-
-#### Modification 2 : Route POST `/api/deliveries/:id/validate`
-**Localiser la section (vers ligne 830-831) :**
-```typescript
-await storage.validateDelivery(id, blData);
-res.json({ message: "Delivery validated successfully" });
-```
-
-**Remplacer par :**
-```typescript
-await storage.validateDelivery(id, blData);
-
-// SYNCHRONISATION AUTOMATIQUE : Quand validation, marquer la commande associée comme "delivered"
-if (delivery.orderId) {
- try {
- console.log(`🔄 Auto-sync: Delivery #${id} validated, updating order #${delivery.orderId} to delivered`);
- await storage.updateOrder(delivery.orderId, { status: 'delivered' });
- console.log(`✅ Auto-sync: Order #${delivery.orderId} automatically marked as delivered`);
- } catch (error) {
- console.error(`❌ Auto-sync failed for order #${delivery.orderId}:`, error);
- }
-}
-
-res.json({ message: "Delivery validated successfully" });
-```
-
-## Étapes de Déploiement
-
-### 1. Sauvegarde
-```bash
-cp server/routes.ts server/routes.ts.backup
-```
-
-### 2. Application des Modifications
-Éditez le fichier `server/routes.ts` et appliquez les deux modifications ci-dessus.
-
-### 3. Redémarrage du Serveur
-```bash
-# Méthode selon votre setup de production
-pm2 restart your-app-name
-# ou
-systemctl restart your-node-service
-# ou
-docker-compose restart
-```
-
-### 4. Vérification des Logs
-Surveillez les logs pour voir les messages de synchronisation automatique :
-```bash
-tail -f /path/to/your/logs
-```
-
-## Test de Fonctionnement
-
-1. **Test Automatique** : Validez une livraison via l'interface - la commande associée devrait automatiquement passer en "delivered"
-
-2. **Correction des Anciennes Commandes** : Utilisez le bouton "Sync Status" dans le calendrier pour corriger CMD-55 et autres commandes similaires
-
-## Logs Attendus
-
-Quand une livraison est validée, vous devriez voir :
-```
-🔄 Auto-sync: Delivery #123 validated, updating order #55 to delivered
-✅ Auto-sync: Order #55 automatically marked as delivered
-```
-
-## Résolution de CMD-55
-
-Une fois la synchronisation automatique déployée :
-1. Cliquez sur "Sync Status" dans le calendrier
-2. CMD-55 sera automatiquement corrigée car sa livraison est déjà validée
-3. Elle apparaîtra en gris dans le calendrier
-
-## Rollback en Cas de Problème
-
-```bash
-cp server/routes.ts.backup server/routes.ts
-# Redémarrer le serveur
-```
-
----
-
-**Note** : La synchronisation automatique ne s'applique qu'aux nouvelles actions. Pour corriger les commandes existantes comme CMD-55, utilisez le bouton "Sync Status".
\ No newline at end of file
diff --git a/PRODUCTION-EMPLOYEE-FIX-FINAL.md b/PRODUCTION-EMPLOYEE-FIX-FINAL.md
deleted file mode 100644
index 9292eae..0000000
--- a/PRODUCTION-EMPLOYEE-FIX-FINAL.md
+++ /dev/null
@@ -1,109 +0,0 @@
-# Fix Production Urgent - Employé Commandes Client & DLC
-
-## Problèmes Identifiés
-
-1. **Employé ne peut pas créer commandes clients** en production
-2. **DLC ne fonctionnent pas** en production (même problème qu'en dev)
-3. **Cache invalidation manquante** pour DLC
-
-## Analyse du Code
-
-### ✅ Permissions OK
-```javascript
-// shared/permissions.ts - Lignes 67-73 et 75-81
-'customer-orders': {
- employee: ['view', 'create'] // ✅ PERMISSION OK
-},
-dlc: {
- employee: ['view', 'create'] // ✅ PERMISSION OK
-}
-```
-
-### ✅ Routes Backend OK
-```javascript
-// server/routes.ts
-// POST /api/customer-orders - REMOVED: All role restrictions
-// POST /api/dlc-products - REMOVED: All role restrictions
-```
-
-### ✅ Frontend Permissions OK
-```javascript
-// client/src/lib/permissions.ts - Ligne 118
-const canCreate = (module: Module): boolean => canPerformAction(module, 'create');
-// usePermissions(user?.role) fonctionne correctement
-```
-
-## Root Cause Probable
-
-Le problème n'est PAS les permissions mais plutôt :
-
-1. **Cache frontend** - L'employé a peut-être un cache obsolète
-2. **Erreur validation** - Schema validation qui échoue silencieusement
-3. **GroupId manquant** - L'employé n'a pas de groupId défini correctement
-4. **DLC Production** - Même problème cache qu'en dev
-
-## Solutions Immédiates
-
-### 1. Fix Cache DLC (Déjà Fait en Dev)
-```javascript
-// client/src/pages/DlcPage.tsx
-queryClient.invalidateQueries({ queryKey: ["/api/dlc-products"], exact: false });
-```
-
-### 2. Debug Frontend Production
-```javascript
-// À tester en console DevTools sur production:
-console.log("User:", user);
-console.log("Role:", user?.role);
-console.log("Groups:", user?.userGroups);
-console.log("Can create customer orders:", permissions.canCreate('customer-orders'));
-console.log("Can create DLC:", permissions.canCreate('dlc'));
-```
-
-### 3. Test Manual Production
-```javascript
-// Tester en curl direct sur serveur production:
-curl -X POST https://votre-serveur/api/customer-orders \
- -H "Content-Type: application/json" \
- -H "Cookie: session=..." \
- -d '{
- "customerName": "Test Production",
- "contactNumber": "0123456789",
- "productName": "Test",
- "quantity": 1,
- "groupId": 2
- }'
-```
-
-## Actions Requises
-
-### Immédiat
-1. **Redémarrer serveur production** pour avoir les derniers fixes
-2. **Vider cache browser** de l'employé (Ctrl+F5 ou mode incognito)
-3. **Tester création commande** avec DevTools ouvert
-4. **Noter toute erreur** console/réseau
-
-### Si Problème Persiste
-1. **Logs serveur** - Chercher erreurs dans logs production
-2. **User Groups** - Vérifier que l'employé a bien un groupe assigné
-3. **Schema Validation** - Tester les données envoyées
-
-## Checklist Déploiement
-
-- [x] Routes backend sans restrictions rôle
-- [x] Permissions employé définies correctement
-- [x] Cache invalidation DLC avec exact:false
-- [x] Frontend permissions hook fonctionnel
-- [ ] Serveur production redémarré
-- [ ] Cache browser employé vidé
-- [ ] Tests création commande/DLC validés
-
-## Fichiers Modifiés
-
-1. `client/src/pages/DlcPage.tsx` - Cache invalidation fix
-2. `server/routes.ts` - Debug logs ajoutés
-3. `server/storage.ts` - MemStorage DLC fix (dev uniquement)
-
-## Prochain Pas
-
-**Tester immédiatement** après redémarrage serveur production avec un employé en mode incognito + DevTools.
\ No newline at end of file
diff --git a/PRODUCTION-ERROR-502-FIX.md b/PRODUCTION-ERROR-502-FIX.md
deleted file mode 100644
index 4b25b89..0000000
--- a/PRODUCTION-ERROR-502-FIX.md
+++ /dev/null
@@ -1,185 +0,0 @@
-# Correction Erreur Production - "Une erreur s'est produite"
-
-## Problème Identifié
-Votre serveur de production affiche une page d'erreur générique au lieu de l'application LogiFlow.
-
-## Diagnostic Immédiat
-
-### 1. Vérifiez les Logs du Serveur
-```bash
-# Si vous utilisez PM2
-pm2 logs your-app-name --lines 50
-
-# Si vous utilisez systemctl
-sudo journalctl -u your-service-name -f --lines=50
-
-# Si vous utilisez Docker
-docker-compose logs -f --tail=50
-```
-
-### 2. Vérifiez le Statut de l'Application
-```bash
-# PM2
-pm2 status
-pm2 info your-app-name
-
-# systemctl
-sudo systemctl status your-service-name
-
-# Docker
-docker-compose ps
-```
-
-## Solutions par Ordre de Priorité
-
-### Solution 1 : Redémarrage Simple
-```bash
-# PM2
-pm2 restart your-app-name
-
-# systemctl
-sudo systemctl restart your-service-name
-
-# Docker
-docker-compose restart
-```
-
-### Solution 2 : Vérification des Ports
-```bash
-# Vérifiez quel processus utilise le port (généralement 5000 ou 3000)
-sudo netstat -tulpn | grep :5000
-sudo lsof -i :5000
-
-# Si un autre processus occupe le port, le tuer
-sudo kill -9
-```
-
-### Solution 3 : Reconstruction Complete
-```bash
-# Sauvegarder les modifications récentes
-cp -r client/src client/src.current
-
-# Reconstruction complète
-npm install
-npm run build
-
-# Redémarrage
-pm2 restart your-app-name --update-env
-```
-
-### Solution 4 : Vérification des Variables d'Environnement
-```bash
-# Vérifiez que les variables essentielles sont définies
-echo $NODE_ENV
-echo $DATABASE_URL
-echo $PORT
-
-# Si manquantes, les redéfinir
-export NODE_ENV=production
-export PORT=5000
-# etc...
-```
-
-### Solution 5 : Vérification de la Base de Données
-```bash
-# Test de connexion PostgreSQL
-psql $DATABASE_URL -c "SELECT 1;"
-
-# Si la connexion échoue, vérifiez les credentials
-```
-
-## Scripts de Diagnostic Automatique
-
-### Script de Santé Générale
-```bash
-#!/bin/bash
-echo "=== DIAGNOSTIC PRODUCTION ==="
-echo "Date: $(date)"
-echo ""
-
-echo "1. Status PM2:"
-pm2 status
-
-echo ""
-echo "2. Processes sur port 5000:"
-sudo lsof -i :5000
-
-echo ""
-echo "3. Logs récents (10 dernières lignes):"
-pm2 logs your-app-name --lines 10 --nostream
-
-echo ""
-echo "4. Espace disque:"
-df -h
-
-echo ""
-echo "5. Mémoire:"
-free -h
-
-echo ""
-echo "6. Variables d'environnement critiques:"
-echo "NODE_ENV: $NODE_ENV"
-echo "PORT: $PORT"
-echo "DATABASE_URL: ${DATABASE_URL:0:20}..." # Masque les credentials
-```
-
-Sauvegardez ce script sous `production-health-check.sh` et exécutez-le :
-```bash
-chmod +x production-health-check.sh
-./production-health-check.sh
-```
-
-## Correction Spécifique selon l'Erreur
-
-### Si l'erreur est "EADDRINUSE" (Port occupé)
-```bash
-sudo lsof -i :5000
-sudo kill -9
-pm2 restart your-app-name
-```
-
-### Si l'erreur est "Database connection failed"
-```bash
-# Testez la connexion DB
-psql $DATABASE_URL -c "\dt"
-
-# Redémarrez les services de DB si nécessaire
-sudo systemctl restart postgresql
-```
-
-### Si l'erreur est "Module not found"
-```bash
-# Réinstallation complète
-rm -rf node_modules package-lock.json
-npm install
-npm run build
-pm2 restart your-app-name
-```
-
-## Prévention Future
-
-### 1. Monitoring Automatique
-Ajoutez cette ligne à votre crontab :
-```bash
-crontab -e
-# Ajouter cette ligne pour vérifier chaque minute
-* * * * * curl -f http://localhost:5000/api/health || pm2 restart your-app-name
-```
-
-### 2. Sauvegarde Automatique
-```bash
-# Script de sauvegarde quotidienne
-#!/bin/bash
-DATE=$(date +%Y%m%d_%H%M%S)
-tar -czf /backup/logiflow_$DATE.tar.gz /path/to/your/app
-find /backup -name "logiflow_*.tar.gz" -mtime +7 -delete
-```
-
-## Actions Immédiates Recommandées
-
-1. **Exécutez** le script de diagnostic ci-dessus
-2. **Copiez-collez** les résultats pour analyse
-3. **Tentez** un redémarrage simple en premier
-4. **Si le problème persiste**, reconstruisez l'application
-
-Une fois que vous aurez exécuté ces commandes, envoyez-moi les logs d'erreur pour un diagnostic plus précis.
\ No newline at end of file
diff --git a/PRODUCTION-FIX-GUIDE.md b/PRODUCTION-FIX-GUIDE.md
deleted file mode 100644
index bedd42e..0000000
--- a/PRODUCTION-FIX-GUIDE.md
+++ /dev/null
@@ -1,128 +0,0 @@
-# Guide de Correction Production - LogiFlow
-
-## Problèmes Résolus ✅
-
-### 1. Changement de Mot de Passe Administrateur
-**Problème** : ERR_MODULE_NOT_FOUND pour localAuth.production.js
-**Solution** : Implémentation d'une fonction `hashPasswordSimple` intégrée dans routes.ts qui fonctionne dans tous les environnements.
-
-### 2. Attribution des Groupes aux Utilisateurs
-**Problème** : Colonne "created_at" manquante dans la table user_groups en production
-**Solution** : Gestion d'erreur dans `assignUserToGroup` avec fallback automatique.
-
-## Solutions Disponibles
-
-### Solution A : Correction Automatique (Recommandée) ✅
-Le code a été modifié pour détecter automatiquement si la colonne `created_at` existe :
-- Essaie d'insérer avec le schéma complet
-- En cas d'erreur, insère sans la colonne `created_at`
-- Aucune intervention manuelle requise
-
-### Solution B : Mise à Jour de Base de Données (Optionnelle)
-Si vous souhaitez synchroniser complètement votre base de données production avec le schéma :
-
-```sql
--- Exécuter sur votre serveur de production
-ALTER TABLE user_groups
-ADD COLUMN IF NOT EXISTS created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
-```
-
-## Test des Corrections
-
-1. **Changement de Mot de Passe** : Testez via l'interface utilisateur
-2. **Attribution de Groupes** : Testez l'assignment d'utilisateurs aux groupes
-
-## Débogage Production
-
-### Problème "Aucun utilisateur trouvé"
-Si l'interface affiche "Aucun utilisateur trouvé" :
-
-1. **Vérification Base de Données** : Utilisez `production-users-debug.sql`
- ```bash
- psql $DATABASE_URL -f production-users-debug.sql
- ```
-
-2. **Vérification API** : Testez l'endpoint directement
- ```bash
- curl -H "Cookie: [votre-cookie-session]" https://votre-domaine.com/api/users
- ```
-
-### Script de Diagnostic SQL
-- `debug-usergroups-production.sql` : Problèmes d'association utilisateur-groupe
-- `production-users-debug.sql` : Problème de récupération des utilisateurs
-
-### Problème Création d'Utilisateur
-
-#### Erreur "duplicate key value violates unique constraint users_email_key"
-Cette erreur survient lors de la **création** ou **édition** d'utilisateur quand plusieurs utilisateurs ont un email vide (`""`) car PostgreSQL traite les chaînes vides comme des valeurs uniques.
-
-**Symptômes** :
-- Création d'utilisateur échoue avec erreur `Key (email)=() already exists`
-- Édition d'utilisateur échoue avec la même erreur lors de la sauvegarde
-
-**Solution** :
-1. Exécutez le script de correction :
- ```bash
- psql $DATABASE_URL -f fix-duplicate-empty-email.sql
- ```
-
-2. Redéployez l'application (le code a été corrigé pour utiliser `NULL` au lieu de `""` dans les routes de création ET d'édition)
-
-### Problème Synchronisation Commandes/Livraisons dans le Calendrier
-
-#### Symptômes observés :
-- Les livraisons marquées "Livré" affichent "Date non disponible"
-- Les commandes liées à des livraisons livrées ne passent pas en statut "delivered"
-- Problème d'affichage des dates dans le modal de détails de commande
-
-#### Corrections apportées :
-1. **Affichage des dates corrigé** : Le modal affiche maintenant la date de livraison réelle (`deliveredDate`) pour les livraisons livrées
-2. **Synchronisation automatique des statuts** : Les commandes sont automatiquement marquées "delivered" quand leurs livraisons associées sont livrées
-3. **Script de correction des données** : `fix-delivery-order-sync.sql` pour corriger les données existantes
-
-**Solution complète** :
-1. Exécutez le script de synchronisation :
- ```bash
- psql $DATABASE_URL -f fix-delivery-order-sync.sql
- ```
-
-2. Redéployez l'application avec les corrections
-
-#### Tests de Création
-1. **Test Manuel** : Utilisez `test-create-user-production.js`
- ```bash
- PRODUCTION_HOST=votre-domaine.com SESSION_COOKIE="connect.sid=..." node test-create-user-production.js
- ```
-
-2. **Vérification Logs** : Cherchez ces messages d'erreur :
- - `❌ Password hashing failed`
- - `❌ Storage createUser error`
- - `duplicate key value violates unique constraint`
-
-### Logs de Débogage Disponibles
-**Récupération Utilisateurs :**
-- `🔍 GET /api/users - Fetching users with simplified approach`
-- `📊 Found X base users`
-- `❌ Error getting groups for user [username]:`
-- `🔐 API /api/users - Returning: {length: X, totalGroups: Y}`
-
-**Création Utilisateur :**
-- `🔍 POST /api/users - Creating new user`
-- `📥 Request body: [données]`
-- `🔒 Hashing password...`
-- `🔍 Storage createUser called with: [username]`
-- `✅ Storage createUser successful: [username]`
-
-## Déploiement
-
-1. Redéployez votre application avec les dernières modifications
-2. Testez les fonctionnalités utilisateur en production
-3. Les logs montreront si le mode fallback est utilisé pour les groupes
-
-## Logs de Débogage
-
-En production, vous verrez :
-- `⚠️ Production mode: user_groups table missing created_at column, inserting without it` si la colonne n'existe pas
-- Aucun message si la table a été mise à jour avec la colonne manquante
-
-Ces corrections garantissent la compatibilité dans tous les environnements sans casser la fonctionnalité.
\ No newline at end of file
diff --git a/PRODUCTION-FIXES-FINAL.md b/PRODUCTION-FIXES-FINAL.md
deleted file mode 100644
index 912e6dd..0000000
--- a/PRODUCTION-FIXES-FINAL.md
+++ /dev/null
@@ -1,133 +0,0 @@
-# CORRECTIONS FINALES POUR SERVEUR DE PRODUCTION
-# Erreurs 403 Employés - Version Corrigée
-
-## ⚠️ CLARIFICATION IMPORTANTE
-**Les employés ne doivent PAS créer de tâches, seulement les voir**
-
-## CORRECTIONS À APPLIQUER SUR VOTRE SERVEUR PRIVÉ
-
-### 1️⃣ FICHIER: client/src/pages/Tasks.tsx
-**Correction erreur 403 /api/users**
-
-#### A) Ligne 84-85 (requête des utilisateurs):
-```typescript
-// REMPLACER:
-enabled: !!user,
-
-// PAR:
-enabled: !!user && (user.role === 'admin' || user.role === 'manager' || user.role === 'directeur'),
-```
-
-### 2️⃣ FICHIER: server/routes.ts
-**Les permissions dans shared/permissions.ts restent inchangées**
-
-#### A) Route GET /api/suppliers (environ ligne 188-194):
-```typescript
-// REMPLACER:
-if (!user || (user.role !== 'admin' && user.role !== 'manager')) {
- return res.status(403).json({ message: "Insufficient permissions" });
-}
-
-// PAR:
-if (!user || (user.role !== 'admin' && user.role !== 'manager' && user.role !== 'directeur' && user.role !== 'employee')) {
- return res.status(403).json({ message: "Insufficient permissions" });
-}
-```
-
-#### B) Route POST /api/suppliers (environ ligne 240-242):
-```typescript
-// REMPLACER:
-if (user.role !== 'admin' && user.role !== 'manager') {
- console.error('❌ Insufficient permissions:', { userRole: user.role, required: ['admin', 'manager'] });
- return res.status(403).json({ message: "Insufficient permissions" });
-}
-
-// PAR:
-if (user.role !== 'admin' && user.role !== 'manager' && user.role !== 'directeur') {
- console.error('❌ Insufficient permissions:', { userRole: user.role, required: ['admin', 'manager', 'directeur'] });
- return res.status(403).json({ message: "Insufficient permissions" });
-}
-```
-
-#### C) Route PUT /api/suppliers/:id (environ ligne 281-283):
-```typescript
-// REMPLACER:
-if (!user || (user.role !== 'admin' && user.role !== 'manager')) {
- return res.status(403).json({ message: "Insufficient permissions" });
-}
-
-// PAR:
-if (!user || (user.role !== 'admin' && user.role !== 'manager' && user.role !== 'directeur')) {
- return res.status(403).json({ message: "Insufficient permissions" });
-}
-```
-
-#### D) Route DELETE /api/suppliers/:id (environ ligne 298-300):
-```typescript
-// REMPLACER:
-if (!user || (user.role !== 'admin' && user.role !== 'manager')) {
- return res.status(403).json({ message: "Insufficient permissions" });
-}
-
-// PAR:
-if (!user || (user.role !== 'admin' && user.role !== 'directeur')) {
- return res.status(403).json({ message: "Insufficient permissions" });
-}
-```
-
-#### E) Route POST /api/dlc-products/:id/validate (environ ligne 2332-2334):
-```typescript
-// REMPLACER:
-if (!user || !['admin', 'manager'].includes(user.role)) {
- return res.status(403).json({ message: "Insufficient permissions to validate products" });
-}
-
-// PAR:
-if (!user || !['admin', 'manager', 'directeur'].includes(user.role)) {
- return res.status(403).json({ message: "Insufficient permissions to validate products" });
-}
-```
-
-## 📋 ÉTAPES D'APPLICATION SIMPLIFIÉES
-
-1. **Sauvegarde** (sur votre serveur de production):
-```bash
-cp server/routes.ts server/routes.ts.backup
-```
-
-2. **Modification**: Ouvrez `server/routes.ts` et effectuez les 5 corrections ci-dessus
-
-3. **Redémarrage**: Redémarrez votre serveur Node.js
-
-4. **Test**: Testez avec un compte employé
-
-## ✅ RÉSULTAT ATTENDU
-
-- ✅ Employés peuvent voir les fournisseurs (modules Commandes Client et DLC)
-- ✅ Employés peuvent voir la page tâches et les tâches existantes
-- ❌ Employés ne peuvent PAS créer de tâches (comportement inchangé)
-- ✅ Directeurs peuvent valider les produits DLC
-- ✅ Plus d'erreurs 403 sur les actions autorisées
-
-## 🔍 PERMISSIONS FINALES PAR RÔLE
-
-### Employés:
-- **Fournisseurs**: Lecture seulement
-- **Tâches**: Lecture seulement (voir page et tâches)
-- **Commandes Client**: Voir + Créer
-- **DLC**: Voir + Créer
-
-### Problème Résolu:
-Les erreurs 403 venaient principalement des restrictions d'accès aux **fournisseurs**, pas des tâches. Les employés ont besoin de voir les fournisseurs pour créer des commandes client et des produits DLC.
-
-## 🧪 COMMANDE DE TEST POST-CORRECTION
-
-```bash
-# Test accès fournisseurs pour employé (doit fonctionner):
-curl -X GET "https://votre-serveur.com/api/suppliers" \
- -H "Cookie: session=TOKEN_SESSION_EMPLOYE"
-
-# Résultat attendu: HTTP 200 avec liste des fournisseurs
-```
-
-**Note**: Les permissions des tâches restent inchangées - les employés peuvent seulement voir les tâches, pas les créer.
\ No newline at end of file
diff --git a/PRODUCTION-GROUPID-FIX-URGENT.md b/PRODUCTION-GROUPID-FIX-URGENT.md
deleted file mode 100644
index f2e4554..0000000
--- a/PRODUCTION-GROUPID-FIX-URGENT.md
+++ /dev/null
@@ -1,66 +0,0 @@
-# Fix Urgent Production - GroupId Magasin #2 → #1
-
-## Problème Production Confirmé
-
-Utilisateur production assigné au magasin #2 (Houdemont) :
-```
-group_id: 2,
-group_name: 'Houdemont'
-```
-
-**MAIS** : DLC et commandes client créées pour magasin #1 malgré le fix backend.
-
-## Cause Probable
-
-Les logs production montrent que l'utilisateur a bien `group_id: 2` dans la base, mais la structure de données `user.userGroups` en production peut être différente du développement.
-
-## Fix Appliqué
-
-### 1. Debug Logs Production Renforcés
-```javascript
-console.log("🔍 DLC GroupId Debug Production:", {
- originalGroupId: req.body.groupId,
- userGroups: user.userGroups?.map(ug => ({
- groupId: ug.groupId,
- groupName: ug.group?.name,
- rawGroup: ug.group
- })),
- userGroupsLength: user.userGroups?.length,
- firstUserGroup: user.userGroups?.[0]
-});
-```
-
-### 2. Accès Alternatif pour Production
-```javascript
-if (user.userGroups?.[0]?.groupId) {
- finalGroupId = user.userGroups[0].groupId;
-} else if (user.userGroups?.[0]?.group?.id) {
- // Alternative access pattern for production
- finalGroupId = user.userGroups[0].group.id;
-} else {
- finalGroupId = 1; // Emergency fallback
-}
-```
-
-## Hypothèses Production
-
-1. **Structure différente** : `user.userGroups[0].group.id` au lieu de `user.userGroups[0].groupId`
-2. **Mapping manquant** : Les relations ne sont pas correctement chargées en production
-3. **Cache production** : Les données utilisateur ne sont pas à jour
-
-## Actions Requises
-
-1. ✅ **Logs debug renforcés** pour identifier structure exacte
-2. ✅ **Accès alternatif** aux données groupe
-3. 🔄 **Déployer en production**
-4. 🧪 **Tester création DLC/commande avec employé magasin #2**
-5. 📋 **Analyser logs pour identifier structure de données exacte**
-
-## Résultat Attendu
-
-Après déploiement, les logs production révéleront :
-- Structure exacte de `user.userGroups[0]`
-- Chemin d'accès correct pour `groupId`
-- Fix automatique via accès alternatif
-
-**DÉPLOIEMENT PRODUCTION URGENT REQUIS**
\ No newline at end of file
diff --git a/PRODUCTION-GROUPID-FRONTEND-FIX-FINAL.md b/PRODUCTION-GROUPID-FRONTEND-FIX-FINAL.md
deleted file mode 100644
index 90198a0..0000000
--- a/PRODUCTION-GROUPID-FRONTEND-FIX-FINAL.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Fix Final Frontend - GroupId Production
-
-## Problème Identifié en Production
-
-Les logs production montrent clairement :
-- ✅ **Utilisateur assigné groupe #2** : `group_id: 2, group_name: 'Houdemont'`
-- ✅ **API DLC lit correctement** : `userGroups: [ { groupId: 2, groupName: 'Houdemont' } ]`
-- ❌ **Création utilise groupId: 1** au lieu du groupe assigné
-
-## Cause Exacte
-
-Le frontend ne priorise pas correctement le groupe assigné lors de la création. La logique donnait priorité à `selectedStoreId` (admin) avant le groupe assigné de l'utilisateur.
-
-## Fix Appliqué
-
-### 1. DLC Page - Nouvelle Priorité
-```javascript
-// AVANT (Problématique)
-if (user?.role === 'admin' && selectedStoreId) {
- groupId = selectedStoreId; // Admin prioritaire
-} else if (user?.userGroups?.[0]?.groupId) {
- groupId = user.userGroups[0].groupId; // Groupe utilisateur second
-}
-
-// APRÈS (Corrigé)
-if (user?.userGroups?.[0]?.groupId) {
- // PRIORITÉ ABSOLUE: groupe assigné utilisateur
- groupId = user.userGroups[0].groupId;
-} else if (user?.role === 'admin' && selectedStoreId) {
- // Admin seulement si pas de groupe assigné
- groupId = selectedStoreId;
-}
-```
-
-### 2. Customer Order Form - Même Logique
-```javascript
-// Même priorité dans les deux endroits:
-// 1. user.userGroups[0].groupId (PRIORITÉ)
-// 2. admin selectedStoreId
-// 3. fallbacks...
-```
-
-### 3. Formulaire Default Value Fix
-```javascript
-// AVANT
-groupId: order?.groupId || (user?.role === 'admin' && selectedStoreId ? selectedStoreId : user?.userGroups?.[0]?.groupId) || 1
-
-// APRÈS
-groupId: order?.groupId || (user?.userGroups?.[0]?.groupId || (user?.role === 'admin' && selectedStoreId ? selectedStoreId : 1))
-```
-
-## Logique de Priorité Unifiée
-
-**PARTOUT DANS L'APPLICATION :**
-1. 🎯 **Groupe assigné utilisateur** (`user.userGroups[0].groupId`) - **PRIORITÉ ABSOLUE**
-2. 🏪 **Admin store selection** (`selectedStoreId`) - Si pas de groupe assigné
-3. 📋 **Premier groupe disponible** - Fallback admin
-4. 🚨 **groupId = 1** - Urgence
-
-## Résultat Attendu Production
-
-Employé assigné magasin #2 (Houdemont) :
-- ✅ **DLC création** → `groupId: 2` (groupe assigné prioritaire)
-- ✅ **Commande client** → `groupId: 2` (groupe assigné prioritaire)
-- ✅ **Cohérence** avec les autres modules qui fonctionnent déjà
-
-**DÉPLOIEMENT PRODUCTION IMMÉDIAT REQUIS**
\ No newline at end of file
diff --git a/PRODUCTION-SCHEMA-UPDATE.sql b/PRODUCTION-SCHEMA-UPDATE.sql
deleted file mode 100644
index 9874ccd..0000000
--- a/PRODUCTION-SCHEMA-UPDATE.sql
+++ /dev/null
@@ -1,39 +0,0 @@
--- =============================================
--- PRODUCTION SCHEMA UPDATE - Groups NocoDB Configuration
--- Date: 2025-08-12
--- Description: Synchronise le schéma production avec les nouveaux champs NocoDB
--- =============================================
-
--- Retirer le champ nocodbTableId qui n'est plus nécessaire
-ALTER TABLE groups DROP COLUMN IF EXISTS "nocodb_table_id";
-
--- Ajouter les nouveaux champs de configuration NocoDB par magasin
-ALTER TABLE groups ADD COLUMN IF NOT EXISTS "nocodb_bl_column_name" VARCHAR;
-ALTER TABLE groups ADD COLUMN IF NOT EXISTS "nocodb_amount_column_name" VARCHAR;
-ALTER TABLE groups ADD COLUMN IF NOT EXISTS "nocodb_supplier_column_name" VARCHAR;
-ALTER TABLE groups ADD COLUMN IF NOT EXISTS "webhook_url" VARCHAR(500);
-
--- Modifier la colonne color pour avoir une valeur par défaut (si elle n'en a pas déjà une)
-ALTER TABLE groups ALTER COLUMN color SET DEFAULT '#1976D2';
-
--- Ajout de commentaires pour documentation
-COMMENT ON COLUMN groups.color IS 'Couleur hex du groupe, par défaut #1976D2';
-COMMENT ON COLUMN groups.nocodb_table_name IS 'Nom de la table NocoDB spécifique au magasin';
-COMMENT ON COLUMN groups.invoice_column_name IS 'Nom de la colonne facture dans la table NocoDB du magasin';
-COMMENT ON COLUMN groups.nocodb_bl_column_name IS 'Nom de la colonne BL dans la table NocoDB du magasin';
-COMMENT ON COLUMN groups.nocodb_amount_column_name IS 'Nom de la colonne montant dans la table NocoDB du magasin';
-COMMENT ON COLUMN groups.nocodb_supplier_column_name IS 'Nom de la colonne fournisseur dans la table NocoDB du magasin';
-COMMENT ON COLUMN groups.webhook_url IS 'URL webhook pour notifications spécifiques au magasin';
-
--- Vérification du schéma final
-SELECT
- column_name,
- data_type,
- is_nullable,
- column_default,
- col_description(pg_class.oid, ordinal_position) as column_comment
-FROM information_schema.columns
-JOIN pg_class ON pg_class.relname = table_name
-WHERE table_name = 'groups'
- AND table_schema = 'public'
-ORDER BY ordinal_position;
\ No newline at end of file
diff --git a/PRODUCTION-STORAGE-DEBUG-URGENT.md b/PRODUCTION-STORAGE-DEBUG-URGENT.md
deleted file mode 100644
index df0d004..0000000
--- a/PRODUCTION-STORAGE-DEBUG-URGENT.md
+++ /dev/null
@@ -1,66 +0,0 @@
-# Debug Production Storage - GroupId Mystery
-
-## Problème Production
-
-Utilisateur assigné magasin #2 crée DLC/commandes → apparaît magasin #1
-
-## Analyse Couche Storage
-
-Il y a 2 implémentations storage :
-
-### 1. MemStorage (Développement)
-```javascript
-async createDlcProduct(dlcProduct: any): Promise {
- const newProduct = { id, ...dlcProduct, createdAt, updatedAt };
- // Enregistre directement les données passées
-}
-```
-
-### 2. Drizzle ORM (Production)
-```javascript
-async createDlcProduct(dlcProductData: InsertDlcProductFrontend): Promise {
- const { dlcDate, ...restData } = dlcProductData as any;
- const [dlcProduct] = await db.insert(dlcProducts).values({
- ...restData, // ⚠️ SI restData.groupId = 1, il sera enregistré tel quel
- expiryDate: dlcDate,
- });
-}
-```
-
-## Hypothèses du Problème
-
-1. **Frontend envoie groupId: 1** malgré les corrections
-2. **Backend force finalGroupId: 2** mais quelque chose le rechange
-3. **Storage reçoit groupId: 1** et l'enregistre tel quel
-4. **Base de données a une contrainte/trigger** qui force groupId: 1
-
-## Debug Ajouté
-
-### 1. Logs Storage Drizzle (Production)
-```javascript
-console.log("🔍 STORAGE DEBUG - DLC insertData:", insertData);
-console.log("🔍 STORAGE DEBUG - DLC insertData.groupId:", insertData.groupId, typeof insertData.groupId);
-console.log("🔍 STORAGE DEBUG - DLC returned from DB:", dlcProduct);
-console.log("🔍 STORAGE DEBUG - DLC returned groupId:", dlcProduct.groupId, typeof dlcProduct.groupId);
-```
-
-### 2. Même Logs pour Customer Orders
-
-## Plan de Debug Production
-
-1. ✅ **Logs routse backend** - Voir finalGroupId calculé
-2. ✅ **Logs storage layer** - Voir données envoyées à DB
-3. ✅ **Logs retour DB** - Voir ce que la DB retourne
-4. 🔄 **Déployer en production**
-5. 🧪 **Tester création DLC/commande avec employé magasin #2**
-6. 📋 **Analyser logs complets pour identifier où groupId change**
-
-## Résultat Attendu
-
-Les logs révéleront :
-- Frontend calcule-t-il groupId: 2 ?
-- Backend force-t-il finalGroupId: 2 ?
-- Storage reçoit-il groupId: 2 ?
-- DB retourne-t-elle groupId: 1 ou 2 ?
-
-**POINT DE RUPTURE IDENTIFIÉ = PROBLÈME RÉSOLU**
\ No newline at end of file
diff --git a/REACT-ERROR-310-FINAL-FIX.md b/REACT-ERROR-310-FINAL-FIX.md
deleted file mode 100644
index 759126a..0000000
--- a/REACT-ERROR-310-FINAL-FIX.md
+++ /dev/null
@@ -1,45 +0,0 @@
-# React Error #310 - Correction Définitive
-
-## Problème Identifié
-L'erreur React #310 en production était causée par l'utilisation de `React.` dans les composants shadcn/ui au lieu d'importer directement les hooks React. Cela pose problème lors de la minification/bundling en production.
-
-## Corrections Appliquées
-
-### 1. Button.tsx
-- **Avant :** `import * as React from "react"` + `React.forwardRef`
-- **Après :** `import React, { forwardRef } from "react"` + `forwardRef`
-
-### 2. Tabs.tsx
-- **Avant :** `import * as React from "react"` + `React.forwardRef`
-- **Après :** `import React, { forwardRef } from "react"` + `forwardRef`
-- Corrigé pour : `TabsList`, `TabsTrigger`, `TabsContent`
-
-### 3. Input.tsx
-- **Avant :** `import * as React from "react"` + `React.forwardRef`
-- **Après :** `import React, { forwardRef } from "react"` + `forwardRef`
-
-### 4. Badge.tsx
-- **Avant :** `import * as React from "react"`
-- **Après :** `import React from "react"`
-
-## Composants Corrigés
-Ces corrections ciblent uniquement les composants utilisés dans la page `BLReconciliation.tsx` :
-- ✅ Button
-- ✅ Input
-- ✅ Badge
-- ✅ Tabs (TabsContent, TabsList, TabsTrigger)
-
-## Impact
-- **Bénéfice :** Résout l'erreur React #310 en production
-- **Sécurité :** Conserve tous les composants shadcn/ui sans utiliser HTML natif
-- **Compatibilité :** Autres modules non affectés, continuent de fonctionner normalement
-
-## Tests Requis
-1. Déployer sur le serveur privé de production
-2. Vérifier que la page de rapprochement se charge sans erreur React #310
-3. Tester toutes les fonctionnalités : pagination, validation, dévalidation, suppression
-4. Confirmer que les autres modules fonctionnent toujours correctement
-
-## Status
-✅ Corrections appliquées en développement
-🔄 En attente de test en production
\ No newline at end of file
diff --git a/REACT-ERROR-310-FIX.md b/REACT-ERROR-310-FIX.md
deleted file mode 100644
index 5f21d98..0000000
--- a/REACT-ERROR-310-FIX.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# Fix React Error #310 - Production Issue
-
-## Problem
-React Error #310 occurs in production due to incorrect React hooks usage.
-The error is: "Minified React error #310" which typically means using `React.useEffect` instead of `useEffect` or other hook import issues.
-
-## Files Fixed
-
-### 1. client/src/hooks/use-toast.ts
-- ✅ Changed `import * as React from "react"` to `import { useState, useEffect, ReactNode } from "react"`
-- ✅ Changed `React.useState` to `useState`
-- ✅ Changed `React.useEffect` to `useEffect`
-- ✅ Changed `React.ReactNode` to `ReactNode`
-
-### 2. client/src/hooks/use-mobile.tsx
-- ✅ Changed `import * as React from "react"` to `import { useState, useEffect } from "react"`
-- ✅ Changed `React.useState` to `useState`
-- ✅ Changed `React.useEffect` to `useEffect`
-
-### 3. client/src/pages/BLReconciliation.tsx
-- ✅ Added proper `useEffect` import
-- ✅ Changed `React.useEffect` to `useEffect`
-- ✅ Removed React.Fragment usage in JSX (this is fine as it's JSX, not hook)
-
-## Status
-All React hook usage issues have been corrected. The pagination system is now implemented with proper React hook imports that should work in production.
-
-## Next Steps
-Deploy to production and test the reconciliation page.
\ No newline at end of file
diff --git a/REACT-ERROR-310-PRODUCTION-FIX-FINAL.md b/REACT-ERROR-310-PRODUCTION-FIX-FINAL.md
deleted file mode 100644
index 66a9933..0000000
--- a/REACT-ERROR-310-PRODUCTION-FIX-FINAL.md
+++ /dev/null
@@ -1,90 +0,0 @@
-# Solution Définitive - React Error #310 Production
-
-## Analyse du Problème
-L'erreur React #310 persistait en production malgré les multiples tentatives de correction des composants shadcn/ui. Le problème était systémique et lié à :
-
-1. **Minification en production** : Les références `React.forwardRef`, `React.useState` etc. posaient problème lors du bundling
-2. **43 composants shadcn/ui affectés** : Une correction partielle ne suffisait pas
-3. **Architecture complexe** : Les interdépendances entre composants shadcn/ui créaient des effets de cascade
-
-## Solution Adoptée : Remplacement Complet par des Composants Robustes
-
-### 🔧 Approche Technique
-**Remplacement de `BLReconciliation.tsx` par une version entièrement autonome :**
-
-- ✅ **Composants UI personnalisés** : `RobustButton`, `RobustInput`, `RobustBadge`, `RobustTabs`
-- ✅ **Imports React standards** : `import { useState, useEffect } from "react"`
-- ✅ **Tailwind CSS direct** : Pas de dépendance shadcn/ui
-- ✅ **Zero références React.\*** : Évite complètement le problème de minification
-
-### 🎯 Fonctionnalités Conservées
-- **Pagination complète** : 20 éléments par page avec "Affichage de X à Y sur Z éléments"
-- **Système de permissions** : Directeur/Admin permissions intactes
-- **Onglets rapprochement** : Manuel vs Automatique
-- **Actions utilisateur** : Valider, Dévalider, Supprimer
-- **Filtrage/Recherche** : Par fournisseur, BL, facture
-- **Design cohérent** : Interface visuelle identique
-
-### 🏗️ Architecture des Composants Robustes
-
-#### RobustButton
-```tsx
-const RobustButton = ({ children, onClick, disabled, variant, size, className, title }) => {
- // Utilise Tailwind CSS directement, pas de forwardRef
- // Variants: default, ghost, outline, destructive
-}
-```
-
-#### RobustPagination
-```tsx
-const RobustPagination = ({ currentPage, totalPages, onPageChange, totalItems, itemsPerPage }) => {
- // Pagination native "Affichage de X à Y sur Z éléments"
- // Boutons Précédent/Suivant avec icônes
-}
-```
-
-### 📁 Fichiers Modifiés
-- `client/src/pages/BLReconciliation.tsx` → **Version robuste complète**
-- `client/src/pages/BLReconciliation_shadcn_broken.tsx` → **Ancienne version sauvegardée**
-
-### 🚀 Avantages de cette Solution
-
-1. **Élimination totale du risque** : Plus de dépendance shadcn/ui pour cette page
-2. **Performance optimisée** : Moins de dépendances, bundling plus léger
-3. **Maintenabilité** : Code plus simple et prévisible
-4. **Compatibilité garantie** : Fonctionne avec tous les bundlers
-5. **Design cohérent** : Interface utilisateur identique à l'original
-
-### 🔍 Points de Contrôle
-
-**Avant déploiement, vérifier :**
-- [ ] Page se charge sans erreur React #310
-- [ ] Pagination fonctionne (20 items par page)
-- [ ] Onglets Manuel/Automatique switchent correctement
-- [ ] Boutons Valider/Dévalider/Supprimer fonctionnent
-- [ ] Permissions respectées selon rôle utilisateur
-- [ ] Design cohérent avec le reste de l'application
-
-### 📊 Impact Technique
-
-**Réduction des dépendances :**
-- ❌ `@radix-ui/react-tabs`
-- ❌ `@radix-ui/react-dialog`
-- ❌ `@radix-ui/react-button`
-- ✅ **Tailwind CSS uniquement**
-
-**Amélioration des performances :**
-- Bundle plus léger (-15% pour cette page)
-- Temps de chargement réduit
-- Élimination des re-renders inutiles
-
-## Conclusion
-
-Cette solution **élimine définitivement** l'erreur React #310 en remplaçant l'architecture problématique par des composants robustes et autonomes. L'approche garantit :
-
-- **Stabilité en production** : Zero risque d'erreur React #310
-- **Fonctionnalités intactes** : Toutes les features métier conservées
-- **Design cohérent** : Expérience utilisateur identique
-- **Maintenabilité** : Code plus simple et prévisible
-
-**Status : ✅ Solution prête pour déploiement en production**
\ No newline at end of file
diff --git a/README.md b/README.md
deleted file mode 100644
index addb04c..0000000
--- a/README.md
+++ /dev/null
@@ -1,200 +0,0 @@
-# LogiFlow - Plateforme de Gestion Logistique
-
-LogiFlow est une application web complète de gestion logistique conçue spécialement pour les magasins de la chaîne La Foir'Fouille. Elle centralise la gestion des commandes, livraisons, stocks, utilisateurs et bien plus à travers une interface moderne et intuitive.
-
-## 🎯 Fonctionnalités Principales
-
-### 📦 Gestion des Commandes et Livraisons
-- **Commandes Fournisseurs** : Création, suivi et gestion des commandes avec planification des dates de livraison
-- **Livraisons** : Suivi des livraisons avec statuts (en attente, planifiée, livrée) et gestion des bons de livraison
-- **Réconciliation BL** : Rapprochement automatique entre bons de livraison et factures
-- **Tableau de Bord** : Vue d'ensemble avec statistiques en temps réel
-
-### 🏪 Gestion Multi-Magasins
-- **Sélection de Magasin** : Interface permettant de filtrer les données par magasin
-- **Magasins Personnalisés** : Support des magasins "Frouard" et "Houdemont"
-- **Permissions par Magasin** : Contrôle d'accès granulaire selon les magasins assignés
-
-### 📅 Gestion DLC (Dates Limites de Consommation)
-- **Suivi des Produits** : Gestion des produits avec dates d'expiration (DLC, DDM, DLUO)
-- **Alertes Automatiques** : Notifications pour produits expirant sous 15 jours
-- **Filtres Avancés** : Tri par statut (validés, expire bientôt, expirés)
-- **Génération de Codes** : Support des codes EAN13 pour les produits
-- **Impression** : Rapports PDF des produits expirant bientôt ou expirés
-
-### 👥 Gestion des Utilisateurs et Rôles
-- **Système de Rôles** : 4 rôles (Admin, Manager, Employé, Directeur) avec 54 permissions
-- **Permissions Granulaires** : Contrôle d'accès précis pour chaque fonctionnalité
-- **Interface de Gestion** : Assignation et modification des permissions en temps réel
-- **Traçabilité** : Suivi des actions utilisateurs
-
-### 📋 Gestion des Tâches
-- **Planification** : Création et assignation de tâches avec dates d'échéance
-- **Calendrier Intégré** : Vue calendrier pour la planification des tâches
-- **Suivi de Progression** : Statuts et validation des tâches terminées
-- **Filtres** : Tri par priorité, statut et dates
-
-### 🛒 Commandes Clients
-- **Point de Vente** : Gestion des commandes clients avec génération de codes-barres
-- **Suivi Livraison** : Statuts de préparation et livraison
-- **Historique** : Archive complète des commandes clients
-
-### 📢 Gestion des Publicités
-- **Campagnes Marketing** : Planification et suivi des campagnes publicitaires
-- **Participation Magasins** : Gestion de la participation par magasin
-- **Calendrier** : Vue hebdomadaire et mensuelle des campagnes
-
-## 🛠️ Technologies Utilisées
-
-### Frontend
-- **React 18** avec TypeScript pour une interface moderne et typée
-- **Vite** pour un développement rapide et des builds optimisés
-- **Shadcn/ui** composants UI modernes basés sur Radix UI
-- **Tailwind CSS** pour un design responsive et cohérent
-- **TanStack Query** pour la gestion d'état serveur
-- **Wouter** pour le routage léger
-- **React Hook Form + Zod** pour la validation des formulaires
-
-### Backend
-- **Express.js** avec TypeScript pour l'API REST
-- **PostgreSQL** base de données relationnelle robuste
-- **Drizzle ORM** pour les requêtes typées et sécurisées
-- **Passport.js** pour l'authentification locale et production
-- **Express Sessions** avec stockage PostgreSQL
-
-### Infrastructure
-- **Docker** pour le déploiement en production
-- **Replit** pour le développement collaboratif
-- **Environment adaptatif** : détection automatique développement/production
-
-## 🚀 Installation et Démarrage
-
-### Prérequis
-- Node.js 18+
-- PostgreSQL
-- npm ou yarn
-
-### Installation
-```bash
-# Cloner le projet
-git clone [url-du-projet]
-cd logiflow
-
-# Installer les dépendances
-npm install
-
-# Configurer la base de données
-cp .env.example .env
-# Modifier DATABASE_URL dans .env
-
-# Démarrer l'application
-npm run dev
-```
-
-L'application sera accessible sur `http://localhost:5000`
-
-### Comptes par Défaut
-- **Administrateur** : admin / admin
-- **Base de données** : Initialisation automatique avec données de test
-
-## 🔐 Système de Permissions
-
-L'application dispose d'un système de permissions granulaire avec 54 permissions réparties en 12 catégories :
-
-### Catégories de Permissions
-- **Tableau de Bord** : Accès aux statistiques et vues d'ensemble
-- **Magasins** : Gestion des magasins et groupes
-- **Fournisseurs** : Gestion des contacts fournisseurs
-- **Commandes** : Création et suivi des commandes
-- **Livraisons** : Gestion des livraisons et réceptions
-- **Publicités** : Campagnes marketing et communication
-- **Commandes Clients** : Point de vente et suivi client
-- **Gestion DLC** : Suivi des dates d'expiration
-- **Gestion des Tâches** : Planification et suivi des tâches
-- **Utilisateurs** : Gestion des comptes utilisateurs
-- **Gestion des Rôles** : Administration des permissions
-- **Administration** : Configuration système et maintenance
-
-### Rôles Prédéfinis
-- **Admin** : Accès complet à toutes les fonctionnalités
-- **Directeur** : Accès étendu avec supervision multi-magasins
-- **Manager** : Gestion opérationnelle d'un magasin
-- **Employé** : Accès aux opérations quotidiennes
-
-## 📊 Fonctionnalités Avancées
-
-### Pagination Intelligente
-- **Pagination adaptative** : 10 éléments pour les vues détaillées, 20 pour les vues de synthèse
-- **Filtres intégrés** : Recherche et tri sans perte de pagination
-- **Performance optimisée** : Pagination côté client pour la réactivité
-
-### Système de Logs
-- **Traçabilité complète** : Logs détaillés pour toutes les opérations critiques
-- **Debug en production** : Outils de diagnostic intégrés
-- **Monitoring** : Suivi des performances et erreurs
-
-### Sécurité
-- **Authentification robuste** : Support développement (Replit Auth) et production (local)
-- **Hachage sécurisé** : PBKDF2 pour les mots de passe
-- **Sessions sécurisées** : Stockage PostgreSQL avec rotation automatique
-- **Validation stricte** : Zod pour la validation côté client et serveur
-
-## 🗂️ Structure du Projet
-
-```
-logiflow/
-├── client/ # Frontend React
-│ ├── src/
-│ │ ├── components/ # Composants réutilisables
-│ │ ├── pages/ # Pages de l'application
-│ │ ├── hooks/ # Hooks personnalisés
-│ │ └── lib/ # Utilitaires et configuration
-├── server/ # Backend Express
-│ ├── routes.ts # Routes API principales
-│ ├── storage.ts # Interface de stockage
-│ └── auth/ # Système d'authentification
-├── shared/ # Code partagé frontend/backend
-│ └── schema.ts # Schémas de données Drizzle
-└── migrations/ # Migrations de base de données
-```
-
-## 🔧 Configuration
-
-### Variables d'Environnement
-```env
-DATABASE_URL=postgresql://user:password@localhost:5432/logiflow
-SESSION_SECRET=your-session-secret-key
-NODE_ENV=development|production
-```
-
-### Déploiement Production
-```bash
-# Build de production
-npm run build
-
-# Démarrage production
-npm run start
-```
-
-## 📈 Métriques et Performance
-
-- **Base de données** : PostgreSQL avec contraintes et index optimisés
-- **Cache intelligent** : TanStack Query avec invalidation automatique
-- **Responsive design** : Interface adaptée mobile et desktop
-- **Accessibilité** : Composants Radix UI conformes WCAG
-
-## 🤝 Contribution
-
-L'application est conçue pour évoluer facilement :
-- **Architecture modulaire** : Ajout simple de nouvelles fonctionnalités
-- **Types TypeScript** : Sécurité et auto-complétion complètes
-- **Tests intégrés** : Validation automatique des modifications
-- **Documentation** : Code auto-documenté avec TypeScript
-
-## 📝 Licence
-
-Application propriétaire développée pour Frodis.
-
----
-
-**LogiFlow** - Optimisation logistique pour un commerce moderne
diff --git a/RECONCILIATION-MODAL-FIX.md b/RECONCILIATION-MODAL-FIX.md
deleted file mode 100644
index 477ebf2..0000000
--- a/RECONCILIATION-MODAL-FIX.md
+++ /dev/null
@@ -1,110 +0,0 @@
-# Fix Rapprochement - Restrictions Édition
-
-## 🎯 Demandes Utilisateur
-
-1. **Les rapprochements validés ne peuvent plus être édités**
-2. **Ajouter bouton supprimer pour les admins** (onglet automatique)
-
-## ✅ Corrections Appliquées
-
-### 1. **Onglet Manuel** - Édition Restreinte
-```typescript
-// Avant : Bouton modifier toujours disponible
- handleOpenModal(delivery)}>
-
-
-
-// Après : Modifier seulement si non validé
-{!delivery.reconciled && (
- handleOpenModal(delivery)}>
-
-
-)}
-```
-
-### 2. **Onglet Automatique** - Boutons Admin
-```typescript
-// Avant : Seulement modifier + dévalider
-
- handleOpenModal(delivery)}>Modifier
- {admin && Dévalider }
-
-
-// Après : Supprimer + édition restreinte
-
- {admin && delivery.reconciled && Dévalider }
- {admin && Supprimer }
- {!delivery.reconciled && Modifier }
-
-```
-
-## 🔒 Logique des Boutons par État
-
-### **Rapprochement Non Validé** (`delivery.reconciled = false`)
-- ✅ **Modifier** : Disponible pour tous les rôles autorisés
-- ✅ **Valider** : Disponible selon permissions
-- ✅ **Supprimer** : Admin uniquement
-
-### **Rapprochement Validé** (`delivery.reconciled = true`)
-- ❌ **Modifier** : BLOQUÉ (plus d'édition possible)
-- ✅ **Dévalider** : Admin uniquement
-- ✅ **Supprimer** : Admin uniquement
-
-## 🎨 Interface Utilisateur
-
-### États Visuels
-```css
-/* Non validé */
-bg-white (normal) ou bg-red-50 (problème)
-
-/* Validé */
-bg-gray-100 opacity-60 text-gray-500 (grisé)
-```
-
-### Boutons par Onglet
-
-#### **Manuel**
-- Non validé : `[Valider] [Supprimer] [Modifier]`
-- Validé : `[Dévalider] [Supprimer]` (admin) ou `[]` (autres)
-
-#### **Automatique**
-- Non validé : `[Modifier]`
-- Validé : `[Dévalider] [Supprimer]` (admin) ou `[]` (autres)
-
-## 🔧 Imports Requis
-
-```typescript
-import { Trash2, Ban, Settings, Check } from 'lucide-react';
-```
-
-## 🧪 Tests de Validation
-
-### Test 1 : Édition Restreinte
-1. Créer une livraison
-2. **Vérifier** : Bouton modifier visible
-3. Valider le rapprochement
-4. **Vérifier** : Bouton modifier DISPARU
-5. **Vérifier** : Ligne grisée
-
-### Test 2 : Boutons Admin (Automatique)
-1. Se connecter comme admin
-2. Aller sur onglet "Automatique"
-3. **Vérifier** : Bouton supprimer visible
-4. **Vérifier** : Dévalider visible si validé
-5. **Vérifier** : Modifier visible si non validé
-
-### Test 3 : Permissions Non-Admin
-1. Se connecter comme manager/directeur
-2. **Vérifier** : Pas de bouton supprimer
-3. **Vérifier** : Pas de bouton dévalider
-4. **Vérifier** : Modifier visible si non validé
-
-## 📊 Status
-
-- ✅ Édition bloquée pour rapprochements validés
-- ✅ Bouton supprimer ajouté pour admins (automatique)
-- ✅ Logique cohérente entre onglets manuel/automatique
-- ✅ Permissions respectées selon le rôle
-- ✅ Interface claire avec grisage des validés
-
-**Les rapprochements validés sont maintenant protégés contre l'édition !**
\ No newline at end of file
diff --git a/REMOVE-SYNC-BUTTON-PRODUCTION.md b/REMOVE-SYNC-BUTTON-PRODUCTION.md
deleted file mode 100644
index 893c69b..0000000
--- a/REMOVE-SYNC-BUTTON-PRODUCTION.md
+++ /dev/null
@@ -1,90 +0,0 @@
-# Suppression du Bouton "Sync Status" - Production
-
-## Modifications à Appliquer sur Votre Serveur de Production
-
-Pour supprimer le bouton "Sync Status" qui n'est plus nécessaire avec la synchronisation automatique :
-
-### Fichier : `client/src/pages/Calendar.tsx`
-
-#### 1. Supprimer le bouton "Sync Status"
-**Localisez et supprimez (lignes ~319-329) :**
-```typescript
-{user?.role === 'admin' && (
-
-
- {isSyncing ? 'Sync...' : 'Sync Status'}
-
-)}
-```
-
-#### 2. Supprimer la variable d'état isSyncing
-**Localisez et supprimez :**
-```typescript
-const [isSyncing, setIsSyncing] = useState(false);
-```
-
-#### 3. Supprimer la fonction handleSyncOrderDeliveryStatus
-**Localisez et supprimez toute la fonction (environ 100 lignes) :**
-```typescript
-// Fonction pour synchroniser les statuts commandes/livraisons
-const handleSyncOrderDeliveryStatus = async () => {
- // ... toute la fonction complète
-};
-```
-
-## Étapes de Déploiement
-
-### 1. Sauvegarde
-```bash
-cp client/src/pages/Calendar.tsx client/src/pages/Calendar.tsx.backup
-```
-
-### 2. Application des Modifications
-Éditez le fichier `client/src/pages/Calendar.tsx` et appliquez les trois suppressions ci-dessus.
-
-### 3. Reconstruction du Frontend
-```bash
-# Si vous utilisez un build process
-npm run build
-# ou
-yarn build
-
-# Si vous utilisez Vite en production
-npm run build && npm run preview
-```
-
-### 4. Redémarrage de l'Application
-```bash
-# Via PM2
-pm2 restart your-app-name
-
-# Via systemctl
-sudo systemctl restart your-service
-
-# Via Docker
-docker-compose restart
-```
-
-## Vérification
-
-Après déploiement :
-- Le bouton "Sync Status" ne devrait plus apparaître dans l'interface
-- La synchronisation automatique fonctionnera toujours (lors des validations de livraisons)
-- L'interface sera plus propre et simplifiée
-
-## Rollback si Nécessaire
-
-```bash
-cp client/src/pages/Calendar.tsx.backup client/src/pages/Calendar.tsx
-# Puis reconstruire et redémarrer
-```
-
----
-
-**Résultat** : Interface calendrier simplifiée sans le bouton de synchronisation manuelle, la synchronisation se fait maintenant automatiquement lors des validations de livraisons.
\ No newline at end of file
diff --git a/ROLLBACK-SOLUTION-REACT-ERROR-310.md b/ROLLBACK-SOLUTION-REACT-ERROR-310.md
deleted file mode 100644
index d9ca374..0000000
--- a/ROLLBACK-SOLUTION-REACT-ERROR-310.md
+++ /dev/null
@@ -1,96 +0,0 @@
-# Rollback Solution - React Error #310
-
-## ✅ Problème Identifié
-L'erreur React #310 en production est apparue **après l'ajout des actions sur les lignes et des 2 onglets**. La version précédente (backup) fonctionnait parfaitement.
-
-## 🔄 Action Effectuée
-**Rollback vers la version fonctionnelle :**
-- `BLReconciliation_backup.tsx` → `BLReconciliation.tsx` (restauré)
-- `BLReconciliation.tsx` récente → `BLReconciliation_recent_broken.tsx` (sauvegardé)
-- Restauration du système de notifications shadcn/ui standard
-
-## 📊 Comparaison des Versions
-
-### Version Backup (Fonctionnelle) - 21KB
-✅ **Caractéristiques :**
-- Interface simple avec 2 onglets (Manuel/Automatique)
-- Actions limitées : Voir détails + Dévalider automatique uniquement
-- Pas de pagination complexe
-- Une seule fonction d'action : `handleDevalidateAutoReconciliation`
-- shadcn/ui standard (Button, Tabs, Badge, Input)
-
-### Version Récente (Cassée) - 35KB
-❌ **Problèmes introduits :**
-- Actions complexes : Valider/Dévalider/Supprimer
-- Système de pagination complet avec mutations multiples
-- Composants UI personnalisés (RobustButton, RobustInput, etc.)
-- Système de permissions complexe
-- Gestion d'états multiples
-
-## 🎯 Fonctionnalités de la Version Restaurée
-
-### Interface
-- ✅ Onglets Manuel vs Automatique
-- ✅ Recherche par fournisseur/BL/facture
-- ✅ Affichage des livraisons avec statut "delivered"
-- ✅ Design cohérent shadcn/ui
-
-### Actions Disponibles
-- ✅ **Voir les détails** (icône œil)
-- ✅ **Dévalider rapprochement automatique** (directeurs/admins uniquement)
-- ✅ Filtrage automatique selon mode fournisseur
-- ✅ Notifications toast
-
-### Permissions
-- ✅ Accès restreint : managers, directeurs, admins uniquement
-- ✅ Actions de dévalidation : directeurs et admins uniquement
-- ✅ Redirection automatique pour employés
-
-## 🚀 Plan de Réimplémentation Progressive
-
-### Phase 1 : Test de la Version Backup ✅
-- [ ] Déployer la version backup en production
-- [ ] Vérifier absence d'erreur React #310
-- [ ] Confirmer fonctionnement des onglets
-- [ ] Tester l'action de dévalidation
-
-### Phase 2 : Ajout Progressif des Fonctionnalités
-1. **Pagination simple** (si nécessaire)
-2. **Action Valider** (une à la fois)
-3. **Action Supprimer** (après validation des précédentes)
-4. **Améliorations UI** (en dernier)
-
-### Phase 3 : Test à Chaque Étape
-- Test en développement
-- Test en production
-- Rollback immédiat si erreur React #310
-
-## 📁 Fichiers de Sauvegarde
-
-```
-client/src/pages/BLReconciliation.tsx # ✅ Version backup restaurée
-client/src/pages/BLReconciliation_recent_broken.tsx # ❌ Version avec erreur React #310
-client/src/pages/BLReconciliation_shadcn_broken.tsx # ❌ Autre version problématique
-client/src/hooks/use-toast-robust.ts # 🔧 Composants robustes (inutilisés)
-client/src/components/ToasterRobust.tsx # 🔧 Composants robustes (inutilisés)
-```
-
-## 🔍 Points de Test Production
-
-**À vérifier immédiatement :**
-- [ ] Page `/bl-reconciliation` se charge sans erreur React #310
-- [ ] Onglets Manuel/Automatique switchent correctement
-- [ ] Recherche fonctionne
-- [ ] Action "Dévalider automatique" fonctionne (directeur/admin)
-- [ ] Notifications s'affichent
-- [ ] Autres modules restent inchangés
-
-## 💡 Conclusion
-
-Cette approche de **rollback progressif** permet de :
-1. **Éliminer immédiatement** l'erreur React #310
-2. **Conserver les fonctionnalités essentielles** du module
-3. **Réajouter les features** de manière contrôlée
-4. **Identifier précisément** quelle modification cause l'erreur
-
-**Status : ✅ Version backup restaurée - Prêt pour test production**
\ No newline at end of file
diff --git a/SOLUTION-DEFINITIVE-REACT-ERROR-310.md b/SOLUTION-DEFINITIVE-REACT-ERROR-310.md
deleted file mode 100644
index 3fd8a06..0000000
--- a/SOLUTION-DEFINITIVE-REACT-ERROR-310.md
+++ /dev/null
@@ -1,122 +0,0 @@
-# Solution Définitive React Error #310 - Production Ready
-
-## ✅ Problème Résolu
-L'erreur React #310 qui affectait uniquement le module de rapprochement BL/Factures est maintenant **complètement éliminée**.
-
-## 🔧 Solution Implémentée
-
-### 1. Remplacement Complet du Module BLReconciliation
-- **Ancien fichier** : `client/src/pages/BLReconciliation.tsx` → sauvegardé en `BLReconciliation_shadcn_broken.tsx`
-- **Nouveau fichier** : Version robuste sans dépendances shadcn/ui problématiques
-
-### 2. Système de Notifications Robuste
-- **Ancien système** : `@/hooks/use-toast` + `@/components/ui/toaster` (shadcn/ui)
-- **Nouveau système** : `@/hooks/use-toast-robust` + `@/components/ToasterRobust` (Tailwind CSS pur)
-
-### 3. Composants UI Personnalisés
-- `RobustButton` : Remplace Button shadcn/ui
-- `RobustInput` : Remplace Input shadcn/ui
-- `RobustBadge` : Remplace Badge shadcn/ui
-- `RobustTabs` : Remplace Tabs shadcn/ui
-- `RobustPagination` : Pagination native avec "Affichage de X à Y sur Z éléments"
-
-## 🎯 Fonctionnalités Conservées à 100%
-
-### Interface Utilisateur
-- ✅ Design identique avec Tailwind CSS
-- ✅ Pagination 20 éléments par page
-- ✅ Onglets Manuel/Automatique
-- ✅ Filtrage par recherche
-- ✅ Coloration des lignes dévalidées (rouge)
-
-### Logique Métier
-- ✅ Permissions strictes (Directeur/Admin uniquement)
-- ✅ Actions : Valider, Dévalider, Supprimer
-- ✅ Rapprochement automatique pour fournisseurs configurés
-- ✅ Rapprochement manuel pour autres fournisseurs
-- ✅ Gestion des BL et factures
-
-### Sécurité & Performance
-- ✅ Système de permissions inchangé
-- ✅ APIs et validations identiques
-- ✅ Performance améliorée (bundle plus léger)
-- ✅ Zero risque d'erreur React #310
-
-## 📁 Fichiers Modifiés
-
-```
-client/src/pages/BLReconciliation.tsx # ✅ Version robuste complète
-client/src/hooks/use-toast-robust.ts # ✅ Notifications robustes
-client/src/components/ToasterRobust.tsx # ✅ Affichage notifications
-client/src/App.tsx # ✅ Remplacement Toaster
-```
-
-## 🚀 Déploiement Production
-
-### 1. Tests Requis
-- [ ] Page `/bl-reconciliation` se charge sans erreur React #310
-- [ ] Connexion admin/directeur fonctionne
-- [ ] Navigation entre onglets Manuel/Automatique
-- [ ] Pagination affiche "Affichage de X à Y sur Z éléments"
-- [ ] Boutons d'action (Valider/Dévalider/Supprimer) fonctionnent
-- [ ] Notifications s'affichent correctement
-- [ ] Autres modules restent inchangés
-
-### 2. Commandes de Déploiement
-```bash
-# Build production
-npm run build
-
-# Test build local
-npm run preview
-
-# Déployer sur serveur privé
-# [commandes spécifiques à votre serveur]
-```
-
-### 3. Rollback si Nécessaire
-En cas de problème, restaurer l'ancienne version :
-```bash
-mv client/src/pages/BLReconciliation_shadcn_broken.tsx client/src/pages/BLReconciliation.tsx
-# Puis redéployer
-```
-
-## 📊 Impact Technique
-
-### Avant (Problématique)
-- ❌ 190+ imports shadcn/ui dans l'app
-- ❌ Erreur React #310 en production sur rapprochement
-- ❌ Composants `React.forwardRef` problématiques
-- ❌ Bundle lourd avec dépendances Radix UI
-
-### Après (Robuste)
-- ✅ Module rapprochement 100% autonome
-- ✅ Zero dépendance shadcn/ui pour cette page
-- ✅ Imports React standards uniquement
-- ✅ Bundle -15% plus léger pour cette fonctionnalité
-- ✅ Compatible avec tous les bundlers
-- ✅ Autres modules intacts
-
-## 🔍 Confirmation Solution
-
-### Développement
-- ✅ Application se lance sans erreur
-- ✅ Page rapprochement charge correctement
-- ✅ Toutes fonctionnalités opérationnelles
-- ✅ Design cohérent avec le reste de l'app
-
-### Production Ready
-- ✅ Code optimisé pour minification
-- ✅ Zero référence React.* problématique
-- ✅ Tailwind CSS pur (compatible)
-- ✅ Notifications robustes fonctionnelles
-
-## 💡 Conclusion
-
-Cette solution **élimine définitivement** l'erreur React #310 en:
-1. **Isolant le problème** : Seul le module rapprochement était affecté
-2. **Remplaçant l'architecture** : Composants robustes sans dépendances problématiques
-3. **Conservant les fonctionnalités** : 100% des features métier préservées
-4. **Optimisant les performances** : Bundle plus léger et plus rapide
-
-**Status Final : ✅ PRODUCTION READY - Erreur React #310 éliminée**
\ No newline at end of file
diff --git a/URGENT-API-FIX.md b/URGENT-API-FIX.md
deleted file mode 100644
index 13a82cc..0000000
--- a/URGENT-API-FIX.md
+++ /dev/null
@@ -1,114 +0,0 @@
-# Fix Urgent - API Enregistrement + Icône
-
-## ✅ Problèmes Identifiés et Corrigés
-
-### 1. **Doublon d'endpoint API** ❌ → ✅
-**Problème :** Deux endpoints `PUT /api/deliveries/:id` (lignes 670 et 766)
-- Premier endpoint : Logique complète (auto-sync + auto-validation)
-- Deuxième endpoint : Simple mise à jour MAIS écrase le premier !
-
-**Solution :**
-- ✅ Supprimé le doublon (ligne 766+)
-- ✅ Conservé le premier avec toute la logique
-- ✅ Ajouté logs debug pour traçabilité
-
-### 2. **Erreurs TypeScript** 🔧 → ✅
-**Problème :** 93 erreurs LSP → 88 erreurs LSP
-- `userGroups` non typé
-- `getSupplier()` n'existe pas
-
-**Solution :**
-- ✅ Cast `(user as any).userGroups?.map()` avec fallback `|| []`
-- ✅ Remplacé `storage.getSupplier()` par `storage.getSuppliers().find()`
-
-### 3. **Icône Interface** 👁️ → ⚙️
-**Changement :** Eye icon → Settings icon comme demandé
-- ✅ Changé dans onglet manuel ET automatique
-- ✅ Tooltip mis à jour : "Modifier les données de rapprochement"
-
-## 🔧 API Endpoint Final
-
-```typescript
-PUT /api/deliveries/:id
-├── 🔒 Authentication + Permissions
-├── 📝 Validation insertDeliverySchema.partial()
-├── 💾 storage.updateDelivery(id, data)
-├── 🔄 Auto-sync Order (si status = 'delivered')
-├── 🤖 Auto-validation Rapprochement (fournisseur automatique)
-└── ✅ Response avec delivery mis à jour
-```
-
-## 🐛 Debug Logs Ajoutés
-
-### Console Backend
-```
-🔄 Updating delivery: { id, data, user }
-✅ Delivery updated successfully: { id, updatedDelivery }
-🔄 Auto-sync: Delivery #X marked as delivered...
-🤖 Auto-reconciliation: Delivery #X from automatic supplier...
-```
-
-### Console Frontend
-```
-Sending update for delivery: X with data: {...}
-Update response: {...}
-```
-
-## 🧪 Tests de Validation
-
-### Test 1 : Enregistrement Modal
-- [ ] Ouvrir modal (icône ⚙️)
-- [ ] Modifier N° BL, montants
-- [ ] Cliquer "Enregistrer"
-- [ ] **Vérifier console :** Logs "🔄 Updating delivery" et "✅ Delivery updated"
-- [ ] Toast "Succès" affiché
-- [ ] Modal se ferme
-- [ ] Données mises à jour dans tableau
-
-### Test 2 : Validation Rapprochement
-- [ ] Modal ouvert avec N° BL renseigné
-- [ ] Cliquer "Valider le rapprochement"
-- [ ] **Vérifier console :** `reconciled: true, validatedAt: ...`
-- [ ] Toast "Succès"
-- [ ] Ligne devient verte (rapproché)
-
-### Test 3 : Auto-validation
-- [ ] Fournisseur en mode automatique
-- [ ] Livraison status "delivered" + N° BL présent
-- [ ] **Vérifier console :** "🤖 Auto-reconciliation"
-- [ ] Rapprochement automatiquement validé
-
-## 🚨 Debug Si Toujours Erreur
-
-### 1. Vérifier Console F12
-```javascript
-// Dans DevTools Network
-PUT /api/deliveries/123
-Status: 200 ✅ ou 4xx/5xx ❌
-Response: {...} ou Error message
-```
-
-### 2. Vérifier Console Serveur
-```bash
-# Rechercher logs
-grep "Updating delivery" logs
-grep "Error updating delivery" logs
-```
-
-### 3. Test API Direct
-```bash
-curl -X PUT /api/deliveries/123 \
- -H "Content-Type: application/json" \
- -d '{"blNumber": "TEST123", "blAmount": 100}'
-```
-
-## 📊 Status
-
-- ✅ Doublon endpoint supprimé
-- ✅ Logs debug ajoutés
-- ✅ Types corrigés (88 erreurs vs 93)
-- ✅ Icône Settings remplace Eye
-- ✅ Modal avec debug console
-- 🔄 **À tester en production**
-
-**L'enregistrement devrait maintenant fonctionner !**
\ No newline at end of file
diff --git a/URGENT-CMD-55-FIX.md b/URGENT-CMD-55-FIX.md
deleted file mode 100644
index f6ce865..0000000
--- a/URGENT-CMD-55-FIX.md
+++ /dev/null
@@ -1,197 +0,0 @@
-# URGENT - Correction CMD-55 et Déploiement Bouton Validation
-
-## Problèmes Identifiés en Production
-
-### 1. Erreur de Modification de Commande
-- **Symptôme** : Toast rouge "Impossible de modifier la commande"
-- **Cause Probable** : Problème de validation ou de permission sur le serveur
-- **Impact** : Les utilisateurs ne peuvent pas modifier les commandes existantes
-
-### 2. Bouton de Validation Manquant
-- **Symptôme** : Pas de bouton "Valider Commande" visible sur les cartes
-- **Cause** : Modifications récentes non déployées sur le serveur de production
-- **Impact** : Impossible de valider CMD-55 directement depuis le calendrier
-
-## Solutions Immédiates
-
-### A. Pour le Problème CMD-55 - Solution SQL Directe
-
-Si vous avez accès à votre base de données PostgreSQL en production, exécutez cette commande SQL immédiatement :
-
-```sql
-UPDATE orders
-SET status = 'delivered', updated_at = NOW()
-WHERE id = 55;
-```
-
-Cette commande marquera directement CMD-55 comme "delivered" dans la base de données.
-
-### B. Déploiement du Bouton de Validation
-
-#### Fichiers à Modifier sur Votre Serveur de Production :
-
-1. **`client/src/components/CalendarGrid.tsx`** - Remplacer tout le contenu par :
-```typescript
-import { format, startOfMonth, endOfMonth, eachDayOfInterval, isSameDay, isSameMonth, isToday } from "date-fns";
-import { fr } from "date-fns/locale";
-import { safeDate } from "@/lib/dateUtils";
-import { Plus, Check, CheckCircle } from "lucide-react";
-import { Button } from "@/components/ui/button";
-import { useToast } from "@/hooks/use-toast";
-import type { OrderWithRelations, DeliveryWithRelations } from "@shared/schema";
-
-interface CalendarGridProps {
- currentDate: Date;
- orders: OrderWithRelations[];
- deliveries: DeliveryWithRelations[];
- onDateClick: (date: Date) => void;
- onItemClick: (item: any, type: 'order' | 'delivery') => void;
- user?: { role: string } | null;
- onOrderValidated?: () => void;
-}
-
-export default function CalendarGrid({
- currentDate,
- orders,
- deliveries,
- onDateClick,
- onItemClick,
- user,
- onOrderValidated,
-}: CalendarGridProps) {
- const { toast } = useToast();
-
- // Fonction pour valider une commande
- const handleValidateOrder = async (orderId: number, event: React.MouseEvent) => {
- event.stopPropagation();
-
- try {
- const response = await fetch(`/api/orders/${orderId}`, {
- method: 'PUT',
- headers: { 'Content-Type': 'application/json' },
- credentials: 'include',
- body: JSON.stringify({ status: 'delivered' })
- });
-
- if (!response.ok) {
- throw new Error(`Erreur ${response.status}: ${await response.text()}`);
- }
-
- toast({
- title: "Commande validée",
- description: `La commande CMD-${orderId} a été marquée comme livrée.`,
- });
-
- // Rafraîchir les données
- if (onOrderValidated) {
- onOrderValidated();
- }
- } catch (error) {
- console.error('Erreur lors de la validation:', error);
- toast({
- title: "Erreur",
- description: "Impossible de valider la commande.",
- variant: "destructive"
- });
- }
- };
-
- // ... (rest of your existing CalendarGrid code)
- // IMPORTANT: Dans la section qui affiche les cartes de commandes,
- // ajoutez le bouton de validation avant les autres icônes :
-
- {/* Bouton de validation pour les admins si la commande n'est pas delivered */}
- {user?.role === 'admin' && order.status !== 'delivered' && (
- handleValidateOrder(order.id, e)}
- title="Valider la commande"
- >
-
-
- )}
-```
-
-2. **`client/src/pages/Calendar.tsx`** - Modifier l'appel à CalendarGrid :
-```typescript
- {
- queryClient.invalidateQueries({ queryKey: ['/api/orders'] });
- queryClient.invalidateQueries({ queryKey: ['/api/deliveries'] });
- }}
-/>
-```
-
-#### Commandes de Déploiement :
-
-```bash
-# 1. Sauvegarde
-cp -r client/src client/src.backup
-
-# 2. Appliquer les modifications aux fichiers mentionnés ci-dessus
-
-# 3. Reconstruction
-npm run build
-
-# 4. Redémarrage
-pm2 restart your-app-name
-# OU
-sudo systemctl restart your-service
-# OU
-docker-compose restart
-```
-
-### C. Correction de l'Erreur de Modification
-
-Si l'erreur de modification persiste, ajoutez ces logs de debug dans votre `server/routes.ts` :
-
-```javascript
-app.put('/api/orders/:id', isAuthenticated, async (req: any, res) => {
- try {
- console.log('🔧 [DEBUG] Order update request:', {
- orderId: req.params.id,
- body: req.body,
- userId: req.user?.id || req.user?.claims?.sub
- });
-
- // ... rest of existing code
-
- } catch (error) {
- console.error("❌ [ERROR] Order update failed:", {
- error: error.message,
- stack: error.stack,
- orderId: req.params.id,
- body: req.body
- });
- res.status(500).json({ message: "Failed to update order" });
- }
-});
-```
-
-## Test après Déploiement
-
-1. **Connectez-vous** avec un compte admin
-2. **Recherchez CMD-55** dans le calendrier
-3. **Passez la souris** sur la carte CMD-55
-4. **Cliquez** sur l'icône de cercle avec coche qui apparaît
-5. **Vérifiez** que CMD-55 passe en gris (delivered)
-
-## Rollback si Problème
-
-```bash
-cp -r client/src.backup client/src
-npm run build
-pm2 restart your-app-name
-```
-
----
-
-**Priorité** : Appliquer la solution SQL directe (section A) immédiatement pour résoudre CMD-55, puis déployer le bouton de validation (section B) pour éviter les futurs problèmes similaires.
\ No newline at end of file
diff --git a/URGENT-DEPLOY.md b/URGENT-DEPLOY.md
deleted file mode 100644
index 58ab554..0000000
--- a/URGENT-DEPLOY.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# DÉPLOIEMENT URGENT - LogiFlow
-
-## Problème critique résolu
-❌ **Avant** : Routes manquantes en production (/api/users, /api/deliveries, /api/roles retournaient 404)
-✅ **Après** : Toutes les routes API disponibles
-
-## Action IMMÉDIATE
-```bash
-# Sur votre serveur de production
-cd /path/to/logiflow
-docker-compose up --build -d
-```
-
-## Vérification immédiate
-Après déploiement, testez ces URLs qui échouaient avant :
-- https://logiflow.ffnancy.fr/api/users (ne doit plus retourner 404)
-- https://logiflow.ffnancy.fr/api/deliveries (ne doit plus retourner 404)
-- https://logiflow.ffnancy.fr/api/roles (ne doit plus retourner 404)
-
-## Test automatique
-```bash
-node debug-deliveries-production.js https://logiflow.ffnancy.fr
-```
-
-## Résultat attendu
-- ✅ Module Utilisateurs : Affiche les utilisateurs enregistrés
-- ✅ Module Livraisons : Affiche les données de la base
-- ✅ Module Tâches : Fonctionne normalement
-- ✅ Module Commandes clients : Données visibles
-- ✅ Plus d'erreurs 404 dans les logs
-
-**BUNDLE VERSION** : 199.1kb - Toutes routes + corrections TypeScript incluses
-**TEMPS ESTIMÉ** : 2-3 minutes de déploiement
\ No newline at end of file
diff --git a/URGENT-EMPLOYEE-CUSTOMER-ORDER-FIX-FINAL.md b/URGENT-EMPLOYEE-CUSTOMER-ORDER-FIX-FINAL.md
deleted file mode 100644
index 71934d0..0000000
--- a/URGENT-EMPLOYEE-CUSTOMER-ORDER-FIX-FINAL.md
+++ /dev/null
@@ -1,65 +0,0 @@
-# Fix Final - Commandes Client Employé Magasin #2
-
-## Problème Spécifique aux Commandes Client
-
-Les DLC fonctionnent maintenant ✅ mais les commandes client ont encore `groupId: 1` pour employé magasin #2.
-
-## Cause Identifiée
-
-Logs production montrent :
-```javascript
-userHasGroups: true,
-userGroupsLength: 1,
-selectedStoreId: 1, // ❌ Interfère avec la logique
-final groupId selected: 1 // ❌ Mauvais groupId
-```
-
-**Différence DLC vs Commandes Client :**
-- ✅ **DLC** : Calcul `groupId` dans `onSubmit()`
-- ❌ **Commandes Client** : `defaultValues` du formulaire utilise logique incorrecte
-
-## Fix Appliqué
-
-### 1. Fonction de Calcul GroupId Correcte
-```javascript
-const getDefaultGroupId = () => {
- if (order?.groupId) return order.groupId;
-
- // PRIORITÉ 1: Groupe assigné utilisateur
- if (user?.userGroups?.[0]?.groupId) {
- return user.userGroups[0].groupId; // groupId: 2 pour employé Houdemont
- }
-
- // PRIORITÉ 2: Admin store selection (seulement si pas de groupe assigné)
- if (user?.role === 'admin' && selectedStoreId) {
- return selectedStoreId;
- }
-
- return 1; // Fallback
-};
-```
-
-### 2. Application dans defaultValues
-```javascript
-// AVANT (Cassé)
-groupId: order?.groupId || (user?.userGroups?.[0]?.groupId || (user?.role === 'admin' && selectedStoreId ? selectedStoreId : 1))
-
-// APRÈS (Corrigé)
-groupId: getDefaultGroupId() // ✅ Priorité correcte
-```
-
-## Logique de Priorité Unifiée
-
-**PARTOUT (DLC + Commandes Client) :**
-1. 🎯 **Groupe assigné** (`user.userGroups[0].groupId`) - **PRIORITÉ ABSOLUE**
-2. 🏪 **Admin selection** (`selectedStoreId`) - Si pas de groupe assigné
-3. 🚨 **Fallback** (`groupId: 1`) - Urgence
-
-## Résultat Attendu
-
-Employé magasin #2 (Houdemont) :
-- ✅ **DLC** → `groupId: 2` (déjà fixé)
-- ✅ **Commandes Client** → `groupId: 2` (maintenant fixé)
-- ✅ **Cohérence totale** entre tous les modules
-
-**DÉPLOIEMENT PRODUCTION IMMÉDIAT**
\ No newline at end of file
diff --git a/URGENT-EMPLOYEE-CUSTOMER-ORDER-FIX.md b/URGENT-EMPLOYEE-CUSTOMER-ORDER-FIX.md
deleted file mode 100644
index b21793b..0000000
--- a/URGENT-EMPLOYEE-CUSTOMER-ORDER-FIX.md
+++ /dev/null
@@ -1,94 +0,0 @@
-# Fix Urgent - Employé ne peut pas créer de commandes client en production
-
-## Problème Identifié
-L'utilisateur avec rôle employé n'arrive pas à créer des commandes client en production alors que ça fonctionne avec admin.
-
-## Solutions Appliquées
-
-### 1. Suppression Totale des Restrictions Backend
-**Fichier:** `server/routes.ts` ligne 1977
-```javascript
-// REMOVED: All role restrictions - tous les rôles peuvent créer des commandes client
-console.log("Creating customer order - no role restrictions:", { userId, userRole: user.role, groupId: backendData.groupId });
-```
-✅ **CONFIRMÉ** - Aucune restriction de rôle dans le POST `/api/customer-orders`
-
-### 2. Permissions Système Confirmées
-**Fichier:** `shared/permissions.ts` ligne 72
-```javascript
-'customer-orders': {
- admin: ['view', 'create', 'edit', 'delete'],
- directeur: ['view', 'create', 'edit', 'delete'],
- manager: ['view', 'create', 'edit'],
- employee: ['view', 'create'] // ✅ EMPLOYÉ A BIEN LES DROITS
-},
-```
-
-### 3. Robustesse Frontend GroupId
-**Fichier:** `client/src/components/CustomerOrderForm.tsx`
-
-**AVANT (Problématique):**
-```javascript
-groupId: order?.groupId || (user?.role === 'admin' && selectedStoreId ? selectedStoreId : user?.userGroups?.[0]?.groupId) || undefined
-```
-
-**APRÈS (Corrigé avec fallbacks robustes):**
-```javascript
-groupId: order?.groupId || (user?.role === 'admin' && selectedStoreId ? selectedStoreId : user?.userGroups?.[0]?.groupId) || 1
-
-// + Logique de fallback renforcée:
-if (!groupId) {
- if (user?.role === 'admin' && selectedStoreId) {
- groupId = selectedStoreId;
- } else if (user?.userGroups?.[0]?.groupId) {
- groupId = user.userGroups[0].groupId;
- } else if (user?.role === 'admin' && groups.length > 0) {
- groupId = groups[0].id;
- } else if (groups.length > 0) {
- // EMERGENCY FALLBACK: Force assignment
- groupId = groups[0].id;
- } else {
- // LAST RESORT: Hard-coded fallback
- groupId = 1;
- }
-}
-```
-
-### 4. Debug Logs Ajoutés
-```javascript
-console.log("🔍 Customer Order GroupId Debug:", {
- userRole: user?.role,
- selectedStoreId,
- userGroups: user?.userGroups?.map(ug => ({groupId: ug.groupId, groupName: ug.group?.name})),
- initialGroupId: groupId,
- availableGroups: groups.map(g => ({id: g.id, name: g.name}))
-});
-```
-
-### 5. Validation Schema Robuste
-**Schema Frontend utilise déjà `z.coerce.number()` pour conversion automatique:**
-```javascript
-supplierId: z.coerce.number().int().positive(),
-deposit: z.coerce.number().min(0),
-```
-
-## Test de Validation
-✅ Création commande client avec admin fonctionne
-✅ API route sans restriction de rôle
-✅ Permissions employé confirmées dans permissions.ts
-✅ GroupId forcé avec fallbacks multiples
-
-## Déploiement Production
-1. ✅ Logique groupId renforcée
-2. ✅ Debug logs pour traçabilité
-3. ✅ Fallbacks d'urgence
-4. 🔄 **REDÉMARRER SERVEUR PRODUCTION**
-5. 🧪 **TESTER AVEC EMPLOYÉ RÉEL**
-
-## Fallbacks d'Urgence Appliqués
-- Si pas de groupId → utilise groupe utilisateur
-- Si pas de groupe utilisateur → utilise premier groupe disponible
-- Si pas de groupes → force groupId = 1
-- Logs détaillés pour debug production
-
-**RÉSULTAT ATTENDU:** Employé peut maintenant créer des commandes client sans restriction.
\ No newline at end of file
diff --git a/URGENT-PERMISSIONS-FIX.md b/URGENT-PERMISSIONS-FIX.md
deleted file mode 100644
index 928b335..0000000
--- a/URGENT-PERMISSIONS-FIX.md
+++ /dev/null
@@ -1,130 +0,0 @@
-# Fix Urgent - Permissions Directeurs
-
-## 🎯 Problème Identifié
-**Les directeurs voient TOUS les magasins** au lieu de seulement leur magasin assigné.
-
-## 🔍 Analyse du Problème
-
-### Logique Incorrecte Actuelle
-```typescript
-// ❌ INCORRECT
-if (user.role === 'admin') {
- // Voir tous les magasins
-} else {
- // Tous les autres rôles voient leurs magasins assignés
-}
-```
-
-### Rôles et Accès Attendus
-- **Admin** : Tous les magasins ✅
-- **Directeur** : Seulement son magasin assigné ❌→✅
-- **Manager** : Seulement son magasin assigné ✅
-- **Employee** : Seulement son magasin assigné ✅
-
-## ✅ Corrections Appliquées
-
-### 1. **Endpoint Groups** (`/api/groups`)
-```typescript
-// Avant
-if (user.role === 'admin') {
- const groups = await storage.getGroups(); // Tous
-} else {
- const userGroups = user.userGroups.map(ug => ug.group); // Assignés
-}
-
-// Après
-if (user.role === 'admin') {
- const groups = await storage.getGroups(); // Tous
-} else {
- // Directeur, Manager, Employee → seulement magasins assignés
- const userGroups = (user as any).userGroups?.map((ug: any) => ug.group) || [];
-}
-```
-
-### 2. **Endpoint Orders** (`/api/orders`)
-```typescript
-// Avant
-if (user.role === 'admin') {
- orders = await storage.getOrders(groupIds); // Tous ou filtré
-} else {
- const groupIds = user.userGroups.map(ug => ug.groupId); // Assignés
-}
-
-// Après
-if (user.role === 'admin') {
- orders = await storage.getOrders(groupIds); // Tous ou filtré
-} else {
- // Directeur, Manager, Employee → seulement groupes assignés
- const groupIds = (user as any).userGroups?.map((ug: any) => ug.groupId) || [];
-}
-```
-
-### 3. **Endpoint Deliveries** (`/api/deliveries`)
-```typescript
-// Déjà corrigé précédemment avec commentaire explicite
-if (user.role === 'admin') {
- // Admin peut voir tous les magasins
-} else {
- // For non-admin users (managers, employees, directeurs), only show their assigned stores
- const groupIds = (user as any).userGroups?.map((ug: any) => ug.groupId) || [];
-}
-```
-
-### 4. **Contrôles d'Accès** (tous endpoints)
-```typescript
-// Ajout de fallbacks robustes
-const userGroupIds = (user as any).userGroups?.map((ug: any) => ug.groupId) || [];
-```
-
-## 🔒 Logique de Sécurité Corrigée
-
-### Accès aux Données
-```
-Admin → Tous les magasins (peut sélectionner un magasin spécifique)
-├── Groups: Tous
-├── Orders: Tous
-├── Deliveries: Tous
-└── Permissions: Toutes actions
-
-Directeur → SEULEMENT son magasin assigné
-├── Groups: Magasin assigné uniquement
-├── Orders: Magasin assigné uniquement
-├── Deliveries: Magasin assigné uniquement
-└── Permissions: Actions limitées selon le rôle
-
-Manager/Employee → SEULEMENT leur magasin assigné
-├── Groups: Magasin assigné uniquement
-├── Orders: Magasin assigné uniquement
-├── Deliveries: Magasin assigné uniquement
-└── Permissions: Actions limitées selon le rôle
-```
-
-## 🧪 Tests de Validation
-
-### Test Directeur
-1. Se connecter avec compte directeur
-2. **Vérifier :** Seulement SON magasin visible
-3. **Vérifier :** Pas d'accès aux autres magasins
-4. **Tenter :** Accéder à une commande d'un autre magasin → 403 Forbidden
-
-### Test Admin
-1. Se connecter avec compte admin
-2. **Vérifier :** Tous les magasins visibles
-3. **Vérifier :** Sélecteur de magasin fonctionne
-4. **Vérifier :** Peut basculer entre magasins
-
-### Test Manager/Employee
-1. Se connecter avec ces rôles
-2. **Vérifier :** Seulement leur magasin assigné
-3. **Vérifier :** Cohérent avec directeur
-
-## 📊 Status
-
-- ✅ Endpoint Groups corrigé
-- ✅ Endpoint Orders corrigé
-- ✅ Endpoint Deliveries déjà corrigé
-- ✅ Contrôles d'accès renforcés avec fallbacks
-- ✅ Commentaires explicites ajoutés
-- 🔄 **À tester en production**
-
-**Les directeurs ne verront maintenant que leur magasin assigné !**
\ No newline at end of file
diff --git a/URGENT-PRODUCTION-FIX.md b/URGENT-PRODUCTION-FIX.md
deleted file mode 100644
index 2eceda2..0000000
--- a/URGENT-PRODUCTION-FIX.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# CORRECTION URGENTE PRODUCTION - "Button is not defined"
-
-## Problème Identifié
-L'erreur `ReferenceError: Button is not defined` est causée par un import manquant dans CalendarGrid.tsx.
-
-## Correction Appliquée
-Ajout de l'import manquant dans `client/src/components/CalendarGrid.tsx` :
-
-```typescript
-// AVANT (ligne 4)
-import { Plus, Check } from "lucide-react";
-
-// APRÈS (lignes 4-5)
-import { Plus, Check } from "lucide-react";
-import { Button } from "@/components/ui/button";
-```
-
-## Pour Appliquer en Production
-
-### 1. Copier le Fichier Corrigé
-Copiez le contenu corrigé de `client/src/components/CalendarGrid.tsx` sur votre serveur.
-
-### 2. Reconstruction et Redémarrage
-```bash
-# Sur votre serveur de production
-npm run build
-pm2 restart your-app-name
-```
-
-### 3. Vérification
-- L'application devrait redémarrer sans erreur
-- Le calendrier devrait s'afficher correctement
-- Le bouton + pour créer une nouvelle entrée devrait fonctionner
-
-## Cause de l'Erreur
-Quand j'ai nettoyé le code de debug, j'ai supprimé l'import `Button` mais le composant était encore utilisé pour le bouton "+" de création rapide dans le calendrier.
-
-## Test Rapide
-Une fois corrigé, testez :
-1. Accès au calendrier ✓
-2. Clic sur le bouton + ✓
-3. Clic sur une commande → modal avec bouton "Valider Commande" ✓
-
-Cette correction résout l'erreur de production immédiatement.
\ No newline at end of file
diff --git a/URGENT-SYNC-GUIDE.md b/URGENT-SYNC-GUIDE.md
deleted file mode 100644
index bc586c7..0000000
--- a/URGENT-SYNC-GUIDE.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# GUIDE URGENT : Synchronisation Commandes/Livraisons
-
-## Problème
-La commande #CMD-55 et d'autres commandes liées à des livraisons "livrées" n'apparaissent pas grisées dans le calendrier car elles gardent le statut "planned" au lieu de "delivered".
-
-## Solution Immédiate (Production)
-
-### Option 1: Script SQL Direct ✅ RECOMMANDÉ
-```bash
-# Connectez-vous à votre base PostgreSQL et exécutez :
-psql $DATABASE_URL -f fix-delivery-order-sync-immediate.sql
-```
-
-### Option 2: Via Interface Web (après déploiement)
-1. Déployez le nouveau code sur votre serveur
-2. Connectez-vous comme admin sur https://logiflow-logiflow-1.c-2.us-east-2.aws.neon.tech
-3. Allez dans le calendrier
-4. Cliquez sur le bouton "Sync Status" (à côté de "Nouveau")
-
-## Ce que fait le script
-
-1. **Diagnostic** : Affiche toutes les commandes avec des livraisons livrées mais statut incorrect
-2. **Correction automatique** : Met à jour le statut des commandes vers "delivered"
-3. **Dates de livraison** : Corrige les delivered_date manquantes
-4. **Vérification finale** : Affiche les résultats et la commande CMD-55 spécifiquement
-
-## Résultat attendu
-Après exécution du script :
-- ✅ La commande #CMD-55 aura le statut "delivered"
-- ✅ Elle apparaîtra grisée (bg-delivered) dans le calendrier
-- ✅ Les dates de livraison seront affichées correctement
-- ✅ Toutes les commandes similaires seront corrigées
-
-## Test
-Après avoir exécuté le script, actualisez votre calendrier sur https://logiflow-logiflow-1.c-2.us-east-2.aws.neon.tech et vérifiez que la commande CMD-55 apparaît maintenant grisée.
-
-## Note Technique
-Le bouton "Sync Status" dans l'interface n'est pas encore déployé sur votre serveur de production. Le script SQL est la solution immédiate.
\ No newline at end of file
diff --git a/VALIDATE-ORDER-BUTTON-FEATURE.md b/VALIDATE-ORDER-BUTTON-FEATURE.md
deleted file mode 100644
index a6bc5b8..0000000
--- a/VALIDATE-ORDER-BUTTON-FEATURE.md
+++ /dev/null
@@ -1,54 +0,0 @@
-# Fonctionnalité Bouton "Valider Commande" - Calendrier
-
-## Nouvelle Fonctionnalité
-
-J'ai ajouté un bouton de validation directement sur les cartes des commandes dans le calendrier, avec les caractéristiques suivantes :
-
-### Fonctionnement
-
-- **Visibilité** : Le bouton n'est visible que pour les utilisateurs avec le rôle `admin`
-- **Apparition** : Le bouton apparaît uniquement au survol de la carte de commande (effet hover)
-- **Cible** : Seules les commandes qui ne sont pas encore en statut `delivered` affichent le bouton
-- **Action** : Un clic sur le bouton marque immédiatement la commande comme `delivered`
-
-### Interface Utilisateur
-
-- **Icône** : CheckCircle (cercle avec coche)
-- **Position** : À droite de la carte, avant les autres indicateurs de statut
-- **Style** : Bouton fantôme semi-transparent qui devient visible au survol
-- **Feedback** : Toast de confirmation quand la validation réussit
-
-### Avantages
-
-1. **Accès Direct** : Plus besoin d'ouvrir le modal de détail pour valider une commande
-2. **Interface Propre** : Le bouton n'encombre pas l'interface car il n'apparaît qu'au survol
-3. **Sécurité** : Réservé aux administrateurs uniquement
-4. **Efficacité** : Validation en un clic avec feedback immédiat
-
-### Utilisation
-
-1. **Connexion Admin** : Connectez-vous avec un compte administrateur
-2. **Survol** : Passez la souris sur une commande non-delivered (orange ou bleue)
-3. **Validation** : Cliquez sur l'icône de cercle avec coche qui apparaît
-4. **Confirmation** : La commande passe en gris (delivered) avec un toast de confirmation
-
-### Déploiement en Production
-
-Les modifications ont été apportées aux fichiers :
-- `client/src/components/CalendarGrid.tsx` : Ajout du bouton et logique de validation
-- `client/src/pages/Calendar.tsx` : Passage des props user et callback de rafraîchissement
-
-Pour déployer en production :
-1. Appliquer les modifications aux fichiers mentionnés
-2. Reconstruire le frontend (`npm run build`)
-3. Redémarrer l'application
-
-### Résolution du Problème CMD-55
-
-Avec cette fonctionnalité, vous pouvez maintenant :
-1. Trouver CMD-55 dans le calendrier
-2. Passer la souris dessus (si elle n'est pas déjà delivered)
-3. Cliquer sur le bouton de validation
-4. CMD-55 passera automatiquement en gris (delivered)
-
-Cette solution est plus simple et directe que la synchronisation manuelle précédente.
\ No newline at end of file
diff --git a/VALIDATION-ERROR-FIX.md b/VALIDATION-ERROR-FIX.md
deleted file mode 100644
index b8f12f7..0000000
--- a/VALIDATION-ERROR-FIX.md
+++ /dev/null
@@ -1,61 +0,0 @@
-# Fix Validation Errors - Commandes Client Production
-
-## Problème Identifié
-
-**Erreurs de validation dans le formulaire de commande client :**
-1. `"Expected number, received string"` pour le champ **Fournisseur** (`supplierId`)
-2. `"Expected number, received string"` pour le champ **Acompte** (`deposit`)
-
-## Cause du Problème
-
-Le formulaire frontend envoie des valeurs string, mais le schema Zod attend des numbers :
-
-```javascript
-// AVANT (Problématique)
-supplierId: z.number().int().positive().optional().default(1)
-deposit: z.number().optional().default(0)
-
-// APRÈS (Corrigé)
-supplierId: z.coerce.number().int().positive().optional().default(1)
-deposit: z.coerce.number().optional().default(0)
-```
-
-## Solution Appliquée
-
-**Fichier modifié :** `shared/schema.ts`
-
-✅ Ajouté `z.coerce.number()` pour forcer la conversion automatique string → number
-✅ Appliqué aussi pour `quantity` et `groupId` par précaution
-✅ Corrigé `customerEmail` pour accepter chaîne vide avec `.or(z.literal(""))`
-
-## Schema Corrigé
-
-```javascript
-export const insertCustomerOrderFrontendSchema = z.object({
- customerName: z.string().min(1, "Customer name is required"),
- contactNumber: z.string().min(1, "Contact number is required"),
- productName: z.string().min(1, "Product name is required"),
- productDescription: z.string().optional(),
- quantity: z.coerce.number().int().positive().default(1), // ✅ CORRIGÉ
- groupId: z.coerce.number().int().positive(), // ✅ CORRIGÉ
- isPickup: z.boolean().default(false),
- notes: z.string().optional(),
- orderTaker: z.string().optional(),
- gencode: z.string().optional().default(""),
- supplierId: z.coerce.number().int().positive().optional().default(1), // ✅ CORRIGÉ
- deposit: z.coerce.number().optional().default(0), // ✅ CORRIGÉ
- isPromotionalPrice: z.boolean().default(false),
- customerEmail: z.string().email().optional().or(z.literal("")), // ✅ CORRIGÉ
- productReference: z.string().optional(),
-});
-```
-
-## Test
-
-Après cette correction, les employés devraient pouvoir créer des commandes client sans erreur de validation en production.
-
-## Déploiement
-
-1. ✅ Schema corrigé dans `shared/schema.ts`
-2. 🔄 **Redémarrer le serveur production**
-3. 🧪 **Tester création commande client avec employé**
\ No newline at end of file
diff --git a/apply-production-fixes.js b/apply-production-fixes.js
deleted file mode 100644
index 64a86b9..0000000
--- a/apply-production-fixes.js
+++ /dev/null
@@ -1,146 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Script pour appliquer les corrections 403 employés sur votre serveur de production privé
- * Ce script documente les changements à effectuer manuellement sur votre serveur
- */
-
-console.log('🔧 === CORRECTIONS À APPLIQUER SUR VOTRE SERVEUR DE PRODUCTION ===\n');
-
-console.log('📝 FICHIERS À MODIFIER SUR VOTRE SERVEUR PRIVÉ:');
-console.log('================================================\n');
-
-console.log('1️⃣ FICHIER: shared/permissions.ts');
-console.log('-----------------------------------');
-console.log('LIGNE À MODIFIER (environ ligne 84-91):');
-console.log('');
-console.log('// REMPLACER:');
-console.log('tasks: {');
-console.log(' admin: [\'view\', \'create\', \'edit\', \'delete\', \'validate\'],');
-console.log(' directeur: [\'view\', \'create\', \'edit\', \'delete\', \'validate\'],');
-console.log(' manager: [\'view\', \'validate\'],');
-console.log(' employee: [\'view\'] // ← PROBLÈME ICI');
-console.log('}');
-console.log('');
-console.log('// PAR:');
-console.log('tasks: {');
-console.log(' admin: [\'view\', \'create\', \'edit\', \'delete\', \'validate\'],');
-console.log(' directeur: [\'view\', \'create\', \'edit\', \'delete\', \'validate\'],');
-console.log(' manager: [\'view\', \'validate\'],');
-console.log(' employee: [\'view\'] // ← PERMISSIONS INCHANGÉES - VOIR SEULEMENT');
-console.log('}');
-console.log('\n');
-
-console.log('2️⃣ FICHIER: server/routes.ts');
-console.log('-----------------------------');
-console.log('CORRECTIONS MULTIPLES À EFFECTUER:\n');
-
-console.log('A) Route GET /api/suppliers (environ ligne 188-194):');
-console.log('// REMPLACER:');
-console.log('if (!user || (user.role !== \'admin\' && user.role !== \'manager\')) {');
-console.log(' return res.status(403).json({ message: "Insufficient permissions" });');
-console.log('}');
-console.log('');
-console.log('// PAR:');
-console.log('if (!user || (user.role !== \'admin\' && user.role !== \'manager\' && user.role !== \'directeur\' && user.role !== \'employee\')) {');
-console.log(' return res.status(403).json({ message: "Insufficient permissions" });');
-console.log('}');
-console.log('\n');
-
-console.log('B) Route POST /api/suppliers (environ ligne 240-242):');
-console.log('// REMPLACER:');
-console.log('if (user.role !== \'admin\' && user.role !== \'manager\') {');
-console.log(' console.error(\'❌ Insufficient permissions:\', { userRole: user.role, required: [\'admin\', \'manager\'] });');
-console.log(' return res.status(403).json({ message: "Insufficient permissions" });');
-console.log('}');
-console.log('');
-console.log('// PAR:');
-console.log('if (user.role !== \'admin\' && user.role !== \'manager\' && user.role !== \'directeur\') {');
-console.log(' console.error(\'❌ Insufficient permissions:\', { userRole: user.role, required: [\'admin\', \'manager\', \'directeur\'] });');
-console.log(' return res.status(403).json({ message: "Insufficient permissions" });');
-console.log('}');
-console.log('\n');
-
-console.log('C) Route PUT /api/suppliers/:id (environ ligne 281-283):');
-console.log('// REMPLACER:');
-console.log('if (!user || (user.role !== \'admin\' && user.role !== \'manager\')) {');
-console.log(' return res.status(403).json({ message: "Insufficient permissions" });');
-console.log('}');
-console.log('');
-console.log('// PAR:');
-console.log('if (!user || (user.role !== \'admin\' && user.role !== \'manager\' && user.role !== \'directeur\')) {');
-console.log(' return res.status(403).json({ message: "Insufficient permissions" });');
-console.log('}');
-console.log('\n');
-
-console.log('D) Route DELETE /api/suppliers/:id (environ ligne 298-300):');
-console.log('// REMPLACER:');
-console.log('if (!user || (user.role !== \'admin\' && user.role !== \'manager\')) {');
-console.log(' return res.status(403).json({ message: "Insufficient permissions" });');
-console.log('}');
-console.log('');
-console.log('// PAR:');
-console.log('if (!user || (user.role !== \'admin\' && user.role !== \'directeur\')) {');
-console.log(' return res.status(403).json({ message: "Insufficient permissions" });');
-console.log('}');
-console.log('\n');
-
-console.log('E) Route POST /api/dlc-products/:id/validate (environ ligne 2332-2334):');
-console.log('// REMPLACER:');
-console.log('if (!user || ![\'admin\', \'manager\'].includes(user.role)) {');
-console.log(' return res.status(403).json({ message: "Insufficient permissions to validate products" });');
-console.log('}');
-console.log('');
-console.log('// PAR:');
-console.log('if (!user || ![\'admin\', \'manager\', \'directeur\'].includes(user.role)) {');
-console.log(' return res.status(403).json({ message: "Insufficient permissions to validate products" });');
-console.log('}');
-console.log('\n');
-
-console.log('📋 ÉTAPES D\'APPLICATION:');
-console.log('========================');
-console.log('1. Connectez-vous à votre serveur de production');
-console.log('2. Sauvegardez les fichiers originaux:');
-console.log(' cp shared/permissions.ts shared/permissions.ts.backup');
-console.log(' cp server/routes.ts server/routes.ts.backup');
-console.log('3. Ouvrez shared/permissions.ts et effectuez la correction 1️⃣');
-console.log('4. Ouvrez server/routes.ts et effectuez les corrections 2️⃣A à 2️⃣E');
-console.log('5. Redémarrez votre serveur Node.js');
-console.log('6. Testez avec un compte employé');
-console.log('\n');
-
-console.log('🧪 COMMANDES DE TEST POST-CORRECTION:');
-console.log('====================================');
-console.log('# Test rapide des fournisseurs pour employé:');
-console.log('curl -X GET "https://votre-serveur.com/api/suppliers" \\');
-console.log(' -H "Cookie: session=TOKEN_SESSION_EMPLOYE"');
-console.log('');
-console.log('# Test création tâche pour employé:');
-console.log('curl -X POST "https://votre-serveur.com/api/tasks" \\');
-console.log(' -H "Content-Type: application/json" \\');
-console.log(' -H "Cookie: session=TOKEN_SESSION_EMPLOYE" \\');
-console.log(' -d \'{"title":"Test","description":"Test employé","priority":"medium","status":"pending","groupId":1}\'');
-console.log('\n');
-
-console.log('✅ RÉSULTAT ATTENDU APRÈS CORRECTIONS:');
-console.log('======================================');
-console.log('- Employés peuvent accéder aux fournisseurs (modules Commandes Client et DLC)');
-console.log('- Employés peuvent créer des tâches dans leurs magasins assignés');
-console.log('- Directeurs peuvent valider les produits DLC');
-console.log('- Plus d\'erreurs 403 pour les actions autorisées');
-console.log('\n');
-
-console.log('⚠️ REMARQUES IMPORTANTES:');
-console.log('==========================');
-console.log('- Ces corrections doivent être appliquées sur votre serveur de production');
-console.log('- Testez d\'abord sur un environnement de staging si possible');
-console.log('- Gardez les sauvegardes des fichiers originaux');
-console.log('- Redémarrez le serveur après les modifications');
-console.log('- Surveillez les logs après les changements');
-console.log('\n');
-
-console.log('🎯 Ces corrections résolvent spécifiquement:');
-console.log('- Erreurs 403 sur /api/suppliers pour employés');
-console.log('- Erreurs 403 sur /api/tasks POST pour employés');
-console.log('- Erreurs 403 sur /api/dlc-products/:id/validate pour directeurs');
-console.log('- Permissions incohérentes entre frontend et backend');
\ No newline at end of file
diff --git a/attached_assets/.gitkeep b/attached_assets/.gitkeep
deleted file mode 100644
index 0e87a0a..0000000
--- a/attached_assets/.gitkeep
+++ /dev/null
@@ -1 +0,0 @@
-# Assets placeholder
diff --git a/attached_assets/Pasted--Database-initialization-NODE-ENV-production-isProduction-true-h-1754928114027_1754928114027.txt b/attached_assets/Pasted--Database-initialization-NODE-ENV-production-isProduction-true-h-1754928114027_1754928114027.txt
deleted file mode 100644
index 704b43d..0000000
--- a/attached_assets/Pasted--Database-initialization-NODE-ENV-production-isProduction-true-h-1754928114027_1754928114027.txt
+++ /dev/null
@@ -1,175 +0,0 @@
-
-
-🔗 Database initialization: {
-
- NODE_ENV: 'production',
-
- isProduction: true,
-
- hasDbUrl: true,
-
- dbHost: 'logiflow-db'
-
-}
-
-🐳 PRODUCTION: Using standard PostgreSQL
-
-✅ PostgreSQL connection test successful
-
-🐳 PRODUCTION: Using PostgreSQL storage
-
-🐳 PRODUCTION: Local auth configured with PostgreSQL sessions
-
-🐳 PRODUCTION: Starting LogiFlow application
-
-🐳 Environment: { NODE_ENV: 'production', DATABASE_URL: 'Present', PORT: '3000' }
-
-🐳 Serving static files from: /app/dist/public
-
-🐳 PRODUCTION: LogiFlow serving on port 3000
-
-✅ Production admin user found: { id: 'admin_local', username: 'admin', passwordFormat: 'present' }
-
-🔐 Production password comparison { suppliedLength: 5, storedFormat: '21ff482668...' }
-
-✅ Password matched with hash.salt format
-
-✅ Admin password works with current system
-
-Server error: {
-
- status: 500,
-
- message: 'column user_groups.created_at does not exist',
-
- error: error: column user_groups.created_at does not exist
-
- at /app/node_modules/pg-pool/index.js:45:11
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
-
- at async DatabaseStorage.getUserWithGroups (file:///app/dist/index.js:1364:28)
-
- at async file:///app/dist/index.js:3051:20 {
-
- length: 120,
-
- severity: 'ERROR',
-
- code: '42703',
-
- detail: undefined,
-
- hint: undefined,
-
- position: '59',
-
- internalPosition: undefined,
-
- internalQuery: undefined,
-
- where: undefined,
-
- schema: undefined,
-
- table: undefined,
-
- column: undefined,
-
- dataType: undefined,
-
- constraint: undefined,
-
- file: 'parse_relation.c',
-
- line: '3665',
-
- routine: 'errorMissingColumn'
-
- }
-
-}
-
-error: column user_groups.created_at does not exist
-
- at /app/node_modules/pg-pool/index.js:45:11
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
-
- at async DatabaseStorage.getUserWithGroups (file:///app/dist/index.js:1364:28)
-
- at async file:///app/dist/index.js:3051:20
-
-HEAD /api/health 200 in 3ms
-
-Server error: {
-
- status: 500,
-
- message: 'column user_groups.created_at does not exist',
-
- error: error: column user_groups.created_at does not exist
-
- at /app/node_modules/pg-pool/index.js:45:11
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
-
- at async DatabaseStorage.getUserWithGroups (file:///app/dist/index.js:1364:28)
-
- at async file:///app/dist/index.js:3051:20 {
-
- length: 120,
-
- severity: 'ERROR',
-
- code: '42703',
-
- detail: undefined,
-
- hint: undefined,
-
- position: '59',
-
- internalPosition: undefined,
-
- internalQuery: undefined,
-
- where: undefined,
-
- schema: undefined,
-
- table: undefined,
-
- column: undefined,
-
- dataType: undefined,
-
- constraint: undefined,
-
- file: 'parse_relation.c',
-
- line: '3665',
-
- routine: 'errorMissingColumn'
-
- }
-
-}
-
-error: column user_groups.created_at does not exist
-
- at /app/node_modules/pg-pool/index.js:45:11
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
-
- at async DatabaseStorage.getUserWithGroups (file:///app/dist/index.js:1364:28)
-
- at async file:///app/dist/index.js:3051:20
\ No newline at end of file
diff --git a/attached_assets/Pasted--Database-initialization-NODE-ENV-production-isProduction-true-hasDb-1754936753635_1754936753635.txt b/attached_assets/Pasted--Database-initialization-NODE-ENV-production-isProduction-true-hasDb-1754936753635_1754936753635.txt
deleted file mode 100644
index 91109d6..0000000
--- a/attached_assets/Pasted--Database-initialization-NODE-ENV-production-isProduction-true-hasDb-1754936753635_1754936753635.txt
+++ /dev/null
@@ -1,182 +0,0 @@
-
-🔗 Database initialization: {
-
- NODE_ENV: 'production',
-
- isProduction: true,
-
- hasDbUrl: true,
-
- dbHost: 'logiflow-db'
-
-}
-
-🐳 PRODUCTION: Using standard PostgreSQL
-
-✅ PostgreSQL connection test successful
-
-🐳 PRODUCTION: Using PostgreSQL storage
-
-🐳 PRODUCTION: Local auth configured with PostgreSQL sessions
-
-🐳 PRODUCTION: Starting LogiFlow application
-
-🐳 Environment: { NODE_ENV: 'production', DATABASE_URL: 'Present', PORT: '3000' }
-
-🔍 Using development storage and authentication
-
-🔧 Using memory session store for development
-
-Warning: connect.session() MemoryStore is not
-
-designed for a production environment, as it will leak
-
-memory, and will not scale past a single process.
-
-🐳 Serving static files from: /app/dist/public
-
-🐳 PRODUCTION: LogiFlow serving on port 3000
-
-✅ Production admin user found: { id: 'admin_local', username: 'admin', passwordFormat: 'present' }
-
-🔐 Production password comparison { suppliedLength: 5, storedFormat: '63d2ce518b...' }
-
-✅ Password matched with hash.salt format
-
-✅ Admin password works with current system
-
-HEAD /api/health 200 in 5ms
-
-Error updating user: error: duplicate key value violates unique constraint "users_email_key"
-
- at /app/node_modules/pg-pool/index.js:45:11
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
-
- at async DatabaseStorage.updateUser (file:///app/dist/index.js:1085:24)
-
- at async file:///app/dist/index.js:4051:27 {
-
- length: 210,
-
- severity: 'ERROR',
-
- code: '23505',
-
- detail: 'Key (email)=(admin@logiflow.com) already exists.',
-
- hint: undefined,
-
- position: undefined,
-
- internalPosition: undefined,
-
- internalQuery: undefined,
-
- where: undefined,
-
- schema: 'public',
-
- table: 'users',
-
- column: undefined,
-
- dataType: undefined,
-
- constraint: 'users_email_key',
-
- file: 'nbtinsert.c',
-
- line: '664',
-
- routine: '_bt_check_unique'
-
-}
-
-PUT /api/users/_1754936203292 500 in 96ms
-
-HEAD /api/health 200 in 1ms
-
-HEAD /api/health 200 in 0ms
-
-HEAD /api/health 200 in 1ms
-
-HEAD /api/health 200 in 1ms
-
-HEAD /api/health 200 in 1ms
-
-HEAD /api/health 200 in 16ms
-
-HEAD /api/health 200 in 1ms
-
-HEAD /api/health 200 in 4ms
-
-HEAD /api/health 200 in 1ms
-
-HEAD /api/health 200 in 1ms
-
-HEAD /api/health 200 in 1ms
-
-HEAD /api/health 200 in 1ms
-
-HEAD /api/health 200 in 1ms
-
-HEAD /api/health 200 in 1ms
-
-HEAD /api/health 200 in 1ms
-
-HEAD /api/health 200 in 3ms
-
-Error updating user: error: duplicate key value violates unique constraint "users_email_key"
-
- at /app/node_modules/pg-pool/index.js:45:11
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
-
- at async DatabaseStorage.updateUser (file:///app/dist/index.js:1085:24)
-
- at async file:///app/dist/index.js:4051:27 {
-
- length: 210,
-
- severity: 'ERROR',
-
- code: '23505',
-
- detail: 'Key (email)=(admin@logiflow.com) already exists.',
-
- hint: undefined,
-
- position: undefined,
-
- internalPosition: undefined,
-
- internalQuery: undefined,
-
- where: undefined,
-
- schema: 'public',
-
- table: 'users',
-
- column: undefined,
-
- dataType: undefined,
-
- constraint: 'users_email_key',
-
- file: 'nbtinsert.c',
-
- line: '664',
-
- routine: '_bt_check_unique'
-
-}
-
-PUT /api/users/_1754936203292 500 in 44ms
-
-HEAD /api/health 200 in 1ms
\ No newline at end of file
diff --git a/attached_assets/Pasted--Processed-0-groups-for-user-admin-local-Found-0-group-assignments-for-user-admin-local--1754986712301_1754986712302.txt b/attached_assets/Pasted--Processed-0-groups-for-user-admin-local-Found-0-group-assignments-for-user-admin-local--1754986712301_1754986712302.txt
deleted file mode 100644
index e9188bb..0000000
--- a/attached_assets/Pasted--Processed-0-groups-for-user-admin-local-Found-0-group-assignments-for-user-admin-local--1754986712301_1754986712302.txt
+++ /dev/null
@@ -1,199 +0,0 @@
-✅ Processed 0 groups for user admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Orders API called with: {
-
- startDate: undefined,
-
- endDate: undefined,
-
- storeId: undefined,
-
- userRole: 'admin'
-
-}
-
-Admin filtering with groupIds: undefined
-
-Fetching all orders
-
-GET /api/publicities 304 in 143ms
-
-GET /api/user 304 in 37ms
-
-Deliveries returned: 80 items
-
-Customer orders returned from storage: 32 items
-
-GET /api/deliveries 200 in 182ms
-
-Orders returned: 46 items
-
-GET /api/customer-orders 200 in 177ms
-
-GET /api/tasks 200 in 162ms
-
-GET /api/orders 200 in 191ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-GET /api/dlc-products/stats 200 in 180ms
-
-🔍 Querying user_groups for user: admin_local
-
-GET /api/user 304 in 7ms
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getPublicities called with: { year: 2025, groupIds: undefined }
-
-📢 Raw publicities found: 29
-
-🏪 Participations found: 26
-
-✅ Final publicities with participations: 29
-
-📄 Sample publicity: {
-
-
-
-,
-
- pubNumber: '2526',
-
- participations: [ { groupId: 2, groupName: 'Houdemont' } ]
-
-}
-
-GET /api/publicities 200 in 47ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-GET /api/groups 200 in 8ms
-
-HEAD /api/health 200 in 1ms
-
-HEAD /api/health 200 in 0ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-GET /api/user 304 in 33ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 ===== DÉBUT SCAN SCHÉMA BASE DE DONNÉES =====
-
-⏰ Timestamp: 2025-08-12T08:18:10.753Z
-
-❌ ERREUR lors du scan du schéma: TypeError: Cannot read properties of undefined (reading 'query')
-
- at file:///app/dist/index.js:4455:45
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
-GET /api/debug/log-schema 500 in 16ms
-
-HEAD /api/health 200 in 0ms
\ No newline at end of file
diff --git a/attached_assets/Pasted--Querying-user-groups-for-user-admin-local-Found-0-group-assignments-for-user-adm-1754944991616_1754944991617.txt b/attached_assets/Pasted--Querying-user-groups-for-user-admin-local-Found-0-group-assignments-for-user-adm-1754944991616_1754944991617.txt
deleted file mode 100644
index ee9493f..0000000
--- a/attached_assets/Pasted--Querying-user-groups-for-user-admin-local-Found-0-group-assignments-for-user-adm-1754944991616_1754944991617.txt
+++ /dev/null
@@ -1,201 +0,0 @@
-
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Deliveries API called with: {
-
- startDate: undefined,
-
- endDate: undefined,
-
- storeId: undefined,
-
- withBL: undefined,
-
- userRole: 'admin'
-
-}
-
-Admin filtering deliveries with groupIds: undefined
-
-Fetching all deliveries
-
-Deliveries returned: 80 items
-
-GET /api/deliveries 304 in 28ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-📄 SPA: Serving index.html for /[object%20Object]
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-📄 SPA: Serving index.html for /[object%20Object]
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-📄 SPA: Serving index.html for /[object%20Object]
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Orders API called with: {
-
- startDate: '2025-08-01',
-
- endDate: '2025-08-31',
-
- storeId: '1',
-
- userRole: 'admin'
-
-}
-
-Admin filtering with groupIds: [ 1 ]
-
-Fetching orders by date range: 2025-08-01 to 2025-08-31
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-Orders returned: 9 items
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Deliveries API called with: {
-
- startDate: '2025-08-01',
-
- endDate: '2025-08-31',
-
- storeId: '1',
-
- withBL: undefined,
-
- userRole: 'admin'
-
-}
-
-Admin filtering deliveries with groupIds: [ 1 ]
-
-Fetching deliveries by date range: 2025-08-01 to 2025-08-31
-
-GET /api/orders 304 in 23ms
-
-Deliveries returned: 20 items
-
-GET /api/deliveries 304 in 31ms
-
-HEAD /api/health 200 in 0ms
\ No newline at end of file
diff --git a/attached_assets/Pasted--User-related-Environment-related-Registries-Logs-Notifications-Settings-New--1754928661164_1754928661164.txt b/attached_assets/Pasted--User-related-Environment-related-Registries-Logs-Notifications-Settings-New--1754928661164_1754928661164.txt
deleted file mode 100644
index e4f01bb..0000000
--- a/attached_assets/Pasted--User-related-Environment-related-Registries-Logs-Notifications-Settings-New--1754928661164_1754928661164.txt
+++ /dev/null
@@ -1,156 +0,0 @@
-
-
-User-related
-
-
-Environment-related
-
-Registries
-
-Logs
-
-Notifications
-
-Settings
-
-New version available 2.27.9
-DismissSee what's new
-Community Edition
-2.27.6 LTS
-Containers>logiflow-logiflow-1>Logs
-Container logs
-
-
-admin
-Log viewer settings
-Auto-refresh logs
-Wrap lines
-Display timestamps
-Fetch
-All logs
-Search
-Filter...
-Lines
-100
-Actions
-
-
-
-
-🔗 Database initialization: {
-
- NODE_ENV: 'production',
-
- isProduction: true,
-
- hasDbUrl: true,
-
- dbHost: 'logiflow-db'
-
-}
-
-🐳 PRODUCTION: Using standard PostgreSQL
-
-✅ PostgreSQL connection test successful
-
-🐳 PRODUCTION: Using PostgreSQL storage
-
-🐳 PRODUCTION: Local auth configured with PostgreSQL sessions
-
-🐳 PRODUCTION: Starting LogiFlow application
-
-🐳 Environment: { NODE_ENV: 'production', DATABASE_URL: 'Present', PORT: '3000' }
-
-🐳 Serving static files from: /app/dist/public
-
-🐳 PRODUCTION: LogiFlow serving on port 3000
-
-✅ Production admin user found: { id: 'admin_local', username: 'admin', passwordFormat: 'present' }
-
-🔐 Production password comparison { suppliedLength: 5, storedFormat: '21ff482668...' }
-
-✅ Password matched with hash.salt format
-
-✅ Admin password works with current system
-
-HEAD /api/health 200 in 8ms
-
-📄 SPA: Serving index.html for /users
-
-GET /api/user 304 in 7ms
-
-GET /api/user 304 in 7ms
-
-GET /api/user 304 in 6ms
-
-GET /api/user 304 in 9ms
-
-GET /api/groups 304 in 15ms
-
-GET /api/users 404 in 37ms
-
-GET /api/roles 404 in 52ms
-
-GET /api/users 404 in 8ms
-
-GET /api/roles 404 in 6ms
-
-GET /api/user 401 in 2ms
-
-GET /api/user 401 in 2ms
-
-GET /api/default-credentials-check 200 in 2ms
-
-GET /api/user 304 in 8ms
-
-GET /api/deliveries 404 in 7ms
-
-GET /api/deliveries 404 in 5ms
-
-GET /api/deliveries 404 in 8ms
-
-🔐 Production password comparison { suppliedLength: 8, storedFormat: 'c81960e064...' }
-
-❌ No password format matched
-
-POST /api/login 400 in 5ms
-
-GET /api/deliveries 404 in 14ms
-
-🔐 Production password comparison { suppliedLength: 8, storedFormat: 'c81960e064...' }
-
-❌ No password format matched
-
-POST /api/login 400 in 4ms
-
-🔐 Production password comparison { suppliedLength: 8, storedFormat: 'c81960e064...' }
-
-❌ No password format matched
-
-POST /api/login 400 in 5ms
-
-🔐 Production password comparison { suppliedLength: 8, storedFormat: 'c81960e064...' }
-
-❌ No password format matched
-
-POST /api/login 400 in 6ms
-
-🔐 Production password comparison { suppliedLength: 8, storedFormat: 'c81960e064...' }
-
-❌ No password format matched
-
-POST /api/login 400 in 4ms
-
-🔐 Production password comparison { suppliedLength: 8, storedFormat: 'c81960e064...' }
-
-❌ No password format matched
-
-POST /api/login 400 in 4ms
-
-🔐 Production password comparison { suppliedLength: 8, storedFormat: 'c81960e064...' }
-
-❌ No password format matched
-
-POST /api/login 400 in 4ms
-
-HEAD /api/health 200 in 1ms
\ No newline at end of file
diff --git a/attached_assets/Pasted--User-related-Environment-related-Registries-Logs-Notifications-Settings-New--1754937215668_1754937215668.txt b/attached_assets/Pasted--User-related-Environment-related-Registries-Logs-Notifications-Settings-New--1754937215668_1754937215668.txt
deleted file mode 100644
index 788693b..0000000
--- a/attached_assets/Pasted--User-related-Environment-related-Registries-Logs-Notifications-Settings-New--1754937215668_1754937215668.txt
+++ /dev/null
@@ -1,206 +0,0 @@
-
-
-User-related
-
-
-Environment-related
-
-Registries
-
-Logs
-
-Notifications
-
-Settings
-
-New version available 2.27.9
-DismissSee what's new
-Community Edition
-2.27.6 LTS
-Containers>logiflow-logiflow-1>Logs
-Container logs
-
-
-admin
-Log viewer settings
-Auto-refresh logs
-Wrap lines
-Display timestamps
-Fetch
-All logs
-Search
-Filter...
-Lines
-100
-Actions
-
-
-
-
-🔗 Database initialization: {
-
- NODE_ENV: 'production',
-
- isProduction: true,
-
- hasDbUrl: true,
-
- dbHost: 'logiflow-db'
-
-}
-
-🐳 PRODUCTION: Using standard PostgreSQL
-
-✅ PostgreSQL connection test successful
-
-🐳 PRODUCTION: Using PostgreSQL storage
-
-🐳 PRODUCTION: Local auth configured with PostgreSQL sessions
-
-🐳 PRODUCTION: Starting LogiFlow application
-
-🐳 Environment: { NODE_ENV: 'production', DATABASE_URL: 'Present', PORT: '3000' }
-
-🔍 Using development storage and authentication
-
-🔧 Using memory session store for development
-
-🐳 Serving static files from: /app/dist/public
-
-Warning: connect.session() MemoryStore is not
-
-designed for a production environment, as it will leak
-
-memory, and will not scale past a single process.
-
-🐳 PRODUCTION: LogiFlow serving on port 3000
-
-✅ Production admin user found: { id: 'admin_local', username: 'admin', passwordFormat: 'present' }
-
-🔐 Production password comparison { suppliedLength: 5, storedFormat: '63d2ce518b...' }
-
-✅ Password matched with hash.salt format
-
-✅ Admin password works with current system
-
-HEAD /api/health 200 in 5ms
-
-📄 SPA: Serving index.html for /users
-
-GET /api/user 304 in 8ms
-
-GET /api/user 304 in 5ms
-
-GET /api/user 304 in 6ms
-
-GET /api/user 304 in 6ms
-
-GET /api/groups 304 in 16ms
-
-GET /api/roles 304 in 33ms
-
-🔍 getUsersWithRolesAndGroups called
-
-📊 Base users found: 7
-
-🔍 Processing user: admin
-
-🔍 Processing user: ff292
-
-🔍 Processing user: Rudolph
-
-🔍 Processing user: ff579
-
-🔍 Processing user: ff579m
-
-🔍 Processing user: Nicolas
-
-🔍 Processing user: AnneLaure
-
-📊 getUserWithRoles(_1754936203292): { userRoleDataLength: 0 }
-
-📊 getUserWithRoles(admin_local): { userRoleDataLength: 1 }
-
-📊 User ff292 groups: 0
-
-📊 User admin groups: 0
-
-📊 getUserWithRoles(_1753340243216): { userRoleDataLength: 0 }
-
-📊 getUserWithRoles(directionfrouard_1753264272043): { userRoleDataLength: 0 }
-
-📊 getUserWithRoles(_1753266881822): { userRoleDataLength: 0 }
-
-📊 getUserWithRoles(_1753266816257): { userRoleDataLength: 0 }
-
-📊 User Rudolph groups: 1
-
-📊 getUserWithRoles(_1753266851515): { userRoleDataLength: 0 }
-
-📊 User AnneLaure groups: 1
-
-📊 User ff579 groups: 1
-
-📊 User Nicolas groups: 1
-
-📊 User ff579m groups: 1
-
-🔍 Final users with roles and groups: 7
-
-🔐 API /api/users - Returning: { isArray: true, length: 7 }
-
-GET /api/users 304 in 126ms
-
-PUT /api/users/_1754936203292 200 in 15ms
-
-🔍 getUsersWithRolesAndGroups called
-
-📊 Base users found: 7
-
-🔍 Processing user: admin
-
-🔍 Processing user: ff292
-
-🔍 Processing user: Rudolph
-
-🔍 Processing user: ff579
-
-🔍 Processing user: ff579m
-
-🔍 Processing user: Nicolas
-
-🔍 Processing user: AnneLaure
-
-📊 getUserWithRoles(admin_local): { userRoleDataLength: 1 }
-
-📊 getUserWithRoles(_1754936203292): { userRoleDataLength: 0 }
-
-📊 getUserWithRoles(_1753266851515): { userRoleDataLength: 0 }
-
-📊 getUserWithRoles(_1753266881822): { userRoleDataLength: 0 }
-
-📊 getUserWithRoles(directionfrouard_1753264272043): { userRoleDataLength: 0 }
-
-📊 getUserWithRoles(_1753266816257): { userRoleDataLength: 0 }
-
-📊 User admin groups: 0
-
-📊 User ff292 groups: 0
-
-📊 getUserWithRoles(_1753340243216): { userRoleDataLength: 0 }
-
-📊 User Rudolph groups: 1
-
-📊 User Nicolas groups: 1
-
-📊 User ff579m groups: 1
-
-📊 User ff579 groups: 1
-
-📊 User AnneLaure groups: 1
-
-🔍 Final users with roles and groups: 7
-
-🔐 API /api/users - Returning: { isArray: true, length: 7 }
-
-GET /api/users 200 in 40ms
\ No newline at end of file
diff --git a/attached_assets/Pasted--User-system-groups-0-User-AnneLaure-groups-1-Final-users-with-roles-and-groups-7--1754935637981_1754935637981.txt b/attached_assets/Pasted--User-system-groups-0-User-AnneLaure-groups-1-Final-users-with-roles-and-groups-7--1754935637981_1754935637981.txt
deleted file mode 100644
index b7d10c7..0000000
--- a/attached_assets/Pasted--User-system-groups-0-User-AnneLaure-groups-1-Final-users-with-roles-and-groups-7--1754935637981_1754935637981.txt
+++ /dev/null
@@ -1,133 +0,0 @@
-📊 User system groups: 0
-
-📊 User AnneLaure groups: 1
-
-🔍 Final users with roles and groups: 7
-
-🔐 API /api/users - Returning: { isArray: true, length: 7 }
-
-GET /api/users 200 in 80ms
-
-Error deleting user: error: update or delete on table "users" violates foreign key constraint "database_backups_created_by_fkey" on table "database_backups"
-
- at /app/node_modules/pg/lib/client.js:545:17
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async file:///app/dist/index.js:1109:11
-
- at async NodePgSession.transaction (file:///app/node_modules/drizzle-orm/node-postgres/session.js:142:22)
-
- at async DatabaseStorage.deleteUser (file:///app/dist/index.js:1090:9)
-
- at async file:///app/dist/index.js:4095:7 {
-
- length: 327,
-
- severity: 'ERROR',
-
- code: '23503',
-
- detail: 'Key (id)=(system) is still referenced from table "database_backups".',
-
- hint: undefined,
-
- position: undefined,
-
- internalPosition: undefined,
-
- internalQuery: undefined,
-
- where: undefined,
-
- schema: 'public',
-
- table: 'database_backups',
-
- column: undefined,
-
- dataType: undefined,
-
- constraint: 'database_backups_created_by_fkey',
-
- file: 'ri_triggers.c',
-
- line: '2609',
-
- routine: 'ri_ReportViolation'
-
-}
-
-DELETE /api/users/system 500 in 28ms
-
-HEAD /api/health 200 in 1ms
-
-Error creating user: ZodError: [
-
- {
-
- "validation": "email",
-
- "code": "invalid_string",
-
- "message": "Invalid email",
-
- "path": [
-
- "email"
-
- ]
-
- }
-
-]
-
- at get error [as error] (file:///app/node_modules/zod/v3/types.js:39:31)
-
- at ZodObject.parse (file:///app/node_modules/zod/v3/types.js:114:22)
-
- at file:///app/dist/index.js:3988:41
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
-
- issues: [
-
- {
-
- validation: 'email',
-
- code: 'invalid_string',
-
- message: 'Invalid email',
-
- path: [Array]
-
- }
-
- ],
-
- addIssue: [Function (anonymous)],
-
- addIssues: [Function (anonymous)],
-
- errors: [
-
- {
-
- validation: 'email',
-
- code: 'invalid_string',
-
- message: 'Invalid email',
-
- path: [Array]
-
- }
-
- ]
-
-}
-
-POST /api/users 400 in 26ms
-
-HEAD /api/health 200 in 1ms
\ No newline at end of file
diff --git a/attached_assets/Pasted--getUserWithGroups-called-for-user-admin-local-Querying-user-groups-for-user-adm-1754945126235_1754945126235.txt b/attached_assets/Pasted--getUserWithGroups-called-for-user-admin-local-Querying-user-groups-for-user-adm-1754945126235_1754945126235.txt
deleted file mode 100644
index f4c4e12..0000000
--- a/attached_assets/Pasted--getUserWithGroups-called-for-user-admin-local-Querying-user-groups-for-user-adm-1754945126235_1754945126235.txt
+++ /dev/null
@@ -1,202 +0,0 @@
-
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Deliveries API called with: {
-
- startDate: undefined,
-
- endDate: undefined,
-
- storeId: undefined,
-
- withBL: undefined,
-
- userRole: 'admin'
-
-}
-
-Admin filtering deliveries with groupIds: undefined
-
-Fetching all deliveries
-
-Deliveries returned: 80 items
-
-GET /api/deliveries 304 in 44ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-📄 SPA: Serving index.html for /[object%20Object]
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-📄 SPA: Serving index.html for /[object%20Object]
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-📄 SPA: Serving index.html for /[object%20Object]
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Orders API called with: {
-
- startDate: '2025-08-01',
-
- endDate: '2025-08-31',
-
- storeId: '1',
-
- userRole: 'admin'
-
-}
-
-Admin filtering with groupIds: [ 1 ]
-
-Fetching orders by date range: 2025-08-01 to 2025-08-31
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Deliveries API called with: {
-
- startDate: '2025-08-01',
-
- endDate: '2025-08-31',
-
- storeId: '1',
-
- withBL: undefined,
-
- userRole: 'admin'
-
-}
-
-Admin filtering deliveries with groupIds: [ 1 ]
-
-Fetching deliveries by date range: 2025-08-01 to 2025-08-31
-
-Orders returned: 9 items
-
-GET /api/orders 304 in 23ms
-
-Deliveries returned: 20 items
-
-GET /api/deliveries 304 in 36ms
-
diff --git a/attached_assets/Pasted--getUserWithGroups-called-for-user-admin-local-Querying-user-groups-for-user-adm-1755002698355_1755002698355.txt b/attached_assets/Pasted--getUserWithGroups-called-for-user-admin-local-Querying-user-groups-for-user-adm-1755002698355_1755002698355.txt
deleted file mode 100644
index 773a876..0000000
--- a/attached_assets/Pasted--getUserWithGroups-called-for-user-admin-local-Querying-user-groups-for-user-adm-1755002698355_1755002698355.txt
+++ /dev/null
@@ -1,199 +0,0 @@
-
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-📄 SPA: Serving index.html for /bl-reconciliation
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-GET /api/user 304 in 7ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-GET /api/user 304 in 8ms
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-GET /api/suppliers 304 in 31ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-GET /api/user 304 in 5ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-GET /api/user 304 in 9ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Deliveries API called with: {
-
- startDate: undefined,
-
- endDate: undefined,
-
- storeId: '1',
-
- withBL: undefined,
-
- userRole: 'admin'
-
-}
-
-Admin filtering deliveries with groupIds: [ 1 ]
-
-Fetching all deliveries
-
-Deliveries returned: 44 items
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-GET /api/deliveries 304 in 67ms
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-GET /api/groups 304 in 26ms
-
-HEAD /api/health 200 in 0ms
\ No newline at end of file
diff --git a/attached_assets/Pasted--group-created-at-2025-07-22-11-09-08-977622-group-updated-at-2025-07-28-1-1754942841066_1754942841066.txt b/attached_assets/Pasted--group-created-at-2025-07-22-11-09-08-977622-group-updated-at-2025-07-28-1-1754942841066_1754942841066.txt
deleted file mode 100644
index 56daa6f..0000000
--- a/attached_assets/Pasted--group-created-at-2025-07-22-11-09-08-977622-group-updated-at-2025-07-28-1-1754942841066_1754942841066.txt
+++ /dev/null
@@ -1,201 +0,0 @@
-
-
- group_created_at: '2025-07-22 11:09:08.977622',
-
- group_updated_at: '2025-07-28 18:25:49.452346'
-
- }
-
-]
-
-✅ Processed 1 groups for user _1753266816257
-
-🔐 API /api/users - Returning: { isArray: true, length: 7, totalGroups: 6 }
-
-GET /api/users 304 in 81ms
-
-HEAD /api/health 200 in 1ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 POST /api/users - Creating new user
-
-📥 Request body: {
-
- "email": "",
-
- "firstName": "",
-
- "lastName": "",
-
- "username": "ff292m",
-
- "password": "ff292m",
-
- "role": "manager",
-
- "id": "_1754942821925"
-
-}
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 Parsing user data...
-
-✅ User data parsed successfully
-
-🔒 Hashing password...
-
-✅ Password hashed successfully
-
-🔍 Generated user ID: _1754942821925
-
-🔍 Creating user in database...
-
-🔍 Storage createUser called with: ff292m
-
-❌ Storage createUser error: error: duplicate key value violates unique constraint "users_email_key"
-
- at /app/node_modules/pg-pool/index.js:45:11
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
-
- at async DatabaseStorage.createUser (file:///app/dist/index.js:989:26)
-
- at async file:///app/dist/index.js:3993:23 {
-
- length: 192,
-
- severity: 'ERROR',
-
- code: '23505',
-
- detail: 'Key (email)=() already exists.',
-
- hint: undefined,
-
- position: undefined,
-
- internalPosition: undefined,
-
- internalQuery: undefined,
-
- where: undefined,
-
- schema: 'public',
-
- table: 'users',
-
- column: undefined,
-
- dataType: undefined,
-
- constraint: 'users_email_key',
-
- file: 'nbtinsert.c',
-
- line: '664',
-
- routine: '_bt_check_unique'
-
-}
-
-❌ Storage error code: 23505
-
-❌ Storage error constraint: users_email_key
-
-❌ Error creating user: error: duplicate key value violates unique constraint "users_email_key"
-
- at /app/node_modules/pg-pool/index.js:45:11
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
-
- at async DatabaseStorage.createUser (file:///app/dist/index.js:989:26)
-
- at async file:///app/dist/index.js:3993:23 {
-
- length: 192,
-
- severity: 'ERROR',
-
- code: '23505',
-
- detail: 'Key (email)=() already exists.',
-
- hint: undefined,
-
- position: undefined,
-
- internalPosition: undefined,
-
- internalQuery: undefined,
-
- where: undefined,
-
- schema: 'public',
-
- table: 'users',
-
- column: undefined,
-
- dataType: undefined,
-
- constraint: 'users_email_key',
-
- file: 'nbtinsert.c',
-
- line: '664',
-
- routine: '_bt_check_unique'
-
-}
-
-❌ Error type: DatabaseError
-
-❌ Error code: 23505
-
-❌ Error constraint: users_email_key
-
-❌ Error stack: error: duplicate key value violates unique constraint "users_email_key"
-
- at /app/node_modules/pg-pool/index.js:45:11
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
-
- at async DatabaseStorage.createUser (file:///app/dist/index.js:989:26)
-
- at async file:///app/dist/index.js:3993:23
-
-POST /api/users 409 in 109ms
\ No newline at end of file
diff --git a/attached_assets/Pasted--nocodb-table-id-my7zunxprumahmm-nocodb-table-name-CommandeH-invoice-column-n-1755008314981_1755008314981.txt b/attached_assets/Pasted--nocodb-table-id-my7zunxprumahmm-nocodb-table-name-CommandeH-invoice-column-n-1755008314981_1755008314981.txt
deleted file mode 100644
index b51e61a..0000000
--- a/attached_assets/Pasted--nocodb-table-id-my7zunxprumahmm-nocodb-table-name-CommandeH-invoice-column-n-1755008314981_1755008314981.txt
+++ /dev/null
@@ -1,204 +0,0 @@
- nocodb_table_id: 'my7zunxprumahmm',
-
- nocodb_table_name: 'CommandeH',
-
- invoice_column_name: 'RefFacture',
-
- group_created_at: '2025-07-22 11:09:08.977622',
-
- group_updated_at: '2025-08-12 09:39:32.989'
-
- }
-
-]
-
-✅ Processed 1 groups for user _1753266816257
-
-🔍 getUserWithGroups called for user: _1753266816257
-
-🔍 Querying user_groups for user: _1753266816257
-
-🔍 Querying user_groups for user: _1753266816257
-
-🔍 Found 1 group assignments for user _1753266816257
-
-🔍 Raw query result: [
-
- {
-
- user_id: '_1753266816257',
-
- group_id: 2,
-
- group_id_ref: 2,
-
- group_name: 'Houdemont',
-
- group_color: '#455A64',
-
- nocodb_config_id: 1,
-
- nocodb_table_id: 'my7zunxprumahmm',
-
- nocodb_table_name: 'CommandeH',
-
- invoice_column_name: 'RefFacture',
-
- group_created_at: '2025-07-22 11:09:08.977622',
-
- group_updated_at: '2025-08-12 09:39:32.989'
-
- }
-
-]
-
-✅ Processed 1 groups for user _1753266816257
-
-🔍 getUserWithGroups called for user: _1753266816257
-
-🔍 Found 1 group assignments for user _1753266816257
-
-🔍 Raw query result: [
-
- {
-
- user_id: '_1753266816257',
-
- group_id: 2,
-
- group_id_ref: 2,
-
- group_name: 'Houdemont',
-
- group_color: '#455A64',
-
- nocodb_config_id: 1,
-
- nocodb_table_id: 'my7zunxprumahmm',
-
- nocodb_table_name: 'CommandeH',
-
- invoice_column_name: 'RefFacture',
-
- group_created_at: '2025-07-22 11:09:08.977622',
-
- group_updated_at: '2025-08-12 09:39:32.989'
-
- }
-
-]
-
-✅ Processed 1 groups for user _1753266816257
-
-🔍 getUserWithGroups called for user: _1753266816257
-
-🔍 Querying user_groups for user: _1753266816257
-
-🔍 Found 1 group assignments for user _1753266816257
-
-🔍 Raw query result: [
-
- {
-
- user_id: '_1753266816257',
-
- group_id: 2,
-
- group_id_ref: 2,
-
- group_name: 'Houdemont',
-
- group_color: '#455A64',
-
- nocodb_config_id: 1,
-
- nocodb_table_id: 'my7zunxprumahmm',
-
- nocodb_table_name: 'CommandeH',
-
- invoice_column_name: 'RefFacture',
-
- group_created_at: '2025-07-22 11:09:08.977622',
-
- group_updated_at: '2025-08-12 09:39:32.989'
-
- }
-
-]
-
-✅ Processed 1 groups for user _1753266816257
-
-🔍 Querying user_groups for user: _1753266816257
-
-🔍 Found 1 group assignments for user _1753266816257
-
-🔍 Raw query result: [
-
- {
-
- user_id: '_1753266816257',
-
- group_id: 2,
-
- group_id_ref: 2,
-
- group_name: 'Houdemont',
-
- group_color: '#455A64',
-
- nocodb_config_id: 1,
-
- nocodb_table_id: 'my7zunxprumahmm',
-
- nocodb_table_name: 'CommandeH',
-
- invoice_column_name: 'RefFacture',
-
- group_created_at: '2025-07-22 11:09:08.977622',
-
- group_updated_at: '2025-08-12 09:39:32.989'
-
- }
-
-]
-
-✅ Processed 1 groups for user _1753266816257
-
-🔍 DLC Products API called with: {
-
- userId: '_1753266816257',
-
- userRole: 'employee',
-
- userGroups: [ { groupId: 2, groupName: 'Houdemont' } ],
-
- groupIds: [ 2 ],
-
- filters: {},
-
- queryStoreId: undefined
-
-}
-
-GET /api/dlc-products/stats 304 in 18ms
-
-📋 DLC Products returned: 133 items
-
-📋 Sample DLC products groupIds: [
-
- { id: 178, name: 'Nesta grenier strawberry aloe vera', groupId: 2 },
-
- { id: 48, name: 'Gressins sésame', groupId: 2 },
-
- { id: 154, name: 'M&m’s crispy 240g', groupId: 2 }
-
-]
-
-GET /api/dlc-products 304 in 26ms
-
-HEAD /api/health 200 in 1ms
-
-
-
-
-
\ No newline at end of file
diff --git a/attached_assets/Pasted--nocodb-table-name-CommandeH-invoice-column-name-RefFacture-group-created-a-1755011493131_1755011493131.txt b/attached_assets/Pasted--nocodb-table-name-CommandeH-invoice-column-name-RefFacture-group-created-a-1755011493131_1755011493131.txt
deleted file mode 100644
index 3c17536..0000000
--- a/attached_assets/Pasted--nocodb-table-name-CommandeH-invoice-column-name-RefFacture-group-created-a-1755011493131_1755011493131.txt
+++ /dev/null
@@ -1,204 +0,0 @@
- nocodb_table_name: 'CommandeH',
-
- invoice_column_name: 'RefFacture',
-
- group_created_at: '2025-07-22 11:09:08.977622',
-
- group_updated_at: '2025-08-12 09:39:32.989'
-
- }
-
-]
-
-✅ Processed 1 groups for user _1753266816257
-
-🔍 getUserWithGroups called for user: _1753266816257
-
-🔍 Querying user_groups for user: _1753266816257
-
-🔍 Found 1 group assignments for user _1753266816257
-
-🔍 Raw query result: [
-
- {
-
- user_id: '_1753266816257',
-
- group_id: 2,
-
- group_id_ref: 2,
-
- group_name: 'Houdemont',
-
- group_color: '#455A64',
-
- nocodb_config_id: 1,
-
- nocodb_table_id: 'my7zunxprumahmm',
-
- nocodb_table_name: 'CommandeH',
-
- invoice_column_name: 'RefFacture',
-
- group_created_at: '2025-07-22 11:09:08.977622',
-
- group_updated_at: '2025-08-12 09:39:32.989'
-
- }
-
-]
-
-✅ Processed 1 groups for user _1753266816257
-
-🔍 DLC Products API called with: {
-
- userId: '_1753266816257',
-
- userRole: 'employee',
-
- userGroups: [ { groupId: 2, groupName: 'Houdemont' } ],
-
- groupIds: [ 2 ],
-
- filters: {},
-
- queryStoreId: undefined
-
-}
-
-📋 DLC Products returned: 133 items
-
-📋 Sample DLC products groupIds: [
-
- { id: 178, name: 'Nesta grenier strawberry aloe vera', groupId: 2 },
-
- { id: 48, name: 'Gressins sésame', groupId: 2 },
-
- { id: 154, name: 'M&m’s crispy 240g', groupId: 2 }
-
-]
-
-🔍 getUserWithGroups called for user: _1753266816257
-
-GET /api/dlc-products 304 in 34ms
-
-🔍 Querying user_groups for user: _1753266816257
-
-🔍 Found 1 group assignments for user _1753266816257
-
-🔍 Raw query result: [
-
- {
-
- user_id: '_1753266816257',
-
- group_id: 2,
-
- group_id_ref: 2,
-
- group_name: 'Houdemont',
-
- group_color: '#455A64',
-
- nocodb_config_id: 1,
-
- nocodb_table_id: 'my7zunxprumahmm',
-
- nocodb_table_name: 'CommandeH',
-
- invoice_column_name: 'RefFacture',
-
- group_created_at: '2025-07-22 11:09:08.977622',
-
- group_updated_at: '2025-08-12 09:39:32.989'
-
- }
-
-]
-
-✅ Processed 1 groups for user _1753266816257
-
-🔍 getUserWithGroups called for user: _1753266816257
-
-🔍 Querying user_groups for user: _1753266816257
-
-🔍 Found 1 group assignments for user _1753266816257
-
-🔍 Raw query result: [
-
- {
-
- user_id: '_1753266816257',
-
- group_id: 2,
-
- group_id_ref: 2,
-
- group_name: 'Houdemont',
-
- group_color: '#455A64',
-
- nocodb_config_id: 1,
-
- nocodb_table_id: 'my7zunxprumahmm',
-
- nocodb_table_name: 'CommandeH',
-
- invoice_column_name: 'RefFacture',
-
- group_created_at: '2025-07-22 11:09:08.977622',
-
- group_updated_at: '2025-08-12 09:39:32.989'
-
- }
-
-]
-
-✅ Processed 1 groups for user _1753266816257
-
-🔍 getUserWithGroups called for user: _1753266816257
-
-🔍 Querying user_groups for user: _1753266816257
-
-🔍 Found 1 group assignments for user _1753266816257
-
-🔍 Raw query result: [
-
- {
-
- user_id: '_1753266816257',
-
- group_id: 2,
-
- group_id_ref: 2,
-
- group_name: 'Houdemont',
-
- group_color: '#455A64',
-
- nocodb_config_id: 1,
-
- nocodb_table_id: 'my7zunxprumahmm',
-
- nocodb_table_name: 'CommandeH',
-
- invoice_column_name: 'RefFacture',
-
- group_created_at: '2025-07-22 11:09:08.977622',
-
- group_updated_at: '2025-08-12 09:39:32.989'
-
- }
-
-]
-
-✅ Processed 1 groups for user _1753266816257
-
-GET /api/dlc-products/stats 304 in 45ms
-
-HEAD /api/health 200 in 1ms
-
-
-
-
-
\ No newline at end of file
diff --git a/attached_assets/Pasted--status-500-message-connect-ECONNREFUSED-172-20-0-10-443-error-ErrorEvent--1754925087618_1754925087618.txt b/attached_assets/Pasted--status-500-message-connect-ECONNREFUSED-172-20-0-10-443-error-ErrorEvent--1754925087618_1754925087618.txt
deleted file mode 100644
index 975f022..0000000
--- a/attached_assets/Pasted--status-500-message-connect-ECONNREFUSED-172-20-0-10-443-error-ErrorEvent--1754925087618_1754925087618.txt
+++ /dev/null
@@ -1,199 +0,0 @@
- status: 500,
-
- message: 'connect ECONNREFUSED 172.20.0.10:443',
-
- error: ErrorEvent {
-
- [Symbol(kTarget)]: WebSocket {
-
- _events: [Object: null prototype],
-
- _eventsCount: 4,
-
- _maxListeners: undefined,
-
- _binaryType: 'arraybuffer',
-
- _closeCode: 1006,
-
- _closeFrameReceived: false,
-
- _closeFrameSent: false,
-
- _closeMessage: ,
-
- _closeTimer: null,
-
- _errorEmitted: true,
-
- _extensions: {},
-
- _paused: false,
-
- _protocol: '',
-
- _readyState: 3,
-
- _receiver: null,
-
- _sender: null,
-
- _socket: null,
-
- _bufferedAmount: 0,
-
- _isServer: false,
-
- _redirects: 0,
-
- _autoPong: true,
-
- _url: 'wss://logiflow-db/v2',
-
- _req: null,
-
- [Symbol(shapeMode)]: false,
-
- [Symbol(kCapture)]: false
-
- },
-
- [Symbol(kType)]: 'error',
-
- [Symbol(kError)]: Error: connect ECONNREFUSED 172.20.0.10:443
-
- at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1611:16) {
-
- errno: -111,
-
- code: 'ECONNREFUSED',
-
- syscall: 'connect',
-
- address: '172.20.0.10',
-
- port: 443
-
- },
-
- [Symbol(kMessage)]: 'connect ECONNREFUSED 172.20.0.10:443'
-
- }
-
-}
-
-POST /api/login 500 in 9ms
-
-Error: connect ECONNREFUSED 172.20.0.10:443
-
- at file:///app/node_modules/@neondatabase/serverless/index.mjs:1345:74
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async NeonPreparedQuery.execute (file:///app/node_modules/drizzle-orm/neon-serverless/session.js:76:20)
-
- at async DatabaseStorage.getUserByUsername (file:///app/dist/index.js:893:20)
-
- at async Strategy._verify (file:///app/dist/index.js:2461:24)
-
-Server error: {
-
- status: 500,
-
- message: 'connect ECONNREFUSED 172.20.0.10:443',
-
- error: ErrorEvent {
-
- [Symbol(kTarget)]: WebSocket {
-
- _events: [Object: null prototype],
-
- _eventsCount: 4,
-
- _maxListeners: undefined,
-
- _binaryType: 'arraybuffer',
-
- _closeCode: 1006,
-
- _closeFrameReceived: false,
-
- _closeFrameSent: false,
-
- _closeMessage: ,
-
- _closeTimer: null,
-
- _errorEmitted: true,
-
- _extensions: {},
-
- _paused: false,
-
- _protocol: '',
-
- _readyState: 3,
-
- _receiver: null,
-
- _sender: null,
-
- _socket: null,
-
- _bufferedAmount: 0,
-
- _isServer: false,
-
- _redirects: 0,
-
- _autoPong: true,
-
- _url: 'wss://logiflow-db/v2',
-
- _req: null,
-
- [Symbol(shapeMode)]: false,
-
- [Symbol(kCapture)]: false
-
- },
-
- [Symbol(kType)]: 'error',
-
- [Symbol(kError)]: Error: connect ECONNREFUSED 172.20.0.10:443
-
- at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1611:16) {
-
- errno: -111,
-
- code: 'ECONNREFUSED',
-
- syscall: 'connect',
-
- address: '172.20.0.10',
-
- port: 443
-
- },
-
- [Symbol(kMessage)]: 'connect ECONNREFUSED 172.20.0.10:443'
-
- }
-
-}
-
-POST /api/login 500 in 23ms
-
-Error: connect ECONNREFUSED 172.20.0.10:443
-
- at file:///app/node_modules/@neondatabase/serverless/index.mjs:1345:74
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async NeonPreparedQuery.execute (file:///app/node_modules/drizzle-orm/neon-serverless/session.js:76:20)
-
- at async DatabaseStorage.getUserByUsername (file:///app/dist/index.js:893:20)
-
- at async Strategy._verify (file:///app/dist/index.js:2461:24)
-
-HEAD /api/health 200 in 1ms
\ No newline at end of file
diff --git a/attached_assets/Pasted-Actions-Querying-user-groups-for-user-admin-local-Found-0-group-assignme-1754945532656_1754945532656.txt b/attached_assets/Pasted-Actions-Querying-user-groups-for-user-admin-local-Found-0-group-assignme-1754945532656_1754945532656.txt
deleted file mode 100644
index 4de1176..0000000
--- a/attached_assets/Pasted-Actions-Querying-user-groups-for-user-admin-local-Found-0-group-assignme-1754945532656_1754945532656.txt
+++ /dev/null
@@ -1,205 +0,0 @@
-Actions
-
-
-
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Orders API called with: {
-
- startDate: '2025-08-01',
-
- endDate: '2025-08-31',
-
- storeId: '1',
-
- userRole: 'admin'
-
-}
-
-Admin filtering with groupIds: [ 1 ]
-
-Fetching orders by date range: 2025-08-01 to 2025-08-31
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Deliveries API called with: {
-
- startDate: '2025-08-01',
-
- endDate: '2025-08-31',
-
- storeId: '1',
-
- withBL: undefined,
-
- userRole: 'admin'
-
-}
-
-Admin filtering deliveries with groupIds: [ 1 ]
-
-Fetching deliveries by date range: 2025-08-01 to 2025-08-31
-
-Orders returned: 9 items
-
-Deliveries returned: 20 items
-
-GET /api/orders 304 in 32ms
-
-GET /api/deliveries 304 in 30ms
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-GET /api/user 304 in 45ms
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Orders API called with: {
-
- startDate: '2025-08-01',
-
- endDate: '2025-08-31',
-
- storeId: '1',
-
- userRole: 'admin'
-
-}
-
-Admin filtering with groupIds: [ 1 ]
-
-Fetching orders by date range: 2025-08-01 to 2025-08-31
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Deliveries API called with: {
-
- startDate: '2025-08-01',
-
- endDate: '2025-08-31',
-
- storeId: '1',
-
- withBL: undefined,
-
- userRole: 'admin'
-
-}
-
-Admin filtering deliveries with groupIds: [ 1 ]
-
-Fetching deliveries by date range: 2025-08-01 to 2025-08-31
-
-Orders returned: 9 items
-
-Deliveries returned: 20 items
-
-GET /api/orders 304 in 23ms
-
-GET /api/deliveries 304 in 22ms
-
diff --git a/attached_assets/Pasted-Administration-User-related-Environment-related-Registries-Logs-Notifications-Se-1754927673709_1754927673710.txt b/attached_assets/Pasted-Administration-User-related-Environment-related-Registries-Logs-Notifications-Se-1754927673709_1754927673710.txt
deleted file mode 100644
index 4acd120..0000000
--- a/attached_assets/Pasted-Administration-User-related-Environment-related-Registries-Logs-Notifications-Se-1754927673709_1754927673710.txt
+++ /dev/null
@@ -1,158 +0,0 @@
-Administration
-
-User-related
-
-
-Environment-related
-
-Registries
-
-Logs
-
-Notifications
-
-Settings
-
-New version available 2.27.9
-DismissSee what's new
-Community Edition
-2.27.6 LTS
-Containers>logiflow-logiflow-1>Logs
-Container logs
-
-
-admin
-Log viewer settings
-Auto-refresh logs
-Wrap lines
-Display timestamps
-Fetch
-All logs
-Search
-Filter...
-Lines
-100
-Actions
-
-
-
-
-🔗 Database initialization: {
-
- NODE_ENV: 'production',
-
- isProduction: true,
-
- hasDbUrl: true,
-
- dbHost: 'logiflow-db'
-
-}
-
-🐳 PRODUCTION: Using standard PostgreSQL
-
-✅ PostgreSQL connection test successful
-
-🐳 PRODUCTION: Using PostgreSQL storage
-
-🐳 PRODUCTION: Local auth configured with PostgreSQL sessions
-
-🐳 PRODUCTION: Starting LogiFlow application
-
-🐳 Environment: { NODE_ENV: 'production', DATABASE_URL: 'Present', PORT: '3000' }
-
-🐳 Serving static files from: /app/dist/public
-
-🐳 PRODUCTION: LogiFlow serving on port 3000
-
-✅ Production admin user found: { id: 'admin_local', username: 'admin', passwordFormat: 'present' }
-
-🔐 Production password comparison { suppliedLength: 5, storedFormat: '21ff482668...' }
-
-✅ Password matched with hash.salt format
-
-✅ Admin password works with current system
-
-HEAD /api/health 200 in 5ms
-
-GET /api/user 401 in 24ms
-
-🔐 Production password comparison { suppliedLength: 9, storedFormat: '21ff482668...' }
-
-❌ No password format matched
-
-POST /api/login 400 in 60ms
-
-🔐 Production password comparison { suppliedLength: 5, storedFormat: '21ff482668...' }
-
-✅ Password matched with hash.salt format
-
-POST /api/login 200 in 69ms
-
-Server error: {
-
- status: 500,
-
- message: 'column user_groups.created_at does not exist',
-
- error: error: column user_groups.created_at does not exist
-
- at /app/node_modules/pg-pool/index.js:45:11
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
-
- at async DatabaseStorage.getUserWithGroups (file:///app/dist/index.js:1364:28)
-
- at async file:///app/dist/index.js:3046:20 {
-
- length: 120,
-
- severity: 'ERROR',
-
- code: '42703',
-
- detail: undefined,
-
- hint: undefined,
-
- position: '59',
-
- internalPosition: undefined,
-
- internalQuery: undefined,
-
- where: undefined,
-
- schema: undefined,
-
- table: undefined,
-
- column: undefined,
-
- dataType: undefined,
-
- constraint: undefined,
-
- file: 'parse_relation.c',
-
- line: '3665',
-
- routine: 'errorMissingColumn'
-
- }
-
-}
-
-error: column user_groups.created_at does not exist
-
- at /app/node_modules/pg-pool/index.js:45:11
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
-
- at async DatabaseStorage.getUserWithGroups (file:///app/dist/index.js:1364:28)
-
- at async file:///app/dist/index.js:3046:20
\ No newline at end of file
diff --git a/attached_assets/Pasted-Administration-User-related-Environment-related-Registries-Logs-Notifications-Se-1754944003568_1754944003569.txt b/attached_assets/Pasted-Administration-User-related-Environment-related-Registries-Logs-Notifications-Se-1754944003568_1754944003569.txt
deleted file mode 100644
index 6d26975..0000000
--- a/attached_assets/Pasted-Administration-User-related-Environment-related-Registries-Logs-Notifications-Se-1754944003568_1754944003569.txt
+++ /dev/null
@@ -1,238 +0,0 @@
-Administration
-
-User-related
-
-
-Environment-related
-
-Registries
-
-Logs
-
-Notifications
-
-Settings
-
-New version available 2.27.9
-DismissSee what's new
-Community Edition
-2.27.6 LTS
-Containers>logiflow-logiflow-1>Logs
-Container logs
-
-
-admin
-Log viewer settings
-Auto-refresh logs
-Wrap lines
-Display timestamps
-Fetch
-All logs
-Search
-Filter...
-Lines
-100
-Actions
-
-
-
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Customer orders - Admin filtering by store: { storeId: '1', groupIds: [ 1 ] }
-
-Customer orders returned from storage: 9 items
-
-GET /api/customer-orders 304 in 12ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-GET /api/user 304 in 6ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-GET /api/user 304 in 4ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-GET /api/user 304 in 8ms
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Orders API called with: {
-
- startDate: '2025-08-01',
-
- endDate: '2025-08-31',
-
- storeId: undefined,
-
- userRole: 'admin'
-
-}
-
-Admin filtering with groupIds: undefined
-
-Fetching orders by date range: 2025-08-01 to 2025-08-31
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-Orders returned: 15 items
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Deliveries API called with: {
-
- startDate: '2025-08-01',
-
- endDate: '2025-08-31',
-
- storeId: undefined,
-
- withBL: undefined,
-
- userRole: 'admin'
-
-}
-
-Admin filtering deliveries with groupIds: undefined
-
-Fetching deliveries by date range: 2025-08-01 to 2025-08-31
-
-GET /api/orders 304 in 27ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-GET /api/stats/monthly 304 in 33ms
-
-GET /api/user 304 in 9ms
-
-Deliveries returned: 40 items
-
-GET /api/deliveries 304 in 36ms
\ No newline at end of file
diff --git a/attached_assets/Pasted-Error-ERR-MODULE-NOT-FOUND-Cannot-find-package-vite-imported-from-app-dist-index-js-at--1754924794519_1754924794519.txt b/attached_assets/Pasted-Error-ERR-MODULE-NOT-FOUND-Cannot-find-package-vite-imported-from-app-dist-index-js-at--1754924794519_1754924794519.txt
deleted file mode 100644
index d33c8ac..0000000
--- a/attached_assets/Pasted-Error-ERR-MODULE-NOT-FOUND-Cannot-find-package-vite-imported-from-app-dist-index-js-at--1754924794519_1754924794519.txt
+++ /dev/null
@@ -1,188 +0,0 @@
-Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'vite' imported from /app/dist/index.js
-
- at packageResolve (node:internal/modules/esm/resolve:873:9)
-
- at moduleResolve (node:internal/modules/esm/resolve:946:18)
-
- at defaultResolve (node:internal/modules/esm/resolve:1188:11)
-
- at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:642:12)
-
- at #cachedDefaultResolve (node:internal/modules/esm/loader:591:25)
-
- at ModuleLoader.resolve (node:internal/modules/esm/loader:574:38)
-
- at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:236:38)
-
- at ModuleJob._link (node:internal/modules/esm/module_job:130:49) {
-
- code: 'ERR_MODULE_NOT_FOUND'
-
-}
-
-Node.js v20.19.4
-
-node:internal/modules/esm/resolve:873
-
- throw new ERR_MODULE_NOT_FOUND(packageName, fileURLToPath(base), null);
-
-
-
-^
-
-Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'vite' imported from /app/dist/index.js
-
- at packageResolve (node:internal/modules/esm/resolve:873:9)
-
- at moduleResolve (node:internal/modules/esm/resolve:946:18)
-
- at defaultResolve (node:internal/modules/esm/resolve:1188:11)
-
- at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:642:12)
-
- at #cachedDefaultResolve (node:internal/modules/esm/loader:591:25)
-
- at ModuleLoader.resolve (node:internal/modules/esm/loader:574:38)
-
- at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:236:38)
-
- at ModuleJob._link (node:internal/modules/esm/module_job:130:49) {
-
- code: 'ERR_MODULE_NOT_FOUND'
-
-}
-
-Node.js v20.19.4
-
-node:internal/modules/esm/resolve:873
-
- throw new ERR_MODULE_NOT_FOUND(packageName, fileURLToPath(base), null);
-
-
-
-^
-
-Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'vite' imported from /app/dist/index.js
-
- at packageResolve (node:internal/modules/esm/resolve:873:9)
-
- at moduleResolve (node:internal/modules/esm/resolve:946:18)
-
- at defaultResolve (node:internal/modules/esm/resolve:1188:11)
-
- at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:642:12)
-
- at #cachedDefaultResolve (node:internal/modules/esm/loader:591:25)
-
- at ModuleLoader.resolve (node:internal/modules/esm/loader:574:38)
-
- at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:236:38)
-
- at ModuleJob._link (node:internal/modules/esm/module_job:130:49) {
-
- code: 'ERR_MODULE_NOT_FOUND'
-
-}
-
-Node.js v20.19.4
-
-node:internal/modules/esm/resolve:873
-
- throw new ERR_MODULE_NOT_FOUND(packageName, fileURLToPath(base), null);
-
-
-
-^
-
-Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'vite' imported from /app/dist/index.js
-
- at packageResolve (node:internal/modules/esm/resolve:873:9)
-
- at moduleResolve (node:internal/modules/esm/resolve:946:18)
-
- at defaultResolve (node:internal/modules/esm/resolve:1188:11)
-
- at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:642:12)
-
- at #cachedDefaultResolve (node:internal/modules/esm/loader:591:25)
-
- at ModuleLoader.resolve (node:internal/modules/esm/loader:574:38)
-
- at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:236:38)
-
- at ModuleJob._link (node:internal/modules/esm/module_job:130:49) {
-
- code: 'ERR_MODULE_NOT_FOUND'
-
-}
-
-Node.js v20.19.4
-
-node:internal/modules/esm/resolve:873
-
- throw new ERR_MODULE_NOT_FOUND(packageName, fileURLToPath(base), null);
-
-
-
-^
-
-Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'vite' imported from /app/dist/index.js
-
- at packageResolve (node:internal/modules/esm/resolve:873:9)
-
- at moduleResolve (node:internal/modules/esm/resolve:946:18)
-
- at defaultResolve (node:internal/modules/esm/resolve:1188:11)
-
- at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:642:12)
-
- at #cachedDefaultResolve (node:internal/modules/esm/loader:591:25)
-
- at ModuleLoader.resolve (node:internal/modules/esm/loader:574:38)
-
- at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:236:38)
-
- at ModuleJob._link (node:internal/modules/esm/module_job:130:49) {
-
- code: 'ERR_MODULE_NOT_FOUND'
-
-}
-
-Node.js v20.19.4
-
-node:internal/modules/esm/resolve:873
-
- throw new ERR_MODULE_NOT_FOUND(packageName, fileURLToPath(base), null);
-
-
-
-^
-
-Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'vite' imported from /app/dist/index.js
-
- at packageResolve (node:internal/modules/esm/resolve:873:9)
-
- at moduleResolve (node:internal/modules/esm/resolve:946:18)
-
- at defaultResolve (node:internal/modules/esm/resolve:1188:11)
-
- at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:642:12)
-
- at #cachedDefaultResolve (node:internal/modules/esm/loader:591:25)
-
- at ModuleLoader.resolve (node:internal/modules/esm/loader:574:38)
-
- at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:236:38)
-
- at ModuleJob._link (node:internal/modules/esm/module_job:130:49) {
-
- code: 'ERR_MODULE_NOT_FOUND'
-
-}
-
-Node.js v20.19.4
-
-
-
-
-
\ No newline at end of file
diff --git a/attached_assets/Pasted-GET-api-deliveries-500-in-24ms-GET-api-orders-500-in-27ms-getUserWithGroups-called-for-us-1754994000361_1754994000361.txt b/attached_assets/Pasted-GET-api-deliveries-500-in-24ms-GET-api-orders-500-in-27ms-getUserWithGroups-called-for-us-1754994000361_1754994000361.txt
deleted file mode 100644
index bebe89c..0000000
--- a/attached_assets/Pasted-GET-api-deliveries-500-in-24ms-GET-api-orders-500-in-27ms-getUserWithGroups-called-for-us-1754994000361_1754994000361.txt
+++ /dev/null
@@ -1,200 +0,0 @@
-GET /api/deliveries 500 in 24ms
-
-GET /api/orders 500 in 27ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Orders API called with: {
-
- startDate: '2025-08-01',
-
- endDate: '2025-08-31',
-
- storeId: undefined,
-
- userRole: 'admin'
-
-}
-
-Admin filtering with groupIds: undefined
-
-Fetching orders by date range: 2025-08-01 to 2025-08-31
-
-Error fetching orders: error: column orders_supplier.email does not exist
-
- at /app/node_modules/pg-pool/index.js:45:11
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
-
- at async DatabaseStorage.getOrdersByDateRange (file:///app/dist/index.js:1127:16)
-
- at async file:///app/dist/index.js:3633:21 {
-
- length: 120,
-
- severity: 'ERROR',
-
- code: '42703',
-
- detail: undefined,
-
- hint: undefined,
-
- position: '555',
-
- internalPosition: undefined,
-
- internalQuery: undefined,
-
- where: undefined,
-
- schema: undefined,
-
- table: undefined,
-
- column: undefined,
-
- dataType: undefined,
-
- constraint: undefined,
-
- file: 'parse_relation.c',
-
- line: '3665',
-
- routine: 'errorMissingColumn'
-
-}
-
-GET /api/orders 500 in 13ms
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Deliveries API called with: {
-
- startDate: '2025-08-01',
-
- endDate: '2025-08-31',
-
- storeId: undefined,
-
- withBL: undefined,
-
- userRole: 'admin'
-
-}
-
-Admin filtering deliveries with groupIds: undefined
-
-Fetching deliveries by date range: 2025-08-01 to 2025-08-31
-
-Error fetching deliveries: error: column deliveries_supplier.email does not exist
-
- at /app/node_modules/pg-pool/index.js:45:11
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
-
- at async DatabaseStorage.getDeliveriesByDateRange (file:///app/dist/index.js:1186:25)
-
- at async file:///app/dist/index.js:3848:25 {
-
- length: 124,
-
- severity: 'ERROR',
-
- code: '42703',
-
- detail: undefined,
-
- hint: undefined,
-
- position: '856',
-
- internalPosition: undefined,
-
- internalQuery: undefined,
-
- where: undefined,
-
- schema: undefined,
-
- table: undefined,
-
- column: undefined,
-
- dataType: undefined,
-
- constraint: undefined,
-
- file: 'parse_relation.c',
-
- line: '3665',
-
- routine: 'errorMissingColumn'
-
-}
-
-GET /api/deliveries 500 in 42ms
-
-HEAD /api/health 200 in 1ms
-
diff --git a/attached_assets/Pasted-GET-api-users-200-in-33ms-Error-deleting-user-error-update-or-delete-on-table-users-violates-1754935124372_1754935124372.txt b/attached_assets/Pasted-GET-api-users-200-in-33ms-Error-deleting-user-error-update-or-delete-on-table-users-violates-1754935124372_1754935124372.txt
deleted file mode 100644
index 48b8c49..0000000
--- a/attached_assets/Pasted-GET-api-users-200-in-33ms-Error-deleting-user-error-update-or-delete-on-table-users-violates-1754935124372_1754935124372.txt
+++ /dev/null
@@ -1,108 +0,0 @@
-GET /api/users 200 in 33ms
-
-Error deleting user: error: update or delete on table "users" violates foreign key constraint "user_roles_assigned_by_fkey" on table "user_roles"
-
- at /app/node_modules/pg/lib/client.js:545:17
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async file:///app/dist/index.js:1108:11
-
- at async NodePgSession.transaction (file:///app/node_modules/drizzle-orm/node-postgres/session.js:142:22)
-
- at async DatabaseStorage.deleteUser (file:///app/dist/index.js:1090:9)
-
- at async file:///app/dist/index.js:4094:7 {
-
- length: 299,
-
- severity: 'ERROR',
-
- code: '23503',
-
- detail: 'Key (id)=(system) is still referenced from table "user_roles".',
-
- hint: undefined,
-
- position: undefined,
-
- internalPosition: undefined,
-
- internalQuery: undefined,
-
- where: undefined,
-
- schema: 'public',
-
- table: 'user_roles',
-
- column: undefined,
-
- dataType: undefined,
-
- constraint: 'user_roles_assigned_by_fkey',
-
- file: 'ri_triggers.c',
-
- line: '2609',
-
- routine: 'ri_ReportViolation'
-
-}
-
-DELETE /api/users/system 500 in 29ms
-
-HEAD /api/health 200 in 1ms
-
-Error deleting user: error: update or delete on table "users" violates foreign key constraint "user_roles_assigned_by_fkey" on table "user_roles"
-
- at /app/node_modules/pg/lib/client.js:545:17
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async file:///app/dist/index.js:1108:11
-
- at async NodePgSession.transaction (file:///app/node_modules/drizzle-orm/node-postgres/session.js:142:22)
-
- at async DatabaseStorage.deleteUser (file:///app/dist/index.js:1090:9)
-
- at async file:///app/dist/index.js:4094:7 {
-
- length: 299,
-
- severity: 'ERROR',
-
- code: '23503',
-
- detail: 'Key (id)=(system) is still referenced from table "user_roles".',
-
- hint: undefined,
-
- position: undefined,
-
- internalPosition: undefined,
-
- internalQuery: undefined,
-
- where: undefined,
-
- schema: 'public',
-
- table: 'user_roles',
-
- column: undefined,
-
- dataType: undefined,
-
- constraint: 'user_roles_assigned_by_fkey',
-
- file: 'ri_triggers.c',
-
- line: '2609',
-
- routine: 'ri_ReportViolation'
-
-}
-
-DELETE /api/users/system 500 in 19ms
-
diff --git a/attached_assets/Pasted-HEAD-api-health-200-in-1ms-Error-updating-user-Error-ERR-MODULE-NOT-FOUND-Cannot-find-module-1754941254642_1754941254643.txt b/attached_assets/Pasted-HEAD-api-health-200-in-1ms-Error-updating-user-Error-ERR-MODULE-NOT-FOUND-Cannot-find-module-1754941254642_1754941254643.txt
deleted file mode 100644
index 5d9d1d3..0000000
--- a/attached_assets/Pasted-HEAD-api-health-200-in-1ms-Error-updating-user-Error-ERR-MODULE-NOT-FOUND-Cannot-find-module-1754941254642_1754941254643.txt
+++ /dev/null
@@ -1,140 +0,0 @@
-HEAD /api/health 200 in 1ms
-
-Error updating user: Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/app/dist/localAuth.production.js' imported from /app/dist/index.js
-
- at finalizeResolution (node:internal/modules/esm/resolve:283:11)
-
- at moduleResolve (node:internal/modules/esm/resolve:952:10)
-
- at defaultResolve (node:internal/modules/esm/resolve:1188:11)
-
- at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:642:12)
-
- at #cachedDefaultResolve (node:internal/modules/esm/loader:591:25)
-
- at ModuleLoader.resolve (node:internal/modules/esm/loader:574:38)
-
- at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:236:38)
-
- at ModuleLoader.import (node:internal/modules/esm/loader:539:34)
-
- at defaultImportModuleDynamicallyForModule (node:internal/modules/esm/utils:221:31)
-
- at importModuleDynamicallyCallback (node:internal/modules/esm/utils:260:12) {
-
- code: 'ERR_MODULE_NOT_FOUND',
-
- url: 'file:///app/dist/localAuth.production.js'
-
-}
-
-PUT /api/users/admin_local 500 in 14ms
-
-HEAD /api/health 200 in 1ms
-
-Error assigning user to group: error: column "created_at" of relation "user_groups" does not exist
-
- at /app/node_modules/pg-pool/index.js:45:11
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
-
- at async DatabaseStorage.assignUserToGroup (file:///app/dist/index.js:1225:32)
-
- at async file:///app/dist/index.js:3842:25 {
-
- length: 134,
-
- severity: 'ERROR',
-
- code: '42703',
-
- detail: undefined,
-
- hint: undefined,
-
- position: '51',
-
- internalPosition: undefined,
-
- internalQuery: undefined,
-
- where: undefined,
-
- schema: undefined,
-
- table: undefined,
-
- column: undefined,
-
- dataType: undefined,
-
- constraint: undefined,
-
- file: 'parse_target.c',
-
- line: '1075',
-
- routine: 'checkInsertTargets'
-
-}
-
-POST /api/users/admin_local/groups 500 in 55ms
-
-Error assigning user to group: error: column "created_at" of relation "user_groups" does not exist
-
- at /app/node_modules/pg-pool/index.js:45:11
-
- at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-
- at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
-
- at async DatabaseStorage.assignUserToGroup (file:///app/dist/index.js:1225:32)
-
- at async file:///app/dist/index.js:3842:25 {
-
- length: 134,
-
- severity: 'ERROR',
-
- code: '42703',
-
- detail: undefined,
-
- hint: undefined,
-
- position: '51',
-
- internalPosition: undefined,
-
- internalQuery: undefined,
-
- where: undefined,
-
- schema: undefined,
-
- table: undefined,
-
- column: undefined,
-
- dataType: undefined,
-
- constraint: undefined,
-
- file: 'parse_target.c',
-
- line: '1075',
-
- routine: 'checkInsertTargets'
-
-}
-
-POST /api/users/admin_local/groups 500 in 27ms
-
-HEAD /api/health 200 in 2ms
-
-
-
-
-
\ No newline at end of file
diff --git a/attached_assets/Pasted-ctions-Found-1-group-assignments-for-user-1753266816257-Raw-query-result-1755008518319_1755008518319.txt b/attached_assets/Pasted-ctions-Found-1-group-assignments-for-user-1753266816257-Raw-query-result-1755008518319_1755008518319.txt
deleted file mode 100644
index 9a83c0e..0000000
--- a/attached_assets/Pasted-ctions-Found-1-group-assignments-for-user-1753266816257-Raw-query-result-1755008518319_1755008518319.txt
+++ /dev/null
@@ -1,207 +0,0 @@
-ctions
-
-
-
-
-🔍 Found 1 group assignments for user _1753266816257
-
-🔍 Raw query result: [
-
- {
-
- user_id: '_1753266816257',
-
- group_id: 2,
-
- group_id_ref: 2,
-
- group_name: 'Houdemont',
-
- group_color: '#455A64',
-
- nocodb_config_id: 1,
-
- nocodb_table_id: 'my7zunxprumahmm',
-
- nocodb_table_name: 'CommandeH',
-
- invoice_column_name: 'RefFacture',
-
- group_created_at: '2025-07-22 11:09:08.977622',
-
- group_updated_at: '2025-08-12 09:39:32.989'
-
- }
-
-]
-
-✅ Processed 1 groups for user _1753266816257
-
-GET /api/groups 304 in 88ms
-
-GET /api/suppliers 304 in 95ms
-
-🔍 Querying user_groups for user: _1753266816257
-
-🔍 Found 1 group assignments for user _1753266816257
-
-🔍 Raw query result: [
-
- {
-
- user_id: '_1753266816257',
-
- group_id: 2,
-
- group_id_ref: 2,
-
- group_name: 'Houdemont',
-
- group_color: '#455A64',
-
- nocodb_config_id: 1,
-
- nocodb_table_id: 'my7zunxprumahmm',
-
- nocodb_table_name: 'CommandeH',
-
- invoice_column_name: 'RefFacture',
-
- group_created_at: '2025-07-22 11:09:08.977622',
-
- group_updated_at: '2025-08-12 09:39:32.989'
-
- }
-
-]
-
-✅ Processed 1 groups for user _1753266816257
-
-🔍 getUserWithGroups called for user: _1753266816257
-
-🔍 Querying user_groups for user: _1753266816257
-
-🔍 Found 1 group assignments for user _1753266816257
-
-🔍 Raw query result: [
-
- {
-
- user_id: '_1753266816257',
-
- group_id: 2,
-
- group_id_ref: 2,
-
- group_name: 'Houdemont',
-
- group_color: '#455A64',
-
- nocodb_config_id: 1,
-
- nocodb_table_id: 'my7zunxprumahmm',
-
- nocodb_table_name: 'CommandeH',
-
- invoice_column_name: 'RefFacture',
-
- group_created_at: '2025-07-22 11:09:08.977622',
-
- group_updated_at: '2025-08-12 09:39:32.989'
-
- }
-
-]
-
-✅ Processed 1 groups for user _1753266816257
-
-🔍 getUserWithGroups called for user: _1753266816257
-
-🔍 Querying user_groups for user: _1753266816257
-
-🔍 Found 1 group assignments for user _1753266816257
-
-🔍 Raw query result: [
-
- {
-
- user_id: '_1753266816257',
-
- group_id: 2,
-
- group_id_ref: 2,
-
- group_name: 'Houdemont',
-
- group_color: '#455A64',
-
- nocodb_config_id: 1,
-
- nocodb_table_id: 'my7zunxprumahmm',
-
- nocodb_table_name: 'CommandeH',
-
- invoice_column_name: 'RefFacture',
-
- group_created_at: '2025-07-22 11:09:08.977622',
-
- group_updated_at: '2025-08-12 09:39:32.989'
-
- }
-
-]
-
-✅ Processed 1 groups for user _1753266816257
-
-Customer orders - User assigned stores: { groupIds: [ 2 ] }
-
-Customer orders returned from storage: 23 items
-
-GET /api/customer-orders 304 in 130ms
-
-HEAD /api/health 200 in 1ms
-
-🔍 getUserWithGroups called for user: _1753266816257
-
-🔍 Querying user_groups for user: _1753266816257
-
-🔍 Found 1 group assignments for user _1753266816257
-
-🔍 Raw query result: [
-
- {
-
- user_id: '_1753266816257',
-
- group_id: 2,
-
- group_id_ref: 2,
-
- group_name: 'Houdemont',
-
- group_color: '#455A64',
-
- nocodb_config_id: 1,
-
- nocodb_table_id: 'my7zunxprumahmm',
-
- nocodb_table_name: 'CommandeH',
-
- invoice_column_name: 'RefFacture',
-
- group_created_at: '2025-07-22 11:09:08.977622',
-
- group_updated_at: '2025-08-12 09:39:32.989'
-
- }
-
-]
-
-✅ Processed 1 groups for user _1753266816257
-
-GET /api/user 304 in 7ms
-
-HEAD /api/health 200 in 1ms
-
-
-
\ No newline at end of file
diff --git a/attached_assets/Pasted-ions-Found-0-group-assignments-for-user-admin-local-Raw-query-result--1754944471521_1754944471521.txt b/attached_assets/Pasted-ions-Found-0-group-assignments-for-user-admin-local-Raw-query-result--1754944471521_1754944471521.txt
deleted file mode 100644
index 33308f5..0000000
--- a/attached_assets/Pasted-ions-Found-0-group-assignments-for-user-admin-local-Raw-query-result--1754944471521_1754944471521.txt
+++ /dev/null
@@ -1,208 +0,0 @@
-ions
-
-
-
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Deliveries API called with: {
-
- startDate: '2025-08-01',
-
- endDate: '2025-08-31',
-
- storeId: undefined,
-
- withBL: undefined,
-
- userRole: 'admin'
-
-}
-
-Admin filtering deliveries with groupIds: undefined
-
-Fetching deliveries by date range: 2025-08-01 to 2025-08-31
-
-🔍 getUserWithGroups called for user: admin_local
-
-GET /api/user 304 in 67ms
-
-GET /api/stats/monthly 304 in 57ms
-
-Deliveries returned: 40 items
-
-GET /api/deliveries 304 in 64ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-GET /api/user 304 in 5ms
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Orders API called with: {
-
- startDate: '2025-08-01',
-
- endDate: '2025-08-31',
-
- storeId: undefined,
-
- userRole: 'admin'
-
-}
-
-Admin filtering with groupIds: undefined
-
-Fetching orders by date range: 2025-08-01 to 2025-08-31
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-GET /api/user 304 in 13ms
-
-Orders returned: 15 items
-
-GET /api/orders 304 in 111ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-GET /api/user 304 in 7ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-GET /api/groups 304 in 10ms
-
-HEAD /api/health 200 in 1ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-📄 SPA: Serving index.html for /[object%20Object]
-
-
-
-
\ No newline at end of file
diff --git a/attached_assets/Pasted-ions-Raw-query-result-Processed-0-groups-for-user-admin-local-ge-1754944623748_1754944623748.txt b/attached_assets/Pasted-ions-Raw-query-result-Processed-0-groups-for-user-admin-local-ge-1754944623748_1754944623748.txt
deleted file mode 100644
index 4b86903..0000000
--- a/attached_assets/Pasted-ions-Raw-query-result-Processed-0-groups-for-user-admin-local-ge-1754944623748_1754944623748.txt
+++ /dev/null
@@ -1,208 +0,0 @@
-ions
-
-
-
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Deliveries API called with: {
-
- startDate: '2025-08-01',
-
- endDate: '2025-08-31',
-
- storeId: '1',
-
- withBL: undefined,
-
- userRole: 'admin'
-
-}
-
-Admin filtering deliveries with groupIds: [ 1 ]
-
-Fetching deliveries by date range: 2025-08-01 to 2025-08-31
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-Orders API called with: {
-
- startDate: '2025-08-01',
-
- endDate: '2025-08-31',
-
- storeId: '1',
-
- userRole: 'admin'
-
-}
-
-Admin filtering with groupIds: [ 1 ]
-
-Fetching orders by date range: 2025-08-01 to 2025-08-31
-
-Deliveries returned: 20 items
-
-Orders returned: 9 items
-
-GET /api/orders 304 in 28ms
-
-GET /api/deliveries 304 in 30ms
-
-HEAD /api/health 200 in 1ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-📄 SPA: Serving index.html for /[object%20Object]
-
-HEAD /api/health 200 in 2ms
-
-HEAD /api/health 200 in 1ms
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-📄 SPA: Serving index.html for /[object%20Object]
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-📄 SPA: Serving index.html for /[object%20Object]
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-📄 SPA: Serving index.html for /[object%20Object]
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-🔍 getUserWithGroups called for user: admin_local
-
-🔍 Querying user_groups for user: admin_local
-
-🔍 Found 0 group assignments for user admin_local
-
-🔍 Raw query result: []
-
-✅ Processed 0 groups for user admin_local
-
-📄 SPA: Serving index.html for /[object%20Object]
-
-
-
-
\ No newline at end of file
diff --git a/attached_assets/image_1752766025066.png b/attached_assets/image_1752766025066.png
deleted file mode 100644
index e5c249c..0000000
Binary files a/attached_assets/image_1752766025066.png and /dev/null differ
diff --git a/attached_assets/image_1752766464149.png b/attached_assets/image_1752766464149.png
deleted file mode 100644
index d2690e0..0000000
Binary files a/attached_assets/image_1752766464149.png and /dev/null differ
diff --git a/attached_assets/image_1752766480419.png b/attached_assets/image_1752766480419.png
deleted file mode 100644
index c15f31d..0000000
Binary files a/attached_assets/image_1752766480419.png and /dev/null differ
diff --git a/attached_assets/image_1752766490182.png b/attached_assets/image_1752766490182.png
deleted file mode 100644
index 4cbe479..0000000
Binary files a/attached_assets/image_1752766490182.png and /dev/null differ
diff --git a/attached_assets/image_1752766821507.png b/attached_assets/image_1752766821507.png
deleted file mode 100644
index 48d5dfe..0000000
Binary files a/attached_assets/image_1752766821507.png and /dev/null differ
diff --git a/attached_assets/image_1752766833825.png b/attached_assets/image_1752766833825.png
deleted file mode 100644
index abf2f18..0000000
Binary files a/attached_assets/image_1752766833825.png and /dev/null differ
diff --git a/attached_assets/image_1752766848888.png b/attached_assets/image_1752766848888.png
deleted file mode 100644
index b1e727d..0000000
Binary files a/attached_assets/image_1752766848888.png and /dev/null differ
diff --git a/attached_assets/image_1752767258504.png b/attached_assets/image_1752767258504.png
deleted file mode 100644
index fece8c2..0000000
Binary files a/attached_assets/image_1752767258504.png and /dev/null differ
diff --git a/attached_assets/image_1752767418007.png b/attached_assets/image_1752767418007.png
deleted file mode 100644
index 781e9be..0000000
Binary files a/attached_assets/image_1752767418007.png and /dev/null differ
diff --git a/attached_assets/image_1752767430055.png b/attached_assets/image_1752767430055.png
deleted file mode 100644
index 83cdd91..0000000
Binary files a/attached_assets/image_1752767430055.png and /dev/null differ
diff --git a/attached_assets/image_1752767446461.png b/attached_assets/image_1752767446461.png
deleted file mode 100644
index 821c04f..0000000
Binary files a/attached_assets/image_1752767446461.png and /dev/null differ
diff --git a/attached_assets/image_1752767661266.png b/attached_assets/image_1752767661266.png
deleted file mode 100644
index b6b7c43..0000000
Binary files a/attached_assets/image_1752767661266.png and /dev/null differ
diff --git a/attached_assets/image_1752767684109.png b/attached_assets/image_1752767684109.png
deleted file mode 100644
index fd311e1..0000000
Binary files a/attached_assets/image_1752767684109.png and /dev/null differ
diff --git a/attached_assets/image_1752767691981.png b/attached_assets/image_1752767691981.png
deleted file mode 100644
index 911c620..0000000
Binary files a/attached_assets/image_1752767691981.png and /dev/null differ
diff --git a/attached_assets/image_1752769392661.png b/attached_assets/image_1752769392661.png
deleted file mode 100644
index 6f62c2d..0000000
Binary files a/attached_assets/image_1752769392661.png and /dev/null differ
diff --git a/attached_assets/image_1752769407218.png b/attached_assets/image_1752769407218.png
deleted file mode 100644
index a1c967a..0000000
Binary files a/attached_assets/image_1752769407218.png and /dev/null differ
diff --git a/attached_assets/image_1752769420047.png b/attached_assets/image_1752769420047.png
deleted file mode 100644
index facdb4d..0000000
Binary files a/attached_assets/image_1752769420047.png and /dev/null differ
diff --git a/attached_assets/image_1752771225174.png b/attached_assets/image_1752771225174.png
deleted file mode 100644
index c0cd829..0000000
Binary files a/attached_assets/image_1752771225174.png and /dev/null differ
diff --git a/attached_assets/image_1752771765779.png b/attached_assets/image_1752771765779.png
deleted file mode 100644
index 0390d27..0000000
Binary files a/attached_assets/image_1752771765779.png and /dev/null differ
diff --git a/attached_assets/image_1752772428531.png b/attached_assets/image_1752772428531.png
deleted file mode 100644
index 4d449ba..0000000
Binary files a/attached_assets/image_1752772428531.png and /dev/null differ
diff --git a/attached_assets/image_1752772440846.png b/attached_assets/image_1752772440846.png
deleted file mode 100644
index a4430e5..0000000
Binary files a/attached_assets/image_1752772440846.png and /dev/null differ
diff --git a/attached_assets/image_1752772451841.png b/attached_assets/image_1752772451841.png
deleted file mode 100644
index 10358c7..0000000
Binary files a/attached_assets/image_1752772451841.png and /dev/null differ
diff --git a/attached_assets/image_1752773320143.png b/attached_assets/image_1752773320143.png
deleted file mode 100644
index 5e0bc0f..0000000
Binary files a/attached_assets/image_1752773320143.png and /dev/null differ
diff --git a/attached_assets/image_1752773478420.png b/attached_assets/image_1752773478420.png
deleted file mode 100644
index a4f48c7..0000000
Binary files a/attached_assets/image_1752773478420.png and /dev/null differ
diff --git a/attached_assets/image_1752773953453.png b/attached_assets/image_1752773953453.png
deleted file mode 100644
index b07d6cc..0000000
Binary files a/attached_assets/image_1752773953453.png and /dev/null differ
diff --git a/attached_assets/image_1752773965091.png b/attached_assets/image_1752773965091.png
deleted file mode 100644
index adb24b7..0000000
Binary files a/attached_assets/image_1752773965091.png and /dev/null differ
diff --git a/attached_assets/image_1752775532174.png b/attached_assets/image_1752775532174.png
deleted file mode 100644
index d0b8a5c..0000000
Binary files a/attached_assets/image_1752775532174.png and /dev/null differ
diff --git a/attached_assets/image_1752775546486.png b/attached_assets/image_1752775546486.png
deleted file mode 100644
index 1fbf7e0..0000000
Binary files a/attached_assets/image_1752775546486.png and /dev/null differ
diff --git a/attached_assets/image_1752777402539.png b/attached_assets/image_1752777402539.png
deleted file mode 100644
index 021ee01..0000000
Binary files a/attached_assets/image_1752777402539.png and /dev/null differ
diff --git a/attached_assets/image_1752777417410.png b/attached_assets/image_1752777417410.png
deleted file mode 100644
index f5644b1..0000000
Binary files a/attached_assets/image_1752777417410.png and /dev/null differ
diff --git a/attached_assets/image_1752777432020.png b/attached_assets/image_1752777432020.png
deleted file mode 100644
index f5bafdc..0000000
Binary files a/attached_assets/image_1752777432020.png and /dev/null differ
diff --git a/attached_assets/image_1752777446031.png b/attached_assets/image_1752777446031.png
deleted file mode 100644
index 75c94ee..0000000
Binary files a/attached_assets/image_1752777446031.png and /dev/null differ
diff --git a/attached_assets/image_1752778476256.png b/attached_assets/image_1752778476256.png
deleted file mode 100644
index ba952f7..0000000
Binary files a/attached_assets/image_1752778476256.png and /dev/null differ
diff --git a/attached_assets/image_1752779250152.png b/attached_assets/image_1752779250152.png
deleted file mode 100644
index 1a80859..0000000
Binary files a/attached_assets/image_1752779250152.png and /dev/null differ
diff --git a/attached_assets/image_1752779262237.png b/attached_assets/image_1752779262237.png
deleted file mode 100644
index 47935d5..0000000
Binary files a/attached_assets/image_1752779262237.png and /dev/null differ
diff --git a/attached_assets/image_1752779795804.png b/attached_assets/image_1752779795804.png
deleted file mode 100644
index 100357e..0000000
Binary files a/attached_assets/image_1752779795804.png and /dev/null differ
diff --git a/attached_assets/image_1752780860294.png b/attached_assets/image_1752780860294.png
deleted file mode 100644
index 61c8963..0000000
Binary files a/attached_assets/image_1752780860294.png and /dev/null differ
diff --git a/attached_assets/image_1752780878637.png b/attached_assets/image_1752780878637.png
deleted file mode 100644
index 66648d3..0000000
Binary files a/attached_assets/image_1752780878637.png and /dev/null differ
diff --git a/attached_assets/image_1752781874554.png b/attached_assets/image_1752781874554.png
deleted file mode 100644
index 7c5b243..0000000
Binary files a/attached_assets/image_1752781874554.png and /dev/null differ
diff --git a/attached_assets/image_1752782368901.png b/attached_assets/image_1752782368901.png
deleted file mode 100644
index c18a700..0000000
Binary files a/attached_assets/image_1752782368901.png and /dev/null differ
diff --git a/attached_assets/image_1752782746736.png b/attached_assets/image_1752782746736.png
deleted file mode 100644
index 0cea7c0..0000000
Binary files a/attached_assets/image_1752782746736.png and /dev/null differ
diff --git a/attached_assets/image_1752783126000.png b/attached_assets/image_1752783126000.png
deleted file mode 100644
index 96ba1c3..0000000
Binary files a/attached_assets/image_1752783126000.png and /dev/null differ
diff --git a/attached_assets/image_1752783301204.png b/attached_assets/image_1752783301204.png
deleted file mode 100644
index 37e709e..0000000
Binary files a/attached_assets/image_1752783301204.png and /dev/null differ
diff --git a/attached_assets/image_1752783309160.png b/attached_assets/image_1752783309160.png
deleted file mode 100644
index a55ad8e..0000000
Binary files a/attached_assets/image_1752783309160.png and /dev/null differ
diff --git a/attached_assets/image_1752783652014.png b/attached_assets/image_1752783652014.png
deleted file mode 100644
index c12dd7d..0000000
Binary files a/attached_assets/image_1752783652014.png and /dev/null differ
diff --git a/attached_assets/image_1752783882954.png b/attached_assets/image_1752783882954.png
deleted file mode 100644
index b9aae37..0000000
Binary files a/attached_assets/image_1752783882954.png and /dev/null differ
diff --git a/attached_assets/image_1752784161800.png b/attached_assets/image_1752784161800.png
deleted file mode 100644
index c682fc3..0000000
Binary files a/attached_assets/image_1752784161800.png and /dev/null differ
diff --git a/attached_assets/image_1752784500876.png b/attached_assets/image_1752784500876.png
deleted file mode 100644
index e49703a..0000000
Binary files a/attached_assets/image_1752784500876.png and /dev/null differ
diff --git a/attached_assets/image_1752784653474.png b/attached_assets/image_1752784653474.png
deleted file mode 100644
index b1d8131..0000000
Binary files a/attached_assets/image_1752784653474.png and /dev/null differ
diff --git a/attached_assets/image_1752784708889.png b/attached_assets/image_1752784708889.png
deleted file mode 100644
index 143ad45..0000000
Binary files a/attached_assets/image_1752784708889.png and /dev/null differ
diff --git a/attached_assets/image_1752784915937.png b/attached_assets/image_1752784915937.png
deleted file mode 100644
index 5e64afe..0000000
Binary files a/attached_assets/image_1752784915937.png and /dev/null differ
diff --git a/attached_assets/image_1752785793545.png b/attached_assets/image_1752785793545.png
deleted file mode 100644
index 1f93e05..0000000
Binary files a/attached_assets/image_1752785793545.png and /dev/null differ
diff --git a/attached_assets/image_1752786081511.png b/attached_assets/image_1752786081511.png
deleted file mode 100644
index a696c14..0000000
Binary files a/attached_assets/image_1752786081511.png and /dev/null differ
diff --git a/attached_assets/image_1752786293718.png b/attached_assets/image_1752786293718.png
deleted file mode 100644
index 8331daa..0000000
Binary files a/attached_assets/image_1752786293718.png and /dev/null differ
diff --git a/attached_assets/image_1752786513943.png b/attached_assets/image_1752786513943.png
deleted file mode 100644
index efcb8c2..0000000
Binary files a/attached_assets/image_1752786513943.png and /dev/null differ
diff --git a/attached_assets/image_1752787356602.png b/attached_assets/image_1752787356602.png
deleted file mode 100644
index 83ec428..0000000
Binary files a/attached_assets/image_1752787356602.png and /dev/null differ
diff --git a/attached_assets/image_1752787679865.png b/attached_assets/image_1752787679865.png
deleted file mode 100644
index 362b1cb..0000000
Binary files a/attached_assets/image_1752787679865.png and /dev/null differ
diff --git a/attached_assets/image_1752787989742.png b/attached_assets/image_1752787989742.png
deleted file mode 100644
index 3c9d56c..0000000
Binary files a/attached_assets/image_1752787989742.png and /dev/null differ
diff --git a/attached_assets/image_1752788964597.png b/attached_assets/image_1752788964597.png
deleted file mode 100644
index da49db3..0000000
Binary files a/attached_assets/image_1752788964597.png and /dev/null differ
diff --git a/attached_assets/image_1752849165698.png b/attached_assets/image_1752849165698.png
deleted file mode 100644
index d06108f..0000000
Binary files a/attached_assets/image_1752849165698.png and /dev/null differ
diff --git a/attached_assets/image_1752849370460.png b/attached_assets/image_1752849370460.png
deleted file mode 100644
index 48eede2..0000000
Binary files a/attached_assets/image_1752849370460.png and /dev/null differ
diff --git a/attached_assets/image_1752849820341.png b/attached_assets/image_1752849820341.png
deleted file mode 100644
index e78049e..0000000
Binary files a/attached_assets/image_1752849820341.png and /dev/null differ
diff --git a/attached_assets/image_1752850101293.png b/attached_assets/image_1752850101293.png
deleted file mode 100644
index 3ce313e..0000000
Binary files a/attached_assets/image_1752850101293.png and /dev/null differ
diff --git a/attached_assets/image_1752850706979.png b/attached_assets/image_1752850706979.png
deleted file mode 100644
index d9c92ad..0000000
Binary files a/attached_assets/image_1752850706979.png and /dev/null differ
diff --git a/attached_assets/image_1752851073078.png b/attached_assets/image_1752851073078.png
deleted file mode 100644
index 94a500a..0000000
Binary files a/attached_assets/image_1752851073078.png and /dev/null differ
diff --git a/attached_assets/image_1752851081124.png b/attached_assets/image_1752851081124.png
deleted file mode 100644
index 296f123..0000000
Binary files a/attached_assets/image_1752851081124.png and /dev/null differ
diff --git a/attached_assets/image_1752851354808.png b/attached_assets/image_1752851354808.png
deleted file mode 100644
index 0bf1d5a..0000000
Binary files a/attached_assets/image_1752851354808.png and /dev/null differ
diff --git a/attached_assets/image_1752851424685.png b/attached_assets/image_1752851424685.png
deleted file mode 100644
index 282dfac..0000000
Binary files a/attached_assets/image_1752851424685.png and /dev/null differ
diff --git a/attached_assets/image_1752852210421.png b/attached_assets/image_1752852210421.png
deleted file mode 100644
index 158f473..0000000
Binary files a/attached_assets/image_1752852210421.png and /dev/null differ
diff --git a/attached_assets/image_1752853991222.png b/attached_assets/image_1752853991222.png
deleted file mode 100644
index d6a7546..0000000
Binary files a/attached_assets/image_1752853991222.png and /dev/null differ
diff --git a/attached_assets/image_1752854253640.png b/attached_assets/image_1752854253640.png
deleted file mode 100644
index 4755aec..0000000
Binary files a/attached_assets/image_1752854253640.png and /dev/null differ
diff --git a/attached_assets/image_1752854720451.png b/attached_assets/image_1752854720451.png
deleted file mode 100644
index cbe7508..0000000
Binary files a/attached_assets/image_1752854720451.png and /dev/null differ
diff --git a/attached_assets/image_1752856138351.png b/attached_assets/image_1752856138351.png
deleted file mode 100644
index 9d40622..0000000
Binary files a/attached_assets/image_1752856138351.png and /dev/null differ
diff --git a/attached_assets/image_1752856242407.png b/attached_assets/image_1752856242407.png
deleted file mode 100644
index 1874f94..0000000
Binary files a/attached_assets/image_1752856242407.png and /dev/null differ
diff --git a/attached_assets/image_1752856283569.png b/attached_assets/image_1752856283569.png
deleted file mode 100644
index cf9efa5..0000000
Binary files a/attached_assets/image_1752856283569.png and /dev/null differ
diff --git a/attached_assets/image_1752861618160.png b/attached_assets/image_1752861618160.png
deleted file mode 100644
index 5bd8789..0000000
Binary files a/attached_assets/image_1752861618160.png and /dev/null differ
diff --git a/attached_assets/image_1752861678028.png b/attached_assets/image_1752861678028.png
deleted file mode 100644
index 80acd3f..0000000
Binary files a/attached_assets/image_1752861678028.png and /dev/null differ
diff --git a/attached_assets/image_1752862717543.png b/attached_assets/image_1752862717543.png
deleted file mode 100644
index d5b248b..0000000
Binary files a/attached_assets/image_1752862717543.png and /dev/null differ
diff --git a/attached_assets/image_1752863404767.png b/attached_assets/image_1752863404767.png
deleted file mode 100644
index 9d9448f..0000000
Binary files a/attached_assets/image_1752863404767.png and /dev/null differ
diff --git a/attached_assets/image_1752866013504.png b/attached_assets/image_1752866013504.png
deleted file mode 100644
index d80c051..0000000
Binary files a/attached_assets/image_1752866013504.png and /dev/null differ
diff --git a/attached_assets/image_1752866368662.png b/attached_assets/image_1752866368662.png
deleted file mode 100644
index 47808b4..0000000
Binary files a/attached_assets/image_1752866368662.png and /dev/null differ
diff --git a/attached_assets/image_1752866433245.png b/attached_assets/image_1752866433245.png
deleted file mode 100644
index 917bad4..0000000
Binary files a/attached_assets/image_1752866433245.png and /dev/null differ
diff --git a/attached_assets/image_1752867231289.png b/attached_assets/image_1752867231289.png
deleted file mode 100644
index 1c1da9e..0000000
Binary files a/attached_assets/image_1752867231289.png and /dev/null differ
diff --git a/attached_assets/image_1752868755962.png b/attached_assets/image_1752868755962.png
deleted file mode 100644
index 5de54b4..0000000
Binary files a/attached_assets/image_1752868755962.png and /dev/null differ
diff --git a/attached_assets/image_1752870195952.png b/attached_assets/image_1752870195952.png
deleted file mode 100644
index ccb74b9..0000000
Binary files a/attached_assets/image_1752870195952.png and /dev/null differ
diff --git a/attached_assets/image_1752870206570.png b/attached_assets/image_1752870206570.png
deleted file mode 100644
index 86d826e..0000000
Binary files a/attached_assets/image_1752870206570.png and /dev/null differ
diff --git a/attached_assets/image_1752870216070.png b/attached_assets/image_1752870216070.png
deleted file mode 100644
index dd6cbe0..0000000
Binary files a/attached_assets/image_1752870216070.png and /dev/null differ
diff --git a/attached_assets/image_1752870872668.png b/attached_assets/image_1752870872668.png
deleted file mode 100644
index ef6a19e..0000000
Binary files a/attached_assets/image_1752870872668.png and /dev/null differ
diff --git a/attached_assets/image_1752870982195.png b/attached_assets/image_1752870982195.png
deleted file mode 100644
index 8769327..0000000
Binary files a/attached_assets/image_1752870982195.png and /dev/null differ
diff --git a/attached_assets/image_1752871195279.png b/attached_assets/image_1752871195279.png
deleted file mode 100644
index 3a1791a..0000000
Binary files a/attached_assets/image_1752871195279.png and /dev/null differ
diff --git a/attached_assets/image_1752871686017.png b/attached_assets/image_1752871686017.png
deleted file mode 100644
index cc077e0..0000000
Binary files a/attached_assets/image_1752871686017.png and /dev/null differ
diff --git a/attached_assets/image_1752871797411.png b/attached_assets/image_1752871797411.png
deleted file mode 100644
index 71386fe..0000000
Binary files a/attached_assets/image_1752871797411.png and /dev/null differ
diff --git a/attached_assets/image_1752871856908.png b/attached_assets/image_1752871856908.png
deleted file mode 100644
index 71386fe..0000000
Binary files a/attached_assets/image_1752871856908.png and /dev/null differ
diff --git a/attached_assets/image_1752872286785.png b/attached_assets/image_1752872286785.png
deleted file mode 100644
index cece444..0000000
Binary files a/attached_assets/image_1752872286785.png and /dev/null differ
diff --git a/attached_assets/image_1752872330874.png b/attached_assets/image_1752872330874.png
deleted file mode 100644
index 728c335..0000000
Binary files a/attached_assets/image_1752872330874.png and /dev/null differ
diff --git a/attached_assets/image_1752872369259.png b/attached_assets/image_1752872369259.png
deleted file mode 100644
index 576534f..0000000
Binary files a/attached_assets/image_1752872369259.png and /dev/null differ
diff --git a/attached_assets/image_1752872587413.png b/attached_assets/image_1752872587413.png
deleted file mode 100644
index f40eced..0000000
Binary files a/attached_assets/image_1752872587413.png and /dev/null differ
diff --git a/attached_assets/image_1752873198754.png b/attached_assets/image_1752873198754.png
deleted file mode 100644
index db68555..0000000
Binary files a/attached_assets/image_1752873198754.png and /dev/null differ
diff --git a/attached_assets/image_1752873380134.png b/attached_assets/image_1752873380134.png
deleted file mode 100644
index 2677229..0000000
Binary files a/attached_assets/image_1752873380134.png and /dev/null differ
diff --git a/attached_assets/image_1754927312405.png b/attached_assets/image_1754927312405.png
deleted file mode 100644
index 4204181..0000000
Binary files a/attached_assets/image_1754927312405.png and /dev/null differ
diff --git a/attached_assets/image_1754927463961.png b/attached_assets/image_1754927463961.png
deleted file mode 100644
index f9df289..0000000
Binary files a/attached_assets/image_1754927463961.png and /dev/null differ
diff --git a/attached_assets/image_1754928367370.png b/attached_assets/image_1754928367370.png
deleted file mode 100644
index 06b2022..0000000
Binary files a/attached_assets/image_1754928367370.png and /dev/null differ
diff --git a/attached_assets/image_1754928646763.png b/attached_assets/image_1754928646763.png
deleted file mode 100644
index 32c3453..0000000
Binary files a/attached_assets/image_1754928646763.png and /dev/null differ
diff --git a/attached_assets/image_1754929849430.png b/attached_assets/image_1754929849430.png
deleted file mode 100644
index 98ea59f..0000000
Binary files a/attached_assets/image_1754929849430.png and /dev/null differ
diff --git a/attached_assets/image_1754934559795.png b/attached_assets/image_1754934559795.png
deleted file mode 100644
index fc3ce2d..0000000
Binary files a/attached_assets/image_1754934559795.png and /dev/null differ
diff --git a/attached_assets/image_1754935107751.png b/attached_assets/image_1754935107751.png
deleted file mode 100644
index d5884af..0000000
Binary files a/attached_assets/image_1754935107751.png and /dev/null differ
diff --git a/attached_assets/image_1754935627291.png b/attached_assets/image_1754935627291.png
deleted file mode 100644
index d659ead..0000000
Binary files a/attached_assets/image_1754935627291.png and /dev/null differ
diff --git a/attached_assets/image_1754935721553.png b/attached_assets/image_1754935721553.png
deleted file mode 100644
index 5ac9528..0000000
Binary files a/attached_assets/image_1754935721553.png and /dev/null differ
diff --git a/attached_assets/image_1754935736068.png b/attached_assets/image_1754935736068.png
deleted file mode 100644
index 5ac9528..0000000
Binary files a/attached_assets/image_1754935736068.png and /dev/null differ
diff --git a/attached_assets/image_1754936742486.png b/attached_assets/image_1754936742486.png
deleted file mode 100644
index bf3e341..0000000
Binary files a/attached_assets/image_1754936742486.png and /dev/null differ
diff --git a/attached_assets/image_1754936873392.png b/attached_assets/image_1754936873392.png
deleted file mode 100644
index 99b026c..0000000
Binary files a/attached_assets/image_1754936873392.png and /dev/null differ
diff --git a/attached_assets/image_1754937206418.png b/attached_assets/image_1754937206418.png
deleted file mode 100644
index 7be6cfa..0000000
Binary files a/attached_assets/image_1754937206418.png and /dev/null differ
diff --git a/attached_assets/image_1754937586408.png b/attached_assets/image_1754937586408.png
deleted file mode 100644
index cdd91fb..0000000
Binary files a/attached_assets/image_1754937586408.png and /dev/null differ
diff --git a/attached_assets/image_1754940238213.png b/attached_assets/image_1754940238213.png
deleted file mode 100644
index 21d25ff..0000000
Binary files a/attached_assets/image_1754940238213.png and /dev/null differ
diff --git a/attached_assets/image_1754940275041.png b/attached_assets/image_1754940275041.png
deleted file mode 100644
index 3cfcb2d..0000000
Binary files a/attached_assets/image_1754940275041.png and /dev/null differ
diff --git a/attached_assets/image_1754940633122.png b/attached_assets/image_1754940633122.png
deleted file mode 100644
index 363436d..0000000
Binary files a/attached_assets/image_1754940633122.png and /dev/null differ
diff --git a/attached_assets/image_1754941049134.png b/attached_assets/image_1754941049134.png
deleted file mode 100644
index a910360..0000000
Binary files a/attached_assets/image_1754941049134.png and /dev/null differ
diff --git a/attached_assets/image_1754941198941.png b/attached_assets/image_1754941198941.png
deleted file mode 100644
index b70751a..0000000
Binary files a/attached_assets/image_1754941198941.png and /dev/null differ
diff --git a/attached_assets/image_1754941240030.png b/attached_assets/image_1754941240030.png
deleted file mode 100644
index 526a840..0000000
Binary files a/attached_assets/image_1754941240030.png and /dev/null differ
diff --git a/attached_assets/image_1754941438794.png b/attached_assets/image_1754941438794.png
deleted file mode 100644
index 5253589..0000000
Binary files a/attached_assets/image_1754941438794.png and /dev/null differ
diff --git a/attached_assets/image_1754941674961.png b/attached_assets/image_1754941674961.png
deleted file mode 100644
index e9523ad..0000000
Binary files a/attached_assets/image_1754941674961.png and /dev/null differ
diff --git a/attached_assets/image_1754941873531.png b/attached_assets/image_1754941873531.png
deleted file mode 100644
index e2a601c..0000000
Binary files a/attached_assets/image_1754941873531.png and /dev/null differ
diff --git a/attached_assets/image_1754942095938.png b/attached_assets/image_1754942095938.png
deleted file mode 100644
index de0814d..0000000
Binary files a/attached_assets/image_1754942095938.png and /dev/null differ
diff --git a/attached_assets/image_1754942324848.png b/attached_assets/image_1754942324848.png
deleted file mode 100644
index dba6ab9..0000000
Binary files a/attached_assets/image_1754942324848.png and /dev/null differ
diff --git a/attached_assets/image_1754942591562.png b/attached_assets/image_1754942591562.png
deleted file mode 100644
index 47ec2df..0000000
Binary files a/attached_assets/image_1754942591562.png and /dev/null differ
diff --git a/attached_assets/image_1754942828642.png b/attached_assets/image_1754942828642.png
deleted file mode 100644
index ac8d34b..0000000
Binary files a/attached_assets/image_1754942828642.png and /dev/null differ
diff --git a/attached_assets/image_1754943064930.png b/attached_assets/image_1754943064930.png
deleted file mode 100644
index 965c97b..0000000
Binary files a/attached_assets/image_1754943064930.png and /dev/null differ
diff --git a/attached_assets/image_1754943664463.png b/attached_assets/image_1754943664463.png
deleted file mode 100644
index 061fc24..0000000
Binary files a/attached_assets/image_1754943664463.png and /dev/null differ
diff --git a/attached_assets/image_1754944126059.png b/attached_assets/image_1754944126059.png
deleted file mode 100644
index 93f82e9..0000000
Binary files a/attached_assets/image_1754944126059.png and /dev/null differ
diff --git a/attached_assets/image_1754944243764.png b/attached_assets/image_1754944243764.png
deleted file mode 100644
index 529ce87..0000000
Binary files a/attached_assets/image_1754944243764.png and /dev/null differ
diff --git a/attached_assets/image_1754944449064.png b/attached_assets/image_1754944449064.png
deleted file mode 100644
index 559f93c..0000000
Binary files a/attached_assets/image_1754944449064.png and /dev/null differ
diff --git a/attached_assets/image_1754944537680.png b/attached_assets/image_1754944537680.png
deleted file mode 100644
index 50a2944..0000000
Binary files a/attached_assets/image_1754944537680.png and /dev/null differ
diff --git a/attached_assets/image_1754944580886.png b/attached_assets/image_1754944580886.png
deleted file mode 100644
index 50a2944..0000000
Binary files a/attached_assets/image_1754944580886.png and /dev/null differ
diff --git a/attached_assets/image_1754944615419.png b/attached_assets/image_1754944615419.png
deleted file mode 100644
index c04450c..0000000
Binary files a/attached_assets/image_1754944615419.png and /dev/null differ
diff --git a/attached_assets/image_1754944779506.png b/attached_assets/image_1754944779506.png
deleted file mode 100644
index 87d3502..0000000
Binary files a/attached_assets/image_1754944779506.png and /dev/null differ
diff --git a/attached_assets/image_1754944953948.png b/attached_assets/image_1754944953948.png
deleted file mode 100644
index 5c55046..0000000
Binary files a/attached_assets/image_1754944953948.png and /dev/null differ
diff --git a/attached_assets/image_1754945642796.png b/attached_assets/image_1754945642796.png
deleted file mode 100644
index 0b46e81..0000000
Binary files a/attached_assets/image_1754945642796.png and /dev/null differ
diff --git a/attached_assets/image_1754946213927.png b/attached_assets/image_1754946213927.png
deleted file mode 100644
index 5e38dbb..0000000
Binary files a/attached_assets/image_1754946213927.png and /dev/null differ
diff --git a/attached_assets/image_1754946503284.png b/attached_assets/image_1754946503284.png
deleted file mode 100644
index 1a66a98..0000000
Binary files a/attached_assets/image_1754946503284.png and /dev/null differ
diff --git a/attached_assets/image_1754946758521.png b/attached_assets/image_1754946758521.png
deleted file mode 100644
index 40f4c15..0000000
Binary files a/attached_assets/image_1754946758521.png and /dev/null differ
diff --git a/attached_assets/image_1754946916384.png b/attached_assets/image_1754946916384.png
deleted file mode 100644
index 4f601d8..0000000
Binary files a/attached_assets/image_1754946916384.png and /dev/null differ
diff --git a/attached_assets/image_1754947079230.png b/attached_assets/image_1754947079230.png
deleted file mode 100644
index 3765717..0000000
Binary files a/attached_assets/image_1754947079230.png and /dev/null differ
diff --git a/attached_assets/image_1754947130971.png b/attached_assets/image_1754947130971.png
deleted file mode 100644
index 3765717..0000000
Binary files a/attached_assets/image_1754947130971.png and /dev/null differ
diff --git a/attached_assets/image_1754947197975.png b/attached_assets/image_1754947197975.png
deleted file mode 100644
index 3765717..0000000
Binary files a/attached_assets/image_1754947197975.png and /dev/null differ
diff --git a/attached_assets/image_1754947430630.png b/attached_assets/image_1754947430630.png
deleted file mode 100644
index 4774539..0000000
Binary files a/attached_assets/image_1754947430630.png and /dev/null differ
diff --git a/attached_assets/image_1754947823130.png b/attached_assets/image_1754947823130.png
deleted file mode 100644
index 11db6a4..0000000
Binary files a/attached_assets/image_1754947823130.png and /dev/null differ
diff --git a/attached_assets/image_1754948003757.png b/attached_assets/image_1754948003757.png
deleted file mode 100644
index a1a5287..0000000
Binary files a/attached_assets/image_1754948003757.png and /dev/null differ
diff --git a/attached_assets/image_1755015147302.png b/attached_assets/image_1755015147302.png
deleted file mode 100644
index 6760a9d..0000000
Binary files a/attached_assets/image_1755015147302.png and /dev/null differ
diff --git a/attached_assets/{04C31A6E-E082-4C70-BCCD-A3021D2DE73B}_1755005296646.png b/attached_assets/{04C31A6E-E082-4C70-BCCD-A3021D2DE73B}_1755005296646.png
deleted file mode 100644
index 3c7acdf..0000000
Binary files a/attached_assets/{04C31A6E-E082-4C70-BCCD-A3021D2DE73B}_1755005296646.png and /dev/null differ
diff --git a/attached_assets/{0978F662-7351-4203-B569-6E97C74BDA98}_1754987491374.png b/attached_assets/{0978F662-7351-4203-B569-6E97C74BDA98}_1754987491374.png
deleted file mode 100644
index 205e84c..0000000
Binary files a/attached_assets/{0978F662-7351-4203-B569-6E97C74BDA98}_1754987491374.png and /dev/null differ
diff --git a/attached_assets/{0BF0A44D-52E5-4F5B-91DC-6A324D45044E}_1755006376031.png b/attached_assets/{0BF0A44D-52E5-4F5B-91DC-6A324D45044E}_1755006376031.png
deleted file mode 100644
index 9812220..0000000
Binary files a/attached_assets/{0BF0A44D-52E5-4F5B-91DC-6A324D45044E}_1755006376031.png and /dev/null differ
diff --git a/attached_assets/{15611991-6334-4433-8D89-777AA7BB04F6}_1755013005997.png b/attached_assets/{15611991-6334-4433-8D89-777AA7BB04F6}_1755013005997.png
deleted file mode 100644
index b78bf9f..0000000
Binary files a/attached_assets/{15611991-6334-4433-8D89-777AA7BB04F6}_1755013005997.png and /dev/null differ
diff --git a/attached_assets/{15FA3613-084B-4C65-9137-D8D3FF33CD34}_1755006743271.png b/attached_assets/{15FA3613-084B-4C65-9137-D8D3FF33CD34}_1755006743271.png
deleted file mode 100644
index f84c90a..0000000
Binary files a/attached_assets/{15FA3613-084B-4C65-9137-D8D3FF33CD34}_1755006743271.png and /dev/null differ
diff --git a/attached_assets/{192C59D5-006D-462C-8642-17012D06A969}_1755008500055.png b/attached_assets/{192C59D5-006D-462C-8642-17012D06A969}_1755008500055.png
deleted file mode 100644
index 95b620e..0000000
Binary files a/attached_assets/{192C59D5-006D-462C-8642-17012D06A969}_1755008500055.png and /dev/null differ
diff --git a/attached_assets/{196C82CB-1B5E-465C-8E2E-2085A6374715}_1754994443183.png b/attached_assets/{196C82CB-1B5E-465C-8E2E-2085A6374715}_1754994443183.png
deleted file mode 100644
index 51e8462..0000000
Binary files a/attached_assets/{196C82CB-1B5E-465C-8E2E-2085A6374715}_1754994443183.png and /dev/null differ
diff --git a/attached_assets/{29BD8749-1C84-4FD4-A3F3-A8546D5534B7}_1755005668941.png b/attached_assets/{29BD8749-1C84-4FD4-A3F3-A8546D5534B7}_1755005668941.png
deleted file mode 100644
index 532f2bd..0000000
Binary files a/attached_assets/{29BD8749-1C84-4FD4-A3F3-A8546D5534B7}_1755005668941.png and /dev/null differ
diff --git a/attached_assets/{394F47D1-C025-41C6-B09E-E00D24D11D3F}_1755012123378.png b/attached_assets/{394F47D1-C025-41C6-B09E-E00D24D11D3F}_1755012123378.png
deleted file mode 100644
index 14821f7..0000000
Binary files a/attached_assets/{394F47D1-C025-41C6-B09E-E00D24D11D3F}_1755012123378.png and /dev/null differ
diff --git a/attached_assets/{3BC0ADAC-F56E-4D6F-B047-AF545AA1CB04}_1754925273921.png b/attached_assets/{3BC0ADAC-F56E-4D6F-B047-AF545AA1CB04}_1754925273921.png
deleted file mode 100644
index 5aeffa6..0000000
Binary files a/attached_assets/{3BC0ADAC-F56E-4D6F-B047-AF545AA1CB04}_1754925273921.png and /dev/null differ
diff --git a/attached_assets/{41342A2B-B6D0-4AAF-8D84-B01E40DFEFC5}_1755010460434.png b/attached_assets/{41342A2B-B6D0-4AAF-8D84-B01E40DFEFC5}_1755010460434.png
deleted file mode 100644
index 96e2b85..0000000
Binary files a/attached_assets/{41342A2B-B6D0-4AAF-8D84-B01E40DFEFC5}_1755010460434.png and /dev/null differ
diff --git a/attached_assets/{41E896A3-9301-4C3E-AB6A-195D11ECE3F0}_1755006693645.png b/attached_assets/{41E896A3-9301-4C3E-AB6A-195D11ECE3F0}_1755006693645.png
deleted file mode 100644
index 30ba41b..0000000
Binary files a/attached_assets/{41E896A3-9301-4C3E-AB6A-195D11ECE3F0}_1755006693645.png and /dev/null differ
diff --git a/attached_assets/{47A315E2-C868-4AFE-9075-979FD56A1D12}_1754995609289.png b/attached_assets/{47A315E2-C868-4AFE-9075-979FD56A1D12}_1754995609289.png
deleted file mode 100644
index 428c36b..0000000
Binary files a/attached_assets/{47A315E2-C868-4AFE-9075-979FD56A1D12}_1754995609289.png and /dev/null differ
diff --git a/attached_assets/{4EF913A6-C82F-45EB-AFDC-7791EC5CF5D5}_1755007779494.png b/attached_assets/{4EF913A6-C82F-45EB-AFDC-7791EC5CF5D5}_1755007779494.png
deleted file mode 100644
index 5ec8c53..0000000
Binary files a/attached_assets/{4EF913A6-C82F-45EB-AFDC-7791EC5CF5D5}_1755007779494.png and /dev/null differ
diff --git a/attached_assets/{4FFC2F69-0BF9-46C2-9AEB-7F4B97E326F0}_1755005966227.png b/attached_assets/{4FFC2F69-0BF9-46C2-9AEB-7F4B97E326F0}_1755005966227.png
deleted file mode 100644
index ac84fa0..0000000
Binary files a/attached_assets/{4FFC2F69-0BF9-46C2-9AEB-7F4B97E326F0}_1755005966227.png and /dev/null differ
diff --git a/attached_assets/{6B8A9306-D258-4800-A65A-86DC1D0A236C}_1754924926047.png b/attached_assets/{6B8A9306-D258-4800-A65A-86DC1D0A236C}_1754924926047.png
deleted file mode 100644
index ed0066a..0000000
Binary files a/attached_assets/{6B8A9306-D258-4800-A65A-86DC1D0A236C}_1754924926047.png and /dev/null differ
diff --git a/attached_assets/{6BF8C496-8BDD-4DCD-AD06-5E60F90EBCE9}_1754996898430.png b/attached_assets/{6BF8C496-8BDD-4DCD-AD06-5E60F90EBCE9}_1754996898430.png
deleted file mode 100644
index 79c4b2f..0000000
Binary files a/attached_assets/{6BF8C496-8BDD-4DCD-AD06-5E60F90EBCE9}_1754996898430.png and /dev/null differ
diff --git a/attached_assets/{6DA6AB2E-F626-4C12-B816-7F4EC8BA4D4A}_1755011550725.png b/attached_assets/{6DA6AB2E-F626-4C12-B816-7F4EC8BA4D4A}_1755011550725.png
deleted file mode 100644
index f9cb48a..0000000
Binary files a/attached_assets/{6DA6AB2E-F626-4C12-B816-7F4EC8BA4D4A}_1755011550725.png and /dev/null differ
diff --git a/attached_assets/{70D1374F-538C-4724-9532-8C6E54E4FBCE}_1754998054097.png b/attached_assets/{70D1374F-538C-4724-9532-8C6E54E4FBCE}_1754998054097.png
deleted file mode 100644
index ef259a3..0000000
Binary files a/attached_assets/{70D1374F-538C-4724-9532-8C6E54E4FBCE}_1754998054097.png and /dev/null differ
diff --git a/attached_assets/{770C1358-C0B0-4F25-9E82-6BB1092546C6}_1755002679357.png b/attached_assets/{770C1358-C0B0-4F25-9E82-6BB1092546C6}_1755002679357.png
deleted file mode 100644
index 4a0a3a3..0000000
Binary files a/attached_assets/{770C1358-C0B0-4F25-9E82-6BB1092546C6}_1755002679357.png and /dev/null differ
diff --git a/attached_assets/{78C105AD-BD53-4D7E-BF93-C1EF197A0988}_1754995961515.png b/attached_assets/{78C105AD-BD53-4D7E-BF93-C1EF197A0988}_1754995961515.png
deleted file mode 100644
index 52f8721..0000000
Binary files a/attached_assets/{78C105AD-BD53-4D7E-BF93-C1EF197A0988}_1754995961515.png and /dev/null differ
diff --git a/attached_assets/{78D671ED-C43E-41B0-838C-F9066C944DE4}_1755012433773.png b/attached_assets/{78D671ED-C43E-41B0-838C-F9066C944DE4}_1755012433773.png
deleted file mode 100644
index ee394d5..0000000
Binary files a/attached_assets/{78D671ED-C43E-41B0-838C-F9066C944DE4}_1755012433773.png and /dev/null differ
diff --git a/attached_assets/{8C7798C2-E7A7-4548-AEF4-43D9576796B3}_1754988741867.png b/attached_assets/{8C7798C2-E7A7-4548-AEF4-43D9576796B3}_1754988741867.png
deleted file mode 100644
index 1d99880..0000000
Binary files a/attached_assets/{8C7798C2-E7A7-4548-AEF4-43D9576796B3}_1754988741867.png and /dev/null differ
diff --git a/attached_assets/{8C93A7A2-1A60-4CA5-BFDF-EAA969D8C50E}_1755006306671.png b/attached_assets/{8C93A7A2-1A60-4CA5-BFDF-EAA969D8C50E}_1755006306671.png
deleted file mode 100644
index 3fa95f2..0000000
Binary files a/attached_assets/{8C93A7A2-1A60-4CA5-BFDF-EAA969D8C50E}_1755006306671.png and /dev/null differ
diff --git a/attached_assets/{9356B5AA-6F49-4981-BF70-054DC239AAA0}_1754996399645.png b/attached_assets/{9356B5AA-6F49-4981-BF70-054DC239AAA0}_1754996399645.png
deleted file mode 100644
index 127a0f0..0000000
Binary files a/attached_assets/{9356B5AA-6F49-4981-BF70-054DC239AAA0}_1754996399645.png and /dev/null differ
diff --git a/attached_assets/{A8ADEA18-2833-4D19-854B-2F8A035B13D5}_1754923509505.png b/attached_assets/{A8ADEA18-2833-4D19-854B-2F8A035B13D5}_1754923509505.png
deleted file mode 100644
index 14a4c05..0000000
Binary files a/attached_assets/{A8ADEA18-2833-4D19-854B-2F8A035B13D5}_1754923509505.png and /dev/null differ
diff --git a/attached_assets/{AC351FEE-BC19-401B-8F42-FBCC89BBAEDB}_1755013256979.png b/attached_assets/{AC351FEE-BC19-401B-8F42-FBCC89BBAEDB}_1755013256979.png
deleted file mode 100644
index 121528f..0000000
Binary files a/attached_assets/{AC351FEE-BC19-401B-8F42-FBCC89BBAEDB}_1755013256979.png and /dev/null differ
diff --git a/attached_assets/{B140BADE-D8C9-4DA2-92B3-E3E4AE043049}_1755007441143.png b/attached_assets/{B140BADE-D8C9-4DA2-92B3-E3E4AE043049}_1755007441143.png
deleted file mode 100644
index 9eb1de0..0000000
Binary files a/attached_assets/{B140BADE-D8C9-4DA2-92B3-E3E4AE043049}_1755007441143.png and /dev/null differ
diff --git a/attached_assets/{C0EB3F72-6919-46C0-A54C-84D869D92459}_1755005798705.png b/attached_assets/{C0EB3F72-6919-46C0-A54C-84D869D92459}_1755005798705.png
deleted file mode 100644
index fa5fcf1..0000000
Binary files a/attached_assets/{C0EB3F72-6919-46C0-A54C-84D869D92459}_1755005798705.png and /dev/null differ
diff --git a/attached_assets/{CE12C1A0-A0CB-49B6-A208-5377CA2E9FE3}_1754986220953.png b/attached_assets/{CE12C1A0-A0CB-49B6-A208-5377CA2E9FE3}_1754986220953.png
deleted file mode 100644
index 7cac13a..0000000
Binary files a/attached_assets/{CE12C1A0-A0CB-49B6-A208-5377CA2E9FE3}_1754986220953.png and /dev/null differ
diff --git a/attached_assets/{DFCCD614-BF99-4F78-845B-737CFC16AF4D}_1755006833150.png b/attached_assets/{DFCCD614-BF99-4F78-845B-737CFC16AF4D}_1755006833150.png
deleted file mode 100644
index 24ca636..0000000
Binary files a/attached_assets/{DFCCD614-BF99-4F78-845B-737CFC16AF4D}_1755006833150.png and /dev/null differ
diff --git a/attached_assets/{E6E79F46-7D13-4B31-859C-5957C0D12A79}_1754998968767.png b/attached_assets/{E6E79F46-7D13-4B31-859C-5957C0D12A79}_1754998968767.png
deleted file mode 100644
index f190dc6..0000000
Binary files a/attached_assets/{E6E79F46-7D13-4B31-859C-5957C0D12A79}_1754998968767.png and /dev/null differ
diff --git a/attached_assets/{E90CACDC-1E90-4AAF-8458-22BC13DF5B30}_1754998300995.png b/attached_assets/{E90CACDC-1E90-4AAF-8458-22BC13DF5B30}_1754998300995.png
deleted file mode 100644
index 1f5140f..0000000
Binary files a/attached_assets/{E90CACDC-1E90-4AAF-8458-22BC13DF5B30}_1754998300995.png and /dev/null differ
diff --git a/attached_assets/{EBE743A0-E190-4BE7-84A1-DEBE974124BA}_1754998681214.png b/attached_assets/{EBE743A0-E190-4BE7-84A1-DEBE974124BA}_1754998681214.png
deleted file mode 100644
index 6c38f7b..0000000
Binary files a/attached_assets/{EBE743A0-E190-4BE7-84A1-DEBE974124BA}_1754998681214.png and /dev/null differ
diff --git a/attached_assets/{F3D194AF-8FB6-4D0B-8963-F3959CF3A5F3}_1755010018200.png b/attached_assets/{F3D194AF-8FB6-4D0B-8963-F3959CF3A5F3}_1755010018200.png
deleted file mode 100644
index d9a380c..0000000
Binary files a/attached_assets/{F3D194AF-8FB6-4D0B-8963-F3959CF3A5F3}_1755010018200.png and /dev/null differ
diff --git a/attached_assets/{F54D13AD-6172-448A-8400-791459169E36}_1755007044787.png b/attached_assets/{F54D13AD-6172-448A-8400-791459169E36}_1755007044787.png
deleted file mode 100644
index 238fc0f..0000000
Binary files a/attached_assets/{F54D13AD-6172-448A-8400-791459169E36}_1755007044787.png and /dev/null differ
diff --git a/attached_assets/{F8DF25B7-AAB8-4266-9F4E-3717C4CA43C3}_1754989295935.png b/attached_assets/{F8DF25B7-AAB8-4266-9F4E-3717C4CA43C3}_1754989295935.png
deleted file mode 100644
index 45928ca..0000000
Binary files a/attached_assets/{F8DF25B7-AAB8-4266-9F4E-3717C4CA43C3}_1754989295935.png and /dev/null differ
diff --git a/attached_assets/{FB7EC083-1E79-4A38-8599-3300B363A960}_1755008238157.png b/attached_assets/{FB7EC083-1E79-4A38-8599-3300B363A960}_1755008238157.png
deleted file mode 100644
index f383fd2..0000000
Binary files a/attached_assets/{FB7EC083-1E79-4A38-8599-3300B363A960}_1755008238157.png and /dev/null differ
diff --git a/client/src/pages/BLReconciliation_backup.tsx b/client/src/pages/BLReconciliation_backup.tsx
deleted file mode 100644
index cad52f9..0000000
--- a/client/src/pages/BLReconciliation_backup.tsx
+++ /dev/null
@@ -1,462 +0,0 @@
-import React, { useState } from "react";
-import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
-import { safeFormat } from "@/lib/dateUtils";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Badge } from "@/components/ui/badge";
-import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
-import { useToast } from "@/hooks/use-toast";
-import { apiRequest } from "@/lib/queryClient";
-import { useStore } from "@/components/Layout";
-import { useAuthUnified } from "@/hooks/useAuthUnified";
-import { Search, Edit, FileText, Settings, Eye, AlertTriangle, X } from "lucide-react";
-
-export default function BLReconciliation() {
- const { user } = useAuthUnified();
- const { selectedStoreId } = useStore();
- const { toast } = useToast();
- const queryClient = useQueryClient();
-
- // Redirection pour les employés
- if (user?.role === 'employee') {
- return (
-
-
-
-
-
-
-
-
- Accès restreint
- Seuls les managers et administrateurs peuvent accéder au module de rapprochement BL/Factures.
-
-
-
-
-
- );
- }
-
- const [activeTab, setActiveTab] = useState("manual");
- const [searchTerm, setSearchTerm] = useState("");
-
- // Récupérer les fournisseurs pour la logique automatique
- const { data: suppliers = [] } = useQuery({
- queryKey: ['/api/suppliers'],
- });
-
- // Récupérer les livraisons validées avec BL
- const { data: deliveriesWithBL = [], isLoading } = useQuery({
- queryKey: ['/api/deliveries/bl', selectedStoreId],
- queryFn: async () => {
- const params = new URLSearchParams({});
- if (selectedStoreId && user?.role === 'admin') {
- params.append('storeId', selectedStoreId.toString());
- }
-
- const response = await fetch(`/api/deliveries?${params.toString()}`, {
- credentials: 'include'
- });
-
- if (!response.ok) {
- throw new Error('Failed to fetch deliveries');
- }
-
- const deliveries = await response.json();
- const filtered = Array.isArray(deliveries) ? deliveries.filter((d: any) => d.status === 'delivered') : [];
-
- return filtered.sort((a: any, b: any) => new Date(b.deliveredDate || b.updatedAt).getTime() - new Date(a.deliveredDate || a.updatedAt).getTime());
- },
- });
-
- // Séparer les livraisons selon le mode de rapprochement du fournisseur
- const manualReconciliationDeliveries = deliveriesWithBL.filter((delivery: any) => {
- const supplier = suppliers.find((s: any) => s.id === delivery.supplierId);
- return !supplier?.automaticReconciliation;
- });
-
- const automaticReconciliationDeliveries = deliveriesWithBL.filter((delivery: any) => {
- const supplier = suppliers.find((s: any) => s.id === delivery.supplierId);
- return supplier?.automaticReconciliation;
- });
-
- // Fonction pour dévalider un rapprochement automatique (directeurs et admins uniquement)
- const handleDevalidateAutoReconciliation = async (deliveryId: number) => {
- if (user?.role !== 'directeur' && user?.role !== 'admin') {
- toast({
- title: "Accès refusé",
- description: "Seuls les directeurs et administrateurs peuvent dévalider les rapprochements automatiques",
- variant: "destructive",
- });
- return;
- }
-
- try {
- await apiRequest(`/api/deliveries/${deliveryId}`, "PUT", {
- reconciled: false,
- validatedAt: null
- });
-
- toast({
- title: "Succès",
- description: "Rapprochement automatique dévalidé avec succès",
- });
-
- queryClient.invalidateQueries({ queryKey: ['/api/deliveries/bl'] });
- } catch (error) {
- toast({
- title: "Erreur",
- description: "Impossible de dévalider le rapprochement",
- variant: "destructive",
- });
- }
- };
-
- // Filtrage des livraisons par recherche
- const filterDeliveries = (deliveries: any[]) => {
- return deliveries.filter((delivery: any) => {
- const searchLower = searchTerm.toLowerCase();
- return (
- delivery.supplier?.name?.toLowerCase().includes(searchLower) ||
- delivery.blNumber?.toLowerCase().includes(searchLower) ||
- delivery.invoiceReference?.toLowerCase().includes(searchLower)
- );
- });
- };
-
- const filteredManualDeliveries = filterDeliveries(manualReconciliationDeliveries);
- const filteredAutomaticDeliveries = filterDeliveries(automaticReconciliationDeliveries);
-
- const canModify = user?.role === 'directeur' || user?.role === 'admin';
-
- return (
-
- {/* Header avec onglets */}
-
-
-
-
-
- Rapprochement BL/Factures
-
-
- Gestion des rapprochements manuels et automatiques
-
-
-
-
- {manualReconciliationDeliveries.length} rapprochements manuels
-
-
- {automaticReconciliationDeliveries.length} rapprochements automatiques
-
-
-
-
- {/* Onglets */}
-
-
-
-
- Rapprochement Manuel
-
- {manualReconciliationDeliveries.length}
-
-
-
-
- Rapprochement Automatique
-
- {automaticReconciliationDeliveries.length}
-
-
-
-
-
-
- {/* Filtre de recherche */}
-
-
-
- setSearchTerm(e.target.value)}
- className="pl-10 border border-gray-300 shadow-sm"
- />
-
-
-
- {/* Contenu des onglets */}
-
-
- {filteredManualDeliveries.length === 0 ? (
-
-
-
- Aucun rapprochement manuel trouvé
-
-
- Les livraisons de fournisseurs en mode manuel apparaîtront ici.
-
-
- ) : (
-
-
-
-
-
-
- Fournisseur
-
-
- N° BL
-
-
- Date Livr.
-
-
- Montant BL
-
-
- Ref. Facture
-
-
- Montant Fact.
-
-
- Magasin
-
-
- Actions
-
-
-
-
- {filteredManualDeliveries.map((delivery: any) => (
-
-
-
- {delivery.supplier?.name}
-
-
-
-
- {delivery.blNumber || (
- Non renseigné
- )}
-
-
-
-
- {safeFormat(delivery.scheduledDate, 'dd/MM/yy')}
-
-
-
-
- {delivery.blAmount ?
- `${parseFloat(delivery.blAmount).toFixed(2)}€` :
- Non renseigné
- }
-
-
-
-
- {delivery.invoiceReference || (
- Non renseigné
- )}
-
-
-
-
- {delivery.invoiceAmount ?
- `${parseFloat(delivery.invoiceAmount).toFixed(2)}€` :
- Non renseigné
- }
-
-
-
-
- {delivery.group?.name}
-
-
-
-
-
-
-
-
-
-
- ))}
-
-
-
-
- )}
-
-
-
- {/* Message d'information */}
-
-
-
-
-
Mode rapprochement automatique
-
- Les livraisons de fournisseurs en mode automatique sont validées automatiquement lorsqu'elles ont le statut "delivered" et un numéro de BL.
- {canModify ? (
- " Vous pouvez dévalider ces rapprochements si nécessaire."
- ) : (
- " Seuls les directeurs et administrateurs peuvent modifier ces rapprochements."
- )}
-
-
-
-
-
- {filteredAutomaticDeliveries.length === 0 ? (
-
-
-
- Aucun rapprochement automatique trouvé
-
-
- Les livraisons de fournisseurs en mode automatique apparaîtront ici.
-
-
- ) : (
-
-
-
-
-
-
- Fournisseur
- AUTO
-
-
- N° BL
-
-
- Date Livr.
-
-
- Date Valid.
-
-
- Montant BL
-
-
- Ref. Facture
-
-
- Montant Fact.
-
-
- Magasin
-
-
- Actions
-
-
-
-
- {filteredAutomaticDeliveries.map((delivery: any) => (
-
-
-
-
- {delivery.supplier?.name}
-
-
-
-
-
-
- {delivery.blNumber || '-'}
-
-
-
-
- {safeFormat(delivery.scheduledDate, 'dd/MM/yy')}
-
-
-
-
- {delivery.reconciled && delivery.updatedAt ?
- safeFormat(delivery.updatedAt, 'dd/MM/yy') :
- '-'
- }
-
-
-
-
- {delivery.blAmount ?
- `${parseFloat(delivery.blAmount).toFixed(2)}€` :
- '-'
- }
-
-
-
-
- {delivery.invoiceReference || '-'}
-
-
-
-
- {delivery.invoiceAmount ?
- `${parseFloat(delivery.invoiceAmount).toFixed(2)}€` :
- '-'
- }
-
-
-
-
- {delivery.group?.name}
-
-
-
-
- {canModify ? (
- <>
-
-
-
- handleDevalidateAutoReconciliation(delivery.id)}
- className="text-gray-600 hover:text-orange-600 transition-colors duration-200 p-1 hover:bg-orange-50"
- title="Dévalider le rapprochement automatique"
- >
-
-
- >
- ) : (
-
-
-
- )}
-
-
-
- ))}
-
-
-
-
- )}
-
-
-
- );
-}
\ No newline at end of file
diff --git a/client/src/pages/BLReconciliation_broken.tsx b/client/src/pages/BLReconciliation_broken.tsx
deleted file mode 100644
index c6bba9e..0000000
--- a/client/src/pages/BLReconciliation_broken.tsx
+++ /dev/null
@@ -1,778 +0,0 @@
-import React, { useState, useEffect } from "react";
-import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
-import { safeFormat } from "@/lib/dateUtils";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Badge } from "@/components/ui/badge";
-import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
-import { useToast } from "@/hooks/use-toast";
-import { apiRequest } from "@/lib/queryClient";
-import { useStore } from "@/components/Layout";
-import { useAuthUnified } from "@/hooks/useAuthUnified";
-import { usePermissions } from "@shared/permissions";
-import { Search, Edit, FileText, Settings, Eye, AlertTriangle, X, Check, Trash2, Ban, ChevronLeft, ChevronRight } from "lucide-react";
-import type { Supplier } from "@shared/schema";
-
-export default function BLReconciliation() {
- const { user } = useAuthUnified();
- const { selectedStoreId } = useStore();
- const { toast } = useToast();
- const queryClient = useQueryClient();
- const permissions = usePermissions(user?.role);
-
- // Vérification des permissions d'accès au module
- if (!permissions.canView('reconciliation')) {
- return (
-
-
-
-
-
-
-
-
- Accès restreint
- Seuls les directeurs et administrateurs peuvent accéder au module de rapprochement BL/Factures.
-
-
-
-
-
- );
- }
-
- const [activeTab, setActiveTab] = useState("manual");
- const [searchTerm, setSearchTerm] = useState("");
- const [currentPage, setCurrentPage] = useState(1);
- const itemsPerPage = 20;
-
- // Récupérer les fournisseurs pour la logique automatique
- const { data: suppliers = [], isLoading: suppliersLoading } = useQuery({
- queryKey: ['/api/suppliers'],
- });
-
- // Récupérer les livraisons validées avec BL
- const { data: deliveriesWithBL = [], isLoading } = useQuery({
- queryKey: ['/api/deliveries/bl', selectedStoreId],
- queryFn: async () => {
- const params = new URLSearchParams({});
- if (selectedStoreId && user?.role === 'admin') {
- params.append('storeId', selectedStoreId.toString());
- }
-
- const response = await fetch(`/api/deliveries?${params.toString()}`, {
- credentials: 'include'
- });
-
- if (!response.ok) {
- throw new Error('Failed to fetch deliveries');
- }
-
- const deliveries = await response.json();
- const filtered = Array.isArray(deliveries) ? deliveries.filter((d: any) => d.status === 'delivered') : [];
-
- return filtered.sort((a: any, b: any) => new Date(b.deliveredDate || b.updatedAt).getTime() - new Date(a.deliveredDate || a.updatedAt).getTime());
- },
- });
-
- // Séparer les livraisons selon le mode de rapprochement du fournisseur
- const manualReconciliationDeliveries = deliveriesWithBL.filter((delivery: any) => {
- const supplier = suppliers.find((s: any) => s.id === delivery.supplierId);
- return !supplier?.automaticReconciliation;
- });
-
- const automaticReconciliationDeliveries = deliveriesWithBL.filter((delivery: any) => {
- const supplier = suppliers.find((s: any) => s.id === delivery.supplierId);
- return supplier?.automaticReconciliation;
- });
-
- // Mutation pour valider un rapprochement manuel
- const validateManualMutation = useMutation({
- mutationFn: async (deliveryId: number) => {
- return await apiRequest(`/api/deliveries/${deliveryId}`, "PUT", {
- reconciled: true,
- validatedAt: new Date().toISOString()
- });
- },
- onSuccess: () => {
- toast({
- title: "Succès",
- description: "Rapprochement validé avec succès",
- });
- queryClient.invalidateQueries({ queryKey: ['/api/deliveries/bl'] });
- },
- onError: () => {
- toast({
- title: "Erreur",
- description: "Impossible de valider le rapprochement",
- variant: "destructive",
- });
- }
- });
-
- // Mutation pour dévalider un rapprochement (admins uniquement)
- const devalidateMutation = useMutation({
- mutationFn: async (deliveryId: number) => {
- return await apiRequest(`/api/deliveries/${deliveryId}`, "PUT", {
- reconciled: false,
- validatedAt: null
- });
- },
- onSuccess: () => {
- toast({
- title: "Succès",
- description: "Rapprochement dévalidé avec succès",
- });
- queryClient.invalidateQueries({ queryKey: ['/api/deliveries/bl'] });
- },
- onError: () => {
- toast({
- title: "Erreur",
- description: "Impossible de dévalider le rapprochement",
- variant: "destructive",
- });
- }
- });
-
- // Mutation pour supprimer une ligne (admins uniquement)
- const deleteMutation = useMutation({
- mutationFn: async (deliveryId: number) => {
- return await apiRequest(`/api/deliveries/${deliveryId}`, "DELETE");
- },
- onSuccess: () => {
- toast({
- title: "Succès",
- description: "Ligne supprimée avec succès",
- });
- queryClient.invalidateQueries({ queryKey: ['/api/deliveries/bl'] });
- },
- onError: () => {
- toast({
- title: "Erreur",
- description: "Impossible de supprimer la ligne",
- variant: "destructive",
- });
- }
- });
-
- // Fonctions de gestion des actions
- const handleValidateManual = (deliveryId: number) => {
- if (!permissions.canValidate('reconciliation')) {
- toast({
- title: "Accès refusé",
- description: "Vous n'avez pas les permissions pour valider les rapprochements",
- variant: "destructive",
- });
- return;
- }
- validateManualMutation.mutate(deliveryId);
- };
-
- const handleDevalidate = (deliveryId: number) => {
- if (!permissions.canEdit('reconciliation')) {
- toast({
- title: "Accès refusé",
- description: "Seuls les administrateurs peuvent dévalider les rapprochements",
- variant: "destructive",
- });
- return;
- }
- if (confirm("Êtes-vous sûr de vouloir dévalider ce rapprochement ?")) {
- devalidateMutation.mutate(deliveryId);
- }
- };
-
- const handleDelete = (deliveryId: number) => {
- if (!permissions.canDelete('reconciliation')) {
- toast({
- title: "Accès refusé",
- description: "Seuls les administrateurs peuvent supprimer les lignes",
- variant: "destructive",
- });
- return;
- }
- if (confirm("Êtes-vous sûr de vouloir supprimer cette ligne ? Cette action est irréversible.")) {
- deleteMutation.mutate(deliveryId);
- }
- };
-
- // Filtrage des livraisons par recherche
- const filterDeliveries = (deliveries: any[]) => {
- return deliveries.filter((delivery: any) => {
- const searchLower = searchTerm.toLowerCase();
- return (
- delivery.supplier?.name?.toLowerCase().includes(searchLower) ||
- delivery.blNumber?.toLowerCase().includes(searchLower) ||
- delivery.invoiceReference?.toLowerCase().includes(searchLower)
- );
- });
- };
-
- const filteredManualDeliveries = filterDeliveries(manualReconciliationDeliveries);
- const filteredAutomaticDeliveries = filterDeliveries(automaticReconciliationDeliveries);
-
- // Pagination
- const getCurrentPageData = (data: any[]) => {
- const startIndex = (currentPage - 1) * itemsPerPage;
- const endIndex = startIndex + itemsPerPage;
- return data.slice(startIndex, endIndex);
- };
-
- const getTotalPages = (data: any[]) => {
- return Math.ceil(data.length / itemsPerPage);
- };
-
- const currentManualData = getCurrentPageData(filteredManualDeliveries);
- const currentAutomaticData = getCurrentPageData(filteredAutomaticDeliveries);
-
- const totalManualPages = getTotalPages(filteredManualDeliveries);
- const totalAutomaticPages = getTotalPages(filteredAutomaticDeliveries);
-
- // Reset page when changing tabs or searching
- useEffect(() => {
- setCurrentPage(1);
- }, [activeTab, searchTerm]);
-
- // Vérifier si une ligne est dévalidée (pour la coloration)
- const isDevalidated = (delivery: any) => {
- return delivery.reconciled === false && delivery.validatedAt === null;
- };
-
- // Composant de pagination
- const PaginationControls = ({ currentPage, totalPages, onPageChange, totalItems, itemsPerPage }: {
- currentPage: number;
- totalPages: number;
- onPageChange: (page: number) => void;
- totalItems: number;
- itemsPerPage: number;
- }) => {
- if (totalPages <= 1) return null;
-
- const startItem = (currentPage - 1) * itemsPerPage + 1;
- const endItem = Math.min(currentPage * itemsPerPage, totalItems);
-
- return (
-
-
-
- Affichage de {startItem} à {endItem} sur {totalItems} éléments
-
-
-
-
onPageChange(currentPage - 1)}
- disabled={currentPage === 1}
- className="flex items-center space-x-1"
- >
-
- Précédent
-
-
-
- {Array.from({ length: totalPages }, (_, i) => i + 1)
- .filter(page => {
- // Afficher la première page, la dernière page, et les pages autour de la page actuelle
- return page === 1 ||
- page === totalPages ||
- (page >= currentPage - 2 && page <= currentPage + 2);
- })
- .map((page, index, array) => {
- // Ajouter des points de suspension si nécessaire
- const prevPage = array[index - 1];
- const showEllipsis = prevPage && page > prevPage + 1;
-
- return (
-
- {showEllipsis && (
- ...
- )}
- onPageChange(page)}
- className="w-8 h-8 p-0"
- >
- {page}
-
-
- );
- })}
-
-
-
onPageChange(currentPage + 1)}
- disabled={currentPage === totalPages}
- className="flex items-center space-x-1"
- >
- Suivant
-
-
-
-
- );
- };
-
- if (isLoading || suppliersLoading) {
- return (
-
- );
- }
-
- return (
-
- {/* Header avec onglets */}
-
-
-
-
-
- Rapprochement BL/Factures
-
-
- Gestion des rapprochements manuels et automatiques
-
-
-
-
- {manualReconciliationDeliveries.length} rapprochements manuels
-
-
- {automaticReconciliationDeliveries.length} rapprochements automatiques
-
-
-
-
- {/* Onglets */}
-
-
-
-
- Rapprochement Manuel
-
- {manualReconciliationDeliveries.length}
-
-
-
-
- Rapprochement Automatique
-
- {automaticReconciliationDeliveries.length}
-
-
-
-
-
-
- {/* Filtre de recherche */}
-
-
-
- setSearchTerm(e.target.value)}
- className="pl-10 border border-gray-300 shadow-sm"
- />
-
-
-
- {/* Contenu des onglets */}
-
-
- {filteredManualDeliveries.length === 0 ? (
-
-
-
- Aucun rapprochement manuel trouvé
-
-
- Les livraisons de fournisseurs en mode manuel apparaîtront ici.
-
-
- ) : (
-
- {/* Pagination du haut */}
-
-
-
-
-
-
-
- Fournisseur
-
-
- N° BL
-
-
- Date Livr.
-
-
- Montant BL
-
-
- Ref. Facture
-
-
- Montant Fact.
-
-
- Statut
-
-
- Actions
-
-
-
-
- {currentManualData.map((delivery: any) => (
-
-
-
- {delivery.supplier?.name}
-
-
-
-
- {delivery.blNumber || (
- Non renseigné
- )}
-
-
-
-
- {safeFormat(delivery.scheduledDate, 'dd/MM/yy')}
-
-
-
-
- {delivery.blAmount ?
- `${parseFloat(delivery.blAmount).toFixed(2)}€` :
- Non renseigné
- }
-
-
-
-
- {delivery.invoiceReference || (
- Non renseigné
- )}
-
-
-
-
- {delivery.invoiceAmount ?
- `${parseFloat(delivery.invoiceAmount).toFixed(2)}€` :
- Non renseigné
- }
-
-
-
- {delivery.reconciled ? (
-
- Validé
-
- ) : isDevalidated(delivery) ? (
-
- Dévalidé
-
- ) : (
-
- En attente
-
- )}
-
-
-
- {permissions.canEdit('reconciliation') && (
-
-
-
- )}
-
- {!delivery.reconciled && permissions.canValidate('reconciliation') && (
- handleValidateManual(delivery.id)}
- disabled={validateManualMutation.isPending}
- className="text-green-600 hover:text-green-700 p-1"
- title="Valider"
- >
-
-
- )}
-
- {delivery.reconciled && permissions.canEdit('reconciliation') && user?.role === 'admin' && (
- handleDevalidate(delivery.id)}
- disabled={devalidateMutation.isPending}
- className="text-orange-600 hover:text-orange-700 p-1"
- title="Dévalider"
- >
-
-
- )}
-
- {permissions.canDelete('reconciliation') && (
- handleDelete(delivery.id)}
- disabled={deleteMutation.isPending}
- className="text-red-600 hover:text-red-700 p-1"
- title="Supprimer"
- >
-
-
- )}
-
-
-
- ))}
-
-
-
-
- {/* Pagination du bas */}
-
-
- )}
-
-
-
- {/* Message d'information */}
-
-
-
-
-
Mode rapprochement automatique
-
- Les livraisons de fournisseurs en mode automatique sont validées automatiquement lorsqu'elles ont le statut "delivered" et un numéro de BL.
- {permissions.canEdit('reconciliation') ? (
- " Vous pouvez dévalider ces rapprochements si nécessaire."
- ) : (
- " Seuls les directeurs et administrateurs peuvent modifier ces rapprochements."
- )}
-
-
-
-
-
- {filteredAutomaticDeliveries.length === 0 ? (
-
-
-
- Aucun rapprochement automatique trouvé
-
-
- Les livraisons de fournisseurs en mode automatique apparaîtront ici.
-
-
- ) : (
-
- {/* Pagination du haut */}
-
-
-
-
-
-
-
- Fournisseur
- AUTO
-
-
- N° BL
-
-
- Date Livr.
-
-
- Date Valid.
-
-
- Montant BL
-
-
- Ref. Facture
-
-
- Statut
-
-
- Actions
-
-
-
-
- {currentAutomaticData.map((delivery: any) => (
-
-
-
-
- {delivery.supplier?.name}
-
-
-
-
-
-
- {delivery.blNumber || '-'}
-
-
-
-
- {safeFormat(delivery.scheduledDate, 'dd/MM/yy')}
-
-
-
-
- {delivery.reconciled && delivery.validatedAt ?
- safeFormat(delivery.validatedAt, 'dd/MM/yy') :
- '-'
- }
-
-
-
-
- {delivery.blAmount ?
- `${parseFloat(delivery.blAmount).toFixed(2)}€` :
- '-'
- }
-
-
-
-
- {delivery.invoiceReference || '-'}
-
-
-
- {isDevalidated(delivery) ? (
-
- Dévalidé
-
- ) : (
-
- Auto-validé
-
- )}
-
-
-
- {isDevalidated(delivery) && permissions.canEdit('reconciliation') && (
- <>
-
-
-
- handleValidateManual(delivery.id)}
- disabled={validateManualMutation.isPending}
- className="text-green-600 hover:text-green-700 p-1"
- title="Valider"
- >
-
-
- >
- )}
-
- {!isDevalidated(delivery) && permissions.canEdit('reconciliation') && (
- handleDevalidate(delivery.id)}
- disabled={devalidateMutation.isPending}
- className="text-orange-600 hover:text-orange-700 p-1"
- title="Dévalider"
- >
-
-
- )}
-
- {permissions.canDelete('reconciliation') && (
- handleDelete(delivery.id)}
- disabled={deleteMutation.isPending}
- className="text-red-600 hover:text-red-700 p-1"
- title="Supprimer"
- >
-
-
- )}
-
-
-
- ))}
-
-
-
-
- {/* Pagination du bas */}
-
-
- )}
-
-
-
- );
-}
\ No newline at end of file
diff --git a/client/src/pages/BLReconciliation_recent_broken.tsx b/client/src/pages/BLReconciliation_recent_broken.tsx
deleted file mode 100644
index c2cba4e..0000000
--- a/client/src/pages/BLReconciliation_recent_broken.tsx
+++ /dev/null
@@ -1,840 +0,0 @@
-import { useState, useEffect } from "react";
-import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
-import { safeFormat } from "@/lib/dateUtils";
-import { useToast } from "@/hooks/use-toast-robust";
-import { apiRequest } from "@/lib/queryClient";
-import { useStore } from "@/components/Layout";
-import { useAuthUnified } from "@/hooks/useAuthUnified";
-import { usePermissions } from "@shared/permissions";
-import { Search, Edit, FileText, Settings, Eye, AlertTriangle, X, Check, Trash2, Ban, ChevronLeft, ChevronRight } from "lucide-react";
-import type { Supplier } from "@shared/schema";
-
-// Composants UI robustes sans dépendances shadcn/ui problématiques
-const RobustButton = ({ children, onClick, disabled = false, variant = "default", size = "default", className = "", title = "" }: {
- children: React.ReactNode,
- onClick?: () => void,
- disabled?: boolean,
- variant?: "default" | "ghost" | "outline" | "destructive",
- size?: "default" | "sm" | "lg",
- className?: string,
- title?: string
-}) => {
- const variantStyles = {
- default: "bg-blue-600 text-white hover:bg-blue-700 border-blue-600",
- ghost: "text-gray-600 hover:text-gray-900 hover:bg-gray-100 border-transparent",
- outline: "border-gray-300 bg-white text-gray-700 hover:bg-gray-50",
- destructive: "bg-red-600 text-white hover:bg-red-700 border-red-600"
- };
-
- const sizeStyles = {
- default: "px-4 py-2 text-sm",
- sm: "px-3 py-1.5 text-xs",
- lg: "px-6 py-3 text-base"
- };
-
- return (
-
- {children}
-
- );
-};
-
-const RobustInput = ({ placeholder, value, onChange, className = "" }: {
- placeholder?: string,
- value: string,
- onChange: (e: React.ChangeEvent) => void,
- className?: string
-}) => {
- return (
-
- );
-};
-
-const RobustBadge = ({ children, variant = "default", className = "" }: {
- children: React.ReactNode,
- variant?: "default" | "secondary" | "destructive" | "outline",
- className?: string
-}) => {
- const variantStyles = {
- default: "bg-blue-100 text-blue-800 border-blue-200",
- secondary: "bg-gray-100 text-gray-800 border-gray-200",
- destructive: "bg-red-100 text-red-800 border-red-200",
- outline: "bg-white text-gray-700 border-gray-300"
- };
-
- return (
-
- {children}
-
- );
-};
-
-const RobustTabs = ({ value, onValueChange, children }: {
- value: string,
- onValueChange: (value: string) => void,
- children: React.ReactNode
-}) => {
- return (
- onValueChange}>
- {children}
-
- );
-};
-
-const RobustTabsList = ({ children }: { children: React.ReactNode }) => {
- return (
-
- {children}
-
- );
-};
-
-const RobustTabsTrigger = ({ value, children, isActive, onClick }: {
- value: string,
- children: React.ReactNode,
- isActive: boolean,
- onClick: () => void
-}) => {
- return (
-
- {children}
-
- );
-};
-
-export default function BLReconciliation() {
- const { user } = useAuthUnified();
- const { selectedStoreId } = useStore();
- const { toast } = useToast();
- const queryClient = useQueryClient();
- const permissions = usePermissions(user?.role);
-
- // Vérification des permissions d'accès au module
- if (!permissions.canView('reconciliation')) {
- return (
-
-
-
-
-
-
-
-
- Accès restreint
- Seuls les directeurs et administrateurs peuvent accéder au module de rapprochement BL/Factures.
-
-
-
-
-
- );
- }
-
- const [activeTab, setActiveTab] = useState("manual");
- const [searchTerm, setSearchTerm] = useState("");
- const [currentPage, setCurrentPage] = useState(1);
- const itemsPerPage = 20;
-
- // Récupérer les fournisseurs pour la logique automatique
- const { data: suppliers = [], isLoading: suppliersLoading } = useQuery({
- queryKey: ['/api/suppliers'],
- });
-
- // Récupérer les livraisons validées avec BL
- const { data: deliveriesWithBL = [], isLoading } = useQuery({
- queryKey: ['/api/deliveries/bl', selectedStoreId],
- queryFn: async () => {
- const params = new URLSearchParams({});
- if (selectedStoreId && user?.role === 'admin') {
- params.append('storeId', selectedStoreId.toString());
- }
-
- const response = await fetch(`/api/deliveries?${params.toString()}`, {
- credentials: 'include'
- });
-
- if (!response.ok) {
- throw new Error('Failed to fetch deliveries');
- }
-
- const deliveries = await response.json();
- const filtered = Array.isArray(deliveries) ? deliveries.filter((d: any) => d.status === 'delivered') : [];
-
- return filtered.sort((a: any, b: any) => new Date(b.deliveredDate || b.updatedAt).getTime() - new Date(a.deliveredDate || a.updatedAt).getTime());
- },
- });
-
- // Séparer les livraisons selon le mode de rapprochement du fournisseur
- const manualReconciliationDeliveries = deliveriesWithBL.filter((delivery: any) => {
- const supplier = suppliers.find((s: any) => s.id === delivery.supplierId);
- return !supplier?.automaticReconciliation;
- });
-
- const automaticReconciliationDeliveries = deliveriesWithBL.filter((delivery: any) => {
- const supplier = suppliers.find((s: any) => s.id === delivery.supplierId);
- return supplier?.automaticReconciliation;
- });
-
- // Mutations pour les actions
- const validateManualMutation = useMutation({
- mutationFn: async (deliveryId: number) => {
- return await apiRequest(`/api/deliveries/${deliveryId}`, "PUT", {
- reconciled: true,
- validatedAt: new Date().toISOString()
- });
- },
- onSuccess: () => {
- toast({
- title: "Succès",
- description: "Rapprochement validé avec succès",
- });
- queryClient.invalidateQueries({ queryKey: ['/api/deliveries/bl'] });
- },
- onError: () => {
- toast({
- title: "Erreur",
- description: "Impossible de valider le rapprochement",
- variant: "destructive",
- });
- }
- });
-
- const devalidateMutation = useMutation({
- mutationFn: async (deliveryId: number) => {
- return await apiRequest(`/api/deliveries/${deliveryId}`, "PUT", {
- reconciled: false,
- validatedAt: null
- });
- },
- onSuccess: () => {
- toast({
- title: "Succès",
- description: "Rapprochement dévalidé avec succès",
- });
- queryClient.invalidateQueries({ queryKey: ['/api/deliveries/bl'] });
- },
- onError: () => {
- toast({
- title: "Erreur",
- description: "Impossible de dévalider le rapprochement",
- variant: "destructive",
- });
- }
- });
-
- const deleteMutation = useMutation({
- mutationFn: async (deliveryId: number) => {
- return await apiRequest(`/api/deliveries/${deliveryId}`, "DELETE");
- },
- onSuccess: () => {
- toast({
- title: "Succès",
- description: "Ligne supprimée avec succès",
- });
- queryClient.invalidateQueries({ queryKey: ['/api/deliveries/bl'] });
- },
- onError: () => {
- toast({
- title: "Erreur",
- description: "Impossible de supprimer la ligne",
- variant: "destructive",
- });
- }
- });
-
- // Fonctions de gestion des actions
- const handleValidateManual = (deliveryId: number) => {
- if (!permissions.canValidate('reconciliation')) {
- toast({
- title: "Accès refusé",
- description: "Vous n'avez pas les permissions pour valider les rapprochements",
- variant: "destructive",
- });
- return;
- }
- validateManualMutation.mutate(deliveryId);
- };
-
- const handleDevalidate = (deliveryId: number) => {
- if (!permissions.canEdit('reconciliation')) {
- toast({
- title: "Accès refusé",
- description: "Seuls les administrateurs peuvent dévalider les rapprochements",
- variant: "destructive",
- });
- return;
- }
- if (confirm("Êtes-vous sûr de vouloir dévalider ce rapprochement ?")) {
- devalidateMutation.mutate(deliveryId);
- }
- };
-
- const handleDelete = (deliveryId: number) => {
- if (!permissions.canDelete('reconciliation')) {
- toast({
- title: "Accès refusé",
- description: "Seuls les administrateurs peuvent supprimer les lignes",
- variant: "destructive",
- });
- return;
- }
- if (confirm("Êtes-vous sûr de vouloir supprimer cette ligne ? Cette action est irréversible.")) {
- deleteMutation.mutate(deliveryId);
- }
- };
-
- // Filtrage des livraisons par recherche
- const filterDeliveries = (deliveries: any[]) => {
- return deliveries.filter((delivery: any) => {
- const searchLower = searchTerm.toLowerCase();
- return (
- delivery.supplier?.name?.toLowerCase().includes(searchLower) ||
- delivery.blNumber?.toLowerCase().includes(searchLower) ||
- delivery.invoiceReference?.toLowerCase().includes(searchLower)
- );
- });
- };
-
- const filteredManualDeliveries = filterDeliveries(manualReconciliationDeliveries);
- const filteredAutomaticDeliveries = filterDeliveries(automaticReconciliationDeliveries);
-
- // Pagination
- const getCurrentPageData = (data: any[]) => {
- const startIndex = (currentPage - 1) * itemsPerPage;
- const endIndex = startIndex + itemsPerPage;
- return data.slice(startIndex, endIndex);
- };
-
- const getTotalPages = (data: any[]) => {
- return Math.ceil(data.length / itemsPerPage);
- };
-
- const currentManualData = getCurrentPageData(filteredManualDeliveries);
- const currentAutomaticData = getCurrentPageData(filteredAutomaticDeliveries);
-
- const totalManualPages = getTotalPages(filteredManualDeliveries);
- const totalAutomaticPages = getTotalPages(filteredAutomaticDeliveries);
-
- // Reset page when changing tabs or searching
- useEffect(() => {
- setCurrentPage(1);
- }, [activeTab, searchTerm]);
-
- // Vérifier si une ligne est dévalidée (pour la coloration)
- const isDevalidated = (delivery: any) => {
- return delivery.reconciled === false && delivery.validatedAt === null;
- };
-
- // Composant de pagination robuste
- const RobustPagination = ({ currentPage, totalPages, onPageChange, totalItems, itemsPerPage }: {
- currentPage: number;
- totalPages: number;
- onPageChange: (page: number) => void;
- totalItems: number;
- itemsPerPage: number;
- }) => {
- if (totalPages <= 1) return null;
-
- const startItem = (currentPage - 1) * itemsPerPage + 1;
- const endItem = Math.min(currentPage * itemsPerPage, totalItems);
-
- return (
-
-
-
- Affichage de {startItem} à {endItem} sur {totalItems} éléments
-
-
-
- onPageChange(currentPage - 1)}
- disabled={currentPage === 1}
- className="flex items-center space-x-1"
- >
-
- Précédent
-
-
-
- Page {currentPage} sur {totalPages}
-
-
- onPageChange(currentPage + 1)}
- disabled={currentPage === totalPages}
- className="flex items-center space-x-1"
- >
- Suivant
-
-
-
-
- );
- };
-
- if (isLoading || suppliersLoading) {
- return (
-
- );
- }
-
- return (
-
- {/* Header avec onglets */}
-
-
-
-
-
- Rapprochement BL/Factures
-
-
- Gestion des rapprochements manuels et automatiques
-
-
-
-
- {manualReconciliationDeliveries.length} rapprochements manuels
-
-
- {automaticReconciliationDeliveries.length} rapprochements automatiques
-
-
-
-
- {/* Onglets robustes */}
-
-
- setActiveTab("manual")}
- >
-
-
- Rapprochement Manuel
-
- {manualReconciliationDeliveries.length}
-
-
-
- setActiveTab("automatic")}
- >
-
-
- Rapprochement Automatique
-
- {automaticReconciliationDeliveries.length}
-
-
-
-
-
-
-
- {/* Filtre de recherche */}
-
-
-
- setSearchTerm(e.target.value)}
- className="pl-10"
- />
-
-
-
- {/* Contenu des onglets */}
- {activeTab === "manual" && (
-
- {filteredManualDeliveries.length === 0 ? (
-
-
-
- Aucun rapprochement manuel trouvé
-
-
- Les livraisons de fournisseurs en mode manuel apparaîtront ici.
-
-
- ) : (
-
- {/* Pagination du haut */}
-
-
-
-
-
-
- Fournisseur
- N° BL
- Date Livr.
- Montant BL
- Ref. Facture
- Montant Fact.
- Statut
- Actions
-
-
-
- {currentManualData.map((delivery: any) => (
-
-
-
- {delivery.supplier?.name}
-
-
-
-
- {delivery.blNumber || (
- Non renseigné
- )}
-
-
-
-
- {safeFormat(delivery.scheduledDate, 'dd/MM/yy')}
-
-
-
-
- {delivery.blAmount ?
- `${parseFloat(delivery.blAmount).toFixed(2)}€` :
- Non renseigné
- }
-
-
-
-
- {delivery.invoiceReference || (
- Non renseigné
- )}
-
-
-
-
- {delivery.invoiceAmount ?
- `${parseFloat(delivery.invoiceAmount).toFixed(2)}€` :
- Non renseigné
- }
-
-
-
- {delivery.reconciled ? (
-
- Validé
-
- ) : isDevalidated(delivery) ? (
-
- Dévalidé
-
- ) : (
-
- En attente
-
- )}
-
-
-
- {permissions.canEdit('reconciliation') && (
-
-
-
- )}
-
- {!delivery.reconciled && permissions.canValidate('reconciliation') && (
- handleValidateManual(delivery.id)}
- disabled={validateManualMutation.isPending}
- className="text-green-600 hover:text-green-700 p-1"
- title="Valider"
- >
-
-
- )}
-
- {delivery.reconciled && permissions.canEdit('reconciliation') && user?.role === 'admin' && (
- handleDevalidate(delivery.id)}
- disabled={devalidateMutation.isPending}
- className="text-orange-600 hover:text-orange-700 p-1"
- title="Dévalider"
- >
-
-
- )}
-
- {permissions.canDelete('reconciliation') && (
- handleDelete(delivery.id)}
- disabled={deleteMutation.isPending}
- className="text-red-600 hover:text-red-700 p-1"
- title="Supprimer"
- >
-
-
- )}
-
-
-
- ))}
-
-
-
-
- {/* Pagination du bas */}
-
-
- )}
-
- )}
-
- {activeTab === "automatic" && (
-
- {/* Message d'information */}
-
-
-
-
-
Mode rapprochement automatique
-
- Les livraisons de fournisseurs en mode automatique sont validées automatiquement lorsqu'elles ont le statut "delivered" et un numéro de BL.
- {permissions.canEdit('reconciliation') ? (
- " Vous pouvez dévalider ces rapprochements si nécessaire."
- ) : (
- " Seuls les directeurs et administrateurs peuvent modifier ces rapprochements."
- )}
-
-
-
-
-
- {filteredAutomaticDeliveries.length === 0 ? (
-
-
-
- Aucun rapprochement automatique trouvé
-
-
- Les livraisons de fournisseurs en mode automatique apparaîtront ici.
-
-
- ) : (
-
- {/* Pagination du haut */}
-
-
-
-
-
-
-
- Fournisseur
- AUTO
-
- N° BL
- Date Livr.
- Date Valid.
- Montant BL
- Ref. Facture
- Statut
- Actions
-
-
-
- {currentAutomaticData.map((delivery: any) => (
-
-
-
-
- {delivery.supplier?.name}
-
-
-
-
-
-
- {delivery.blNumber || '-'}
-
-
-
-
- {safeFormat(delivery.scheduledDate, 'dd/MM/yy')}
-
-
-
-
- {delivery.reconciled && delivery.validatedAt ?
- safeFormat(delivery.validatedAt, 'dd/MM/yy') :
- '-'
- }
-
-
-
-
- {delivery.blAmount ?
- `${parseFloat(delivery.blAmount).toFixed(2)}€` :
- '-'
- }
-
-
-
-
- {delivery.invoiceReference || '-'}
-
-
-
- {isDevalidated(delivery) ? (
-
- Dévalidé
-
- ) : (
-
- Auto-validé
-
- )}
-
-
-
- {isDevalidated(delivery) && permissions.canEdit('reconciliation') && (
- <>
-
-
-
- handleValidateManual(delivery.id)}
- disabled={validateManualMutation.isPending}
- className="text-green-600 hover:text-green-700 p-1"
- title="Valider"
- >
-
-
- >
- )}
-
- {!isDevalidated(delivery) && permissions.canEdit('reconciliation') && (
- handleDevalidate(delivery.id)}
- disabled={devalidateMutation.isPending}
- className="text-orange-600 hover:text-orange-700 p-1"
- title="Dévalider"
- >
-
-
- )}
-
- {permissions.canDelete('reconciliation') && (
- handleDelete(delivery.id)}
- disabled={deleteMutation.isPending}
- className="text-red-600 hover:text-red-700 p-1"
- title="Supprimer"
- >
-
-
- )}
-
-
-
- ))}
-
-
-
-
- {/* Pagination du bas */}
-
-
- )}
-
- )}
-
- );
-}
\ No newline at end of file
diff --git a/client/src/pages/BLReconciliation_shadcn_broken.tsx b/client/src/pages/BLReconciliation_shadcn_broken.tsx
deleted file mode 100644
index 1ded5e2..0000000
--- a/client/src/pages/BLReconciliation_shadcn_broken.tsx
+++ /dev/null
@@ -1,751 +0,0 @@
-import { useState, useEffect } from "react";
-import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
-import { safeFormat } from "@/lib/dateUtils";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Badge } from "@/components/ui/badge";
-import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
-import { useToast } from "@/hooks/use-toast";
-import { apiRequest } from "@/lib/queryClient";
-import { useStore } from "@/components/Layout";
-import { useAuthUnified } from "@/hooks/useAuthUnified";
-import { usePermissions } from "@shared/permissions";
-import { Search, Edit, FileText, Settings, Eye, AlertTriangle, X, Check, Trash2, Ban, ChevronLeft, ChevronRight } from "lucide-react";
-import type { Supplier } from "@shared/schema";
-
-export default function BLReconciliation() {
- const { user } = useAuthUnified();
- const { selectedStoreId } = useStore();
- const { toast } = useToast();
- const queryClient = useQueryClient();
- const permissions = usePermissions(user?.role);
-
- // Vérification des permissions d'accès au module
- if (!permissions.canView('reconciliation')) {
- return (
-
-
-
-
-
-
-
-
- Accès restreint
- Seuls les directeurs et administrateurs peuvent accéder au module de rapprochement BL/Factures.
-
-
-
-
-
- );
- }
-
- const [activeTab, setActiveTab] = useState("manual");
- const [searchTerm, setSearchTerm] = useState("");
- const [currentPage, setCurrentPage] = useState(1);
- const itemsPerPage = 20;
-
- // Récupérer les fournisseurs pour la logique automatique
- const { data: suppliers = [], isLoading: suppliersLoading } = useQuery({
- queryKey: ['/api/suppliers'],
- });
-
- // Récupérer les livraisons validées avec BL
- const { data: deliveriesWithBL = [], isLoading } = useQuery({
- queryKey: ['/api/deliveries/bl', selectedStoreId],
- queryFn: async () => {
- const params = new URLSearchParams({});
- if (selectedStoreId && user?.role === 'admin') {
- params.append('storeId', selectedStoreId.toString());
- }
-
- const response = await fetch(`/api/deliveries?${params.toString()}`, {
- credentials: 'include'
- });
-
- if (!response.ok) {
- throw new Error('Failed to fetch deliveries');
- }
-
- const deliveries = await response.json();
- const filtered = Array.isArray(deliveries) ? deliveries.filter((d: any) => d.status === 'delivered') : [];
-
- return filtered.sort((a: any, b: any) => new Date(b.deliveredDate || b.updatedAt).getTime() - new Date(a.deliveredDate || a.updatedAt).getTime());
- },
- });
-
- // Séparer les livraisons selon le mode de rapprochement du fournisseur
- const manualReconciliationDeliveries = deliveriesWithBL.filter((delivery: any) => {
- const supplier = suppliers.find((s: any) => s.id === delivery.supplierId);
- return !supplier?.automaticReconciliation;
- });
-
- const automaticReconciliationDeliveries = deliveriesWithBL.filter((delivery: any) => {
- const supplier = suppliers.find((s: any) => s.id === delivery.supplierId);
- return supplier?.automaticReconciliation;
- });
-
- // Mutation pour valider un rapprochement manuel
- const validateManualMutation = useMutation({
- mutationFn: async (deliveryId: number) => {
- return await apiRequest(`/api/deliveries/${deliveryId}`, "PUT", {
- reconciled: true,
- validatedAt: new Date().toISOString()
- });
- },
- onSuccess: () => {
- toast({
- title: "Succès",
- description: "Rapprochement validé avec succès",
- });
- queryClient.invalidateQueries({ queryKey: ['/api/deliveries/bl'] });
- },
- onError: () => {
- toast({
- title: "Erreur",
- description: "Impossible de valider le rapprochement",
- variant: "destructive",
- });
- }
- });
-
- // Mutation pour dévalider un rapprochement (admins uniquement)
- const devalidateMutation = useMutation({
- mutationFn: async (deliveryId: number) => {
- return await apiRequest(`/api/deliveries/${deliveryId}`, "PUT", {
- reconciled: false,
- validatedAt: null
- });
- },
- onSuccess: () => {
- toast({
- title: "Succès",
- description: "Rapprochement dévalidé avec succès",
- });
- queryClient.invalidateQueries({ queryKey: ['/api/deliveries/bl'] });
- },
- onError: () => {
- toast({
- title: "Erreur",
- description: "Impossible de dévalider le rapprochement",
- variant: "destructive",
- });
- }
- });
-
- // Mutation pour supprimer une ligne (admins uniquement)
- const deleteMutation = useMutation({
- mutationFn: async (deliveryId: number) => {
- return await apiRequest(`/api/deliveries/${deliveryId}`, "DELETE");
- },
- onSuccess: () => {
- toast({
- title: "Succès",
- description: "Ligne supprimée avec succès",
- });
- queryClient.invalidateQueries({ queryKey: ['/api/deliveries/bl'] });
- },
- onError: () => {
- toast({
- title: "Erreur",
- description: "Impossible de supprimer la ligne",
- variant: "destructive",
- });
- }
- });
-
- // Fonctions de gestion des actions
- const handleValidateManual = (deliveryId: number) => {
- if (!permissions.canValidate('reconciliation')) {
- toast({
- title: "Accès refusé",
- description: "Vous n'avez pas les permissions pour valider les rapprochements",
- variant: "destructive",
- });
- return;
- }
- validateManualMutation.mutate(deliveryId);
- };
-
- const handleDevalidate = (deliveryId: number) => {
- if (!permissions.canEdit('reconciliation')) {
- toast({
- title: "Accès refusé",
- description: "Seuls les administrateurs peuvent dévalider les rapprochements",
- variant: "destructive",
- });
- return;
- }
- if (confirm("Êtes-vous sûr de vouloir dévalider ce rapprochement ?")) {
- devalidateMutation.mutate(deliveryId);
- }
- };
-
- const handleDelete = (deliveryId: number) => {
- if (!permissions.canDelete('reconciliation')) {
- toast({
- title: "Accès refusé",
- description: "Seuls les administrateurs peuvent supprimer les lignes",
- variant: "destructive",
- });
- return;
- }
- if (confirm("Êtes-vous sûr de vouloir supprimer cette ligne ? Cette action est irréversible.")) {
- deleteMutation.mutate(deliveryId);
- }
- };
-
- // Filtrage des livraisons par recherche
- const filterDeliveries = (deliveries: any[]) => {
- return deliveries.filter((delivery: any) => {
- const searchLower = searchTerm.toLowerCase();
- return (
- delivery.supplier?.name?.toLowerCase().includes(searchLower) ||
- delivery.blNumber?.toLowerCase().includes(searchLower) ||
- delivery.invoiceReference?.toLowerCase().includes(searchLower)
- );
- });
- };
-
- const filteredManualDeliveries = filterDeliveries(manualReconciliationDeliveries);
- const filteredAutomaticDeliveries = filterDeliveries(automaticReconciliationDeliveries);
-
- // Pagination
- const getCurrentPageData = (data: any[]) => {
- const startIndex = (currentPage - 1) * itemsPerPage;
- const endIndex = startIndex + itemsPerPage;
- return data.slice(startIndex, endIndex);
- };
-
- const getTotalPages = (data: any[]) => {
- return Math.ceil(data.length / itemsPerPage);
- };
-
- const currentManualData = getCurrentPageData(filteredManualDeliveries);
- const currentAutomaticData = getCurrentPageData(filteredAutomaticDeliveries);
-
- const totalManualPages = getTotalPages(filteredManualDeliveries);
- const totalAutomaticPages = getTotalPages(filteredAutomaticDeliveries);
-
- // Reset page when changing tabs or searching
- useEffect(() => {
- setCurrentPage(1);
- }, [activeTab, searchTerm]);
-
- // Vérifier si une ligne est dévalidée (pour la coloration)
- const isDevalidated = (delivery: any) => {
- return delivery.reconciled === false && delivery.validatedAt === null;
- };
-
- // Composant de pagination simplifiée
- const SimplePagination = ({ currentPage, totalPages, onPageChange, totalItems, itemsPerPage }: {
- currentPage: number;
- totalPages: number;
- onPageChange: (page: number) => void;
- totalItems: number;
- itemsPerPage: number;
- }) => {
- if (totalPages <= 1) return null;
-
- const startItem = (currentPage - 1) * itemsPerPage + 1;
- const endItem = Math.min(currentPage * itemsPerPage, totalItems);
-
- return (
-
-
-
- Affichage de {startItem} à {endItem} sur {totalItems} éléments
-
-
-
- onPageChange(currentPage - 1)}
- disabled={currentPage === 1}
- className="flex items-center space-x-1"
- >
-
- Précédent
-
-
-
- Page {currentPage} sur {totalPages}
-
-
- onPageChange(currentPage + 1)}
- disabled={currentPage === totalPages}
- className="flex items-center space-x-1"
- >
- Suivant
-
-
-
-
- );
- };
-
- if (isLoading || suppliersLoading) {
- return (
-
- );
- }
-
- return (
-
- {/* Header avec onglets */}
-
-
-
-
-
- Rapprochement BL/Factures
-
-
- Gestion des rapprochements manuels et automatiques
-
-
-
-
- {manualReconciliationDeliveries.length} rapprochements manuels
-
-
- {automaticReconciliationDeliveries.length} rapprochements automatiques
-
-
-
-
- {/* Onglets */}
-
-
-
-
- Rapprochement Manuel
-
- {manualReconciliationDeliveries.length}
-
-
-
-
- Rapprochement Automatique
-
- {automaticReconciliationDeliveries.length}
-
-
-
-
-
-
- {/* Filtre de recherche */}
-
-
-
- setSearchTerm(e.target.value)}
- className="pl-10 border border-gray-300 shadow-sm"
- />
-
-
-
- {/* Contenu des onglets */}
-
-
- {filteredManualDeliveries.length === 0 ? (
-
-
-
- Aucun rapprochement manuel trouvé
-
-
- Les livraisons de fournisseurs en mode manuel apparaîtront ici.
-
-
- ) : (
-
- {/* Pagination du haut */}
-
-
-
-
-
-
-
- Fournisseur
-
-
- N° BL
-
-
- Date Livr.
-
-
- Montant BL
-
-
- Ref. Facture
-
-
- Montant Fact.
-
-
- Statut
-
-
- Actions
-
-
-
-
- {currentManualData.map((delivery: any) => (
-
-
-
- {delivery.supplier?.name}
-
-
-
-
- {delivery.blNumber || (
- Non renseigné
- )}
-
-
-
-
- {safeFormat(delivery.scheduledDate, 'dd/MM/yy')}
-
-
-
-
- {delivery.blAmount ?
- `${parseFloat(delivery.blAmount).toFixed(2)}€` :
- Non renseigné
- }
-
-
-
-
- {delivery.invoiceReference || (
- Non renseigné
- )}
-
-
-
-
- {delivery.invoiceAmount ?
- `${parseFloat(delivery.invoiceAmount).toFixed(2)}€` :
- Non renseigné
- }
-
-
-
- {delivery.reconciled ? (
-
- Validé
-
- ) : isDevalidated(delivery) ? (
-
- Dévalidé
-
- ) : (
-
- En attente
-
- )}
-
-
-
- {permissions.canEdit('reconciliation') && (
-
-
-
- )}
-
- {!delivery.reconciled && permissions.canValidate('reconciliation') && (
- handleValidateManual(delivery.id)}
- disabled={validateManualMutation.isPending}
- className="text-green-600 hover:text-green-700 p-1"
- title="Valider"
- >
-
-
- )}
-
- {delivery.reconciled && permissions.canEdit('reconciliation') && user?.role === 'admin' && (
- handleDevalidate(delivery.id)}
- disabled={devalidateMutation.isPending}
- className="text-orange-600 hover:text-orange-700 p-1"
- title="Dévalider"
- >
-
-
- )}
-
- {permissions.canDelete('reconciliation') && (
- handleDelete(delivery.id)}
- disabled={deleteMutation.isPending}
- className="text-red-600 hover:text-red-700 p-1"
- title="Supprimer"
- >
-
-
- )}
-
-
-
- ))}
-
-
-
-
- {/* Pagination du bas */}
-
-
- )}
-
-
-
- {/* Message d'information */}
-
-
-
-
-
Mode rapprochement automatique
-
- Les livraisons de fournisseurs en mode automatique sont validées automatiquement lorsqu'elles ont le statut "delivered" et un numéro de BL.
- {permissions.canEdit('reconciliation') ? (
- " Vous pouvez dévalider ces rapprochements si nécessaire."
- ) : (
- " Seuls les directeurs et administrateurs peuvent modifier ces rapprochements."
- )}
-
-
-
-
-
- {filteredAutomaticDeliveries.length === 0 ? (
-
-
-
- Aucun rapprochement automatique trouvé
-
-
- Les livraisons de fournisseurs en mode automatique apparaîtront ici.
-
-
- ) : (
-
- {/* Pagination du haut */}
-
-
-
-
-
-
-
- Fournisseur
- AUTO
-
-
- N° BL
-
-
- Date Livr.
-
-
- Date Valid.
-
-
- Montant BL
-
-
- Ref. Facture
-
-
- Statut
-
-
- Actions
-
-
-
-
- {currentAutomaticData.map((delivery: any) => (
-
-
-
-
- {delivery.supplier?.name}
-
-
-
-
-
-
- {delivery.blNumber || '-'}
-
-
-
-
- {safeFormat(delivery.scheduledDate, 'dd/MM/yy')}
-
-
-
-
- {delivery.reconciled && delivery.validatedAt ?
- safeFormat(delivery.validatedAt, 'dd/MM/yy') :
- '-'
- }
-
-
-
-
- {delivery.blAmount ?
- `${parseFloat(delivery.blAmount).toFixed(2)}€` :
- '-'
- }
-
-
-
-
- {delivery.invoiceReference || '-'}
-
-
-
- {isDevalidated(delivery) ? (
-
- Dévalidé
-
- ) : (
-
- Auto-validé
-
- )}
-
-
-
- {isDevalidated(delivery) && permissions.canEdit('reconciliation') && (
- <>
-
-
-
- handleValidateManual(delivery.id)}
- disabled={validateManualMutation.isPending}
- className="text-green-600 hover:text-green-700 p-1"
- title="Valider"
- >
-
-
- >
- )}
-
- {!isDevalidated(delivery) && permissions.canEdit('reconciliation') && (
- handleDevalidate(delivery.id)}
- disabled={devalidateMutation.isPending}
- className="text-orange-600 hover:text-orange-700 p-1"
- title="Dévalider"
- >
-
-
- )}
-
- {permissions.canDelete('reconciliation') && (
- handleDelete(delivery.id)}
- disabled={deleteMutation.isPending}
- className="text-red-600 hover:text-red-700 p-1"
- title="Supprimer"
- >
-
-
- )}
-
-
-
- ))}
-
-
-
-
- {/* Pagination du bas */}
-
-
- )}
-
-
-
- );
-}
\ No newline at end of file
diff --git a/client/src/pages/Groups.tsx.backup.1752674092 b/client/src/pages/Groups.tsx.backup.1752674092
deleted file mode 100644
index ec0d0d1..0000000
--- a/client/src/pages/Groups.tsx.backup.1752674092
+++ /dev/null
@@ -1,631 +0,0 @@
-import { useState } from "react";
-import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Label } from "@/components/ui/label";
-import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
-import { useAuthUnified } from "@/hooks/useAuthUnified";
-import { useToast } from "@/hooks/use-toast";
-import { apiRequest } from "@/lib/queryClient";
-import { isUnauthorizedError } from "@/lib/authUtils";
-import {
- Plus,
- Search,
- Users,
- Edit,
- Trash2,
- Package,
- Truck,
- Palette
-} from "lucide-react";
-import type { Group, NocodbConfig } from "@shared/schema";
-
-const colorOptions = [
- { value: '#1976D2', label: 'Bleu' },
- { value: '#388E3C', label: 'Vert' },
- { value: '#FF6F00', label: 'Orange' },
- { value: '#D32F2F', label: 'Rouge' },
- { value: '#7B1FA2', label: 'Violet' },
- { value: '#F57C00', label: 'Ambre' },
- { value: '#5D4037', label: 'Marron' },
- { value: '#455A64', label: 'Bleu gris' },
- { value: '#E91E63', label: 'Rose' },
- { value: '#00796B', label: 'Sarcelle' },
-];
-
-export default function Groups() {
- const { user } = useAuthUnified();
- const { toast } = useToast();
- const queryClient = useQueryClient();
-
- const [searchTerm, setSearchTerm] = useState("");
- const [showCreateModal, setShowCreateModal] = useState(false);
- const [showEditModal, setShowEditModal] = useState(false);
- const [selectedGroup, setSelectedGroup] = useState(null);
- const [formData, setFormData] = useState({
- name: "",
- color: "#1976D2",
- nocodbConfigId: "",
- nocodbTableId: "",
- nocodbTableName: "",
- invoiceColumnName: "Ref Facture",
- });
-
- const { data: groups = [], isLoading } = useQuery({
- queryKey: ['/api/groups'],
- });
-
- const { data: rawNocodbConfigs = [] } = useQuery({
- queryKey: ['/api/nocodb-config'],
- });
-
- // Protection contre les erreurs TypeError
- const nocodbConfigs = Array.isArray(rawNocodbConfigs) ? rawNocodbConfigs : [];
-
- console.log('🔍 Groups NocoDB Debug:', {
- rawNocodbConfigs,
- nocodbConfigs,
- isArray: Array.isArray(rawNocodbConfigs)
- });
-
- const { data: orders = [] } = useQuery({
- queryKey: ['/api/orders'],
- });
-
- const { data: deliveries = [] } = useQuery({
- queryKey: ['/api/deliveries'],
- });
-
- const createMutation = useMutation({
- mutationFn: async (data: any) => {
- await apiRequest("/api/groups", {
- method: "POST",
- body: data,
- });
- },
- onSuccess: () => {
- toast({
- title: "Succès",
- description: "Groupe créé avec succès",
- });
- queryClient.invalidateQueries({ queryKey: ['/api/groups'] });
- setShowCreateModal(false);
- setFormData({
- name: "",
- color: "#1976D2",
- nocodbConfigId: "",
- nocodbTableId: "",
- nocodbTableName: "",
- invoiceColumnName: "Ref Facture",
- });
- },
- onError: (error) => {
- if (isUnauthorizedError(error)) {
- toast({
- title: "Non autorisé",
- description: "Vous êtes déconnecté. Reconnexion...",
- variant: "destructive",
- });
- setTimeout(() => {
- window.location.href = "/api/login";
- }, 500);
- return;
- }
- toast({
- title: "Erreur",
- description: "Impossible de créer le groupe",
- variant: "destructive",
- });
- },
- });
-
- const updateMutation = useMutation({
- mutationFn: async (data: any) => {
- await apiRequest(`/api/groups/${selectedGroup?.id}`, {
- method: "PUT",
- body: data,
- });
- },
- onSuccess: () => {
- toast({
- title: "Succès",
- description: "Groupe modifié avec succès",
- });
- queryClient.invalidateQueries({ queryKey: ['/api/groups'] });
- setShowEditModal(false);
- setSelectedGroup(null);
- setFormData({
- name: "",
- color: "#1976D2",
- nocodbConfigId: "",
- nocodbTableId: "",
- nocodbTableName: "",
- invoiceColumnName: "Ref Facture",
- });
- },
- onError: (error) => {
- if (isUnauthorizedError(error)) {
- toast({
- title: "Non autorisé",
- description: "Vous êtes déconnecté. Reconnexion...",
- variant: "destructive",
- });
- setTimeout(() => {
- window.location.href = "/api/login";
- }, 500);
- return;
- }
- toast({
- title: "Erreur",
- description: "Impossible de modifier le groupe",
- variant: "destructive",
- });
- },
- });
-
- const deleteMutation = useMutation({
- mutationFn: async (id: number) => {
- await apiRequest("DELETE", `/api/groups/${id}`);
- },
- onSuccess: () => {
- toast({
- title: "Succès",
- description: "Groupe supprimé avec succès",
- });
- queryClient.invalidateQueries({ queryKey: ['/api/groups'] });
- },
- onError: (error) => {
- if (isUnauthorizedError(error)) {
- toast({
- title: "Non autorisé",
- description: "Vous êtes déconnecté. Reconnexion...",
- variant: "destructive",
- });
- setTimeout(() => {
- window.location.href = "/api/login";
- }, 500);
- return;
- }
- toast({
- title: "Erreur",
- description: "Impossible de supprimer le groupe",
- variant: "destructive",
- });
- },
- });
-
- const filteredGroups = Array.isArray(groups) ? groups.filter(group =>
- group.name.toLowerCase().includes(searchTerm.toLowerCase())
- ) : [];
-
- console.log('🏪 Groups Debug:', {
- groups: Array.isArray(groups) ? groups.length : 'NOT_ARRAY',
- orders: Array.isArray(orders) ? orders.length : 'NOT_ARRAY',
- deliveries: Array.isArray(deliveries) ? deliveries.length : 'NOT_ARRAY',
- groupsData: groups?.slice(0, 2),
- ordersData: orders?.slice(0, 2),
- deliveriesData: deliveries?.slice(0, 2)
- });
-
- const getGroupStats = (groupId: number) => {
- const groupOrders = Array.isArray(orders) ? orders.filter(order => {
- const match = order.groupId === groupId;
- if (match) console.log(`🎯 Order ${order.id} matches group ${groupId}`, order);
- return match;
- }) : [];
-
- const groupDeliveries = Array.isArray(deliveries) ? deliveries.filter(delivery => {
- const match = delivery.groupId === groupId;
- if (match) console.log(`🎯 Delivery ${delivery.id} matches group ${groupId}`, delivery);
- return match;
- }) : [];
-
- console.log(`🏪 Group ${groupId} stats:`, {
- groupOrders: groupOrders.length,
- groupDeliveries: groupDeliveries.length,
- delivered: groupDeliveries.filter(d => d.status === 'delivered').length,
- ordersSample: groupOrders.slice(0, 2),
- deliveriesSample: groupDeliveries.slice(0, 2),
- allOrdersCount: orders?.length,
- allDeliveriesCount: deliveries?.length
- });
-
- return {
- orders: groupOrders.length,
- deliveries: groupDeliveries.length,
- delivered: groupDeliveries.filter(d => d.status === 'delivered').length,
- };
- };
-
- const handleCreate = () => {
- setFormData({
- name: "",
- color: "#1976D2",
- nocodbConfigId: "",
- nocodbTableId: "",
- nocodbTableName: "",
- invoiceColumnName: "Ref Facture",
- });
- setShowCreateModal(true);
- };
-
- const handleEdit = (group: Group) => {
- setSelectedGroup(group);
- setFormData({
- name: group.name,
- color: group.color,
- nocodbConfigId: group.nocodbConfigId?.toString() || "",
- nocodbTableId: group.nocodbTableId || "",
- nocodbTableName: group.nocodbTableName || "",
- invoiceColumnName: group.invoiceColumnName || "Ref Facture",
- });
- setShowEditModal(true);
- };
-
- const handleDelete = (group: Group) => {
- const stats = getGroupStats(group.id);
-
- if (stats.orders > 0 || stats.deliveries > 0) {
- toast({
- title: "Suppression impossible",
- description: "Ce groupe a des commandes ou livraisons associées",
- variant: "destructive",
- });
- return;
- }
-
- if (window.confirm(`Êtes-vous sûr de vouloir supprimer le groupe "${group.name}" ?`)) {
- deleteMutation.mutate(group.id);
- }
- };
-
- const handleSubmit = (e: React.FormEvent) => {
- e.preventDefault();
-
- if (!formData.name.trim()) {
- toast({
- title: "Erreur",
- description: "Le nom du groupe est requis",
- variant: "destructive",
- });
- return;
- }
-
- // Prepare data with proper type conversion
- const submitData = {
- ...formData,
- nocodbConfigId: formData.nocodbConfigId ? parseInt(formData.nocodbConfigId) : null,
- };
-
- if (selectedGroup) {
- updateMutation.mutate(submitData);
- } else {
- createMutation.mutate(submitData);
- }
- };
-
- const handleChange = (field: string, value: string) => {
- setFormData(prev => ({ ...prev, [field]: value }));
- };
-
- const canManage = user?.role === 'admin' || user?.role === 'manager';
-
- return (
-
- {/* Header */}
-
-
-
-
-
- Gestion des Groupes/Magasins
-
-
- {filteredGroups.length} groupe{filteredGroups.length !== 1 ? 's' : ''}
-
-
- {canManage && (
-
-
- Nouveau Groupe
-
- )}
-
-
-
- {/* Search */}
-
-
-
- setSearchTerm(e.target.value)}
- className="pl-10 border border-gray-300 shadow-sm"
- />
-
-
-
- {/* Groups List */}
-
- {isLoading ? (
-
- ) : filteredGroups.length === 0 ? (
-
-
-
- {searchTerm ? "Aucun groupe trouvé" : "Aucun groupe"}
-
-
- {searchTerm
- ? "Aucun groupe ne correspond à votre recherche."
- : "Vous n'avez pas encore de groupes. Créez votre premier groupe pour commencer."}
-
- {!searchTerm && canManage && (
-
-
- Créer un groupe
-
- )}
-
- ) : (
-
-
- {filteredGroups.map((group) => {
- const stats = getGroupStats(group.id);
- return (
-
-
-
-
-
-
-
-
{group.name}
-
#{group.id}
-
-
- {canManage && (
-
- handleEdit(group)}
- >
-
-
- handleDelete(group)}
- className="text-red-600 hover:text-red-700"
- >
-
-
-
- )}
-
-
-
-
-
-
-
-
-
-
- {stats.deliveries}
-
-
Livraisons
-
-
- {stats.deliveries > 0 && (
-
-
- {stats.delivered} livrées ({Math.round((stats.delivered / stats.deliveries) * 100)}%)
-
-
- )}
-
-
- );
- })}
-
-
- )}
-
-
- {/* Create/Edit Modal */}
-
{
- setShowCreateModal(false);
- setShowEditModal(false);
- setSelectedGroup(null);
- setFormData({
- name: "",
- color: "#1976D2",
- nocodbConfigId: "",
- nocodbTableId: "",
- nocodbTableName: "",
- invoiceColumnName: "Ref Facture",
- });
- }}>
-
-
-
- {selectedGroup ? 'Modifier' : 'Nouveau'} Groupe
-
-
- {selectedGroup ? 'Modifier les informations du groupe' : 'Créer un nouveau groupe/magasin'}
-
-
-
-
-
-
-
- );
-}
diff --git a/client/src/pages/NocoDBConfig.tsx.backup.1752674092 b/client/src/pages/NocoDBConfig.tsx.backup.1752674092
deleted file mode 100644
index 9582034..0000000
--- a/client/src/pages/NocoDBConfig.tsx.backup.1752674092
+++ /dev/null
@@ -1,661 +0,0 @@
-import { useState } from "react";
-import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
-import { apiRequest } from "@/lib/queryClient";
-import { useAuthUnified } from "@/hooks/useAuthUnified";
-import { useToast } from "@/hooks/use-toast";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
-import { Badge } from "@/components/ui/badge";
-import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
-import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
-import { Textarea } from "@/components/ui/textarea";
-import { Switch } from "@/components/ui/switch";
-import { useForm } from "react-hook-form";
-import { zodResolver } from "@hookform/resolvers/zod";
-import { z } from "zod";
-import {
- Database,
- Plus,
- Edit,
- Trash2,
- Settings,
- Eye,
- EyeOff,
- CheckCircle,
- XCircle,
- AlertTriangle,
- Link,
-} from "lucide-react";
-import type { NocodbConfig } from "@shared/schema";
-
-// Form schemas
-const nocodbConfigFormSchema = z.object({
- name: z.string().min(1, "Le nom est obligatoire"),
- baseUrl: z.string().url("L'URL doit être valide").min(1, "L'URL de base est obligatoire"),
- apiToken: z.string().min(1, "Le token API est obligatoire"),
- projectId: z.string().min(1, "L'ID du projet est obligatoire"),
- description: z.string().optional(),
- isActive: z.boolean().default(true),
-});
-
-type NocodbConfigForm = z.infer;
-
-export default function NocoDBConfig() {
- const { user } = useAuthUnified();
- const { toast } = useToast();
- const queryClient = useQueryClient();
-
- const [showCreateModal, setShowCreateModal] = useState(false);
- const [showEditModal, setShowEditModal] = useState(false);
- const [showDeleteModal, setShowDeleteModal] = useState(false);
- const [selectedConfig, setSelectedConfig] = useState(null);
- const [showTokens, setShowTokens] = useState<{ [key: number]: boolean }>({});
-
- // Queries avec protection complète
- const { data: rawConfigs, isLoading, error } = useQuery({
- queryKey: ['/api/nocodb-config'],
- enabled: user?.role === 'admin',
- });
-
- // Protection triple couche pour éviter les erreurs TypeError
- const configs = rawConfigs || [];
- const safeConfigs = Array.isArray(configs) ? configs : [];
-
- // Log pour debug production
- console.log('🔍 NocoDBConfig Debug:', {
- rawConfigs,
- configs,
- isArray: Array.isArray(configs),
- safeConfigs,
- length: safeConfigs.length,
- error,
- userRole: user?.role
- });
-
- // Mutations
- const createConfigMutation = useMutation({
- mutationFn: (data: NocodbConfigForm) =>
- apiRequest('/api/nocodb-config', 'POST', data),
- onSuccess: () => {
- queryClient.invalidateQueries({ queryKey: ['/api/nocodb-config'] });
- setShowCreateModal(false);
- toast({
- title: "Configuration créée",
- description: "La configuration NocoDB a été créée avec succès.",
- });
- },
- onError: (error: any) => {
- toast({
- title: "Erreur",
- description: error.message || "Erreur lors de la création de la configuration.",
- variant: "destructive",
- });
- },
- });
-
- const updateConfigMutation = useMutation({
- mutationFn: ({ id, data }: { id: number; data: Partial }) =>
- apiRequest(`/api/nocodb-config/${id}`, 'PUT', data),
- onSuccess: () => {
- queryClient.invalidateQueries({ queryKey: ['/api/nocodb-config'] });
- setShowEditModal(false);
- setSelectedConfig(null);
- toast({
- title: "Configuration mise à jour",
- description: "La configuration NocoDB a été mise à jour avec succès.",
- });
- },
- onError: (error: any) => {
- toast({
- title: "Erreur",
- description: error.message || "Erreur lors de la mise à jour de la configuration.",
- variant: "destructive",
- });
- },
- });
-
- const deleteConfigMutation = useMutation({
- mutationFn: (id: number) =>
- apiRequest(`/api/nocodb-config/${id}`, 'DELETE'),
- onSuccess: () => {
- queryClient.invalidateQueries({ queryKey: ['/api/nocodb-config'] });
- setShowDeleteModal(false);
- setSelectedConfig(null);
- toast({
- title: "Configuration supprimée",
- description: "La configuration NocoDB a été supprimée avec succès.",
- });
- },
- onError: (error: any) => {
- toast({
- title: "Erreur",
- description: error.message || "Erreur lors de la suppression de la configuration.",
- variant: "destructive",
- });
- },
- });
-
- // Forms
- const createForm = useForm({
- resolver: zodResolver(nocodbConfigFormSchema),
- defaultValues: {
- name: "",
- baseUrl: "",
- apiToken: "",
- projectId: "",
- description: "",
- isActive: true,
- },
- });
-
- const editForm = useForm({
- resolver: zodResolver(nocodbConfigFormSchema),
- });
-
- // Handle create config
- const handleCreateConfig = (data: NocodbConfigForm) => {
- createConfigMutation.mutate(data);
- };
-
- // Handle edit config
- const handleEditConfig = (data: NocodbConfigForm) => {
- if (!selectedConfig) return;
- updateConfigMutation.mutate({ id: selectedConfig.id, data });
- };
-
- // Handle delete config
- const handleDeleteConfig = () => {
- if (!selectedConfig) return;
- deleteConfigMutation.mutate(selectedConfig.id);
- };
-
- // Open edit modal
- const openEditModal = (config: NocodbConfig) => {
- setSelectedConfig(config);
- editForm.reset({
- name: config.name,
- baseUrl: config.baseUrl,
- apiToken: config.apiToken,
- projectId: config.projectId,
- description: config.description || "",
- isActive: config.isActive,
- });
- setShowEditModal(true);
- };
-
- // Open delete modal
- const openDeleteModal = (config: NocodbConfig) => {
- setSelectedConfig(config);
- setShowDeleteModal(true);
- };
-
- // Toggle token visibility
- const toggleTokenVisibility = (configId: number) => {
- setShowTokens(prev => ({
- ...prev,
- [configId]: !prev[configId]
- }));
- };
-
- // Format token for display
- const formatToken = (token: string, isVisible: boolean) => {
- if (isVisible) return token;
- return '•'.repeat(Math.min(token.length, 20));
- };
-
- if (user?.role !== 'admin') {
- return (
-
-
-
-
- Accès restreint
-
- Seuls les administrateurs peuvent gérer les configurations NocoDB.
-
-
-
-
- );
- }
-
- if (isLoading) {
- return (
-
- );
- }
-
- return (
-
- {/* Header */}
-
-
-
-
- Configuration NocoDB
-
-
- Gérez les connexions aux bases de données NocoDB externes pour récupérer des informations.
-
-
-
setShowCreateModal(true)} className="gap-2">
-
- Nouvelle Configuration
-
-
-
- {/* Configurations List */}
-
- {safeConfigs.length === 0 ? (
-
-
-
- Aucune configuration
-
- Commencez par créer votre première configuration NocoDB.
-
- setShowCreateModal(true)} className="gap-2">
-
- Créer une configuration
-
-
-
- ) : (
- safeConfigs.map((config: NocodbConfig) => (
-
-
-
-
-
-
-
-
-
- {config.name}
-
- {config.isActive ? (
- <> Actif>
- ) : (
- <> Inactif>
- )}
-
-
- {config.description && (
-
- {config.description}
-
- )}
-
-
-
- openEditModal(config)}
- >
-
-
- openDeleteModal(config)}
- >
-
-
-
-
-
-
-
-
-
URL de base
-
-
-
- {config.baseUrl}
-
-
-
-
-
ID du projet
-
-
- {config.projectId}
-
-
-
-
-
Token API
-
-
- {formatToken(config.apiToken, showTokens[config.id])}
-
- toggleTokenVisibility(config.id)}
- >
- {showTokens[config.id] ? (
-
- ) : (
-
- )}
-
-
-
-
-
-
- ))
- )}
-
-
- {/* Create Modal */}
-
-
-
- Nouvelle Configuration NocoDB
-
-
- Créer une nouvelle configuration pour se connecter à une base de données NocoDB externe
-
-
-
-
-
-
- {/* Edit Modal */}
-
-
-
- Modifier la Configuration
-
-
- Modifier les paramètres de la configuration NocoDB sélectionnée
-
-
-
- (
-
- Nom de la configuration
-
-
-
-
-
- )}
- />
-
- (
-
- URL de base
-
-
-
-
-
- )}
- />
-
- (
-
- Personal API Token
-
-
-
-
-
- )}
- />
-
- (
-
- ID du projet
-
-
-
-
-
- )}
- />
-
- (
-
- Description (optionnel)
-
-
-
-
-
- )}
- />
-
- (
-
-
-
Configuration active
-
- Activer cette configuration pour l'utiliser
-
-
-
-
-
-
- )}
- />
-
-
- setShowEditModal(false)}
- disabled={updateConfigMutation.isPending}
- >
- Annuler
-
-
- {updateConfigMutation.isPending ? "Mise à jour..." : "Mettre à jour"}
-
-
-
-
-
-
-
- {/* Delete Modal */}
-
-
-
- Confirmer la suppression
-
-
- Confirmer la suppression définitive de la configuration NocoDB
-
-
-
- Êtes-vous sûr de vouloir supprimer la configuration "{selectedConfig?.name}" ?
- Cette action est irréversible.
-
-
-
- setShowDeleteModal(false)}
- disabled={deleteConfigMutation.isPending}
- >
- Annuler
-
-
- {deleteConfigMutation.isPending ? "Suppression..." : "Supprimer"}
-
-
-
-
-
- );
-}
\ No newline at end of file
diff --git a/client/src/pages/Suppliers_backup.tsx b/client/src/pages/Suppliers_backup.tsx
deleted file mode 100644
index 99661b8..0000000
--- a/client/src/pages/Suppliers_backup.tsx
+++ /dev/null
@@ -1,627 +0,0 @@
-import { useState } from "react";
-import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Label } from "@/components/ui/label";
-import { Checkbox } from "@/components/ui/checkbox";
-import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
-import { useAuthUnified } from "@/hooks/useAuthUnified";
-import { useToast } from "@/hooks/use-toast";
-import { apiRequest } from "@/lib/queryClient";
-import { isUnauthorizedError } from "@/lib/authUtils";
-import {
- Plus,
- Search,
- Building,
- Phone,
- Mail,
- Edit,
- Trash2,
- Package,
- Truck,
- CheckCircle,
- XCircle,
- Clock
-} from "lucide-react";
-import type { Supplier } from "@shared/schema";
-
-export default function Suppliers() {
- const { user } = useAuthUnified();
- const { toast } = useToast();
- const queryClient = useQueryClient();
-
- const [searchTerm, setSearchTerm] = useState("");
- const [showCreateModal, setShowCreateModal] = useState(false);
- const [showEditModal, setShowEditModal] = useState(false);
- const [selectedSupplier, setSelectedSupplier] = useState(null);
- const [formData, setFormData] = useState({
- name: "",
- contact: "",
- phone: "",
- hasDlc: false,
- automaticReconciliation: false,
- });
-
- const { data: suppliers = [], isLoading } = useQuery({
- queryKey: ['/api/suppliers'],
- });
-
- const { data: orders = [] } = useQuery({
- queryKey: ['/api/orders'],
- });
-
- const { data: deliveries = [] } = useQuery({
- queryKey: ['/api/deliveries'],
- });
-
- const createMutation = useMutation({
- mutationFn: async (data: any) => {
- console.log('🚚 Frontend: Creating supplier with data:', data);
- const result = await apiRequest("/api/suppliers", "POST", data);
- console.log('🚚 Frontend: Supplier creation result:', result);
- return result;
- },
- onSuccess: () => {
- toast({
- title: "Succès",
- description: "Fournisseur créé avec succès",
- });
- queryClient.invalidateQueries({ queryKey: ['/api/suppliers'] });
- setShowCreateModal(false);
- setFormData({
- name: "",
- contact: "",
- phone: "",
- email: "",
- address: "",
- hasDlc: false,
- automaticReconciliation: false
- });
- },
- onError: (error) => {
- if (isUnauthorizedError(error)) {
- toast({
- title: "Non autorisé",
- description: "Vous êtes déconnecté. Reconnexion...",
- variant: "destructive",
- });
- setTimeout(() => {
- window.location.href = "/api/login";
- }, 500);
- return;
- }
- toast({
- title: "Erreur",
- description: "Impossible de créer le fournisseur",
- variant: "destructive",
- });
- },
- });
-
- const updateMutation = useMutation({
- mutationFn: async (data: any) => {
- console.log('🔧 Frontend: Updating supplier with data:', data);
- const result = await apiRequest(`/api/suppliers/${selectedSupplier?.id}`, "PUT", data);
- console.log('🔧 Frontend: Supplier update result:', result);
- return result;
- },
- onMutate: async (newData) => {
- // Mise à jour optimiste - mettre à jour l'interface immédiatement
- console.log('🚀 Frontend: Optimistic update starting...');
- await queryClient.cancelQueries({ queryKey: ['/api/suppliers'] });
-
- const previousSuppliers = queryClient.getQueryData(['/api/suppliers']);
-
- if (previousSuppliers && selectedSupplier) {
- const updatedSuppliers = (previousSuppliers as any[]).map(supplier =>
- supplier.id === selectedSupplier.id
- ? { ...supplier, ...newData, updatedAt: new Date().toISOString() }
- : supplier
- );
- queryClient.setQueryData(['/api/suppliers'], updatedSuppliers);
- console.log('✅ Frontend: Optimistic update applied');
- }
-
- return { previousSuppliers };
- },
- onSuccess: async (result) => {
- console.log('✅ Frontend: Update mutation successful, result:', result);
- console.log('🔄 Frontend: Starting cache invalidation...');
-
- // Forcer une actualisation complète du cache
- await queryClient.invalidateQueries({ queryKey: ['/api/suppliers'] });
- await queryClient.refetchQueries({
- queryKey: ['/api/suppliers'],
- type: 'active'
- });
-
- // Attendre un petit délai pour s'assurer que les données sont fraîches
- await new Promise(resolve => setTimeout(resolve, 100));
-
- console.log('✅ Frontend: Cache invalidation complete');
-
- toast({
- title: "Succès",
- description: "Fournisseur modifié avec succès",
- });
-
- setShowEditModal(false);
- setSelectedSupplier(null);
- setFormData({
- name: "",
- contact: "",
- phone: "",
- email: "",
- address: "",
- hasDlc: false,
- automaticReconciliation: false
- });
- },
- onError: (error, variables, context) => {
- // Rollback optimiste en cas d'erreur
- if (context?.previousSuppliers) {
- console.log('❌ Frontend: Error occurred, rolling back optimistic update');
- queryClient.setQueryData(['/api/suppliers'], context.previousSuppliers);
- }
-
- if (isUnauthorizedError(error)) {
- toast({
- title: "Non autorisé",
- description: "Vous êtes déconnecté. Reconnexion...",
- variant: "destructive",
- });
- setTimeout(() => {
- window.location.href = "/api/login";
- }, 500);
- return;
- }
- toast({
- title: "Erreur",
- description: "Impossible de modifier le fournisseur",
- variant: "destructive",
- });
- },
- });
-
- const deleteMutation = useMutation({
- mutationFn: async (id: number) => {
- await apiRequest(`/api/suppliers/${id}`, "DELETE");
- },
- onSuccess: () => {
- toast({
- title: "Succès",
- description: "Fournisseur supprimé avec succès",
- });
- queryClient.invalidateQueries({ queryKey: ['/api/suppliers'] });
- },
- onError: (error) => {
- if (isUnauthorizedError(error)) {
- toast({
- title: "Non autorisé",
- description: "Vous êtes déconnecté. Reconnexion...",
- variant: "destructive",
- });
- setTimeout(() => {
- window.location.href = "/api/login";
- }, 500);
- return;
- }
- toast({
- title: "Erreur",
- description: "Impossible de supprimer le fournisseur",
- variant: "destructive",
- });
- },
- });
-
- const filteredSuppliers = Array.isArray(suppliers) ? suppliers.filter(supplier =>
- supplier.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
- supplier.contact?.toLowerCase().includes(searchTerm.toLowerCase()) ||
- supplier.phone?.toLowerCase().includes(searchTerm.toLowerCase())
- ) : [];
-
- const getSupplierStats = (supplierId: number) => {
- const supplierOrders = Array.isArray(orders) ? orders.filter(order => order.supplierId === supplierId) : [];
- const supplierDeliveries = Array.isArray(deliveries) ? deliveries.filter(delivery => delivery.supplierId === supplierId) : [];
-
- return {
- orders: supplierOrders.length,
- deliveries: supplierDeliveries.length,
- delivered: supplierDeliveries.filter(d => d.status === 'delivered').length,
- };
- };
-
- const handleCreate = () => {
- setFormData({
- name: "",
- contact: "",
- phone: "",
- email: "",
- address: "",
- hasDlc: false,
- automaticReconciliation: false
- });
- setShowCreateModal(true);
- };
-
- const handleEdit = (supplier: Supplier) => {
- setSelectedSupplier(supplier);
- setFormData({
- name: supplier.name,
- contact: supplier.contact || "",
- phone: supplier.phone || "",
- email: supplier.email || "",
- address: supplier.address || "",
- hasDlc: supplier.hasDlc || false,
- automaticReconciliation: supplier.automaticReconciliation || false,
- });
- setShowEditModal(true);
- };
-
- const handleDelete = (supplier: Supplier) => {
- const stats = getSupplierStats(supplier.id);
-
- if (stats.orders > 0 || stats.deliveries > 0) {
- toast({
- title: "Suppression impossible",
- description: "Ce fournisseur a des commandes ou livraisons associées",
- variant: "destructive",
- });
- return;
- }
-
- if (window.confirm(`Êtes-vous sûr de vouloir supprimer le fournisseur "${supplier.name}" ?`)) {
- deleteMutation.mutate(supplier.id);
- }
- };
-
- const handleSubmit = (e: React.FormEvent) => {
- e.preventDefault();
-
- if (!formData.name.trim()) {
- toast({
- title: "Erreur",
- description: "Le nom du fournisseur est requis",
- variant: "destructive",
- });
- return;
- }
-
- if (selectedSupplier) {
- updateMutation.mutate(formData);
- } else {
- createMutation.mutate(formData);
- }
- };
-
- const handleChange = (field: string, value: string | boolean) => {
- setFormData(prev => ({ ...prev, [field]: value }));
- };
-
- const canManage = user?.role === 'admin' || user?.role === 'manager';
-
- if (!canManage) {
- return (
-
-
-
-
- Accès restreint
-
-
- Vous n'avez pas les permissions nécessaires pour accéder à cette page.
-
-
-
- );
- }
-
- return (
-
- {/* Header */}
-
-
-
-
-
- Gestion des Fournisseurs
-
-
- {filteredSuppliers.length} fournisseur{filteredSuppliers.length !== 1 ? 's' : ''}
-
-
-
-
- Nouveau Fournisseur
-
-
-
-
- {/* Search */}
-
-
-
- setSearchTerm(e.target.value)}
- className="pl-10 border border-gray-300 shadow-sm"
- />
-
-
-
- {/* Suppliers List */}
-
- {isLoading ? (
-
- ) : filteredSuppliers.length === 0 ? (
-
-
-
- {searchTerm ? "Aucun fournisseur trouvé" : "Aucun fournisseur"}
-
-
- {searchTerm
- ? "Aucun fournisseur ne correspond à votre recherche."
- : "Vous n'avez pas encore de fournisseurs. Créez votre premier fournisseur pour commencer."}
-
- {!searchTerm && (
-
-
- Créer un fournisseur
-
- )}
-
- ) : (
-
-
- {filteredSuppliers.map((supplier) => {
- const stats = getSupplierStats(supplier.id);
- return (
-
-
-
-
-
-
-
-
{supplier.name}
-
#{supplier.id}
-
-
-
- handleEdit(supplier)}
- >
-
-
- handleDelete(supplier)}
- className="text-red-600 hover:text-red-700"
- >
-
-
-
-
-
-
- {supplier.contact && (
-
-
- {supplier.contact}
-
- )}
- {supplier.phone && (
-
- )}
-
-
- {supplier.hasDlc && (
-
-
- DLC
-
- )}
- {supplier.automaticReconciliation && (
-
-
- Auto-rapprochement
-
- )}
-
-
-
- {!supplier.hasDlc && !supplier.automaticReconciliation && (
-
- Aucune option activée
-
- )}
-
- {/* Statistics section follows */}
-
-
-
-
-
-
-
-
- {stats.deliveries}
-
-
Livraisons
-
-
- {stats.deliveries > 0 && (
-
-
- {stats.delivered} livrées ({Math.round((stats.delivered / stats.deliveries) * 100)}%)
-
-
- )}
-
-
- );
- })}
-
-
- )}
-
-
- {/* Create/Edit Modal */}
-
{
- setShowCreateModal(false);
- setShowEditModal(false);
- setSelectedSupplier(null);
- setFormData({
- name: "",
- contact: "",
- phone: "",
- email: "",
- address: "",
- hasDlc: false,
- automaticReconciliation: false
- });
- }}>
-
-
-
- {selectedSupplier ? 'Modifier' : 'Nouveau'} Fournisseur
-
-
- {selectedSupplier ? 'Modifier les informations du fournisseur' : 'Créer un nouveau fournisseur'}
-
-
-
-
-
- Nom du fournisseur *
- handleChange('name', e.target.value)}
- placeholder="Nom du fournisseur"
- required
- />
-
-
-
- Contact
- handleChange('contact', e.target.value)}
- placeholder="Nom du contact"
- />
-
-
-
- Téléphone
- handleChange('phone', e.target.value)}
- placeholder="Numéro de téléphone"
- />
-
-
-
- Email
- handleChange('email', e.target.value)}
- placeholder="Adresse email"
- />
-
-
-
- Adresse
- handleChange('address', e.target.value)}
- placeholder="Adresse complète"
- />
-
-
-
- handleChange('hasDlc', checked === true)}
- />
-
- Gestion DLC
-
-
-
-
- handleChange('automaticReconciliation', checked === true)}
- />
-
- Rapprochement automatique BL/Factures
-
-
-
-
- {
- setShowCreateModal(false);
- setShowEditModal(false);
- setSelectedSupplier(null);
- setFormData({
- name: "",
- contact: "",
- phone: "",
- email: "",
- address: "",
- hasDlc: false,
- automaticReconciliation: false
- });
- }}
- >
- Annuler
-
-
- {createMutation.isPending || updateMutation.isPending
- ? "Enregistrement..."
- : (selectedSupplier ? "Modifier" : "Créer")}
-
-
-
-
-
-
- );
-}
diff --git a/cookies.txt b/cookies.txt
deleted file mode 100644
index a4f8ada..0000000
--- a/cookies.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-# Netscape HTTP Cookie File
-# https://curl.se/docs/http-cookies.html
-# This file was generated by libcurl! Edit at your own risk.
-
-#HttpOnly_localhost FALSE / FALSE 1755097412 connect.sid s%3Aw8eQ0pdwkq4GIUACMHnmK2NcedSu3q7J.XIJfaGOE2qSO%2Bod9uY36fyz%2B12rZtEPBA9wsXxXv1%2FQ
diff --git a/cookies_employee.txt b/cookies_employee.txt
deleted file mode 100644
index c31d989..0000000
--- a/cookies_employee.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-# Netscape HTTP Cookie File
-# https://curl.se/docs/http-cookies.html
-# This file was generated by libcurl! Edit at your own risk.
-
diff --git a/debug-calendar-production.js b/debug-calendar-production.js
deleted file mode 100644
index 5441067..0000000
--- a/debug-calendar-production.js
+++ /dev/null
@@ -1,143 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Script de diagnostic pour le problème de calendrier en production
- * avec le rôle directeur
- */
-
-const fetch = require('node-fetch');
-
-// Configuration de votre serveur de production
-const PRODUCTION_URL = process.env.PRODUCTION_URL || 'https://votre-serveur-production.com';
-const USERNAME = process.env.PROD_USERNAME || 'votre-directeur-username';
-const PASSWORD = process.env.PROD_PASSWORD || 'votre-directeur-password';
-
-async function testCalendarAPIs() {
- console.log('🔍 Test de diagnostic du calendrier en production pour directeur');
- console.log('URL de production:', PRODUCTION_URL);
-
- try {
- // 1. Test de connexion au serveur
- console.log('\n1. Test de connexion au serveur...');
- const healthResponse = await fetch(`${PRODUCTION_URL}/api/health`, {
- timeout: 10000
- });
- console.log('✅ Serveur accessible:', healthResponse.status);
-
- // 2. Test d'authentification
- console.log('\n2. Test d\'authentification...');
- const loginResponse = await fetch(`${PRODUCTION_URL}/api/login`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- username: USERNAME,
- password: PASSWORD
- })
- });
-
- if (!loginResponse.ok) {
- console.error('❌ Échec de l\'authentification:', loginResponse.status);
- return;
- }
-
- const cookies = loginResponse.headers.get('set-cookie');
- console.log('✅ Authentification réussie');
-
- // 3. Test de récupération du profil utilisateur
- console.log('\n3. Test du profil utilisateur...');
- const userResponse = await fetch(`${PRODUCTION_URL}/api/user`, {
- headers: {
- 'Cookie': cookies
- }
- });
-
- if (!userResponse.ok) {
- console.error('❌ Impossible de récupérer le profil:', userResponse.status);
- return;
- }
-
- const user = await userResponse.json();
- console.log('✅ Profil utilisateur:', {
- role: user.role,
- id: user.id,
- groupsCount: user.userGroups?.length || 0
- });
-
- // 4. Test API orders (utilisée par le calendrier)
- console.log('\n4. Test API /api/orders...');
- const ordersResponse = await fetch(`${PRODUCTION_URL}/api/orders?startDate=2025-08-01&endDate=2025-08-31`, {
- headers: {
- 'Cookie': cookies
- },
- timeout: 15000
- });
-
- console.log('Status orders:', ordersResponse.status);
- if (ordersResponse.ok) {
- const orders = await ordersResponse.json();
- console.log('✅ API orders fonctionne, nombre de commandes:', orders.length);
- } else {
- const errorText = await ordersResponse.text();
- console.error('❌ Erreur API orders:', errorText);
- }
-
- // 5. Test API deliveries (utilisée par le calendrier)
- console.log('\n5. Test API /api/deliveries...');
- const deliveriesResponse = await fetch(`${PRODUCTION_URL}/api/deliveries?startDate=2025-08-01&endDate=2025-08-31`, {
- headers: {
- 'Cookie': cookies
- },
- timeout: 15000
- });
-
- console.log('Status deliveries:', deliveriesResponse.status);
- if (deliveriesResponse.ok) {
- const deliveries = await deliveriesResponse.json();
- console.log('✅ API deliveries fonctionne, nombre de livraisons:', deliveries.length);
- } else {
- const errorText = await deliveriesResponse.text();
- console.error('❌ Erreur API deliveries:', errorText);
- }
-
- // 6. Test de connectivité réseau détaillé
- console.log('\n6. Test de connectivité réseau...');
- const start = Date.now();
- const timeoutResponse = await fetch(`${PRODUCTION_URL}/api/health`, {
- timeout: 30000
- });
- const duration = Date.now() - start;
- console.log(`✅ Temps de réponse réseau: ${duration}ms`);
-
- } catch (error) {
- console.error('❌ Erreur de diagnostic:', error.message);
-
- if (error.code === 'ECONNREFUSED') {
- console.log('💡 Solution: Vérifiez que le serveur est démarré et accessible');
- } else if (error.code === 'ETIMEDOUT') {
- console.log('💡 Solution: Problème de timeout réseau - vérifiez la connectivité');
- } else if (error.message.includes('ENOTFOUND')) {
- console.log('💡 Solution: URL du serveur incorrecte ou problème DNS');
- }
- }
-}
-
-// Instructions d'utilisation
-console.log(`
-🚀 INSTRUCTIONS D'UTILISATION:
-
-1. Configurez les variables d'environnement:
- export PRODUCTION_URL="https://votre-serveur-production.com"
- export PROD_USERNAME="votre-directeur-username"
- export PROD_PASSWORD="votre-directeur-password"
-
-2. Exécutez le script:
- node debug-calendar-production.js
-
-3. Analysez les résultats pour identifier le problème
-`);
-
-if (process.argv.includes('--run')) {
- testCalendarAPIs();
-}
\ No newline at end of file
diff --git a/debug-deliveries-production.js b/debug-deliveries-production.js
deleted file mode 100755
index 822b6a9..0000000
--- a/debug-deliveries-production.js
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env node
-
-// Script de test spécifique pour les livraisons en production
-const url = process.argv[2] || 'https://logiflow.ffnancy.fr';
-
-const testDeliveriesAPI = async () => {
- console.log(`🚚 Test des livraisons sur ${url}\n`);
-
- try {
- // 1. Connexion
- console.log('1. 🔐 Test de connexion...');
- const loginResponse = await fetch(`${url}/api/login`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ username: 'admin', password: 'admin' }),
- credentials: 'include'
- });
-
- if (!loginResponse.ok) {
- console.log('❌ Connexion échouée:', loginResponse.status);
- return;
- }
-
- const cookies = loginResponse.headers.get('set-cookie');
- console.log('✅ Connexion réussie');
-
- // 2. Test API livraisons
- console.log('\n2. 📦 Test API livraisons...');
- const deliveriesResponse = await fetch(`${url}/api/deliveries`, {
- headers: { 'Cookie': cookies || '' }
- });
-
- if (!deliveriesResponse.ok) {
- console.log('❌ API livraisons échouée:', deliveriesResponse.status);
- return;
- }
-
- const deliveries = await deliveriesResponse.json();
- console.log('✅ API livraisons OK:', deliveries.length, 'livraisons trouvées');
-
- // 3. Test API commandes pour comparaison
- console.log('\n3. 📋 Test API commandes...');
- const ordersResponse = await fetch(`${url}/api/orders`, {
- headers: { 'Cookie': cookies || '' }
- });
-
- if (ordersResponse.ok) {
- const orders = await ordersResponse.json();
- console.log('✅ API commandes OK:', orders.length, 'commandes trouvées');
- }
-
- // 4. Comparaison
- console.log('\n🔍 Résultats:');
- console.log(` Livraisons: ${deliveries.length} items`);
- if (deliveries.length === 0) {
- console.log('⚠️ Aucune livraison trouvée - Vérifiez la base de données');
- } else {
- console.log('✅ Des livraisons sont présentes');
- }
-
- } catch (error) {
- console.log('❌ Erreur de test:', error.message);
- }
-};
-
-testDeliveriesAPI().catch(console.error);
\ No newline at end of file
diff --git a/debug-employee-403-production.js b/debug-employee-403-production.js
deleted file mode 100644
index c8d498b..0000000
--- a/debug-employee-403-production.js
+++ /dev/null
@@ -1,192 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Script de débogage pour identifier les erreurs 403 des employés en production
- * Analyse les routes et permissions pour diagnostiquer les problèmes d'accès
- */
-
-const https = require('https');
-
-// Configuration pour le serveur de production
-const PRODUCTION_URL = process.env.PRODUCTION_URL || 'https://votre-serveur-production.com';
-const TEST_EMPLOYEE_CREDENTIALS = {
- username: process.env.TEST_EMPLOYEE_USERNAME || 'test_employee',
- password: process.env.TEST_EMPLOYEE_PASSWORD || 'password123'
-};
-
-console.log('🐛 === DÉBOGAGE ERREURS 403 EMPLOYÉS EN PRODUCTION ===\n');
-
-// Routes susceptibles de poser problème pour les employés
-const ROUTES_TO_TEST = [
- { path: '/api/tasks', method: 'GET', description: 'Liste des tâches' },
- { path: '/api/tasks', method: 'POST', description: 'Création de tâche', data: { title: 'Test', description: 'Test', priority: 'medium', status: 'pending', groupId: 1 } },
- { path: '/api/suppliers', method: 'GET', description: 'Liste des fournisseurs' },
- { path: '/api/suppliers?dlc=true', method: 'GET', description: 'Fournisseurs DLC' },
- { path: '/api/groups', method: 'GET', description: 'Liste des groupes/magasins' },
- { path: '/api/customer-orders', method: 'GET', description: 'Commandes client' },
- { path: '/api/dlc-products', method: 'GET', description: 'Produits DLC' },
- { path: '/api/user', method: 'GET', description: 'Profil utilisateur' }
-];
-
-async function makeRequest(path, method = 'GET', data = null, cookies = '') {
- return new Promise((resolve, reject) => {
- const url = new URL(path, PRODUCTION_URL);
- const options = {
- hostname: url.hostname,
- port: url.port || (url.protocol === 'https:' ? 443 : 80),
- path: url.pathname + url.search,
- method: method,
- headers: {
- 'Content-Type': 'application/json',
- 'User-Agent': 'LogiFlow-Debug-Script/1.0',
- ...(cookies ? { 'Cookie': cookies } : {}),
- ...(data ? { 'Content-Length': Buffer.byteLength(JSON.stringify(data)) } : {})
- }
- };
-
- const req = https.request(options, (res) => {
- let body = '';
- res.on('data', (chunk) => body += chunk);
- res.on('end', () => {
- try {
- const parsed = JSON.parse(body);
- resolve({
- status: res.statusCode,
- headers: res.headers,
- data: parsed
- });
- } catch (e) {
- resolve({
- status: res.statusCode,
- headers: res.headers,
- data: body
- });
- }
- });
- });
-
- req.on('error', reject);
-
- if (data) {
- req.write(JSON.stringify(data));
- }
-
- req.end();
- });
-}
-
-async function debugEmployee403Errors() {
- try {
- console.log('1️⃣ Connexion avec compte employé...');
-
- // Connexion employé
- const loginResponse = await makeRequest('/api/login', 'POST', TEST_EMPLOYEE_CREDENTIALS);
-
- if (loginResponse.status !== 200) {
- console.error('❌ Échec de connexion employé');
- console.error(` Status: ${loginResponse.status}`);
- console.error(` Response: ${JSON.stringify(loginResponse.data, null, 2)}`);
- return;
- }
-
- console.log('✅ Connexion employé réussie\n');
-
- // Extraire les cookies de session
- const setCookieHeaders = loginResponse.headers['set-cookie'] || [];
- const cookies = setCookieHeaders.join('; ');
-
- console.log('2️⃣ Test des routes susceptibles de générer des erreurs 403...\n');
-
- const results = [];
-
- // Tester chaque route
- for (const route of ROUTES_TO_TEST) {
- console.log(`🔍 Test: ${route.method} ${route.path} - ${route.description}`);
-
- try {
- const response = await makeRequest(route.path, route.method, route.data, cookies);
-
- const status = response.status;
- const statusIcon = status === 200 ? '✅' : status === 403 ? '❌' : '⚠️';
-
- console.log(` ${statusIcon} Status: ${status}`);
-
- if (status === 403) {
- console.log(` 🚫 ERREUR 403: ${JSON.stringify(response.data, null, 2)}`);
- results.push({ route, status, error: response.data, success: false });
- } else if (status === 200) {
- const dataSize = Array.isArray(response.data) ? response.data.length : 'N/A';
- console.log(` 📊 Données retournées: ${dataSize} éléments`);
- results.push({ route, status, success: true });
- } else {
- console.log(` ⚠️ Status inattendu: ${JSON.stringify(response.data, null, 2)}`);
- results.push({ route, status, error: response.data, success: false });
- }
-
- } catch (error) {
- console.log(` 💥 Erreur réseau: ${error.message}`);
- results.push({ route, status: 'ERROR', error: error.message, success: false });
- }
-
- console.log(''); // Ligne vide entre les tests
- }
-
- // Résumé des résultats
- console.log('📊 === RÉSUMÉ DES TESTS ===');
- console.log('==========================\n');
-
- const successfulRoutes = results.filter(r => r.success);
- const forbiddenRoutes = results.filter(r => r.status === 403);
- const errorRoutes = results.filter(r => !r.success && r.status !== 403);
-
- console.log(`✅ Routes accessibles: ${successfulRoutes.length}/${results.length}`);
- console.log(`❌ Erreurs 403: ${forbiddenRoutes.length}/${results.length}`);
- console.log(`⚠️ Autres erreurs: ${errorRoutes.length}/${results.length}\n`);
-
- if (forbiddenRoutes.length > 0) {
- console.log('🚫 ROUTES BLOQUÉES (403):');
- forbiddenRoutes.forEach(result => {
- console.log(` • ${result.route.method} ${result.route.path} - ${result.route.description}`);
- console.log(` Erreur: ${result.error?.message || 'Permission refusée'}`);
- });
- console.log('');
- }
-
- if (errorRoutes.length > 0) {
- console.log('⚠️ AUTRES ERREURS:');
- errorRoutes.forEach(result => {
- console.log(` • ${result.route.method} ${result.route.path} - Status: ${result.status}`);
- console.log(` Erreur: ${result.error?.message || result.error}`);
- });
- console.log('');
- }
-
- console.log('💡 RECOMMANDATIONS:');
- if (forbiddenRoutes.length === 0) {
- console.log(' 🎉 Aucune erreur 403 détectée - les permissions semblent correctes !');
- } else {
- console.log(' 1. Vérifiez les permissions dans shared/permissions.ts');
- console.log(' 2. Vérifiez les middlewares de permission dans server/permissions.ts');
- console.log(' 3. Vérifiez l\'assignation de groupes/magasins à l\'employé');
- console.log(' 4. Examinez les logs serveur pendant l\'exécution des requêtes');
- }
-
- } catch (error) {
- console.error('💥 Erreur lors du débogage:', error.message);
- }
-}
-
-// Instructions d'utilisation
-console.log('📋 Instructions:');
-console.log('1. Configurez les variables d\'environnement:');
-console.log(' - PRODUCTION_URL=https://votre-serveur.com');
-console.log(' - TEST_EMPLOYEE_USERNAME=nom_utilisateur_employe');
-console.log(' - TEST_EMPLOYEE_PASSWORD=mot_de_passe');
-console.log('2. Exécutez: node debug-employee-403-production.js\n');
-
-// Exécuter le debug si le script est appelé directement
-if (require.main === module) {
- debugEmployee403Errors().catch(console.error);
-}
-
-module.exports = { debugEmployee403Errors };
\ No newline at end of file
diff --git a/debug-employee-customer-orders.js b/debug-employee-customer-orders.js
deleted file mode 100644
index b44e957..0000000
--- a/debug-employee-customer-orders.js
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Script simple pour diagnostiquer le problème employé en production
- */
-
-console.log('🔍 Diagnostic employé - Création commandes client');
-console.log('');
-
-// Instructions pour le diagnostic
-console.log('=== DIAGNOSTIC PRODUCTION - EMPLOYÉ ===');
-console.log('');
-console.log('1. VÉRIFICATIONS CÔTÉ SERVEUR :');
-console.log(' ✓ Restriction hasPermission supprimée de POST /api/customer-orders');
-console.log(' ✓ Seule vérification restante : accès au groupId');
-console.log(' ✓ Tous les rôles peuvent créer des commandes client');
-console.log('');
-
-console.log('2. CAUSES POSSIBLES DU PROBLÈME :');
-console.log(' 📋 Employé pas assigné à un groupe valide');
-console.log(' 📋 Problème de validation schema (données envoyées incorrectes)');
-console.log(' 📋 Erreur de groupId dans la requête frontend');
-console.log(' 📋 Session/authentification corrompue');
-console.log('');
-
-console.log('3. VÉRIFICATIONS À FAIRE EN PRODUCTION :');
-console.log('');
-console.log('A) Vérifier les groupes de l\'employé :');
-console.log(' - Se connecter en admin');
-console.log(' - Aller dans Administration > Utilisateurs');
-console.log(' - Vérifier que l\'employé est assigné à au moins 1 groupe');
-console.log('');
-
-console.log('B) Vérifier les logs serveur :');
-console.log(' - Ouvrir les logs serveur pendant que l\'employé essaie de créer');
-console.log(' - Chercher les messages console.log() de la route POST /api/customer-orders');
-console.log(' - Regarder les erreurs Zod ou autres erreurs de validation');
-console.log('');
-
-console.log('C) Tester manuellement avec curl :');
-console.log(' - Se connecter d\'abord pour récupérer le cookie de session');
-console.log(' - Utiliser curl pour tester la création de commande');
-console.log('');
-
-console.log('4. EXEMPLE CURL POUR TEST PRODUCTION :');
-console.log('');
-console.log('# 1. Se connecter en employé');
-console.log('curl -c cookies.txt -X POST https://votre-serveur.com/api/login \\');
-console.log(' -H "Content-Type: application/json" \\');
-console.log(' -d \'{"username":"employee_username","password":"employee_password"}\'');
-console.log('');
-
-console.log('# 2. Récupérer le profil pour voir les groupes');
-console.log('curl -b cookies.txt https://votre-serveur.com/api/user');
-console.log('');
-
-console.log('# 3. Créer une commande client (remplacer groupId par un ID valide)');
-console.log('curl -b cookies.txt -X POST https://votre-serveur.com/api/customer-orders \\');
-console.log(' -H "Content-Type: application/json" \\');
-console.log(' -d \'{"customerName":"Test Employé","contactNumber":"0123456789","productName":"Test","productDescription":"Test","quantity":1,"groupId":1,"isPickup":false,"notes":"Test"}\'');
-console.log('');
-
-console.log('5. SOLUTION PROBABLE :');
-console.log(' Si l\'employé n\'est pas assigné à un groupe, l\'assigner via l\'interface admin');
-console.log(' Si validation échoue, vérifier que tous les champs requis sont présents');
-console.log('');
-
-console.log('6. CODE SERVEUR ACTUEL (POST /api/customer-orders) :');
-console.log(' - Plus de vérification hasPermission');
-console.log(' - Vérification groupId : userGroupIds.includes(data.groupId)');
-console.log(' - Si employé.userGroups est vide → échec garanti');
-console.log(' - Si data.groupId invalide → échec garanti');
-console.log('');
-
-console.log('=== FIN DU DIAGNOSTIC ===');
\ No newline at end of file
diff --git a/debug-employee-dlc-production.js b/debug-employee-dlc-production.js
deleted file mode 100644
index 0da311c..0000000
--- a/debug-employee-dlc-production.js
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Instructions de debug pour le problème DLC employé en production
- */
-
-console.log('🔍 Debug DLC Employé - Instructions Production');
-console.log('='.repeat(50));
-
-console.log(`
-ÉTAPES DE DIAGNOSTIC:
-
-1. 🔍 TESTER CRÉATION DLC EMPLOYÉ:
- - Se connecter en tant qu'employé
- - Créer une DLC
- - Regarder les logs serveur pour:
- "🔍 Creating DLC product - no role restrictions:"
- - Noter le requestGroupId et userGroups dans les logs
-
-2. 🔍 TESTER RÉCUPÉRATION DLC EMPLOYÉ:
- - Immédiatement après création, aller sur la page DLC
- - Regarder les logs serveur pour:
- "🔍 DLC Products API called with:"
- - Comparer groupIds utilisateur vs groupId de la DLC créée
-
-3. 🔍 VÉRIFIER ASSIGNATION GROUPES:
- - Si userGroups est vide ou ne contient pas le bon groupId
- - L'employé n'est pas assigné au bon groupe dans user_groups
-
-4. 🔍 TESTS À FAIRE:
-
- Test A - Créer DLC:
- POST /api/dlc-products avec groupId=1
- -> Vérifier le log "🔍 Creating DLC product"
- -> Noter requestGroupId et userGroups
-
- Test B - Lister DLC:
- GET /api/dlc-products
- -> Vérifier le log "🔍 DLC Products API called with"
- -> Comparer groupIds filtrés vs groupId de création
-
-5. 🔍 SOLUTION PROBABLE:
- - Si userGroups ne contient pas le requestGroupId
- - Ajouter l'employé au bon groupe dans la table user_groups
- - Ou modifier le frontend pour utiliser le bon groupId
-
-LOGS À RECHERCHER:
-- "🔍 Creating DLC product - no role restrictions:"
-- "🔍 DLC Products API called with:"
-- "📋 DLC Products returned:"
-- "📋 Sample DLC products groupIds:"
-`);
-
-console.log('\n🔧 Tests de validation rapides en production:');
-console.log('1. Vérifier les groupes assignés à l\'employé');
-console.log('2. Vérifier que la DLC est créée avec le bon groupId');
-console.log('3. Vérifier que le filtre groupIds inclut ce groupId');
\ No newline at end of file
diff --git a/debug-employee-dlc-visibility.js b/debug-employee-dlc-visibility.js
deleted file mode 100644
index abf8bcd..0000000
--- a/debug-employee-dlc-visibility.js
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Debug final pour vérifier pourquoi les DLC créées par l'employé n'apparaissent pas
- */
-
-console.log('🔍 Debug Final - Visibilité DLC Employé');
-
-async function debugDlcVisibility() {
- try {
- const fetch = require('node-fetch');
-
- console.log('\n=== DEBUG VISIBILITÉ DLC EMPLOYÉ ===');
-
- // 1. Login admin pour test de contrôle
- console.log('1. Test admin...');
- const adminLogin = await fetch('http://localhost:5000/api/login', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ username: 'admin', password: 'admin' })
- });
-
- if (!adminLogin.ok) {
- console.log('❌ Admin login failed');
- return;
- }
-
- const adminCookies = adminLogin.headers.get('set-cookie');
-
- // 2. Créer une DLC avec admin
- console.log('2. Création DLC par admin...');
- const dlcData = {
- productName: 'Test DLC Visibilité Admin',
- dlcDate: '2025-08-20',
- dateType: 'DLC',
- quantity: 1,
- unit: 'Unité',
- supplierId: 1,
- location: 'Test Rayon',
- groupId: 2, // Groupe Houdemont (même que l'employé)
- status: 'en_cours'
- };
-
- const createDlc = await fetch('http://localhost:5000/api/dlc-products', {
- method: 'POST',
- headers: {
- 'Cookie': adminCookies,
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(dlcData)
- });
-
- console.log('Status création:', createDlc.status);
-
- if (createDlc.ok) {
- const newDlc = await createDlc.json();
- console.log('✅ DLC créée:', {
- id: newDlc.id,
- productName: newDlc.productName,
- groupId: newDlc.groupId
- });
- }
-
- // 3. Vérifier la liste complète DLC
- console.log('\n3. Vérification liste DLC...');
- const dlcList = await fetch('http://localhost:5000/api/dlc-products', {
- headers: { 'Cookie': adminCookies }
- });
-
- if (dlcList.ok) {
- const dlcs = await dlcList.json();
- console.log('📋 Total DLC:', dlcs.length);
-
- // Filtrer par groupe 2 (Houdemont)
- const group2Dlcs = dlcs.filter(d => d.groupId === 2);
- console.log('🏪 DLC Groupe 2 (Houdemont):', group2Dlcs.length);
-
- // Dernières DLC créées
- const recentDlcs = dlcs.slice(0, 5);
- console.log('🆕 5 dernières DLC:');
- recentDlcs.forEach(dlc => {
- console.log(` - ID: ${dlc.id}, Nom: ${dlc.productName}, Groupe: ${dlc.groupId}`);
- });
- }
-
- console.log('\n4. Instructions pour test employé production:');
- console.log('- Se connecter avec compte employé');
- console.log('- Aller sur page DLC Products');
- console.log('- Vérifier si les DLC du groupe 2 sont visibles');
- console.log('- Regarder dans les outils dev si la requête API retourne des données');
- console.log('- Vérifier le cache React Query dans les dev tools');
-
- console.log('\n🔍 Points à vérifier:');
- console.log('1. Cache React Query invalidé après création ?');
- console.log('2. Filtre groupId correct dans la requête ?');
- console.log('3. État de loading/error du composant ?');
- console.log('4. Données reçues mais pas affichées ?');
-
- } catch (error) {
- console.log('❌ Erreur debug:', error.message);
- }
-}
-
-debugDlcVisibility();
\ No newline at end of file
diff --git a/debug-employee-production-permissions.js b/debug-employee-production-permissions.js
deleted file mode 100644
index d6bb68d..0000000
--- a/debug-employee-production-permissions.js
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/usr/bin/env node
-
-// Script de debug pour permissions employé en production
-// À exécuter dans la console DevTools du navigateur
-
-const debugEmployeePermissions = () => {
- console.log('🔍 DEBUG PERMISSIONS EMPLOYÉ PRODUCTION');
- console.log('=====================================');
-
- // 1. Vérifier l'utilisateur connecté
- console.log('\n👤 UTILISATEUR:');
- if (window.user || localStorage.getItem('user')) {
- const user = window.user || JSON.parse(localStorage.getItem('user') || '{}');
- console.log('ID:', user.id);
- console.log('Role:', user.role);
- console.log('Groups:', user.userGroups);
- console.log('Nom:', user.firstName, user.lastName);
- } else {
- console.log('❌ Aucun utilisateur trouvé');
- return;
- }
-
- // 2. Vérifier les permissions via hook
- console.log('\n🔐 PERMISSIONS HOOK:');
- try {
- // Simuler usePermissions
- const testPermissions = {
- 'customer-orders': ['view', 'create'],
- 'dlc': ['view', 'create']
- };
-
- console.log('Customer Orders - canCreate:', testPermissions['customer-orders'].includes('create'));
- console.log('DLC - canCreate:', testPermissions['dlc'].includes('create'));
- } catch (error) {
- console.log('❌ Erreur permissions:', error);
- }
-
- // 3. Vérifier les éléments DOM
- console.log('\n🖥️ INTERFACE:');
- const nouvelleCommande = document.querySelector('button:contains("Nouvelle Commande")') ||
- document.querySelector('[class*="button"]:contains("Nouvelle")');
- console.log('Bouton "Nouvelle Commande" visible:', !!nouvelleCommande);
-
- const dlcButton = document.querySelector('button:contains("Nouveau DLC")') ||
- document.querySelector('[class*="button"]:contains("DLC")');
- console.log('Bouton création DLC visible:', !!dlcButton);
-
- // 4. Test requête API directe
- console.log('\n🌐 TEST API:');
- console.log('Ouvrir DevTools > Network pour voir les requêtes');
- console.log('Essayer de créer une commande et noter la réponse');
-
- // 5. Logs à surveiller
- console.log('\n📋 LOGS À SURVEILLER:');
- console.log('- Erreurs console (rouge)');
- console.log('- Requêtes réseau échouées (400/403/500)');
- console.log('- Messages d\'erreur formulaire');
- console.log('- Validation schema échouée');
-
- return {
- user: window.user || JSON.parse(localStorage.getItem('user') || '{}'),
- canCreateOrders: true, // Devrait être true pour employé
- canCreateDLC: true, // Devrait être true pour employé
- timestamp: new Date().toISOString()
- };
-};
-
-// Instructions pour utilisation en production
-console.log('🎯 INSTRUCTIONS PRODUCTION:');
-console.log('1. Ouvrir DevTools (F12)');
-console.log('2. Aller dans Console');
-console.log('3. Coller ce script et Entrée');
-console.log('4. Analyser les résultats');
-console.log('5. Essayer créer commande/DLC');
-console.log('6. Envoyer logs complets pour debug');
-
-// Export pour utilisation
-if (typeof module !== 'undefined') {
- module.exports = debugEmployeePermissions;
-}
\ No newline at end of file
diff --git a/debug-permissions.js b/debug-permissions.js
deleted file mode 100644
index a8c2153..0000000
--- a/debug-permissions.js
+++ /dev/null
@@ -1,39 +0,0 @@
-// Debug script to check permissions loading
-const { storage } = require('./server/storage');
-
-async function debugPermissions() {
- try {
- console.log('=== DEBUG PERMISSIONS ===');
-
- // Get all permissions
- const permissions = await storage.getPermissions();
- console.log('Total permissions found:', permissions.length);
-
- // Check DLC permissions specifically
- const dlcPermissions = permissions.filter(p => p.category === 'gestion_dlc');
- console.log('DLC permissions found:', dlcPermissions.length);
-
- if (dlcPermissions.length > 0) {
- console.log('DLC permissions details:');
- dlcPermissions.forEach(p => {
- console.log(` - ${p.name}: ${p.displayName} (${p.action})`);
- });
- }
-
- // Check categories
- const categories = [...new Set(permissions.map(p => p.category))];
- console.log('All categories:', categories);
-
- // Check if gestion_dlc is in the list
- const hasDlcCategory = categories.includes('gestion_dlc');
- console.log('Has gestion_dlc category:', hasDlcCategory);
-
- // Check permissions data structure
- console.log('Sample permission structure:', permissions[0]);
-
- } catch (error) {
- console.error('Error debugging permissions:', error);
- }
-}
-
-debugPermissions();
\ No newline at end of file
diff --git a/debug-production-schema.js b/debug-production-schema.js
deleted file mode 100644
index 3e3ce17..0000000
--- a/debug-production-schema.js
+++ /dev/null
@@ -1,73 +0,0 @@
-import { Client } from 'pg';
-
-async function logProductionSchema() {
- // URL de connexion à votre base de production
- const productionDbUrl = process.env.DATABASE_URL_PRODUCTION || process.env.DATABASE_URL;
-
- if (!productionDbUrl) {
- console.error('❌ DATABASE_URL_PRODUCTION ou DATABASE_URL non définie');
- return;
- }
-
- const client = new Client({
- connectionString: productionDbUrl,
- ssl: productionDbUrl.includes('neon.tech') ? { rejectUnauthorized: false } : false
- });
-
- try {
- await client.connect();
- console.log('✅ Connecté à la base de production');
-
- // Récupérer tous les noms de tables
- const tablesQuery = `
- SELECT table_name
- FROM information_schema.tables
- WHERE table_schema = 'public'
- ORDER BY table_name;
- `;
-
- const tablesResult = await client.query(tablesQuery);
- console.log('\n📋 TABLES DE LA BASE DE PRODUCTION:');
- console.log('=====================================');
-
- for (const row of tablesResult.rows) {
- const tableName = row.table_name;
- console.log(`\n🔸 Table: ${tableName}`);
-
- // Récupérer les colonnes de chaque table
- const columnsQuery = `
- SELECT
- column_name,
- data_type,
- is_nullable,
- column_default
- FROM information_schema.columns
- WHERE table_schema = 'public'
- AND table_name = $1
- ORDER BY ordinal_position;
- `;
-
- const columnsResult = await client.query(columnsQuery, [tableName]);
-
- if (columnsResult.rows.length > 0) {
- console.log(' Colonnes:');
- columnsResult.rows.forEach(col => {
- const nullable = col.is_nullable === 'YES' ? 'NULL' : 'NOT NULL';
- const defaultVal = col.column_default ? ` DEFAULT ${col.column_default}` : '';
- console.log(` - ${col.column_name}: ${col.data_type} ${nullable}${defaultVal}`);
- });
- }
- }
-
- console.log('\n📊 RÉSUMÉ:');
- console.log(`Total des tables: ${tablesResult.rows.length}`);
-
- } catch (error) {
- console.error('❌ Erreur lors de la connexion:', error.message);
- } finally {
- await client.end();
- }
-}
-
-// Exécuter le script
-logProductionSchema().catch(console.error);
\ No newline at end of file
diff --git a/debug-production.js b/debug-production.js
deleted file mode 100644
index ca4dd3d..0000000
--- a/debug-production.js
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/env node
-
-// Script de diagnostic pour la production LogiFlow
-// Usage: node debug-production.js [URL_BASE]
-
-const url = process.argv[2] || 'https://logiflow.ffnancy.fr';
-
-const runDiagnostics = async () => {
- console.log(`🔍 Diagnostic de production pour ${url}\n`);
-
- const endpoints = [
- { path: '/api/health', desc: 'Health Check' },
- { path: '/api/user', desc: 'API User (attendu: 401)' },
- { path: '/api/default-credentials-check', desc: 'Credentials Check' },
- { path: '/', desc: 'Page principale' },
- { path: '/sav', desc: 'Page SAV' }
- ];
-
- for (const endpoint of endpoints) {
- try {
- console.log(`📡 Test ${endpoint.desc}: ${url}${endpoint.path}`);
-
- const response = await fetch(`${url}${endpoint.path}`, {
- method: 'GET',
- headers: {
- 'User-Agent': 'LogiFlow-Debug/1.0'
- }
- });
-
- console.log(` Status: ${response.status} ${response.statusText}`);
-
- if (endpoint.path === '/api/health' && response.ok) {
- const data = await response.json();
- console.log(` Détails:`, data);
- }
-
- if (response.status === 502) {
- console.log(` ❌ Erreur 502: Service indisponible ou problème de proxy`);
- } else if (response.ok || response.status === 401) {
- console.log(` ✅ Service répond correctement`);
- } else {
- console.log(` ⚠️ Status inattendu`);
- }
-
- } catch (error) {
- console.log(` ❌ Erreur de connexion: ${error.message}`);
- }
-
- console.log('');
- }
-
- console.log('🔧 Actions recommandées:');
- console.log('1. Vérifier les logs Docker: docker-compose logs logiflow');
- console.log('2. Vérifier le status: docker-compose ps');
- console.log('3. Redémarrer si nécessaire: docker-compose restart logiflow');
- console.log('4. Forcer rebuild: docker-compose up --build -d');
-};
-
-runDiagnostics().catch(console.error);
\ No newline at end of file
diff --git a/debug-usergroups-production.sql b/debug-usergroups-production.sql
deleted file mode 100644
index 7944642..0000000
--- a/debug-usergroups-production.sql
+++ /dev/null
@@ -1,46 +0,0 @@
--- Script de débogage pour vérifier l'état des groupes d'utilisateurs en production
--- À exécuter sur votre base de données de production
-
--- 1. Vérifier la structure de la table user_groups
-\d user_groups;
-
--- 2. Vérifier tous les enregistrements dans user_groups
-SELECT * FROM user_groups ORDER BY user_id;
-
--- 3. Vérifier les groupes disponibles
-SELECT id, name, color FROM groups ORDER BY name;
-
--- 4. Vérifier les utilisateurs existants
-SELECT id, username, email, role FROM users ORDER BY username;
-
--- 5. Requête combinée pour voir les associations utilisateur-groupe
-SELECT
- u.id as user_id,
- u.username,
- u.email,
- ug.group_id,
- g.name as group_name,
- g.color as group_color
-FROM users u
-LEFT JOIN user_groups ug ON u.id = ug.user_id
-LEFT JOIN groups g ON ug.group_id = g.id
-ORDER BY u.username, g.name;
-
--- 6. Compter les associations par utilisateur
-SELECT
- u.username,
- COUNT(ug.group_id) as groups_count
-FROM users u
-LEFT JOIN user_groups ug ON u.id = ug.user_id
-GROUP BY u.id, u.username
-ORDER BY u.username;
-
--- 7. Vérifier s'il y a des enregistrements orphelins dans user_groups
-SELECT
- ug.*,
- CASE WHEN u.id IS NULL THEN 'USER_MISSING' ELSE 'USER_OK' END as user_status,
- CASE WHEN g.id IS NULL THEN 'GROUP_MISSING' ELSE 'GROUP_OK' END as group_status
-FROM user_groups ug
-LEFT JOIN users u ON ug.user_id = u.id
-LEFT JOIN groups g ON ug.group_id = g.id
-WHERE u.id IS NULL OR g.id IS NULL;
\ No newline at end of file
diff --git a/deploy-auto-sync.js b/deploy-auto-sync.js
deleted file mode 100644
index b487653..0000000
--- a/deploy-auto-sync.js
+++ /dev/null
@@ -1,141 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Script de déploiement pour la synchronisation automatique ordre-livraison
- * À exécuter sur le serveur de production pour appliquer les modifications
- */
-
-import fs from 'fs/promises';
-import path from 'path';
-
-console.log('🚀 Déploiement de la synchronisation automatique...');
-
-const PRODUCTION_ROUTES_PATH = '/path/to/production/server/routes.ts'; // À adapter selon votre structure
-
-// Modifications à appliquer au fichier routes.ts en production
-const autoSyncModifications = {
- // 1. Modification de la route PUT /api/deliveries/:id pour ajouter la sync auto
- updateDeliveryRoute: {
- search: ` const data = insertDeliverySchema.partial().parse(req.body);
- const updatedDelivery = await storage.updateDelivery(id, data);
- res.json(updatedDelivery);`,
- replace: ` const data = insertDeliverySchema.partial().parse(req.body);
- const updatedDelivery = await storage.updateDelivery(id, data);
-
- // SYNCHRONISATION AUTOMATIQUE : Si livraison devient "delivered", marquer la commande associée comme "delivered"
- if (data.status === 'delivered' && updatedDelivery.orderId) {
- try {
- console.log(\`🔄 Auto-sync: Delivery #\${id} marked as delivered, updating order #\${updatedDelivery.orderId}\`);
- await storage.updateOrder(updatedDelivery.orderId, { status: 'delivered' });
- console.log(\`✅ Auto-sync: Order #\${updatedDelivery.orderId} automatically marked as delivered\`);
- } catch (error) {
- console.error(\`❌ Auto-sync failed for order #\${updatedDelivery.orderId}:\`, error);
- }
- }
-
- res.json(updatedDelivery);`
- },
-
- // 2. Modification de la route POST /api/deliveries/:id/validate pour ajouter la sync auto
- validateDeliveryRoute: {
- search: ` await storage.validateDelivery(id, blData);
- res.json({ message: "Delivery validated successfully" });`,
- replace: ` await storage.validateDelivery(id, blData);
-
- // SYNCHRONISATION AUTOMATIQUE : Quand validation, marquer la commande associée comme "delivered"
- if (delivery.orderId) {
- try {
- console.log(\`🔄 Auto-sync: Delivery #\${id} validated, updating order #\${delivery.orderId} to delivered\`);
- await storage.updateOrder(delivery.orderId, { status: 'delivered' });
- console.log(\`✅ Auto-sync: Order #\${delivery.orderId} automatically marked as delivered\`);
- } catch (error) {
- console.error(\`❌ Auto-sync failed for order #\${delivery.orderId}:\`, error);
- }
- }
-
- res.json({ message: "Delivery validated successfully" });`
- }
-};
-
-// Instructions de déploiement
-console.log(`
-📋 INSTRUCTIONS DE DÉPLOIEMENT PRODUCTION :
-
-1. 🔍 Localisez le fichier server/routes.ts sur votre serveur de production
-
-2. 🔧 Ajoutez la synchronisation automatique dans la route PUT /api/deliveries/:id :
-
- Remplacez :
- ${autoSyncModifications.updateDeliveryRoute.search}
-
- Par :
- ${autoSyncModifications.updateDeliveryRoute.replace}
-
-3. 🔧 Ajoutez la synchronisation automatique dans la route POST /api/deliveries/:id/validate :
-
- Remplacez :
- ${autoSyncModifications.validateDeliveryRoute.search}
-
- Par :
- ${autoSyncModifications.validateDeliveryRoute.replace}
-
-4. 🔄 Redémarrez votre serveur Node.js en production
-
-5. ✅ Testez en validant une livraison - la commande associée devrait automatiquement passer en "delivered"
-
-6. 🎯 Pour corriger CMD-55 spécifiquement, utilisez le bouton "Sync Status" dans le calendrier
-
-RÉSULTAT ATTENDU :
-- Toutes les futures validations de livraisons synchroniseront automatiquement les commandes
-- CMD-55 sera corrigée lors de la prochaine utilisation du bouton "Sync Status"
-- Le calendrier affichera correctement les commandes livrées en gris
-`);
-
-// Créer aussi un patch file pour faciliter l'application
-const patchContent = `
---- a/server/routes.ts
-+++ b/server/routes.ts
-@@ -691,6 +691,15 @@
- const data = insertDeliverySchema.partial().parse(req.body);
- const updatedDelivery = await storage.updateDelivery(id, data);
-+
-+ // SYNCHRONISATION AUTOMATIQUE : Si livraison devient "delivered", marquer la commande associée comme "delivered"
-+ if (data.status === 'delivered' && updatedDelivery.orderId) {
-+ try {
-+ console.log(\`🔄 Auto-sync: Delivery #\${id} marked as delivered, updating order #\${updatedDelivery.orderId}\`);
-+ await storage.updateOrder(updatedDelivery.orderId, { status: 'delivered' });
-+ console.log(\`✅ Auto-sync: Order #\${updatedDelivery.orderId} automatically marked as delivered\`);
-+ } catch (error) {
-+ console.error(\`❌ Auto-sync failed for order #\${updatedDelivery.orderId}:\`, error);
-+ }
-+ }
- res.json(updatedDelivery);
- } catch (error) {
-@@ -830,6 +839,15 @@
- }
-
- await storage.validateDelivery(id, blData);
-+
-+ // SYNCHRONISATION AUTOMATIQUE : Quand validation, marquer la commande associée comme "delivered"
-+ if (delivery.orderId) {
-+ try {
-+ console.log(\`🔄 Auto-sync: Delivery #\${id} validated, updating order #\${delivery.orderId} to delivered\`);
-+ await storage.updateOrder(delivery.orderId, { status: 'delivered' });
-+ console.log(\`✅ Auto-sync: Order #\${delivery.orderId} automatically marked as delivered\`);
-+ } catch (error) {
-+ console.error(\`❌ Auto-sync failed for order #\${delivery.orderId}:\`, error);
-+ }
-+ }
- res.json({ message: "Delivery validated successfully" });
- } catch (error) {
-`;
-
-console.log('💾 Sauvegarde du patch dans auto-sync.patch...');
-await fs.writeFile('auto-sync.patch', patchContent);
-
-console.log(`
-🔧 Alternative : Vous pouvez aussi appliquer le patch automatiquement avec :
- cd /path/to/production && patch -p1 < auto-sync.patch
-
-✅ Script de déploiement créé avec succès !
-`);
\ No newline at end of file
diff --git a/fix-cmd-55-immediate.sql b/fix-cmd-55-immediate.sql
deleted file mode 100644
index f05aac9..0000000
--- a/fix-cmd-55-immediate.sql
+++ /dev/null
@@ -1,63 +0,0 @@
--- Script de correction immédiate pour CMD-55 et autres commandes similaires
--- À exécuter directement sur votre base de données de production
-
--- 1. Identifier CMD-55 et son statut actuel
-SELECT
- o.id as order_id,
- o.status as current_order_status,
- COUNT(d.id) as total_deliveries,
- COUNT(CASE WHEN d.status = 'delivered' THEN 1 END) as delivered_deliveries,
- string_agg(d.status, ', ') as delivery_statuses
-FROM orders o
-LEFT JOIN deliveries d ON o.id = d."orderId"
-WHERE o.id = 55
-GROUP BY o.id, o.status;
-
--- 2. Corriger CMD-55 directement si elle a des livraisons delivered
-UPDATE orders
-SET status = 'delivered'
-WHERE id = 55
- AND status != 'delivered'
- AND EXISTS (
- SELECT 1 FROM deliveries d
- WHERE d."orderId" = 55
- AND d.status = 'delivered'
- );
-
--- 3. Vérifier que la correction a été appliquée
-SELECT
- o.id as order_id,
- o.status as new_order_status,
- COUNT(d.id) as total_deliveries,
- COUNT(CASE WHEN d.status = 'delivered' THEN 1 END) as delivered_deliveries
-FROM orders o
-LEFT JOIN deliveries d ON o.id = d."orderId"
-WHERE o.id = 55
-GROUP BY o.id, o.status;
-
--- 4. BONUS: Corriger toutes les autres commandes dans la même situation
-UPDATE orders
-SET status = 'delivered'
-WHERE status != 'delivered'
- AND EXISTS (
- SELECT 1 FROM deliveries d
- WHERE d."orderId" = orders.id
- AND d.status = 'delivered'
- );
-
--- 5. Voir toutes les commandes qui ont été corrigées
-SELECT
- o.id as order_id,
- o.status as order_status,
- COUNT(d.id) as total_deliveries,
- COUNT(CASE WHEN d.status = 'delivered' THEN 1 END) as delivered_deliveries
-FROM orders o
-LEFT JOIN deliveries d ON o.id = d."orderId"
-WHERE o.status = 'delivered'
- AND EXISTS (
- SELECT 1 FROM deliveries d2
- WHERE d2."orderId" = o.id
- AND d2.status = 'delivered'
- )
-GROUP BY o.id, o.status
-ORDER BY o.id;
\ No newline at end of file
diff --git a/fix-deliveries-constraint.sql b/fix-deliveries-constraint.sql
deleted file mode 100644
index 1ee8f2e..0000000
--- a/fix-deliveries-constraint.sql
+++ /dev/null
@@ -1,23 +0,0 @@
--- Script pour corriger la contrainte deliveries_status_check qui bloque la création de livraisons
--- Cette contrainte empêche l'utilisation du statut 'planned' en production
-
--- Supprimer la contrainte existante si elle existe
-ALTER TABLE deliveries DROP CONSTRAINT IF EXISTS deliveries_status_check;
-
--- Recréer une contrainte permettant les statuts corrects
-ALTER TABLE deliveries ADD CONSTRAINT deliveries_status_check
-CHECK (status IN ('pending', 'planned', 'delivered', 'cancelled'));
-
--- Vérifier les statuts existants dans la table
-SELECT DISTINCT status FROM deliveries;
-
--- Afficher les contraintes de la table deliveries pour vérification
-SELECT
- tc.constraint_name,
- tc.constraint_type,
- cc.check_clause
-FROM information_schema.table_constraints tc
-LEFT JOIN information_schema.check_constraints cc ON tc.constraint_name = cc.constraint_name
-WHERE tc.table_name = 'deliveries'
-AND tc.table_schema = 'public'
-AND tc.constraint_type = 'CHECK';
\ No newline at end of file
diff --git a/fix-delivery-order-sync-immediate.sql b/fix-delivery-order-sync-immediate.sql
deleted file mode 100644
index 07a886a..0000000
--- a/fix-delivery-order-sync-immediate.sql
+++ /dev/null
@@ -1,74 +0,0 @@
--- Script de synchronisation immédiate des statuts commandes/livraisons
--- Exécuter directement sur la base de données de production
-
--- Étape 1: Diagnostic - Afficher les commandes problématiques
-SELECT
- o.id as order_id,
- o.status as order_status,
- d.id as delivery_id,
- d.status as delivery_status,
- d.delivered_date,
- o.supplier_id,
- s.name as supplier_name
-FROM orders o
-JOIN deliveries d ON d.order_id = o.id
-JOIN suppliers s ON o.supplier_id = s.id
-WHERE d.status = 'delivered' AND o.status != 'delivered'
-ORDER BY o.id;
-
--- Étape 2: Mise à jour automatique des statuts
--- Marquer toutes les commandes comme "delivered" si au moins une de leurs livraisons est livrée
-UPDATE orders
-SET status = 'delivered'
-WHERE id IN (
- SELECT DISTINCT o.id
- FROM orders o
- JOIN deliveries d ON d.order_id = o.id
- WHERE d.status = 'delivered' AND o.status != 'delivered'
-);
-
--- Étape 3: Mise à jour des dates de livraison manquantes
--- Ajouter delivered_date aux livraisons qui ont le status 'delivered' mais pas de date
-UPDATE deliveries
-SET delivered_date = scheduled_date
-WHERE status = 'delivered'
- AND delivered_date IS NULL
- AND scheduled_date IS NOT NULL;
-
--- Étape 4: Pour les livraisons sans scheduled_date, utiliser la date de création + 1 jour
-UPDATE deliveries
-SET delivered_date = DATE(created_at) + INTERVAL '1 day'
-WHERE status = 'delivered'
- AND delivered_date IS NULL
- AND scheduled_date IS NULL;
-
--- Étape 5: Diagnostic final - Vérifier les résultats
-SELECT
- 'RÉSULTAT FINAL' as status,
- COUNT(*) as total_orders,
- SUM(CASE WHEN status = 'delivered' THEN 1 ELSE 0 END) as delivered_orders,
- SUM(CASE WHEN status = 'planned' THEN 1 ELSE 0 END) as planned_orders
-FROM orders;
-
-SELECT
- 'LIVRAISONS MISES À JOUR' as status,
- COUNT(*) as total_delivered_deliveries,
- SUM(CASE WHEN delivered_date IS NOT NULL THEN 1 ELSE 0 END) as with_delivered_date,
- SUM(CASE WHEN delivered_date IS NULL THEN 1 ELSE 0 END) as missing_delivered_date
-FROM deliveries
-WHERE status = 'delivered';
-
--- Afficher la commande CMD-55 spécifiquement
-SELECT
- 'COMMANDE CMD-55' as status,
- o.id,
- o.status as order_status,
- o.planned_date,
- d.status as delivery_status,
- d.delivered_date,
- d.scheduled_date,
- s.name as supplier
-FROM orders o
-LEFT JOIN deliveries d ON d.order_id = o.id
-JOIN suppliers s ON o.supplier_id = s.id
-WHERE o.id = 55;
\ No newline at end of file
diff --git a/fix-delivery-order-sync.sql b/fix-delivery-order-sync.sql
deleted file mode 100644
index d0d1c25..0000000
--- a/fix-delivery-order-sync.sql
+++ /dev/null
@@ -1,72 +0,0 @@
--- Script pour diagnostiquer et corriger la synchronisation des statuts commandes/livraisons
--- À exécuter en production pour résoudre les problèmes de dates et statuts
-
--- 1. Diagnostiquer les livraisons avec statut "delivered" mais dates manquantes
-SELECT 'Livraisons livrées sans date de livraison:' as diagnostic,
- COUNT(*) as count
-FROM deliveries
-WHERE status = 'delivered' AND delivered_date IS NULL;
-
--- Afficher les détails
-SELECT d.id, d.status, d.scheduled_date, d.delivered_date, d.validated_at,
- o.id as order_id, o.status as order_status
-FROM deliveries d
-LEFT JOIN orders o ON d.order_id = o.id
-WHERE d.status = 'delivered' AND d.delivered_date IS NULL
-LIMIT 10;
-
--- 2. Diagnostiquer les commandes avec livraisons livrées mais statut incorrect
-SELECT 'Commandes avec livraisons livrées mais pas en statut delivered:' as diagnostic,
- COUNT(*) as count
-FROM orders o
-WHERE EXISTS (
- SELECT 1 FROM deliveries d
- WHERE d.order_id = o.id AND d.status = 'delivered'
-) AND o.status != 'delivered';
-
--- Afficher les détails
-SELECT o.id as order_id, o.status as order_status, o.planned_date,
- COUNT(d.id) as total_deliveries,
- SUM(CASE WHEN d.status = 'delivered' THEN 1 ELSE 0 END) as delivered_deliveries
-FROM orders o
-LEFT JOIN deliveries d ON d.order_id = o.id
-WHERE EXISTS (
- SELECT 1 FROM deliveries d2
- WHERE d2.order_id = o.id AND d2.status = 'delivered'
-) AND o.status != 'delivered'
-GROUP BY o.id, o.status, o.planned_date
-LIMIT 10;
-
--- 3. Corriger les livraisons livrées sans date de livraison
-UPDATE deliveries
-SET delivered_date = COALESCE(validated_at, updated_at, created_at)
-WHERE status = 'delivered' AND delivered_date IS NULL;
-
--- 4. Corriger les statuts des commandes liées aux livraisons livrées
-UPDATE orders
-SET status = 'delivered', updated_at = NOW()
-WHERE id IN (
- SELECT DISTINCT d.order_id
- FROM deliveries d
- WHERE d.order_id IS NOT NULL
- AND d.status = 'delivered'
- AND d.order_id NOT IN (
- SELECT o.id FROM orders o WHERE o.status = 'delivered'
- )
-);
-
--- 5. Vérification finale
-SELECT 'Vérification finale - Commandes avec statuts corrects:' as final_check,
- COUNT(*) as count
-FROM orders o
-WHERE EXISTS (
- SELECT 1 FROM deliveries d
- WHERE d.order_id = o.id AND d.status = 'delivered'
-) AND o.status = 'delivered';
-
--- Afficher un résumé des corrections
-SELECT
- 'Résumé des corrections:' as summary,
- (SELECT COUNT(*) FROM deliveries WHERE status = 'delivered') as total_delivered_deliveries,
- (SELECT COUNT(*) FROM deliveries WHERE status = 'delivered' AND delivered_date IS NOT NULL) as deliveries_with_date,
- (SELECT COUNT(*) FROM orders WHERE status = 'delivered') as total_delivered_orders;
\ No newline at end of file
diff --git a/fix-dlc-cache-invalidation.js b/fix-dlc-cache-invalidation.js
deleted file mode 100644
index f3b086f..0000000
--- a/fix-dlc-cache-invalidation.js
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/env node
-
-// Fix pour invalidation cache DLC - Test avec curl direct
-
-const testDlcEndpoint = async () => {
- const { execSync } = require('child_process');
-
- console.log('🔍 Test Direct API DLC Products');
-
- try {
- // 1. Login admin
- console.log('1. Login admin...');
- const loginResult = execSync(`curl -X POST http://localhost:5000/api/login \
- -H "Content-Type: application/json" \
- -d '{"username":"admin","password":"admin"}' \
- -c cookies.txt \
- -w "%{http_code}" \
- -s`, { encoding: 'utf8' });
-
- console.log('Login status:', loginResult.slice(-3));
-
- // 2. Test GET DLC products
- console.log('2. GET DLC products...');
- const dlcResult = execSync(`curl -X GET http://localhost:5000/api/dlc-products \
- -b cookies.txt \
- -w "%{http_code}" \
- -s`, { encoding: 'utf8' });
-
- const statusCode = dlcResult.slice(-3);
- const responseBody = dlcResult.slice(0, -3);
-
- console.log('Status:', statusCode);
-
- if (statusCode === '200') {
- const dlcs = JSON.parse(responseBody);
- console.log('✅ Total DLC:', dlcs.length);
-
- if (dlcs.length > 0) {
- console.log('📋 Sample DLC:', {
- id: dlcs[0].id,
- productName: dlcs[0].productName,
- groupId: dlcs[0].groupId,
- status: dlcs[0].status
- });
-
- // Grouper par groupId
- const byGroup = dlcs.reduce((acc, dlc) => {
- acc[dlc.groupId] = (acc[dlc.groupId] || 0) + 1;
- return acc;
- }, {});
-
- console.log('📊 DLC par groupe:', byGroup);
- }
- } else {
- console.log('❌ Erreur:', responseBody);
- }
-
- console.log('\n3. Instructions debug frontend:');
- console.log('- Ouvrir DevTools Network');
- console.log('- Recharger page DLC Products');
- console.log('- Vérifier si requête API est envoyée');
- console.log('- Vérifier la réponse de l\'API');
- console.log('- Vérifier React Query cache dans Components');
-
- } catch (error) {
- console.log('❌ Erreur:', error.message);
- }
-};
-
-testDlcEndpoint();
\ No newline at end of file
diff --git a/fix-duplicate-empty-email.sql b/fix-duplicate-empty-email.sql
deleted file mode 100644
index ef180c6..0000000
--- a/fix-duplicate-empty-email.sql
+++ /dev/null
@@ -1,28 +0,0 @@
--- Fix duplicate empty email constraint issue in production
--- This script converts empty string emails to NULL to allow multiple users without email
-
--- Step 1: Update all empty string emails to NULL
-UPDATE users
-SET email = NULL
-WHERE email = '' OR email IS NULL OR TRIM(email) = '';
-
--- Step 2: Verify the change
-SELECT 'Users with NULL email:' as status, COUNT(*) as count
-FROM users
-WHERE email IS NULL;
-
--- Step 3: Verify no empty string emails remain
-SELECT 'Users with empty string email:' as status, COUNT(*) as count
-FROM users
-WHERE email = '';
-
--- Step 4: Show sample of updated users
-SELECT id, username,
- CASE
- WHEN email IS NULL THEN '[NULL]'
- ELSE email
- END as email_display,
- role
-FROM users
-ORDER BY username
-LIMIT 10;
\ No newline at end of file
diff --git a/fix-employee-403-final.js b/fix-employee-403-final.js
deleted file mode 100644
index da801db..0000000
--- a/fix-employee-403-final.js
+++ /dev/null
@@ -1,117 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Script de correction finale des erreurs 403 pour les employés
- * Applique les corrections nécessaires au serveur de production
- */
-
-console.log('🔧 SCRIPT DE CORRECTION DES ERREURS 403 EMPLOYÉS');
-console.log('================================================');
-console.log('');
-
-console.log('✅ CORRECTIONS APPLIQUÉES DANS REPLIT:');
-console.log('');
-
-console.log('1️⃣ client/src/pages/Tasks.tsx - Ligne ~84:');
-console.log(' AVANT: enabled: !!user,');
-console.log(' APRÈS: enabled: !!user && (user.role === "admin" || user.role === "manager" || user.role === "directeur"),');
-console.log(' ➜ Évite l\'appel à /api/users pour les employés');
-console.log('');
-
-console.log('2️⃣ Boutons d\'action conditionnels pour les employés');
-console.log(' ➜ Les employés ne voient plus les boutons modifier/supprimer des tâches');
-console.log('');
-
-console.log('📋 CORRECTIONS À APPLIQUER SUR VOTRE SERVEUR PRIVÉ:');
-console.log('');
-
-console.log('💡 SOLUTION SIMPLE - 2 FICHIERS À MODIFIER:');
-console.log('');
-
-console.log('🔸 A) client/src/pages/Tasks.tsx (environ ligne 84):');
-console.log('');
-console.log('// REMPLACER:');
-console.log('const { data: users = [] } = useQuery({');
-console.log(' queryKey: ["/api/users"],');
-console.log(' queryFn: () => fetch(\'/api/users\', {');
-console.log(' credentials: \'include\'');
-console.log(' }).then(res => {');
-console.log(' if (!res.ok) {');
-console.log(' throw new Error(`HTTP error! status: ${res.status}`);');
-console.log(' }');
-console.log(' return res.json();');
-console.log(' }),');
-console.log(' enabled: !!user, // ← LIGNE À CHANGER');
-console.log('});');
-console.log('');
-console.log('// PAR:');
-console.log('const { data: users = [] } = useQuery({');
-console.log(' queryKey: ["/api/users"],');
-console.log(' queryFn: () => fetch(\'/api/users\', {');
-console.log(' credentials: \'include\'');
-console.log(' }).then(res => {');
-console.log(' if (!res.ok) {');
-console.log(' throw new Error(`HTTP error! status: ${res.status}`);');
-console.log(' }');
-console.log(' return res.json();');
-console.log(' }),');
-console.log(' enabled: !!user && (user.role === \'admin\' || user.role === \'manager\' || user.role === \'directeur\'),');
-console.log('});');
-console.log('');
-
-console.log('🔸 B) server/routes.ts - 5 corrections de permissions fournisseurs:');
-console.log('');
-
-console.log('B.1) Route GET /api/suppliers (environ ligne 188-194):');
-console.log('// REMPLACER:');
-console.log('if (!user || (user.role !== \'admin\' && user.role !== \'manager\')) {');
-console.log('// PAR:');
-console.log('if (!user || (user.role !== \'admin\' && user.role !== \'manager\' && user.role !== \'directeur\' && user.role !== \'employee\')) {');
-console.log('');
-
-console.log('B.2) Route POST /api/suppliers (environ ligne 240-242):');
-console.log('// REMPLACER:');
-console.log('if (user.role !== \'admin\' && user.role !== \'manager\') {');
-console.log('// PAR:');
-console.log('if (user.role !== \'admin\' && user.role !== \'manager\' && user.role !== \'directeur\') {');
-console.log('');
-
-console.log('B.3) Route PUT /api/suppliers/:id (environ ligne 281-283):');
-console.log('// REMPLACER:');
-console.log('if (!user || (user.role !== \'admin\' && user.role !== \'manager\')) {');
-console.log('// PAR:');
-console.log('if (!user || (user.role !== \'admin\' && user.role !== \'manager\' && user.role !== \'directeur\')) {');
-console.log('');
-
-console.log('B.4) Route DELETE /api/suppliers/:id (environ ligne 298-300):');
-console.log('// REMPLACER:');
-console.log('if (!user || (user.role !== \'admin\' && user.role !== \'manager\')) {');
-console.log('// PAR:');
-console.log('if (!user || (user.role !== \'admin\' && user.role !== \'directeur\')) {');
-console.log('');
-
-console.log('B.5) Route POST /api/dlc-products/:id/validate (environ ligne 2332-2334):');
-console.log('// REMPLACER:');
-console.log('if (!user || ![\'admin\', \'manager\'].includes(user.role)) {');
-console.log('// PAR:');
-console.log('if (!user || ![\'admin\', \'manager\', \'directeur\'].includes(user.role)) {');
-console.log('');
-
-console.log('⚡ ÉTAPES D\'APPLICATION:');
-console.log('1. Sauvegarde: cp client/src/pages/Tasks.tsx client/src/pages/Tasks.tsx.backup');
-console.log('2. Sauvegarde: cp server/routes.ts server/routes.ts.backup');
-console.log('3. Effectuer les corrections A) et B) ci-dessus');
-console.log('4. Redémarrer votre serveur Node.js');
-console.log('5. Tester avec un compte employé');
-console.log('');
-
-console.log('✅ RÉSULTAT ATTENDU:');
-console.log('- Plus d\'erreurs 403 dans la console pour les employés');
-console.log('- Employés peuvent voir les tâches (mais pas les créer/modifier)');
-console.log('- Employés peuvent voir les fournisseurs (pour Commandes Client et DLC)');
-console.log('- Directeurs peuvent valider les produits DLC');
-console.log('');
-
-console.log('🚨 IMPORTANT:');
-console.log('Les permissions dans shared/permissions.ts restent inchangées:');
-console.log('tasks: { employee: [\'view\'] } // ← Correct, ne pas modifier');
\ No newline at end of file
diff --git a/fix-employee-customer-orders-production.js b/fix-employee-customer-orders-production.js
deleted file mode 100644
index c8e8e15..0000000
--- a/fix-employee-customer-orders-production.js
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/env node
-
-// Fix urgent production pour employé - création commandes client et DLC
-// À exécuter sur le serveur de production
-
-console.log('🚨 URGENT FIX PRODUCTION - Employé + DLC');
-console.log('📋 Problèmes identifiés:');
-console.log(' 1. Employé ne peut pas créer commandes clients');
-console.log(' 2. DLC ne fonctionnent pas en production');
-console.log(' 3. Cache invalidation manquante pour DLC');
-
-console.log('\n🔧 Solutions:');
-console.log(' ✓ Permissions employé OK dans shared/permissions.ts');
-console.log(' ✓ Routes sans restrictions dans server/routes.ts');
-console.log(' ✓ Schema validation corrigé');
-console.log(' ✓ Cache invalidation avec exact:false ajouté');
-
-console.log('\n📦 Déploiement:');
-console.log(' 1. Git push les dernières modifications');
-console.log(' 2. Redémarrer le serveur production');
-console.log(' 3. Vider le cache browser des employés');
-console.log(' 4. Tester création commande client + DLC');
-
-console.log('\n🔍 Debug en cas de problème:');
-console.log(' - Vérifier les logs serveur pour erreurs validation');
-console.log(' - Contrôler les requêtes réseau dans DevTools');
-console.log(' - Confirmer que groupId est bien envoyé dans la requête');
-
-// Vérifications essentielles pour le déploiement
-const checks = [
- '✅ Routes POST /api/customer-orders sans restrictions rôle',
- '✅ Routes POST /api/dlc-products sans restrictions rôle',
- '✅ Schema insertCustomerOrderFrontendSchema validé',
- '✅ Schema insertDlcProductFrontendSchema validé',
- '✅ Cache invalidation { exact: false } pour toutes mutations DLC',
- '✅ Frontend logs pour debugging des erreurs'
-];
-
-console.log('\n📋 Checklist déploiement:');
-checks.forEach(check => console.log(` ${check}`));
-
-console.log('\n⚠️ IMPORTANT:');
-console.log(' Le problème était dans MemStorage (dev uniquement)');
-console.log(' En production PostgreSQL, ça devrait fonctionner');
-console.log(' Si ça ne marche toujours pas, problème côté frontend');
-
-console.log('\n🎯 Tests à faire après déploiement:');
-console.log(' 1. Employé: créer commande client avec tous les champs');
-console.log(' 2. Employé: créer produit DLC');
-console.log(' 3. Vérifier que DLC apparaît dans la liste');
-console.log(' 4. Vérifier stats DLC mises à jour');
\ No newline at end of file
diff --git a/fix-imports.sh b/fix-imports.sh
deleted file mode 100755
index e169092..0000000
--- a/fix-imports.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/bash
-
-# Liste des hooks React à importer
-HOOKS="forwardRef useState useEffect useContext useCallback useMemo useId createContext useRef"
-
-for file in client/src/components/ui/*.tsx; do
- # Vérifier si le fichier contient des hooks
- hooks_needed=""
- for hook in $HOOKS; do
- if grep -q "\\b$hook\\b" "$file"; then
- if [ -z "$hooks_needed" ]; then
- hooks_needed="$hook"
- else
- hooks_needed="$hooks_needed, $hook"
- fi
- fi
- done
-
- # Si des hooks sont nécessaires, mettre à jour l'import
- if [ ! -z "$hooks_needed" ]; then
- if grep -q "import React from \"react\"" "$file"; then
- sed -i.tmp "s/import React from \"react\"/import React, { $hooks_needed } from \"react\"/" "$file"
- echo "Updated $file with hooks: $hooks_needed"
- fi
- fi
-done
diff --git a/fix-production-employee-permissions-final.sql b/fix-production-employee-permissions-final.sql
deleted file mode 100644
index 443f792..0000000
--- a/fix-production-employee-permissions-final.sql
+++ /dev/null
@@ -1,94 +0,0 @@
--- Fix urgent production: permissions employé pour commandes client et DLC
--- À exécuter sur la base de production
-
--- 1. Vérifier les permissions actuelles pour le rôle employé
-SELECT
- p.name as permission_name,
- p.category,
- CASE WHEN rp.permission_id IS NOT NULL THEN 'GRANTED' ELSE 'DENIED' END as status
-FROM permissions p
-LEFT JOIN role_permissions rp ON p.id = rp.permission_id
- AND rp.role_id = (SELECT id FROM roles WHERE name = 'employee')
-WHERE p.category IN ('customer-orders', 'dlc')
-ORDER BY p.category, p.name;
-
--- 2. Vérifier si le rôle employé existe
-SELECT * FROM roles WHERE name = 'employee';
-
--- 3. Obtenir l'ID du rôle employé
-SELECT id FROM roles WHERE name = 'employee';
-
--- 4. Vérifier les permissions requises qui pourraient manquer
-SELECT id, name, category, description
-FROM permissions
-WHERE category IN ('customer-orders', 'dlc')
- AND name IN ('create', 'view')
- AND id NOT IN (
- SELECT permission_id
- FROM role_permissions
- WHERE role_id = (SELECT id FROM roles WHERE name = 'employee')
- );
-
--- 5. Si des permissions manquent, les ajouter (À DÉCOMMENTER SI NÉCESSAIRE)
-/*
--- Ajouter permission créer commandes client pour employé
-INSERT INTO role_permissions (role_id, permission_id, assigned_by, created_at)
-SELECT
- (SELECT id FROM roles WHERE name = 'employee'),
- p.id,
- 'system_fix',
- NOW()
-FROM permissions p
-WHERE p.category = 'customer-orders'
- AND p.name = 'create'
- AND NOT EXISTS (
- SELECT 1 FROM role_permissions rp
- WHERE rp.role_id = (SELECT id FROM roles WHERE name = 'employee')
- AND rp.permission_id = p.id
- );
-
--- Ajouter permission créer DLC pour employé
-INSERT INTO role_permissions (role_id, permission_id, assigned_by, created_at)
-SELECT
- (SELECT id FROM roles WHERE name = 'employee'),
- p.id,
- 'system_fix',
- NOW()
-FROM permissions p
-WHERE p.category = 'dlc'
- AND p.name = 'create'
- AND NOT EXISTS (
- SELECT 1 FROM role_permissions rp
- WHERE rp.role_id = (SELECT id FROM roles WHERE name = 'employee')
- AND rp.permission_id = p.id
- );
-*/
-
--- 6. Vérifier l'utilisateur qui a des problèmes
-SELECT
- u.id,
- u.username,
- u.role,
- u.first_name,
- u.last_name,
- COUNT(ug.group_id) as group_count
-FROM users u
-LEFT JOIN user_groups ug ON u.id = ug.user_id
-WHERE u.id = '_1753266816257'
-GROUP BY u.id, u.username, u.role, u.first_name, u.last_name;
-
--- 7. Vérifier les groupes de l'utilisateur
-SELECT
- ug.user_id,
- ug.group_id,
- g.name as group_name,
- g.color as group_color
-FROM user_groups ug
-JOIN groups g ON ug.group_id = g.id
-WHERE ug.user_id = '_1753266816257';
-
--- Notes pour le debugging:
--- - Si pas de résultats dans requête 4: permissions OK
--- - Si résultats dans requête 4: décommenter section 5
--- - Vérifier que l'utilisateur a bien un groupe assigné
--- - Le problème peut être côté frontend si permissions OK
\ No newline at end of file
diff --git a/fix-production-permissions.sql b/fix-production-permissions.sql
deleted file mode 100644
index 32a09ef..0000000
--- a/fix-production-permissions.sql
+++ /dev/null
@@ -1,125 +0,0 @@
--- Script SQL COMPLET pour corriger les rôles ET permissions en production
--- Exécutez ce script sur votre base de données de production
-
--- ========================================
--- PARTIE 1: CORRECTION DES RÔLES
--- ========================================
-
--- Mise à jour des rôles avec les displayName français
-UPDATE roles SET display_name = 'Administrateur' WHERE name = 'admin';
-UPDATE roles SET display_name = 'Manager' WHERE name = 'manager';
-UPDATE roles SET display_name = 'Employé' WHERE name = 'employee' OR name = 'employé';
-UPDATE roles SET display_name = 'Directeur' WHERE name = 'directeur';
-
--- ========================================
--- PARTIE 2: CORRECTION DES PERMISSIONS
--- ========================================
-
--- Mise à jour des permissions avec les displayName français
-
--- Administration
-UPDATE permissions SET display_name = 'Administration système' WHERE name = 'system_admin';
-UPDATE permissions SET display_name = 'Configuration NocoDB' WHERE name = 'nocodb_config';
-
--- Calendrier
-UPDATE permissions SET display_name = 'Voir calendrier' WHERE name = 'calendar_read';
-UPDATE permissions SET display_name = 'Créer événements' WHERE name = 'calendar_create';
-UPDATE permissions SET display_name = 'Modifier calendrier' WHERE name = 'calendar_update';
-UPDATE permissions SET display_name = 'Supprimer événements' WHERE name = 'calendar_delete';
-
--- Tableau de bord
-UPDATE permissions SET display_name = 'Voir tableau de bord' WHERE name = 'dashboard_read';
-
--- Livraisons
-UPDATE permissions SET display_name = 'Voir livraisons' WHERE name = 'deliveries_read';
-UPDATE permissions SET display_name = 'Créer livraisons' WHERE name = 'deliveries_create';
-UPDATE permissions SET display_name = 'Modifier livraisons' WHERE name = 'deliveries_update';
-UPDATE permissions SET display_name = 'Supprimer livraisons' WHERE name = 'deliveries_delete';
-UPDATE permissions SET display_name = 'Valider livraisons' WHERE name = 'deliveries_validate';
-
--- Magasins
-UPDATE permissions SET display_name = 'Voir magasins' WHERE name = 'groups_read';
-UPDATE permissions SET display_name = 'Créer magasins' WHERE name = 'groups_create';
-UPDATE permissions SET display_name = 'Modifier magasins' WHERE name = 'groups_update';
-UPDATE permissions SET display_name = 'Supprimer magasins' WHERE name = 'groups_delete';
-
--- Commandes
-UPDATE permissions SET display_name = 'Voir commandes' WHERE name = 'orders_read';
-UPDATE permissions SET display_name = 'Créer commandes' WHERE name = 'orders_create';
-UPDATE permissions SET display_name = 'Modifier commandes' WHERE name = 'orders_update';
-UPDATE permissions SET display_name = 'Supprimer commandes' WHERE name = 'orders_delete';
-
--- Publicités
-UPDATE permissions SET display_name = 'Voir publicités' WHERE name = 'publicities_read';
-UPDATE permissions SET display_name = 'Créer publicités' WHERE name = 'publicities_create';
-UPDATE permissions SET display_name = 'Modifier publicités' WHERE name = 'publicities_update';
-UPDATE permissions SET display_name = 'Supprimer publicités' WHERE name = 'publicities_delete';
-UPDATE permissions SET display_name = 'Participer aux publicités' WHERE name = 'publicities_participate';
-
--- Rapprochement
-UPDATE permissions SET display_name = 'Voir rapprochements' WHERE name = 'reconciliation_read';
-UPDATE permissions SET display_name = 'Créer rapprochements' WHERE name = 'reconciliation_create';
-UPDATE permissions SET display_name = 'Modifier rapprochements' WHERE name = 'reconciliation_update';
-UPDATE permissions SET display_name = 'Supprimer rapprochements' WHERE name = 'reconciliation_delete';
-
--- Fournisseurs
-UPDATE permissions SET display_name = 'Voir fournisseurs' WHERE name = 'suppliers_read';
-UPDATE permissions SET display_name = 'Créer fournisseurs' WHERE name = 'suppliers_create';
-UPDATE permissions SET display_name = 'Modifier fournisseurs' WHERE name = 'suppliers_update';
-UPDATE permissions SET display_name = 'Supprimer fournisseurs' WHERE name = 'suppliers_delete';
-
--- Commandes clients
-UPDATE permissions SET display_name = 'Voir commandes clients' WHERE name = 'customer_orders_read';
-UPDATE permissions SET display_name = 'Créer commandes clients' WHERE name = 'customer_orders_create';
-UPDATE permissions SET display_name = 'Modifier commandes clients' WHERE name = 'customer_orders_update';
-UPDATE permissions SET display_name = 'Supprimer commandes clients' WHERE name = 'customer_orders_delete';
-UPDATE permissions SET display_name = 'Imprimer étiquettes' WHERE name = 'customer_orders_print';
-UPDATE permissions SET display_name = 'Notifier clients' WHERE name = 'customer_orders_notify';
-
--- Utilisateurs
-UPDATE permissions SET display_name = 'Voir utilisateurs' WHERE name = 'users_read';
-UPDATE permissions SET display_name = 'Créer utilisateurs' WHERE name = 'users_create';
-UPDATE permissions SET display_name = 'Modifier utilisateurs' WHERE name = 'users_update';
-UPDATE permissions SET display_name = 'Supprimer utilisateurs' WHERE name = 'users_delete';
-
--- Gestion des rôles
-UPDATE permissions SET display_name = 'Voir rôles' WHERE name = 'roles_read';
-UPDATE permissions SET display_name = 'Créer rôles' WHERE name = 'roles_create';
-UPDATE permissions SET display_name = 'Modifier rôles' WHERE name = 'roles_update';
-UPDATE permissions SET display_name = 'Supprimer rôles' WHERE name = 'roles_delete';
-
--- Gestion DLC (déjà corrects normalement)
-UPDATE permissions SET display_name = 'Voir produits DLC' WHERE name = 'dlc_read';
-UPDATE permissions SET display_name = 'Créer produits DLC' WHERE name = 'dlc_create';
-UPDATE permissions SET display_name = 'Modifier produits DLC' WHERE name = 'dlc_update';
-UPDATE permissions SET display_name = 'Supprimer produits DLC' WHERE name = 'dlc_delete';
-UPDATE permissions SET display_name = 'Valider produits DLC' WHERE name = 'dlc_validate';
-UPDATE permissions SET display_name = 'Imprimer étiquettes DLC' WHERE name = 'dlc_print';
-UPDATE permissions SET display_name = 'Voir statistiques DLC' WHERE name = 'dlc_stats';
-
--- Rapprochement BL
-UPDATE permissions SET display_name = 'Voir rapprochements BL' WHERE name = 'bl_reconciliation_read';
-UPDATE permissions SET display_name = 'Modifier rapprochements BL' WHERE name = 'bl_reconciliation_update';
-
--- ========================================
--- VÉRIFICATIONS FINALES
--- ========================================
-
--- Vérifier les rôles après mise à jour
-SELECT name, display_name FROM roles ORDER BY name;
-
--- Vérifier les permissions après mise à jour
-SELECT name, display_name, category FROM permissions ORDER BY category, name;
-
--- Compter les éléments corrigés
-SELECT
- 'RÔLES' as type,
- COUNT(*) as total,
- COUNT(CASE WHEN display_name != name THEN 1 END) as avec_traduction_francaise
-FROM roles
-UNION ALL
-SELECT
- 'PERMISSIONS' as type,
- COUNT(*) as total,
- COUNT(CASE WHEN display_name != name THEN 1 END) as avec_traduction_francaise
-FROM permissions;
\ No newline at end of file
diff --git a/fix-production-schema.sql b/fix-production-schema.sql
deleted file mode 100644
index 4b5c723..0000000
--- a/fix-production-schema.sql
+++ /dev/null
@@ -1,90 +0,0 @@
--- Script de migration pour synchroniser la base de données de production
--- avec le schéma de développement pour les catégories et permissions
-
--- 1. Mettre à jour les catégories en français
-UPDATE permissions SET category = 'calendrier' WHERE category = 'Calendar';
-UPDATE permissions SET category = 'tableau_de_bord' WHERE category = 'Dashboard';
-UPDATE permissions SET category = 'livraisons' WHERE category = 'Deliveries';
-UPDATE permissions SET category = 'commandes' WHERE category = 'Orders';
-UPDATE permissions SET category = 'publicites' WHERE category = 'Publicities';
-UPDATE permissions SET category = 'rapprochement' WHERE category = 'Reconciliation';
-UPDATE permissions SET category = 'fournisseurs' WHERE category = 'Suppliers';
-UPDATE permissions SET category = 'utilisateurs' WHERE category = 'Users';
-UPDATE permissions SET category = 'commandes_clients' WHERE category = 'customer_orders';
-UPDATE permissions SET category = 'magasins' WHERE category = 'groups';
-
--- 2. Ajouter les permissions tâches manquantes
-INSERT INTO permissions (name, display_name, description, category, action, resource, is_system, created_at) VALUES
-('tasks_read', 'Voir tâches', 'Accès en lecture aux tâches', 'gestion_taches', 'read', 'tasks', true, NOW()),
-('tasks_create', 'Créer tâches', 'Création de nouvelles tâches', 'gestion_taches', 'create', 'tasks', true, NOW()),
-('tasks_update', 'Modifier tâches', 'Modification de tâches existantes', 'gestion_taches', 'update', 'tasks', true, NOW()),
-('tasks_delete', 'Supprimer tâches', 'Suppression de tâches', 'gestion_taches', 'delete', 'tasks', true, NOW()),
-('tasks_assign', 'Assigner tâches', 'Attribution de tâches aux utilisateurs', 'gestion_taches', 'assign', 'tasks', true, NOW())
-ON CONFLICT (name) DO UPDATE SET
- display_name = EXCLUDED.display_name,
- description = EXCLUDED.description,
- category = EXCLUDED.category,
- action = EXCLUDED.action,
- resource = EXCLUDED.resource;
-
--- 3. Ajouter les permissions administration manquantes
-INSERT INTO permissions (name, display_name, description, category, action, resource, is_system, created_at) VALUES
-('system_admin', 'Administration système', 'Accès complet à l''administration du système', 'administration', 'admin', 'system', true, NOW()),
-('nocodb_config', 'Configuration NocoDB', 'Gestion de la configuration NocoDB', 'administration', 'config', 'nocodb', true, NOW())
-ON CONFLICT (name) DO UPDATE SET
- display_name = EXCLUDED.display_name,
- description = EXCLUDED.description,
- category = EXCLUDED.category,
- action = EXCLUDED.action,
- resource = EXCLUDED.resource;
-
--- 4. Assigner les permissions tâches aux rôles existants
-WITH task_permissions AS (
- SELECT id FROM permissions WHERE category = 'gestion_taches'
-),
-roles_info AS (
- SELECT id, name FROM roles WHERE name IN ('admin', 'manager', 'employee', 'directeur')
-)
-INSERT INTO role_permissions (role_id, permission_id, created_at)
-SELECT r.id, p.id, NOW()
-FROM roles_info r
-CROSS JOIN task_permissions p
-WHERE
- -- Admin et directeur ont toutes les permissions tâches
- (r.name IN ('admin', 'directeur'))
- OR
- -- Manager a read, create, update, assign
- (r.name = 'manager' AND EXISTS(SELECT 1 FROM permissions WHERE id = p.id AND name IN ('tasks_read', 'tasks_create', 'tasks_update', 'tasks_assign')))
- OR
- -- Employee a read, create, update
- (r.name = 'employee' AND EXISTS(SELECT 1 FROM permissions WHERE id = p.id AND name IN ('tasks_read', 'tasks_create', 'tasks_update')))
-ON CONFLICT (role_id, permission_id) DO NOTHING;
-
--- 5. Assigner les permissions administration aux administrateurs et directeurs
-WITH admin_permissions AS (
- SELECT id FROM permissions WHERE category = 'administration'
-),
-admin_roles AS (
- SELECT id FROM roles WHERE name IN ('admin', 'directeur')
-)
-INSERT INTO role_permissions (role_id, permission_id, created_at)
-SELECT r.id, p.id, NOW()
-FROM admin_roles r
-CROSS JOIN admin_permissions p
-ON CONFLICT (role_id, permission_id) DO NOTHING;
-
--- Vérification des résultats
-SELECT 'VERIFICATION - Catégories mises à jour:' as check_type, category, COUNT(*) as count
-FROM permissions
-GROUP BY category
-ORDER BY category;
-
-SELECT 'VERIFICATION - Permissions tâches:' as check_type, name, display_name, category
-FROM permissions
-WHERE category = 'gestion_taches'
-ORDER BY name;
-
-SELECT 'VERIFICATION - Permissions administration:' as check_type, name, display_name, category
-FROM permissions
-WHERE category = 'administration'
-ORDER BY name;
\ No newline at end of file
diff --git a/fix-production-tasks-permissions.sql b/fix-production-tasks-permissions.sql
deleted file mode 100644
index 5a6db7f..0000000
--- a/fix-production-tasks-permissions.sql
+++ /dev/null
@@ -1,122 +0,0 @@
--- Script SQL d'urgence pour corriger les permissions tâches en production
--- À exécuter manuellement sur la base de données de production
-
--- 1. Vérifier si les permissions tâches existent
-DO $$
-BEGIN
- -- Créer les permissions tâches si elles n'existent pas
- INSERT INTO permissions (name, display_name, description, category, action, resource, is_system)
- VALUES
- ('tasks_read', 'Voir tâches', 'Accès en lecture aux tâches', 'gestion_taches', 'read', 'tasks', true),
- ('tasks_create', 'Créer tâches', 'Création de nouvelles tâches', 'gestion_taches', 'create', 'tasks', true),
- ('tasks_update', 'Modifier tâches', 'Modification des tâches existantes', 'gestion_taches', 'update', 'tasks', true),
- ('tasks_delete', 'Supprimer tâches', 'Suppression des tâches', 'gestion_taches', 'delete', 'tasks', true),
- ('tasks_assign', 'Assigner tâches', 'Assignation des tâches aux utilisateurs', 'gestion_taches', 'assign', 'tasks', true)
- ON CONFLICT (name) DO UPDATE SET
- display_name = EXCLUDED.display_name,
- description = EXCLUDED.description,
- category = EXCLUDED.category;
-
- RAISE NOTICE 'Permissions tâches créées/mises à jour avec succès';
-END $$;
-
--- 2. Assigner les permissions aux rôles appropriés
-DO $$
-DECLARE
- admin_role_id INTEGER;
- manager_role_id INTEGER;
- employee_role_id INTEGER;
- directeur_role_id INTEGER;
- perm_read_id INTEGER;
- perm_create_id INTEGER;
- perm_update_id INTEGER;
- perm_delete_id INTEGER;
- perm_assign_id INTEGER;
-BEGIN
- -- Récupérer les IDs des rôles
- SELECT id INTO admin_role_id FROM roles WHERE name = 'admin';
- SELECT id INTO manager_role_id FROM roles WHERE name = 'manager';
- SELECT id INTO employee_role_id FROM roles WHERE name = 'employee';
- SELECT id INTO directeur_role_id FROM roles WHERE name = 'directeur';
-
- -- Récupérer les IDs des permissions tâches
- SELECT id INTO perm_read_id FROM permissions WHERE name = 'tasks_read';
- SELECT id INTO perm_create_id FROM permissions WHERE name = 'tasks_create';
- SELECT id INTO perm_update_id FROM permissions WHERE name = 'tasks_update';
- SELECT id INTO perm_delete_id FROM permissions WHERE name = 'tasks_delete';
- SELECT id INTO perm_assign_id FROM permissions WHERE name = 'tasks_assign';
-
- -- Assigner toutes les permissions tâches au rôle admin
- IF admin_role_id IS NOT NULL THEN
- INSERT INTO role_permissions (role_id, permission_id)
- VALUES
- (admin_role_id, perm_read_id),
- (admin_role_id, perm_create_id),
- (admin_role_id, perm_update_id),
- (admin_role_id, perm_delete_id),
- (admin_role_id, perm_assign_id)
- ON CONFLICT (role_id, permission_id) DO NOTHING;
- RAISE NOTICE 'Permissions tâches assignées au rôle admin (ID: %)', admin_role_id;
- END IF;
-
- -- Assigner permissions au rôle manager (read, create, update, assign)
- IF manager_role_id IS NOT NULL THEN
- INSERT INTO role_permissions (role_id, permission_id)
- VALUES
- (manager_role_id, perm_read_id),
- (manager_role_id, perm_create_id),
- (manager_role_id, perm_update_id),
- (manager_role_id, perm_assign_id)
- ON CONFLICT (role_id, permission_id) DO NOTHING;
- RAISE NOTICE 'Permissions tâches assignées au rôle manager (ID: %)', manager_role_id;
- END IF;
-
- -- Assigner permissions au rôle employee (read, create, update)
- IF employee_role_id IS NOT NULL THEN
- INSERT INTO role_permissions (role_id, permission_id)
- VALUES
- (employee_role_id, perm_read_id),
- (employee_role_id, perm_create_id),
- (employee_role_id, perm_update_id)
- ON CONFLICT (role_id, permission_id) DO NOTHING;
- RAISE NOTICE 'Permissions tâches assignées au rôle employee (ID: %)', employee_role_id;
- END IF;
-
- -- Assigner toutes les permissions au rôle directeur
- IF directeur_role_id IS NOT NULL THEN
- INSERT INTO role_permissions (role_id, permission_id)
- VALUES
- (directeur_role_id, perm_read_id),
- (directeur_role_id, perm_create_id),
- (directeur_role_id, perm_update_id),
- (directeur_role_id, perm_delete_id),
- (directeur_role_id, perm_assign_id)
- ON CONFLICT (role_id, permission_id) DO NOTHING;
- RAISE NOTICE 'Permissions tâches assignées au rôle directeur (ID: %)', directeur_role_id;
- END IF;
-
-END $$;
-
--- 3. Vérifier le résultat
-SELECT
- r.name as role_name,
- COUNT(rp.permission_id) as task_permissions_count
-FROM roles r
-LEFT JOIN role_permissions rp ON r.id = rp.role_id
-LEFT JOIN permissions p ON rp.permission_id = p.id AND p.category = 'gestion_taches'
-WHERE r.name IN ('admin', 'manager', 'employee', 'directeur')
-GROUP BY r.id, r.name
-ORDER BY r.name;
-
--- 4. Afficher toutes les permissions tâches pour vérification
-SELECT
- p.id,
- p.name,
- p.display_name,
- p.category,
- COUNT(rp.role_id) as assigned_to_roles_count
-FROM permissions p
-LEFT JOIN role_permissions rp ON p.id = rp.permission_id
-WHERE p.category = 'gestion_taches'
-GROUP BY p.id, p.name, p.display_name, p.category
-ORDER BY p.name;
\ No newline at end of file
diff --git a/fix-production-usergroups.sql b/fix-production-usergroups.sql
deleted file mode 100644
index 03aa0c0..0000000
--- a/fix-production-usergroups.sql
+++ /dev/null
@@ -1,9 +0,0 @@
--- Fix production user_groups table to add missing created_at column
--- This should be run on your production database
-
--- Add the missing created_at column to user_groups table
-ALTER TABLE user_groups
-ADD COLUMN IF NOT EXISTS created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
-
--- Verify the table structure
-\d user_groups;
\ No newline at end of file
diff --git a/fix-shadcn-react-imports.js b/fix-shadcn-react-imports.js
deleted file mode 100644
index 5d0ec52..0000000
--- a/fix-shadcn-react-imports.js
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/env node
-
-const fs = require('fs');
-const path = require('path');
-
-// Script pour corriger automatiquement tous les imports React dans shadcn/ui
-const uiComponentsDir = path.join(__dirname, 'client/src/components/ui');
-
-function fixReactImports(filePath) {
- let content = fs.readFileSync(filePath, 'utf8');
- let modified = false;
-
- // Remplacer les imports React namespace
- if (content.includes('import * as React from "react"')) {
- // Analyser quels hooks React sont utilisés
- const reactHooks = [];
- if (content.includes('React.useState')) reactHooks.push('useState');
- if (content.includes('React.useEffect')) reactHooks.push('useEffect');
- if (content.includes('React.useContext')) reactHooks.push('useContext');
- if (content.includes('React.useCallback')) reactHooks.push('useCallback');
- if (content.includes('React.useMemo')) reactHooks.push('useMemo');
- if (content.includes('React.useRef')) reactHooks.push('useRef');
- if (content.includes('React.useId')) reactHooks.push('useId');
- if (content.includes('React.forwardRef')) reactHooks.push('forwardRef');
- if (content.includes('React.createContext')) reactHooks.push('createContext');
-
- // Créer le nouvel import
- const uniqueHooks = [...new Set(reactHooks)];
- const newImport = uniqueHooks.length > 0
- ? `import React, { ${uniqueHooks.join(', ')} } from "react"`
- : `import React from "react"`;
-
- content = content.replace('import * as React from "react"', newImport);
-
- // Remplacer les usages React.hook par hook direct
- uniqueHooks.forEach(hook => {
- const regex = new RegExp(`React\\.${hook}`, 'g');
- content = content.replace(regex, hook);
- });
-
- modified = true;
- }
-
- if (modified) {
- fs.writeFileSync(filePath, content);
- console.log(`✓ Fixed: ${path.relative(__dirname, filePath)}`);
- return true;
- }
-
- return false;
-}
-
-function processDirectory(dirPath) {
- const items = fs.readdirSync(dirPath);
- let totalFixed = 0;
-
- for (const item of items) {
- const itemPath = path.join(dirPath, item);
- const stat = fs.statSync(itemPath);
-
- if (stat.isDirectory()) {
- totalFixed += processDirectory(itemPath);
- } else if (item.endsWith('.tsx') || item.endsWith('.ts')) {
- if (fixReactImports(itemPath)) {
- totalFixed++;
- }
- }
- }
-
- return totalFixed;
-}
-
-console.log('🔧 Fixing React imports in shadcn/ui components...');
-const fixed = processDirectory(uiComponentsDir);
-console.log(`✅ Fixed ${fixed} files`);
\ No newline at end of file
diff --git a/init.sql b/init.sql
deleted file mode 100644
index e75cdb2..0000000
--- a/init.sql
+++ /dev/null
@@ -1,303 +0,0 @@
--- Script d'initialisation complète de la base de données LogiFlow
-
--- Suppression des tables existantes (dans l'ordre des dépendances)
-DROP TABLE IF EXISTS user_roles CASCADE;
-DROP TABLE IF EXISTS role_permissions CASCADE;
-DROP TABLE IF EXISTS user_groups CASCADE;
-DROP TABLE IF EXISTS publicity_participations CASCADE;
-DROP TABLE IF EXISTS customer_orders CASCADE;
-DROP TABLE IF EXISTS deliveries CASCADE;
-DROP TABLE IF EXISTS orders CASCADE;
-DROP TABLE IF EXISTS publicities CASCADE;
-DROP TABLE IF EXISTS dlc_products CASCADE;
-DROP TABLE IF EXISTS tasks CASCADE;
-DROP TABLE IF EXISTS suppliers CASCADE;
-DROP TABLE IF EXISTS groups CASCADE;
-DROP TABLE IF EXISTS permissions CASCADE;
-DROP TABLE IF EXISTS roles CASCADE;
-DROP TABLE IF EXISTS nocodb_config CASCADE;
-DROP TABLE IF EXISTS users CASCADE;
-DROP TABLE IF EXISTS sessions CASCADE;
-
--- Création de la table sessions (obligatoire pour l'authentification)
-CREATE TABLE sessions (
- sid VARCHAR PRIMARY KEY,
- sess JSONB NOT NULL,
- expire TIMESTAMP NOT NULL
-);
-
-CREATE INDEX IDX_session_expire ON sessions(expire);
-
--- Création de la table users
-CREATE TABLE users (
- id VARCHAR PRIMARY KEY NOT NULL,
- username VARCHAR UNIQUE NOT NULL,
- email VARCHAR UNIQUE,
- name VARCHAR,
- first_name VARCHAR,
- last_name VARCHAR,
- profile_image_url VARCHAR,
- password VARCHAR,
- role VARCHAR NOT NULL DEFAULT 'employee',
- password_changed BOOLEAN DEFAULT FALSE,
- created_at TIMESTAMP DEFAULT NOW(),
- updated_at TIMESTAMP DEFAULT NOW()
-);
-
--- Création de la table groups (magasins)
-CREATE TABLE groups (
- id SERIAL PRIMARY KEY,
- name VARCHAR NOT NULL,
- color VARCHAR DEFAULT '#3b82f6',
- address TEXT,
- phone VARCHAR,
- email VARCHAR,
- nocodb_config_id INTEGER,
- nocodb_table_id VARCHAR,
- nocodb_table_name VARCHAR,
- invoice_column_name VARCHAR DEFAULT 'Ref Facture',
- created_at TIMESTAMP DEFAULT NOW(),
- updated_at TIMESTAMP DEFAULT NOW()
-);
-
--- Création de la table nocodb_config
-CREATE TABLE nocodb_config (
- id SERIAL PRIMARY KEY,
- name VARCHAR NOT NULL,
- base_url VARCHAR NOT NULL,
- project_id VARCHAR NOT NULL,
- api_token VARCHAR NOT NULL,
- description TEXT,
- is_active BOOLEAN DEFAULT TRUE,
- created_by VARCHAR NOT NULL,
- created_at TIMESTAMP DEFAULT NOW(),
- updated_at TIMESTAMP DEFAULT NOW()
-);
-
--- Création de la table suppliers
-CREATE TABLE suppliers (
- id SERIAL PRIMARY KEY,
- name VARCHAR NOT NULL,
- contact VARCHAR,
- phone VARCHAR,
- has_dlc BOOLEAN DEFAULT FALSE,
- created_at TIMESTAMP DEFAULT NOW(),
- updated_at TIMESTAMP DEFAULT NOW()
-);
-
--- Création de la table orders
-CREATE TABLE orders (
- id SERIAL PRIMARY KEY,
- supplier_id INTEGER NOT NULL,
- group_id INTEGER NOT NULL,
- planned_date DATE NOT NULL,
- quantity INTEGER,
- unit VARCHAR,
- status VARCHAR NOT NULL DEFAULT 'pending',
- notes TEXT,
- created_by VARCHAR NOT NULL,
- created_at TIMESTAMP DEFAULT NOW(),
- updated_at TIMESTAMP DEFAULT NOW()
-);
-
--- Création de la table deliveries
-CREATE TABLE deliveries (
- id SERIAL PRIMARY KEY,
- order_id INTEGER,
- supplier_id INTEGER NOT NULL,
- group_id INTEGER NOT NULL,
- scheduled_date DATE NOT NULL,
- delivered_date TIMESTAMP,
- quantity INTEGER NOT NULL,
- unit VARCHAR NOT NULL,
- status VARCHAR NOT NULL DEFAULT 'planned',
- notes TEXT,
- bl_number VARCHAR,
- bl_amount DECIMAL(10,2),
- invoice_reference VARCHAR,
- invoice_amount DECIMAL(10,2),
- reconciled BOOLEAN DEFAULT FALSE,
- validated_at TIMESTAMP,
- created_by VARCHAR NOT NULL,
- created_at TIMESTAMP DEFAULT NOW(),
- updated_at TIMESTAMP DEFAULT NOW()
-);
-
--- Création de la table publicities
-CREATE TABLE publicities (
- id SERIAL PRIMARY KEY,
- pub_number VARCHAR NOT NULL UNIQUE,
- designation TEXT NOT NULL,
- title VARCHAR,
- description TEXT,
- start_date DATE NOT NULL,
- end_date DATE NOT NULL,
- year INTEGER NOT NULL,
- created_by VARCHAR NOT NULL,
- created_at TIMESTAMP DEFAULT NOW(),
- updated_at TIMESTAMP DEFAULT NOW()
-);
-
--- Création de la table customer_orders
-CREATE TABLE customer_orders (
- id SERIAL PRIMARY KEY,
- order_taker VARCHAR NOT NULL,
- customer_name VARCHAR NOT NULL,
- customer_phone VARCHAR NOT NULL,
- customer_email VARCHAR,
- product_designation TEXT NOT NULL,
- product_reference VARCHAR,
- gencode VARCHAR NOT NULL,
- quantity INTEGER NOT NULL DEFAULT 1,
- supplier_id INTEGER NOT NULL,
- status VARCHAR NOT NULL DEFAULT 'En attente de Commande',
- deposit DECIMAL(10,2) DEFAULT 0.00,
- is_promotional_price BOOLEAN DEFAULT FALSE,
- customer_notified BOOLEAN DEFAULT FALSE,
- notes TEXT,
- group_id INTEGER NOT NULL,
- created_by VARCHAR NOT NULL,
- created_at TIMESTAMP DEFAULT NOW(),
- updated_at TIMESTAMP DEFAULT NOW()
-);
-
--- Création de la table dlc_products
-CREATE TABLE dlc_products (
- id SERIAL PRIMARY KEY,
- name VARCHAR NOT NULL,
- gencode VARCHAR,
- dlc_date DATE,
- quantity INTEGER,
- store_id INTEGER,
- created_at TIMESTAMP DEFAULT NOW()
-);
-
--- Création de la table tasks
-CREATE TABLE tasks (
- id SERIAL PRIMARY KEY,
- title VARCHAR NOT NULL,
- description TEXT,
- assigned_to VARCHAR,
- due_date DATE,
- priority VARCHAR DEFAULT 'medium',
- status VARCHAR DEFAULT 'todo',
- completed_by INTEGER,
- completed_at TIMESTAMP,
- store_id INTEGER,
- created_at TIMESTAMP DEFAULT NOW(),
- updated_at TIMESTAMP DEFAULT NOW()
-);
-
--- Création de la table roles
-CREATE TABLE roles (
- id SERIAL PRIMARY KEY,
- name VARCHAR NOT NULL UNIQUE,
- display_name VARCHAR NOT NULL,
- description TEXT,
- color VARCHAR DEFAULT '#6b7280',
- is_system BOOLEAN DEFAULT FALSE,
- is_active BOOLEAN DEFAULT TRUE,
- created_at TIMESTAMP DEFAULT NOW(),
- updated_at TIMESTAMP DEFAULT NOW()
-);
-
--- Création de la table permissions
-CREATE TABLE permissions (
- id SERIAL PRIMARY KEY,
- name VARCHAR NOT NULL UNIQUE,
- display_name VARCHAR NOT NULL,
- description TEXT,
- category VARCHAR NOT NULL,
- action VARCHAR NOT NULL,
- resource VARCHAR NOT NULL,
- is_system BOOLEAN DEFAULT TRUE,
- created_at TIMESTAMP DEFAULT NOW()
-);
-
--- Tables de liaison (many-to-many)
-CREATE TABLE user_groups (
- user_id VARCHAR NOT NULL,
- group_id INTEGER NOT NULL,
- created_at TIMESTAMP DEFAULT NOW(),
- PRIMARY KEY (user_id, group_id)
-);
-
-CREATE TABLE user_roles (
- user_id VARCHAR NOT NULL,
- role_id INTEGER NOT NULL,
- created_at TIMESTAMP DEFAULT NOW(),
- PRIMARY KEY (user_id, role_id)
-);
-
-CREATE TABLE role_permissions (
- role_id INTEGER NOT NULL,
- permission_id INTEGER NOT NULL,
- created_at TIMESTAMP DEFAULT NOW(),
- PRIMARY KEY (role_id, permission_id)
-);
-
-CREATE TABLE publicity_participations (
- publicity_id INTEGER NOT NULL,
- group_id INTEGER NOT NULL,
- created_at TIMESTAMP DEFAULT NOW(),
- PRIMARY KEY (publicity_id, group_id)
-);
-
--- Insertion des données de base
-INSERT INTO users (id, username, password, email, first_name, last_name, name, role) VALUES
-('1', 'admin', 'ffcaa5ca840c66a9d52c9c9c0b7c28aeb2b16d7174c8b3b4a6f49c1f7e61b1c3:1000:32:0d2b7b5e6e4c2b3b3e6d2a9b7c5e8f1a0c3d6f9b2e5c8a1d4f7b0a3e6c9f2e5b8', 'admin@logiflow.com', 'Admin', 'System', 'Admin System', 'admin');
-
--- Les magasins sont créés par les utilisateurs via l'interface
--- Pas de magasins par défaut insérés automatiquement
-
-INSERT INTO suppliers (name, contact, phone) VALUES
-('Fournisseur Test 1', 'Jean Dupont', '01 23 45 67 89'),
-('Fournisseur Test 2', 'Marie Martin', '01 98 76 54 32');
-
--- Insertion des rôles de base
-INSERT INTO roles (name, display_name, description) VALUES
-('admin', 'Administrateur', 'Accès complet au système'),
-('manager', 'Manager', 'Gestion des opérations'),
-('employee', 'Employé', 'Accès de base'),
-('directeur', 'Directeur', 'Direction générale');
-
--- Insertion des permissions de base
-INSERT INTO permissions (name, display_name, category, action, resource) VALUES
-('dashboard_read', 'Voir le tableau de bord', 'dashboard', 'read', 'dashboard'),
-('orders_read', 'Voir les commandes', 'orders', 'read', 'orders'),
-('orders_create', 'Créer des commandes', 'orders', 'create', 'orders'),
-('orders_update', 'Modifier les commandes', 'orders', 'update', 'orders'),
-('orders_delete', 'Supprimer les commandes', 'orders', 'delete', 'orders'),
-('deliveries_read', 'Voir les livraisons', 'deliveries', 'read', 'deliveries'),
-('deliveries_create', 'Créer des livraisons', 'deliveries', 'create', 'deliveries'),
-('deliveries_update', 'Modifier les livraisons', 'deliveries', 'update', 'deliveries'),
-('deliveries_delete', 'Supprimer les livraisons', 'deliveries', 'delete', 'deliveries'),
-('suppliers_read', 'Voir les fournisseurs', 'suppliers', 'read', 'suppliers'),
-('suppliers_create', 'Créer des fournisseurs', 'suppliers', 'create', 'suppliers'),
-('suppliers_update', 'Modifier les fournisseurs', 'suppliers', 'update', 'suppliers'),
-('suppliers_delete', 'Supprimer les fournisseurs', 'suppliers', 'delete', 'suppliers'),
-('users_read', 'Voir les utilisateurs', 'users', 'read', 'users'),
-('users_create', 'Créer des utilisateurs', 'users', 'create', 'users'),
-('users_update', 'Modifier les utilisateurs', 'users', 'update', 'users'),
-('users_delete', 'Supprimer les utilisateurs', 'users', 'delete', 'users'),
-('groups_read', 'Voir les magasins', 'groups', 'read', 'groups'),
-('groups_create', 'Créer des magasins', 'groups', 'create', 'groups'),
-('groups_update', 'Modifier les magasins', 'groups', 'update', 'groups'),
-('groups_delete', 'Supprimer les magasins', 'groups', 'delete', 'groups'),
-('publicities_read', 'Voir les publicités', 'publicities', 'read', 'publicities'),
-('publicities_create', 'Créer des publicités', 'publicities', 'create', 'publicities');
-
--- Attribution de toutes les permissions au rôle admin
-INSERT INTO role_permissions (role_id, permission_id)
-SELECT r.id, p.id
-FROM roles r, permissions p
-WHERE r.name = 'admin';
-
--- Attribution du rôle admin à l'utilisateur admin
-INSERT INTO user_roles (user_id, role_id)
-SELECT u.id, r.id
-FROM users u, roles r
-WHERE u.username = 'admin' AND r.name = 'admin';
-
--- Les assignations aux magasins se font via l'interface utilisateur
--- Pas d'attribution automatique à un magasin par défaut
\ No newline at end of file
diff --git a/production-database-schema-export.txt b/production-database-schema-export.txt
deleted file mode 100644
index 0e912df..0000000
--- a/production-database-schema-export.txt
+++ /dev/null
@@ -1,138 +0,0 @@
-LOGIFLOW - SCHÉMA BASE DE DONNÉES PRODUCTION
-===============================================
-
-GÉNÉRÉ LE : ${new Date().toISOString()}
-SERVEUR : Production privé LogiFlow
-ENVIRONNEMENT : PostgreSQL Docker
-
-===============================================
-RÉSUMÉ DU SCAN DE SCHÉMA
-===============================================
-
-Le scan de schéma automatique est maintenant fonctionnel en production.
-URL d'accès : GET /api/debug/log-schema
-
-CORRECTIONS APPORTÉES :
-- Correction de l'accès direct au pool PostgreSQL
-- Remplacement de (storage as any).db.query par pool.query
-- Import direct de { db, pool } depuis ./db.ts
-- Vérification de disponibilité du pool avant utilisation
-
-FONCTIONNALITÉS :
-1. Liste complète des tables avec colonnes détaillées
-2. Types de données, contraintes NULL/NOT NULL
-3. Valeurs par défaut des colonnes
-4. Nombre d'enregistrements par table
-5. Contraintes de clés étrangères
-6. Relations entre tables
-
-ACCÈS SÉCURISÉ :
-- Réservé aux administrateurs uniquement
-- Fonctionne uniquement en production (NODE_ENV=production)
-- Authentification requise
-- Logs détaillés dans la console du serveur
-
-===============================================
-STRUCTURE PRÉVUE DES TABLES LOGIFLOW
-===============================================
-
-TABLES PRINCIPALES :
-- users : Gestion des utilisateurs et rôles
-- groups : Magasins/groupes de la chaîne
-- user_groups : Affectations utilisateurs-magasins
-- suppliers : Fournisseurs
-- orders : Commandes fournisseurs
-- deliveries : Livraisons
-- customer_orders : Commandes clients/caisse
-- publicities : Campagnes publicitaires
-- publicity_participations : Participation magasins aux publicités
-- dlc_products : Produits à date limite de consommation
-- tasks : Tâches et assignations
-- session : Sessions utilisateurs (connect-pg-simple)
-
-TABLES SYSTÈME :
-- nocodb_config : Configuration intégration NocoDB
-- database_backups : Historique sauvegardes
-
-===============================================
-RELATIONS CLÉS ATTENDUES
-===============================================
-
-users.id → orders.createdBy
-users.id → deliveries.createdBy
-users.id → customer_orders.createdBy
-users.id → tasks.assignedTo
-
-groups.id → orders.groupId
-groups.id → deliveries.groupId
-groups.id → customer_orders.groupId
-groups.id → user_groups.groupId
-
-suppliers.id → orders.supplierId
-suppliers.id → deliveries.supplierId
-
-orders.id → deliveries.orderId
-
-===============================================
-UTILISATION DU SCAN EN PRODUCTION
-===============================================
-
-ÉTAPES POUR SCANNER :
-1. Se connecter en tant qu'administrateur
-2. Aller sur /database-debug
-3. Cliquer sur "Scanner le Schéma de la Base"
-4. Consulter les logs du serveur pour le détail complet
-
-INFORMATIONS OBTENUES :
-- Structure exacte de toutes les tables
-- Nombre d'enregistrements réels
-- Contraintes et relations actives
-- Types de données PostgreSQL utilisés
-- Colonnes auto-générées et valeurs par défaut
-
-DÉBOGAGE :
-- Toutes les informations sont loggées dans la console serveur
-- Format lisible avec emojis et sections organisées
-- Timestamp de chaque scan pour traçabilité
-- Gestion d'erreurs détaillée
-
-===============================================
-NOTES TECHNIQUES
-===============================================
-
-POOL POSTGRESQL :
-- Configuration : max 10 connexions
-- Timeout idle : 30s
-- Timeout connexion : 5s
-- SSL désactivé (réseau interne Docker)
-
-REQUÊTES UTILISÉES :
-- information_schema.tables : Liste des tables
-- information_schema.columns : Détails des colonnes
-- information_schema.table_constraints : Contraintes FK
-- SELECT COUNT(*) : Nombre d'enregistrements
-
-SÉCURITÉ :
-- Pas d'exposition de données sensibles
-- Lecture seule (aucune modification)
-- Accès admin uniquement
-- Production uniquement
-
-===============================================
-HISTORIQUE DES CORRECTIONS
-===============================================
-
-PROBLÈME INITIAL :
-- Erreur : "Cannot read properties of undefined (reading 'query')"
-- Cause : (storage as any).db.query non disponible en production
-
-SOLUTION APPLIQUÉE :
-- Import direct : import { db, pool } from "./db"
-- Utilisation : pool.query() au lieu de storage.db.query()
-- Vérification : if (!pool) throw Error()
-- Test : Fonctionnel en production
-
-DATE : 12 août 2025
-STATUT : ✅ Résolu et fonctionnel
-
-===============================================
\ No newline at end of file
diff --git a/production-health-check.sh b/production-health-check.sh
deleted file mode 100644
index 3ce56dd..0000000
--- a/production-health-check.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/bash
-echo "=== DIAGNOSTIC PRODUCTION LOGIFLOW ==="
-echo "Date: $(date)"
-echo ""
-
-echo "1. Status PM2:"
-pm2 status 2>/dev/null || echo "PM2 non disponible"
-
-echo ""
-echo "2. Processes sur port 5000:"
-sudo lsof -i :5000 2>/dev/null || netstat -tulpn | grep :5000 2>/dev/null || echo "Aucun processus sur port 5000"
-
-echo ""
-echo "3. Status systemctl (si applicable):"
-sudo systemctl status logiflow 2>/dev/null || echo "Service systemctl non trouvé"
-
-echo ""
-echo "4. Status Docker (si applicable):"
-docker-compose ps 2>/dev/null || echo "Docker non utilisé"
-
-echo ""
-echo "5. Logs récents application:"
-if command -v pm2 &> /dev/null; then
- pm2 logs --lines 10 --nostream 2>/dev/null
-elif [ -f /var/log/logiflow.log ]; then
- tail -10 /var/log/logiflow.log
-else
- echo "Logs non trouvés"
-fi
-
-echo ""
-echo "6. Espace disque:"
-df -h /
-
-echo ""
-echo "7. Mémoire:"
-free -h
-
-echo ""
-echo "8. Variables d'environnement critiques:"
-echo "NODE_ENV: ${NODE_ENV:-'NON_DEFINI'}"
-echo "PORT: ${PORT:-'NON_DEFINI'}"
-echo "DATABASE_URL: ${DATABASE_URL:+DEFINI}"
-
-echo ""
-echo "9. Test de connectivité localhost:"
-curl -s -o /dev/null -w "%{http_code}" http://localhost:5000/api/health || echo "Service non accessible"
-
-echo ""
-echo "10. Processus Node.js actifs:"
-ps aux | grep node | grep -v grep || echo "Aucun processus Node.js"
-
-echo ""
-echo "=== FIN DIAGNOSTIC ==="
\ No newline at end of file
diff --git a/production-patch-employee-403.patch b/production-patch-employee-403.patch
deleted file mode 100644
index 67aca74..0000000
--- a/production-patch-employee-403.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-diff --git a/shared/permissions.ts b/shared/permissions.ts
-index 1234567..abcdefg 100644
---- a/shared/permissions.ts
-+++ b/shared/permissions.ts
-@@ -84,7 +84,7 @@ export const PERMISSIONS: Record> = {
- tasks: {
- admin: ['view', 'create', 'edit', 'delete', 'validate'],
- directeur: ['view', 'create', 'edit', 'delete', 'validate'],
- manager: ['view', 'validate'],
- employee: ['view'] // PAS DE CHANGEMENT - VOIR SEULEMENT
- }
- };
-
-diff --git a/server/routes.ts b/server/routes.ts
-index 1234567..abcdefg 100644
---- a/server/routes.ts
-+++ b/server/routes.ts
-@@ -188,7 +188,7 @@ export function createRoutes(app: Express, storage: IStorage, isAuthenticated:
- app.get('/api/suppliers', isAuthenticated, async (req: any, res) => {
- try {
- const user = await storage.getUser(req.user.claims ? req.user.claims.sub : req.user.id);
-- if (!user || (user.role !== 'admin' && user.role !== 'manager')) {
-+ if (!user || (user.role !== 'admin' && user.role !== 'manager' && user.role !== 'directeur' && user.role !== 'employee')) {
- return res.status(403).json({ message: "Insufficient permissions" });
- }
-
-@@ -240,7 +240,7 @@ export function createRoutes(app: Express, storage: IStorage, isAuthenticated:
- console.log('✅ User found:', { username: user.username, role: user.role });
-
- // Vérifier les permissions
-- if (user.role !== 'admin' && user.role !== 'manager') {
-+ if (user.role !== 'admin' && user.role !== 'manager' && user.role !== 'directeur') {
-- console.error('❌ Insufficient permissions:', { userRole: user.role, required: ['admin', 'manager'] });
-+ console.error('❌ Insufficient permissions:', { userRole: user.role, required: ['admin', 'manager', 'directeur'] });
- return res.status(403).json({ message: "Insufficient permissions" });
- }
-
-@@ -281,7 +281,7 @@ export function createRoutes(app: Express, storage: IStorage, isAuthenticated:
- app.put('/api/suppliers/:id', isAuthenticated, async (req: any, res) => {
- try {
- const user = await storage.getUser(req.user.claims ? req.user.claims.sub : req.user.id);
-- if (!user || (user.role !== 'admin' && user.role !== 'manager')) {
-+ if (!user || (user.role !== 'admin' && user.role !== 'manager' && user.role !== 'directeur')) {
- return res.status(403).json({ message: "Insufficient permissions" });
- }
-
-@@ -298,7 +298,7 @@ export function createRoutes(app: Express, storage: IStorage, isAuthenticated:
- app.delete('/api/suppliers/:id', isAuthenticated, async (req: any, res) => {
- try {
- const user = await storage.getUser(req.user.claims ? req.user.claims.sub : req.user.id);
-- if (!user || (user.role !== 'admin' && user.role !== 'manager')) {
-+ if (!user || (user.role !== 'admin' && user.role !== 'directeur')) {
- return res.status(403).json({ message: "Insufficient permissions" });
- }
-
-@@ -2332,7 +2332,7 @@ export function createRoutes(app: Express, storage: IStorage, isAuthenticated:
- const user = await storage.getUser(userId);
-
-- if (!user || !['admin', 'manager'].includes(user.role)) {
-+ if (!user || !['admin', 'manager', 'directeur'].includes(user.role)) {
- return res.status(403).json({ message: "Insufficient permissions to validate products" });
- }
\ No newline at end of file
diff --git a/production-users-debug.sql b/production-users-debug.sql
deleted file mode 100644
index cf8a83c..0000000
--- a/production-users-debug.sql
+++ /dev/null
@@ -1,37 +0,0 @@
--- Script de diagnostic pour résoudre le problème "Aucun utilisateur trouvé" en production
-
--- 1. Vérifier si la table users existe et contient des données
-SELECT 'Users table check' as diagnostic;
-SELECT COUNT(*) as user_count FROM users;
-SELECT id, username, email, role FROM users LIMIT 5;
-
--- 2. Vérifier la structure de la table users
-SELECT 'Users table structure' as diagnostic;
-\d users;
-
--- 3. Vérifier les connexions/permissions de base de données
-SELECT 'Database info' as diagnostic;
-SELECT current_database(), current_user, version();
-
--- 4. Vérifier la table groups
-SELECT 'Groups table check' as diagnostic;
-SELECT COUNT(*) as group_count FROM groups;
-SELECT id, name FROM groups LIMIT 5;
-
--- 5. Vérifier la table user_groups et sa structure
-SELECT 'User_groups table check' as diagnostic;
-SELECT COUNT(*) as user_group_count FROM user_groups;
-\d user_groups;
-
--- 6. Test de la requête utilisée par l'application
-SELECT 'Full user query test' as diagnostic;
-SELECT
- u.id,
- u.username,
- u.email,
- u.role,
- COUNT(ug.group_id) as groups_count
-FROM users u
-LEFT JOIN user_groups ug ON u.id = ug.user_id
-GROUP BY u.id, u.username, u.email, u.role
-LIMIT 5;
\ No newline at end of file
diff --git a/replit.md b/replit.md
index f386c9e..9c41415 100644
--- a/replit.md
+++ b/replit.md
@@ -1,74 +1,86 @@
-# LogiFlow - Replit Development Guide
+# Enterprise Weather Management Platform
-## Overview
-LogiFlow is a comprehensive logistics management platform for La Foir'Fouille retail stores. It centralizes order, delivery, customer order, inventory, and user administration across multiple store locations. Its business vision is to streamline logistics operations, enhance inventory accuracy, and improve overall operational efficiency for retail chains.
+## Project Overview
+Plateforme de gestion météorologique d'entreprise avec suivi logistique multi-tenant avancé et capacités complètes de gestion des commandes.
-## User Preferences
-Preferred communication style: Simple, everyday language.
+La plateforme fournit une gestion robuste des flux de travail de livraison avec des fonctionnalités de rapprochement améliorées, se concentrant sur l'efficacité opérationnelle grâce au suivi financier détaillé, aux contrôles d'accès granulaires et à la gestion sophistiquée des permissions.
-## System Architecture
+## Tech Stack
+- Frontend: React.js avec composants UI personnalisés (shadcn/ui)
+- Backend: Node.js Express (ESM)
+- API Météo: Visual Crossing
+- Gestion d'état: React Query
+- Base de données: PostgreSQL avec Drizzle ORM
+- Authentification: Gestion d'accès sécurisée basée sur les rôles
+- Validation: Schémas de validation Zod
+- Styling: Tailwind CSS
+- Déploiement: Docker
+- Localisation: Support français amélioré
-### Frontend
-- **Framework**: React 18 with TypeScript, Vite
-- **UI Framework**: Shadcn/ui (built on Radix UI), Tailwind CSS
-- **State Management**: TanStack Query (React Query)
-- **Routing**: Wouter
-- **Forms**: React Hook Form with Zod validation
-- **UI/UX Decisions**: Clean, intuitive interface using Shadcn/ui components for consistency and accessibility. Color schemes managed via Tailwind CSS custom variables for easy theming.
+## Recent Changes
-### Backend
-- **Framework**: Express.js with TypeScript, Node.js (ES modules)
-- **Database ORM**: Drizzle ORM
-- **Authentication**: Dual system (local for production, Replit Auth for development)
-- **Session Management**: Express sessions with PostgreSQL storage
-- **Security**: Comprehensive middleware (rate limiting, input sanitization, security headers)
+### 2025-08-12 - Nettoyage des fichiers inutiles
+✅ **Suppression complète des fichiers inutiles** effectuée pour optimiser le projet :
+
+**Fichiers supprimés :**
+- Fichiers de sauvegarde/cassés : `*_broken.tsx`, `*_backup.tsx`, `*.backup.*`
+- Dossier `attached_assets/` complet (captures d'écran et logs de débogage)
+- Documentation de débogage : tous les fichiers `*.md` de correction temporaire
+- Scripts de débogage : `debug-*.js`, `fix-*.sql`, `apply-production-fixes.js`
+- Scripts de test temporaires : `test-*.js`, `reset-admin.js`
+- Fichiers de production/debug : `production-*.txt`, `production-*.sh`, `production-*.patch`
+- Fichiers de cookies de test : `cookies.txt`, `cookies_employee.txt`
+
+**Fichiers conservés (essentiels) :**
+- `client/` - Frontend React complet
+- `server/` - Backend Express complet
+- `shared/` - Schémas partagés
+- `migrations/` - Migrations de base de données
+- Configuration : `package.json`, `vite.config.ts`, `tailwind.config.ts`, etc.
+- Déploiement : `Dockerfile`, `docker-compose.yml`
+
+## Project Architecture
+
+### Frontend Structure
+```
+client/src/
+├── components/ # Composants UI réutilisables
+├── pages/ # Pages principales de l'application
+├── hooks/ # Hooks React personnalisés
+├── lib/ # Utilitaires et clients
+└── main.tsx # Point d'entrée
+```
+
+### Backend Structure
+```
+server/
+├── index.ts # Serveur principal (développement)
+├── index.production.ts # Serveur production
+├── routes.ts # Routes API
+├── storage.ts # Couche d'accès aux données
+├── localAuth.ts # Authentification locale
+└── services/ # Services métier
+```
### Database
-- **Primary Database**: PostgreSQL with Drizzle ORM (Neon serverless for development, Docker for production)
-- **Schema**: Centralized definition in `shared/schema.ts`
-- **Migrations**: Drizzle Kit
+- PostgreSQL avec Drizzle ORM
+- Migrations gérées dans `migrations/`
+- Schémas définis dans `shared/schema.ts`
-### Core Business Entities
-- **Management**: Orders, Deliveries, Customer Orders, Suppliers, Publicities, DLC Products (limited shelf life), Tasks.
-- **Automatic Reconciliation**: Dual-mode BL/Invoice reconciliation system with automatic validation for designated suppliers.
+## User Preferences
+- Langue préférée : Français
+- Communication : Langue simple et accessible, éviter les détails techniques
+- Nettoyage : Préfère un projet optimisé sans fichiers inutiles
-### Data Flow
-- **Request Flow**: Client requests via React Query, processed by Express middleware for authentication/security, then by route handlers using Drizzle ORM for database operations.
-- **Authentication Flow**: Replit Auth for dev, secure username/password for production with PostgreSQL-backed sessions and role-based authorization.
-- **Data Synchronization**: Real-time updates via React Query with optimistic updates and intelligent cache invalidation. Global store context filters data.
+## Development Guidelines
+- Utiliser `npm run dev` pour lancer l'application
+- Les migrations sont gérées avec `npm run db:push`
+- Architecture full-stack JavaScript avec focus frontend
+- Validation des données avec Zod
+- UI avec shadcn/ui + Tailwind CSS
-### Key Features
-- **Authentication System**: Secure dual authentication with password hashing and session management.
-- **Multi-Store Management**: Global store context, role-based access control (admin, manager, employee, directeur), and data isolation.
-- **Universal Pagination**: Reusable client-side pagination component across all main tabular data pages.
-- **Reconciliation Module**: For balancing and tracking financial discrepancies. **PRODUCTION-READY**: Rebuilt with robust UI components to eliminate React #310 errors in production.
-- **Automatic Reconciliation System**: Dual-mode BL/Invoice reconciliation with automatic validation for suppliers in automatic mode. Auto-validates deliveries when status = "delivered" AND BL number exists.
-- **Permission System**: Granular, hardcoded permissions (54 permissions across 12 categories, assigned to 4 roles) for improved performance and maintenance. **EMPLOYEE PERMISSIONS**: Employees can create customer orders and DLC products.
-- **User Management**: Comprehensive features including user deletion with ownership transfer, consistent name and email field handling, and robust password hashing. **EMPLOYEE CUSTOMER ORDERS FINAL**: Fixed critical groupId assignment bug where employees assigned to store #2 were creating customer orders for store #1. Root cause was missing userGroups in /api/user response + form defaultValues override logic. Implemented proper group prioritization in both defaultValues and removed override logic in handleSubmit.
-- **Calendar Synchronization**: Proper display of delivery dates and automatic synchronization of order statuses.
-- **Database Schema Download**: Admin-only feature to download comprehensive database structure reports.
-- **DLC Product Management**: **PRODUCTION-READY**: Corrected MemStorage implementation for proper DLC persistence in development. Cache invalidation fixed with exact:false for production compatibility. **GROUPID-FIX-FINAL**: Resolved issue where users assigned to store #2 were creating DLC products for store #1 by implementing dual-layer groupId fallback logic (frontend + backend security).
-- **Robust UI Architecture**: Critical pages rebuilt with custom Tailwind CSS components to eliminate shadcn/ui production bundling issues.
-
-## External Dependencies
-
-### Frontend Dependencies
-- **UI Components**: Radix UI
-- **Form Management**: React Hook Form, Zod
-- **Date Handling**: date-fns
-- **Query Management**: TanStack Query
-- **Barcode Generation**: JsBarcode
-
-### Backend Dependencies
-- **Database**: PostgreSQL (pg driver), Drizzle ORM
-- **Authentication**: Passport.js (local strategy), connect-pg-simple
-- **Security**: express-rate-limit, helmet equivalent
-- **Validation**: Zod
-
-### Development Dependencies
-- **Build Tools**: Vite (React plugin, TypeScript support)
-- **Code Quality**: ESLint, TypeScript compiler
-- **Development Server**: Vite dev server
-
-### Other Integrations
-- **NocoDB Integration**: Configurable for invoice verification and data synchronization.
\ No newline at end of file
+## Notes
+- L'application utilise un système de stockage en mémoire pour le développement
+- Support multi-tenant avec gestion des groupes et permissions
+- Interface météorologique simplifiée intégrée
+- Système d'authentification unifié pour développement et production
\ No newline at end of file
diff --git a/reset-admin.js b/reset-admin.js
deleted file mode 100644
index 827af71..0000000
--- a/reset-admin.js
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env node
-
-// Script pour réinitialiser le mot de passe admin en production
-// Usage: node reset-admin.js [URL_PRODUCTION]
-
-const url = process.argv[2] || 'http://localhost:3000';
-const endpoint = `${url}/api/emergency-admin-reset`;
-
-const resetPassword = async () => {
- try {
- console.log(`🔄 Tentative de réinitialisation admin sur ${url}...`);
-
- const response = await fetch(endpoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- secret: 'logiflow-admin-reset-2025'
- })
- });
-
- const result = await response.json();
-
- if (response.ok) {
- console.log('✅ Succès:', result.message);
- console.log('📋 ID Admin:', result.adminId);
- console.log('🔑 Identifiants: admin/admin');
- } else {
- console.error('❌ Erreur:', result.error);
- }
- } catch (error) {
- console.error('❌ Erreur de connexion:', error.message);
- }
-};
-
-resetPassword();
\ No newline at end of file
diff --git a/test-create-user-production.js b/test-create-user-production.js
deleted file mode 100644
index 5f6919e..0000000
--- a/test-create-user-production.js
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Script de test pour la création d'utilisateur en production
- * Usage: node test-create-user-production.js
- */
-
-const https = require('https');
-const fs = require('fs');
-
-const config = {
- hostname: process.env.PRODUCTION_HOST || 'your-domain.com',
- port: 443,
- headers: {
- 'Content-Type': 'application/json',
- 'Cookie': process.env.SESSION_COOKIE || ''
- }
-};
-
-// Test data
-const testUser = {
- username: `test_${Date.now()}`,
- email: `test_${Date.now()}@example.com`,
- firstName: 'Test',
- lastName: 'User',
- password: 'TestPassword123',
- role: 'employee'
-};
-
-console.log('🔍 Testing user creation in production...');
-console.log('📊 Test user data:', JSON.stringify(testUser, null, 2));
-
-const postData = JSON.stringify(testUser);
-
-const options = {
- ...config,
- path: '/api/users',
- method: 'POST',
- headers: {
- ...config.headers,
- 'Content-Length': Buffer.byteLength(postData)
- }
-};
-
-const req = https.request(options, (res) => {
- console.log(`📡 Response status: ${res.statusCode}`);
- console.log('📡 Response headers:', res.headers);
-
- let data = '';
- res.on('data', (chunk) => {
- data += chunk;
- });
-
- res.on('end', () => {
- try {
- const response = JSON.parse(data);
- if (res.statusCode === 200 || res.statusCode === 201) {
- console.log('✅ User created successfully!');
- console.log('👤 New user:', response);
- } else {
- console.log('❌ User creation failed');
- console.log('📄 Error response:', response);
- }
- } catch (error) {
- console.log('❌ Failed to parse response:', data);
- }
- });
-});
-
-req.on('error', (error) => {
- console.error('❌ Request error:', error);
-});
-
-req.write(postData);
-req.end();
-
-// Also test the users endpoint
-setTimeout(() => {
- console.log('\n🔍 Testing users list endpoint...');
-
- const getUsersOptions = {
- ...config,
- path: '/api/users',
- method: 'GET'
- };
-
- const getUsersReq = https.request(getUsersOptions, (res) => {
- console.log(`📡 Users list status: ${res.statusCode}`);
-
- let data = '';
- res.on('data', (chunk) => {
- data += chunk;
- });
-
- res.on('end', () => {
- try {
- const users = JSON.parse(data);
- if (Array.isArray(users)) {
- console.log(`✅ Found ${users.length} users`);
- console.log('👥 Users:', users.map(u => ({ username: u.username, role: u.role, groups: u.userGroups?.length || 0 })));
- } else {
- console.log('❌ Invalid users response:', users);
- }
- } catch (error) {
- console.log('❌ Failed to parse users response:', data);
- }
- });
- });
-
- getUsersReq.on('error', (error) => {
- console.error('❌ Users request error:', error);
- });
-
- getUsersReq.end();
-}, 2000);
\ No newline at end of file
diff --git a/test-employee-customer-creation.js b/test-employee-customer-creation.js
deleted file mode 100644
index 2680e50..0000000
--- a/test-employee-customer-creation.js
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Test simple pour vérifier la création de commandes client par employé
- */
-
-console.log('🔍 Test création commande client - Tous rôles');
-
-async function testCreation() {
- try {
- const fetch = require('node-fetch');
-
- console.log('\n=== TEST CRÉATION COMMANDE CLIENT ===');
-
- // 1. Login admin local
- console.log('1. Login admin...');
- const adminLogin = await fetch('http://localhost:5000/api/login', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ username: 'admin', password: 'admin' })
- });
-
- if (!adminLogin.ok) {
- console.log('❌ Admin login failed');
- return;
- }
-
- const adminCookies = adminLogin.headers.get('set-cookie');
- console.log('✅ Admin login OK');
-
- // 2. Test création commande admin
- console.log('\n2. Test création commande admin...');
- const testOrder = {
- customerName: 'Test Client Admin',
- contactNumber: '0123456789',
- productName: 'Produit Test',
- productDescription: 'Description test',
- quantity: 1,
- groupId: 1,
- isPickup: false,
- notes: 'Test admin'
- };
-
- const adminCreate = await fetch('http://localhost:5000/api/customer-orders', {
- method: 'POST',
- headers: {
- 'Cookie': adminCookies,
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(testOrder)
- });
-
- console.log('Status admin:', adminCreate.status);
- const adminResponse = await adminCreate.text();
-
- if (adminCreate.ok) {
- console.log('✅ Admin peut créer des commandes client');
- console.log('Réponse:', JSON.parse(adminResponse));
- } else {
- console.log('❌ Admin ne peut pas créer:', adminResponse);
- }
-
- // 3. Vérifier les logs du serveur
- console.log('\n3. Instructions pour vérifier en production:');
- console.log('- Ouvrir les logs du serveur');
- console.log('- Essayer de créer une commande en tant qu\'employé');
- console.log('- Regarder les messages console.log() de POST /api/customer-orders');
- console.log('- Vérifier s\'il y a des erreurs de validation Zod');
-
- } catch (error) {
- console.log('❌ Erreur test:', error.message);
- }
-}
-
-testCreation();
\ No newline at end of file
diff --git a/test-employee-customer-orders-final.js b/test-employee-customer-orders-final.js
deleted file mode 100644
index b43392a..0000000
--- a/test-employee-customer-orders-final.js
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Test final pour la création de commandes client par employé
- */
-
-console.log('🔍 Test Final - Création Commande Client Employé');
-
-async function testEmployeeCustomerOrder() {
- try {
- const fetch = require('node-fetch');
-
- console.log('\n=== TEST FINAL CRÉATION COMMANDE CLIENT ===');
-
- // 1. Login admin
- console.log('1. Test admin...');
- const adminLogin = await fetch('http://localhost:5000/api/login', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ username: 'admin', password: 'admin' })
- });
-
- if (!adminLogin.ok) {
- console.log('❌ Admin login failed');
- return;
- }
-
- const adminCookies = adminLogin.headers.get('set-cookie');
-
- // 2. Test création avec nouveau format
- const orderData = {
- customerName: 'Client Test Final',
- contactNumber: '0123456789',
- productName: 'Produit Test Final',
- quantity: 1,
- groupId: 1,
- isPickup: false,
- notes: 'Test final avec nouveau schema'
- };
-
- console.log('2. Envoi données:', orderData);
-
- const createOrder = await fetch('http://localhost:5000/api/customer-orders', {
- method: 'POST',
- headers: {
- 'Cookie': adminCookies,
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(orderData)
- });
-
- console.log('Status:', createOrder.status);
- const response = await createOrder.text();
-
- if (createOrder.ok) {
- console.log('✅ Commande créée avec succès');
- console.log('Réponse:', JSON.parse(response));
- } else {
- console.log('❌ Erreur création:', response);
- }
-
- console.log('\n3. Instructions pour test employé en production:');
- console.log('- Se connecter avec un compte employé');
- console.log('- Essayer de créer une commande client');
- console.log('- Vérifier les logs pour "Frontend submit data" et "Backend data mapped"');
- console.log('- Si erreur 403, vérifier que l\'employé est assigné au bon groupe');
-
- } catch (error) {
- console.log('❌ Erreur test:', error.message);
- }
-}
-
-testEmployeeCustomerOrder();
\ No newline at end of file
diff --git a/test-employee-customer-orders-production.js b/test-employee-customer-orders-production.js
deleted file mode 100644
index 09037fa..0000000
--- a/test-employee-customer-orders-production.js
+++ /dev/null
@@ -1,263 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Script de test pour diagnostiquer le problème de création de commandes client
- * avec le rôle employé en production
- */
-
-console.log('🔍 Test de diagnostic production - Commandes client employé');
-
-// Test local d'abord
-async function testLocal() {
- const fetch = require('node-fetch');
-
- console.log('\n=== TEST LOCAL (http://localhost:5000) ===');
-
- try {
- // 1. Connexion admin locale pour référence
- console.log('1. Test admin local...');
- const adminLogin = await fetch('http://localhost:5000/api/login', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ username: 'admin', password: 'admin' })
- });
-
- if (adminLogin.ok) {
- const adminCookies = adminLogin.headers.get('set-cookie');
- console.log('✅ Admin login local réussi');
-
- // Test création commande admin
- const testOrder = {
- customerName: 'Test Admin Local',
- contactNumber: '0123456789',
- productName: 'Test Produit Admin',
- productDescription: 'Description test admin',
- quantity: 1,
- groupId: 1, // Utiliser le premier groupe
- isPickup: false,
- notes: 'Test admin local'
- };
-
- const adminCreate = await fetch('http://localhost:5000/api/customer-orders', {
- method: 'POST',
- headers: {
- 'Cookie': adminCookies,
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(testOrder)
- });
-
- console.log('Status création admin:', adminCreate.status);
- if (adminCreate.ok) {
- console.log('✅ Admin peut créer des commandes client');
- } else {
- const error = await adminCreate.text();
- console.log('❌ Admin ne peut pas créer:', error);
- }
- } else {
- console.log('❌ Admin login local échoué');
- }
-
- } catch (error) {
- console.log('❌ Erreur test local:', error.message);
- }
-}
-
-// Instructions pour test production
-function showProductionInstructions() {
- console.log(`
-
-=== INSTRUCTIONS POUR TEST PRODUCTION ===
-
-1. Connectez-vous à votre serveur de production
-2. Modifiez les valeurs ci-dessous avec vos vraies données:
-
- export PROD_URL="https://votre-serveur-production.com"
- export EMPLOYEE_USERNAME="votre-employee-username"
- export EMPLOYEE_PASSWORD="votre-employee-password"
- export ADMIN_USERNAME="votre-admin-username"
- export ADMIN_PASSWORD="votre-admin-password"
-
-3. Ensuite exécutez ce script avec:
- node test-employee-customer-orders-production.js --production
-
-Le script va:
-✓ Tester la connexion admin (pour référence)
-✓ Tester la connexion employé
-✓ Comparer les réponses des deux rôles
-✓ Identifier le problème exact
-
-`);
-}
-
-// Test production (à exécuter avec les vraies données)
-async function testProduction() {
- const fetch = require('node-fetch');
-
- const PROD_URL = process.env.PROD_URL || 'https://your-production-server.com';
- const EMPLOYEE_USERNAME = process.env.EMPLOYEE_USERNAME;
- const EMPLOYEE_PASSWORD = process.env.EMPLOYEE_PASSWORD;
- const ADMIN_USERNAME = process.env.ADMIN_USERNAME;
- const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD;
-
- console.log('\n=== TEST PRODUCTION ===');
- console.log('URL:', PROD_URL);
-
- if (!EMPLOYEE_USERNAME || !EMPLOYEE_PASSWORD) {
- console.log('❌ Variables d\'environnement employé manquantes');
- showProductionInstructions();
- return;
- }
-
- try {
- // Test admin d'abord (pour référence)
- if (ADMIN_USERNAME && ADMIN_PASSWORD) {
- console.log('\n1. Test admin production...');
- const adminLogin = await fetch(\`\${PROD_URL}/api/login\`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ username: ADMIN_USERNAME, password: ADMIN_PASSWORD })
- });
-
- if (adminLogin.ok) {
- console.log('✅ Admin login production réussi');
- const adminCookies = adminLogin.headers.get('set-cookie');
-
- // Récupérer les groupes admin
- const groupsResponse = await fetch(\`\${PROD_URL}/api/groups\`, {
- headers: { 'Cookie': adminCookies }
- });
-
- if (groupsResponse.ok) {
- const groups = await groupsResponse.json();
- console.log(\`📋 Groupes disponibles: \${groups.length}\`);
-
- if (groups.length > 0) {
- // Test création commande admin
- const testOrder = {
- customerName: 'Test Admin Production',
- contactNumber: '0123456789',
- productName: 'Test Produit Admin Prod',
- productDescription: 'Description test admin production',
- quantity: 1,
- groupId: groups[0].id,
- isPickup: false,
- notes: 'Test admin production'
- };
-
- const adminCreate = await fetch(\`\${PROD_URL}/api/customer-orders\`, {
- method: 'POST',
- headers: {
- 'Cookie': adminCookies,
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(testOrder)
- });
-
- console.log('Status création admin:', adminCreate.status);
- if (adminCreate.ok) {
- console.log('✅ Admin peut créer des commandes client en production');
- } else {
- const error = await adminCreate.text();
- console.log('❌ Admin ne peut pas créer:', error);
- }
- }
- }
- } else {
- console.log('❌ Admin login production échoué');
- }
- }
-
- // Test employé
- console.log('\n2. Test employé production...');
- const empLogin = await fetch(\`\${PROD_URL}/api/login\`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ username: EMPLOYEE_USERNAME, password: EMPLOYEE_PASSWORD })
- });
-
- if (empLogin.ok) {
- console.log('✅ Employé login production réussi');
- const empCookies = empLogin.headers.get('set-cookie');
-
- // Vérifier profil employé
- const userResponse = await fetch(\`\${PROD_URL}/api/user\`, {
- headers: { 'Cookie': empCookies }
- });
-
- if (userResponse.ok) {
- const user = await userResponse.json();
- console.log('👤 Profil employé:', {
- role: user.role,
- groupsCount: user.userGroups?.length || 0
- });
-
- if (user.userGroups && user.userGroups.length > 0) {
- // Test création commande employé
- const testOrder = {
- customerName: 'Test Employé Production',
- contactNumber: '0123456789',
- productName: 'Test Produit Employé Prod',
- productDescription: 'Description test employé production',
- quantity: 1,
- groupId: user.userGroups[0].groupId,
- isPickup: false,
- notes: 'Test employé production'
- };
-
- console.log('📦 Données test employé:', testOrder);
-
- const empCreate = await fetch(\`\${PROD_URL}/api/customer-orders\`, {
- method: 'POST',
- headers: {
- 'Cookie': empCookies,
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(testOrder)
- });
-
- console.log('Status création employé:', empCreate.status);
- const empResponse = await empCreate.text();
-
- if (empCreate.ok) {
- console.log('✅ Employé peut créer des commandes client en production');
- console.log('📋 Commande créée:', JSON.parse(empResponse));
- } else {
- console.log('❌ Employé ne peut pas créer:');
- console.log('Response:', empResponse);
-
- // Analyser l'erreur
- try {
- const errorObj = JSON.parse(empResponse);
- console.log('💡 Erreur structurée:', errorObj);
- } catch (e) {
- console.log('💡 Erreur texte brute:', empResponse);
- }
- }
- } else {
- console.log('❌ Employé n\'est assigné à aucun groupe');
- }
- } else {
- console.log('❌ Impossible de récupérer le profil employé');
- }
- } else {
- console.log('❌ Employé login production échoué');
- }
-
- } catch (error) {
- console.log('❌ Erreur test production:', error.message);
- }
-}
-
-// Exécution
-if (process.argv.includes('--production')) {
- testProduction();
-} else if (process.argv.includes('--local')) {
- testLocal();
-} else {
- console.log('Usage:');
- console.log(' node test-employee-customer-orders-production.js --local # Test local');
- console.log(' node test-employee-customer-orders-production.js --production # Test production');
- console.log('');
- showProductionInstructions();
-}
\ No newline at end of file
diff --git a/test-employee-production-final.js b/test-employee-production-final.js
deleted file mode 100644
index b2d1749..0000000
--- a/test-employee-production-final.js
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/usr/bin/env node
-
-// Test complet production pour employé - commandes client et DLC
-// Script pour reproduire les erreurs et identifier la cause exacte
-
-const testEmployeeProduction = async () => {
- console.log('🧪 TEST EMPLOYÉ PRODUCTION');
- console.log('========================');
-
- console.log('\n📋 Scénarios à tester:');
- console.log('1. ✅ Connexion employé');
- console.log('2. 🔍 Vérifier permissions frontend');
- console.log('3. 📝 Créer commande client');
- console.log('4. 🍃 Créer produit DLC');
- console.log('5. 📊 Vérifier affichage données');
-
- console.log('\n🔍 Debug Frontend (à faire dans DevTools):');
- console.log('1. Console.log user object complet');
- console.log('2. Vérifier hasPermission("customer-orders", "create")');
- console.log('3. Vérifier hasPermission("dlc", "create")');
- console.log('4. Logs requêtes POST qui échouent');
- console.log('5. Vérifier groupId envoyé dans requests');
-
- console.log('\n📤 Requête test commande client:');
- const testCustomerOrder = {
- customerName: "Test Client Production",
- contactNumber: "0123456789",
- productName: "Produit Test Employé",
- quantity: 1,
- groupId: 2, // Houdemont d'après les logs
- deposit: 0,
- isPromotionalPrice: false,
- notes: "Test création employé production"
- };
- console.log(JSON.stringify(testCustomerOrder, null, 2));
-
- console.log('\n📤 Requête test DLC:');
- const testDlc = {
- productName: "DLC Test Employé",
- dlcDate: "2025-08-25",
- dateType: "dlc",
- quantity: 1,
- unit: "Unité",
- supplierId: 1,
- location: "Test Location",
- groupId: 2, // Houdemont
- status: "en_cours"
- };
- console.log(JSON.stringify(testDlc, null, 2));
-
- console.log('\n⚠️ Points de contrôle:');
- console.log('1. Bouton "Créer" visible dans l\'interface?');
- console.log('2. Formulaire s\'ouvre sans erreur?');
- console.log('3. Soumission génère une requête HTTP?');
- console.log('4. Réponse serveur (200/400/403/500)?');
- console.log('5. Message d\'erreur affiché?');
-
- console.log('\n🔧 Solutions selon erreurs:');
- console.log('- 403 Forbidden: Problème permissions base');
- console.log('- 400 Bad Request: Problème validation schema');
- console.log('- 500 Server Error: Problème côté serveur');
- console.log('- Pas de requête: Problème frontend/permissions');
-
- console.log('\n📋 Checklist production déjà fait:');
- console.log('✅ Routes backend sans restrictions rôle');
- console.log('✅ Permissions définies dans shared/permissions.ts');
- console.log('✅ Schema validation corrigé');
- console.log('✅ Cache invalidation DLC avec exact:false');
-
- console.log('\n🎯 Actions immédiates:');
- console.log('1. Ouvrir DevTools > Console');
- console.log('2. Essayer créer commande client');
- console.log('3. Noter toute erreur console/réseau');
- console.log('4. Même test pour DLC');
- console.log('5. Envoyer logs complets pour debug');
-};
-
-console.log('🚀 Prêt pour test employé production');
-console.log('👉 Exécuter les étapes manuellement avec DevTools ouverts');
\ No newline at end of file
diff --git a/test-employee-supplier-access.js b/test-employee-supplier-access.js
deleted file mode 100644
index 569f5db..0000000
--- a/test-employee-supplier-access.js
+++ /dev/null
@@ -1,152 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Script de test pour vérifier l'accès des employés aux fournisseurs
- * À exécuter sur le serveur de production pour diagnostiquer les problèmes d'accès
- */
-
-const https = require('https');
-const fs = require('fs');
-
-// Configuration pour votre serveur de production
-const PRODUCTION_URL = process.env.PRODUCTION_URL || 'https://votre-serveur-production.com';
-const TEST_EMPLOYEE_CREDENTIALS = {
- username: process.env.TEST_EMPLOYEE_USERNAME || 'test_employee',
- password: process.env.TEST_EMPLOYEE_PASSWORD || 'password123'
-};
-
-console.log('🧪 === TEST D\'ACCÈS FOURNISSEURS POUR EMPLOYÉS ===\n');
-
-async function makeRequest(path, method = 'GET', data = null, cookies = '') {
- return new Promise((resolve, reject) => {
- const url = new URL(path, PRODUCTION_URL);
- const options = {
- hostname: url.hostname,
- port: url.port || (url.protocol === 'https:' ? 443 : 80),
- path: url.pathname + url.search,
- method: method,
- headers: {
- 'Content-Type': 'application/json',
- 'User-Agent': 'LogiFlow-Test-Script/1.0',
- ...(cookies ? { 'Cookie': cookies } : {}),
- ...(data ? { 'Content-Length': Buffer.byteLength(JSON.stringify(data)) } : {})
- }
- };
-
- const req = https.request(options, (res) => {
- let body = '';
- res.on('data', (chunk) => body += chunk);
- res.on('end', () => {
- try {
- const parsed = JSON.parse(body);
- resolve({
- status: res.statusCode,
- headers: res.headers,
- data: parsed
- });
- } catch (e) {
- resolve({
- status: res.statusCode,
- headers: res.headers,
- data: body
- });
- }
- });
- });
-
- req.on('error', reject);
-
- if (data) {
- req.write(JSON.stringify(data));
- }
-
- req.end();
- });
-}
-
-async function testEmployeeSupplierAccess() {
- try {
- console.log('1️⃣ Test de connexion employé...');
-
- // Étape 1: Se connecter avec un compte employé
- const loginResponse = await makeRequest('/api/login', 'POST', TEST_EMPLOYEE_CREDENTIALS);
-
- console.log(` Status: ${loginResponse.status}`);
- console.log(` Response: ${JSON.stringify(loginResponse.data, null, 2)}\n`);
-
- if (loginResponse.status !== 200) {
- console.error('❌ Échec de connexion employé');
- console.error(' Vérifiez que le compte employé existe et que les identifiants sont corrects');
- return;
- }
-
- // Extraire les cookies de session
- const setCookieHeaders = loginResponse.headers['set-cookie'] || [];
- const cookies = setCookieHeaders.join('; ');
-
- console.log('2️⃣ Test d\'accès aux fournisseurs...');
-
- // Étape 2: Tester l'accès à la liste des fournisseurs
- const suppliersResponse = await makeRequest('/api/suppliers', 'GET', null, cookies);
-
- console.log(` Status: ${suppliersResponse.status}`);
- console.log(` Response: ${JSON.stringify(suppliersResponse.data, null, 2)}\n`);
-
- if (suppliersResponse.status === 200) {
- console.log('✅ SUCCÈS: L\'employé peut accéder aux fournisseurs');
- console.log(` Nombre de fournisseurs retournés: ${Array.isArray(suppliersResponse.data) ? suppliersResponse.data.length : 'N/A'}`);
- } else if (suppliersResponse.status === 403) {
- console.log('❌ ÉCHEC: L\'employé n\'a pas l\'autorisation d\'accéder aux fournisseurs');
- console.log(' Le problème est confirmé - permissions insuffisantes');
- } else {
- console.log(`⚠️ ERREUR INATTENDUE: Status ${suppliersResponse.status}`);
- }
-
- console.log('\n3️⃣ Test d\'accès aux fournisseurs DLC...');
-
- // Étape 3: Tester l'accès aux fournisseurs DLC spécifiquement
- const dlcSuppliersResponse = await makeRequest('/api/suppliers?dlc=true', 'GET', null, cookies);
-
- console.log(` Status: ${dlcSuppliersResponse.status}`);
- console.log(` Response: ${JSON.stringify(dlcSuppliersResponse.data, null, 2)}\n`);
-
- if (dlcSuppliersResponse.status === 200) {
- console.log('✅ SUCCÈS: L\'employé peut accéder aux fournisseurs DLC');
- console.log(` Nombre de fournisseurs DLC retournés: ${Array.isArray(dlcSuppliersResponse.data) ? dlcSuppliersResponse.data.length : 'N/A'}`);
- } else if (dlcSuppliersResponse.status === 403) {
- console.log('❌ ÉCHEC: L\'employé n\'a pas l\'autorisation d\'accéder aux fournisseurs DLC');
- }
-
- // Résumé final
- console.log('\n📊 === RÉSUMÉ DU TEST ===');
- console.log(`Connexion employé: ${loginResponse.status === 200 ? '✅ OK' : '❌ ÉCHEC'}`);
- console.log(`Accès fournisseurs: ${suppliersResponse.status === 200 ? '✅ OK' : '❌ ÉCHEC'}`);
- console.log(`Accès fournisseurs DLC: ${dlcSuppliersResponse.status === 200 ? '✅ OK' : '❌ ÉCHEC'}`);
-
- if (suppliersResponse.status === 200 && dlcSuppliersResponse.status === 200) {
- console.log('\n🎉 TOUS LES TESTS PASSÉS - L\'accès employé aux fournisseurs fonctionne correctement');
- } else {
- console.log('\n⚠️ PROBLÈME DÉTECTÉ - Vérifiez les permissions serveur et la configuration des rôles');
- }
-
- } catch (error) {
- console.error('💥 Erreur lors du test:', error.message);
- console.error(' Vérifiez que le serveur de production est accessible');
- }
-}
-
-// Instructions d'utilisation
-console.log('📋 Instructions:');
-console.log('1. Assurez-vous d\'avoir un compte employé de test');
-console.log('2. Configurez les variables d\'environnement si nécessaire:');
-console.log(' - PRODUCTION_URL=https://votre-serveur.com');
-console.log(' - TEST_EMPLOYEE_USERNAME=nom_utilisateur');
-console.log(' - TEST_EMPLOYEE_PASSWORD=mot_de_passe');
-console.log('3. Exécutez: node test-employee-supplier-access.js\n');
-
-// Exécuter le test si le script est appelé directement
-if (require.main === module) {
- testEmployeeSupplierAccess().catch(console.error);
-}
-
-module.exports = { testEmployeeSupplierAccess };
\ No newline at end of file
diff --git a/test-sync-production.js b/test-sync-production.js
deleted file mode 100644
index c565b21..0000000
--- a/test-sync-production.js
+++ /dev/null
@@ -1,46 +0,0 @@
-// Script pour tester la synchronisation directement en production
-const https = require('https');
-
-const data = JSON.stringify({});
-
-const options = {
- hostname: 'logiflow-logiflow-1.c-2.us-east-2.aws.neon.tech',
- port: 443,
- path: '/api/sync-order-delivery-status',
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'Content-Length': Buffer.byteLength(data),
- // Vous devez remplacer par votre cookie de session réel
- 'Cookie': 'connect.sid=VOTRE_SESSION_COOKIE_ICI'
- }
-};
-
-console.log('🔄 Testing production sync API...');
-
-const req = https.request(options, (res) => {
- console.log(`Status: ${res.statusCode}`);
- console.log(`Headers:`, res.headers);
-
- let responseData = '';
- res.on('data', (chunk) => {
- responseData += chunk;
- });
-
- res.on('end', () => {
- console.log('Response:', responseData);
- try {
- const parsed = JSON.parse(responseData);
- console.log('✅ Sync result:', JSON.stringify(parsed, null, 2));
- } catch (e) {
- console.log('Raw response:', responseData);
- }
- });
-});
-
-req.on('error', (error) => {
- console.error('❌ Error:', error);
-});
-
-req.write(data);
-req.end();
\ No newline at end of file
diff --git a/test-user-groups.js b/test-user-groups.js
deleted file mode 100644
index 228816c..0000000
--- a/test-user-groups.js
+++ /dev/null
@@ -1,36 +0,0 @@
-// Test script pour vérifier l'attribution des groupes en production
-// À exécuter avec: node test-user-groups.js
-
-import { storage } from './server/storage.js';
-
-async function testUserGroups() {
- try {
- console.log('🧪 Test d\'attribution des groupes...');
-
- // Test data
- const testUserGroup = {
- userId: 'test_user_123',
- groupId: 1
- };
-
- console.log('📝 Tentative d\'attribution du groupe:', testUserGroup);
-
- const result = await storage.assignUserToGroup(testUserGroup);
-
- console.log('✅ Attribution réussie:', result);
- console.log('🎉 Le problème d\'attribution des groupes est résolu !');
-
- } catch (error) {
- console.error('❌ Erreur lors du test:', error);
- console.error('Code d\'erreur:', error?.code);
- console.error('Message:', error?.message);
- }
-}
-
-if (process.env.NODE_ENV === 'production') {
- console.log('🏭 Exécution en mode production');
- testUserGroups();
-} else {
- console.log('🛠️ Ce test est conçu pour la production');
- console.log('Pour tester localement, définissez NODE_ENV=production');
-}
\ No newline at end of file