diff --git a/attached_assets/image_1754944243764.png b/attached_assets/image_1754944243764.png new file mode 100644 index 0000000..529ce87 Binary files /dev/null and b/attached_assets/image_1754944243764.png differ diff --git a/client/src/pages/Calendar.tsx b/client/src/pages/Calendar.tsx index 5d7bb15..4f45f5e 100644 --- a/client/src/pages/Calendar.tsx +++ b/client/src/pages/Calendar.tsx @@ -1,6 +1,6 @@ import { useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; -import { ChevronLeft, ChevronRight, Plus } from "lucide-react"; +import { ChevronLeft, ChevronRight, Plus, RefreshCw } from "lucide-react"; import { Button } from "@/components/ui/button"; import CalendarGrid from "@/components/CalendarGrid"; import QuickCreateMenu from "@/components/modals/QuickCreateMenu"; @@ -11,6 +11,7 @@ import StatsPanel from "@/components/StatsPanel"; import { useAuthUnified } from "@/hooks/useAuthUnified"; import { useStore } from "@/components/Layout"; import { apiRequest } from "@/lib/queryClient"; +import { useToast } from "@/hooks/use-toast"; import { format, startOfMonth, endOfMonth } from "date-fns"; import { fr } from "date-fns/locale"; @@ -18,6 +19,7 @@ export default function Calendar() { const { user } = useAuthUnified(); const { selectedStoreId } = useStore(); const queryClient = useQueryClient(); + const { toast } = useToast(); const [currentDate, setCurrentDate] = useState(new Date()); // Current date const [selectedDate, setSelectedDate] = useState(null); const [showQuickCreate, setShowQuickCreate] = useState(false); @@ -25,6 +27,7 @@ export default function Calendar() { const [showCreateOrder, setShowCreateOrder] = useState(false); const [showCreateDelivery, setShowCreateDelivery] = useState(false); const [selectedItem, setSelectedItem] = useState(null); + const [isSyncing, setIsSyncing] = useState(false); const monthStart = startOfMonth(currentDate); const monthEnd = endOfMonth(currentDate); @@ -138,6 +141,41 @@ export default function Calendar() { setShowCreateDelivery(true); }; + // Fonction pour synchroniser les statuts commandes/livraisons + const handleSyncOrderDeliveryStatus = async () => { + if (user?.role !== 'admin') return; + + setIsSyncing(true); + try { + console.log('🔄 Starting manual sync of order-delivery status...'); + const response = await apiRequest({ + url: '/api/sync-order-delivery-status', + method: 'POST' + }); + + console.log('🔄 Sync result:', response); + + toast({ + title: "Synchronisation terminée", + description: `${response.diagnostics.ordersFixed} commande(s) corrigée(s) sur ${response.diagnostics.problematicOrdersFound} problématique(s)`, + }); + + // Rafraîchir les données du calendrier + queryClient.invalidateQueries({ queryKey: ['/api/orders'] }); + queryClient.invalidateQueries({ queryKey: ['/api/deliveries'] }); + + } catch (error) { + console.error('❌ Sync failed:', error); + toast({ + title: "Erreur de synchronisation", + description: "Impossible de synchroniser les statuts. Vérifiez la console.", + variant: "destructive" + }); + } finally { + setIsSyncing(false); + } + }; + const isLoading = loadingOrders || loadingDeliveries; return ( @@ -197,13 +235,27 @@ export default function Calendar() { - +
+ {user?.role === 'admin' && ( + + )} + +
diff --git a/server/routes.ts b/server/routes.ts index 04ae466..70fa5b5 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -522,6 +522,64 @@ export async function registerRoutes(app: Express): Promise { } }); + // Route pour diagnostiquer et synchroniser les statuts commandes/livraisons + app.post('/api/sync-order-delivery-status', isAuthenticated, async (req: any, res) => { + try { + const user = await storage.getUserWithGroups(req.user.claims ? req.user.claims.sub : req.user.id); + if (!user || user.role !== 'admin') { + return res.status(403).json({ message: "Access denied" }); + } + + console.log('🔄 Starting order-delivery status synchronization...'); + + // Diagnostic: Trouver les commandes avec livraisons livrées mais pas en statut "delivered" + const orders = await storage.getOrders(); + const problematicOrders = []; + const fixedOrders = []; + + for (const order of orders) { + if (order.deliveries && order.deliveries.length > 0) { + const hasDeliveredDeliveries = order.deliveries.some(d => d.status === 'delivered'); + + if (hasDeliveredDeliveries && order.status !== 'delivered') { + console.log(`🔍 Found problematic order: #CMD-${order.id} (status: ${order.status}) with delivered deliveries`); + problematicOrders.push({ + orderId: order.id, + currentStatus: order.status, + deliveredDeliveries: order.deliveries.filter(d => d.status === 'delivered').length, + totalDeliveries: order.deliveries.length + }); + + // Fixer automatiquement + try { + await storage.updateOrder(order.id, { status: 'delivered' }); + console.log(`✅ Fixed order #CMD-${order.id} status to 'delivered'`); + fixedOrders.push(order.id); + } catch (error) { + console.error(`❌ Failed to fix order #CMD-${order.id}:`, error); + } + } + } + } + + console.log('🔄 Synchronization completed'); + + res.json({ + message: "Synchronization completed", + diagnostics: { + problematicOrdersFound: problematicOrders.length, + ordersFixed: fixedOrders.length, + problematicOrders, + fixedOrders + } + }); + + } catch (error) { + console.error("❌ Error in sync operation:", error); + res.status(500).json({ message: "Failed to synchronize statuses", error: error.message }); + } + }); + // Deliveries routes app.get('/api/deliveries', isAuthenticated, async (req: any, res) => { try {