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>
This commit is contained in:
2026-10-01 13:20:01 +05:30
co-authored by Claude Opus 5.5
parent 4f02f24aae
commit b6994c0b76
39 changed files with 4407 additions and 245 deletions
+78 -1
View File
@@ -71,11 +71,17 @@ export class RbiCircularsService {
* @param reportingDate yyyy-MM-dd. Defaults to the current business date on the backend.
* @param officeId Optional — scopes every figure to one office.
*/
getForm1(reportingDate?: string, officeId?: number): Observable<any> {
getForm1(reportingDate?: string, baseDate?: string, officeId?: number): Observable<any> {
let params = new HttpParams();
if (reportingDate) {
params = params.set('reportingDate', reportingDate);
}
// The base date can be given outright. The 45-day lag lands where it lands, and a bank reading
// an earlier fortnight — or correcting a filing — needs to name the date the base is struck at
// rather than work backwards from it. Left blank it is derived from the lag as before.
if (baseDate) {
params = params.set('baseDate', baseDate);
}
if (officeId != null) {
params = params.set('officeId', String(officeId));
}
@@ -97,6 +103,44 @@ export class RbiCircularsService {
return this.http.get('/rbireservereturn/form9', { params });
}
/**
* Form 9 in the shape it is filed — the statutory statement of compliance with section 24.
*
* A different statement from `getForm9`, not a reformatting: three dated columns rather than one,
* and the ratio charged on the last Friday of the second preceding fortnight rather than on the
* month end itself.
*/
getForm9Statutory(reportingDate?: string, officeId?: number): Observable<any> {
let params = new HttpParams();
if (reportingDate) {
params = params.set('reportingDate', reportingDate);
}
if (officeId != null) {
params = params.set('officeId', String(officeId));
}
return this.http.get('/rbireservereturn/form9-statutory', { params });
}
/**
* Form IX — the Return on Assets and Liabilities a co-operative bank files monthly, code R408.
*
* A different return from `getForm9` despite the name: that one reports the SLR ratio, this one
* reports the whole balance sheet. Every figure comes back in rupees thousands, with the rupee
* figure alongside it so a line can still be reconciled against the ledger.
*
* @param reportingDate yyyy-MM-dd — any date in the month; the return reports that month's end.
*/
getForm9Return(reportingDate?: string, officeId?: number): Observable<any> {
let params = new HttpParams();
if (reportingDate) {
params = params.set('reportingDate', reportingDate);
}
if (officeId != null) {
params = params.set('officeId', String(officeId));
}
return this.http.get('/rbireservereturn/form9-return', { params });
}
/**
* OSS 1 — Return on Assets and Liabilities, computed live from the ledger.
*
@@ -121,6 +165,39 @@ export class RbiCircularsService {
return this.http.get('/ossreturn/oss2', { params: this.ossParams(quarterEndDate, officeId) });
}
/**
* Form 1 as a co-operative bank files it — Banking Regulation (Co-operative Societies) Rules
* 1966, Rule 5, sections 18(1) and 24(3).
*
* A different statement from `getForm1`, not a reformatting: three columns rather than one, both
* ratios settled on the same liabilities, and those liabilities taken from the last Friday of the
* second preceding fortnight rather than a 45-day lag.
*/
getForm1Statutory(
reportingDate?: string,
firstColumnDate?: string,
secondColumnDate?: string,
officeId?: number
): Observable<any> {
let params = new HttpParams();
if (reportingDate) {
params = params.set('reportingDate', reportingDate);
}
// Both fortnight closes can be given outright. A bank filing August wants 15/08 and 31/08 on
// the face of the form whatever today is, and one date cannot produce a pair that spans a month
// boundary or skips a fortnight — which a late or corrected filing needs.
if (firstColumnDate) {
params = params.set('firstColumnDate', firstColumnDate);
}
if (secondColumnDate) {
params = params.set('secondColumnDate', secondColumnDate);
}
if (officeId != null) {
params = params.set('officeId', String(officeId));
}
return this.http.get('/rbireservereturn/form1-statutory', { params });
}
// ── Saved returns ──
/**