rd account and rd product code update

This commit is contained in:
Nitesh Yadav
2026-05-08 13:51:58 +05:30
parent 19c0e98e96
commit 9e85872eac
35 changed files with 2247 additions and 591 deletions
@@ -49,7 +49,6 @@ import { EditTaxComponentComponent } from './manage-tax-components/edit-tax-comp
import { ViewTaxGroupComponent } from './manage-tax-groups/view-tax-group/view-tax-group.component';
import { ShareProductsDividendsComponent } from './share-products/dividends-share-product/dividends.components';
import { CreateRecurringDepositProductComponent } from './recurring-deposit-products/create-recurring-deposit-product/create-recurring-deposit-product.component';
import { BaseRecurringDepositInterestRateChartComponent } from './recurring-deposit-products/base-recurring-deposit-interest-rate-chart/base-recurring-deposit-interest-rate-chart.component';
import { CreateDividendComponent } from './share-products/create-dividend/create-dividend.component';
import { ViewFixedDepositProductComponent } from './fixed-deposit-products/view-fixed-deposit-product/view-fixed-deposit-product.component';
import { ViewDividendComponent } from './share-products/view-dividend/view-dividend.component';
@@ -655,14 +654,6 @@ const routes: Routes = [
path: 'recurring-deposit-products',
data: { title: 'Recurring Deposit Products', breadcrumb: 'Recurring Deposit Products' },
children: [
{
path: 'base-interest-rates',
component: BaseRecurringDepositInterestRateChartComponent,
data: { title: 'CBS Base Interest Rates', breadcrumb: 'Base Interest Rates' },
resolve: {
recurringDepositProductsTemplate: RecurringDepositProductsTemplateResolver
}
},
{
path: 'create',
component: CreateRecurringDepositProductComponent,
@@ -717,14 +708,6 @@ const routes: Routes = [
}
}
]
},
{
path: 'interest-rates',
component: RdInterestRatesTabComponent,
data: { title: 'CBS Base Chart', breadcrumb: 'CBS Base Chart', routeParamBreadcrumb: false },
resolve: {
rdInterestRates: rdInterestRatesResolver
}
}
]
},
@@ -34,6 +34,7 @@ import {
import { ProductsService } from 'app/products/products.service';
import { SettingsService } from 'app/settings/settings.service';
import { Accounting } from 'app/core/utils/accounting';
import { Dates } from 'app/core/utils/dates';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { RecurringDepositProductPreviewStepComponent } from '../recurring-deposit-product-stepper/recurring-deposit-product-preview-step/recurring-deposit-product-preview-step.component';
import { MatTabsModule } from '@angular/material/tabs';
@@ -72,6 +73,7 @@ export class CreateRecurringDepositProductComponent {
private router = inject(Router);
private settingsService = inject(SettingsService);
private accounting = inject(Accounting);
private dateUtils = inject(Dates);
@ViewChild(RecurringDepositProductDetailsStepComponent, { static: true })
recurringDepositProductDetailsStep: RecurringDepositProductDetailsStepComponent;
@@ -112,7 +114,7 @@ export class CreateRecurringDepositProductComponent {
});
this.accountingRuleData = this.accounting.getAccountingRulesForSavings();
// Load the CBS base chart as the reference for the editable table
this.productsService.getRdBaseInterestRates().subscribe({
this.productsService.getFdBaseInterestRates().subscribe({
next: (rates: any[]) => {
this.rdInterestRates = rates || [];
},
@@ -151,7 +153,18 @@ export class CreateRecurringDepositProductComponent {
}
get activeBaseVersion() {
return this.rdInterestRates.find((version: any) => version.isActive) ?? this.rdInterestRates[0] ?? null;
const chart =
this.rdInterestRates.find((version: any) => version.fdType === 'DOUBLE' && version.isActive) ??
this.rdInterestRates.find((version: any) => version.fdType === 'DOUBLE') ??
this.rdInterestRates[0];
if (chart) {
return {
...chart,
versionLabel: chart.versionLabel?.replace('FD', 'RD'),
remarks: chart.remarks?.replace('FD', 'RD')
};
}
return null;
}
get activeBaseSlabs() {
@@ -166,17 +179,66 @@ export class CreateRecurringDepositProductComponent {
...this.recurringDepositProductSettingsStep.recurringDepositProductSettings,
...this.recurringDepositProductChargesStep.recurringDepositProductCharges,
...this.recurringDepositProductAccountingStep.recurringDepositProductAccounting,
charts: this.recurringDepositProductCharts,
rdSlabs: this.activeBaseSlabs
};
}
get recurringDepositProductCharts() {
const activeBaseVersion = this.activeBaseVersion;
if (!activeBaseVersion?.slabs?.length) {
return [];
}
const dateFormat = this.settingsService.dateFormat;
return [
{
name: activeBaseVersion.versionLabel || 'CBS Base Chart',
description: activeBaseVersion.remarks || activeBaseVersion.versionLabel || 'CBS base chart',
fromDate:
this.dateUtils.formatDate(activeBaseVersion.effectiveFromDate, dateFormat) ||
activeBaseVersion.effectiveFromDate,
...(activeBaseVersion.effectiveToDate
? {
endDate:
this.dateUtils.formatDate(activeBaseVersion.effectiveToDate, dateFormat) ||
activeBaseVersion.effectiveToDate
}
: {}),
isPrimaryGroupingByAmount: false,
locale: this.settingsService.language.code,
dateFormat,
chartSlabs: activeBaseVersion.slabs.map((slab: any) => {
const chartSlab: any = {
periodType: slab.periodTypeEnum,
fromPeriod: slab.fromPeriod,
toPeriod: slab.toPeriod,
annualInterestRate: slab.annualInterestRate,
description: slab.description || '',
incentives: [] as any[]
};
if (slab.amountRangeFrom !== null && slab.amountRangeFrom !== undefined && slab.amountRangeFrom !== '') {
chartSlab.amountRangeFrom = slab.amountRangeFrom;
}
if (slab.amountRangeTo !== null && slab.amountRangeTo !== undefined && slab.amountRangeTo !== '') {
chartSlab.amountRangeTo = slab.amountRangeTo;
}
return chartSlab;
})
}
] as any[];
}
submit() {
// TODO: Update once language and date settings are setup
const recurringDepositProduct = {
const recurringDepositProduct: any = this.pruneEmptyValues({
...this.recurringDepositProduct,
charges: this.recurringDepositProduct.charges.map((charge: any) => ({ id: charge.id })),
locale: this.settingsService.language.code // locale required for depositAmount
};
charts: this.recurringDepositProductCharts,
charges: (this.recurringDepositProduct.charges ?? []).map((charge: any) => ({ id: charge.id })),
locale: this.settingsService.language.code
});
if (!recurringDepositProduct.description) {
recurringDepositProduct.description = '';
}
@@ -191,4 +253,35 @@ export class CreateRecurringDepositProductComponent {
);
});
}
private pruneEmptyValues<T>(value: T): T {
if (Array.isArray(value)) {
return value.map((item) => this.pruneEmptyValues(item)).filter((item) => item !== undefined) as T;
}
if (value && typeof value === 'object') {
return Object.entries(value as Record<string, any>).reduce(
(acc, [
key,
currentValue
]) => {
const cleanedValue = this.pruneEmptyValues(currentValue);
if (cleanedValue === undefined) {
return acc;
}
return {
...acc,
[key]: cleanedValue
};
},
{} as Record<string, any>
) as T;
}
if (value === '' || value === null || value === undefined) {
return undefined as T;
}
return value;
}
}
@@ -34,6 +34,7 @@ import {
import { ProductsService } from 'app/products/products.service';
import { SettingsService } from 'app/settings/settings.service';
import { Accounting } from 'app/core/utils/accounting';
import { Dates } from 'app/core/utils/dates';
import { MatTabsModule } from '@angular/material/tabs';
import { RecurringDepositProductPreviewStepComponent } from '../recurring-deposit-product-stepper/recurring-deposit-product-preview-step/recurring-deposit-product-preview-step.component';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
@@ -70,6 +71,7 @@ export class EditRecurringDepositProductComponent {
private router = inject(Router);
private settingsService = inject(SettingsService);
private accounting = inject(Accounting);
private dateUtils = inject(Dates);
@ViewChild(RecurringDepositProductDetailsStepComponent, { static: true })
recurringDepositProductDetailsStep: RecurringDepositProductDetailsStepComponent;
@@ -107,7 +109,7 @@ export class EditRecurringDepositProductComponent {
constructor() {
this.route.data.subscribe((data: { recurringDepositProductAndTemplate: any }) => {
this.recurringDepositProductsTemplate = data.recurringDepositProductAndTemplate;
this.productsService.getRdBaseInterestRates().subscribe({
this.productsService.getFdBaseInterestRates().subscribe({
next: (rates: any[]) => {
this.rdInterestRates = rates || [];
},
@@ -148,7 +150,18 @@ export class EditRecurringDepositProductComponent {
}
get activeBaseVersion() {
return this.rdInterestRates.find((version: any) => version.isActive) ?? this.rdInterestRates[0] ?? null;
const chart =
this.rdInterestRates.find((version: any) => version.fdType === 'DOUBLE' && version.isActive) ??
this.rdInterestRates.find((version: any) => version.fdType === 'DOUBLE') ??
this.rdInterestRates[0];
if (chart) {
return {
...chart,
versionLabel: chart.versionLabel?.replace('FD', 'RD'),
remarks: chart.remarks?.replace('FD', 'RD')
};
}
return null;
}
get activeBaseSlabs() {
@@ -163,6 +176,7 @@ export class EditRecurringDepositProductComponent {
...this.recurringDepositProductSettingsStep.recurringDepositProductSettings,
...this.recurringDepositProductChargesStep.recurringDepositProductCharges,
...this.recurringDepositProductAccountingStep.recurringDepositProductAccounting,
charts: this.recurringDepositProductCharts,
rdSlabs: this.activeBaseSlabs
};
}
@@ -170,13 +184,63 @@ export class EditRecurringDepositProductComponent {
get recurringDepositProductPreview() {
return {
...this.recurringDepositProduct,
charts: this.recurringDepositProductCharts,
rdSlabs: this.activeBaseSlabs
};
}
get recurringDepositProductCharts() {
const activeBaseVersion = this.activeBaseVersion;
if (!activeBaseVersion?.slabs?.length) {
return [];
}
const dateFormat = this.settingsService.dateFormat;
return [
{
name: activeBaseVersion.versionLabel || 'CBS Base Chart',
description: activeBaseVersion.remarks || activeBaseVersion.versionLabel || 'CBS base chart',
fromDate:
this.dateUtils.formatDate(activeBaseVersion.effectiveFromDate, dateFormat) ||
activeBaseVersion.effectiveFromDate,
...(activeBaseVersion.effectiveToDate
? {
endDate:
this.dateUtils.formatDate(activeBaseVersion.effectiveToDate, dateFormat) ||
activeBaseVersion.effectiveToDate
}
: {}),
isPrimaryGroupingByAmount: false,
locale: this.settingsService.language.code,
dateFormat,
chartSlabs: activeBaseVersion.slabs.map((slab: any) => {
const chartSlab: any = {
periodType: slab.periodTypeEnum,
fromPeriod: slab.fromPeriod,
toPeriod: slab.toPeriod,
annualInterestRate: slab.annualInterestRate,
description: slab.description || '',
incentives: [] as any[]
};
if (slab.amountRangeFrom !== null && slab.amountRangeFrom !== undefined && slab.amountRangeFrom !== '') {
chartSlab.amountRangeFrom = slab.amountRangeFrom;
}
if (slab.amountRangeTo !== null && slab.amountRangeTo !== undefined && slab.amountRangeTo !== '') {
chartSlab.amountRangeTo = slab.amountRangeTo;
}
return chartSlab;
})
}
] as any[];
}
submit() {
const recurringDepositProduct: any = this.pruneEmptyValues({
...this.recurringDepositProduct,
charts: this.recurringDepositProductCharts,
charges: (this.recurringDepositProduct.charges ?? []).map((charge: any) => ({ id: charge.id })),
locale: this.settingsService.language.code
});
@@ -63,28 +63,6 @@
</mat-radio-group>
</div>
<div class="rdpc-alert">
<div class="rdpc-alert__content">
<h4>Balance Swap Option</h4>
<p>Enable automated transfer of excess funds to linked deposits or vice-versa to maintain liquidity.</p>
</div>
<mat-radio-group class="rdpc-alert__choices" formControlName="balanceSwapOption">
<mat-radio-button [value]="true">yes</mat-radio-button>
<mat-radio-button [value]="false">no</mat-radio-button>
</mat-radio-group>
</div>
<div class="rdpc-alert">
<div class="rdpc-alert__content">
<h4>MSME</h4>
<p>Micro, Small and Medium Enterprises</p>
</div>
<mat-radio-group class="rdpc-alert__choices" formControlName="msme">
<mat-radio-button [value]="true">yes</mat-radio-button>
<mat-radio-button [value]="false">no</mat-radio-button>
</mat-radio-group>
</div>
<div class="rdpc-alert">
<div class="rdpc-alert__content">
<h4>Nomination Facility</h4>
@@ -55,8 +55,6 @@ export class RecurringDepositProductCurrencyStepComponent implements OnInit {
daysToInactive: this.recurringDepositProductsTemplate.daysToInactive ?? 30,
daysToDormancy: this.recurringDepositProductsTemplate.daysToDormancy ?? 60,
daysToEscheat: this.recurringDepositProductsTemplate.daysToEscheat ?? 90,
balanceSwapOption: this.recurringDepositProductsTemplate.balanceSwapOption ?? false,
msme: this.recurringDepositProductsTemplate.msme ?? false,
nominationFacility: this.recurringDepositProductsTemplate.nominationFacility ?? false,
autoDebitFacility: this.recurringDepositProductsTemplate.autoDebitFacility ?? false
});
@@ -80,8 +78,6 @@ export class RecurringDepositProductCurrencyStepComponent implements OnInit {
daysToInactive: [30],
daysToDormancy: [60],
daysToEscheat: [90],
balanceSwapOption: [false],
msme: [false],
nominationFacility: [false],
autoDebitFacility: [false]
});
@@ -93,8 +89,6 @@ export class RecurringDepositProductCurrencyStepComponent implements OnInit {
currencyCode: formValue.currencyCode,
digitsAfterDecimal: formValue.digitsAfterDecimal,
dormancyAlert: formValue.dormancyAlert,
balanceSwapOption: formValue.balanceSwapOption,
msme: formValue.msme,
nominationFacility: formValue.nominationFacility,
autoDebitFacility: formValue.autoDebitFacility
};
@@ -78,15 +78,6 @@
<mat-error>Account Type <strong>is required</strong></mat-error>
</mat-form-field>
<mat-form-field appearance="outline" class="rdpd-field">
<mat-label>Customer Segment</mat-label>
<mat-select formControlName="customerSegment">
@for (customerSegment of customerSegmentData; track customerSegment) {
<mat-option [value]="customerSegment">{{ customerSegment }}</mat-option>
}
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline" class="rdpd-field">
<mat-label>GL Account (Liability)</mat-label>
<mat-select formControlName="glAccountId" [compareWith]="compareById">
@@ -72,7 +72,6 @@ export class RecurringDepositProductDetailsStepComponent implements OnInit, OnCh
null,
Validators.required
],
customerSegment: [null],
glAccountId: [null],
effectiveTo: [''],
endDate: [''],
@@ -107,7 +106,6 @@ export class RecurringDepositProductDetailsStepComponent implements OnInit, OnCh
private applyTemplate(template: any) {
this.accountTypeData = this.getOptionNames(template.accountTypeOptions);
this.customerSegmentData = this.getOptionNames(template.customerSegmentOptions);
this.liabilityAccountOptions = template.accountingMappingOptions?.liabilityAccountOptions ?? [];
this.cdr.detectChanges();
@@ -117,7 +115,6 @@ export class RecurringDepositProductDetailsStepComponent implements OnInit, OnCh
shortName: isEditing ? template.shortName : template.shortName || '',
description: template.description || '',
accountType: template.accountType ?? this.accountTypeData[0] ?? null,
customerSegment: template.customerSegment ?? this.customerSegmentData[0] ?? null,
glAccountId: template.glAccountId ?? null,
effectiveTo: this.parseDate(template.effectiveTo),
endDate: this.parseDate(template.endDate),
@@ -1,4 +1,4 @@
<!--
<!--
Copyright since 2025 Mifos Initiative
This Source Code Form is subject to the terms of the Mozilla Public
@@ -46,13 +46,6 @@
</div>
}
@if (recurringDepositProduct.customerSegment) {
<div class="flex-100 layout-row">
<span class="flex-40">Customer Segment:</span>
<span class="flex-60">{{ recurringDepositProduct.customerSegment }}</span>
</div>
}
@if (recurringDepositProduct.glAccountId) {
<div class="flex-100 layout-row">
<span class="flex-40">GL Account (Liability):</span>
@@ -116,20 +109,6 @@
</div>
}
@if (recurringDepositProduct.balanceSwapOption !== undefined) {
<div class="flex-100 layout-row">
<span class="flex-40">Balance Swap Option:</span>
<span class="flex-60">{{ recurringDepositProduct.balanceSwapOption | yesNo }}</span>
</div>
}
@if (recurringDepositProduct.msme !== undefined) {
<div class="flex-100 layout-row">
<span class="flex-40">MSME:</span>
<span class="flex-60">{{ recurringDepositProduct.msme | yesNo }}</span>
</div>
}
@if (recurringDepositProduct.nominationFacility !== undefined) {
<div class="flex-100 layout-row">
<span class="flex-40">Nomination Facility:</span>
@@ -144,6 +123,28 @@
</div>
}
@if (
recurringDepositProduct.minDepositAmount !== undefined || recurringDepositProduct.maxDepositAmount !== undefined
) {
<mat-divider class="flex-100"></mat-divider>
<h3 class="mat-h3 flex-100">Deposit Amount</h3>
<mat-divider class="flex-100"></mat-divider>
@if (recurringDepositProduct.minDepositAmount !== undefined) {
<div class="flex-100 layout-row">
<span class="flex-40">Minimum:</span>
<span class="flex-60">{{ recurringDepositProduct.minDepositAmount }}</span>
</div>
}
@if (recurringDepositProduct.maxDepositAmount !== undefined) {
<div class="flex-100 layout-row">
<span class="flex-40">Maximum:</span>
<span class="flex-60">{{ recurringDepositProduct.maxDepositAmount }}</span>
</div>
}
}
<!-- ── Terms ── -->
<h3 class="mat-h3 flex-100">{{ 'labels.inputs.Terms' | translate }}</h3>
<mat-divider class="flex-100"></mat-divider>
@@ -324,8 +325,9 @@
</div>
}
<!-- ── Interest Rate Slabs ── -->
<!-- ── Interest Rate Slabs ── -->
@if (recurringDepositProduct.rdSlabs?.length) {
<mat-divider class="flex-100"></mat-divider>
<h3 class="mat-h3 flex-100">{{ 'labels.heading.Interest Rate Charts' | translate }}</h3>
<mat-divider class="flex-100"></mat-divider>
@@ -7,6 +7,25 @@
-->
<form [formGroup]="recurringDepositProductTermsForm">
<div class="rdpt-section">
<div class="rdpt-section__header">
<span class="rdpt-section__badge"><i class="fas fa-coins"></i></span>
<span>Deposit Amount</span>
</div>
<div class="rdpt-body">
<div class="rdpt-grid rdpt-grid--three">
<mat-form-field appearance="outline" class="rdpt-field">
<mat-label>Minimum</mat-label>
<input type="number" matInput formControlName="minDepositAmount" min="0" step="0.01" />
</mat-form-field>
<mat-form-field appearance="outline" class="rdpt-field">
<mat-label>Maximum</mat-label>
<input type="number" matInput formControlName="maxDepositAmount" min="0" step="0.01" />
</mat-form-field>
</div>
</div>
</div>
<div class="rdpt-section">
<div class="rdpt-section__header">
<span class="rdpt-section__badge"><i class="fas fa-chart-line"></i></span>
@@ -78,6 +97,26 @@
</mat-error>
</mat-form-field>
<mat-form-field appearance="outline" class="rdpt-field">
<mat-label>Interest Compounding Period</mat-label>
<mat-select formControlName="interestCompoundingPeriodType" required>
@for (opt of interestCompoundingPeriodTypeData; track opt.id) {
<mat-option [value]="opt.id">{{ opt.value | translateKey: 'catalogs' }}</mat-option>
}
</mat-select>
<mat-error>Interest Compounding Period <strong>is required</strong></mat-error>
</mat-form-field>
<mat-form-field appearance="outline" class="rdpt-field">
<mat-label>Days in Year</mat-label>
<mat-select formControlName="interestCalculationDaysInYearType" required>
@for (opt of interestCalculationDaysInYearTypeData; track opt.id) {
<mat-option [value]="opt.id">{{ opt.value | translateKey: 'catalogs' }}</mat-option>
}
</mat-select>
<mat-error>Days in Year <strong>is required</strong></mat-error>
</mat-form-field>
@if (recurringDepositProductTermsForm.value.interestCalculationType === 2) {
<mat-form-field appearance="outline" class="rdpt-field">
<mat-label>Average Period</mat-label>
@@ -85,7 +85,9 @@ export class RecurringDepositProductTermsStepComponent implements OnInit {
frequencyFixDay: isEditing ? (this.recurringDepositProductsTemplate.frequencyFixDay ?? 30) : 30,
lastInterestDate: this.recurringDepositProductsTemplate.lastInterestDate
? this.parseDate(this.recurringDepositProductsTemplate.lastInterestDate)
: ''
: '',
minDepositAmount: this.recurringDepositProductsTemplate.minDepositAmount ?? '',
maxDepositAmount: this.recurringDepositProductsTemplate.maxDepositAmount ?? ''
});
}
@@ -145,7 +147,9 @@ export class RecurringDepositProductTermsStepComponent implements OnInit {
30,
[Validators.min(0)]
],
lastInterestDate: ['']
lastInterestDate: [''],
minDepositAmount: [''],
maxDepositAmount: ['']
});
}
@@ -156,14 +160,8 @@ export class RecurringDepositProductTermsStepComponent implements OnInit {
if (formValue.effectiveDate instanceof Date) {
formValue.effectiveDate = this.dateUtils.formatDate(formValue.effectiveDate, dateFormat) || '';
}
if (formValue.lastInterestDate instanceof Date) {
formValue.lastInterestDate = this.dateUtils.formatDate(formValue.lastInterestDate, dateFormat) || '';
}
for (const key in formValue) {
if (formValue[key] === '') {
delete formValue[key];
}
}
formValue.minDepositAmount = formValue.minDepositAmount;
formValue.maxDepositAmount = formValue.maxDepositAmount;
return formValue;
}
}
@@ -20,18 +20,6 @@
{{ 'labels.buttons.Create Recurring Deposit Product' | translate }}
</button>
</div>
<div class="in-block">
<button
mat-stroked-button
color="primary"
[routerLink]="['/products/recurring-deposit-products/base-interest-rates']"
matTooltip="Open the CBS base interest chart"
matTooltipPosition="above"
>
<fa-icon icon="chart-line" class="m-r-10"></fa-icon>
CBS Base Chart
</button>
</div>
</div>
<div class="container">
@@ -48,12 +48,6 @@
<span class="flex-60">{{ recurringDepositProduct.accountType }}</span>
</div>
}
@if (recurringDepositProduct.customerSegment) {
<div class="flex-100 layout-row">
<span class="flex-40">Customer Segment:</span>
<span class="flex-60">{{ recurringDepositProduct.customerSegment }}</span>
</div>
}
@if (recurringDepositProduct.glAccountId) {
<div class="flex-100 layout-row">
<span class="flex-40">GL Account (Liability):</span>
@@ -99,14 +93,6 @@
<span class="flex-40">Dormancy Alert:</span>
<span class="flex-60">{{ recurringDepositProduct.dormancyAlert | yesNo }}</span>
</div>
<div class="flex-100 layout-row">
<span class="flex-40">Balance Swap Option:</span>
<span class="flex-60">{{ recurringDepositProduct.balanceSwapOption | yesNo }}</span>
</div>
<div class="flex-100 layout-row">
<span class="flex-40">MSME:</span>
<span class="flex-60">{{ recurringDepositProduct.msme | yesNo }}</span>
</div>
<div class="flex-100 layout-row">
<span class="flex-40">Nomination Facility:</span>
<span class="flex-60">{{ recurringDepositProduct.nominationFacility | yesNo }}</span>
@@ -18,15 +18,6 @@
>
{{ 'labels.heading.General' | translate }}
</a>
<a
mat-tab-link
[routerLink]="['./interest-rates']"
routerLinkActive
#interestRates="routerLinkActive"
[active]="interestRates.isActive"
>
CBS Base Chart
</a>
@for (recurringDepositDatatable of recurringDepositDatatables; track recurringDepositDatatable) {
<a
mat-tab-link