@if (loadingApplication) {

Loading application…

} @if (application; as a) {
CREDIT · LOAN ORIGINATION · {{ a.branchName | uppercase }}

{{ a.applicationNo }} — {{ a.applicantName }} {{ statusLabels[a.overallStatus] }}

{{ a.productName }} · ₹{{ a.requestedAmount | number: '1.0-0' }} · Applied {{ a.applicationDate }} · {{ progress(a) }}% through the sanctioning workflow.

@if (uploadingDocs > 0) { Uploading {{ uploadingDocs }} file{{ uploadingDocs > 1 ? 's' : '' }}… } @else if (docUploadFailed) { File upload failed } @if (saving) { Saving… } @else if (saveFailed) { Not saved — check connection }
Branch
{{ a.branchName }}
Channel
{{ a.channel === 'BC' ? a.bcAgentName : a.channel === 'SELF_APPLY' ? 'Self-Apply (Digital)' : 'Branch' }}
Customer Type
{{ a.customerType === 'EXISTING' ? 'Existing Customer' : 'New Customer' }}
Tenure / Rate
{{ a.tenureMonths }} months @ {{ a.interestRate }}%
Monthly Income / Eligible Amount
₹{{ a.monthlyIncome | number: '1.0-0' }} / ₹{{ a.eligibleLoanAmount | number: '1.0-0' }}
Sanctioning Authority
{{ sanctioningAuthorityOf(a) }}
Share Member
@if (a.clientId) { @if (loadingShareAccounts) { Checking membership… } @else if (realShareAccounts.length > 0) { } @else { Not a Member } } @else if (a.isShareMember) { Yes — {{ a.shareCertNo }} (since {{ a.shareMemberSince }}) } @else { Not a Member }
@if (a.coBorrowerRequired) {
Co-Borrower
{{ a.coBorrowerName }} @if (a.coBorrowerWanted && a.coBorrowerRelationship) { ({{ a.coBorrowerRelationship }}) }
} @if (a.guarantorRequired) {
Guarantor
{{ a.guarantorName }}
}
@for (s of stageOrder; track s) { @if (canJumpToStage(a, s)) { } @else {
{{ stepMarker(a, s) }} {{ stageLabels[s] }}
} }
@if (a.overallStatus === 'REJECTED') {

See the approval summary below for the recorded reason.

} @else if (a.overallStatus === 'ON_HOLD') {

{{ a.personalDiscussionNotes }}

} @else if (a.overallStatus === 'DISBURSED') {
Disbursement Date
{{ a.disbursementDate }}
Mode
{{ a.disbursementMode }}
ACH Confirmation
{{ a.achConfirmationRef }}
EMI Activation Confirmation
{{ a.emiActivationConfirmed ? 'Confirmed on ' + a.emiActivationDate : 'Pending' }}
Core Banking Loan Account
@if (a.fineractLoanAccountNo) { A/C {{ a.fineractLoanAccountNo }} } @else { Mock disbursement only — no core banking account }
@if (isRevolving(a)) {

{{ a.productName }} is a revolving/renewable limit — repaid on demand and renewed annually, not on a fixed EMI schedule.

} @else {
Loan Amount ₹{{ a.requestedAmount | number: '1.0-0' }} {{ a.tenureMonths }} months @ {{ a.interestRate }}%
Monthly EMI ₹{{ emiAmountFor(a) | number: '1.0-0' }} Reducing balance
Total Interest Payable ₹{{ totalInterestFor(a) | number: '1.0-0' }} over the full tenure
Total Amount Payable ₹{{ totalPayableFor(a) | number: '1.0-0' }} principal + interest
@for (row of emiScheduleFor(a); track row.installmentNo) { }
Inst. No Due Date Opening Balance EMI Principal Interest Closing Balance
{{ row.installmentNo }} {{ row.dueDate }} ₹{{ row.openingBalance | number: '1.0-0' }} ₹{{ row.emiAmount | number: '1.0-0' }} ₹{{ row.principalComponent | number: '1.0-0' }} ₹{{ row.interestComponent | number: '1.0-0' }} ₹{{ row.closingBalance | number: '1.0-0' }}
}
} @else { @if (a.currentStage === 'APPLICATION') {

Received via {{ a.channel === 'BC' ? a.bcAgentName : a.channel === 'SELF_APPLY' ? 'Self-Apply (Digital)' : 'Branch' }} on {{ a.applicationDate }}.

} @if (a.currentStage === 'KYC_DOCUMENTS') {
@if (a.clientId) { @if (loadingKyc) {

Loading KYC record…

} @else {
Aadhaar
{{ a.aadhaarVerified ? 'Verified' : 'Not Verified' }} @if (realKyc?.aadhaarNumberMasked) { {{ realKyc.aadhaarNumberMasked }} }
PAN
{{ a.panVerified ? 'Verified' : 'Not Verified' }} @if (realKyc?.panNumber) { {{ maskPan(realKyc.panNumber) }} }
Income Proof @if (findDocument('income'); as incomeDoc) { Submitted {{ incomeDoc.name || incomeDoc.fileName }} } @else { @if (newKycCapture.incomeProof.employmentType === 'SALARIED') {
@if (newKycCapture.incomeProof.salaried.file || hasStoredDoc('KYC:incomeProof:salaried')) { }
} @else {

Last 3 years' Income Tax Returns:

@for (doc of newKycCapture.incomeProof.itr; track $index) {
@if (!doc.exception) { @if (doc.file || hasStoredDoc('KYC:incomeProof:itr:' + $index)) { } } @if (!doc.file) { }
@if (doc.exception) { } } } @if (a.incomeProofSubmitted) { @if (itrHasException) { Submitted — with exception(s) } @else { Submitted } } @else { Missing } }
Bank Statement @if (findDocument('bank statement'); as bankDoc) { Submitted {{ bankDoc.name || bankDoc.fileName }} } @else {
@if (newKycCapture.bankStatement.file || hasStoredDoc('KYC:bankStatement')) { @if (canReopenBankStatementAnalysis()) { } }
@if (a.bankStatementSubmitted) { Submitted } @else { Missing } }
Electricity Bill (Address Proof) @if (findDocument('electricity') || findDocument('address proof'); as billDoc) { Submitted {{ billDoc.name || billDoc.fileName }} } @else { @if (electricityBillTooOld) {

Must not be older than 3 months.

}
@if (newKycCapture.electricityBill.file || hasStoredDoc('KYC:electricityBill')) { }
@if (a.electricityBillSubmitted) { Submitted } @else { Missing } }
} } @else {

Captured for this application — final Aadhaar/PAN verification happens when the customer's CBS client profile is created.

Aadhaar
@if (newKycCapture.aadhaar.front || newKycCapture.aadhaar.back) {
@if (newKycCapture.aadhaar.front) { } @if (newKycCapture.aadhaar.back) { }
} @if (newKycCapture.aadhaar.verified) { Aadhaar Verified } @else {
@if (newKycCapture.aadhaar.otpSent) {
@for (d of newKycCapture.aadhaar.otpDigits; track $index) { }
}
}
PAN
@if (newKycCapture.pan.front || newKycCapture.pan.back) {
@if (newKycCapture.pan.front) { } @if (newKycCapture.pan.back) { }
} @if (newKycCapture.pan.verified) { PAN Verified } @else {
}
Income Proof @if (newKycCapture.incomeProof.employmentType === 'SALARIED') {
@if (newKycCapture.incomeProof.salaried.file) { }
} @else {

Last 3 years' Income Tax Returns:

@for (doc of newKycCapture.incomeProof.itr; track $index) {
@if (!doc.exception) { @if (doc.file) { } } @if (!doc.file) { }
@if (doc.exception) { } } } @if (a.incomeProofSubmitted) { @if (itrHasException) { Submitted — with exception(s) } @else { Submitted } } @else { Missing }
Bank Statement
@if (newKycCapture.bankStatement.file) { @if (isCsvFile(newKycCapture.bankStatement.file)) { } }
@if (a.bankStatementSubmitted) { Submitted } @else { Missing }
Electricity Bill (Address Proof) @if (electricityBillTooOld) {

Must not be older than 3 months.

}
@if (newKycCapture.electricityBill.file) { }
@if (a.electricityBillSubmitted) { Submitted } @else { Missing }
} @if (a.productDocuments.length > 0) {
Loan-Specific Documents — {{ a.productName }}
@for (doc of a.productDocuments; track doc.key) { @if (doc.key === 'coOwnerKyc') {
{{ doc.label }} @if (doc.hint) { {{ doc.hint }} } @if (coOwnerCapture.hasCoOwner) {
} @if (doc.submitted) { {{ coOwnerCapture.hasCoOwner ? 'Verified' : 'Not Applicable' }} } @else { Missing }
} @else {
{{ doc.label }} @if (doc.custom) { } @if (doc.hint) { {{ doc.hint }} }
@if (productDocCapture[doc.key]; as capture) { @if (capture.file || hasStoredDoc('PRODUCT_DOC:' + doc.key)) { } }
@if (doc.submitted) { Submitted } @else { Missing }
} }
} @if (!isRevolving(a)) { @if (amountOutOfRange(a)) {

{{ a.productName }} allows ₹{{ productLimitsFor(a)?.minAmt | number: '1.0-0' }} – ₹{{ productLimitsFor(a)?.maxAmt | number: '1.0-0' }} — this amount won't be saved until it's in range.

} @if (tenureOutOfRange(a)) {

{{ a.productName }} allows {{ productLimitsFor(a)?.minTenure }}–{{ productLimitsFor(a)?.maxTenure }} months — this tenure won't be saved until it's in range.

} }

Eligible Loan Amount preview: ₹{{ eligiblePreview(a) | number: '1.0-0' }}

@if (isRevolving(a)) {

{{ a.productName }} is a revolving/renewable limit — repaid on demand, no fixed EMI.

} @else {

Estimated EMI: ₹{{ emiPreview(a) | number: '1.0-0' }} / month ({{ emiToIncomePctPreview(a) | number: '1.0-1' }}% of monthly income)

@if (emiToIncomePctPreview(a) > 40) { @if (a.coBorrowerRequired && coBorrowerDetailsComplete(a) && combinedEligibilityOk(a)) {

EMI exceeds 40% of the applicant's own income, but the Co-Borrower added below already covers it — see the Co-Borrower section.

} @else {

EMI exceeds 40% of monthly income — add a Co-Borrower, reduce the loan amount, or increase the tenure before proceeding.

} } }
@if (a.monthlyIncome > 0) {
Monthly Income (Last Assessed)
₹{{ a.monthlyIncome | number: '1.0-0' }}
Eligible Loan Amount
₹{{ a.eligibleLoanAmount | number: '1.0-0' }}
Estimated EMI
@if (isRevolving(a)) { No fixed EMI (revolving limit) } @else { ₹{{ emiAmountFor(a) | number: '1.0-0' }} / month }
} @if (!isRevolving(a)) {
EMI Calculation Basis
Principal (Loan Amount)
₹{{ a.requestedAmount | number: '1.0-0' }}
Interest Rate
{{ a.interestRate }}% p.a. ({{ a.interestRate / 12 | number: '1.2-2' }}% / month)
Tenure
{{ a.tenureMonths }} months
Total Interest Payable
₹{{ totalInterestFor(a) | number: '1.0-0' }}
Total Amount Payable
₹{{ totalPayableFor(a) | number: '1.0-0' }}

Reducing-balance EMI formula: EMI = [P × r × (1+r)n] / [(1+r)n − 1] — where P = Principal, r = Monthly Interest Rate, n = Tenure in months. On P = ₹{{ a.requestedAmount | number: '1.0-0' }}, r = {{ a.interestRate / 12 / 100 | number: '1.4-4' }}, n = {{ a.tenureMonths }} → EMI = ₹{{ emiAmountFor(a) | number: '1.0-0' }} / month.

} @if (a.coBorrowerRequired) {
Co-Borrower (raises household eligibility)
@if (a.coBorrowerWanted) {

Upload the co-borrower's last 3 months' salary slips:

@for (doc of coBorrowerCapture.salarySlips; track $index) { @if (doc.file || hasStoredDoc('COBORROWER:salarySlip:' + $index)) { } }
@if (coBorrowerDetailsComplete(a)) {
Combined Household Eligibility Calculation
Applicant's Monthly Income
₹{{ a.monthlyIncome | number: '1.0-0' }}
Applicant's EMI Capacity (40%)
₹{{ applicantEmiCapacity(a) | number: '1.0-0' }}
Co-Borrower's Monthly Income
₹{{ a.coBorrowerMonthlyIncome | number: '1.0-0' }}
Co-Borrower's EMI Capacity (40%)
₹{{ coBorrowerEmiCapacity(a) | number: '1.0-0' }}
Combined Household EMI Capacity
₹{{ combinedEmiCapacity(a) | number: '1.0-0' }}
Estimated EMI (this loan)
₹{{ emiAmountFor(a) | number: '1.0-0' }}

Combined Capacity = (40% × ₹{{ a.monthlyIncome | number: '1.0-0' }} applicant) + (40% × ₹{{ a.coBorrowerMonthlyIncome | number: '1.0-0' }} co-borrower) = ₹{{ applicantEmiCapacity(a) | number: '1.0-0' }} + ₹{{ coBorrowerEmiCapacity(a) | number: '1.0-0' }} = ₹{{ combinedEmiCapacity(a) | number: '1.0-0' }}. Estimated EMI ₹{{ emiAmountFor(a) | number: '1.0-0' }} is {{ combinedEligibilityOk(a) ? 'within' : 'above' }} this combined capacity.

@if (combinedEligibilityOk(a)) { Eligible with Co-Borrower } @else { Still not eligible — increase co-borrower income, reduce the amount, or extend tenure }
} } @if (!affordabilityOk(a)) {

@if (!coBorrowerDetailsComplete(a)) { @if (!a.coBorrowerWanted) { Check "Add a Co-Borrower" and complete their details to proceed. } @else { Add the co-borrower's name, relationship, monthly income and all 3 salary slips to proceed. } } @else { Combined household income still doesn't cover the EMI at 40% — adjust the amount, tenure, or co-borrower before proceeding. }

}
}
} @if (a.currentStage === 'CIC_CHECK') {
Customer Consent — Credit Bureau Check

RBI's Fair Practices Code requires the customer's signed consent before a credit bureau pull. Generate the declaration letter below, get it signed by the customer, then upload the signed copy.

@if (a.channel === 'BRANCH') { } @else { }
@if (cicConsentCapture.file || hasStoredDoc('CIC:consent')) {
} @if (a.cicConsentSigned) { Signed Declaration Uploaded } @else { Awaiting Signed Declaration }
CIC Check Charge — ₹{{ cicCheckCharge }}
@if (a.clientId && realDebitableAccounts.length > 0) {

Select which account to debit the ₹{{ cicCheckCharge }} charge from:

@for (acc of realDebitableAccounts; track acc.id) { }
} @else { @if (a.clientId && loadingShareAccounts) {

Loading accounts…

} @else { @if (a.clientId) {

No open savings/current account on file for this customer — collect the charge via payment link instead.

} @if (!a.cicPaymentLinkUrl || a.cicPaymentLinkUrl === '—') {
} @else {

{{ a.cicPaymentLinkUrl }}

@if (!a.cicChargeCollected) {
} } } } @if (a.cicChargeCollected) { Charge Collected — {{ a.cicChargeMode === 'ACCOUNT_DEBIT' ? a.cicChargeAccountLabel : 'Ref ' + a.cicPaymentReference }} } @else { Charge Not Collected }
@if (a.cibilScore === 0) {
@if (!a.cicConsentSigned || !a.cicChargeCollected) {

Print/share the declaration and get it signed, and collect the ₹{{ cicCheckCharge }} check charge, before checking the credit score.

} } @else {
{{ a.cibilScore }} {{ cibilBandOf(a.cibilScore) }}
Credit Bureau {{ a.cicBureau }}
Uploaded Report File {{ a.cicReportUploaded ? a.cicReportFileName : 'Not uploaded yet' }}
Field Inquiry Status {{ a.fiRequestPushed ? 'Pushed to ' + a.fiAgencyAssigned + ' (' + a.fiRequestDate + ')' : 'Not pushed yet' }}
@if (a.cicReportUploaded) {
@if (hasStoredDoc('CIC:report')) { }
}
} @if (a.cibilScore > 0) {
@if (a.cicReportUploaded && !a.fiRequestPushed) { } @else if (a.cicReportUploaded && a.fiRequestPushed) { }
}
} @if (a.currentStage === 'FIELD_INVESTIGATION') {
@if (a.clientId) {
Registered Addresses on File (Fineract)
@if (loadingAddresses) {

Loading addresses…

} @else if (realAddresses.length === 0) {

No addresses on file for this client.

} @else {
@for (addr of realAddresses; track $index) {
{{ addr.addressType || 'Address' }}

{{ formatRealAddress(addr) }}

}
}
}
@for (key of fiRows(a); track key) {
{{ fiCheckLabels[key] }}
@if (a[key].officerAssigned === '—') {
} @else {

Assigned to {{ a[key].officerAssigned }} on {{ a[key].assignedDate }}

@if (a[key].status === 'PENDING') { @if (fiIsOverdue(a, key)) {

⚠ {{ fiSlaLabel(a, key) }} — this visit is overdue.

} @else {

{{ fiSlaLabel(a, key) }}

}

Site Photos ({{ fiPhotoCapture[key].length }}):

@for (photo of fiPhotoCapture[key]; track $index) { }
@if (!fiCanVerify(a, key)) {

Capture latitude, longitude and at least one site photo before marking Verified.

}
} @else if (a[key].status === 'VERIFIED') { Verified } @else { Failed
} }
}
@if (a.secured) {
Property Valuation
Market Value (Area × Market Rate)
₹{{ a.propertyValuation | number: '1.0-0' }}
Guideline Value (Area × Circle Rate)
₹{{ guidelineValue(a) | number: '1.0-0' }}
Realizable Value (90% of Market)
₹{{ realizableValue(a) | number: '1.0-0' }}
Distress Sale Value (75% of Market)
₹{{ distressValue(a) | number: '1.0-0' }}
Loan-to-Value (vs Realizable)
{{ ltvPercent(a) | number: '1.0-1' }}%
@if (ltvHigh(a)) {

LTV exceeds 80% of the realizable value — this loan amount is aggressive against the property's worth; consider a lower amount or additional security.

}
}
Agent Report
{{ a.agentReportUploaded ? a.agentReportFileName : 'Not uploaded yet' }}
@if (a.agentReportUploaded) {
Report Remark
{{ a.agentReportRemark }}
}
@if (a.agentReportUploaded && hasStoredDoc('FI:agentReport')) {
} @if (!a.agentReportUploaded) {
}
} @if (a.currentStage === 'PERSONAL_DISCUSSION') {
Briefing Report — For the Meeting

Everything captured so far — KYC, CIC score, Field Investigation, property valuation, agent report and the full stage history — as one PDF for whoever takes this meeting.

Meeting Scheduler
@if (a.meetingScheduled) {

Scheduled with {{ a.meetingWith }} on {{ a.meetingDate }} at {{ a.meetingTime }} ({{ a.meetingMode === 'ONLINE' ? 'Online' : a.meetingMode === 'CALL' ? 'Phone Call' : 'Offline' }})

}
@if (a.meetingScheduled) {
@if (discrepancySelection === 'NONE') { } @else { }
} @else {

Schedule the meeting above before recording the discussion report.

}
} @if (a.currentStage === 'CREDIT_COMMITTEE') {
Full Application Report — For the Committee

Everything captured on this application — KYC, CIC score, Field Investigation, property valuation, agent report, meeting and stage history — as one PDF for every committee member to review before deciding.

Reports Required — present below reports, then complete.

@if (a.secured) { } @if (a.secured) { }
@if (committeeReportsReady(a) && !committeeCanApprove(a)) {

Enter the Resolution No. and Resolution Date the committee passed this decision under before approving.

}
} @if (a.currentStage === 'RISK_APPROVAL') {
@if (a.secured) { }
@if (a.guarantorRequired) {
Guarantor — Must Be an Existing Share Member
@if (!a.guarantorClientId) { @if (searchingGuarantor) {

Searching…

} @else if (guarantorSearchText.length >= 2 && guarantorSearchResults.length === 0) {

No clients found.

} @if (guarantorSearchResults.length > 0) {
@for (client of guarantorSearchResults; track client.id) { }
}

The guarantor must already be a bank client with an active share account — search and select them above, a name alone isn't enough.

} @else { @if (loadingGuarantorShareCheck) {

Checking share membership…

} @else if (a.guarantorHasShareAccount) { Share Member — Verified } @else { No Share Account Found

This client has no active share account — a guarantor must already be a bank member. Pick a different guarantor.

} }
}
} @if (a.currentStage === 'LEGAL_APPROVAL') {
@if (a.secured) { }
@if (a.legalDocuments.length > 0) {
}
} @if (a.currentStage === 'CUSTOMER_SIGNING') {

Loan Agreement and Sanction Letter ready for the customer's acknowledgement and signature.

} @if (a.currentStage === 'CHEQUE_ACH') {
} @if (a.currentStage === 'POST_CHECK') {

Document Signing by:

} @if (a.currentStage === 'DISBURSED') {

Disbursing also confirms EMI Activation for this account in the same step. @if (a.customerType === 'EXISTING' && a.clientId) { A real Fineract loan account will be created, approved and disbursed in Core Banking at the same time. } @else { This is a mock disbursement only — no Core Banking account exists until this customer is fully onboarded as a client. }

@if (a.fineractLoanError) {

{{ a.fineractLoanError }}

}
} }
Loan Committee {{ a.creditCommitteeApproval.decision }} {{ a.creditCommitteeApproval.approverName }} · {{ a.creditCommitteeApproval.date }} {{ a.creditCommitteeApproval.remarks }}
Risk Approval {{ a.riskApproval.decision }} {{ a.riskApproval.approverName }} · {{ a.riskApproval.date }} {{ a.riskApproval.remarks }}
Legal Approval {{ a.legalApproval.decision }} {{ a.legalApproval.approverName }} · {{ a.legalApproval.date }} {{ a.legalApproval.remarks }}
Post-Disbursement Check {{ a.postCheckApproval.decision }} {{ a.postCheckApproval.approverName }} · {{ a.postCheckApproval.date }} {{ a.postCheckApproval.remarks }}
@for (h of a.stageHistory; track h.date + h.stage + h.outcome) {
{{ stepMarker(a, h.stage) }}
{{ stageLabels[h.stage] }} — {{ h.outcome }} {{ h.date }}

{{ h.remarks }}

{{ h.actionBy }}
} @empty {

No activity recorded yet.

}
} @else {
}
{{ toastMsg }}