Business Line of Credit Interest Calculator
Calculation Basis:
Specific Drawn Amount Details:
Average Daily Balance Details:
Common Loan & Cycle Details:
Calculation Results:
Calculated Interest for Cycle: ${formatCurrency(interestCalculated)}
Periodic Maintenance Fee: ${calculatorData.results.maintenanceFeeDisplay}
Total Estimated Cost for Cycle: ${formatCurrency(totalCostForCycle)}
Effective Rate for Cycle: ${effectiveCycleRate.toFixed(3)}%
Simple APR Equivalent (including fees): ${simpleAprEquivalent.toFixed(3)}%
`; resultsSectionEl.style.display = 'block'; } function downloadPDF() { if (!calculatorData.results) { displayError("Please calculate the interest first before downloading PDF."); return; } clearError(); if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF === 'undefined') { displayError('PDF generation library (jsPDF core) is not loaded.'); console.error('window.jspdf or window.jspdf.jsPDF is not defined.'); return; } const JSPDFConstructor = window.jspdf.jsPDF; const doc = new JSPDFConstructor(); if (typeof doc.autoTable !== 'function') { displayError('PDF table plugin (jsPDF-AutoTable) is not functional.'); console.error('doc.autoTable is not a function.'); return; } const inputs = calculatorData.inputs; const results = calculatorData.results; doc.setFontSize(18); doc.text("Business Line of Credit Interest Calculation", 14, 22); doc.setFontSize(10); doc.setTextColor(100); doc.text(`Report Generated: ${new Date().toLocaleDateString()} ${new Date().toLocaleTimeString()}`, 14, 30); doc.setTextColor(0); const headStyles = { fillColor: [0, 115, 170], textColor: 255, fontStyle: 'bold' }; const tableBody = []; tableBody.push(["Calculation Basis:", inputs.calculationMode === 'specificDrawn' ? 'Specific Drawn Amount' : 'Average Daily Balance']); if (inputs.calculationMode === 'specificDrawn') { tableBody.push(["Drawn Amount:", formatCurrency(inputs.drawnAmount)]); } else { tableBody.push(["Average Daily Balance:", formatCurrency(inputs.averageDailyBalance)]); } tableBody.push(["Annual Interest Rate:", `${inputs.annualInterestRate.toFixed(2)}%`]); tableBody.push(["Days in Billing Cycle:", inputs.daysInCycle.toString()]); tableBody.push(["Periodic Maintenance Fee:", formatCurrency(inputs.maintenanceFee)]); doc.autoTable({ startY: 40, head: [['Input Parameter', 'Value']], body: tableBody, theme: 'grid', headStyles: headStyles, columnStyles: { 0: { fontStyle: 'bold' } } }); let lastY = doc.lastAutoTable.finalY + 10; const resultsTableBody = [ ["Calculated Interest for Cycle:", formatCurrency(results.interestCalculated)], ["Periodic Maintenance Fee:", formatCurrency(inputs.maintenanceFee)], // Already formatted this way [{content: "Total Estimated Cost for Cycle:", styles: {fontStyle:'bold'}}, {content: formatCurrency(results.totalCostForCycle), styles:{fontStyle:'bold'}}], ["Effective Rate for Cycle:", `${results.effectiveCycleRate.toFixed(3)}%`], ["Simple APR Equivalent (incl. fees):", `${results.simpleAprEquivalent.toFixed(3)}%`] ]; doc.autoTable({ startY: lastY, head: [['Result Metric', 'Value']], body: resultsTableBody, theme: 'grid', headStyles: headStyles, columnStyles: { 0: { fontStyle: 'bold' } }, didParseCell: function (data) { if(data.row.index === 2 && data.column.index === 1) { // Total Cost Value data.cell.styles.fontStyle = 'bold'; data.cell.styles.textColor = [217, 83, 79]; // Reddish highlight } } }); lastY = doc.lastAutoTable.finalY + 10; doc.setFontSize(9); doc.setTextColor(100); const noteText = [ "This calculator provides an estimate for general informational purposes only.", "Actual interest charges may vary based on lender-specific calculation methods, compounding frequency, and terms.", "The 'Simple APR Equivalent' is a basic annualization of the cycle's cost and may not reflect a legally defined APR." ]; noteText.forEach(line => { if (lastY > 270) { doc.addPage(); lastY = 20; } doc.text(line, 14, lastY); lastY += 5; }); doc.save("Line_of_Credit_Interest_Estimate.pdf"); } // Event Listeners if (calculateButton) calculateButton.addEventListener('click', calculateInterest); if (downloadPdfButton) downloadPdfButton.addEventListener('click', downloadPDF); // Initial setup toggleConditionalInputs(); // Set correct inputs visible on load });