Fix invalid unit_of_measure 'dozen' causing 422 API errors

**Issue:**
Creating ingredients failed with 422 error:
```
Input should be 'kg', 'g', 'l', 'ml', 'units', 'pcs', 'pkg', 'bags' or 'boxes'
input: "dozen"
```

**Root Cause:**
Frontend was using units not supported by backend UnitOfMeasure enum:
- "dozen" (docena)
- "cup" (taza)
- "tbsp" (cucharada)
- "tsp" (cucharadita)
- "piece" → should be "pcs"
- "package" → should be "pkg"
- "bag" → should be "bags"
- "box" → should be "boxes"

**Backend Supported Units (inventory.ts:28-38):**
kg, g, l, ml, units, pcs, pkg, bags, boxes

**Solution:**
Replaced all invalid units with backend-compatible ones across codebase.

**Files Modified:**

1. **UploadSalesDataStep.tsx:604**
   - Before: ['kg', 'g', 'L', 'ml', 'units', 'dozen']
   - After: ['kg', 'g', 'l', 'ml', 'units', 'pcs', 'pkg', 'bags', 'boxes']

2. **BatchAddIngredientsModal.tsx:53**
   - Before: ['kg', 'g', 'L', 'ml', 'units', 'dozen']
   - After: ['kg', 'g', 'l', 'ml', 'units', 'pcs', 'pkg', 'bags', 'boxes']

3. **QuickAddIngredientModal.tsx:69**
   - Before: ['kg', 'g', 'L', 'ml', 'units', 'dozen']
   - After: ['kg', 'g', 'l', 'ml', 'units', 'pcs', 'pkg', 'bags', 'boxes']

4. **inventory/index.ts:51-62**
   - Removed: 'piece', 'package', 'bag', 'box', 'dozen', 'cup', 'tbsp', 'tsp'
   - Added: 'units', 'pcs', 'pkg', 'bags', 'boxes'
   - Added comment: "must match backend UnitOfMeasure enum exactly"

5. **ingredientHelpers.ts:168**
   - Eggs unit changed from 'dozen' → 'units'

6. **utils/constants.ts:77-87**
   - Removed volume units: cup, tbsp, tsp
   - Removed count units: piece, dozen, package, bag, box
   - Added: units, pcs, pkg, bags, boxes
   - Now matches backend enum exactly

**Also Fixed:**
- Changed 'L' to lowercase 'l' for consistency with backend

**Impact:**
 All ingredient creation now uses valid backend units
 No more 422 validation errors
 Frontend/backend unit enums synchronized

**Build Status:** ✓ Successful in 22.23s
This commit is contained in:
Claude
2025-11-07 08:36:35 +00:00
parent 98fc7a6749
commit bedd4868ac
6 changed files with 15 additions and 21 deletions

View File

