remove npv in roi calculator

This commit is contained in:
Tobias Brunner 2025-07-21 16:12:53 +02:00
parent cea00c7e8c
commit 25400be405
Signed by: tobru
SSH key fingerprint: SHA256:kOXg1R6c11XW3/Pt9dbLdQvOJGFAy+B2K6v6PtRWBGQ
2 changed files with 3 additions and 67 deletions

View file

@ -51,7 +51,6 @@ class ROICalculator {
return {
investmentAmount: parseFloat(document.getElementById('investment-amount').getAttribute('data-value')),
timeframe: parseInt(document.getElementById('timeframe').value),
discountRate: parseFloat(document.getElementById('discount-rate').value) / 100,
revenuePerInstance: parseFloat(document.getElementById('revenue-per-instance').value),
servalaShare: parseFloat(document.getElementById('servala-share').value) / 100,
gracePeriod: parseInt(document.getElementById('grace-period').value)
@ -81,11 +80,6 @@ class ROICalculator {
let cumulativeCSPRevenue = 0;
let cumulativeServalaRevenue = 0;
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
let currentPhase = 0;
@ -130,15 +124,6 @@ class ROICalculator {
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({
month,
scenario: scenario.name,
@ -150,8 +135,6 @@ class ROICalculator {
servalaRevenue,
cumulativeCSPRevenue,
cumulativeServalaRevenue,
discountedCashFlow,
totalDiscountedCashFlow: totalDiscountedCashFlow + inputs.investmentAmount,
investmentScaleFactor: investmentScaleFactor,
adjustedChurnRate: adjustedChurnRate
});
@ -162,7 +145,6 @@ class ROICalculator {
// Calculate final metrics
const totalRevenue = cumulativeCSPRevenue + cumulativeServalaRevenue;
const roi = ((cumulativeCSPRevenue - inputs.investmentAmount) / inputs.investmentAmount) * 100;
const npv = totalDiscountedCashFlow;
return {
scenario: scenario.name,
@ -171,9 +153,7 @@ class ROICalculator {
cspRevenue: cumulativeCSPRevenue,
servalaRevenue: cumulativeServalaRevenue,
roi,
npv,
breakEvenMonth,
npvBreakEvenMonth,
monthlyData,
investmentScaleFactor: investmentScaleFactor,
adjustedChurnRate: adjustedChurnRate * 100
@ -370,7 +350,6 @@ class ROICalculator {
<td>${this.formatCurrencyDetailed(result.servalaRevenue)}</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.npvBreakEvenMonth ? result.npvBreakEvenMonth + ' months' : 'N/A'}</td>
`;
});
}
@ -552,11 +531,6 @@ function updateInvestmentAmount(value) {
updateCalculations();
}
function updateDiscountRate(value) {
document.getElementById('discount-rate').value = value;
updateCalculations();
}
function updateRevenuePerInstance(value) {
document.getElementById('revenue-per-instance').value = value;
updateCalculations();
@ -716,7 +690,6 @@ function exportToPDF() {
const params = [
['Investment Amount:', calculator.formatCurrencyDetailed(inputs.investmentAmount)],
['Investment Timeframe:', `${inputs.timeframe} years`],
['Discount Rate:', `${(inputs.discountRate * 100).toFixed(1)}%`],
['Revenue per Instance:', calculator.formatCurrencyDetailed(inputs.revenuePerInstance)],
['Servala Revenue Share:', `${(inputs.servalaShare * 100).toFixed(0)}%`],
['Grace Period:', `${inputs.gracePeriod} months`]
@ -756,8 +729,7 @@ function exportToPDF() {
['CSP Revenue:', calculator.formatCurrencyDetailed(result.cspRevenue)],
['Servala Revenue:', calculator.formatCurrencyDetailed(result.servalaRevenue)],
['ROI:', calculator.formatPercentage(result.roi)],
['Break-even:', result.breakEvenMonth ? `${result.breakEvenMonth} months` : 'Not achieved'],
['NPV Break-even:', result.npvBreakEvenMonth ? `${result.npvBreakEvenMonth} months` : 'Not achieved']
['Break-even:', result.breakEvenMonth ? `${result.breakEvenMonth} months` : 'Not achieved']
];
resultData.forEach(([label, value]) => {
@ -803,8 +775,6 @@ function exportToPDF() {
doc.text('• Churn rates reflect typical SaaS industry standards', 30, yPos);
yPos += 6;
doc.text('• Revenue calculations include grace period provisions', 30, yPos);
yPos += 6;
doc.text('• NPV calculations use specified discount rate', 30, yPos);
}
// Add footer
@ -838,17 +808,16 @@ function exportToCSV() {
const inputs = calculator.getInputValues();
csvContent += `Investment Amount,${inputs.investmentAmount}\n`;
csvContent += `Timeframe (years),${inputs.timeframe}\n`;
csvContent += `Discount Rate (%),${(inputs.discountRate * 100).toFixed(1)}\n`;
csvContent += `Revenue per Instance,${inputs.revenuePerInstance}\n`;
csvContent += `Servala Share (%),${(inputs.servalaShare * 100).toFixed(0)}\n`;
csvContent += `Grace Period (months),${inputs.gracePeriod}\n\n`;
// Add scenario summary
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 => {
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';
@ -903,8 +872,6 @@ function resetCalculator() {
investmentInput.value = '500,000';
document.getElementById('investment-slider').value = 500000;
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-slider').value = 50;
document.getElementById('servala-share').value = 25;