Dynamic Inventory Pricing Strategy Tool

Dynamic Inventory Pricing Strategy Tool

Automatically adjust product prices based on inventory and sales velocity.

Suggested Price Adjustments

Configure your data and rules, then click "Apply Rules & Calculate Prices" on the configuration tab.

${results.increasedCount}

Unchanged

${results.unchangedCount}

`; let tableHtml = ``; results.pricedProducts.forEach(p => { const changeColor = p.priceChange > 0 ? 'text-green-600' : p.priceChange < 0 ? 'text-red-600' : 'text-gray-500'; tableHtml += ``; }); tableHtml += `
Product Applied Rule Original Price New Price Change
${p.name} ${p.appliedRule} $${p.price.toFixed(2)} $${p.newPrice.toFixed(2)} ${p.priceChange !== 0 ? p.priceChange.toFixed(2) + '%' : '-'}
`; resultsContainer.innerHTML = tableHtml; }; // --- CORE LOGIC --- const handleCalculation = () => { calculateBtnSpinner.classList.remove('hidden'); calculateBtnText.textContent = 'Calculating...'; calculateBtn.disabled = true; setTimeout(() => { let discountedCount = 0, increasedCount = 0; const pricedProducts = products.map(p => { let newPrice = p.price; let appliedRule = 'None'; let priceChange = 0; for (const rule of rules) { const inv_check = rule.inv_cond === '>' ? p.inventory > rule.inv_val : p.inventory < rule.inv_val; const vel_check = rule.vel_cond === '>' ? p.velocity > rule.vel_val : p.velocity < rule.vel_val; if (inv_check && vel_check) { appliedRule = rule.name; if (rule.action_type === 'discount') { priceChange = -rule.action_val; newPrice = p.price * (1 - rule.action_val / 100); discountedCount++; } else { priceChange = rule.action_val; newPrice = p.price * (1 + rule.action_val / 100); increasedCount++; } break; } } return { ...p, newPrice, appliedRule, priceChange }; }); const results = { pricedProducts, discountedCount, increasedCount, unchangedCount: products.length - (discountedCount + increasedCount) }; renderDashboard(results); switchTab('dashboard'); downloadPdfBtn.disabled = false; calculateBtnSpinner.classList.add('hidden'); calculateBtnText.textContent = 'Apply Rules & Calculate Prices'; calculateBtn.disabled = false; }, 500); }; // --- UI & EVENT HANDLERS --- const switchTab = (tabId) => { currentTab = tabId; Object.values(tabPanes).forEach(pane => pane.classList.add('hidden')); tabPanes[tabId].classList.remove('hidden'); Object.values(tabButtons).forEach(btn => btn.classList.replace('tab-active', 'tab-inactive')); tabButtons[tabId].classList.replace('tab-inactive', 'tab-active'); updateNavButtons(); }; const navigateTabs = (direction) => { const currentIndex = tabs.indexOf(currentTab); const newIndex = direction === 'next' ? currentIndex + 1 : currentIndex - 1; if (newIndex >= 0 && newIndex < tabs.length) switchTab(tabs[newIndex]); }; const updateNavButtons = () => { const currentIndex = tabs.indexOf(currentTab); prevBtn.disabled = currentIndex === 0; nextBtn.disabled = currentIndex === tabs.length - 1; prevBtn.classList.toggle('opacity-50', prevBtn.disabled); nextBtn.classList.toggle('opacity-50', nextBtn.disabled); }; const handlePdfDownload = () => { const pdfRenderContainer = document.getElementById('pdf-render-content'); const pdfContent = document.getElementById('pdf-content').innerHTML; const header = `

Dynamic Pricing Report

`; pdfRenderContainer.innerHTML = header + pdfContent + '
'; html2canvas(pdfRenderContainer, { scale: 2 }).then(canvas => { const imgData = canvas.toDataURL('image/png'); const { jsPDF } = window.jspdf; const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(), margin = 40; const contentWidth = pdfWidth - margin * 2; const pdfHeight = (canvas.height * contentWidth) / canvas.width; pdf.addImage(imgData, 'PNG', margin, margin, contentWidth, pdfHeight); pdf.save('Dynamic-Pricing-Report.pdf'); }); }; // --- EVENT LISTENERS --- window.switchTab = switchTab; window.navigateTabs = navigateTabs; calculateBtn.addEventListener('click', handleCalculation); downloadPdfBtn.addEventListener('click', handlePdfDownload); addProductBtn.addEventListener('click', () => { products.push({ id: nextProductId++, name: 'New Product', inventory: 0, velocity: 0, price: 0 }); renderConfig(); }); addRuleBtn.addEventListener('click', () => { rules.push({ id: nextRuleId++, name: 'New Rule', inv_cond: '>', inv_val: 0, vel_cond: '>', vel_val: 0, action_type: 'discount', action_val: 10 }); renderConfig(); }); productsBody.addEventListener('input', e => { if (!e.target.classList.contains('cfg-input')) return; const id = parseInt(e.target.closest('tr').dataset.id); const prop = e.target.dataset.prop; const item = products.find(p => p.id === id); if (item) item[prop] = e.target.type === 'number' ? parseFloat(e.target.value) : e.target.value; }); productsBody.addEventListener('click', e => { if (!e.target.classList.contains('rm-prod-btn')) return; const id = parseInt(e.target.closest('tr').dataset.id); products = products.filter(p => p.id !== id); renderConfig(); }); rulesContainer.addEventListener('change', e => { const id = parseInt(e.target.closest('[data-id]').dataset.id); const prop = e.target.dataset.prop; const item = rules.find(r => r.id === id); if(item) item[prop] = e.target.type === 'number' ? parseFloat(e.target.value) : e.target.value; }); rulesContainer.addEventListener('click', e => { if (!e.target.classList.contains('rm-rule-btn')) return; const id = parseInt(e.target.closest('[data-id]').dataset.id); rules = rules.filter(r => r.id !== id); renderConfig(); }); // --- INITIALIZATION --- renderConfig(); updateNavButtons(); switchTab('dashboard'); });
Scroll to Top