- 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>
253 lines
9.5 KiB
TypeScript
253 lines
9.5 KiB
TypeScript
/**
|
|
* 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/.
|
|
*/
|
|
|
|
import { Injectable, inject } from '@angular/core';
|
|
import { HttpClient, HttpParams } from '@angular/common/http';
|
|
import { Observable } from 'rxjs';
|
|
|
|
export interface RbiFeedItem {
|
|
id: number;
|
|
title: string;
|
|
link: string;
|
|
description: string;
|
|
pubDate: any; // Fineract returns [year,month,day,hour,min,sec] array
|
|
category: string;
|
|
fetchedOn?: any;
|
|
openProjectWpId?: number; // OpenProject work package ID
|
|
openProjectWpStatus?: string;
|
|
openProjectWpProgress?: number;
|
|
}
|
|
|
|
@Injectable({
|
|
providedIn: 'root'
|
|
})
|
|
export class RbiCircularsService {
|
|
private http = inject(HttpClient);
|
|
|
|
getAll(category?: string): Observable<RbiFeedItem[]> {
|
|
let params = new HttpParams();
|
|
if (category) {
|
|
params = params.set('category', category);
|
|
}
|
|
return this.http.get<RbiFeedItem[]>('/rbi-feeds', { params });
|
|
}
|
|
|
|
getById(id: number): Observable<RbiFeedItem> {
|
|
return this.http.get<RbiFeedItem>(`/rbi-feeds/${id}`);
|
|
}
|
|
|
|
triggerFetch(): Observable<any> {
|
|
return this.http.post('/rbi-feeds/fetch', {});
|
|
}
|
|
|
|
/**
|
|
* Members and share capital per share type for one financial year, with the year before alongside.
|
|
*
|
|
* @param financialYear the year the FY opens in — 2025 means FY 2025-26.
|
|
*/
|
|
getShareCapitalReturn(financialYear: number): Observable<any> {
|
|
return this.http.get('/shareproducts/capital-return', {
|
|
params: new HttpParams().set('financialYear', String(financialYear))
|
|
});
|
|
}
|
|
|
|
/** Financial years that actually have share activity, newest first, for the year picker. */
|
|
getShareCapitalReturnYears(): Observable<any> {
|
|
return this.http.get('/shareproducts/capital-return/financial-years');
|
|
}
|
|
|
|
/**
|
|
* Form 1 — CRR, computed live from the ledger for the fortnight the reporting date falls in.
|
|
*
|
|
* The DTL base and the balances maintained are read as at different dates: the base lags by 45
|
|
* days (snapped back to a reporting Friday), the holdings are as at the reporting date itself.
|
|
* The response's `basis` block states both, so the lag is auditable rather than implied.
|
|
*
|
|
* @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, 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));
|
|
}
|
|
return this.http.get('/rbireservereturn/form1', { params });
|
|
}
|
|
|
|
/**
|
|
* Form 9 — SLR, computed live on the month-end position. Any date within a month resolves to that
|
|
* month's end, since the return reports the position at close.
|
|
*/
|
|
getForm9(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', { 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.
|
|
*
|
|
* Every figure is a closing balance as at the quarter end; the bank's own particulars come from
|
|
* the institution profile. Any date inside a quarter resolves to that quarter, so a caller never
|
|
* has to know which day a quarter ends on.
|
|
*
|
|
* @param quarterEndDate yyyy-MM-dd — any date in the quarter. Defaults to the business date.
|
|
* @param officeId Optional — scopes every figure to one office.
|
|
*/
|
|
getOss1(quarterEndDate?: string, officeId?: number): Observable<any> {
|
|
return this.http.get('/ossreturn/oss1', { params: this.ossParams(quarterEndDate, officeId) });
|
|
}
|
|
|
|
/**
|
|
* OSS 2 — Return on Earnings, computed live from the ledger.
|
|
*
|
|
* Earnings lines report the movement over the quarter rather than a closing balance, so the same
|
|
* accounts read as balances would carry forward every earlier quarter's income as well.
|
|
*/
|
|
getOss2(quarterEndDate?: string, officeId?: number): Observable<any> {
|
|
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 ──
|
|
|
|
/**
|
|
* Returns saved earlier, newest first. A saved return is served from the snapshot taken when it
|
|
* was saved, never recomputed — a backdated entry or a changed mapping would otherwise produce a
|
|
* different statement from the one that was reviewed.
|
|
*/
|
|
getSavedReturns(formCode?: string): Observable<any> {
|
|
let params = new HttpParams();
|
|
if (formCode) {
|
|
params = params.set('formCode', formCode);
|
|
}
|
|
return this.http.get('/rbiformafiling', { params });
|
|
}
|
|
|
|
/** One saved return, with the stored snapshot, so the screen renders what was saved. */
|
|
getSavedReturn(filingId: number): Observable<any> {
|
|
return this.http.get(`/rbiformafiling/${filingId}`);
|
|
}
|
|
|
|
/** Keeps the return currently on screen. Re-saving the same form and date replaces it. */
|
|
saveReturn(formCode: string, reportingDate: string, report: any, remarks?: string): Observable<any> {
|
|
return this.http.post('/rbiformafiling', {
|
|
formCode,
|
|
reportingDate,
|
|
report,
|
|
remarks,
|
|
locale: 'en',
|
|
dateFormat: 'yyyy-MM-dd'
|
|
});
|
|
}
|
|
|
|
/** Moves a saved return along its filing lifecycle; the snapshot itself is untouched. */
|
|
updateSavedReturnStatus(filingId: number, status: string, remarks?: string): Observable<any> {
|
|
return this.http.post(`/rbiformafiling/${filingId}/status`, { status, remarks });
|
|
}
|
|
|
|
deleteSavedReturn(filingId: number): Observable<any> {
|
|
return this.http.delete(`/rbiformafiling/${filingId}`);
|
|
}
|
|
|
|
private ossParams(quarterEndDate?: string, officeId?: number): HttpParams {
|
|
let params = new HttpParams();
|
|
if (quarterEndDate) {
|
|
params = params.set('quarterEndDate', quarterEndDate);
|
|
}
|
|
if (officeId != null) {
|
|
params = params.set('officeId', String(officeId));
|
|
}
|
|
return params;
|
|
}
|
|
}
|