Files
cbsnexora/src/app/interest-posting-summary/interest-posting-summary.component.html
T
keshavandClaude Opus 5.5 b6994c0b76 feat(rbi-reserve,savings): Form 1/Form 9 returns UI, branch-wise interest posting reports and summary
- Reports > Interest Posting Reports: per branch and product, generate/regenerate
  at any time, approve; branch column, HO-on-behalf marker, posted txn per account
- Reports > Interest Posting Summary (branch-wise) for the head office, with Excel export
- Day Close warns and disables Close Day while the branch's interest report is unapproved
- Savings product accounting: Interest On Savings (expense), Savings Interest Payable
  and Paid (liability rows, required)
- RBI Form 1 statutory and Form 9 return screens, reserve config updates
- Interest posting report GETs exempted from the response cache

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 13:20:01 +05:30

173 lines
5.5 KiB
HTML

<!--
Copyright since 2025 Mifos Initiative
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
<div class="ipr">
<div class="ipr-head">
<div>
<h2 class="ipr-head-t"><fa-icon icon="percentage"></fa-icon> Interest Posting Summary</h2>
<div class="ipr-head-s">
Savings interest across every branch: for each posting date, branch and product, how many customers were paid
and how much. Each branch approves and posts its own; this is the head office's view.
</div>
</div>
<div class="ipr-head-a">
<label class="ipr-date">
From
<input type="date" [(ngModel)]="fromDate" (change)="load()" />
</label>
<label class="ipr-date">
To
<input type="date" [(ngModel)]="toDate" (change)="load()" />
</label>
<label class="ipr-date">
Product
<select [(ngModel)]="productId">
<option [ngValue]="null">All products</option>
@for (p of products; track p.id) {
<option [ngValue]="p.id">{{ p.name }}</option>
}
</select>
</label>
<button class="ipr-btn" (click)="load()" [disabled]="loading"><fa-icon icon="undo"></fa-icon> Reload</button>
<button class="ipr-btn ipr-btn--primary" (click)="exportExcel()" [disabled]="loading || shown.length === 0">
<fa-icon icon="file-excel"></fa-icon> Export Excel
</button>
</div>
</div>
@if (errorMessage) {
<div class="ipr-alert ipr-alert--error">
<fa-icon icon="exclamation-triangle"></fa-icon>
<div>{{ errorMessage }}</div>
</div>
}
@if (pendingCount > 0) {
<div class="ipr-alert ipr-alert--warn">
<fa-icon icon="clock"></fa-icon>
<div>{{ pendingCount }} branch report(s) in this period are not posted yet.</div>
</div>
}
<div class="ipr-card">
<div class="ipr-detail-head">
<div>
<h3>Branch totals</h3>
<div class="muted">{{ fromDate }} to {{ toDate }}</div>
</div>
<div class="ipr-total">
<span>Total interest</span>
<strong>₹{{ totalInterest | number: '1.2-2' }}</strong>
<span class="muted">{{ totalCustomers }} customer(s) · posted ₹{{ postedInterest | number: '1.2-2' }}</span>
</div>
</div>
<table class="ipr-table">
<thead>
<tr>
<th>Branch</th>
<th class="num">Reports</th>
<th class="num">Customers</th>
<th class="num">Interest</th>
<th class="num">Posted</th>
<th class="num">Not yet posted</th>
</tr>
</thead>
<tbody>
@for (b of byBranch; track b.officeName) {
<tr>
<td>
<strong>{{ b.officeName }}</strong>
</td>
<td class="num">{{ b.reports }}</td>
<td class="num">{{ b.customers }}</td>
<td class="num">₹{{ b.interest | number: '1.2-2' }}</td>
<td class="num">₹{{ b.posted | number: '1.2-2' }}</td>
<td class="num">₹{{ b.interest - b.posted | number: '1.2-2' }}</td>
</tr>
} @empty {
<tr>
<td colspan="6" class="ipr-empty">
@if (loading) {
Loading…
} @else {
No interest posting report in this period.
}
</td>
</tr>
}
</tbody>
@if (byBranch.length > 0) {
<tfoot>
<tr>
<td><strong>Total</strong></td>
<td class="num">
<strong>{{ shown.length }}</strong>
</td>
<td class="num">
<strong>{{ totalCustomers }}</strong>
</td>
<td class="num">
<strong>₹{{ totalInterest | number: '1.2-2' }}</strong>
</td>
<td class="num">
<strong>₹{{ postedInterest | number: '1.2-2' }}</strong>
</td>
<td class="num">
<strong>₹{{ totalInterest - postedInterest | number: '1.2-2' }}</strong>
</td>
</tr>
</tfoot>
}
</table>
</div>
<div class="ipr-card">
<table class="ipr-table">
<thead>
<tr>
<th>Posting date</th>
<th>Branch</th>
<th>Product</th>
<th class="num">Customers</th>
<th class="num">Interest</th>
<th>Status</th>
<th>Approved</th>
<th>Posted</th>
</tr>
</thead>
<tbody>
@for (r of shown; track r.id) {
<tr>
<td>{{ r.postingDate }}</td>
<td>{{ r.officeName }}</td>
<td>
<strong>{{ r.productName }}</strong>
</td>
<td class="num">{{ r.accountCount }}</td>
<td class="num">₹{{ r.totalInterest | number: '1.2-2' }}</td>
<td>
<span class="ipr-badge" [ngClass]="statusClass(r.status)">{{ r.status }}</span>
</td>
<td class="muted">
@if (r.approvedAt) {
{{ r.approvedBy }}
@if (r.approvedOnBehalf) {
<span class="ipr-behalf">(HO)</span>
}
<br />{{ r.approvedAt | date: 'dd MMM, HH:mm' }}
} @else {
—
}
</td>
<td class="muted">{{ r.postedAt ? (r.postedAt | date: 'dd MMM, HH:mm') : '—' }}</td>
</tr>
}
</tbody>
</table>
</div>
</div>