function ProductPrice({ salesUrl, token }) { const [productNo, setProductNo] = React.useState(''); const [rows, setRows] = React.useState([]); const [rowEdits, setRowEdits] = React.useState({}); const [loading, setLoading] = React.useState(false); const [error, setError] = React.useState(''); async function showProduct(e) { if (e && e.preventDefault) e.preventDefault(); const needle = (productNo || '').toString().trim(); if (!needle) { setError('Enter a product no'); return; } setError(''); setLoading(true); try { const found = await fetchProduct(needle); if (found.length === 0) { setRows([]); alert('Product not available'); } else { setRows(found); // log current quantities console.log('Current quantities for', needle, found.map(r => ({ productNo: r.productNo || r.productId, qty: r.qty != null ? r.qty : (r.centralQty != null ? r.centralQty : 0) }))); } } catch (err) { console.error('ProductPrice fetch error', err); alert('Failed to fetch product details'); } finally { setLoading(false); } } async function fetchProduct(needle) { const base = (salesUrl || '').replace(/\/$/, ''); const url = base + '/api/branch-stock?productNo=' + encodeURIComponent(needle); const res = await fetch(url, { method: 'GET', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', ...(token ? { Authorization: 'Bearer ' + token } : {}) } }); const data = await res.json(); if (!data || !data.success) return []; return Array.isArray(data.rows) ? data.rows : []; } const currency = (n) => new Intl.NumberFormat('en-IN', { style: 'currency', currency: 'INR', maximumFractionDigits: 2 }).format(n || 0); async function saveWhatsappStock(key, row) { try { const edit = rowEdits[key] || {}; const supplyQty = Number(edit.supplyQty || 0); const sellPercent = Number(edit.sellPercent || 0); // compute selling price same as BranchSupply.jsx: pct ? cost * (1 + pct/100) : row.sellingPrice const cost = Number(row.costPrice ?? row.cost ?? row.totalCostPrice ?? row.totalCost ?? 0); const rawSelling = sellPercent ? (cost * (1 + sellPercent / 100)) : Number(row.sellingPrice || 0); const sellingPrice = Number(Number(rawSelling || 0).toFixed(2)); // set saving flag setRowEdits(s => ({ ...s, [key]: { ...(s[key] || {}), saving: true } })); const base = (salesUrl || '').replace(/\/$/, ''); const payload = { productNo: row.productNo || row.productId || '', productName: row.productName || '', brand: row.brand || '', model: row.model || '', supplyQty, sellPercent, sellingPrice, costPrice: cost, totalCost: Number(row.totalCostPrice || row.totalCost || 0) }; // log current qty before transfer const currentQty = (row.qty != null) ? row.qty : (row.centralQty != null ? row.centralQty : 0); console.log('Before transfer:', { productNo: payload.productNo, currentQty }); const res = await fetch(base + '/api/whatsapp-stock', { method: 'POST', headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: 'Bearer ' + token } : {}) }, body: JSON.stringify(payload) }); const data = await res.json(); if (!res.ok || !data.success) { alert(data.message || 'Save failed'); } else { alert(data.message || 'Saved'); // reflect saved state setRowEdits(s => ({ ...s, [key]: { ...s[key], saving: false } })); // fetch updated product and log new qty try { const refreshed = await fetchProduct(payload.productNo); const updated = refreshed.find(rr => (rr.productNo || rr.productId) === payload.productNo); const newQty = updated ? (updated.qty != null ? updated.qty : (updated.centralQty != null ? updated.centralQty : 0)) : null; console.log('Transfer completed:', { productNo: payload.productNo, supplyQty, before: currentQty, after: newQty }); } catch (e) { console.error('Failed to fetch refreshed product', e); } } } catch (err) { console.error('saveWhatsappStock error', err); alert('Save failed'); setRowEdits(s => ({ ...s, [key]: { ...s[key], saving: false } })); } } return (
{/* Search Section */}

Product Search

Search and manage product pricing for WhatsApp inventory

setProductNo(e.target.value)} placeholder="Enter product number" className="form-input" required />
{error && (
{error}
)}
{/* Results Table */}

Product Pricing

Set pricing and supply quantities for WhatsApp inventory

{rows.length === 0 ? (
📦
No Products Found
Search for a product number to view pricing details
) : ( <>
{rows.map((r, i) => { const key = r.productNo || r.productId || i; const edit = rowEdits[key] || { sellPercent: '', supplyQty: '' }; const availableQty = (r.qty != null) ? r.qty : (r.centralQty != null ? r.centralQty : 0); const cost = Number(r.costPrice ?? r.cost ?? r.totalCostPrice ?? r.totalCost ?? 0); const sellPct = Number(edit.sellPercent || 0); const calculatedPrice = sellPct ? (cost * (1 + sellPct / 100)) : Number(r.sellingPrice || 0); const supplyQty = Number(edit.supplyQty || 0); const isOverSupply = supplyQty > availableQty; return ( ); })}
No. Product No Product Name Brand Model Stock Qty Total Cost Selling Price Supply Qty Action
{i + 1}
{r.productNo || '-'}
{r.productName || '-'}
{r.brand || '-'} {r.model || '-'} {availableQty} {currency(Number(r.totalCostPrice || r.totalCost || 0))}
setRowEdits(s => ({ ...s, [key]: { ...edit, sellPercent: e.target.value } }))} /> %
{calculatedPrice ? currency(Number(calculatedPrice.toFixed(2))) : '-'}
setRowEdits(s => ({ ...s, [key]: { ...edit, supplyQty: e.target.value } }))} />
{isOverSupply && (
Exceeds stock
)}
)}
); } window.ProductPrice = ProductPrice;