diff --git a/src/app/npa/npa-data.ts b/src/app/npa/npa-data.ts
index 60dc67d56..0f0a79921 100644
--- a/src/app/npa/npa-data.ts
+++ b/src/app/npa/npa-data.ts
@@ -967,6 +967,7 @@ export const REPORT_META: ReportMeta[] = [
{ id: 'probable', group: 'classification', label: 'Probable NPA' },
{ id: 'sma', group: 'classification', label: 'SMA Report' },
{ id: 'recovery-dashboard', group: 'recovery-mgmt', label: 'Recovery Management Dashboard' },
+ { id: 'cc-recovery', group: 'recovery-mgmt', label: 'Cash Credit (CC) Recovery Management' },
{ id: 'daywise-overdue', group: 'recovery-mgmt', label: 'Day-wise Overdue Report' },
{ id: 'daywise-overdrawn', group: 'recovery-mgmt', label: 'Day-wise Overdrawn Report' },
{ id: 'agri-gold-value', group: 'recovery-mgmt', label: 'Agriculture / Gold Market Value Report' },
diff --git a/src/app/npa/npa-reports/npa-reports.component.html b/src/app/npa/npa-reports/npa-reports.component.html
index 9211bbdc8..9ad416d85 100644
--- a/src/app/npa/npa-reports/npa-reports.component.html
+++ b/src/app/npa/npa-reports/npa-reports.component.html
@@ -1400,6 +1400,184 @@
}
+
+ @if (activeReport === 'cc-recovery') {
+
+
+ Cash Credit (CC) Recovery Management — Drawing Power & Overdrawn-Day Tracking
+
+
+ Cash Credit is a revolving working-capital facility secured against stock / receivables. Unlike a Term Loan, it
+ isn't checked against a fixed instalment — it is checked against its Drawing Power (DP), and
+ tracked by how many continuous Days Overdrawn ("Out of Order") it has run — crossing 90 days
+ turns it NPA.
+
+
+
+
+
Drawing Power (DP)
+
+ The maximum amount the borrower may actually draw against the sanctioned CC limit — fixed from the value of
+ stock / book-debts declared in the latest stock statement. Can be lower than the sanctioned limit.
+
+
+
+
+
Out of Order
+
+ A CC account turns "Out of Order" once its outstanding continuously stays above the limit/DP, or adequate
+ credits stop coming in, for 90 days — the CC-specific overdue trigger, in place of a missed EMI.
+
+
+
+
+
Days Overdrawn
+
+ The running count of continuous days an account has stayed Out of Order — the number a recovery desk
+ actually watches day to day, instead of a classification label. A rising count is the early-warning sign.
+
+
+
+
+
NPA (Non-Performing Asset)
+
+ Once Out of Order crosses 90 days, the CC account slips to NPA — Sub-Standard, then Doubtful-1/2/3, then
+ Loss Asset as it ages further.
+
+
+
+
+
+
+
+
+
+ Total CC Accounts
+ {{ ccAccounts.length }}
+ ₹{{ ccTotalSanctioned | number: '1.0-0' }} sanctioned
+
+
+
+ Overdrawn (1–90 Days)
+ 0">{{ ccOverdrawnCount }}
+ Out of Order, not yet NPA
+
+
+
+ NPA (90+ Days Overdrawn)
+ {{ ccNpaCount }}
+ ₹{{ ccTotalOutstanding | number: '1.0-0' }} total outstanding
+
+
+
+ Interest Paid (This Cycle)
+ ₹{{ ccInterestPaidThisCycle | number: '1.0-0' }}
+ of ₹{{ ccInterestDueThisCycle | number: '1.0-0' }} due
+
+
+
+ Total Recovered
+ ₹{{ ccTotalRecovered | number: '1.0-0' }}
+ {{ ccRecoveryPct | number: '1.1-1' }}% of ₹{{ ccTotalSanctioned | number: '1.0-0' }} sanctioned
+
+
+
+
+
+
+ Cash Credit Accounts — Limit, DP & Classification ({{ ccOutOfOrderCount }} of {{ ccAccounts.length }} Out of
+ Order)
+
+
+ @if (ccAccounts.length > pageSize) {
+
+ }
+
+ }
+
@if (activeReport === 'agri-gold-value') {
diff --git a/src/app/npa/npa-reports/npa-reports.component.ts b/src/app/npa/npa-reports/npa-reports.component.ts
index f9f62f9cd..678eac397 100644
--- a/src/app/npa/npa-reports/npa-reports.component.ts
+++ b/src/app/npa/npa-reports/npa-reports.component.ts
@@ -660,6 +660,69 @@ export class NpaReportsComponent implements OnInit, OnDestroy {
return this.overdrawnAccounts.filter((a) => this.overdrawnBreachOf(a)).length;
}
+ // -------------------- Cash Credit (CC) Recovery Management --------------------
+ /** Pure Cash Credit (MSME) accounts only — product code '01' — kept separate from the combined
+ * Overdrawn (CC/OD/KCC) bucket so CC's own Drawing Power / Out-of-Order / SMA-NPA position can
+ * be reviewed on its own, the way a recovery desk actually works a CC book. */
+ get ccAccounts(): LoanAccount[] {
+ return this.allAccounts
+ .filter((a) => a.productCode === '01')
+ .sort((a, b) => this.excessOverDp(b) - this.excessOverDp(a));
+ }
+
+ /** Any CC account that's irregular — either drawn beyond its Drawing Power right now, or already
+ * NPA-staged from its overdrawn history (an NPA account doesn't "go Regular" just because it's
+ * briefly back within DP — RBI upgrade norms require full clearance first). Covers the same
+ * population the 1–90-day Overdrawn and 90+-day NPA buckets below split in two. */
+ get ccOutOfOrderCount(): number {
+ return this.ccAccounts.filter((a) => this.overdrawnBreachOf(a) || this.isNpaStageOf(a)).length;
+ }
+
+ /** Out of Order for 1–90 continuous days — the pre-NPA monitoring window a recovery desk tracks
+ * by plain day-count, not by an SMA-0/1/2 label (that split only matters for regulatory
+ * reporting, not the day-to-day collection screen). */
+ get ccOverdrawnCount(): number {
+ return this.ccAccounts.filter((a) => this.overdrawnBreachOf(a) && !this.isNpaStageOf(a)).length;
+ }
+
+ /** Out of Order for more than 90 continuous days — the point RBI norms classify a CC/OD account
+ * as NPA. */
+ get ccNpaCount(): number {
+ return this.ccAccounts.filter((a) => this.isNpaStageOf(a)).length;
+ }
+
+ get ccTotalSanctioned(): number {
+ return this.ccAccounts.reduce((s, a) => s + a.sanctionedAmount, 0);
+ }
+
+ get ccTotalOutstanding(): number {
+ return this.ccAccounts.reduce((s, a) => s + a.outstandingBalance, 0);
+ }
+
+ /** A Cash Credit account has no fixed EMI — each cycle's "due" amount is interest servicing on
+ * the drawn balance, so this total doubles as "how much interest was CC customers due to pay
+ * this cycle". */
+ get ccInterestDueThisCycle(): number {
+ return this.ccAccounts.reduce((s, a) => s + this.expectedThisMonth(a), 0);
+ }
+
+ /** How much of that interest the CC book has actually paid this cycle — the answer to "which
+ * customers have paid how much interest", summed across the Cash Credit book. */
+ get ccInterestPaidThisCycle(): number {
+ return this.ccAccounts.reduce((s, a) => s + this.actualThisMonth(a), 0);
+ }
+
+ /** Lifetime cash recovered against the CC book (recorded recovery transactions — cash deposits,
+ * cheques, NEFT/RTGS, auction/SARFAESI, OTS) — the answer to "loan diya kitna, recover kitna
+ * hua", measured against what was actually sanctioned. */
+ get ccTotalRecovered(): number {
+ return this.ccAccounts.reduce((s, a) => s + this.recovered(a), 0);
+ }
+
+ get ccRecoveryPct(): number {
+ return this.ccTotalSanctioned ? (this.ccTotalRecovered / this.ccTotalSanctioned) * 100 : 0;
+ }
+
// -------------------- Agriculture / Gold Market Value Report --------------------
get agriGoldAccounts(): LoanAccount[] {
return this.allAccounts
@@ -1617,6 +1680,63 @@ export class NpaReportsComponent implements OnInit, OnDestroy {
}
];
+ case 'cc-recovery':
+ return [
+ {
+ sheetName: 'Cash Credit Recovery',
+ title: 'Cash Credit (CC) Recovery Management — Drawing Power & Overdrawn-Day Tracking',
+ subtitle,
+ headers: [
+ 'Account No',
+ 'Customer',
+ 'Branch',
+ 'Sanctioned Limit',
+ 'Drawing Power',
+ 'Outstanding',
+ 'Pending to Recover',
+ 'Excess Over DP',
+ 'Interest Due (This Cycle)',
+ 'Interest Paid (This Cycle)',
+ 'Total Recovered',
+ 'Days Overdrawn',
+ 'Status',
+ 'Recovery Officer'
+ ],
+ widths: [
+ 16,
+ 22,
+ 16,
+ 16,
+ 16,
+ 16,
+ 16,
+ 16,
+ 18,
+ 18,
+ 18,
+ 14,
+ 14,
+ 20
+ ],
+ rows: this.ccAccounts.map((a) => [
+ a.accountNo,
+ a.customerName,
+ a.branchName,
+ a.sanctionedAmount,
+ a.drawingPower,
+ a.outstandingBalance,
+ a.overdueAmount,
+ this.excessOverDp(a),
+ this.expectedThisMonth(a),
+ this.actualThisMonth(a),
+ this.recovered(a),
+ this.isNpaStageOf(a) || this.overdrawnBreachOf(a) ? a.overdueDays : 0,
+ this.isNpaStageOf(a) ? 'NPA' : this.overdrawnBreachOf(a) ? 'Overdrawn' : 'Regular',
+ a.recoveryOfficer
+ ])
+ }
+ ];
+
case 'daywise-overdrawn':
return [
{
diff --git a/src/app/npa/npa-shared.scss b/src/app/npa/npa-shared.scss
index 419e908f0..f66d106c2 100644
--- a/src/app/npa/npa-shared.scss
+++ b/src/app/npa/npa-shared.scss
@@ -94,6 +94,165 @@
grid-template-columns: repeat(3, 1fr);
}
+// -----------------------------------------------------------------------
+// Cash Credit Recovery Management — a glossary strip explaining DP / Out of
+// Order / SMA / NPA to a reader meeting the terms for the first time (e.g. a
+// stakeholder demo), plus tone-coloured accents for that screen's KPI row.
+// -----------------------------------------------------------------------
+.npa-glossary {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
+ gap: 14px;
+ margin-top: 18px;
+}
+
+.npa-glossary-card {
+ padding: 16px 16px 16px 18px;
+ border-radius: 12px;
+ background: #fff;
+ border: 1px solid #e2e8f0;
+ border-left: 4px solid #64748b;
+ transition: box-shadow 0.15s ease;
+
+ &:hover {
+ box-shadow: 0 4px 14px rgb(15 23 42 / 8%);
+ }
+
+ &__icon {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 34px;
+ height: 34px;
+ border-radius: 999px;
+ background: #f1f5f9;
+ color: #475569;
+ font-size: 14px;
+ margin-bottom: 10px;
+ }
+
+ &__term {
+ font-size: 12px;
+ font-weight: 800;
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+ color: #0f172a;
+ margin-bottom: 6px;
+ }
+
+ &__desc {
+ font-size: 12.5px;
+ line-height: 1.55;
+ color: #475569;
+ margin: 0;
+ }
+
+ &--dp {
+ border-left-color: #2563eb;
+
+ .npa-glossary-card__icon {
+ background: #dbeafe;
+ color: #2563eb;
+ }
+ }
+
+ &--ooo {
+ border-left-color: #d97706;
+
+ .npa-glossary-card__icon {
+ background: #fef3c7;
+ color: #b45309;
+ }
+ }
+
+ &--sma {
+ border-left-color: #ca8a04;
+
+ .npa-glossary-card__icon {
+ background: #fef9c3;
+ color: #854d0e;
+ }
+ }
+
+ &--npa {
+ border-left-color: #dc2626;
+
+ .npa-glossary-card__icon {
+ background: #fee2e2;
+ color: #dc2626;
+ }
+ }
+}
+
+// Compact gap variant for a KPI row that otherwise uses npa-kpis--ratio's 4-wide grid — used by
+// the CC Recovery Management summary row, which packs more (smaller) tiles than the main header.
+.npa-kpis--compact {
+ gap: 8px;
+}
+
+// Tone-coloured KPI tile for the CC summary row — same .inv-kpi tile, with a left accent + icon
+// chip so "Out of Order"/"SMA"/"NPA" read as a severity strip rather than four identical boxes.
+// Sized smaller than the default .inv-kpi tile since this row packs 6 of them.
+.npa-kpi--accent {
+ padding: 10px 12px 10px 14px;
+ border-left: 4px solid var(--npa-kpi-accent, #64748b);
+
+ .inv-kpi__label {
+ font-size: 9px;
+ }
+
+ .inv-kpi__value {
+ font-size: 16px;
+ }
+
+ .inv-kpi__sub {
+ font-size: 10px;
+ }
+
+ .npa-kpi__icon {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 22px;
+ height: 22px;
+ border-radius: 999px;
+ background: var(--npa-kpi-accent-soft, #f1f5f9);
+ color: var(--npa-kpi-accent, #475569);
+ font-size: 10px;
+ margin-bottom: 4px;
+ }
+
+ &--neutral {
+ --npa-kpi-accent: #0f4f3c;
+ --npa-kpi-accent-soft: #dcfce7;
+ }
+
+ &--warn {
+ --npa-kpi-accent: #d97706;
+ --npa-kpi-accent-soft: #fef3c7;
+ }
+
+ &--sma {
+ --npa-kpi-accent: #ca8a04;
+ --npa-kpi-accent-soft: #fef9c3;
+ }
+
+ &--npa {
+ --npa-kpi-accent: #dc2626;
+ --npa-kpi-accent-soft: #fee2e2;
+ }
+
+ &--info {
+ --npa-kpi-accent: #2563eb;
+ --npa-kpi-accent-soft: #dbeafe;
+ }
+
+ &--positive {
+ --npa-kpi-accent: #15803d;
+ --npa-kpi-accent-soft: #dcfce7;
+ }
+}
+
// Account Detail header — title/badge on the left, the Recovery Journey trigger pinned right.
.npa-detail-header {
display: flex;
diff --git a/src/environments/.env.ts b/src/environments/.env.ts
index 5cf0d7b56..c7a2f2020 100644
--- a/src/environments/.env.ts
+++ b/src/environments/.env.ts
@@ -9,8 +9,8 @@
/* tslint:disable */
export default {
'mifos_x': {
- 'version': '261012',
- 'hash': '6b0f218b'
+ 'version': '261019',
+ 'hash': '1b70fb453'
},
'allow_switching_backend_instance': true
};