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.

) : (
{filteredManualDeliveries.map((delivery: any) => ( ))}
Fournisseur N° BL Date Livr. Montant BL Ref. Facture Montant Fact. Magasin Actions
{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.

) : (
{filteredAutomaticDeliveries.map((delivery: any) => ( ))}
Fournisseur AUTO N° BL Date Livr. Date Valid. Montant BL Ref. Facture Montant Fact. Magasin Actions
{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 ? ( <> ) : ( )}
)}
); }