mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-22 06:28:19 +02:00
Merge pull request #16 from R0m1k3/1.1
Fix delivery reconciliation data type errors and improve server valid…
This commit is contained in:
4 files changed
+129
-6
No files matched your search
@@ -0,0 +1,106 @@
|
|||||||
|
# Fix Urgent - Erreurs de Validation Zod
|
||||||
|
|
||||||
|
## ❌ Problème Identifié
|
||||||
|
**Erreur 500 :** ZodError lors de PUT /api/deliveries/:id
|
||||||
|
|
||||||
|
### Erreurs Specifiques
|
||||||
|
1. **blAmount** : Expected string, received number
|
||||||
|
2. **validatedAt** : Expected date, received string
|
||||||
|
|
||||||
|
## 🔍 Analyse du Problème
|
||||||
|
|
||||||
|
### Schema Drizzle (shared/schema.ts)
|
||||||
|
```typescript
|
||||||
|
// Dans deliveries table:
|
||||||
|
blAmount: decimal("bl_amount", { precision: 10, scale: 2 }) // → Zod attend string
|
||||||
|
invoiceAmount: decimal("invoice_amount", { precision: 10, scale: 2 }) // → Zod attend string
|
||||||
|
validatedAt: timestamp("validated_at") // → Zod attend Date object
|
||||||
|
```
|
||||||
|
|
||||||
|
### Données Envoyées depuis Frontend
|
||||||
|
```javascript
|
||||||
|
// ❌ Problématique
|
||||||
|
{
|
||||||
|
blAmount: 3397.86, // number → should be string
|
||||||
|
invoiceAmount: null, // OK
|
||||||
|
validatedAt: '2025-08-12T11:42:39.679Z' // string → should be Date
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## ✅ Solutions Appliquées
|
||||||
|
|
||||||
|
### 1. **Transformation côté Serveur** (server/routes.ts)
|
||||||
|
```typescript
|
||||||
|
// Avant validation Zod, transformer les types
|
||||||
|
const transformedData = { ...req.body };
|
||||||
|
|
||||||
|
// Convertir montants number → string
|
||||||
|
if (transformedData.blAmount !== undefined && transformedData.blAmount !== null) {
|
||||||
|
transformedData.blAmount = transformedData.blAmount.toString();
|
||||||
|
}
|
||||||
|
if (transformedData.invoiceAmount !== undefined && transformedData.invoiceAmount !== null) {
|
||||||
|
transformedData.invoiceAmount = transformedData.invoiceAmount.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convertir validatedAt string → Date
|
||||||
|
if (transformedData.validatedAt && typeof transformedData.validatedAt === 'string') {
|
||||||
|
transformedData.validatedAt = new Date(transformedData.validatedAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = insertDeliverySchema.partial().parse(transformedData);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. **Correction côté Frontend** (ReconciliationModal.tsx)
|
||||||
|
```typescript
|
||||||
|
// Avant
|
||||||
|
validatedAt: new Date() // ❌ Date object → string lors JSON.stringify
|
||||||
|
|
||||||
|
// Après
|
||||||
|
validatedAt: new Date().toISOString() // ✅ string → convertie en Date côté serveur
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. **Montants toujours en string** (ReconciliationModal.tsx)
|
||||||
|
```typescript
|
||||||
|
// Déjà corrigé précédemment
|
||||||
|
blAmount: formData.blAmount ? formData.blAmount.toString() : null,
|
||||||
|
invoiceAmount: formData.invoiceAmount ? formData.invoiceAmount.toString() : null,
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🧪 Test de Validation
|
||||||
|
|
||||||
|
### Payload Attendu Maintenant
|
||||||
|
```javascript
|
||||||
|
// ✅ Correct après transformation
|
||||||
|
{
|
||||||
|
blNumber: 'LD2250800571',
|
||||||
|
blAmount: '3397.86', // string ✅
|
||||||
|
invoiceReference: null,
|
||||||
|
invoiceAmount: null,
|
||||||
|
reconciled: true,
|
||||||
|
validatedAt: new Date('2025-08-12T11:42:39.679Z') // Date object ✅
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tests à Effectuer
|
||||||
|
1. **Enregistrer données BL** : blAmount doit passer en string
|
||||||
|
2. **Valider rapprochement** : validatedAt doit passer en Date
|
||||||
|
3. **Enregistrer montant facture** : invoiceAmount doit passer en string
|
||||||
|
4. **Vérifier console** : Plus d'erreurs ZodError 500
|
||||||
|
|
||||||
|
## 🔄 Flux de Données Complet
|
||||||
|
|
||||||
|
```
|
||||||
|
Frontend Form → JSON.stringify → HTTP Request → Server Transform → Zod Validation → Database
|
||||||
|
↓ ↓ ↓ ↓ ↓ ↓
|
||||||
|
{number} → "3397.86" → "3397.86" → "3397.86" → ✅ → DECIMAL
|
||||||
|
{Date} → "2025-..." → "2025-..." → Date(...) → ✅ → TIMESTAMP
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 Status
|
||||||
|
|
||||||
|
- ✅ Transformation automatique côté serveur
|
||||||
|
- ✅ Frontend envoie validatedAt en ISO string
|
||||||
|
- ✅ Montants forcés en string côté client
|
||||||
|
- 🔄 **À tester en production**
|
||||||
|
|
||||||
|
**L'erreur 500 ZodError devrait être résolue !**
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 334 KiB |
@@ -90,9 +90,9 @@ export default function ReconciliationModal({
|
|||||||
|
|
||||||
updateDeliveryMutation.mutate({
|
updateDeliveryMutation.mutate({
|
||||||
blNumber: formData.blNumber.trim(),
|
blNumber: formData.blNumber.trim(),
|
||||||
blAmount: formData.blAmount ? parseFloat(formData.blAmount) : null,
|
blAmount: formData.blAmount ? formData.blAmount.toString() : null,
|
||||||
invoiceReference: formData.invoiceReference.trim() || null,
|
invoiceReference: formData.invoiceReference.trim() || null,
|
||||||
invoiceAmount: formData.invoiceAmount ? parseFloat(formData.invoiceAmount) : null,
|
invoiceAmount: formData.invoiceAmount ? formData.invoiceAmount.toString() : null,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -108,9 +108,9 @@ export default function ReconciliationModal({
|
|||||||
|
|
||||||
updateDeliveryMutation.mutate({
|
updateDeliveryMutation.mutate({
|
||||||
blNumber: formData.blNumber.trim(),
|
blNumber: formData.blNumber.trim(),
|
||||||
blAmount: formData.blAmount ? parseFloat(formData.blAmount) : null,
|
blAmount: formData.blAmount ? formData.blAmount.toString() : null,
|
||||||
invoiceReference: formData.invoiceReference.trim() || null,
|
invoiceReference: formData.invoiceReference.trim() || null,
|
||||||
invoiceAmount: formData.invoiceAmount ? parseFloat(formData.invoiceAmount) : null,
|
invoiceAmount: formData.invoiceAmount ? formData.invoiceAmount.toString() : null,
|
||||||
reconciled: true,
|
reconciled: true,
|
||||||
validatedAt: new Date().toISOString()
|
validatedAt: new Date().toISOString()
|
||||||
});
|
});
|
||||||
|
|||||||
+19
-2
@@ -690,7 +690,24 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔄 Updating delivery:', { id, data: req.body, user: user.id });
|
console.log('🔄 Updating delivery:', { id, data: req.body, user: user.id });
|
||||||
const data = insertDeliverySchema.partial().parse(req.body);
|
|
||||||
|
// Transform data types before validation
|
||||||
|
const transformedData = { ...req.body };
|
||||||
|
|
||||||
|
// Convert decimal amounts to strings (schema expects string for decimal fields)
|
||||||
|
if (transformedData.blAmount !== undefined && transformedData.blAmount !== null) {
|
||||||
|
transformedData.blAmount = transformedData.blAmount.toString();
|
||||||
|
}
|
||||||
|
if (transformedData.invoiceAmount !== undefined && transformedData.invoiceAmount !== null) {
|
||||||
|
transformedData.invoiceAmount = transformedData.invoiceAmount.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert validatedAt to Date object (schema expects Date for timestamp fields)
|
||||||
|
if (transformedData.validatedAt && typeof transformedData.validatedAt === 'string') {
|
||||||
|
transformedData.validatedAt = new Date(transformedData.validatedAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = insertDeliverySchema.partial().parse(transformedData);
|
||||||
const updatedDelivery = await storage.updateDelivery(id, data);
|
const updatedDelivery = await storage.updateDelivery(id, data);
|
||||||
console.log('✅ Delivery updated successfully:', { id, updatedDelivery });
|
console.log('✅ Delivery updated successfully:', { id, updatedDelivery });
|
||||||
|
|
||||||
@@ -721,7 +738,7 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
// Auto-valider le rapprochement
|
// Auto-valider le rapprochement
|
||||||
await storage.updateDelivery(id, {
|
await storage.updateDelivery(id, {
|
||||||
reconciled: true,
|
reconciled: true,
|
||||||
validatedAt: new Date()
|
validatedAt: new Date().toISOString()
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`✅ Auto-reconciliation: Delivery #${id} automatically validated for supplier ${supplier.name}`);
|
console.log(`✅ Auto-reconciliation: Delivery #${id} automatically validated for supplier ${supplier.name}`);
|
||||||
|
|||||||
Reference in new issue
Block a user