mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-11 17:27:31 +02:00
Make delivery validation require a mandatory delivery note number
Enforce the requirement for a delivery note number (blNumber) during delivery validation on both the delivery and calendar modules. This change updates the frontend validation schema to make blNumber a required field with a minimum length, modifies the backend logic to reject validations without a blNumber, and integrates a new modal component for handling this validation process within the Deliveries page. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 98f01874-e00c-4bbe-9d71-b0b338001848 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/98f01874-e00c-4bbe-9d71-b0b338001848/yaZkPAT
This commit is contained in:
1 parent
6dca340c45
commit
c09388c0aa
3 files changed
+34
-60
No files matched your search
@@ -13,7 +13,7 @@ import { isUnauthorizedError } from "@/lib/authUtils";
|
||||
import { Check, X } from "lucide-react";
|
||||
|
||||
const validateDeliverySchema = z.object({
|
||||
blNumber: z.string().optional(),
|
||||
blNumber: z.string().min(1, "Le numéro de bon de livraison est obligatoire"),
|
||||
blAmount: z.string().optional(),
|
||||
});
|
||||
|
||||
@@ -47,10 +47,8 @@ export default function ValidateDeliveryModal({
|
||||
mutationFn: async (data: ValidateDeliveryForm) => {
|
||||
const payload: any = {};
|
||||
|
||||
// Ajouter blNumber seulement s'il est fourni
|
||||
if (data.blNumber && data.blNumber.trim() !== '') {
|
||||
payload.blNumber = data.blNumber.trim();
|
||||
}
|
||||
// Le blNumber est maintenant obligatoire
|
||||
payload.blNumber = data.blNumber.trim();
|
||||
|
||||
if (data.blAmount && data.blAmount.trim() !== '') {
|
||||
payload.blAmount = parseFloat(data.blAmount);
|
||||
@@ -137,10 +135,10 @@ export default function ValidateDeliveryModal({
|
||||
name="blNumber"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>N° Bon de Livraison</FormLabel>
|
||||
<FormLabel>N° Bon de Livraison *</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder="Ex: BL-2024-001 (optionnel)"
|
||||
placeholder="Ex: BL-2024-001"
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
@@ -29,6 +29,7 @@ import { safeFormat } from "@/lib/dateUtils";
|
||||
import CreateDeliveryModal from "@/components/modals/CreateDeliveryModal";
|
||||
import EditDeliveryModal from "@/components/modals/EditDeliveryModal";
|
||||
import OrderDetailModal from "@/components/modals/OrderDetailModal";
|
||||
import ValidateDeliveryModal from "@/components/modals/ValidateDeliveryModal";
|
||||
import ConfirmDeleteModal from "@/components/modals/ConfirmDeleteModal";
|
||||
import type { DeliveryWithRelations } from "@shared/schema";
|
||||
|
||||
@@ -67,8 +68,10 @@ export default function Deliveries() {
|
||||
const [showEditModal, setShowEditModal] = useState(false);
|
||||
const [showDetailModal, setShowDetailModal] = useState(false);
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
||||
const [showValidateModal, setShowValidateModal] = useState(false);
|
||||
const [selectedDelivery, setSelectedDelivery] = useState<DeliveryWithRelations | null>(null);
|
||||
const [deliveryToDelete, setDeliveryToDelete] = useState<DeliveryWithRelations | null>(null);
|
||||
const [deliveryToValidate, setDeliveryToValidate] = useState<DeliveryWithRelations | null>(null);
|
||||
|
||||
// Construire l'URL pour l'historique complet sans filtrage par date
|
||||
// CRITICAL FIX: Appliquer le filtrage par storeId pour TOUS les rôles, pas seulement admin
|
||||
@@ -107,46 +110,6 @@ export default function Deliveries() {
|
||||
|
||||
const groups = Array.isArray(groupsData) ? groupsData : [];
|
||||
|
||||
const validateMutation = useMutation({
|
||||
mutationFn: async (id: number) => {
|
||||
await apiRequest(`/api/deliveries/${id}/validate`, "POST");
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast({
|
||||
title: "Succès",
|
||||
description: "Livraison validée avec succès",
|
||||
});
|
||||
// Invalider tous les caches liés aux livraisons
|
||||
queryClient.invalidateQueries({ queryKey: ['/api/deliveries'] });
|
||||
queryClient.invalidateQueries({ queryKey: [deliveriesUrl] });
|
||||
// Invalider tous les caches BL/Rapprochement
|
||||
queryClient.invalidateQueries({
|
||||
predicate: (query) =>
|
||||
query.queryKey[0] === '/api/deliveries/bl' ||
|
||||
query.queryKey[0] === '/api/deliveries'
|
||||
});
|
||||
queryClient.invalidateQueries({ queryKey: ['/api/orders'] });
|
||||
queryClient.invalidateQueries({ queryKey: ['/api/stats/monthly'] });
|
||||
},
|
||||
onError: (error) => {
|
||||
if (isUnauthorizedError(error)) {
|
||||
toast({
|
||||
title: "Non autorisé",
|
||||
description: "Vous êtes déconnecté. Reconnexion...",
|
||||
variant: "destructive",
|
||||
});
|
||||
setTimeout(() => {
|
||||
window.location.href = "/api/login";
|
||||
}, 500);
|
||||
return;
|
||||
}
|
||||
toast({
|
||||
title: "Erreur",
|
||||
description: "Impossible de valider la livraison",
|
||||
variant: "destructive",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const deleteMutation = useMutation({
|
||||
mutationFn: async (id: number) => {
|
||||
@@ -231,10 +194,14 @@ export default function Deliveries() {
|
||||
setShowEditModal(true);
|
||||
};
|
||||
|
||||
const handleValidateDelivery = (id: number) => {
|
||||
if (window.confirm("Êtes-vous sûr de vouloir valider cette livraison ?")) {
|
||||
validateMutation.mutate(id);
|
||||
}
|
||||
const handleValidateDelivery = (delivery: DeliveryWithRelations) => {
|
||||
setDeliveryToValidate(delivery);
|
||||
setShowValidateModal(true);
|
||||
};
|
||||
|
||||
const handleValidateModalClose = () => {
|
||||
setShowValidateModal(false);
|
||||
setDeliveryToValidate(null);
|
||||
};
|
||||
|
||||
const handleDeleteDelivery = (delivery: DeliveryWithRelations) => {
|
||||
@@ -448,9 +415,9 @@ export default function Deliveries() {
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => handleValidateDelivery(delivery.id)}
|
||||
onClick={() => handleValidateDelivery(delivery)}
|
||||
className="text-green-600 hover:text-green-700"
|
||||
disabled={validateMutation.isPending}
|
||||
disabled={false}
|
||||
>
|
||||
<Check className="w-4 h-4 border border-gray-300 rounded p-0.5" />
|
||||
</Button>
|
||||
@@ -513,6 +480,14 @@ export default function Deliveries() {
|
||||
/>
|
||||
)}
|
||||
|
||||
{showValidateModal && deliveryToValidate && (
|
||||
<ValidateDeliveryModal
|
||||
isOpen={showValidateModal}
|
||||
onClose={handleValidateModalClose}
|
||||
delivery={deliveryToValidate}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Modal de confirmation de suppression */}
|
||||
<ConfirmDeleteModal
|
||||
isOpen={showDeleteModal}
|
||||
|
||||
+8
-7
@@ -1113,13 +1113,14 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
|
||||
const { blNumber, blAmount } = req.body;
|
||||
|
||||
// BL data is optional - delivery can be validated without it
|
||||
let blData: any = undefined;
|
||||
if (blNumber) {
|
||||
blData = { blNumber };
|
||||
if (blAmount !== undefined && blAmount !== null && blAmount !== '') {
|
||||
blData.blAmount = blAmount;
|
||||
}
|
||||
// Le numéro de BL est maintenant obligatoire pour valider une livraison
|
||||
if (!blNumber || !blNumber.trim()) {
|
||||
return res.status(400).json({ message: "Le numéro de bon de livraison est obligatoire pour valider une livraison" });
|
||||
}
|
||||
|
||||
let blData: any = { blNumber: blNumber.trim() };
|
||||
if (blAmount !== undefined && blAmount !== null && blAmount !== '') {
|
||||
blData.blAmount = blAmount;
|
||||
}
|
||||
|
||||
await storage.validateDelivery(id, blData);
|
||||
|
||||
Reference in new issue
Block a user