${c.score}
${criteriaForms}
`;
};
// --- DATA & EVENT HANDLERS ---
window.updateFinancials = (key, value) => {
financialInputs[key] = (key === 'companyName') ? value : parseFloat(value) || 0;
};
window.updateQualitative = (id, value) => {
const criteria = qualitativeInputs.find(c => c.id === id);
if(criteria) criteria.score = parseInt(value, 10);
const scoreVal = document.getElementById(`score-val-${id}`);
if (scoreVal) scoreVal.textContent = value;
};
// --- RISK CALCULATION LOGIC ---
const handleAnalysis = () => {
const scores = {};
// Score Financials (0-10, lower score is better)
const dte = financialInputs.totalLiabilities / financialInputs.totalAssets;
scores.debtToEquity = Math.min(10, Math.max(0, dte * 15)); // Higher DTE is higher risk
const currentRatio = financialInputs.currentAssets / financialInputs.currentLiabilities;
scores.currentRatio = Math.min(10, Math.max(0, 10 - (currentRatio - 1) * 5)); // Lower ratio is higher risk
const profitMargin = financialInputs.netIncome / financialInputs.revenue;
scores.profitMargin = Math.min(10, Math.max(0, 10 - profitMargin * 50)); // Lower margin is higher risk
scores.businessAge = Math.min(10, Math.max(0, 10 - financialInputs.yearsInBusiness * 1.5)); // Younger is higher risk
const financialRiskScore = (scores.debtToEquity + scores.currentRatio + scores.profitMargin + scores.businessAge) / 4;
// Score Qualitative (0-10, lower score is better)
const qualScores = {};
qualScores.industryRisk = qualitativeInputs.find(q => q.id === 'industryRisk').score;
qualScores.managementExp = 10 - qualitativeInputs.find(q => q.id === 'managementExp').score;
qualScores.collateral = 10 - qualitativeInputs.find(q => q.id === 'collateral').score;
qualScores.businessPlan = 10 - qualitativeInputs.find(q => q.id === 'businessPlan').score;
const qualitativeRiskScore = (qualScores.industryRisk + qualScores.managementExp + qualScores.collateral + qualScores.businessPlan) / 4;
// Final Score (Financials 60%, Qualitative 40%)
const riskScore = (financialRiskScore * 0.6 + qualitativeRiskScore * 0.4) * 10;
let verdict = 'Moderate Risk';
let scoreColor = 'text-yellow-600';
if (riskScore < 35) { verdict = 'Low Risk'; scoreColor = 'text-green-600'; }
else if (riskScore > 65) { verdict = 'High Risk'; scoreColor = 'text-red-600'; }
const allScores = { ...scores, ...qualScores };
const keyWeakness = Object.keys(allScores).reduce((a, b) => allScores[a] > allScores[b] ? a : b);
const readableWeakness = {
debtToEquity: 'High Debt', currentRatio: 'Low Liquidity', profitMargin: 'Low Profitability',
businessAge: 'New Business', industryRisk: 'Risky Industry', managementExp: 'Inexperienced Team',
collateral: 'Weak Collateral', businessPlan: 'Weak Plan'
}[keyWeakness];
analysisResults = {
...financialInputs,
riskScore, verdict, scoreColor, keyWeakness,
componentScores: { ...scores, ...qualScores }
};
switchTab(0);
};
// --- CHART & PDF ---
const renderChart = () => {
if (riskChart) riskChart.destroy();
const ctx = document.getElementById('riskChart')?.getContext('2d');
if (!ctx || !analysisResults) return;
const labels = ['Debt', 'Liquidity', 'Profitability', 'Age', 'Industry', 'Management', 'Collateral', 'Business Plan'];
const data = [
analysisResults.componentScores.debtToEquity, analysisResults.componentScores.currentRatio,
analysisResults.componentScores.profitMargin, analysisResults.componentScores.businessAge,
analysisResults.componentScores.industryRisk, analysisResults.componentScores.managementExp,
analysisResults.componentScores.collateral, analysisResults.componentScores.businessPlan
];
riskChart = new Chart(ctx, {
type: 'radar',
data: {
labels,
datasets: [{
label: 'Risk Factor (Higher is worse)',
data,
backgroundColor: 'rgba(29, 78, 216, 0.2)',
borderColor: 'rgba(29, 78, 216, 1)',
}]
},
options: {
responsive: true, maintainAspectRatio: false,
scales: { r: { beginAtZero: true, max: 10 } },
plugins: { title: { display: true, text: 'Risk Component Analysis' } }
}
});
};
window.downloadPDF = () => {
if (!analysisResults) return;
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
doc.setFontSize(20);
doc.text(`Loan Risk Report: ${analysisResults.companyName}`, doc.internal.pageSize.getWidth() / 2, 20, { align: 'center' });
const summaryText = `
Overall Risk Score: ${analysisResults.riskScore.toFixed(0)} / 100
Verdict: ${analysisResults.verdict}
Key Identified Weakness: ${analysisResults.keyWeakness}
`;
doc.setFontSize(12);
doc.text(summaryText, 14, 35);
const finalY = riskChart ? 75 : 55;
if(riskChart) {
const chartImage = riskChart.toBase64Image();
doc.addImage(chartImage, 'PNG', 14, finalY, 180, 90);
}
doc.autoTable({
startY: finalY + (riskChart ? 100 : 10),
head: [['Financial Metric', 'Value']],
body: [
['Total Assets', `$${analysisResults.totalAssets.toLocaleString()}`],
['Total Liabilities', `$${analysisResults.totalLiabilities.toLocaleString()}`],
['Annual Revenue', `$${analysisResults.revenue.toLocaleString()}`],
['Years in Business', analysisResults.yearsInBusiness],
],
theme: 'striped',
headStyles: { fillColor: [29, 78, 216] },
});
doc.save(`${analysisResults.companyName}-Risk-Report.pdf`);
};
// --- INITIALIZATION ---
DOM.nextBtn.addEventListener('click', () => switchTab(currentTab + 1));
DOM.prevBtn.addEventListener('click', () => switchTab(currentTab - 1));
DOM.tabButtons.forEach((btn, i) => btn.addEventListener('click', () => switchTab(i)));
renderCurrentTab();
updateNavButtons();
});
