mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-23 06:58:19 +02:00
3 files changed
+28
-53
No files matched your search
@@ -77,19 +77,9 @@ export default function ReconciliationModal({
|
|||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
// Validation basique
|
|
||||||
if (!formData.blNumber.trim()) {
|
|
||||||
toast({
|
|
||||||
title: "Erreur",
|
|
||||||
description: "Le numéro de BL est requis",
|
|
||||||
variant: "destructive",
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateDeliveryMutation.mutate({
|
updateDeliveryMutation.mutate({
|
||||||
blNumber: formData.blNumber.trim(),
|
blNumber: formData.blNumber.trim() || null,
|
||||||
blAmount: formData.blAmount ? formData.blAmount.toString() : null,
|
blAmount: formData.blAmount ? formData.blAmount.toString() : null,
|
||||||
invoiceReference: formData.invoiceReference.trim() || null,
|
invoiceReference: formData.invoiceReference.trim() || null,
|
||||||
invoiceAmount: formData.invoiceAmount ? formData.invoiceAmount.toString() : null,
|
invoiceAmount: formData.invoiceAmount ? formData.invoiceAmount.toString() : null,
|
||||||
@@ -97,17 +87,8 @@ export default function ReconciliationModal({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleValidateReconciliation = () => {
|
const handleValidateReconciliation = () => {
|
||||||
if (!formData.blNumber.trim()) {
|
|
||||||
toast({
|
|
||||||
title: "Erreur",
|
|
||||||
description: "Veuillez d'abord renseigner le numéro de BL",
|
|
||||||
variant: "destructive",
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateDeliveryMutation.mutate({
|
updateDeliveryMutation.mutate({
|
||||||
blNumber: formData.blNumber.trim(),
|
blNumber: formData.blNumber.trim() || null,
|
||||||
blAmount: formData.blAmount ? formData.blAmount.toString() : null,
|
blAmount: formData.blAmount ? formData.blAmount.toString() : null,
|
||||||
invoiceReference: formData.invoiceReference.trim() || null,
|
invoiceReference: formData.invoiceReference.trim() || null,
|
||||||
invoiceAmount: formData.invoiceAmount ? formData.invoiceAmount.toString() : null,
|
invoiceAmount: formData.invoiceAmount ? formData.invoiceAmount.toString() : null,
|
||||||
@@ -117,7 +98,7 @@ export default function ReconciliationModal({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const isAutomaticMode = delivery?.supplier?.automaticReconciliation;
|
const isAutomaticMode = delivery?.supplier?.automaticReconciliation;
|
||||||
const canValidate = formData.blNumber.trim().length > 0;
|
const canValidate = true; // Plus de restriction sur le numéro BL
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={isOpen} onOpenChange={onClose}>
|
<Dialog open={isOpen} onOpenChange={onClose}>
|
||||||
@@ -176,13 +157,12 @@ export default function ReconciliationModal({
|
|||||||
<h4 className="font-medium text-gray-900">Bon de Livraison (BL)</h4>
|
<h4 className="font-medium text-gray-900">Bon de Livraison (BL)</h4>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Label htmlFor="blNumber">N° BL *</Label>
|
<Label htmlFor="blNumber">N° BL</Label>
|
||||||
<Input
|
<Input
|
||||||
id="blNumber"
|
id="blNumber"
|
||||||
value={formData.blNumber}
|
value={formData.blNumber}
|
||||||
onChange={(e) => setFormData(prev => ({ ...prev, blNumber: e.target.value }))}
|
onChange={(e) => setFormData(prev => ({ ...prev, blNumber: e.target.value }))}
|
||||||
placeholder="Ex: BL-2025-001"
|
placeholder="Ex: BL-2025-001 (optionnel)"
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -263,8 +243,8 @@ export default function ReconciliationModal({
|
|||||||
|
|
||||||
{/* Note d'aide */}
|
{/* Note d'aide */}
|
||||||
<div className="text-xs text-gray-500 bg-blue-50 p-3 rounded">
|
<div className="text-xs text-gray-500 bg-blue-50 p-3 rounded">
|
||||||
<strong>Note :</strong> Le numéro de BL est obligatoire pour valider un rapprochement.
|
<strong>Note :</strong> Tous les champs sont optionnels.
|
||||||
Les montants sont optionnels mais recommandés pour un suivi précis.
|
Les données BL et facture sont recommandées pour un suivi précis mais pas obligatoires.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { isUnauthorizedError } from "@/lib/authUtils";
|
|||||||
import { Check, X } from "lucide-react";
|
import { Check, X } from "lucide-react";
|
||||||
|
|
||||||
const validateDeliverySchema = z.object({
|
const validateDeliverySchema = z.object({
|
||||||
blNumber: z.string().min(1, "Le numéro de BL est obligatoire"),
|
blNumber: z.string().optional(),
|
||||||
blAmount: z.string().optional(),
|
blAmount: z.string().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -45,9 +45,12 @@ export default function ValidateDeliveryModal({
|
|||||||
|
|
||||||
const validateDeliveryMutation = useMutation({
|
const validateDeliveryMutation = useMutation({
|
||||||
mutationFn: async (data: ValidateDeliveryForm) => {
|
mutationFn: async (data: ValidateDeliveryForm) => {
|
||||||
const payload: any = {
|
const payload: any = {};
|
||||||
blNumber: data.blNumber,
|
|
||||||
};
|
// Ajouter blNumber seulement s'il est fourni
|
||||||
|
if (data.blNumber && data.blNumber.trim() !== '') {
|
||||||
|
payload.blNumber = data.blNumber.trim();
|
||||||
|
}
|
||||||
|
|
||||||
if (data.blAmount && data.blAmount.trim() !== '') {
|
if (data.blAmount && data.blAmount.trim() !== '') {
|
||||||
payload.blAmount = parseFloat(data.blAmount);
|
payload.blAmount = parseFloat(data.blAmount);
|
||||||
@@ -134,10 +137,10 @@ export default function ValidateDeliveryModal({
|
|||||||
name="blNumber"
|
name="blNumber"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>N° Bon de Livraison *</FormLabel>
|
<FormLabel>N° Bon de Livraison</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder="Ex: BL-2024-001"
|
placeholder="Ex: BL-2024-001 (optionnel)"
|
||||||
{...field}
|
{...field}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|||||||
@@ -90,11 +90,15 @@ export default function BLReconciliation() {
|
|||||||
|
|
||||||
// Auto-remplissage si facture trouvée via BL
|
// Auto-remplissage si facture trouvée via BL
|
||||||
if (result.exists && result.matchType === 'bl_number' && result.invoiceReference) {
|
if (result.exists && result.matchType === 'bl_number' && result.invoiceReference) {
|
||||||
// Auto-remplir les champs dans la livraison
|
// Auto-remplir les champs dans la livraison via API
|
||||||
updateDeliveryMutation.mutate({
|
apiRequest(`/api/deliveries/${variables.deliveryId}`, "PUT", {
|
||||||
id: variables.deliveryId,
|
|
||||||
invoiceReference: result.invoiceReference,
|
invoiceReference: result.invoiceReference,
|
||||||
invoiceAmount: result.invoiceAmount
|
invoiceAmount: result.invoiceAmount
|
||||||
|
}).then(() => {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['/api/deliveries/bl'] });
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['/api/deliveries'] });
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error('Erreur auto-remplissage:', error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,17 +267,11 @@ export default function BLReconciliation() {
|
|||||||
setIsModalOpen(false);
|
setIsModalOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSaveReconciliation = async (data: any) => {
|
const handleSaveReconciliation = async () => {
|
||||||
try {
|
try {
|
||||||
await apiRequest(`/api/deliveries/${selectedDelivery.id}`, "PUT", data);
|
|
||||||
|
|
||||||
toast({
|
|
||||||
title: "Succès",
|
|
||||||
description: "Données de rapprochement mises à jour",
|
|
||||||
});
|
|
||||||
|
|
||||||
// Invalidation cache + refetch forcé pour mise à jour immédiate
|
// Invalidation cache + refetch forcé pour mise à jour immédiate
|
||||||
queryClient.invalidateQueries({ queryKey: ['/api/deliveries/bl'] });
|
queryClient.invalidateQueries({ queryKey: ['/api/deliveries/bl'] });
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['/api/deliveries'] });
|
||||||
refetch();
|
refetch();
|
||||||
handleCloseModal();
|
handleCloseModal();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -720,18 +718,12 @@ export default function BLReconciliation() {
|
|||||||
{(delivery.group?.nocodbTableName || delivery.group?.nocodbConfigId || delivery.group?.webhookUrl) && (
|
{(delivery.group?.nocodbTableName || delivery.group?.nocodbConfigId || delivery.group?.webhookUrl) && (
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
{verifyingDeliveries.has(delivery.id) ? (
|
{verifyingDeliveries.has(delivery.id) ? (
|
||||||
<Clock className="h-4 w-4 text-blue-500 animate-spin" title="Vérification en cours..." />
|
<Clock className="h-4 w-4 text-blue-500 animate-spin" />
|
||||||
) : verificationResults[delivery.id] ? (
|
) : verificationResults[delivery.id] ? (
|
||||||
verificationResults[delivery.id].exists ? (
|
verificationResults[delivery.id].exists ? (
|
||||||
<CheckCircle
|
<CheckCircle className="h-4 w-4 text-green-500 cursor-help" />
|
||||||
className="h-4 w-4 text-green-500 cursor-help"
|
|
||||||
title={`Facture vérifiée (${verificationResults[delivery.id].matchType === 'invoice_ref' ? 'référence directe' : 'via BL'})`}
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<XCircle
|
<XCircle className="h-4 w-4 text-red-500 cursor-help" />
|
||||||
className="h-4 w-4 text-red-500 cursor-help"
|
|
||||||
title={`Facture non trouvée: ${verificationResults[delivery.id].errorMessage || 'Aucune correspondance'}`}
|
|
||||||
/>
|
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
|
|||||||
Reference in new issue
Block a user