@@ -50,7 +50,7 @@ export const BatchAddIngredientsModal: React.FC<BatchAddIngredientsModalProps> =
'Other' 'Other'
]; ];
const unitOptions = ['kg', 'g', 'L', 'ml', 'units', 'dozen']; const unitOptions = ['kg', 'g', 'l', 'ml', 'units', 'pcs', 'pkg', 'bags', 'boxes'];
const updateRow = (id: string, field: keyof BatchIngredientRow, value: any) => { const updateRow = (id: string, field: keyof BatchIngredientRow, value: any) => {
setRows(rows.map(row => setRows(rows.map(row =>

View File

@@ -66,7 +66,7 @@ export const QuickAddIngredientModal: React.FC<QuickAddIngredientModalProps> = (
'Other' 'Other'
]; ];
const unitOptions = ['kg', 'g', 'L', 'ml', 'units', 'dozen']; const unitOptions = ['kg', 'g', 'l', 'ml', 'units', 'pcs', 'pkg', 'bags', 'boxes'];
// Check for duplicates when name changes // Check for duplicates when name changes
useEffect(() => { useEffect(() => {

View File

@@ -48,20 +48,17 @@ export const INVENTORY_CONSTANTS = {
{ value: 'out', label: 'Sin Stock' }, { value: 'out', label: 'Sin Stock' },
], ],
// Units of measure commonly used in Spanish bakeries // Units of measure - must match backend UnitOfMeasure enum exactly
BAKERY_UNITS: [ BAKERY_UNITS: [
{ value: 'kg', label: 'Kilogramo (kg)' }, { value: 'kg', label: 'Kilogramo (kg)' },
{ value: 'g', label: 'Gramo (g)' }, { value: 'g', label: 'Gramo (g)' },
{ value: 'l', label: 'Litro (l)' }, { value: 'l', label: 'Litro (l)' },
{ value: 'ml', label: 'Mililitro (ml)' }, { value: 'ml', label: 'Mililitro (ml)' },
{ value: 'piece', label: 'Pieza (pz)' }, { value: 'units', label: 'Unidades' },
{ value: 'package', label: 'Paquete' }, { value: 'pcs', label: 'Piezas' },
{ value: 'bag', label: 'Bolsa' }, { value: 'pkg', label: 'Paquetes' },
{ value: 'box', label: 'Caja' }, { value: 'bags', label: 'Bolsas' },
{ value: 'dozen', label: 'Docena' }, { value: 'boxes', label: 'Cajas' },
{ value: 'cup', label: 'Taza' },
{ value: 'tbsp', label: 'Cucharada' },
{ value: 'tsp', label: 'Cucharadita' },
], ],
// Default form values for new ingredients // Default form values for new ingredients

View File

@@ -165,7 +165,7 @@ export const commonIngredientTemplates: IngredientTemplate[] = [
{ {
name: 'Huevos', name: 'Huevos',
category: 'Dairy', category: 'Dairy',
unit_of_measure: 'dozen', unit_of_measure: 'units',
icon: '🥚', icon: '🥚',
estimated_shelf_life_days: 21, estimated_shelf_life_days: 21,
requires_refrigeration: true, requires_refrigeration: true,

View File

@@ -601,7 +601,7 @@ export const UploadSalesDataStep: React.FC<UploadSalesDataStepProps> = ({
'Other' 'Other'
]; ];
const unitOptions = ['kg', 'g', 'L', 'ml', 'units', 'dozen']; const unitOptions = ['kg', 'g', 'l', 'ml', 'units', 'pcs', 'pkg', 'bags', 'boxes'];
// INVENTORY LIST VIEW (after AI suggestions loaded) // INVENTORY LIST VIEW (after AI suggestions loaded)
if (showInventoryStep) { if (showInventoryStep) {

View File

@@ -77,16 +77,13 @@ export const UNITS_OF_MEASURE = {
volume: { volume: {
l: { label: 'Litro', symbol: 'l', factor: 1000 }, l: { label: 'Litro', symbol: 'l', factor: 1000 },
ml: { label: 'Mililitro', symbol: 'ml', factor: 1 }, ml: { label: 'Mililitro', symbol: 'ml', factor: 1 },
cup: { label: 'Taza', symbol: 'taza', factor: 240 },
tbsp: { label: 'Cucharada', symbol: 'cda', factor: 15 },
tsp: { label: 'Cucharadita', symbol: 'cdta', factor: 5 },
}, },
count: { count: {
piece: { label: 'Pieza', symbol: 'pz', factor: 1 }, units: { label: 'Unidades', symbol: 'ud', factor: 1 },
dozen: { label: 'Docena', symbol: 'doc', factor: 12 }, pcs: { label: 'Piezas', symbol: 'pz', factor: 1 },
package: { label: 'Paquete', symbol: 'paq', factor: 1 }, pkg: { label: 'Paquetes', symbol: 'paq', factor: 1 },
bag: { label: 'Bolsa', symbol: 'bolsa', factor: 1 }, bags: { label: 'Bolsas', symbol: 'bolsa', factor: 1 },
box: { label: 'Caja', symbol: 'caja', factor: 1 }, boxes: { label: 'Cajas', symbol: 'caja', factor: 1 },
}, },
} as const; } as const;