UNPKG

business-as-code

Version:

Primitives for expressing business logic and processes as code

297 lines 7.93 kB
/** * Financial metrics and calculations */ /** * Calculate financial metrics from basic inputs * * @example * ```ts * const metrics = financials({ * revenue: 1000000, * cogs: 300000, * operatingExpenses: 500000, * currency: 'USD', * period: 'monthly', * }) * * console.log(metrics.grossMargin) // 70% * console.log(metrics.operatingMargin) // 20% * console.log(metrics.netMargin) // 20% * ``` */ export function financials(metrics) { const revenue = metrics.revenue || 0; const cogs = metrics.cogs || 0; const operatingExpenses = metrics.operatingExpenses || 0; // Calculate derived metrics const grossProfit = revenue - cogs; const grossMargin = revenue > 0 ? (grossProfit / revenue) * 100 : 0; const operatingIncome = grossProfit - operatingExpenses; const operatingMargin = revenue > 0 ? (operatingIncome / revenue) * 100 : 0; const netIncome = metrics.netIncome ?? operatingIncome; const netMargin = revenue > 0 ? (netIncome / revenue) * 100 : 0; // EBITDA (simplified - would need D&A for accurate calculation) const ebitda = metrics.ebitda ?? operatingIncome; const ebitdaMargin = revenue > 0 ? (ebitda / revenue) * 100 : 0; return { ...metrics, revenue, cogs, grossProfit, grossMargin, operatingExpenses, operatingIncome, operatingMargin, netIncome, netMargin, ebitda, ebitdaMargin, currency: metrics.currency || 'USD', period: metrics.period || 'monthly', }; } /** * Calculate gross margin */ export function calculateGrossMargin(revenue, cogs) { if (revenue === 0) return 0; return ((revenue - cogs) / revenue) * 100; } /** * Calculate operating margin */ export function calculateOperatingMargin(revenue, cogs, operatingExpenses) { if (revenue === 0) return 0; const operatingIncome = revenue - cogs - operatingExpenses; return (operatingIncome / revenue) * 100; } /** * Calculate net margin */ export function calculateNetMargin(revenue, netIncome) { if (revenue === 0) return 0; return (netIncome / revenue) * 100; } /** * Calculate EBITDA margin */ export function calculateEBITDAMargin(revenue, ebitda) { if (revenue === 0) return 0; return (ebitda / revenue) * 100; } /** * Calculate burn rate (monthly cash burn) */ export function calculateBurnRate(cashStart, cashEnd, months) { if (months === 0) return 0; return (cashStart - cashEnd) / months; } /** * Calculate runway (months until cash runs out) */ export function calculateRunway(cash, monthlyBurnRate) { if (monthlyBurnRate === 0) return Infinity; if (monthlyBurnRate < 0) return Infinity; // Company is profitable return cash / monthlyBurnRate; } /** * Calculate customer acquisition cost (CAC) */ export function calculateCAC(marketingSpend, newCustomers) { if (newCustomers === 0) return 0; return marketingSpend / newCustomers; } /** * Calculate customer lifetime value (LTV) */ export function calculateLTV(averageRevenuePerCustomer, averageCustomerLifetimeMonths, grossMarginPercent) { return averageRevenuePerCustomer * averageCustomerLifetimeMonths * (grossMarginPercent / 100); } /** * Calculate LTV:CAC ratio */ export function calculateLTVtoCAC(ltv, cac) { if (cac === 0) return 0; return ltv / cac; } /** * Calculate payback period (months to recover CAC) */ export function calculatePaybackPeriod(cac, monthlyRevPerCustomer) { if (monthlyRevPerCustomer === 0) return 0; return cac / monthlyRevPerCustomer; } /** * Calculate annual recurring revenue (ARR) */ export function calculateARR(mrr) { return mrr * 12; } /** * Calculate monthly recurring revenue (MRR) */ export function calculateMRR(arr) { return arr / 12; } /** * Calculate revenue growth rate */ export function calculateGrowthRate(currentRevenue, previousRevenue) { if (previousRevenue === 0) return 0; return ((currentRevenue - previousRevenue) / previousRevenue) * 100; } /** * Calculate compound annual growth rate (CAGR) */ export function calculateCAGR(beginningValue, endingValue, years) { if (beginningValue === 0 || years === 0) return 0; return (Math.pow(endingValue / beginningValue, 1 / years) - 1) * 100; } /** * Calculate return on investment (ROI) */ export function calculateROI(gain, cost) { if (cost === 0) return 0; return ((gain - cost) / cost) * 100; } /** * Calculate return on equity (ROE) */ export function calculateROE(netIncome, shareholderEquity) { if (shareholderEquity === 0) return 0; return (netIncome / shareholderEquity) * 100; } /** * Calculate return on assets (ROA) */ export function calculateROA(netIncome, totalAssets) { if (totalAssets === 0) return 0; return (netIncome / totalAssets) * 100; } /** * Calculate quick ratio (liquidity) */ export function calculateQuickRatio(currentAssets, inventory, currentLiabilities) { if (currentLiabilities === 0) return 0; return (currentAssets - inventory) / currentLiabilities; } /** * Calculate current ratio (liquidity) */ export function calculateCurrentRatio(currentAssets, currentLiabilities) { if (currentLiabilities === 0) return 0; return currentAssets / currentLiabilities; } /** * Calculate debt-to-equity ratio */ export function calculateDebtToEquity(totalDebt, totalEquity) { if (totalEquity === 0) return 0; return totalDebt / totalEquity; } /** * Format currency value */ export function formatCurrency(amount, currency = 'USD') { const symbol = getCurrencySymbol(currency); const formatted = Math.abs(amount).toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 2, }); const sign = amount < 0 ? '-' : ''; return `${sign}${symbol}${formatted}`; } /** * Get currency symbol */ function getCurrencySymbol(currency) { const symbols = { USD: '$', EUR: '€', GBP: '£', JPY: '¥', CNY: '¥', CAD: 'C$', AUD: 'A$', }; return symbols[currency] || currency + ' '; } /** * Create a financial statement */ export function createStatement(type, period, lineItems, currency = 'USD') { return { type, period, lineItems, currency, }; } /** * Get line item from financial statement */ export function getLineItem(statement, name) { return statement.lineItems[name] || 0; } /** * Compare financial metrics between periods */ export function compareMetrics(current, previous) { const comparison = {}; const keys = [ 'revenue', 'grossProfit', 'operatingIncome', 'netIncome', 'ebitda', ]; for (const key of keys) { const currentVal = current[key] || 0; const previousVal = previous[key] || 0; const change = currentVal - previousVal; const changePercent = previousVal !== 0 ? (change / previousVal) * 100 : 0; comparison[key] = { change, changePercent }; } return comparison; } /** * Validate financial metrics */ export function validateFinancials(metrics) { const errors = []; if (metrics.revenue && metrics.revenue < 0) { errors.push('Revenue cannot be negative'); } if (metrics.cogs && metrics.cogs < 0) { errors.push('COGS cannot be negative'); } if (metrics.operatingExpenses && metrics.operatingExpenses < 0) { errors.push('Operating expenses cannot be negative'); } if (metrics.revenue && metrics.cogs && metrics.cogs > metrics.revenue) { errors.push('COGS cannot exceed revenue'); } return { valid: errors.length === 0, errors, }; } //# sourceMappingURL=financials.js.map