From bedd4868acf50d26067e0c0b9a37b3d584269079 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 7 Nov 2025 08:36:35 +0000 Subject: [PATCH] Fix invalid unit_of_measure 'dozen' causing 422 API errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **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 --- .../domain/inventory/BatchAddIngredientsModal.tsx | 2 +- .../domain/inventory/QuickAddIngredientModal.tsx | 2 +- frontend/src/components/domain/inventory/index.ts | 15 ++++++--------- .../domain/inventory/ingredientHelpers.ts | 2 +- .../onboarding/steps/UploadSalesDataStep.tsx | 2 +- frontend/src/utils/constants.ts | 13 +++++-------- 6 files changed, 15 insertions(+), 21 deletions(-) diff --git a/frontend/src/components/domain/inventory/BatchAddIngredientsModal.tsx b/frontend/src/components/domain/inventory/BatchAddIngredientsModal.tsx index 75e5ea8a..b8be6c46 100644 --- a/frontend/src/components/domain/inventory/BatchAddIngredientsModal.tsx +++ b/frontend/src/components/domain/inventory/BatchAddIngredientsModal.tsx @@ -50,7 +50,7 @@ export const BatchAddIngredientsModal: React.FC = '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) => { setRows(rows.map(row => diff --git a/frontend/src/components/domain/inventory/QuickAddIngredientModal.tsx b/frontend/src/components/domain/inventory/QuickAddIngredientModal.tsx index 752c4fbb..91a0aa55 100644 --- a/frontend/src/components/domain/inventory/QuickAddIngredientModal.tsx +++ b/frontend/src/components/domain/inventory/QuickAddIngredientModal.tsx @@ -66,7 +66,7 @@ export const QuickAddIngredientModal: React.FC = ( '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 useEffect(() => { diff --git a/frontend/src/components/domain/inventory/index.ts b/frontend/src/components/domain/inventory/index.ts index 352611f0..387edbd5 100644 --- a/frontend/src/components/domain/inventory/index.ts +++ b/frontend/src/components/domain/inventory/index.ts @@ -48,20 +48,17 @@ export const INVENTORY_CONSTANTS = { { value: 'out', label: 'Sin Stock' }, ], - // Units of measure commonly used in Spanish bakeries + // Units of measure - must match backend UnitOfMeasure enum exactly BAKERY_UNITS: [ { value: 'kg', label: 'Kilogramo (kg)' }, { value: 'g', label: 'Gramo (g)' }, { value: 'l', label: 'Litro (l)' }, { value: 'ml', label: 'Mililitro (ml)' }, - { value: 'piece', label: 'Pieza (pz)' }, - { value: 'package', label: 'Paquete' }, - { value: 'bag', label: 'Bolsa' }, - { value: 'box', label: 'Caja' }, - { value: 'dozen', label: 'Docena' }, - { value: 'cup', label: 'Taza' }, - { value: 'tbsp', label: 'Cucharada' }, - { value: 'tsp', label: 'Cucharadita' }, + { value: 'units', label: 'Unidades' }, + { value: 'pcs', label: 'Piezas' }, + { value: 'pkg', label: 'Paquetes' }, + { value: 'bags', label: 'Bolsas' }, + { value: 'boxes', label: 'Cajas' }, ], // Default form values for new ingredients diff --git a/frontend/src/components/domain/inventory/ingredientHelpers.ts b/frontend/src/components/domain/inventory/ingredientHelpers.ts index 91551520..e8a8e819 100644 --- a/frontend/src/components/domain/inventory/ingredientHelpers.ts +++ b/frontend/src/components/domain/inventory/ingredientHelpers.ts @@ -165,7 +165,7 @@ export const commonIngredientTemplates: IngredientTemplate[] = [ { name: 'Huevos', category: 'Dairy', - unit_of_measure: 'dozen', + unit_of_measure: 'units', icon: '🥚', estimated_shelf_life_days: 21, requires_refrigeration: true, diff --git a/frontend/src/components/domain/onboarding/steps/UploadSalesDataStep.tsx b/frontend/src/components/domain/onboarding/steps/UploadSalesDataStep.tsx index 16ed6968..59d43cce 100644 --- a/frontend/src/components/domain/onboarding/steps/UploadSalesDataStep.tsx +++ b/frontend/src/components/domain/onboarding/steps/UploadSalesDataStep.tsx @@ -601,7 +601,7 @@ export const UploadSalesDataStep: React.FC = ({ '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) if (showInventoryStep) { diff --git a/frontend/src/utils/constants.ts b/frontend/src/utils/constants.ts index b162b23c..ab307d73 100644 --- a/frontend/src/utils/constants.ts +++ b/frontend/src/utils/constants.ts @@ -77,16 +77,13 @@ export const UNITS_OF_MEASURE = { volume: { l: { label: 'Litro', symbol: 'l', factor: 1000 }, 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: { - piece: { label: 'Pieza', symbol: 'pz', factor: 1 }, - dozen: { label: 'Docena', symbol: 'doc', factor: 12 }, - package: { label: 'Paquete', symbol: 'paq', factor: 1 }, - bag: { label: 'Bolsa', symbol: 'bolsa', factor: 1 }, - box: { label: 'Caja', symbol: 'caja', factor: 1 }, + units: { label: 'Unidades', symbol: 'ud', factor: 1 }, + pcs: { label: 'Piezas', symbol: 'pz', factor: 1 }, + pkg: { label: 'Paquetes', symbol: 'paq', factor: 1 }, + bags: { label: 'Bolsas', symbol: 'bolsa', factor: 1 }, + boxes: { label: 'Cajas', symbol: 'caja', factor: 1 }, }, } as const;