remove npv in roi calculator
This commit is contained in:
parent
cea00c7e8c
commit
25400be405
2 changed files with 3 additions and 67 deletions
|
|
@ -51,7 +51,6 @@ class ROICalculator {
|
||||||
return {
|
return {
|
||||||
investmentAmount: parseFloat(document.getElementById('investment-amount').getAttribute('data-value')),
|
investmentAmount: parseFloat(document.getElementById('investment-amount').getAttribute('data-value')),
|
||||||
timeframe: parseInt(document.getElementById('timeframe').value),
|
timeframe: parseInt(document.getElementById('timeframe').value),
|
||||||
discountRate: parseFloat(document.getElementById('discount-rate').value) / 100,
|
|
||||||
revenuePerInstance: parseFloat(document.getElementById('revenue-per-instance').value),
|
revenuePerInstance: parseFloat(document.getElementById('revenue-per-instance').value),
|
||||||
servalaShare: parseFloat(document.getElementById('servala-share').value) / 100,
|
servalaShare: parseFloat(document.getElementById('servala-share').value) / 100,
|
||||||
gracePeriod: parseInt(document.getElementById('grace-period').value)
|
gracePeriod: parseInt(document.getElementById('grace-period').value)
|
||||||
|
|
@ -81,11 +80,6 @@ class ROICalculator {
|
||||||
let cumulativeCSPRevenue = 0;
|
let cumulativeCSPRevenue = 0;
|
||||||
let cumulativeServalaRevenue = 0;
|
let cumulativeServalaRevenue = 0;
|
||||||
let breakEvenMonth = null;
|
let breakEvenMonth = null;
|
||||||
let npvBreakEvenMonth = null;
|
|
||||||
let totalDiscountedCashFlow = -inputs.investmentAmount;
|
|
||||||
|
|
||||||
// Calculate monthly discount rate
|
|
||||||
const monthlyDiscountRate = Math.pow(1 + inputs.discountRate, 1 / 12) - 1;
|
|
||||||
|
|
||||||
// Track phase progression
|
// Track phase progression
|
||||||
let currentPhase = 0;
|
let currentPhase = 0;
|
||||||
|
|
@ -130,15 +124,6 @@ class ROICalculator {
|
||||||
breakEvenMonth = month;
|
breakEvenMonth = month;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate NPV break-even
|
|
||||||
const discountFactor = Math.pow(1 + monthlyDiscountRate, month);
|
|
||||||
const discountedCashFlow = cspRevenue / discountFactor;
|
|
||||||
totalDiscountedCashFlow += discountedCashFlow;
|
|
||||||
|
|
||||||
if (npvBreakEvenMonth === null && totalDiscountedCashFlow >= 0) {
|
|
||||||
npvBreakEvenMonth = month;
|
|
||||||
}
|
|
||||||
|
|
||||||
monthlyData.push({
|
monthlyData.push({
|
||||||
month,
|
month,
|
||||||
scenario: scenario.name,
|
scenario: scenario.name,
|
||||||
|
|
@ -150,8 +135,6 @@ class ROICalculator {
|
||||||
servalaRevenue,
|
servalaRevenue,
|
||||||
cumulativeCSPRevenue,
|
cumulativeCSPRevenue,
|
||||||
cumulativeServalaRevenue,
|
cumulativeServalaRevenue,
|
||||||
discountedCashFlow,
|
|
||||||
totalDiscountedCashFlow: totalDiscountedCashFlow + inputs.investmentAmount,
|
|
||||||
investmentScaleFactor: investmentScaleFactor,
|
investmentScaleFactor: investmentScaleFactor,
|
||||||
adjustedChurnRate: adjustedChurnRate
|
adjustedChurnRate: adjustedChurnRate
|
||||||
});
|
});
|
||||||
|
|
@ -162,7 +145,6 @@ class ROICalculator {
|
||||||
// Calculate final metrics
|
// Calculate final metrics
|
||||||
const totalRevenue = cumulativeCSPRevenue + cumulativeServalaRevenue;
|
const totalRevenue = cumulativeCSPRevenue + cumulativeServalaRevenue;
|
||||||
const roi = ((cumulativeCSPRevenue - inputs.investmentAmount) / inputs.investmentAmount) * 100;
|
const roi = ((cumulativeCSPRevenue - inputs.investmentAmount) / inputs.investmentAmount) * 100;
|
||||||
const npv = totalDiscountedCashFlow;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
scenario: scenario.name,
|
scenario: scenario.name,
|
||||||
|
|
@ -171,9 +153,7 @@ class ROICalculator {
|
||||||
cspRevenue: cumulativeCSPRevenue,
|
cspRevenue: cumulativeCSPRevenue,
|
||||||
servalaRevenue: cumulativeServalaRevenue,
|
servalaRevenue: cumulativeServalaRevenue,
|
||||||
roi,
|
roi,
|
||||||
npv,
|
|
||||||
breakEvenMonth,
|
breakEvenMonth,
|
||||||
npvBreakEvenMonth,
|
|
||||||
monthlyData,
|
monthlyData,
|
||||||
investmentScaleFactor: investmentScaleFactor,
|
investmentScaleFactor: investmentScaleFactor,
|
||||||
adjustedChurnRate: adjustedChurnRate * 100
|
adjustedChurnRate: adjustedChurnRate * 100
|
||||||
|
|
@ -370,7 +350,6 @@ class ROICalculator {
|
||||||
<td>${this.formatCurrencyDetailed(result.servalaRevenue)}</td>
|
<td>${this.formatCurrencyDetailed(result.servalaRevenue)}</td>
|
||||||
<td class="${result.roi >= 0 ? 'text-success' : 'text-danger'}">${this.formatPercentage(result.roi)}</td>
|
<td class="${result.roi >= 0 ? 'text-success' : 'text-danger'}">${this.formatPercentage(result.roi)}</td>
|
||||||
<td>${result.breakEvenMonth ? result.breakEvenMonth + ' months' : 'N/A'}</td>
|
<td>${result.breakEvenMonth ? result.breakEvenMonth + ' months' : 'N/A'}</td>
|
||||||
<td>${result.npvBreakEvenMonth ? result.npvBreakEvenMonth + ' months' : 'N/A'}</td>
|
|
||||||
`;
|
`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -552,11 +531,6 @@ function updateInvestmentAmount(value) {
|
||||||
updateCalculations();
|
updateCalculations();
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateDiscountRate(value) {
|
|
||||||
document.getElementById('discount-rate').value = value;
|
|
||||||
updateCalculations();
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateRevenuePerInstance(value) {
|
function updateRevenuePerInstance(value) {
|
||||||
document.getElementById('revenue-per-instance').value = value;
|
document.getElementById('revenue-per-instance').value = value;
|
||||||
updateCalculations();
|
updateCalculations();
|
||||||
|
|
@ -716,7 +690,6 @@ function exportToPDF() {
|
||||||
const params = [
|
const params = [
|
||||||
['Investment Amount:', calculator.formatCurrencyDetailed(inputs.investmentAmount)],
|
['Investment Amount:', calculator.formatCurrencyDetailed(inputs.investmentAmount)],
|
||||||
['Investment Timeframe:', `${inputs.timeframe} years`],
|
['Investment Timeframe:', `${inputs.timeframe} years`],
|
||||||
['Discount Rate:', `${(inputs.discountRate * 100).toFixed(1)}%`],
|
|
||||||
['Revenue per Instance:', calculator.formatCurrencyDetailed(inputs.revenuePerInstance)],
|
['Revenue per Instance:', calculator.formatCurrencyDetailed(inputs.revenuePerInstance)],
|
||||||
['Servala Revenue Share:', `${(inputs.servalaShare * 100).toFixed(0)}%`],
|
['Servala Revenue Share:', `${(inputs.servalaShare * 100).toFixed(0)}%`],
|
||||||
['Grace Period:', `${inputs.gracePeriod} months`]
|
['Grace Period:', `${inputs.gracePeriod} months`]
|
||||||
|
|
@ -756,8 +729,7 @@ function exportToPDF() {
|
||||||
['CSP Revenue:', calculator.formatCurrencyDetailed(result.cspRevenue)],
|
['CSP Revenue:', calculator.formatCurrencyDetailed(result.cspRevenue)],
|
||||||
['Servala Revenue:', calculator.formatCurrencyDetailed(result.servalaRevenue)],
|
['Servala Revenue:', calculator.formatCurrencyDetailed(result.servalaRevenue)],
|
||||||
['ROI:', calculator.formatPercentage(result.roi)],
|
['ROI:', calculator.formatPercentage(result.roi)],
|
||||||
['Break-even:', result.breakEvenMonth ? `${result.breakEvenMonth} months` : 'Not achieved'],
|
['Break-even:', result.breakEvenMonth ? `${result.breakEvenMonth} months` : 'Not achieved']
|
||||||
['NPV Break-even:', result.npvBreakEvenMonth ? `${result.npvBreakEvenMonth} months` : 'Not achieved']
|
|
||||||
];
|
];
|
||||||
|
|
||||||
resultData.forEach(([label, value]) => {
|
resultData.forEach(([label, value]) => {
|
||||||
|
|
@ -803,8 +775,6 @@ function exportToPDF() {
|
||||||
doc.text('• Churn rates reflect typical SaaS industry standards', 30, yPos);
|
doc.text('• Churn rates reflect typical SaaS industry standards', 30, yPos);
|
||||||
yPos += 6;
|
yPos += 6;
|
||||||
doc.text('• Revenue calculations include grace period provisions', 30, yPos);
|
doc.text('• Revenue calculations include grace period provisions', 30, yPos);
|
||||||
yPos += 6;
|
|
||||||
doc.text('• NPV calculations use specified discount rate', 30, yPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add footer
|
// Add footer
|
||||||
|
|
@ -838,17 +808,16 @@ function exportToCSV() {
|
||||||
const inputs = calculator.getInputValues();
|
const inputs = calculator.getInputValues();
|
||||||
csvContent += `Investment Amount,${inputs.investmentAmount}\n`;
|
csvContent += `Investment Amount,${inputs.investmentAmount}\n`;
|
||||||
csvContent += `Timeframe (years),${inputs.timeframe}\n`;
|
csvContent += `Timeframe (years),${inputs.timeframe}\n`;
|
||||||
csvContent += `Discount Rate (%),${(inputs.discountRate * 100).toFixed(1)}\n`;
|
|
||||||
csvContent += `Revenue per Instance,${inputs.revenuePerInstance}\n`;
|
csvContent += `Revenue per Instance,${inputs.revenuePerInstance}\n`;
|
||||||
csvContent += `Servala Share (%),${(inputs.servalaShare * 100).toFixed(0)}\n`;
|
csvContent += `Servala Share (%),${(inputs.servalaShare * 100).toFixed(0)}\n`;
|
||||||
csvContent += `Grace Period (months),${inputs.gracePeriod}\n\n`;
|
csvContent += `Grace Period (months),${inputs.gracePeriod}\n\n`;
|
||||||
|
|
||||||
// Add scenario summary
|
// Add scenario summary
|
||||||
csvContent += 'SCENARIO SUMMARY\n';
|
csvContent += 'SCENARIO SUMMARY\n';
|
||||||
csvContent += 'Scenario,Final Instances,Total Revenue,CSP Revenue,Servala Revenue,ROI (%),Break-even (months),NPV Break-even (months)\n';
|
csvContent += 'Scenario,Final Instances,Total Revenue,CSP Revenue,Servala Revenue,ROI (%),Break-even (months)\n';
|
||||||
|
|
||||||
Object.values(calculator.results).forEach(result => {
|
Object.values(calculator.results).forEach(result => {
|
||||||
csvContent += `${result.scenario},${result.finalInstances},${result.totalRevenue.toFixed(2)},${result.cspRevenue.toFixed(2)},${result.servalaRevenue.toFixed(2)},${result.roi.toFixed(2)},${result.breakEvenMonth || 'N/A'},${result.npvBreakEvenMonth || 'N/A'}\n`;
|
csvContent += `${result.scenario},${result.finalInstances},${result.totalRevenue.toFixed(2)},${result.cspRevenue.toFixed(2)},${result.servalaRevenue.toFixed(2)},${result.roi.toFixed(2)},${result.breakEvenMonth || 'N/A'}\n`;
|
||||||
});
|
});
|
||||||
|
|
||||||
csvContent += '\n';
|
csvContent += '\n';
|
||||||
|
|
@ -903,8 +872,6 @@ function resetCalculator() {
|
||||||
investmentInput.value = '500,000';
|
investmentInput.value = '500,000';
|
||||||
document.getElementById('investment-slider').value = 500000;
|
document.getElementById('investment-slider').value = 500000;
|
||||||
document.getElementById('timeframe').value = 3;
|
document.getElementById('timeframe').value = 3;
|
||||||
document.getElementById('discount-rate').value = 10;
|
|
||||||
document.getElementById('discount-slider').value = 10;
|
|
||||||
document.getElementById('revenue-per-instance').value = 50;
|
document.getElementById('revenue-per-instance').value = 50;
|
||||||
document.getElementById('revenue-slider').value = 50;
|
document.getElementById('revenue-slider').value = 50;
|
||||||
document.getElementById('servala-share').value = 25;
|
document.getElementById('servala-share').value = 25;
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,6 @@
|
||||||
<p><strong>Monthly Revenue per Instance:</strong> The recurring revenue generated from each managed service instance (excl. compute).</p>
|
<p><strong>Monthly Revenue per Instance:</strong> The recurring revenue generated from each managed service instance (excl. compute).</p>
|
||||||
<p><strong>Servala Revenue Share:</strong> Percentage of revenue shared with Servala after the grace period. This is Servala's platform fee.</p>
|
<p><strong>Servala Revenue Share:</strong> Percentage of revenue shared with Servala after the grace period. This is Servala's platform fee.</p>
|
||||||
<p><strong>Grace Period:</strong> Initial months where you keep 100% of revenue before sharing begins with Servala.</p>
|
<p><strong>Grace Period:</strong> Initial months where you keep 100% of revenue before sharing begins with Servala.</p>
|
||||||
<p><strong>Discount Rate:</strong> Used for NPV calculations - represents your required rate of return or cost of capital.</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h6 class="text-primary mb-2 mt-3"><i class="bi bi-graph-up"></i> Growth Scenarios</h6>
|
<h6 class="text-primary mb-2 mt-3"><i class="bi bi-graph-up"></i> Growth Scenarios</h6>
|
||||||
|
|
@ -68,14 +67,10 @@
|
||||||
<p>Each scenario has 4 growth phases with customizable instance acquisition rates in Advanced Parameters.</p>
|
<p>Each scenario has 4 growth phases with customizable instance acquisition rates in Advanced Parameters.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h6 class="text-primary mb-2 mt-3"><i class="bi bi-calculator"></i> What is NPV?</h6>
|
|
||||||
<p class="small"><strong>Net Present Value (NPV)</strong> represents the current worth of future cash flows, discounted back to today's value using your discount rate. A positive NPV indicates the investment is profitable. NPV accounts for the time value of money - money received today is worth more than the same amount received in the future.</p>
|
|
||||||
|
|
||||||
<h6 class="text-primary mb-2 mt-3"><i class="bi bi-bullseye"></i> Understanding Results</h6>
|
<h6 class="text-primary mb-2 mt-3"><i class="bi bi-bullseye"></i> Understanding Results</h6>
|
||||||
<div class="small">
|
<div class="small">
|
||||||
<p><strong>ROI:</strong> Return on Investment as a percentage of your initial investment.</p>
|
<p><strong>ROI:</strong> Return on Investment as a percentage of your initial investment.</p>
|
||||||
<p><strong>Break-even:</strong> Month when cumulative revenue equals your initial investment.</p>
|
<p><strong>Break-even:</strong> Month when cumulative revenue equals your initial investment.</p>
|
||||||
<p><strong>NPV Break-even:</strong> Month when discounted cash flows become positive (more accurate timing).</p>
|
|
||||||
<p><strong>Churn:</strong> Monthly percentage of instances that stop generating revenue (customer loss).</p>
|
<p><strong>Churn:</strong> Monthly percentage of instances that stop generating revenue (customer loss).</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -158,31 +153,6 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-group-custom">
|
|
||||||
<label for="discount-rate">
|
|
||||||
Discount Rate for NPV (%)
|
|
||||||
<i class="bi bi-question-circle-fill text-muted ms-1"
|
|
||||||
data-bs-toggle="tooltip"
|
|
||||||
data-bs-placement="top"
|
|
||||||
title="The discount rate represents your required rate of return or cost of capital. It's used to calculate the present value of future cash flows. A higher rate means you need higher returns to justify the investment. For example: 8-10% for conservative investors, 12-15% for moderate risk tolerance, 15-20% for high-risk/high-return expectations. This rate accounts for inflation, risk, and opportunity cost of your capital."
|
|
||||||
style="cursor: help; font-size: 0.8rem;"></i>
|
|
||||||
</label>
|
|
||||||
<input type="number" class="form-control" id="discount-rate"
|
|
||||||
min="5" max="20" step="0.5" value="10"
|
|
||||||
onchange="updateCalculations()">
|
|
||||||
<div class="slider-container">
|
|
||||||
<input type="range" class="slider" id="discount-slider"
|
|
||||||
min="5" max="20" step="0.5" value="10"
|
|
||||||
onchange="updateDiscountRate(this.value)">
|
|
||||||
</div>
|
|
||||||
<small class="text-muted">5% - 20% (your required annual return rate)</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Revenue Model -->
|
|
||||||
<div class="calculator-section">
|
|
||||||
<h4><i class="bi bi-graph-up"></i> Revenue Model</h4>
|
|
||||||
|
|
||||||
<div class="input-group-custom">
|
<div class="input-group-custom">
|
||||||
<label for="revenue-per-instance">Monthly Revenue per Instance</label>
|
<label for="revenue-per-instance">Monthly Revenue per Instance</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
|
|
@ -534,7 +504,6 @@
|
||||||
<th>Servala Revenue</th>
|
<th>Servala Revenue</th>
|
||||||
<th>ROI</th>
|
<th>ROI</th>
|
||||||
<th>Break-even</th>
|
<th>Break-even</th>
|
||||||
<th>NPV Break-even</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id="comparison-tbody">
|
<tbody id="comparison-tbody">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue