diff --git a/.replit b/.replit index dce2674..7e2bfcb 100644 --- a/.replit +++ b/.replit @@ -27,6 +27,10 @@ externalPort = 3000 localPort = 38451 externalPort = 3002 +[[ports]] +localPort = 41035 +externalPort = 5000 + [[ports]] localPort = 41343 externalPort = 3001 diff --git a/client/src/pages/Analytics.tsx b/client/src/pages/Analytics.tsx index 0641090..fe9e398 100644 --- a/client/src/pages/Analytics.tsx +++ b/client/src/pages/Analytics.tsx @@ -8,7 +8,7 @@ import { Calendar } from "@/components/ui/calendar"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { useAuthUnified } from "@/hooks/useAuthUnified"; import { useStore } from "@/contexts/StoreContext"; -import { CalendarIcon, Download, RefreshCw, TrendingUp, Package, Clock, Euro, Store, Truck, BarChart3, PieChart, Activity, FileDown } from "lucide-react"; +import { CalendarIcon, Download, RefreshCw, TrendingUp, Package, CheckCircle2, Euro, Store, Truck, BarChart3, PieChart, Activity, FileDown } from "lucide-react"; import { addDays, format, startOfMonth, endOfMonth, startOfWeek, endOfWeek, startOfYear, endOfYear } from "date-fns"; import { fr } from "date-fns/locale"; import { LineChart, Line, BarChart, Bar, PieChart as RechartsChart, Pie, Cell, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from "recharts"; @@ -362,15 +362,15 @@ export default function Analytics() { - Taux de ponctualité + Taux de réconciliation - {summary?.onTimeRate ? `${summary.onTimeRate.toFixed(1)}%` : '0%'} + {summary?.reconciliationRate ? `${summary.reconciliationRate.toFixed(1)}%` : '0%'} - + diff --git a/server/storage.ts b/server/storage.ts index 80cb2c8..555e66b 100644 --- a/server/storage.ts +++ b/server/storage.ts @@ -274,7 +274,7 @@ export interface IStorage { }): Promise<{ totalOrders: number; totalDeliveries: number; - onTimeRate: number; + reconciliationRate: number; totalAmount: number; avgDeliveryDelay: number; topSuppliers: Array<{ id: number; name: string; count: number; amount: number }>; @@ -2863,7 +2863,7 @@ export class DatabaseStorage implements IStorage { }): Promise<{ totalOrders: number; totalDeliveries: number; - onTimeRate: number; + reconciliationRate: number; totalAmount: number; avgDeliveryDelay: number; topSuppliers: Array<{ id: number; name: string; count: number; amount: number }>; @@ -2905,7 +2905,7 @@ export class DatabaseStorage implements IStorage { const deliveryQuery = db.select({ count: sql`COUNT(*)`, totalAmount: sql`COALESCE(SUM(CAST(bl_amount AS NUMERIC)), 0) + COALESCE(SUM(CAST(invoice_amount AS NUMERIC)), 0)`, - onTime: sql`COUNT(CASE WHEN delivered_date <= scheduled_date THEN 1 END)`, + reconciled: sql`COUNT(CASE WHEN reconciled = true OR reconciled = 1 THEN 1 END)`, avgDelay: sql`AVG(EXTRACT(EPOCH FROM (delivered_date - scheduled_date)) / 86400)` // days }).from(deliveries); if (deliveryConditions.length) deliveryQuery.where(and(...deliveryConditions)); @@ -2949,7 +2949,7 @@ export class DatabaseStorage implements IStorage { return { totalOrders: Number(totalOrders) || 0, totalDeliveries: Number(deliveryStats.count) || 0, - onTimeRate: deliveryStats.count ? (Number(deliveryStats.onTime) / Number(deliveryStats.count)) * 100 : 0, + reconciliationRate: deliveryStats.count ? (Number(deliveryStats.reconciled) / Number(deliveryStats.count)) * 100 : 0, totalAmount: Number(deliveryStats.totalAmount) || 0, avgDeliveryDelay: Number(deliveryStats.avgDelay) || 0, topSuppliers: topSuppliers.map(s => ({ @@ -5134,7 +5134,7 @@ export class MemStorage implements IStorage { }): Promise<{ totalOrders: number; totalDeliveries: number; - onTimeRate: number; + reconciliationRate: number; totalAmount: number; avgDeliveryDelay: number; topSuppliers: Array<{ id: number; name: string; count: number; amount: number }>; @@ -5166,10 +5166,10 @@ export class MemStorage implements IStorage { // Calculate metrics const totalOrders = filteredOrders.length; const totalDeliveries = filteredDeliveries.length; - const onTimeDeliveries = filteredDeliveries.filter(d => - d.deliveredDate && d.deliveredDate <= d.scheduledDate + const reconciledDeliveries = filteredDeliveries.filter(d => + d.reconciled === true || d.reconciled === 1 ).length; - const onTimeRate = totalDeliveries > 0 ? (onTimeDeliveries / totalDeliveries) * 100 : 0; + const reconciliationRate = totalDeliveries > 0 ? (reconciledDeliveries / totalDeliveries) * 100 : 0; const totalAmount = filteredDeliveries.reduce((sum, d) => { return sum + (parseFloat(d.blAmount as any) || 0) + (parseFloat(d.invoiceAmount as any) || 0); @@ -5217,7 +5217,7 @@ export class MemStorage implements IStorage { return { totalOrders, totalDeliveries, - onTimeRate, + reconciliationRate, totalAmount, avgDeliveryDelay: 0, // Simplified for development topSuppliers,