- 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>
173 lines
5.5 KiB
HTML
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>
|