Strategic Financial Planning Simulator
1. Enter Initial Data & Assumptions
Initial Financials (Year 0)
Growth & Operating Assumptions
Investment & Working Capital Assumptions
2. Projected Income Statement
Calculate the model to see the Income Statement.
3. Projected Cash Flow Statement
Calculate the model to see the Cash Flow Statement.
4. Projected Balance Sheet
Calculate the model to see the Balance Sheet.
5. Key Metrics
Calculate the model to see the Key Metrics.
Calculate the model to see the Balance Sheet.
'; keyMetricsOutputDiv.innerHTML = 'Calculate the model to see the Key Metrics.
'; // Reset to the first tab openTab('inputs'); hideMessage(); } /** * Downloads the financial projections as a PDF. */ function downloadPDF() { if (!window.financialProjections) { showMessage('Please calculate the financial projections first.', 'info'); return; } const { jsPDF } = window.jspdf; const pdf = new jsPDF('l', 'mm', 'a4'); // 'l' for landscape, 'mm', 'a4' size (better for wide tables) const BLACK_COLOR = [31, 41, 55]; // Tailwind gray-900 equivalent const BLUE_HEADER_COLOR = [29, 78, 216]; // Tailwind blue-700 equivalent let y = 15; // Y-coordinate for placing content // Title pdf.setFontSize(22); pdf.setFont('helvetica', 'bold'); pdf.setTextColor(BLACK_COLOR[0], BLACK_COLOR[1], BLACK_COLOR[2]); pdf.text('Strategic Financial Planning Simulator Results', 148, y, { align: 'center' }); // Centered for landscape y += 15; // --- 1. Input Parameters Section --- pdf.setFontSize(16); pdf.setFont('helvetica', 'bold'); pdf.text('1. Input Parameters & Assumptions', 15, y); y += 8; const inputs = window.financialProjections.inputs; const inputData = [ ['Initial Revenue', formatCurrency(inputs.initialRevenue)], ['Initial COGS', formatCurrency(inputs.initialCogs)], ['Initial Operating Expenses', formatCurrency(inputs.initialOperatingExpenses)], ['Initial Cash', formatCurrency(inputs.initialCash)], ['Initial Accounts Receivable', formatCurrency(inputs.initialAccountsReceivable)], ['Initial Inventory', formatCurrency(inputs.initialInventory)], ['Initial Fixed Assets (Net)', formatCurrency(inputs.initialFixedAssets)], ['Initial Accounts Payable', formatCurrency(inputs.initialAccountsPayable)], ['Initial Accrued Expenses', formatCurrency(inputs.initialAccruedExpenses)], ['Initial Long-Term Debt', formatCurrency(inputs.initialLongTermDebt)], ['Initial Equity', formatCurrency(inputs.initialEquity)], ['Projection Years', inputs.projectionYears], ['Annual Revenue Growth Rate', `${(inputs.revenueGrowthRate * 100).toFixed(2)}%`], ['COGS as % of Revenue', `${(inputs.cogsAsPctRevenue * 100).toFixed(2)}%`], ['Operating Expenses as % of Revenue', `${(inputs.opexAsPctRevenue * 100).toFixed(2)}%`], ['Depreciation Rate (% of Fixed Assets)', `${(inputs.depreciationRate * 100).toFixed(2)}%`], ['Interest Rate on Debt', `${(inputs.interestRateOnDebt * 100).toFixed(2)}%`], ['Tax Rate', `${(inputs.taxRate * 100).toFixed(2)}%`], ['CAPEX as % of Revenue', `${(inputs.capexAsPctRevenue * 100).toFixed(2)}%`], ['Accounts Receivable Days', inputs.arDays], ['Inventory Days', inputs.inventoryDays], ['Accounts Payable Days', inputs.apDays], ['Accrued Expenses Days', inputs.accruedDays] ]; pdf.autoTable({ startY: y, head: [['Parameter', 'Value']], body: inputData, theme: 'grid', styles: { fontSize: 8, cellPadding: 2, overflow: 'linebreak', lineColor: 200, lineWidth: 0.1 }, headStyles: { fillColor: BLUE_HEADER_COLOR, textColor: 255, fontStyle: 'bold' }, margin: { left: 15, right: 15 }, columnStyles: { 0: { cellWidth: 80 }, 1: { cellWidth: 'auto' } } }); y = pdf.autoTable.previous.finalY + 15; // Helper to add a financial statement table const addFinancialStatementTable = (title, data, displayNames, formatters, startY) => { // Add new page if current content won't fit if (startY + 30 + (Object.keys(displayNames).length * 7) > pdf.internal.pageSize.height - 15) { pdf.addPage('l', 'a4'); // Add a new page in landscape startY = 15; // Reset Y } pdf.setFontSize(16); pdf.setFont('helvetica', 'bold'); pdf.text(title, 15, startY); startY += 8; const headers = ['Line Item']; for (let i = 0; i < data.length; i++) { headers.push(data[i].year === 0 ? 'Current Year' : `Year ${data[i].year}`); } const tableBody = []; Object.keys(displayNames).forEach(item => { const row = [displayNames[item]]; data.forEach(yearData => { const formattedValue = formatters[item] ? formatters[item](yearData[item]) : formatCurrency(yearData[item]); row.push({ content: formattedValue, styles: { halign: 'right' } }); }); tableBody.push(row); }); pdf.autoTable({ startY: startY, head: [headers], body: tableBody, theme: 'grid', styles: { fontSize: 7, cellPadding: 1, overflow: 'linebreak', lineColor: 200, lineWidth: 0.1 }, headStyles: { fillColor: BLUE_HEADER_COLOR, textColor: 255, fontStyle: 'bold' }, margin: { left: 15, right: 15 }, didParseCell: function (data) { if (data.column.index > 0) { // All data columns are right-aligned data.cell.styles.halign = 'right'; } } }); return pdf.autoTable.previous.finalY + 15; }; // --- Income Statement --- const isDisplayNames = { revenue: 'Revenue', cogs: 'Cost of Goods Sold (COGS)', grossProfit: 'Gross Profit', operatingExpenses: 'Operating Expenses', ebitda: 'EBITDA', depreciation: 'Depreciation', ebit: 'EBIT', interestExpense: 'Interest Expense', ebt: 'Earnings Before Tax (EBT)', taxes: 'Taxes', netIncome: 'Net Income' }; const isFormatters = {}; // All are currency, handled by default formatCurrency for this y = addFinancialStatementTable('2. Projected Income Statement', window.financialProjections.incomeStatement, isDisplayNames, isFormatters, y); // --- Cash Flow Statement --- const cfsDisplayNames = { netIncome: 'Net Income', depreciation: 'Depreciation', changeInAR: 'Change in Accounts Receivable', changeInInventory: 'Change in Inventory', changeInAP: 'Change in Accounts Payable', changeInAccruedExpenses: 'Change in Accrued Expenses', cashFlowFromOperations: 'Cash Flow From Operations', capex: 'Capital Expenditures (CAPEX)', cashFlowFromInvesting: 'Cash Flow From Investing', debtIssuanceRepayment: 'Debt Issuance / (Repayment)', equityIssuanceDividends: 'Equity Issuance / (Dividends)', cashFlowFromFinancing: 'Cash Flow From Financing', netChangeInCash: 'Net Change in Cash', endingCash: 'Ending Cash Balance' }; const cfsFormatters = {}; // All are currency y = addFinancialStatementTable('3. Projected Cash Flow Statement', window.financialProjections.cashFlow, cfsDisplayNames, cfsFormatters, y); // --- Balance Sheet --- const bsDisplayNames = { cash: 'Cash', accountsReceivable: 'Accounts Receivable', inventory: 'Inventory', totalCurrentAssets: 'Total Current Assets', fixedAssetsNet: 'Fixed Assets (Net)', totalAssets: 'TOTAL ASSETS', accountsPayable: 'Accounts Payable', accruedExpenses: 'Accrued Expenses', totalCurrentLiabilities: 'Total Current Liabilities', longTermDebt: 'Long-Term Debt', totalLiabilities: 'TOTAL LIABILITIES', equity: 'Equity', totalLiabilitiesAndEquity: 'TOTAL LIABILITIES & EQUITY' }; const bsFormatters = {}; // All are currency y = addFinancialStatementTable('4. Projected Balance Sheet', window.financialProjections.balanceSheet, bsDisplayNames, bsFormatters, y); // --- Key Metrics --- const kmDisplayNames = { ebitdaMargin: 'EBITDA Margin', netProfitMargin: 'Net Profit Margin', currentRatio: 'Current Ratio', debtToEquity: 'Debt to Equity', unleveredFreeCashFlow: 'Unlevered Free Cash Flow' }; const kmFormatters = { ebitdaMargin: (val) => `${(val * 100).toFixed(2)}%`, netProfitMargin: (val) => `${(val * 100).toFixed(2)}%`, currentRatio: (val) => `${val.toFixed(2)}x`, debtToEquity: (val) => `${val.toFixed(2)}x`, unleveredFreeCashFlow: formatCurrency }; y = addFinancialStatementTable('5. Key Metrics', window.financialProjections.keyMetrics.filter(m => m.year > 0), kmDisplayNames, kmFormatters, y); // Exclude Year 0 from key metrics pdf.save('Strategic_Financial_Planning_Simulator_Results.pdf'); } /** * Initializes DOM element references once the document is fully loaded. */ document.addEventListener('DOMContentLoaded', () => { // Initial Financials Inputs initialRevenueInput = document.getElementById('initialRevenue'); initialCogsInput = document.getElementById('initialCogs'); initialOperatingExpensesInput = document.getElementById('initialOperatingExpenses'); initialCashInput = document.getElementById('initialCash'); initialAccountsReceivableInput = document.getElementById('initialAccountsReceivable'); initialInventoryInput = document.getElementById('initialInventory'); initialFixedAssetsInput = document.getElementById('initialFixedAssets'); initialAccountsPayableInput = document.getElementById('initialAccountsPayable'); initialAccruedExpensesInput = document.getElementById('initialAccruedExpenses'); initialLongTermDebtInput = document.getElementById('initialLongTermDebt'); initialEquityInput = document.getElementById('initialEquity'); // Growth & Operating Assumptions Inputs projectionYearsInput = document.getElementById('projectionYears'); revenueGrowthRateInput = document.getElementById('revenueGrowthRate'); cogsAsPctRevenueInput = document.getElementById('cogsAsPctRevenue'); opexAsPctRevenueInput = document.getElementById('opexAsPctRevenue'); depreciationRateInput = document.getElementById('depreciationRate'); interestRateOnDebtInput = document.getElementById('interestRateOnDebt'); taxRateInput = document.getElementById('taxRate'); // Investment & Working Capital Assumptions Inputs capexAsPctRevenueInput = document.getElementById('capexAsPctRevenue'); arDaysInput = document.getElementById('arDays'); inventoryDaysInput = document.getElementById('inventoryDays'); apDaysInput = document.getElementById('apDays'); accruedDaysInput = document.getElementById('accruedDays'); // Output Elements incomeStatementOutputDiv = document.getElementById('incomeStatementOutput'); cashFlowOutputDiv = document.getElementById('cashFlowOutput'); balanceSheetOutputDiv = document.getElementById('balanceSheetOutput'); keyMetricsOutputDiv = document.getElementById('keyMetricsOutput'); messageBox = document.getElementById('messageBox'); // Initialize navigation button states updateNavigationButtons(); });