Personal Finance Audit & Health Check Tool

Personal Finance Audit & Health Check

Monthly Income & Key Expenses

Income

$
$

Key Monthly Financial Commitments

$
$
$
$ (Housing, utilities, food, basic transport, insurance, min. debt payments)

Your Assets

Liquid Assets

$
$

Investments

$
$

Real Estate

$
$

Other Significant Assets

$
$
Total Assets: $0.00

Your Liabilities

Short-Term Debt

$
$

Long-Term Debt

$
$
$
$
$
Total Liabilities: $0.00

Financial Health Check Report

Please fill in your financial details on the previous tabs, then click "View / Refresh Health Check".

Guideline: ${interpretation}

`; return {label, value, unit, statusText, interpretation}; } const displayedRatios = []; displayedRatios.push(addRatio("Savings Rate", savingsRate, "%", {min:15, max:null}, {min:10, max:14.99}, "15%+ is generally considered strong.", "10-15% is a good start. Aim higher if possible.", "<10% indicates an area for potential improvement.", "A savings rate below 10% might make it challenging to reach long-term financial goals. Consider reviewing your budget to identify areas where spending can be reduced or explore ways to increase income to boost savings.")); displayedRatios.push(addRatio("Emergency Fund Coverage", emergencyFundCoverage, " months", {min:3, max:null}, {min:1, max:2.99}, "3-6+ months of essential expenses is a healthy safety net.", "1-3 months provides some cushion, but aim for more.", "<1 month offers limited protection against unexpected events.", "Having less than 1 month of essential expenses in an emergency fund can be risky. Prioritize building this fund to cover 3-6 months of essential living costs for financial security.")); displayedRatios.push(addRatio("Debt-to-Income Ratio (DTI)", dtiRatio, "%", {min:0, max:35.99}, {min:36, max:43}, "Generally, lenders prefer DTI below 36%.", "36-43% is manageable but monitor closely.", ">43% may indicate high debt load and difficulty obtaining new credit.", "A DTI ratio above 43% suggests a significant portion of your income goes to debt. Focus on strategies to reduce debt (e.g., debt snowball/avalanche) or increase income.")); displayedRatios.push(addRatio("Housing Cost Ratio", housingCostRatio, "%", {min:0, max:30}, {min:30.01, max:35}, "Housing costs below 30% of gross income are often recommended.", "30-35% is acceptable for many, but be mindful.", ">35% may strain your budget significantly.", "Housing costs exceeding 35% of gross income can make other financial goals harder to achieve. If possible, explore ways to reduce housing expenses or increase income.")); displayedRatios.push(addRatio("Liquidity (Essential Expenses Cover)", liquidityRatioMonths, " months", {min:1, max:null}, {min:0.5, max:0.99}, "Liquid assets covering 1+ month(s) of essential expenses is a good sign of short-term stability.", "0.5-1 month offers some liquidity.", "<0.5 months indicates very low liquidity for immediate needs.", "Low liquidity (<0.5 months of essential expenses covered by liquid assets) can be risky. Aim to increase your readily available cash reserves.")); // Qualitative Summary const summaryEl = document.getElementById('pfhc-qualitativeSummary'); let summaryText = "Key Observations:
    "; if (goodCount >= 3) summaryText += "
  • Several areas indicate strong financial health.
  • "; if (attentionCount > 0) summaryText += `
  • There are ${attentionCount} area(s) identified that may need attention.
  • `; if (goodCount === 0 && fairCount === 0 && attentionCount === 0 && (netMonthlyIncome > 0 || grossMonthlyIncome > 0) ) summaryText += "
  • Your financial ratios are mostly in ranges that may need attention or lack sufficient data for full assessment.
  • "; else if (goodCount === 0 && fairCount === 0 && attentionCount === 0) summaryText = "Please ensure all income and expense fields are filled for a complete analysis."; summaryText += "
"; summaryEl.innerHTML = summaryText; // Suggestions const suggestionsContainer = document.getElementById('pfhc-suggestionsContainer'); suggestionsContainer.innerHTML = ''; if (suggestions.length > 0) { const ul = document.createElement('ul'); ul.className = 'pfhc-suggestions-list'; suggestions.forEach(sug => { const li = document.createElement('li'); li.textContent = sug; ul.appendChild(li); }); suggestionsContainer.appendChild(ul); } else if (goodCount === displayedRatios.length) { suggestionsContainer.innerHTML = "

Your financial indicators are generally within healthy ranges based on common guidelines. Keep up the good work!

"; } pfhc_healthCheckDataForPdf = { inputs: { grossMonthlyIncome, netMonthlyIncome, monthlySavings, totalMonthlyDebtPayments, monthlyHousingCost, monthlyEssentialExpenses, totalAssets, totalLiabilities, emergencyFundBalance, liquidAssets }, netWorth, ratios: displayedRatios, // Contains label, value, unit, statusText, interpretation qualitativeSummary: summaryEl.innerHTML, // Capture the generated HTML for summary suggestions // Array of suggestion strings }; // No recursive openTab call } catch (error) { console.error("Error generating health check:", error); alert("Error generating health check: " + error.message); pfhc_healthCheckDataForPdf = null; } } function pfhc_downloadPDF() { if (!pfhc_healthCheckDataForPdf) { alert("Please generate the health check report first."); return; } if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF === 'undefined') { alert('PDF library (jsPDF) not loaded.'); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF(); if (typeof doc.autoTable !== 'function') { alert('PDF Table plugin (jsPDF-AutoTable) not loaded.'); return; } const data = pfhc_healthCheckDataForPdf; const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--pfhc-primary-color').trim(); const accentGood = getComputedStyle(document.documentElement).getPropertyValue('--pfhc-accent-good').trim(); const accentFair = getComputedStyle(document.documentElement).getPropertyValue('--pfhc-accent-fair').trim(); const accentAttention = getComputedStyle(document.documentElement).getPropertyValue('--pfhc-accent-attention').trim(); let yPos = 20; doc.setFontSize(18); doc.setTextColor(primaryColor); doc.text("Personal Finance Health Check Report", 105, yPos, { align: 'center' }); yPos += 15; doc.setFontSize(12); doc.setTextColor(primaryColor); doc.text("Financial Snapshot:", 14, yPos); yPos += 7; const snapshotData = [ ["Gross Monthly Income:", pfhc_formatCurrency(data.inputs.grossMonthlyIncome)], ["Net Monthly Income:", pfhc_formatCurrency(data.inputs.netMonthlyIncome)], ["Monthly Savings:", pfhc_formatCurrency(data.inputs.monthlySavings)], ["Monthly Debt Payments:", pfhc_formatCurrency(data.inputs.totalMonthlyDebtPayments)], ["Monthly Housing Cost:", pfhc_formatCurrency(data.inputs.monthlyHousingCost)], ["Monthly Essential Expenses:", pfhc_formatCurrency(data.inputs.monthlyEssentialExpenses)], ["Total Assets:", pfhc_formatCurrency(data.inputs.totalAssets)], ["Total Liabilities:", pfhc_formatCurrency(data.inputs.totalLiabilities)], [{content:"Calculated Net Worth:", styles:{fontStyle:'bold'}}, {content:pfhc_formatCurrency(data.netWorth), styles:{fontStyle:'bold'}}], ]; doc.autoTable({ startY: yPos, body: snapshotData, theme: 'plain', styles: { fontSize: 9 }, columnStyles: {0:{fontStyle:'bold', cellWidth:70}}}); yPos = doc.lastAutoTable.finalY + 10; if (yPos > 250) { doc.addPage(); yPos = 20;} doc.setFontSize(12); doc.setTextColor(primaryColor); doc.text("Key Financial Ratios & Indicators:", 14, yPos); yPos += 7; const ratioHeaders = ["Indicator", "Value", "Status", "General Guideline"]; const ratioBody = data.ratios.map(r => { let valueStr = (isNaN(r.value) || r.value === Infinity) ? 'N/A' : `${r.value.toFixed(1)}${r.unit}`; return [r.label, valueStr, r.statusText, r.interpretation]; }); doc.autoTable({ startY: yPos, head: [ratioHeaders], body: ratioBody, theme: 'grid', headStyles: { fillColor: primaryColor, textColor: [255,255,255], fontStyle: 'bold' }, styles: { fontSize: 8, cellPadding: 1.5, overflow: 'linebreak' }, columnStyles: {1:{halign:'right'}, 2:{halign:'center'}}, didDrawCell: function(hookData) { // Color status cell if (hookData.column.index === 2 && hookData.cell.section === 'body') { const status = hookData.cell.raw; if (status === 'Good') hookData.cell.styles.fillColor = accentGood; else if (status === 'Fair') hookData.cell.styles.fillColor = accentFair; else if (status === 'Needs Attention') hookData.cell.styles.fillColor = accentAttention; if (status === 'Good' || status === 'Needs Attention' || status ==='Fair') hookData.cell.styles.textColor = [255,255,255]; } } }); yPos = doc.lastAutoTable.finalY + 10; if (yPos > 250) { doc.addPage(); yPos = 20;} doc.setFontSize(12); doc.setTextColor(primaryColor); doc.text("Overall Summary & Suggestions:", 14, yPos); yPos +=7; doc.setFontSize(9); doc.setTextColor(50); // Process qualitative summary - remove HTML tags for PDF let summaryTextForPdf = data.qualitativeSummary.replace(/<[^>]*>?/gm, ''); summaryTextForPdf = summaryTextForPdf.replace(/Key Observations:/g, "\nKey Observations:\n"); // Add line breaks const splitSummary = doc.splitTextToSize(summaryTextForPdf, 180); doc.text(splitSummary, 14, yPos); yPos += (splitSummary.length * 4) + 5; if (data.suggestions.length > 0) { if (yPos > 260) { doc.addPage(); yPos = 20;} doc.setFontSize(10); doc.setTextColor(primaryColor); doc.text("Suggestions for Areas to Review:", 14, yPos); yPos += 6; doc.setFontSize(9); doc.setTextColor(50); data.suggestions.forEach(sug => { const splitSuggestion = doc.splitTextToSize(`• ${sug}`, 180); if (yPos > 270 && (yPos + splitSuggestion.length * 4 > 290) ) {doc.addPage(); yPos = 20;} doc.text(splitSuggestion, 16, yPos); yPos += (splitSuggestion.length * 4) + 2; }); } else if (data.ratios.every(r => r.statusText === 'Good')) { if (yPos > 270) {doc.addPage(); yPos = 20;} doc.text("All indicators are generally within healthy ranges. Keep up the great work!", 14, yPos); } // Footer const pageHeight = doc.internal.pageSize.height || doc.internal.pageSize.getHeight(); doc.setFontSize(8); doc.setTextColor(150); doc.text(`Generated on: ${new Date().toLocaleDateString('en-US', {year:'numeric', month:'short', day:'numeric'})}`, 14, pageHeight - 10); doc.text(`Personal Finance Health Check`, doc.internal.pageSize.width - 14, pageHeight - 10, { align: 'right' }); doc.save("Financial_Health_Check_Report.pdf"); } // Initialize document.addEventListener('DOMContentLoaded', () => { if (pfhc_tabs.length > 0 && pfhc_tabs[0]) pfhc_openTab(null, pfhc_tabs[0].id); pfhc_updateNavButtons(); // Add listeners to asset and liability inputs to update totals dynamically const assetLiabilityInputs = document.querySelectorAll('#pfhc-tab2 input[type="number"], #pfhc-tab3 input[type="number"]'); assetLiabilityInputs.forEach(input => { input.addEventListener('input', () => { if (pfhc_currentTab === 1) pfhc_calculateTotalAssets(); // Tab 2 is index 1 if (pfhc_currentTab === 2) pfhc_calculateTotalLiabilities(); // Tab 3 is index 2 // If on report tab and an input changes, refresh report if (pfhc_currentTab === 3) pfhc_generateHealthCheck(); }); }); // Add listeners for Tab 1 inputs for the same reason const tab1Inputs = document.querySelectorAll('#pfhc-tab1 input[type="number"]'); tab1Inputs.forEach(input => { input.addEventListener('input', () => { if (pfhc_currentTab === 3) pfhc_generateHealthCheck(); }); }); const primaryColorVal = getComputedStyle(document.documentElement).getPropertyValue('--pfhc-primary-color').trim(); if (primaryColorVal.startsWith('#')) { const r = parseInt(primaryColorVal.slice(1, 3), 16); const g = parseInt(primaryColorVal.slice(3, 5), 16); const b = parseInt(primaryColorVal.slice(5, 7), 16); document.documentElement.style.setProperty('--pfhc-primary-color-rgb', `${r},${g},${b}`); } // Initial calculation for display pfhc_calculateTotalAssets(); pfhc_calculateTotalLiabilities(); });
Scroll to Top