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 { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { useToast } from "@/hooks/use-toast"; import { apiRequest } from "@/lib/queryClient"; import { useStore } from "@/contexts/StoreContext"; import { useAuthUnified } from "@/hooks/useAuthUnified"; import { usePermissions } from "@shared/permissions"; import { Pagination, usePagination } from "@/components/ui/pagination"; import { Search, Edit, FileText, Settings, Eye, AlertTriangle, X, Check, Trash2, Ban, Filter, Upload, CheckCircle, XCircle, Clock, MessageSquare } from "lucide-react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import ReconciliationComments from "@/components/ReconciliationComments"; import ReconciliationModal from "@/components/modals/ReconciliationModal"; export default function BLReconciliation() { const { user } = useAuthUnified(); const { selectedStoreId } = useStore(); const { toast } = useToast(); const queryClient = useQueryClient(); const permissions = usePermissions(user?.role); // 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.
Gestion des rapprochements manuels et automatiques
Les livraisons de fournisseurs en mode manuel apparaîtront ici.
| Fournisseur | N° BL | Date Livr. | Montant BL | Ref. Facture | Montant Fact. | Échéance | Écart | Magasin | Actions |
|---|---|---|---|---|---|---|---|---|---|
|
{delivery.supplier?.name}
|
{delivery.blNumber || (
handleOpenModal(delivery)}
title="Cliquer pour modifier"
>
Non renseigné
)}
|
{safeFormat(delivery.scheduledDate, 'dd/MM/yy')}
|
{delivery.blAmount ?
`${parseFloat(delivery.blAmount).toFixed(2)}€` :
handleOpenModal(delivery)}
title="Cliquer pour modifier"
>
Non renseigné
}
|
{/* Icône de vérification de facture */}
{(delivery.group?.nocodbTableName || delivery.group?.nocodbConfigId || delivery.group?.webhookUrl) && (
{verifyingDeliveries.has(delivery.id) ? (
)}
{delivery.invoiceReference || (
handleOpenModal(delivery)}
title="Cliquer pour modifier"
>
Non renseigné
)}
|
{delivery.invoiceAmount ?
`${parseFloat(delivery.invoiceAmount).toFixed(2)}€` :
handleOpenModal(delivery)}
title="Cliquer pour modifier"
>
Non renseigné
}
|
{delivery.dueDate ? (
{safeFormat(delivery.dueDate, 'dd/MM/yyyy')}
) : (
-
)}
|
{(() => {
const blAmount = delivery.blAmount ? parseFloat(delivery.blAmount) : 0;
const invoiceAmount = delivery.invoiceAmount ? parseFloat(delivery.invoiceAmount) : 0;
if (blAmount && invoiceAmount) {
const diff = invoiceAmount - blAmount;
const diffAbs = Math.abs(diff);
return (
10 ? 'text-red-600' : 'text-orange-600'
}`}>
{diff > 0 ? '+' : ''}{diff.toFixed(2)}€
);
}
return -;
})()}
|
{delivery.group?.name}
|
{shouldShowInvoiceButton(delivery) && (
)}
{!delivery.reconciled ? (
<>
{permissions.canValidate('reconciliation') && verificationResults[delivery.id]?.exists === true ? (
) : permissions.canValidate('reconciliation') && verificationResults[delivery.id]?.exists === false ? (
) : permissions.canValidate('reconciliation') ? (
) : null}
{permissions.canDelete('reconciliation') && (
)}
>
) : (
<>
{user?.role === 'admin' && (
)}
{permissions.canDelete('reconciliation') && (
)}
>
)}
|
Cette section regroupe toutes les livraisons validées (manuellement ou automatiquement). {(permissions.canEdit('reconciliation') || permissions.canValidate('reconciliation')) ? ( " Vous pouvez dévalider ces rapprochements si nécessaire." ) : ( " Seuls les utilisateurs autorisés peuvent dévalider ces rapprochements." )}
Les livraisons validées apparaîtront ici.
| Fournisseur | N° BL | Date Livr. | Ref. Facture | Montant BL | Montant Fact. | Échéance | Écart | Magasin | Actions |
|---|---|---|---|---|---|---|---|---|---|
|
{delivery.supplier?.name}
{isAutomatic && (
|
{delivery.blNumber || (
Non renseigné
)}
|
{safeFormat(delivery.scheduledDate, 'dd/MM/yy')}
|
{delivery.invoiceReference || (
Non renseignée
)}
|
{delivery.blAmount ?
`${parseFloat(delivery.blAmount).toFixed(2)}€` :
Non renseigné
}
|
{delivery.invoiceAmount ?
`${parseFloat(delivery.invoiceAmount).toFixed(2)}€` :
Non renseigné
}
|
{delivery.dueDate ? (
{safeFormat(delivery.dueDate, 'dd/MM/yyyy')}
) : (
-
)}
|
{ecart !== null ? (
|
{delivery.group?.name}
|
{(permissions.canEdit('reconciliation') || permissions.canValidate('reconciliation')) && (
)}
{permissions.canDelete('reconciliation') && (
)}
|