Mortgage Prepayment Budgeting Tool

Mortgage Prepayment Budgeting Tool

Your Current Mortgage Details

How many monthly payments you've completed so far.

Your Prepayment Plan

The additional amount you plan to pay towards the principal each month.

Prepayment Analysis & Comparison

Regular Monthly Payment (Principal & Interest): $0.00


Scenario 1: No Prepayments

Calculations will appear here.

Scenario 2: With Prepayments

Calculations will appear here.

Summary of Savings

Calculations will appear here.

Report Summary

A summary of your mortgage prepayment analysis will appear here.

With Prepayment: Remaining term ~${Math.ceil(prepaymentScenario.monthsToPayoff/12)} years, Total Future Interest ~$${prepaymentScenario.totalInterestPaid === Infinity ? 'Infinite' : prepaymentScenario.totalInterestPaid.toFixed(2)}.


Total Interest Saved: ${interestSaved === Infinity ? 'Substantial (from never ending)' : (interestSaved > 0 ? `$${interestSaved.toFixed(2)}` : '$0.00')}

Time Saved on Loan: ${timeSavedText}

Full details will be in the PDF.

`; } function mpbt_generatePdf() { const loanAmount = mpbt_getFloatValue('mpbtLoanAmount'); const interestRate = mpbt_getFloatValue('mpbtInterestRate'); const loanTermYears = mpbt_getIntValue('mpbtLoanTermYears'); const paymentsMade = mpbt_getIntValue('mpbtPaymentsMade'); const extraMonthlyPayment = mpbt_getFloatValue('mpbtExtraMonthlyPayment'); const originalScenario = mpbt_calculateAmortizationDetails(loanAmount, interestRate, loanTermYears, paymentsMade, 0); const prepaymentScenario = mpbt_calculateAmortizationDetails(loanAmount, interestRate, loanTermYears, paymentsMade, extraMonthlyPayment); if (!originalScenario || !prepaymentScenario) { alert("Calculation error. Cannot generate PDF."); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF(); let yPos = 20; const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--primary-color').trim(); const accentColor = getComputedStyle(document.documentElement).getPropertyValue('--accent-color').trim(); const textColor = getComputedStyle(document.documentElement).getPropertyValue('--text-color').trim(); const toCurrency = (num) => num === Infinity ? "N/A (Perpetual)" : `$${num.toFixed(2)}`; const formatTerm = (months) => { if (months === Infinity || isNaN(months)) return "Never Paid Off"; const years = Math.floor(months / 12); const remMonths = months % 12; return `${years} years, ${remMonths} months`; }; doc.setFontSize(18); doc.setTextColor(primaryColor); doc.text("Mortgage Prepayment Analysis", doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' }); yPos += 15; doc.setFontSize(12); doc.setTextColor(textColor); doc.text("Loan Details:", 14, yPos); yPos += 7; doc.setFontSize(10); doc.text(`Original Loan Amount: ${toCurrency(loanAmount)}`, 16, yPos); yPos += 6; doc.text(`Annual Interest Rate: ${interestRate.toFixed(2)}%`, 16, yPos); yPos += 6; doc.text(`Original Loan Term: ${loanTermYears} years`, 16, yPos); yPos += 6; doc.text(`Payments Already Made: ${paymentsMade}`, 16, yPos); yPos += 6; doc.text(`Current Approx. Balance: ${toCurrency(originalScenario.currentBalance)}`, 16, yPos); yPos += 6; doc.text(`Regular Monthly Payment (P&I): ${toCurrency(originalScenario.regularMonthlyPayment)}`, 16, yPos); yPos += 8; doc.text("Prepayment Plan:", 14, yPos); yPos += 7; doc.setFontSize(10); doc.text(`Extra Monthly Payment: ${toCurrency(extraMonthlyPayment)}`, 16, yPos); yPos += 8; const tableBody = [ ["Scenario", "Remaining Term", "Total Future Interest", "Payoff Date (from now)"], ["No Prepayment", formatTerm(originalScenario.monthsToPayoff), toCurrency(originalScenario.totalInterestPaid), "~" + Math.ceil(originalScenario.monthsToPayoff/12) + " years"], ["With Prepayment", formatTerm(prepaymentScenario.monthsToPayoff), toCurrency(prepaymentScenario.totalInterestPaid), "~" + Math.ceil(prepaymentScenario.monthsToPayoff/12) + " years"] ]; if (yPos > 240) { doc.addPage(); yPos = 20;} doc.setFontSize(12); doc.setTextColor(primaryColor); doc.text("Comparison Summary", 14, yPos); yPos +=7; doc.autoTable({ startY: yPos, head: [tableBody[0]], body: tableBody.slice(1), theme: 'grid', headStyles: { fillColor: primaryColor, textColor: '#ffffff' }, styles: { fontSize: 9, cellPadding: 2 }, didDrawPage: (d) => { yPos = d.cursor.y; } }); yPos = doc.lastAutoTable.finalY + 10; if (yPos > 250) { doc.addPage(); yPos = 20;} doc.setFontSize(12); doc.setTextColor(accentColor); doc.text("Savings Achieved:", 14, yPos); yPos += 7; doc.setFontSize(10); doc.setTextColor(textColor); let interestSavedVal = 0; let timeSavedMonthsVal = 0; let timeSavedText = "N/A"; if (originalScenario.totalInterestPaid !== Infinity && prepaymentScenario.totalInterestPaid !== Infinity) { interestSavedVal = originalScenario.totalInterestPaid - prepaymentScenario.totalInterestPaid; } else if (prepaymentScenario.totalInterestPaid !== Infinity) { interestSavedVal = Infinity; } if (originalScenario.monthsToPayoff !== Infinity && prepaymentScenario.monthsToPayoff !== Infinity) { timeSavedMonthsVal = originalScenario.monthsToPayoff - prepaymentScenario.monthsToPayoff; } else if (prepaymentScenario.monthsToPayoff !== Infinity) { timeSavedMonthsVal = Infinity; } if(timeSavedMonthsVal === Infinity) { timeSavedText = "Loan becomes payable (was perpetual)"; } else if (timeSavedMonthsVal > 0) { const tsYears = Math.floor(timeSavedMonthsVal / 12); const tsMonthsRem = timeSavedMonthsVal % 12; timeSavedText = `${tsYears} years, ${tsMonthsRem} months`; } else { timeSavedText = "No time saved or payment too low"; } doc.text(`Total Interest Saved: ${interestSavedVal === Infinity ? "Substantial (loan now payable)" : toCurrency(interestSavedVal)}`, 16, yPos); yPos += 6; doc.text(`Time Saved on Loan: ${timeSavedText}`, 16, yPos); yPos += 6; doc.save('mortgage_prepayment_analysis.pdf'); } // Initialize document.addEventListener('DOMContentLoaded', () => { mpbt_showTab(0); // Sample data could be set via input values in HTML or here for testing });
Scroll to Top