From 6f6c80480fb2058060604e251ca13cec47094a3d Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 22 Jul 2025 09:16:40 +0200 Subject: [PATCH] rework investment model --- SERVALA_INVESTMENT_MODELS.md | 342 ++++++++++++++++++ .../js/roi-calculator/calculator-core.js | 111 +++++- .../static/js/roi-calculator/chart-manager.js | 148 +++++--- .../js/roi-calculator/roi-calculator-app.js | 4 +- .../static/js/roi-calculator/ui-manager.js | 72 +++- .../calculator/csp_roi_calculator.html | 97 ++--- 6 files changed, 633 insertions(+), 141 deletions(-) create mode 100644 SERVALA_INVESTMENT_MODELS.md diff --git a/SERVALA_INVESTMENT_MODELS.md b/SERVALA_INVESTMENT_MODELS.md new file mode 100644 index 0000000..f2f1c62 --- /dev/null +++ b/SERVALA_INVESTMENT_MODELS.md @@ -0,0 +1,342 @@ +# Servala Investment Models: Comprehensive Guide + +This document provides detailed information about Servala's two investment models for Cloud Service Providers (CSPs) looking to expand their service portfolio through partnership with Servala's managed services platform. + +## Executive Summary + +Servala offers two distinct investment approaches for CSPs: + +1. **Loan Model**: Low-risk, predictable returns through lending to Servala +2. **Direct Investment Model**: Higher potential returns through performance-based revenue sharing + +Both models enable CSPs to capitalize on the growing demand for managed cloud services while supporting Servala's platform expansion. + +--- + +## Investment Model #1: Loan Model + +### Overview +The Loan Model provides CSPs with a traditional lending arrangement where they provide capital to Servala at a fixed interest rate, receiving guaranteed monthly payments regardless of business performance. + +### Key Characteristics + +#### Financial Structure +- **Investment Range**: CHF 100,000 - CHF 2,000,000 +- **Interest Rates**: Typically 3-7% annually (negotiable) +- **Payment Schedule**: Fixed monthly payments using standard amortization +- **Term Length**: 1-5 years (customizable) + +#### Payment Calculation +Monthly payments are calculated using the standard amortization formula: +``` +Monthly Payment = P × [r(1+r)^n] / [(1+r)^n - 1] +Where: +- P = Principal loan amount +- r = Monthly interest rate (annual rate ÷ 12) +- n = Total number of payments (years × 12) +``` + +#### Revenue Distribution +- **CSP**: 100% of monthly loan payments +- **Servala**: 0% (receives loan capital for operations) + +#### Break-Even Analysis +- **Break-even occurs**: When cumulative payments received equal the original loan amount +- **Typical timeline**: 12-18 months depending on interest rate and term +- **Risk level**: Very low - payments are contractually guaranteed + +### Advantages for CSPs +- **Predictable cash flow**: Fixed monthly income regardless of market conditions +- **Low risk**: Not dependent on Servala's business performance +- **Simple structure**: Traditional lending arrangement with clear terms +- **Principal protection**: Loan principal is protected by Servala's assets and business + +### Considerations +- **Limited upside**: Returns are capped at the agreed interest rate +- **No performance benefits**: CSP doesn't benefit from exceptional business growth +- **Market rate dependency**: Returns may lag behind high-performing investment alternatives + +--- + +## Investment Model #2: Direct Investment Model + +### Overview +The Direct Investment Model allows CSPs to invest directly in Servala's platform operations, earning returns through revenue sharing that scales with business performance and their active involvement in sales. + +### Key Characteristics + +#### Financial Structure +- **Investment Range**: CHF 100,000 - CHF 2,000,000 +- **Revenue Sharing**: 15-35% to Servala (remainder to CSP) +- **Grace Period**: 6+ months of 100% revenue retention for CSP +- **Performance Bonuses**: Up to 15% additional revenue share for high performers + +#### Investment Scaling Benefits +Direct investments unlock operational advantages through progressive scaling: + +| Investment Amount | Scaling Factor | Customer Acquisition | Churn Reduction | +|------------------|----------------|----------------------|-----------------| +| CHF 500,000 | 1.0x | Baseline | 0% | +| CHF 750,000 | 1.25x | +25% vs baseline | 10% | +| CHF 1,000,000 | 1.5x | +50% vs baseline | 20% | +| CHF 1,500,000 | 1.75x | +75% vs baseline | 30% | +| CHF 2,000,000 | 2.0x | +100% vs baseline | 40% | + +#### Dynamic Grace Period +Grace periods extend with larger investments, providing longer periods of 100% revenue retention: + +- **Base Grace Period**: 6 months +- **Extension Formula**: +1 month per CHF 250,000 invested above CHF 500,000 +- **Maximum Grace Period**: 50% of total investment timeframe + +**Examples:** +- CHF 500,000 investment → 6 months grace period +- CHF 1,000,000 investment → 8 months grace period +- CHF 2,000,000 investment → 12 months grace period + +#### Performance-Based Revenue Split +CSPs who exceed baseline performance expectations receive enhanced revenue sharing: + +- **Performance Threshold**: 110% of baseline instance growth +- **Bonus Calculation**: Up to 15% reduction in Servala's revenue share +- **Bonus Formula**: `Bonus = min(15%, (Performance Ratio - 1.1) × 30%)` +- **Minimum Servala Share**: 10% (maximum bonus protection) + +### Revenue Distribution Phases + +#### Phase 1: Grace Period (Months 1-N) +- **CSP**: 100% of monthly revenue +- **Servala**: 0% +- **Duration**: Based on investment amount (6-12 months) + +#### Phase 2: Standard Revenue Sharing (Post-Grace Period) +- **CSP**: 65-90% of monthly revenue (depending on negotiated split) +- **Servala**: 10-35% of monthly revenue +- **Performance bonuses**: Applied based on CSP sales results + +#### Phase 3: Performance Enhancement (Ongoing) +- **Additional bonuses**: Available for CSPs exceeding 110% of baseline performance +- **Reduced Servala share**: Performance bonuses reduce Servala's percentage +- **Incentive alignment**: Rewards active sales participation by CSP + +### Break-Even Analysis +Break-even for direct investment depends on multiple factors: + +#### Conservative Scenario (2% monthly churn) +- **Typical break-even**: 18-24 months +- **Factors**: Lower customer acquisition, baseline performance +- **Risk level**: Moderate + +#### Moderate Scenario (3% monthly churn) +- **Typical break-even**: 15-20 months +- **Factors**: Balanced growth and churn rates +- **Risk level**: Moderate-High + +#### Aggressive Scenario (5% monthly churn) +- **Typical break-even**: 12-18 months (if performance targets met) +- **Factors**: High growth potential, requires active CSP involvement +- **Risk level**: Higher, but potentially higher returns + +### Advantages for CSPs +- **Unlimited upside potential**: Returns scale with business success +- **Performance incentives**: Bonuses for exceeding expectations +- **Extended grace periods**: Larger investments get longer 100% revenue periods +- **Operational scaling**: Investment size directly improves business outcomes +- **Market expansion**: Direct involvement in growing managed services market + +### Considerations +- **Performance dependency**: Returns vary based on business performance +- **Active participation beneficial**: Better results when CSP actively promotes services +- **Market risk**: Subject to cloud services market fluctuations +- **Longer break-even periods**: Typically requires 15-24 months to break even + +--- + +## Comparative Analysis + +### When to Choose Loan Model + +**Ideal for CSPs who:** +- Prioritize predictable, guaranteed returns +- Have limited capacity for active sales involvement +- Prefer traditional lending relationships +- Want to minimize investment risk +- Need steady cash flow for other operations + +**Financial Profile:** +- Risk tolerance: Low +- Return expectations: 3-7% annually +- Time horizon: 1-3 years +- Involvement level: Passive + +### When to Choose Direct Investment Model + +**Ideal for CSPs who:** +- Want to maximize return potential +- Can actively promote and sell managed services +- Are comfortable with performance-based returns +- Seek strategic partnership opportunities +- Have longer investment horizons + +**Financial Profile:** +- Risk tolerance: Moderate to High +- Return expectations: 15-40% annually (performance dependent) +- Time horizon: 2-5 years +- Involvement level: Active + +### ROI Comparison Examples + +#### CHF 1,000,000 Investment Over 3 Years + +**Loan Model (5% annual rate):** +- Monthly payment: ~CHF 30,000 +- Total return: CHF 1,080,000 +- Net profit: CHF 80,000 +- ROI: 8% over 3 years + +**Direct Investment Model (Moderate Scenario):** +- Year 1: CHF 120,000 (with 8-month grace period) +- Year 2: CHF 180,000 (with performance bonuses) +- Year 3: CHF 240,000 (mature customer base) +- Total return: CHF 540,000 +- Net profit: CHF 540,000 - CHF 1,000,000 = break-even in month 22 +- ROI: 35% over 3 years (if targets met) + +--- + +## Risk Assessment + +### Loan Model Risks +- **Interest rate risk**: Fixed rates may underperform market +- **Opportunity cost**: Missing higher-return investment opportunities +- **Inflation risk**: Fixed payments lose value over time +- **Credit risk**: Minimal, backed by Servala's business assets + +**Risk Mitigation:** +- Due diligence on Servala's financial stability +- Legal documentation ensuring payment priority +- Regular financial monitoring and reporting + +### Direct Investment Model Risks +- **Performance risk**: Returns depend on business success +- **Market risk**: Cloud services market volatility +- **Execution risk**: Depends on CSP's sales capabilities +- **Competition risk**: New competitors may impact growth + +**Risk Mitigation:** +- Diversification across multiple growth scenarios +- Performance bonuses aligned with CSP incentives +- Regular monitoring and adjustment capabilities +- Grace periods provide initial return protection + +--- + +## Investment Process + +### Step 1: Initial Assessment +1. **Investment capacity evaluation**: Determine available capital +2. **Risk tolerance assessment**: Choose appropriate model +3. **Strategic alignment review**: Evaluate fit with CSP goals +4. **Market analysis**: Understand local demand for managed services + +### Step 2: Due Diligence +1. **Financial review**: Examine Servala's financial statements +2. **Technical assessment**: Understand platform capabilities +3. **Market validation**: Verify demand in target regions +4. **Reference checks**: Speak with existing partners + +### Step 3: Terms Negotiation +1. **Investment amount**: Determine capital commitment +2. **Model selection**: Choose loan vs. direct investment +3. **Terms customization**: Negotiate rates, periods, splits +4. **Performance metrics**: Define success criteria and bonuses + +### Step 4: Legal Documentation +1. **Investment agreement**: Comprehensive terms and conditions +2. **Operational guidelines**: Define roles and responsibilities +3. **Reporting requirements**: Establish monitoring and reporting +4. **Exit clauses**: Plan for investment conclusion + +### Step 5: Implementation +1. **Capital deployment**: Transfer investment funds +2. **Systems integration**: Implement monitoring and reporting +3. **Sales enablement**: Train CSP teams (for direct investment) +4. **Performance tracking**: Begin monitoring key metrics + +--- + +## Key Performance Indicators (KPIs) + +### Financial Metrics +- **Monthly Recurring Revenue (MRR)**: Total monthly income from services +- **Customer Acquisition Cost (CAC)**: Cost to acquire new customers +- **Customer Lifetime Value (CLV)**: Total revenue per customer +- **Monthly churn rate**: Percentage of customers lost per month +- **Net Revenue Retention**: Revenue growth from existing customers + +### Investment-Specific Metrics +- **Break-even timeline**: Months to recover initial investment +- **Return on Investment (ROI)**: Total return percentage +- **Performance bonus earnings**: Additional income from exceeding targets +- **Grace period utilization**: Revenue during 100% retention period + +### Operational Metrics +- **Instance deployment rate**: New services launched monthly +- **Customer satisfaction scores**: Service quality indicators +- **Support ticket resolution time**: Operational efficiency +- **Platform uptime**: Technical reliability metrics + +--- + +## Frequently Asked Questions + +### General Questions + +**Q: Can I switch between investment models during the term?** +A: Model changes require mutual agreement and may involve restructuring fees. Generally, changes are evaluated at renewal periods. + +**Q: What happens if Servala's business underperforms?** +A: Loan Model investors are protected through contractual guarantees. Direct Investment returns will reflect actual performance, but grace periods provide initial protection. + +**Q: How are disputes resolved?** +A: Investment agreements include arbitration clauses and dispute resolution procedures. Regular communication helps prevent conflicts. + +### Loan Model Questions + +**Q: Are loan payments guaranteed?** +A: Yes, loan payments are contractually guaranteed and backed by Servala's business assets and cash flow. + +**Q: Can I prepay or extend the loan term?** +A: Terms can be modified by mutual agreement. Prepayment may involve early payment discounts or penalties as specified in the agreement. + +### Direct Investment Questions + +**Q: How is performance measured for bonus calculations?** +A: Performance is measured against baseline growth scenarios using actual vs. projected customer instance growth over rolling 6-month periods. + +**Q: What constitutes "active sales participation"?** +A: This includes promoting Servala services to existing customers, participating in joint sales activities, and meeting agreed-upon referral targets. + +**Q: How often are performance bonuses calculated and paid?** +A: Performance bonuses are calculated monthly and applied to that month's revenue sharing. Payments follow the standard monthly distribution schedule. + +--- + +## Contact and Next Steps + +For detailed discussions about investment opportunities: + +1. **Schedule consultation**: Review your specific requirements and objectives +2. **Receive custom proposal**: Get tailored investment terms and projections +3. **Complete due diligence**: Access detailed financial and operational data +4. **Finalize agreement**: Execute legal documentation and begin partnership + +This investment represents an opportunity to participate in the rapidly growing managed cloud services market while supporting innovation in cloud infrastructure automation and management. + +--- + +*This document is for informational purposes only and does not constitute financial advice. All investment decisions should be made after careful consideration of your individual circumstances and consultation with appropriate financial and legal advisors.* + +**Document Version**: 1.0 +**Last Updated**: December 2024 +**Document Owner**: Servala Investment Relations Team \ No newline at end of file diff --git a/hub/services/static/js/roi-calculator/calculator-core.js b/hub/services/static/js/roi-calculator/calculator-core.js index 3d25b21..bd3fba4 100644 --- a/hub/services/static/js/roi-calculator/calculator-core.js +++ b/hub/services/static/js/roi-calculator/calculator-core.js @@ -122,15 +122,32 @@ class ROICalculator { } } - // Calculate investment scaling factor (only for direct investment) - // Base investment of CHF 500,000 = 1.0x multiplier - // Higher investments get multiplicative benefits for instance acquisition + // Enhanced investment scaling factor (only for direct investment) + // Progressive scaling provides clear incentives for larger investments const baseInvestment = 500000; - const investmentScaleFactor = inputs.investmentModel === 'loan' ? 1.0 : Math.sqrt(inputs.investmentAmount / baseInvestment); + let investmentScaleFactor; + let churnReductionFactor; - // Calculate churn reduction factor based on investment (only for direct investment) - // Higher investment = better customer success = lower churn - const churnReductionFactor = inputs.investmentModel === 'loan' ? 1.0 : Math.max(0.7, 1 - (inputs.investmentAmount - baseInvestment) / 2000000 * 0.3); + if (inputs.investmentModel === 'loan') { + investmentScaleFactor = 1.0; + churnReductionFactor = 1.0; + } else { + // Progressive linear scaling with clear breakpoints + if (inputs.investmentAmount <= baseInvestment) { + investmentScaleFactor = inputs.investmentAmount / baseInvestment; + } else if (inputs.investmentAmount <= 1000000) { + // 500k to 1M: Scale from 1.0x to 1.5x + investmentScaleFactor = 1.0 + (inputs.investmentAmount - baseInvestment) / 1000000; + } else { + // 1M to 2M: Scale from 1.5x to 2.0x + investmentScaleFactor = 1.5 + (inputs.investmentAmount - 1000000) / 2000000; + } + + // Enhanced churn reduction with better scaling + // Higher investment = better customer success = lower churn + const churnReductionRatio = Math.min((inputs.investmentAmount - baseInvestment) / 1500000, 1.0); + churnReductionFactor = Math.max(0.6, 1 - (churnReductionRatio * 0.4)); + } // Calculate adjusted churn rate with investment-based reduction const adjustedChurnRate = scenario.churnRate * churnReductionFactor; @@ -142,6 +159,15 @@ class ROICalculator { let cumulativeServalaRevenue = 0; let breakEvenMonth = null; + // Calculate dynamic grace period based on investment size + const baseGracePeriod = inputs.gracePeriod; + const gracePeriodBonus = Math.floor((inputs.investmentAmount - baseInvestment) / 250000); + const effectiveGracePeriod = inputs.investmentModel === 'loan' ? 0 : + Math.min(baseGracePeriod + gracePeriodBonus, Math.floor(totalMonths / 2)); + + // Track baseline performance for performance bonuses (direct investment only) + let baselineInstances = 0; // Will track expected instances without performance scaling + // Track phase progression let currentPhase = 0; let monthsInCurrentPhase = 0; @@ -157,6 +183,11 @@ class ROICalculator { const baseNewInstances = scenario.phases[currentPhase].newInstancesPerMonth; const newInstances = Math.floor(baseNewInstances * investmentScaleFactor); + // Track baseline instances (without investment scaling) for performance comparison + const baselineNewInstances = baseNewInstances; + const baselineChurnedInstances = Math.floor(baselineInstances * scenario.churnRate); + baselineInstances = baselineInstances + baselineNewInstances - baselineChurnedInstances; + // Calculate churn using the pre-calculated adjusted churn rate const churnedInstances = Math.floor(currentInstances * adjustedChurnRate); @@ -164,24 +195,33 @@ class ROICalculator { currentInstances = currentInstances + newInstances - churnedInstances; // Calculate revenue based on investment model - let cspRevenue, servalaRevenue, monthlyRevenue; + let cspRevenue, servalaRevenue, monthlyRevenue, performanceBonus = 0, adjustedServalaShare = inputs.servalaShare; if (inputs.investmentModel === 'loan') { - // Loan model: CSP receives fixed monthly loan payment + // Loan model: CSP receives fixed monthly loan payment (predictable returns) cspRevenue = monthlyLoanPayment; servalaRevenue = 0; monthlyRevenue = monthlyLoanPayment; } else { - // Direct investment model: Revenue based on instances + // Direct investment model: Revenue based on instances with performance incentives monthlyRevenue = currentInstances * inputs.revenuePerInstance; - // Determine revenue split based on grace period - if (month <= inputs.gracePeriod) { + // Calculate performance bonus if CSP exceeds baseline expectations + if (baselineInstances > 0 && month > 6) { // Start performance tracking after 6 months + const performanceRatio = currentInstances / Math.max(baselineInstances, 1); + if (performanceRatio > 1.1) { // 10% threshold for performance bonus + performanceBonus = Math.max(0, Math.min(0.15, (performanceRatio - 1.1) * 0.3)); // Up to 15% bonus + adjustedServalaShare = Math.max(0.10, inputs.servalaShare - performanceBonus); + } + } + + // Determine revenue split based on dynamic grace period + if (month <= effectiveGracePeriod) { cspRevenue = monthlyRevenue; servalaRevenue = 0; } else { - cspRevenue = monthlyRevenue * (1 - inputs.servalaShare); - servalaRevenue = monthlyRevenue * inputs.servalaShare; + cspRevenue = monthlyRevenue * (1 - adjustedServalaShare); + servalaRevenue = monthlyRevenue * adjustedServalaShare; } } @@ -189,8 +229,18 @@ class ROICalculator { cumulativeCSPRevenue += cspRevenue; cumulativeServalaRevenue += servalaRevenue; - // Check for break-even - if (breakEvenMonth === null && cumulativeCSPRevenue >= inputs.investmentAmount) { + // Enhanced break-even calculation + let netPosition; // CSP's net financial position + if (inputs.investmentModel === 'loan') { + // For loan model: net position is cumulative payments received minus loan principal outstanding + const principalPaid = inputs.investmentAmount * (month / totalMonths); // Simplified principal tracking + netPosition = cumulativeCSPRevenue - (inputs.investmentAmount - principalPaid); + } else { + // For direct investment: net position is cumulative revenue minus initial investment + netPosition = cumulativeCSPRevenue - inputs.investmentAmount; + } + + if (breakEvenMonth === null && netPosition >= 0) { breakEvenMonth = month; } @@ -200,34 +250,55 @@ class ROICalculator { newInstances, churnedInstances, totalInstances: currentInstances, + baselineInstances, monthlyRevenue, cspRevenue, servalaRevenue, cumulativeCSPRevenue, cumulativeServalaRevenue, + netPosition, + performanceBonus, + adjustedServalaShare, + effectiveGracePeriod, investmentScaleFactor: investmentScaleFactor, - adjustedChurnRate: adjustedChurnRate + adjustedChurnRate: adjustedChurnRate, + roiPercent: inputs.investmentModel === 'loan' ? + ((cumulativeCSPRevenue - inputs.investmentAmount) / inputs.investmentAmount * 100) : + (netPosition / inputs.investmentAmount * 100) }); monthsInCurrentPhase++; } - // Calculate final metrics + // Calculate final metrics with enhanced business intelligence const totalRevenue = cumulativeCSPRevenue + cumulativeServalaRevenue; - const roi = ((cumulativeCSPRevenue - inputs.investmentAmount) / inputs.investmentAmount) * 100; + const finalNetPosition = inputs.investmentModel === 'loan' ? + cumulativeCSPRevenue - inputs.investmentAmount : + cumulativeCSPRevenue - inputs.investmentAmount; + const roi = (finalNetPosition / inputs.investmentAmount) * 100; + + // Calculate average performance bonus over the investment period + const performanceBonusMonths = monthlyData.filter(m => m.performanceBonus > 0); + const avgPerformanceBonus = performanceBonusMonths.length > 0 ? + performanceBonusMonths.reduce((sum, m) => sum + m.performanceBonus, 0) / performanceBonusMonths.length : 0; return { scenario: scenario.name, investmentModel: inputs.investmentModel, finalInstances: currentInstances, + baselineFinalInstances: baselineInstances, totalRevenue, cspRevenue: cumulativeCSPRevenue, servalaRevenue: cumulativeServalaRevenue, + netPosition: finalNetPosition, roi, breakEvenMonth, + effectiveGracePeriod, + avgPerformanceBonus, monthlyData, investmentScaleFactor: investmentScaleFactor, - adjustedChurnRate: adjustedChurnRate * 100 + adjustedChurnRate: adjustedChurnRate * 100, + performanceMultiplier: baselineInstances > 0 ? (currentInstances / baselineInstances) : 1.0 }; } catch (error) { console.error(`Error calculating scenario ${scenarioKey}:`, error); diff --git a/hub/services/static/js/roi-calculator/chart-manager.js b/hub/services/static/js/roi-calculator/chart-manager.js index de4b6e5..8e5834f 100644 --- a/hub/services/static/js/roi-calculator/chart-manager.js +++ b/hub/services/static/js/roi-calculator/chart-manager.js @@ -17,26 +17,31 @@ class ChartManager { } try { - // Instance Growth Chart - const instanceCanvas = document.getElementById('instanceGrowthChart'); - if (!instanceCanvas) { - console.error('Instance growth chart canvas not found'); + // ROI Progression Chart (replaces Instance Growth Chart) + const roiCanvas = document.getElementById('instanceGrowthChart'); + if (!roiCanvas) { + console.error('ROI progression chart canvas not found'); return; } - const instanceCtx = instanceCanvas.getContext('2d'); - this.charts.instanceGrowth = new Chart(instanceCtx, { + const roiCtx = roiCanvas.getContext('2d'); + this.charts.roiProgression = new Chart(roiCtx, { type: 'line', data: { labels: [], datasets: [] }, options: { responsive: true, maintainAspectRatio: false, plugins: { - legend: { position: 'top' } + legend: { position: 'top' }, + title: { display: true, text: 'ROI Progression Over Time' } }, scales: { y: { - beginAtZero: true, - title: { display: true, text: 'Total Instances' } + title: { display: true, text: 'ROI (%)' }, + grid: { + color: function(context) { + return context.tick.value === 0 ? 'rgba(0,0,0,0.5)' : 'rgba(0,0,0,0.1)'; + } + } }, x: { title: { display: true, text: 'Month' } @@ -45,26 +50,31 @@ class ChartManager { } }); - // Revenue Chart - const revenueCanvas = document.getElementById('revenueChart'); - if (!revenueCanvas) { - console.error('Revenue chart canvas not found'); + // Net Position Chart (replaces simple Revenue Chart) + const netPositionCanvas = document.getElementById('revenueChart'); + if (!netPositionCanvas) { + console.error('Net position chart canvas not found'); return; } - const revenueCtx = revenueCanvas.getContext('2d'); - this.charts.revenue = new Chart(revenueCtx, { + const netPositionCtx = netPositionCanvas.getContext('2d'); + this.charts.netPosition = new Chart(netPositionCtx, { type: 'line', data: { labels: [], datasets: [] }, options: { responsive: true, maintainAspectRatio: false, plugins: { - legend: { position: 'top' } + legend: { position: 'top' }, + title: { display: true, text: 'Net Financial Position (Break-Even Analysis)' } }, scales: { y: { - beginAtZero: true, - title: { display: true, text: 'Cumulative Revenue (CHF)' } + title: { display: true, text: 'Net Position (CHF)' }, + grid: { + color: function(context) { + return context.tick.value === 0 ? 'rgba(0,0,0,0.8)' : 'rgba(0,0,0,0.1)'; + } + } }, x: { title: { display: true, text: 'Month' } @@ -73,28 +83,30 @@ class ChartManager { } }); - // Cash Flow Chart - const cashFlowCanvas = document.getElementById('cashFlowChart'); - if (!cashFlowCanvas) { - console.error('Cash flow chart canvas not found'); + // Model Comparison Chart (replaces generic Cash Flow Chart) + const modelComparisonCanvas = document.getElementById('cashFlowChart'); + if (!modelComparisonCanvas) { + console.error('Model comparison chart canvas not found'); return; } - const cashFlowCtx = cashFlowCanvas.getContext('2d'); - this.charts.cashFlow = new Chart(cashFlowCtx, { + const modelComparisonCtx = modelComparisonCanvas.getContext('2d'); + this.charts.modelComparison = new Chart(modelComparisonCtx, { type: 'bar', data: { labels: [], datasets: [] }, options: { responsive: true, maintainAspectRatio: false, plugins: { - legend: { position: 'top' } + legend: { position: 'top' }, + title: { display: true, text: 'Investment Model Performance Comparison' } }, scales: { y: { - title: { display: true, text: 'Monthly Cash Flow (CHF)' } + beginAtZero: true, + title: { display: true, text: 'Total Return (CHF)' } }, x: { - title: { display: true, text: 'Month' } + title: { display: true, text: 'Growth Scenario' } } } } @@ -126,11 +138,11 @@ class ChartManager { updateCharts() { try { const scenarios = Object.keys(this.calculator.results); - if (scenarios.length === 0 || !this.charts.instanceGrowth) return; + if (scenarios.length === 0 || !this.charts.roiProgression) return; const colors = { conservative: '#28a745', - moderate: '#ffc107', + moderate: '#ffc107', aggressive: '#dc3545' }; @@ -138,43 +150,65 @@ class ChartManager { const maxMonths = Math.max(...scenarios.map(s => this.calculator.monthlyData[s].length)); const monthLabels = Array.from({ length: maxMonths }, (_, i) => `M${i + 1}`); - // Update Instance Growth Chart - this.charts.instanceGrowth.data.labels = monthLabels; - this.charts.instanceGrowth.data.datasets = scenarios.map(scenario => ({ - label: this.calculator.scenarios[scenario].name, - data: this.calculator.monthlyData[scenario].map(d => d.totalInstances), + // Update ROI Progression Chart + this.charts.roiProgression.data.labels = monthLabels; + this.charts.roiProgression.data.datasets = scenarios.map(scenario => ({ + label: `${this.calculator.scenarios[scenario].name} (${this.calculator.results[scenario].investmentModel})`, + data: this.calculator.monthlyData[scenario].map(d => d.roiPercent), borderColor: colors[scenario], backgroundColor: colors[scenario] + '20', - tension: 0.4 + tension: 0.4, + pointBackgroundColor: this.calculator.monthlyData[scenario].map(d => + d.roiPercent >= 0 ? colors[scenario] : '#dc3545' + ) })); - this.charts.instanceGrowth.update(); + this.charts.roiProgression.update(); - // Update Revenue Chart - this.charts.revenue.data.labels = monthLabels; - this.charts.revenue.data.datasets = scenarios.map(scenario => ({ - label: this.calculator.scenarios[scenario].name + ' (CSP)', - data: this.calculator.monthlyData[scenario].map(d => d.cumulativeCSPRevenue), + // Update Net Position Chart (Break-Even Analysis) + this.charts.netPosition.data.labels = monthLabels; + this.charts.netPosition.data.datasets = scenarios.map(scenario => ({ + label: `${this.calculator.scenarios[scenario].name} Net Position`, + data: this.calculator.monthlyData[scenario].map(d => d.netPosition), borderColor: colors[scenario], backgroundColor: colors[scenario] + '20', - tension: 0.4 + tension: 0.4, + fill: { + target: 'origin', + above: colors[scenario] + '10', + below: '#dc354510' + } })); - this.charts.revenue.update(); + this.charts.netPosition.update(); - // Update Cash Flow Chart (show average across scenarios) - const avgCashFlow = monthLabels.map((_, monthIndex) => { - const monthData = scenarios.map(scenario => - this.calculator.monthlyData[scenario][monthIndex]?.cspRevenue || 0 - ); - return monthData.reduce((sum, val) => sum + val, 0) / monthData.length; - }); - - this.charts.cashFlow.data.labels = monthLabels; - this.charts.cashFlow.data.datasets = [{ - label: 'Average Monthly CSP Revenue', - data: avgCashFlow, - backgroundColor: '#007bff' + // Update Model Comparison Chart + const scenarioLabels = scenarios.map(s => this.calculator.scenarios[s].name); + const currentInvestmentModel = Object.values(this.calculator.results)[0]?.investmentModel || 'direct'; + + // Show comparison with both models for the same scenarios + this.charts.modelComparison.data.labels = scenarioLabels; + this.charts.modelComparison.data.datasets = [{ + label: `${currentInvestmentModel === 'loan' ? 'Loan Model' : 'Direct Investment'} - Final Return`, + data: scenarios.map(scenario => this.calculator.results[scenario].cspRevenue), + backgroundColor: scenarios.map(scenario => colors[scenario] + '80'), + borderColor: scenarios.map(scenario => colors[scenario]), + borderWidth: 2 }]; - this.charts.cashFlow.update(); + + // Add performance metrics for direct investment + if (currentInvestmentModel === 'direct') { + this.charts.modelComparison.data.datasets.push({ + label: 'Performance Bonus Impact', + data: scenarios.map(scenario => + this.calculator.results[scenario].avgPerformanceBonus * + this.calculator.results[scenario].cspRevenue + ), + backgroundColor: '#17a2b8', + borderColor: '#17a2b8', + borderWidth: 2 + }); + } + + this.charts.modelComparison.update(); } catch (error) { console.error('Error updating charts:', error); } diff --git a/hub/services/static/js/roi-calculator/roi-calculator-app.js b/hub/services/static/js/roi-calculator/roi-calculator-app.js index d3a8111..b346b0b 100644 --- a/hub/services/static/js/roi-calculator/roi-calculator-app.js +++ b/hub/services/static/js/roi-calculator/roi-calculator-app.js @@ -415,10 +415,10 @@ class ROICalculatorApp { if (selectedModel === 'loan') { if (loanSection) loanSection.style.display = 'block'; - if (modelDescription) modelDescription.textContent = 'Loan Model: Guaranteed returns with fixed monthly payments'; + if (modelDescription) modelDescription.textContent = 'Loan Model: 3-7% guaranteed annual returns with predictable monthly payments and low risk'; } else { if (loanSection) loanSection.style.display = 'none'; - if (modelDescription) modelDescription.textContent = 'Direct Investment: Higher potential returns based on your sales performance'; + if (modelDescription) modelDescription.textContent = 'Direct Investment: Performance-based returns with progressive scaling, bonuses up to 15%, and dynamic grace periods'; } this.updateCalculations(); diff --git a/hub/services/static/js/roi-calculator/ui-manager.js b/hub/services/static/js/roi-calculator/ui-manager.js index 9db5536..89c1114 100644 --- a/hub/services/static/js/roi-calculator/ui-manager.js +++ b/hub/services/static/js/roi-calculator/ui-manager.js @@ -11,23 +11,49 @@ class UIManager { try { const enabledResults = Object.values(this.calculator.results); if (enabledResults.length === 0) { - this.setElementText('total-instances', '0'); - this.setElementText('total-revenue', 'CHF 0'); + this.setElementText('net-position', 'CHF 0'); + this.setElementText('csp-revenue', 'CHF 0'); this.setElementText('roi-percentage', '0%'); this.setElementText('breakeven-time', 'N/A'); return; } - // Calculate averages across enabled scenarios - const avgInstances = Math.round(enabledResults.reduce((sum, r) => sum + r.finalInstances, 0) / enabledResults.length); - const avgRevenue = enabledResults.reduce((sum, r) => sum + r.totalRevenue, 0) / enabledResults.length; + // Calculate averages across enabled scenarios with enhanced financial metrics + const avgNetPosition = enabledResults.reduce((sum, r) => sum + (r.netPosition || 0), 0) / enabledResults.length; + const avgCSPRevenue = enabledResults.reduce((sum, r) => sum + r.cspRevenue, 0) / enabledResults.length; const avgROI = enabledResults.reduce((sum, r) => sum + r.roi, 0) / enabledResults.length; const avgBreakeven = enabledResults.filter(r => r.breakEvenMonth).reduce((sum, r) => sum + r.breakEvenMonth, 0) / enabledResults.filter(r => r.breakEvenMonth).length; - this.setElementText('total-instances', avgInstances.toLocaleString()); - this.setElementText('total-revenue', this.formatCurrency(avgRevenue)); + // Update metrics with financial focus + this.setElementText('net-position', this.formatCurrency(avgNetPosition)); + this.setElementText('csp-revenue', this.formatCurrency(avgCSPRevenue)); this.setElementText('roi-percentage', this.formatPercentage(avgROI)); this.setElementText('breakeven-time', isNaN(avgBreakeven) ? 'N/A' : `${Math.round(avgBreakeven)} months`); + + // Update metric card styling based on performance + const netPositionElement = document.getElementById('net-position'); + if (netPositionElement) { + if (avgNetPosition > 0) { + netPositionElement.className = 'metric-value text-success'; + } else if (avgNetPosition < 0) { + netPositionElement.className = 'metric-value text-danger'; + } else { + netPositionElement.className = 'metric-value'; + } + } + + const roiElement = document.getElementById('roi-percentage'); + if (roiElement) { + if (avgROI > 15) { + roiElement.className = 'metric-value text-success'; + } else if (avgROI > 5) { + roiElement.className = 'metric-value text-warning'; + } else if (avgROI < 0) { + roiElement.className = 'metric-value text-danger'; + } else { + roiElement.className = 'metric-value'; + } + } } catch (error) { console.error('Error updating summary metrics:', error); } @@ -48,15 +74,23 @@ class UIManager { 'Loan' : 'Direct'; + const performanceInfo = result.investmentModel === 'direct' ? + `Performance: ${result.performanceMultiplier.toFixed(2)}x` + + `Grace: ${result.effectiveGracePeriod} months` : + 'Fixed returns'; + const row = tbody.insertRow(); row.innerHTML = ` - ${result.scenario} + ${result.scenario}
${performanceInfo} ${modelLabel} ${result.finalInstances.toLocaleString()} ${this.formatCurrencyDetailed(result.totalRevenue)} ${this.formatCurrencyDetailed(result.cspRevenue)} ${this.formatCurrencyDetailed(result.servalaRevenue)} - ${this.formatPercentage(result.roi)} + + ${this.formatPercentage(result.roi)} + ${result.avgPerformanceBonus > 0 ? `
+${this.formatPercentage(result.avgPerformanceBonus * 100)} bonus` : ''} + ${result.breakEvenMonth ? result.breakEvenMonth + ' months' : 'N/A'} `; }); @@ -87,16 +121,22 @@ class UIManager { allData.forEach(data => { const row = tbody.insertRow(); + + // Enhanced monthly breakdown with financial focus + const performanceIcon = data.performanceBonus > 0 ? ' ' : ''; + const graceIcon = data.month <= (data.effectiveGracePeriod || 6) ? ' ' : ''; + const netPositionClass = (data.netPosition || 0) >= 0 ? 'text-success' : 'text-danger'; + row.innerHTML = ` - ${data.month} - ${data.scenario} - ${data.newInstances} - ${data.churnedInstances} + ${data.month}${graceIcon} + ${data.scenario}${performanceIcon} + +${data.newInstances} + -${data.churnedInstances} ${data.totalInstances.toLocaleString()} ${this.formatCurrencyDetailed(data.monthlyRevenue)} - ${this.formatCurrencyDetailed(data.cspRevenue)} - ${this.formatCurrencyDetailed(data.servalaRevenue)} - ${this.formatCurrencyDetailed(data.cumulativeCSPRevenue)} + ${this.formatCurrencyDetailed(data.cspRevenue)} + ${this.formatCurrencyDetailed(data.servalaRevenue)} + ${this.formatCurrencyDetailed(data.netPosition || (data.cumulativeCSPRevenue - 500000))} `; }); } catch (error) { diff --git a/hub/services/templates/calculator/csp_roi_calculator.html b/hub/services/templates/calculator/csp_roi_calculator.html index b69306b..d221826 100644 --- a/hub/services/templates/calculator/csp_roi_calculator.html +++ b/hub/services/templates/calculator/csp_roi_calculator.html @@ -86,22 +86,21 @@ function logout() { window.ROICalculatorApp?.logout(); }
Calculator Overview
-

This ROI calculator models your investment in the Servala platform by simulating cloud service provider (CSP) business growth over time. Choose between lending to Servala (guaranteed returns) or direct platform investment (higher potential returns based on your sales performance).

+

This ROI calculator models your investment in the Servala platform with two distinct approaches. Choose between guaranteed fixed returns through lending, or performance-based returns through direct investment that rewards your sales capabilities.

Key Parameters
-

Investment Model: Loan to Servala (fixed returns) vs Direct Investment (performance-based returns).

-

Investment Amount: Your capital provided to Servala for platform development and infrastructure.

-

Monthly Revenue per Instance: The recurring revenue generated from each managed service instance (excl. compute).

-

Servala Revenue Share: Percentage of revenue shared with Servala after the grace period (Direct Investment only).

-

Grace Period: Initial months where you keep 100% of revenue before sharing begins with Servala (Direct Investment only).

-

Loan Interest Rate: Annual interest rate on loan to Servala (Loan Model only).

+

Investment Model: Loan (3-7% fixed returns) vs Direct Investment (15-40% performance-based returns).

+

Investment Amount: Higher amounts unlock progressive scaling benefits - 500k = 1.0x, 1M = 1.5x, 2M = 2.0x performance.

+

Dynamic Grace Period: Larger investments get longer 100% revenue retention (6+ months based on investment size).

+

Performance Bonuses: Direct Investment CSPs earn up to 15% additional revenue share for exceeding sales targets.

+

Monthly Revenue per Instance: Recurring revenue from managed services (typically CHF 50-200 per instance).

Investment Models
-

Loan Model: Lend to Servala at fixed interest rate. Lower risk, guaranteed returns, but limited upside.

-

Direct Investment: Invest directly in platform operations. Higher risk, but unlimited upside based on your sales performance during grace period and beyond.

+

Loan Model: Lend capital at fixed interest (3-7% annually). Predictable monthly payments, lower risk, but capped returns.

+

Direct Investment: Invest in operations with revenue sharing. Progressive scaling, performance bonuses, and extended grace periods reward larger investments and active sales participation.

Growth Scenarios
@@ -114,10 +113,11 @@ function logout() { window.ROICalculatorApp?.logout(); }
Understanding Results
-

ROI: Return on Investment as a percentage of your initial investment.

-

Break-even: Month when cumulative revenue equals your initial investment.

-

Churn: Monthly percentage of instances that stop generating revenue (customer loss).

-

Grace Period Advantage: Direct Investment model benefits significantly from aggressive sales during grace period (100% revenue retention).

+

Net Position: Your financial position after accounting for initial investment (above zero = profitable).

+

ROI Progression: How your returns develop over time - shows when investment becomes profitable.

+

Performance Multiplier: How much your actual results exceed baseline expectations (1.0x = baseline, 1.5x = 50% better).

+

Model Comparison: Direct side-by-side comparison of loan vs direct investment returns for your specific scenario.

+

Investment Scaling: Larger investments unlock operational advantages - better customer acquisition and retention capabilities.

@@ -193,21 +193,21 @@ function logout() { window.ROICalculatorApp?.logout(); }
- Direct Investment: Higher potential returns based on your sales performance + Direct Investment: Performance-based returns with progressive scaling, bonuses up to 15%, and dynamic grace periods @@ -500,30 +500,30 @@ function logout() { window.ROICalculatorApp?.logout(); }

Calculating scenarios...

- +
-
0
+
CHF 0
- Total Instances + Net Position
-
CHF 0
+
CHF 0
- Total Revenue + Your Revenue
@@ -532,11 +532,11 @@ function logout() { window.ROICalculatorApp?.logout(); }
0%
- Average ROI + ROI Performance
@@ -545,22 +545,23 @@ function logout() { window.ROICalculatorApp?.logout(); }
N/A
- Avg Break-even + Break-Even
- +
-
Instance Growth Over Time
+
ROI Progression Over Time
+

Shows when your investment becomes profitable (crosses zero line) and how returns develop over time.

@@ -569,13 +570,15 @@ function logout() { window.ROICalculatorApp?.logout(); }
-
Cumulative Revenue
+
Net Financial Position (Break-Even Analysis)
+

Your cumulative profit/loss over time. Above zero = profitable, below zero = recovering investment.

-
Monthly Cash Flow
+
Investment Model Performance Comparison
+

Direct comparison of returns across growth scenarios, showing performance bonuses for direct investment.

@@ -596,18 +599,19 @@ function logout() { window.ROICalculatorApp?.logout(); }
-
Scenario Comparison
+
Financial Performance Comparison
+

Detailed comparison of investment returns across growth scenarios. Direct Investment shows performance multipliers and grace period benefits.

- - - + + + - - - + + + @@ -626,25 +630,26 @@ function logout() { window.ROICalculatorApp?.logout(); }
- Monthly Breakdown + Monthly Financial Flow Analysis
+

Month-by-month financial performance showing revenue distribution, performance bonuses, and progress toward break-even.

ScenarioInvestment ModelFinal InstancesScenario & PerformanceModelBusiness Scale Total RevenueCSP RevenueServala RevenueROIYour RevenueServala ShareROI & Bonuses Break-even
- - - + + + - - - + + +
Month ScenarioNew InstancesChurnedTotal InstancesGrowthChurnScale Monthly RevenueCSP RevenueServala RevenueCumulative CSPYour ShareServala ShareNet Position