diff --git a/frontend/src/components/domain/unified-wizard/wizards/SalesEntryWizard.tsx b/frontend/src/components/domain/unified-wizard/wizards/SalesEntryWizard.tsx index a55837b4..e176def2 100644 --- a/frontend/src/components/domain/unified-wizard/wizards/SalesEntryWizard.tsx +++ b/frontend/src/components/domain/unified-wizard/wizards/SalesEntryWizard.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import { WizardStep, WizardStepProps } from '../../../ui/WizardModal/WizardModal'; import { Edit3, @@ -16,6 +16,7 @@ import { } from 'lucide-react'; import { useTenant } from '../../../../stores/tenant.store'; import { salesService } from '../../../../api/services/sales'; +import { inventoryService } from '../../../../api/services/inventory'; // ======================================== // STEP 1: Entry Method Selection @@ -184,17 +185,42 @@ const EntryMethodStep: React.FC = ({ data, onDataChange, o // ======================================== const ManualEntryStep: React.FC = ({ data, onDataChange, onNext }) => { + const { currentTenant } = useTenant(); const [salesItems, setSalesItems] = useState(data.salesItems || []); const [saleDate, setSaleDate] = useState( data.saleDate || new Date().toISOString().split('T')[0] ); const [paymentMethod, setPaymentMethod] = useState(data.paymentMethod || 'cash'); const [notes, setNotes] = useState(data.notes || ''); + const [products, setProducts] = useState([]); + const [loadingProducts, setLoadingProducts] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + fetchProducts(); + }, []); + + const fetchProducts = async () => { + if (!currentTenant?.id) return; + + setLoadingProducts(true); + try { + const result = await inventoryService.getIngredients(currentTenant.id); + // Filter for finished products only + const finishedProducts = result.filter((p: any) => p.category === 'finished_product'); + setProducts(finishedProducts); + } catch (err: any) { + console.error('Error fetching products:', err); + setError('Error al cargar los productos'); + } finally { + setLoadingProducts(false); + } + }; const handleAddItem = () => { setSalesItems([ ...salesItems, - { id: Date.now(), product: '', quantity: 1, unitPrice: 0, subtotal: 0 }, + { id: Date.now(), productId: '', product: '', quantity: 1, unitPrice: 0, subtotal: 0 }, ]); }; @@ -202,8 +228,18 @@ const ManualEntryStep: React.FC = ({ data, onDataChange, o const updated = salesItems.map((item: any, i: number) => { if (i === index) { const newItem = { ...item, [field]: value }; + + // If product is selected, auto-fill price + if (field === 'productId') { + const selectedProduct = products.find((p: any) => p.id === value); + if (selectedProduct) { + newItem.product = selectedProduct.name; + newItem.unitPrice = selectedProduct.average_cost || selectedProduct.last_purchase_price || 0; + } + } + // Auto-calculate subtotal - if (field === 'quantity' || field === 'unitPrice') { + if (field === 'quantity' || field === 'unitPrice' || field === 'productId') { newItem.subtotal = (newItem.quantity || 0) * (newItem.unitPrice || 0); } return newItem; @@ -278,6 +314,13 @@ const ManualEntryStep: React.FC = ({ data, onDataChange, o + {error && ( +
+ + {error} +
+ )} + {/* Sales Items */}
@@ -287,13 +330,25 @@ const ManualEntryStep: React.FC = ({ data, onDataChange, o
- {salesItems.length === 0 ? ( + {loadingProducts ? ( +
+ + Cargando productos... +
+ ) : products.length === 0 ? ( +
+ +

No hay productos terminados disponibles

+

Agrega productos al inventario primero

+
+ ) : salesItems.length === 0 ? (

No hay productos agregados

@@ -308,13 +363,18 @@ const ManualEntryStep: React.FC = ({ data, onDataChange, o >
- handleUpdateItem(index, 'product', e.target.value)} - className="w-full px-2 py-1.5 text-sm border border-[var(--border-secondary)] rounded focus:outline-none focus:ring-1 focus:ring-[var(--color-primary)]" - /> +