Upgrading to Angular 20:

Replaced checked in package-lock.json by regenerated one.
Ran ng update @angular/core@20 @angular/cli@20
Ran npm install @angular-builders/jest@^20.0.0 @fortawesome/angular-fontawesome@^3.0.0 @swimlane/ngx-graph@^11
Ran npm install ngx-mat-select-search@^8.0.2.
Ran ng update @angular/material@20.
Updated all eslint and typescript to the latest versions.
Removed @angular-devkit/schematics.
Updated fontawesome.
Updated rxjs and tslib.
Moved required node version from 16 to 20.
Updated jest-preset-angular.
Set preserveWhitespaces to false.
Corrected two type declarations in two typescript files to make ng serve run without errors.
Removed unused angular-devkit/schematics from view-user.component.ts .
Updated list of supported browsers.
Upgraded prettier.
Ran prettier . --write the first time.
Ran prettier . --write the second time.
Ran ng generate @angular/core:inject with defaults, excepted a handful of files.
Fixed remaining eslint problems.
Added dist directory to ignores in eslint.config.js.
Let prettier fix formatting, almost everything is just line breaks.
Made htmlhint ignore @if and @for Angular constructs.
Updated node version in Github workflow to 22.12.0 (build.yml).
Updated .env.ts.
Updated Angular datetime format strings from YYYY-MM-DD to yyyy-MM-dd.
Merged changes from dev into angular20 branch.
This commit is contained in:
Felix van Hove
2025-12-08 11:01:01 +01:00
parent f1b4ec2cf2
commit 7fd1486c08
1516 changed files with 39367 additions and 36037 deletions
+2 -5
View File
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
import { ActivatedRouteSnapshot } from '@angular/router';
/** rxjs Imports */
@@ -13,10 +13,7 @@ import { ProductsService } from 'app/products/products.service';
*/
@Injectable()
export class ChargeResolver {
/**
* @param {productsService} productsService Products service.
*/
constructor(private productsService: ProductsService) {}
private productsService = inject(ProductsService);
/**
* Returns the charge data.
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
import { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router';
/** rxjs Imports */
@@ -10,7 +10,7 @@ import { ProductsService } from '../products.service';
@Injectable()
export class ChargesTemplateAndResolver {
constructor(private productsService: ProductsService) {}
private productsService = inject(ProductsService);
/**
* Returns the changes template and data.
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
/** rxjs Imports */
import { Observable } from 'rxjs';
@@ -12,10 +12,7 @@ import { ProductsService } from '../products.service';
*/
@Injectable()
export class ChargesTemplateResolver {
/**
* @param {ProductsService} productsService Products service.
*/
constructor(private productsService: ProductsService) {}
private productsService = inject(ProductsService);
/**
* Returns the charges template data.
+23 -19
View File
@@ -18,9 +18,11 @@
placeholder="{{ 'labels.inputs.Filter' | translate }}"
(selectionChange)="filterByAppliesTo($event.value)"
>
<mat-option *ngFor="let chargeAppliesTo of chargeAppliesToOptions" [value]="chargeAppliesTo.id">
{{ chargeAppliesTo.value | translateKey: 'catalogs' }}
</mat-option>
@for (chargeAppliesTo of chargeAppliesToOptions; track chargeAppliesTo) {
<mat-option [value]="chargeAppliesTo.id">
{{ chargeAppliesTo.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
</mat-form-field>
</div>
@@ -57,22 +59,24 @@
{{ 'labels.commons.Is' | translate }} {{ 'labels.inputs.Penalty' | translate }}?
</th>
<td mat-cell *matCellDef="let charge" class="center">
<fa-icon
*ngIf="charge.penalty"
icon="check-circle"
size="lg"
class="ispenalty"
matTooltip="{{ 'tooltips.Yes' | translate }}"
matTooltipPosition="right"
></fa-icon>
<fa-icon
*ngIf="!charge.penalty"
icon="times-circle"
size="lg"
class="nopenalty"
matTooltip="{{ 'tooltips.No' | translate }}"
matTooltipPosition="right"
></fa-icon>
@if (charge.penalty) {
<fa-icon
icon="check-circle"
size="lg"
class="ispenalty"
matTooltip="{{ 'tooltips.Yes' | translate }}"
matTooltipPosition="right"
></fa-icon>
}
@if (!charge.penalty) {
<fa-icon
icon="times-circle"
size="lg"
class="nopenalty"
matTooltip="{{ 'tooltips.No' | translate }}"
matTooltipPosition="right"
></fa-icon>
}
</td>
</ng-container>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit, TemplateRef, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
import { Component, OnInit, TemplateRef, ElementRef, ViewChild, AfterViewInit, inject } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort, MatSortHeader } from '@angular/material/sort';
import {
@@ -59,6 +59,12 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class ChargesComponent implements OnInit, AfterViewInit {
private route = inject(ActivatedRoute);
private router = inject(Router);
private configurationWizardService = inject(ConfigurationWizardService);
private popoverService = inject(PopoverService);
private charges = inject(Charges);
/** Charge data. */
chargeData: Charge[] = [];
/** Columns to be displayed in charges table. */
@@ -97,13 +103,7 @@ export class ChargesComponent implements OnInit, AfterViewInit {
* @param {ConfigurationWizardService} configurationWizardService ConfigurationWizard Service.
* @param {PopoverService} popoverService PopoverService.
*/
constructor(
private route: ActivatedRoute,
private router: Router,
private configurationWizardService: ConfigurationWizardService,
private popoverService: PopoverService,
private charges: Charges
) {
constructor() {
this.route.data.subscribe((data: { charges: any }) => {
this.chargeData = data.charges;
});
+2 -5
View File
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
/** rxjs Imports */
import { Observable } from 'rxjs';
@@ -12,10 +12,7 @@ import { ProductsService } from '../products.service';
*/
@Injectable()
export class ChargesResolver {
/**
* @param {ProductsService} productsService Products service.
*/
constructor(private productsService: ProductsService) {}
private productsService = inject(ProductsService);
/**
* Returns the products data.
@@ -6,248 +6,265 @@
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Charge Applies To' | translate }}</mat-label>
<mat-select required formControlName="chargeAppliesTo">
<mat-option
*ngFor="let chargeAppliesTo of chargesTemplateData.chargeAppliesToOptions"
[value]="chargeAppliesTo.id"
>
{{ chargeAppliesTo.value | translateKey: 'catalogs' }}
</mat-option>
@for (chargeAppliesTo of chargesTemplateData.chargeAppliesToOptions; track chargeAppliesTo) {
<mat-option [value]="chargeAppliesTo.id">
{{ chargeAppliesTo.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
<mat-error *ngIf="chargeForm.controls.chargeAppliesTo.hasError('required')">
{{ 'labels.inputs.Charge Applies To' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (chargeForm.controls.chargeAppliesTo.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Charge Applies To' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-divider [inset]="true"></mat-divider>
<div
*ngIf="chargeForm.controls.chargeAppliesTo.value"
class="layout-row-wrap gap-2percent layout-lt-md-column form-section"
>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Charge Name' | translate }}</mat-label>
<input matInput required formControlName="name" />
<mat-error *ngIf="chargeForm.controls.name.hasError('required')">
{{ 'labels.inputs.Charge Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Currency' | translate }}</mat-label>
<mat-select required formControlName="currencyCode">
<mat-option *ngFor="let currency of chargesTemplateData.currencyOptions" [value]="currency.code">
{{ currency.name }}
</mat-option>
</mat-select>
<mat-error *ngIf="chargeForm.controls.currencyCode.hasError('required')">
{{ 'labels.inputs.Currency' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Charge Time Type' | translate }}</mat-label>
<mat-select required formControlName="chargeTimeType">
<mat-option *ngFor="let chargeTimeType of chargeTimeTypeData" [value]="chargeTimeType.id">
{{ chargeTimeType.value | translateKey: 'catalogs' }}
</mat-option>
</mat-select>
<mat-error *ngIf="chargeForm.controls.chargeTimeType.hasError('required')">
{{ 'labels.inputs.Charge Time Type' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Charge Calculation Type' | translate }}</mat-label>
<mat-select required formControlName="chargeCalculationType">
<mat-option
*ngFor="let chargeCalculationType of filteredChargeCalculationType()"
[value]="chargeCalculationType.id"
@if (chargeForm.controls.chargeAppliesTo.value) {
<div class="layout-row-wrap gap-2percent layout-lt-md-column form-section">
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Charge Name' | translate }}</mat-label>
<input matInput required formControlName="name" />
@if (chargeForm.controls.name.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Charge Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Currency' | translate }}</mat-label>
<mat-select required formControlName="currencyCode">
@for (currency of chargesTemplateData.currencyOptions; track currency) {
<mat-option [value]="currency.code">
{{ currency.name }}
</mat-option>
}
</mat-select>
@if (chargeForm.controls.currencyCode.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Currency' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Charge Time Type' | translate }}</mat-label>
<mat-select required formControlName="chargeTimeType">
@for (chargeTimeType of chargeTimeTypeData; track chargeTimeType) {
<mat-option [value]="chargeTimeType.id">
{{ chargeTimeType.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
@if (chargeForm.controls.chargeTimeType.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Charge Time Type' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Charge Calculation Type' | translate }}</mat-label>
<mat-select required formControlName="chargeCalculationType">
@for (chargeCalculationType of filteredChargeCalculationType(); track chargeCalculationType) {
<mat-option [value]="chargeCalculationType.id">
{{ chargeCalculationType.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
@if (chargeForm.controls.chargeCalculationType.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Charge Calculation Type' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
@if (chargeForm.controls.chargeAppliesTo.value === 1) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Charge Payment Mode' | translate }}</mat-label>
<mat-select required formControlName="chargePaymentMode">
@for (chargePaymentMode of chargesTemplateData.chargePaymetModeOptions; track chargePaymentMode) {
<mat-option [value]="chargePaymentMode.id">
{{ chargePaymentMode.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
@if (chargeForm.controls.chargePaymentMode.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Charge Payment Mode' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
}
@if (chargeForm.controls.chargeTimeType.value === 9) {
<div class="flex-48 add-fee-frequency-wrapper">
<mat-checkbox labelPosition="before" formControlName="addFeeFrequency">
{{ 'labels.inputs.Add Fee Frequency' | translate }}
</mat-checkbox>
</div>
}
@if (chargeForm.controls.chargeTimeType.value === 9 && chargeForm.controls.addFeeFrequency.value) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Frequency Interval' | translate }}</mat-label>
<input matInput required formControlName="feeInterval" />
@if (chargeForm.controls.feeInterval.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Frequency Interval' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
@if (chargeForm.controls.feeInterval.hasError('pattern')) {
<mat-error>
{{ 'labels.inputs.Frequency Interval' | translate }}
<strong>{{ 'labels.commons.must be a positive integer' | translate }}</strong>
</mat-error>
}
</mat-form-field>
}
@if (chargeForm.controls.chargeTimeType.value === 9 && chargeForm.controls.addFeeFrequency.value) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Charge Frequency' | translate }}</mat-label>
<mat-select required formControlName="feeFrequency">
@for (feeFrequency of chargesTemplateData.feeFrequencyOptions; track feeFrequency) {
<mat-option [value]="feeFrequency.id">
{{ feeFrequency.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
@if (chargeForm.controls.feeFrequency.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Charge Frequency' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
}
@if (chargeForm.controls.chargeTimeType.value === 6 || chargeForm.controls.chargeTimeType.value === 7) {
<mat-form-field (click)="dueDatePicker.open()" class="flex-48">
<mat-label>{{ 'labels.inputs.Due Date' | translate }}</mat-label>
<input
matInput
[min]="minDate"
[max]="maxDate"
[matDatepicker]="dueDatePicker"
required
formControlName="feeOnMonthDay"
/>
<mat-datepicker-toggle matSuffix [for]="dueDatePicker"></mat-datepicker-toggle>
<mat-datepicker #dueDatePicker></mat-datepicker>
@if (chargeForm.controls.feeOnMonthDay.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Due Date' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
}
@if (chargeForm.controls.chargeTimeType.value === 7 || chargeForm.controls.chargeTimeType.value === 11) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Repeat Every' | translate }} ({{ repeatEveryLabel }})</mat-label>
<input matInput required formControlName="feeInterval" />
@if (chargeForm.controls.feeInterval.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Repeat Every' | translate }} ({{ repeatEveryLabel }})
{{ 'labels.commons.is' | translate }} <strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
@if (
(chargeForm.controls.feeInterval.hasError('min') ||
chargeForm.controls.feeInterval.hasError('max')) &&
!chargeForm.controls.feeInterval.hasError('pattern')
) {
<mat-error>
{{ 'labels.inputs.Repeat Every' | translate }} ({{ repeatEveryLabel }})
<strong>{{ 'labels.commons.must be between 1 and 12' | translate }}</strong>
</mat-error>
}
@if (chargeForm.controls.feeInterval.hasError('pattern')) {
<mat-error>
{{ 'labels.inputs.Repeat Every' | translate }} ({{ repeatEveryLabel }})
<strong>{{ 'labels.commons.must be a positive integer' | translate }}</strong>
</mat-error>
}
</mat-form-field>
}
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Amount' | translate }}</mat-label>
<input matInput required formControlName="amount" />
@if (chargeForm.controls.amount.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Amount' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<!--
* minCap and maxCap only allowed for loan ,shares and savings entitites
* In Loan case: Only for the "charge calculation type" set as "%amount", "% loan amount+interest", "%interest",and"%disbursement amount".
* In saving case: Only for 1. charge time type is "withdrawlfee" or "savings no activity fee" with charge calculation type as "% amount"
* In shares case: Only for charge time type: SHARE_PURCHASE and SHARE_REDEEM and with charge calculation type as % amount only
-->
@if (showMinMaxCap()) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Minimum Charge Cap' | translate }}</mat-label>
<input matInput autofocus formControlName="minCap" mifosxValidateOnFocus />
@if (chargeForm.controls.minCap.hasError('maxValue')) {
<mat-error>
{{ 'errors.validation.msg.loanproduct.minimumGap.not.greater.than.specified.number' | translate }}
({{ chargeForm.controls.maxCap.value }})
</mat-error>
}
</mat-form-field>
}
@if (showMinMaxCap()) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Maximum Charge Cap' | translate }}</mat-label>
<input matInput autofocus formControlName="maxCap" mifosxValidateOnFocus />
@if (chargeForm.controls.maxCap.hasError('minValue')) {
<mat-error>
{{ 'errors.validation.msg.loanproduct.maximumGap.not.greater.than.specified.number' | translate }}
({{ chargeForm.controls.minCap.value }})
</mat-error>
}
</mat-form-field>
}
@if (chargeForm.controls.chargeAppliesTo.value === 3) {
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="chargeForm.controls.incomeAccountId"
[glAccountList]="incomeAndLiabilityAccountData"
[inputLabel]="'Income from Charge'"
>
{{ chargeCalculationType.value | translateKey: 'catalogs' }}
</mat-option>
</mat-select>
<mat-error *ngIf="chargeForm.controls.chargeCalculationType.hasError('required')">
{{ 'labels.inputs.Charge Calculation Type' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field *ngIf="chargeForm.controls.chargeAppliesTo.value === 1" class="flex-48">
<mat-label>{{ 'labels.inputs.Charge Payment Mode' | translate }}</mat-label>
<mat-select required formControlName="chargePaymentMode">
<mat-option
*ngFor="let chargePaymentMode of chargesTemplateData.chargePaymetModeOptions"
[value]="chargePaymentMode.id"
>
{{ chargePaymentMode.value | translateKey: 'catalogs' }}
</mat-option>
</mat-select>
<mat-error *ngIf="chargeForm.controls.chargePaymentMode.hasError('required')">
{{ 'labels.inputs.Charge Payment Mode' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<div class="flex-48 add-fee-frequency-wrapper" *ngIf="chargeForm.controls.chargeTimeType.value === 9">
<mat-checkbox labelPosition="before" formControlName="addFeeFrequency">
{{ 'labels.inputs.Add Fee Frequency' | translate }}
</mat-checkbox>
</div>
<mat-form-field
*ngIf="chargeForm.controls.chargeTimeType.value === 9 && chargeForm.controls.addFeeFrequency.value"
class="flex-48"
>
<mat-label>{{ 'labels.inputs.Frequency Interval' | translate }}</mat-label>
<input matInput required formControlName="feeInterval" />
<mat-error *ngIf="chargeForm.controls.feeInterval.hasError('required')">
{{ 'labels.inputs.Frequency Interval' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
<mat-error *ngIf="chargeForm.controls.feeInterval.hasError('pattern')">
{{ 'labels.inputs.Frequency Interval' | translate }}
<strong>{{ 'labels.commons.must be a positive integer' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field
*ngIf="chargeForm.controls.chargeTimeType.value === 9 && chargeForm.controls.addFeeFrequency.value"
class="flex-48"
>
<mat-label>{{ 'labels.inputs.Charge Frequency' | translate }}</mat-label>
<mat-select required formControlName="feeFrequency">
<mat-option
*ngFor="let feeFrequency of chargesTemplateData.feeFrequencyOptions"
[value]="feeFrequency.id"
>
{{ feeFrequency.value | translateKey: 'catalogs' }}
</mat-option>
</mat-select>
<mat-error *ngIf="chargeForm.controls.feeFrequency.hasError('required')">
{{ 'labels.inputs.Charge Frequency' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field
(click)="dueDatePicker.open()"
*ngIf="chargeForm.controls.chargeTimeType.value === 6 || chargeForm.controls.chargeTimeType.value === 7"
class="flex-48"
>
<mat-label>{{ 'labels.inputs.Due Date' | translate }}</mat-label>
<input
matInput
[min]="minDate"
[max]="maxDate"
[matDatepicker]="dueDatePicker"
required
formControlName="feeOnMonthDay"
/>
<mat-datepicker-toggle matSuffix [for]="dueDatePicker"></mat-datepicker-toggle>
<mat-datepicker #dueDatePicker></mat-datepicker>
<mat-error *ngIf="chargeForm.controls.feeOnMonthDay.hasError('required')">
{{ 'labels.inputs.Due Date' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field
class="flex-48"
*ngIf="chargeForm.controls.chargeTimeType.value === 7 || chargeForm.controls.chargeTimeType.value === 11"
>
<mat-label>{{ 'labels.inputs.Repeat Every' | translate }} ({{ repeatEveryLabel }})</mat-label>
<input matInput required formControlName="feeInterval" />
<mat-error *ngIf="chargeForm.controls.feeInterval.hasError('required')">
{{ 'labels.inputs.Repeat Every' | translate }} ({{ repeatEveryLabel }})
{{ 'labels.commons.is' | translate }} <strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
<mat-error
*ngIf="
(chargeForm.controls.feeInterval.hasError('min') ||
chargeForm.controls.feeInterval.hasError('max')) &&
!chargeForm.controls.feeInterval.hasError('pattern')
"
>
{{ 'labels.inputs.Repeat Every' | translate }} ({{ repeatEveryLabel }})
<strong>{{ 'labels.commons.must be between 1 and 12' | translate }}</strong>
</mat-error>
<mat-error *ngIf="chargeForm.controls.feeInterval.hasError('pattern')">
{{ 'labels.inputs.Repeat Every' | translate }} ({{ repeatEveryLabel }})
<strong>{{ 'labels.commons.must be a positive integer' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Amount' | translate }}</mat-label>
<input matInput required formControlName="amount" />
<mat-error *ngIf="chargeForm.controls.amount.hasError('required')">
{{ 'labels.inputs.Amount' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<!--
* minCap and maxCap only allowed for loan ,shares and savings entitites
* In Loan case: Only for the "charge calculation type" set as "%amount", "% loan amount+interest", "%interest",and"%disbursement amount".
* In saving case: Only for 1. charge time type is "withdrawlfee" or "savings no activity fee" with charge calculation type as "% amount"
* In shares case: Only for charge time type: SHARE_PURCHASE and SHARE_REDEEM and with charge calculation type as % amount only
-->
<mat-form-field class="flex-48" *ngIf="showMinMaxCap()">
<mat-label>{{ 'labels.inputs.Minimum Charge Cap' | translate }}</mat-label>
<input matInput autofocus formControlName="minCap" mifosxValidateOnFocus />
<mat-error *ngIf="chargeForm.controls.minCap.hasError('maxValue')">
{{ 'errors.validation.msg.loanproduct.minimumGap.not.greater.than.specified.number' | translate }} ({{
chargeForm.controls.maxCap.value
}})
</mat-error>
</mat-form-field>
<mat-form-field class="flex-48" *ngIf="showMinMaxCap()">
<mat-label>{{ 'labels.inputs.Maximum Charge Cap' | translate }}</mat-label>
<input matInput autofocus formControlName="maxCap" mifosxValidateOnFocus />
<mat-error *ngIf="chargeForm.controls.maxCap.hasError('minValue')">
{{ 'errors.validation.msg.loanproduct.maximumGap.not.greater.than.specified.number' | translate }} ({{
chargeForm.controls.minCap.value
}})
</mat-error>
</mat-form-field>
<mifosx-gl-account-selector
class="flex-48"
*ngIf="chargeForm.controls.chargeAppliesTo.value === 3"
[inputFormControl]="chargeForm.controls.incomeAccountId"
[glAccountList]="incomeAndLiabilityAccountData"
[inputLabel]="'Income from Charge'"
>
</mifosx-gl-account-selector>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Tax Group' | translate }}</mat-label>
<mat-select formControlName="taxGroupId">
<mat-option *ngFor="let taxGroup of chargesTemplateData.taxGroupOptions" [value]="taxGroup.id">
{{ taxGroup.name }}
</mat-option>
</mat-select>
</mat-form-field>
<div class="flex-48 layout-row gap-2percent layout-lt-md-column">
<div class="flex-50 active-wrapper">
<mat-checkbox labelPosition="before" formControlName="active">
{{ 'labels.status.Active' | translate }}
</mat-checkbox>
</div>
<div class="flex-50 penalty-wrapper">
<mat-checkbox labelPosition="before" formControlName="penalty">
{{ 'labels.commons.Is' | translate }} {{ 'labels.inputs.Penalty' | translate }}
</mat-checkbox>
</mifosx-gl-account-selector>
}
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Tax Group' | translate }}</mat-label>
<mat-select formControlName="taxGroupId">
@for (taxGroup of chargesTemplateData.taxGroupOptions; track taxGroup) {
<mat-option [value]="taxGroup.id">
{{ taxGroup.name }}
</mat-option>
}
</mat-select>
</mat-form-field>
<div class="flex-48 layout-row gap-2percent layout-lt-md-column">
<div class="flex-50 active-wrapper">
<mat-checkbox labelPosition="before" formControlName="active">
{{ 'labels.status.Active' | translate }}
</mat-checkbox>
</div>
<div class="flex-50 penalty-wrapper">
<mat-checkbox labelPosition="before" formControlName="penalty">
{{ 'labels.commons.Is' | translate }} {{ 'labels.inputs.Penalty' | translate }}
</mat-checkbox>
</div>
</div>
</div>
</div>
}
</div>
</mat-card-content>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import {
UntypedFormGroup,
UntypedFormBuilder,
@@ -37,6 +37,13 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class CreateChargeComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
private productsService = inject(ProductsService);
private route = inject(ActivatedRoute);
private router = inject(Router);
private dateUtils = inject(Dates);
private settingsService = inject(SettingsService);
/** Charge form. */
chargeForm: UntypedFormGroup;
/** Charges template data. */
@@ -65,14 +72,7 @@ export class CreateChargeComponent implements OnInit {
* @param {Dates} dateUtils Date Utils to format date.
* @param {SettingsService} settingsService Settings Service
*/
constructor(
private formBuilder: UntypedFormBuilder,
private productsService: ProductsService,
private route: ActivatedRoute,
private router: Router,
private dateUtils: Dates,
private settingsService: SettingsService
) {
constructor() {
this.route.data.subscribe((data: { chargesTemplate: any }) => {
this.chargesTemplateData = data.chargesTemplate;
const incomeOptions = data.chargesTemplate.incomeOrLiabilityAccountOptions.incomeAccountOptions || [];
@@ -123,7 +123,8 @@ export class CreateChargeComponent implements OnInit {
'',
[
Validators.required,
Validators.pattern('^\\s*(?=.*[1-9])\\d*(?:\\.\\d+)?\\s*$')]
Validators.pattern('^\\s*(?=.*[1-9])\\d*(?:\\.\\d+)?\\s*$')
]
],
active: [false],
penalty: [false],
@@ -263,7 +264,8 @@ export class CreateChargeComponent implements OnInit {
Validators.required,
Validators.min(1),
Validators.max(12),
Validators.pattern('^[1-9]\\d*$')])
Validators.pattern('^[1-9]\\d*$')
])
);
this.repeatEveryLabel = 'Months';
break;
@@ -277,7 +279,8 @@ export class CreateChargeComponent implements OnInit {
'feeInterval',
new UntypedFormControl('', [
Validators.required,
Validators.pattern('^[1-9]\\d*$')])
Validators.pattern('^[1-9]\\d*$')
])
);
} else {
this.chargeForm.removeControl('feeFrequency');
@@ -290,7 +293,8 @@ export class CreateChargeComponent implements OnInit {
'feeInterval',
new UntypedFormControl('', [
Validators.required,
Validators.pattern('^[1-9]\\d*$')])
Validators.pattern('^[1-9]\\d*$')
])
);
this.repeatEveryLabel = 'Weeks';
break;
@@ -6,12 +6,11 @@
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Charge Applies To' | translate }}</mat-label>
<mat-select required formControlName="chargeAppliesTo">
<mat-option
*ngFor="let chargeAppliesTo of chargeData.chargeAppliesToOptions"
[value]="chargeAppliesTo.id"
>
{{ chargeAppliesTo.value | translateKey: 'catalogs' }}
</mat-option>
@for (chargeAppliesTo of chargeData.chargeAppliesToOptions; track chargeAppliesTo) {
<mat-option [value]="chargeAppliesTo.id">
{{ chargeAppliesTo.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
</mat-form-field>
</div>
@@ -20,187 +19,228 @@
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Name' | translate }}</mat-label>
<input matInput required autofocus formControlName="name" />
<mat-error *ngIf="chargeForm.controls.name.hasError('required')">
{{ 'labels.inputs.Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (chargeForm.controls.name.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Currency' | translate }}</mat-label>
<mat-select required formControlName="currencyCode">
<mat-option *ngFor="let currency of chargeData.currencyOptions" [value]="currency.code">
{{ currency.name }}
</mat-option>
@for (currency of chargeData.currencyOptions; track currency) {
<mat-option [value]="currency.code">
{{ currency.name }}
</mat-option>
}
</mat-select>
<mat-error *ngIf="chargeForm.controls.currencyCode.hasError('required')">
{{ 'labels.inputs.Currency' | translate }} {{ 'labels.inputs.Type' | translate }}
{{ 'labels.commons.is' | translate }} <strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (chargeForm.controls.currencyCode.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Currency' | translate }} {{ 'labels.inputs.Type' | translate }}
{{ 'labels.commons.is' | translate }} <strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Charge Time Type' | translate }}</mat-label>
<mat-select required formControlName="chargeTimeType">
<mat-option *ngFor="let chargeTime of chargeTimeTypeOptions" [value]="chargeTime.id">
{{ chargeTime.value | translateKey: 'catalogs' }}
</mat-option>
@for (chargeTime of chargeTimeTypeOptions; track chargeTime) {
<mat-option [value]="chargeTime.id">
{{ chargeTime.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
<mat-error *ngIf="chargeForm.controls.chargeTimeType.hasError('required')">
{{ 'labels.inputs.Charge Time Type' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (chargeForm.controls.chargeTimeType.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Charge Time Type' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Charge Calculation' | translate }}</mat-label>
<mat-select required formControlName="chargeCalculationType">
<mat-option *ngFor="let chargeCalculation of chargeCalculationTypeOptions" [value]="chargeCalculation.id">
{{ chargeCalculation.value | translateKey: 'catalogs' }}
</mat-option>
@for (chargeCalculation of chargeCalculationTypeOptions; track chargeCalculation) {
<mat-option [value]="chargeCalculation.id">
{{ chargeCalculation.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
<mat-error *ngIf="chargeForm.controls.chargeCalculationType.hasError('required')">
{{ 'labels.inputs.Charge Calculation Type' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (chargeForm.controls.chargeCalculationType.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Charge Calculation Type' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48" *ngIf="chargePaymentMode">
<mat-label>{{ 'labels.inputs.Charge Payment By' | translate }}</mat-label>
<mat-select required formControlName="chargePaymentMode">
<mat-option
*ngFor="let chargePaymentMode of chargeData.chargePaymetModeOptions"
[value]="chargePaymentMode.id"
>
{{ chargePaymentMode.value | translateKey: 'catalogs' }}
</mat-option>
</mat-select>
<mat-error *ngIf="chargeForm.controls.chargePaymentMode.hasError('required')">
{{ 'labels.inputs.Charge Payment Mode' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
@if (chargePaymentMode) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Charge Payment By' | translate }}</mat-label>
<mat-select required formControlName="chargePaymentMode">
@for (chargePaymentMode of chargeData.chargePaymetModeOptions; track chargePaymentMode) {
<mat-option [value]="chargePaymentMode.id">
{{ chargePaymentMode.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
@if (chargeForm.controls.chargePaymentMode.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Charge Payment Mode' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
}
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Amount' | translate }}</mat-label>
<input matInput required autofocus type="text" formControlName="amount" />
<mat-error *ngIf="chargeForm.controls.amount.hasError('required')">
{{ 'labels.inputs.Amount' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (chargeForm.controls.amount.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Amount' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<!--
* minCap and maxCap only allowed for loan ,shares and savings entitites
* In Loan case: Only for the "charge calculation type" set as "%amount", "% loan amount+interest", "%interest",and "%disbursement amount".
* In saving case: Only for 1. charge time type is "withdrawlfee" or "savings no activity fee" with charge calculation type as "% amount"
* In shares case: Only for charge time type: SHARE_PURCHASE and SHARE_REDEEM and with charge calculation type as % amount only
-->
<mat-form-field
class="flex-48"
*ngIf="
(chargeForm.controls.chargeAppliesTo.value === 1 &&
(chargeForm.controls.chargeCalculationType.value === 2 ||
chargeForm.controls.chargeCalculationType.value === 3 ||
chargeForm.controls.chargeCalculationType.value === 4 ||
chargeForm.controls.chargeCalculationType.value === 5)) ||
(chargeForm.controls.chargeAppliesTo.value === 2 &&
(chargeForm.controls.chargeTimeType.value === 16 || chargeForm.controls.chargeTimeType.value === 5) &&
chargeForm.controls.chargeCalculationType.value === 2) ||
(chargeForm.controls.chargeAppliesTo.value === 4 &&
(chargeForm.controls.chargeTimeType.value === 14 || chargeForm.controls.chargeTimeType.value === 15) &&
chargeForm.controls.chargeCalculationType.value === 2)
"
>
<mat-label>{{ 'labels.inputs.Minimum Charge Cap' | translate }}</mat-label>
<input matInput autofocus formControlName="minCap" mifosxValidateOnFocus />
<mat-error *ngIf="chargeForm.controls.minCap.hasError('maxValue')">
{{ 'errors.validation.msg.loanproduct.minimumGap.not.greater.than.specified.number' | translate }} ({{
chargeForm.controls.maxCap.value
}})
</mat-error>
</mat-form-field>
<mat-form-field
class="flex-48"
*ngIf="
(chargeForm.controls.chargeAppliesTo.value === 1 &&
(chargeForm.controls.chargeCalculationType.value === 2 ||
chargeForm.controls.chargeCalculationType.value === 3 ||
chargeForm.controls.chargeCalculationType.value === 4 ||
chargeForm.controls.chargeCalculationType.value === 5)) ||
(chargeForm.controls.chargeAppliesTo.value === 2 &&
(chargeForm.controls.chargeTimeType.value === 16 || chargeForm.controls.chargeTimeType.value === 5) &&
chargeForm.controls.chargeCalculationType.value === 2) ||
(chargeForm.controls.chargeAppliesTo.value === 4 &&
(chargeForm.controls.chargeTimeType.value === 14 || chargeForm.controls.chargeTimeType.value === 15) &&
chargeForm.controls.chargeCalculationType.value === 2)
"
>
<mat-label>{{ 'labels.inputs.Maximum Charge Cap' | translate }}</mat-label>
<input matInput autofocus formControlName="maxCap" mifosxValidateOnFocus />
* minCap and maxCap only allowed for loan ,shares and savings entitites
* In Loan case: Only for the "charge calculation type" set as "%amount", "% loan amount+interest", "%interest",and "%disbursement amount".
* In saving case: Only for 1. charge time type is "withdrawlfee" or "savings no activity fee" with charge calculation type as "% amount"
* In shares case: Only for charge time type: SHARE_PURCHASE and SHARE_REDEEM and with charge calculation type as % amount only
-->
@if (
(chargeForm.controls.chargeAppliesTo.value === 1 &&
(chargeForm.controls.chargeCalculationType.value === 2 ||
chargeForm.controls.chargeCalculationType.value === 3 ||
chargeForm.controls.chargeCalculationType.value === 4 ||
chargeForm.controls.chargeCalculationType.value === 5)) ||
(chargeForm.controls.chargeAppliesTo.value === 2 &&
(chargeForm.controls.chargeTimeType.value === 16 || chargeForm.controls.chargeTimeType.value === 5) &&
chargeForm.controls.chargeCalculationType.value === 2) ||
(chargeForm.controls.chargeAppliesTo.value === 4 &&
(chargeForm.controls.chargeTimeType.value === 14 || chargeForm.controls.chargeTimeType.value === 15) &&
chargeForm.controls.chargeCalculationType.value === 2)
) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Minimum Charge Cap' | translate }}</mat-label>
<input matInput autofocus formControlName="minCap" mifosxValidateOnFocus />
@if (chargeForm.controls.minCap.hasError('maxValue')) {
<mat-error>
{{ 'errors.validation.msg.loanproduct.minimumGap.not.greater.than.specified.number' | translate }} ({{
chargeForm.controls.maxCap.value
}})
</mat-error>
}
</mat-form-field>
}
@if (
(chargeForm.controls.chargeAppliesTo.value === 1 &&
(chargeForm.controls.chargeCalculationType.value === 2 ||
chargeForm.controls.chargeCalculationType.value === 3 ||
chargeForm.controls.chargeCalculationType.value === 4 ||
chargeForm.controls.chargeCalculationType.value === 5)) ||
(chargeForm.controls.chargeAppliesTo.value === 2 &&
(chargeForm.controls.chargeTimeType.value === 16 || chargeForm.controls.chargeTimeType.value === 5) &&
chargeForm.controls.chargeCalculationType.value === 2) ||
(chargeForm.controls.chargeAppliesTo.value === 4 &&
(chargeForm.controls.chargeTimeType.value === 14 || chargeForm.controls.chargeTimeType.value === 15) &&
chargeForm.controls.chargeCalculationType.value === 2)
) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Maximum Charge Cap' | translate }}</mat-label>
<input matInput autofocus formControlName="maxCap" mifosxValidateOnFocus />
@if (chargeForm.controls.maxCap.hasError('minValue')) {
<mat-error>
{{ 'errors.validation.msg.loanproduct.maximumGap.not.greater.than.specified.number' | translate }} ({{
chargeForm.controls.minCap.value
}})
</mat-error>
}
</mat-form-field>
}
<mat-error *ngIf="chargeForm.controls.maxCap.hasError('minValue')">
{{ 'errors.validation.msg.loanproduct.maximumGap.not.greater.than.specified.number' | translate }} ({{
chargeForm.controls.minCap.value
}})
</mat-error>
</mat-form-field>
<mifosx-gl-account-selector
class="flex-48"
*ngIf="showGLAccount"
[inputFormControl]="chargeForm.controls.incomeAccountId"
[glAccountList]="chargeData.incomeOrLiabilityAccountOptions.incomeAccountOptions"
[required]="true"
[inputLabel]="'Income from Charge'"
>
</mifosx-gl-account-selector>
@if (showGLAccount) {
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="chargeForm.controls.incomeAccountId"
[glAccountList]="chargeData.incomeOrLiabilityAccountOptions.incomeAccountOptions"
[required]="true"
[inputLabel]="'Income from Charge'"
>
</mifosx-gl-account-selector>
}
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Tax Group' | translate }}</mat-label>
<mat-select *ngIf="chargeData.taxGroup" formControlName="taxGroupId">
<mat-option *ngFor="let taxGroup of chargeData.taxGroupOptions" [value]="taxGroup.id">
{{ taxGroup.name }}
</mat-option>
</mat-select>
@if (chargeData.taxGroup) {
<mat-select formControlName="taxGroupId">
@for (taxGroup of chargeData.taxGroupOptions; track taxGroup) {
<mat-option [value]="taxGroup.id">
{{ taxGroup.name }}
</mat-option>
}
</mat-select>
}
<mat-select *ngIf="!chargeData.taxGroup" formControlName="taxGroupId">
<mat-option *ngFor="let taxGroup of chargeData.taxGroupOptions" [value]="taxGroup.id">
{{ taxGroup.name }}
</mat-option>
</mat-select>
@if (!chargeData.taxGroup) {
<mat-select formControlName="taxGroupId">
@for (taxGroup of chargeData.taxGroupOptions; track taxGroup) {
<mat-option [value]="taxGroup.id">
{{ taxGroup.name }}
</mat-option>
}
</mat-select>
}
</mat-form-field>
<div class="password-never-expires-wrapper checkbox flex-48" *ngIf="addFeeFrequency">
<mat-checkbox
labelPosition="before"
[checked]="addFeeFrequency && showFeeOptions"
(change)="getFeeFrequency($event.checked)"
>
{{ 'labels.inputs.Add Fee Frequency' | translate }}
</mat-checkbox>
</div>
@if (addFeeFrequency) {
<div class="password-never-expires-wrapper checkbox flex-48">
<mat-checkbox
labelPosition="before"
[checked]="addFeeFrequency && showFeeOptions"
(change)="getFeeFrequency($event.checked)"
>
{{ 'labels.inputs.Add Fee Frequency' | translate }}
</mat-checkbox>
</div>
}
<mat-form-field class="flex-48" *ngIf="addFeeFrequency && showFeeOptions">
<mat-label>{{ 'labels.inputs.Frequency Interval' | translate }}</mat-label>
<input matInput required autofocus type="text" formControlName="feeInterval" />
<mat-error *ngIf="chargeForm.controls.feeInterval.hasError('required')">
{{ 'labels.inputs.Frequency Interval' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
@if (addFeeFrequency && showFeeOptions) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Frequency Interval' | translate }}</mat-label>
<input matInput required autofocus type="text" formControlName="feeInterval" />
@if (chargeForm.controls.feeInterval.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Frequency Interval' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
}
<mat-form-field class="flex-48" *ngIf="addFeeFrequency && showFeeOptions">
<mat-label>{{ 'labels.inputs.Charge Frequency' | translate }}</mat-label>
<mat-select required formControlName="feeFrequency">
<mat-option *ngFor="let chargeFrequency of chargeData.feeFrequencyOptions" [value]="chargeFrequency.id">
{{ chargeFrequency.value | translateKey: 'catalogs' }}
</mat-option>
</mat-select>
<mat-error *ngIf="chargeForm.controls.feeFrequency.hasError('required')">
{{ 'labels.inputs.Add Fee Frequency' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
@if (addFeeFrequency && showFeeOptions) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Charge Frequency' | translate }}</mat-label>
<mat-select required formControlName="feeFrequency">
@for (chargeFrequency of chargeData.feeFrequencyOptions; track chargeFrequency) {
<mat-option [value]="chargeFrequency.id">
{{ chargeFrequency.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
@if (chargeForm.controls.feeFrequency.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Add Fee Frequency' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
}
</div>
<div class="layout-row-wrap gap-2percent layout-lt-md-column form-section">
@@ -210,11 +250,13 @@
</mat-checkbox>
</div>
<div class="send-password-to-email-wrapper flex-48" *ngIf="showPenalty">
<mat-checkbox labelPosition="before" formControlName="penalty">
{{ 'labels.commons.Is' | translate }} {{ 'labels.inputs.Penalty' | translate }}
</mat-checkbox>
</div>
@if (showPenalty) {
<div class="send-password-to-email-wrapper flex-48">
<mat-checkbox labelPosition="before" formControlName="penalty">
{{ 'labels.commons.Is' | translate }} {{ 'labels.inputs.Penalty' | translate }}
</mat-checkbox>
</div>
}
</div>
</mat-card-content>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
@@ -28,6 +28,12 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class EditChargeComponent implements OnInit {
private productsService = inject(ProductsService);
private formBuilder = inject(UntypedFormBuilder);
private route = inject(ActivatedRoute);
private router = inject(Router);
private settingsService = inject(SettingsService);
/** Selected Data. */
chargeData: any;
/** Charge form. */
@@ -63,13 +69,7 @@ export class EditChargeComponent implements OnInit {
* @param {Router} router Router for navigation.
* @param {SettingsService} settingsService Settings Service
*/
constructor(
private productsService: ProductsService,
private formBuilder: UntypedFormBuilder,
private route: ActivatedRoute,
private router: Router,
private settingsService: SettingsService
) {
constructor() {
this.route.data.subscribe((data: { chargesTemplate: any }) => {
this.chargeData = data.chargesTemplate;
});
@@ -53,21 +53,29 @@
{{ chargeData.amount }}
</div>
<div class="flex-50 mat-body-strong" *ngIf="minCap">
{{ 'labels.inputs.Minimum Charge Cap' | translate }}
</div>
@if (minCap) {
<div class="flex-50 mat-body-strong">
{{ 'labels.inputs.Minimum Charge Cap' | translate }}
</div>
}
<div class="flex-50" *ngIf="minCap">
{{ chargeData.minCap }}
</div>
@if (minCap) {
<div class="flex-50">
{{ chargeData.minCap }}
</div>
}
<div class="flex-50 mat-body-strong" *ngIf="maxCap">
{{ 'labels.inputs.Maximum Charge Cap' | translate }}
</div>
@if (maxCap) {
<div class="flex-50 mat-body-strong">
{{ 'labels.inputs.Maximum Charge Cap' | translate }}
</div>
}
<div class="flex-50" *ngIf="maxCap">
{{ chargeData.maxCap }}
</div>
@if (maxCap) {
<div class="flex-50">
{{ chargeData.maxCap }}
</div>
}
<div class="flex-50 mat-body-strong">
{{ 'labels.inputs.Charge Time Type' | translate }}
@@ -101,41 +109,51 @@
{{ chargeData.active === true | yesNo }}
</div>
<div class="flex-50 mat-body-strong" *ngIf="chargeData.chargeTimeType.id === 9 && chargeData.feeFrequency">
{{ 'labels.inputs.Add Fee Frequency' | translate }}
</div>
@if (chargeData.chargeTimeType.id === 9 && chargeData.feeFrequency) {
<div class="flex-50 mat-body-strong">
{{ 'labels.inputs.Add Fee Frequency' | translate }}
</div>
}
<div
class="flex-50"
*ngIf="chargeData.chargeTimeType.id === 9 && chargeData.feeFrequency && chargeData.feeFrequency"
>
{{ chargeData.feeFrequency.value | translateKey: 'catalogs' }}
</div>
@if (chargeData.chargeTimeType.id === 9 && chargeData.feeFrequency && chargeData.feeFrequency) {
<div class="flex-50">
{{ chargeData.feeFrequency.value | translateKey: 'catalogs' }}
</div>
}
<div class="flex-50 mat-body-strong" *ngIf="chargeData.chargeTimeType.id === 9 && chargeData.feeInterval">
{{ 'labels.inputs.Frequency Interval' | translate }}
</div>
@if (chargeData.chargeTimeType.id === 9 && chargeData.feeInterval) {
<div class="flex-50 mat-body-strong">
{{ 'labels.inputs.Frequency Interval' | translate }}
</div>
}
<div class="flex-50" *ngIf="chargeData.chargeTimeType.id === 9 && chargeData.feeInterval">
{{ chargeData.feeInterval }}
</div>
@if (chargeData.chargeTimeType.id === 9 && chargeData.feeInterval) {
<div class="flex-50">
{{ chargeData.feeInterval }}
</div>
}
<mifosx-gl-account-display
class="flex-100"
[accountTitle]="'Income From Charges'"
*ngIf="chargeData.incomeOrLiabilityAccount"
[glAccount]="chargeData.incomeOrLiabilityAccount"
[withTitle]="'50%'"
>
</mifosx-gl-account-display>
@if (chargeData.incomeOrLiabilityAccount) {
<mifosx-gl-account-display
class="flex-100"
[accountTitle]="'Income From Charges'"
[glAccount]="chargeData.incomeOrLiabilityAccount"
[withTitle]="'50%'"
>
</mifosx-gl-account-display>
}
<div class="flex-50 mat-body-strong" *ngIf="chargeData.taxGroup">
{{ 'labels.inputs.Tax Group' | translate }}
</div>
@if (chargeData.taxGroup) {
<div class="flex-50 mat-body-strong">
{{ 'labels.inputs.Tax Group' | translate }}
</div>
}
<div class="flex-50" *ngIf="chargeData.taxGroup">
{{ chargeData.taxGroup.name }}
</div>
@if (chargeData.taxGroup) {
<div class="flex-50">
{{ chargeData.taxGroup.name }}
</div>
}
</div>
<div class="layout-row layout-align-center gap-2percent column-on-mobile">
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
@@ -29,6 +29,12 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class ViewChargeComponent {
private productsService = inject(ProductsService);
private route = inject(ActivatedRoute);
private router = inject(Router);
private dialog = inject(MatDialog);
private translateService = inject(TranslateService);
/** Charge data. */
chargeData: any;
/** Boolean for MinCap and MaxCap */
@@ -42,13 +48,7 @@ export class ViewChargeComponent {
* @param {MatDialog} dialog Dialog reference.
* @param {TranslateService} translateService Translate Service.
*/
constructor(
private productsService: ProductsService,
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private translateService: TranslateService
) {
constructor() {
this.route.data.subscribe((data: { charge: any }) => {
this.chargeData = data.charge;
if (this.chargeData.minCap) {
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
import { ActivatedRouteSnapshot } from '@angular/router';
/** rxjs Imports */
@@ -13,10 +13,7 @@ import { ProductsService } from '../products.service';
*/
@Injectable()
export class CollateralResolver {
/**
* @param {ProductsService} productsService Products service.
*/
constructor(private productsService: ProductsService) {}
private productsService = inject(ProductsService);
/**
* Returns the products data.
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
/** rxjs Imports */
import { Observable } from 'rxjs';
@@ -12,10 +12,7 @@ import { ProductsService } from '../products.service';
*/
@Injectable()
export class CollateralTemplateResolver {
/**
* @param {ProductsService} productsService products Service
*/
constructor(private productsService: ProductsService) {}
private productsService = inject(ProductsService);
/**
* Returns the product Data.
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, ViewChild, OnInit } from '@angular/core';
import { Component, ViewChild, OnInit, inject } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort, MatSortHeader } from '@angular/material/sort';
import {
@@ -42,6 +42,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class CollateralsComponent implements OnInit {
private route = inject(ActivatedRoute);
/** Collateral Data */
collateralData: any;
/** Columns to be displayed in the Collaterals Table */
@@ -64,7 +66,7 @@ export class CollateralsComponent implements OnInit {
* Retrieves the Collaterals data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
*/
constructor(private route: ActivatedRoute) {
constructor() {
this.route.data.subscribe((data: { collaterals: any }) => {
this.collateralData = data.collaterals;
});
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
/** rxjs Imports */
@@ -13,10 +13,7 @@ import { ProductsService } from '../products.service';
*/
@Injectable()
export class CollateralsResolver {
/**
* @param {ProductsService} productsService Products service
*/
constructor(private productsService: ProductsService) {}
private productsService = inject(ProductsService);
/**
* Returns the All Collaterals Data
@@ -6,54 +6,68 @@
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Name' | translate }}</mat-label>
<input matInput required formControlName="name" />
<mat-error *ngIf="collateralForm.controls.name.hasError('required')">
{{ 'labels.inputs.Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (collateralForm.controls.name.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Type/Quality' | translate }}</mat-label>
<input matInput required formControlName="quality" />
<mat-error *ngIf="collateralForm.controls.quality.hasError('required')">
{{ 'labels.inputs.Type/Quality' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (collateralForm.controls.quality.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Type/Quality' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Unit Type' | translate }}</mat-label>
<input matInput required formControlName="unitType" />
<mat-error *ngIf="collateralForm.controls.unitType.hasError('required')">
{{ 'labels.inputs.Unit Type' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (collateralForm.controls.unitType.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Unit Type' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Base Price' | translate }}</mat-label>
<input matInput required formControlName="basePrice" />
<mat-error *ngIf="collateralForm.controls.basePrice.hasError('required')">
{{ 'labels.inputs.Base Price' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (collateralForm.controls.basePrice.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Base Price' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Percentage to Base' | translate }}</mat-label>
<input matInput required formControlName="pctToBase" />
<mat-error *ngIf="collateralForm.controls.pctToBase.hasError('required')">
{{ 'labels.inputs.Percentage to Base' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (collateralForm.controls.pctToBase.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Percentage to Base' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.heading.Currency' | translate }}</mat-label>
<mat-select required formControlName="currency">
<mat-option *ngFor="let currency of collateralTemplateData" [value]="currency.code">
{{ currency.name }}
</mat-option>
@for (currency of collateralTemplateData; track currency) {
<mat-option [value]="currency.code">
{{ currency.name }}
</mat-option>
}
</mat-select>
<mat-error *ngIf="collateralForm.controls.currency.hasError('required')">
{{ 'labels.heading.Currency' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (collateralForm.controls.currency.hasError('required')) {
<mat-error>
{{ 'labels.heading.Currency' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
</div>
</mat-card-content>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import { OrganizationService } from 'app/organization/organization.service';
import { UntypedFormGroup, UntypedFormBuilder, FormControl, Validators, ReactiveFormsModule } from '@angular/forms';
import { Router, ActivatedRoute, RouterLink } from '@angular/router';
@@ -22,6 +22,13 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class CreateCollateralComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
private productsService = inject(ProductsService);
private route = inject(ActivatedRoute);
private router = inject(Router);
private settingsService = inject(SettingsService);
private organizationService = inject(OrganizationService);
/** Collateral form */
collateralForm: UntypedFormGroup;
/** Charges Template data */
@@ -35,14 +42,7 @@ export class CreateCollateralComponent implements OnInit {
* @param {Router} router Router for navigation.
* @param {SettingsService} settingsService Settings Service
*/
constructor(
private formBuilder: UntypedFormBuilder,
private productsService: ProductsService,
private route: ActivatedRoute,
private router: Router,
private settingsService: SettingsService,
private organizationService: OrganizationService
) {
constructor() {
this.route.data.subscribe((data: { collateralTemplate: any }) => {
this.organizationService.getCurrencies().subscribe((orgCurrencies: any) => {
let orgCurrencyList = Array.isArray(orgCurrencies.selectedCurrencyOptions)
@@ -6,59 +6,73 @@
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Name' | translate }}</mat-label>
<input matInput required autoFocus formControlName="name" />
<mat-error *ngIf="collateralForm.controls.name.hasError('required')">
{{ 'labels.inputs.Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (collateralForm.controls.name.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Type/Quality' | translate }}</mat-label>
<input matInput required autoFocus formControlName="quality" />
<mat-error *ngIf="collateralForm.controls.quality.hasError('required')">
{{ 'labels.inputs.Type/Quality' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (collateralForm.controls.quality.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Type/Quality' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Unit Type' | translate }}</mat-label>
<input matInput required autoFocus formControlName="unitType" />
<mat-error *ngIf="collateralForm.controls.unitType.hasError('required')">
{{ 'labels.inputs.Unit Type' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (collateralForm.controls.unitType.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Unit Type' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Base Price' | translate }}</mat-label>
<input matInput required autoFocus formControlName="basePrice" />
<mat-error *ngIf="collateralForm.controls.basePrice.hasError('required')">
{{ 'labels.inputs.Base Price' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (collateralForm.controls.basePrice.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Base Price' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Percentage to Base' | translate }}</mat-label>
<input matInput required autoFocus formControlName="pctToBase" />
<mat-error *ngIf="collateralForm.controls.pctToBase.hasError('required')">
{{ 'labels.inputs.Percentage to Base' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (collateralForm.controls.pctToBase.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Percentage to Base' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.heading.Currency' | translate }}</mat-label>
<mat-select required formControlName="currency">
<mat-option *ngFor="let currency of collateralTemplateData" [value]="currency.code">
{{ currency.name }}
</mat-option>
@for (currency of collateralTemplateData; track currency) {
<mat-option [value]="currency.code">
{{ currency.name }}
</mat-option>
}
</mat-select>
<mat-error *ngIf="collateralForm.controls.currency.hasError('required')">
{{ 'labels.heading.Currency' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (collateralForm.controls.currency.hasError('required')) {
<mat-error>
{{ 'labels.heading.Currency' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
</div>
</mat-card-content>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
@@ -17,6 +17,12 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class EditCollateralComponent implements OnInit {
private productsService = inject(ProductsService);
private formBuilder = inject(UntypedFormBuilder);
private route = inject(ActivatedRoute);
private router = inject(Router);
private settingsService = inject(SettingsService);
/** Colalteral Data */
collateralData: any;
/** Collateral Template */
@@ -32,13 +38,7 @@ export class EditCollateralComponent implements OnInit {
* @param {Router} router Router for navigation.
* @param {SettingsService} settingsService Settings Service.
*/
constructor(
private productsService: ProductsService,
private formBuilder: UntypedFormBuilder,
private route: ActivatedRoute,
private router: Router,
private settingsService: SettingsService
) {
constructor() {
this.route.data.subscribe((data: { collateral: any; collateralTemplate: any }) => {
this.collateralData = data.collateral;
this.collateralTemplateData = data.collateralTemplate;
@@ -98,7 +98,6 @@ describe('ViewCollateralComponent - Integration Tests', () => {
},
provideNativeDateAdapter(),
provideAnimationsAsync()
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
@@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
@@ -24,6 +24,12 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class ViewCollateralComponent {
private productsService = inject(ProductsService);
private route = inject(ActivatedRoute);
private router = inject(Router);
private dialog = inject(MatDialog);
private translateService = inject(TranslateService);
/** Collateral Data */
collateralData: any;
@@ -35,13 +41,7 @@ export class ViewCollateralComponent {
* @param {MatDialog} dialog Dialog reference.
* @param {TranslateService} translateService Translate Service.
*/
constructor(
private productsService: ProductsService,
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private translateService: TranslateService
) {
constructor() {
this.route.data.subscribe((data: { collateral: any }) => {
this.collateralData = data.collateral;
});
@@ -4,9 +4,11 @@
<mat-form-field>
<mat-label>{{ 'labels.inputs.Attribute' | translate }}</mat-label>
<mat-select formControlName="attributeName" required>
<mat-option *ngFor="let attributeName of attributeNameData" [value]="attributeName.id">
{{ attributeName.value }}
</mat-option>
@for (attributeName of attributeNameData; track attributeName) {
<mat-option [value]="attributeName.id">
{{ attributeName.value }}
</mat-option>
}
</mat-select>
<mat-error>
{{ 'labels.inputs.Attribute' | translate }} {{ 'labels.commons.is' | translate }}
@@ -17,9 +19,11 @@
<mat-form-field>
<mat-label>{{ 'labels.inputs.Condition' | translate }}</mat-label>
<mat-select formControlName="conditionType" required>
<mat-option *ngFor="let conditionType of conditionTypeData" [value]="conditionType.id">
{{ conditionType.value }}
</mat-option>
@for (conditionType of conditionTypeData; track conditionType) {
<mat-option [value]="conditionType.id">
{{ conditionType.value }}
</mat-option>
}
</mat-select>
<mat-error>
{{ 'labels.inputs.Condition' | translate }} {{ 'labels.commons.is' | translate }}
@@ -27,32 +31,36 @@
</mat-error>
</mat-form-field>
<mat-form-field *ngIf="depositProductIncentiveForm.value.attributeName">
<mat-label>{{ 'labels.inputs.Value' | translate }}</mat-label>
<mat-select formControlName="attributeValue" *ngIf="depositProductIncentiveForm.value.attributeName !== 3" required>
<mat-option *ngFor="let attributeValue of attributeValueData" [value]="attributeValue.id">
{{ attributeValue.name }}
</mat-option>
</mat-select>
<input
type="number"
matInput
formControlName="attributeValue"
*ngIf="depositProductIncentiveForm.value.attributeName === 3"
required
/>
<mat-error>
{{ 'labels.inputs.Value' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
@if (depositProductIncentiveForm.value.attributeName) {
<mat-form-field>
<mat-label>{{ 'labels.inputs.Value' | translate }}</mat-label>
@if (depositProductIncentiveForm.value.attributeName !== 3) {
<mat-select formControlName="attributeValue" required>
@for (attributeValue of attributeValueData; track attributeValue) {
<mat-option [value]="attributeValue.id">
{{ attributeValue.name }}
</mat-option>
}
</mat-select>
}
@if (depositProductIncentiveForm.value.attributeName === 3) {
<input type="number" matInput formControlName="attributeValue" required />
}
<mat-error>
{{ 'labels.inputs.Value' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
}
<mat-form-field>
<mat-label>{{ 'labels.inputs.Type' | translate }}</mat-label>
<mat-select formControlName="incentiveType" required>
<mat-option *ngFor="let incentiveType of incentiveTypeData" [value]="incentiveType.id">
{{ incentiveType.value }}
</mat-option>
@for (incentiveType of incentiveTypeData; track incentiveType) {
<mat-option [value]="incentiveType.id">
{{ incentiveType.value }}
</mat-option>
}
</mat-select>
<mat-error>
{{ 'labels.inputs.Type' | translate }} {{ 'labels.commons.is' | translate }}
@@ -1,4 +1,4 @@
import { Component, OnInit, Inject } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import {
MatDialogRef,
MAT_DIALOG_DATA,
@@ -26,6 +26,11 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class DepositProductIncentiveFormDialogComponent implements OnInit {
dialogRef = inject<MatDialogRef<DepositProductIncentiveFormDialogComponent>>(MatDialogRef);
data = inject(MAT_DIALOG_DATA);
private formBuilder = inject(UntypedFormBuilder);
private translateService = inject(TranslateService);
layout: {
addButtonText?: string;
} = {
@@ -42,12 +47,9 @@ export class DepositProductIncentiveFormDialogComponent implements OnInit {
attributeValueData: any;
incentiveTypeData: any;
constructor(
public dialogRef: MatDialogRef<DepositProductIncentiveFormDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any,
private formBuilder: UntypedFormBuilder,
private translateService: TranslateService
) {
constructor() {
const data = this.data;
this.createDepositProductIncentiveForm();
this.setConditionalControls();
this.layout = { ...this.layout, ...data.layout };
@@ -85,17 +85,18 @@
</mifosx-fixed-deposit-product-accounting-step>
</mat-step>
<mat-step state="preview" *ngIf="fixedDepositProductFormValid" completed>
<ng-template matStepLabel>{{ 'labels.inputs.PREVIEW' | translate }}</ng-template>
<mifosx-fixed-deposit-product-preview-step
[fixedDepositProductsTemplate]="fixedDepositProductsTemplate"
[chartSlabsDisplayedColumns]="fixedDepositProductInterestRateChartStep.chartSlabsDisplayedColumns"
[accountingRuleData]="accountingRuleData"
[fixedDepositProduct]="fixedDepositProduct"
(submitEvent)="submit()"
>
</mifosx-fixed-deposit-product-preview-step>
</mat-step>
@if (fixedDepositProductFormValid) {
<mat-step state="preview" completed>
<ng-template matStepLabel>{{ 'labels.inputs.PREVIEW' | translate }}</ng-template>
<mifosx-fixed-deposit-product-preview-step
[fixedDepositProductsTemplate]="fixedDepositProductsTemplate"
[chartSlabsDisplayedColumns]="fixedDepositProductInterestRateChartStep.chartSlabsDisplayedColumns"
[accountingRuleData]="accountingRuleData"
[fixedDepositProduct]="fixedDepositProduct"
(submitEvent)="submit()"
>
</mifosx-fixed-deposit-product-preview-step>
</mat-step>
}
</mat-stepper>
</div>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, ViewChild } from '@angular/core';
import { Component, ViewChild, inject } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
/** Custom Components */
@@ -42,6 +42,12 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class CreateFixedDepositProductComponent {
private route = inject(ActivatedRoute);
private productsService = inject(ProductsService);
private router = inject(Router);
private settingsService = inject(SettingsService);
private accounting = inject(Accounting);
@ViewChild(FixedDepositProductDetailsStepComponent, { static: true })
fixedDepositProductDetailsStep: FixedDepositProductDetailsStepComponent;
@ViewChild(FixedDepositProductCurrencyStepComponent, { static: true })
@@ -67,13 +73,7 @@ export class CreateFixedDepositProductComponent {
* @param {SettingsService} settingsService Settings Service.
*/
constructor(
private route: ActivatedRoute,
private productsService: ProductsService,
private router: Router,
private settingsService: SettingsService,
private accounting: Accounting
) {
constructor() {
this.route.data.subscribe((data: { fixedDepositProductsTemplate: any }) => {
this.fixedDepositProductsTemplate = data.fixedDepositProductsTemplate;
});
@@ -84,17 +84,18 @@
</mifosx-fixed-deposit-product-accounting-step>
</mat-step>
<mat-step state="preview" *ngIf="fixedDepositProductFormValidAndNotPrinstine" completed>
<ng-template matStepLabel>{{ 'labels.inputs.PREVIEW' | translate }}</ng-template>
<mifosx-fixed-deposit-product-preview-step
[fixedDepositProductsTemplate]="fixedDepositProductsTemplate"
[chartSlabsDisplayedColumns]="fixedDepositProductInterestRateChartStep.chartSlabsDisplayedColumns"
[accountingRuleData]="accountingRuleData"
[fixedDepositProduct]="fixedDepositProduct"
(submitEvent)="submit()"
>
</mifosx-fixed-deposit-product-preview-step>
</mat-step>
@if (fixedDepositProductFormValidAndNotPrinstine) {
<mat-step state="preview" completed>
<ng-template matStepLabel>{{ 'labels.inputs.PREVIEW' | translate }}</ng-template>
<mifosx-fixed-deposit-product-preview-step
[fixedDepositProductsTemplate]="fixedDepositProductsTemplate"
[chartSlabsDisplayedColumns]="fixedDepositProductInterestRateChartStep.chartSlabsDisplayedColumns"
[accountingRuleData]="accountingRuleData"
[fixedDepositProduct]="fixedDepositProduct"
(submitEvent)="submit()"
>
</mifosx-fixed-deposit-product-preview-step>
</mat-step>
}
</mat-stepper>
</div>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, ViewChild } from '@angular/core';
import { Component, ViewChild, inject } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
/** Custom Components */
@@ -42,6 +42,12 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class EditFixedDepositProductComponent {
private route = inject(ActivatedRoute);
private productsService = inject(ProductsService);
private router = inject(Router);
private settingsService = inject(SettingsService);
private accounting = inject(Accounting);
@ViewChild(FixedDepositProductDetailsStepComponent, { static: true })
fixedDepositProductDetailsStep: FixedDepositProductDetailsStepComponent;
@ViewChild(FixedDepositProductCurrencyStepComponent, { static: true })
@@ -67,13 +73,7 @@ export class EditFixedDepositProductComponent {
* @param {SettingsService} settingsService Settings Service
*/
constructor(
private route: ActivatedRoute,
private productsService: ProductsService,
private router: Router,
private settingsService: SettingsService,
private accounting: Accounting
) {
constructor() {
this.route.data.subscribe((data: { fixedDepositProductAndTemplate: any }) => {
this.fixedDepositProductsTemplate = data.fixedDepositProductAndTemplate;
});
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
import { ActivatedRouteSnapshot } from '@angular/router';
/** rxjs Imports */
@@ -13,10 +13,7 @@ import { ProductsService } from '../../products.service';
*/
@Injectable()
export class FixedDepositProductAndTemplateResolver {
/**
* @param {ProductsService} productsService Products service.
*/
constructor(private productsService: ProductsService) {}
private productsService = inject(ProductsService);
/**
* Returns the Fixed Deposits Product and Template.
@@ -4,291 +4,265 @@
class="flex-98 layout-row gap-5percent layout-lt-md-column radio-group-spacing"
formControlName="accountingRule"
>
<mat-radio-button *ngFor="let accountingRule of accountingRuleData; let i = index" [value]="i + 1">
{{ 'labels.accounting.' + accountingRule | translate }}
</mat-radio-button>
@for (accountingRule of accountingRuleData; track accountingRule; let i = $index) {
<mat-radio-button [value]="i + 1">
{{ 'labels.accounting.' + accountingRule | translate }}
</mat-radio-button>
}
</mat-radio-group>
<mat-divider class="flex-98"></mat-divider>
<div *ngIf="isCashOrAccrualAccounting()" class="flex-fill layout-row-wrap gap-2percent layout-xs-column">
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Assets' | translate }}</h4>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="fixedDepositProductAccountingForm.controls.savingsReferenceAccountId"
[glAccountList]="assetAccountData"
[required]="true"
[inputLabel]="'Saving reference'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
*ngIf="isAccrualAccounting()"
[inputFormControl]="fixedDepositProductAccountingForm.controls.feesReceivableAccountId"
[glAccountList]="assetAccountData"
[required]="true"
[inputLabel]="'Fees Receivable'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
*ngIf="isAccrualAccounting()"
[inputFormControl]="fixedDepositProductAccountingForm.controls.penaltiesReceivableAccountId"
[glAccountList]="assetAccountData"
[required]="true"
[inputLabel]="'Penalties Receivable'"
>
</mifosx-gl-account-selector>
<mat-divider class="flex-98"></mat-divider>
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Liabilities' | translate }}</h4>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="fixedDepositProductAccountingForm.controls.savingsControlAccountId"
[glAccountList]="liabilityAccountData"
[required]="true"
[inputLabel]="'Saving control'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="fixedDepositProductAccountingForm.controls.transfersInSuspenseAccountId"
[glAccountList]="liabilityAccountData"
[required]="true"
[inputLabel]="'Savings transfers in suspense'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
*ngIf="isAccrualAccounting()"
[inputFormControl]="fixedDepositProductAccountingForm.controls.interestPayableAccountId"
[glAccountList]="liabilityAccountData"
[required]="true"
[inputLabel]="'Interest Payable'"
>
</mifosx-gl-account-selector>
<mat-divider class="flex-98"></mat-divider>
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Expenses' | translate }}</h4>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="fixedDepositProductAccountingForm.controls.interestOnSavingsAccountId"
[glAccountList]="expenseAccountData"
[required]="true"
[inputLabel]="'Interest on savings'"
>
</mifosx-gl-account-selector>
<mat-divider class="flex-98"></mat-divider>
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Income' | translate }}</h4>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="fixedDepositProductAccountingForm.controls.incomeFromFeeAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from fees'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="fixedDepositProductAccountingForm.controls.incomeFromPenaltyAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from penalties'"
>
</mifosx-gl-account-selector>
<mat-divider class="flex-98"></mat-divider>
<h3 class="mat-h3 flex-23">{{ 'labels.heading.Advanced Accounting Rules' | translate }}</h3>
<mat-checkbox class="flex-73" formControlName="advancedAccountingRules"></mat-checkbox>
<div
*ngIf="fixedDepositProductAccountingForm.value.advancedAccountingRules"
class="flex-fill layout-row-wrap gap-2percent responsive-column"
>
<div class="flex-100 layout-row-wrap gap-2percent layout-lt-md-column">
<h4 class="mat-h4 flex-63">
{{ 'labels.heading.Configure Fund Sources for Payment Channels' | translate }}
</h4>
<div class="flex-33">
<button
type="button"
mat-raised-button
color="primary"
(click)="add('PaymentFundSource', paymentChannelToFundSourceMappings)"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
<table
class="flex-98 mat-elevation-z1"
mat-table
[dataSource]="paymentChannelToFundSourceMappings.value"
*ngIf="paymentChannelToFundSourceMappings.value.length !== 0"
@if (isCashOrAccrualAccounting()) {
<div class="flex-fill layout-row-wrap gap-2percent layout-xs-column">
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Assets' | translate }}</h4>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="fixedDepositProductAccountingForm.controls.savingsReferenceAccountId"
[glAccountList]="assetAccountData"
[required]="true"
[inputLabel]="'Saving reference'"
>
</mifosx-gl-account-selector>
@if (isAccrualAccounting()) {
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="fixedDepositProductAccountingForm.controls.feesReceivableAccountId"
[glAccountList]="assetAccountData"
[required]="true"
[inputLabel]="'Fees Receivable'"
>
<ng-container matColumnDef="paymentTypeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.heading.Payment Type' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.paymentTypeId | find: paymentTypeData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="fundSourceAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Fund Source' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.fundSourceAccountId | find: assetAccountData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.buttons.Actions' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource; let i = index">
</mifosx-gl-account-selector>
}
@if (isAccrualAccounting()) {
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="fixedDepositProductAccountingForm.controls.penaltiesReceivableAccountId"
[glAccountList]="assetAccountData"
[required]="true"
[inputLabel]="'Penalties Receivable'"
>
</mifosx-gl-account-selector>
}
<mat-divider class="flex-98"></mat-divider>
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Liabilities' | translate }}</h4>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="fixedDepositProductAccountingForm.controls.savingsControlAccountId"
[glAccountList]="liabilityAccountData"
[required]="true"
[inputLabel]="'Saving control'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="fixedDepositProductAccountingForm.controls.transfersInSuspenseAccountId"
[glAccountList]="liabilityAccountData"
[required]="true"
[inputLabel]="'Savings transfers in suspense'"
>
</mifosx-gl-account-selector>
@if (isAccrualAccounting()) {
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="fixedDepositProductAccountingForm.controls.interestPayableAccountId"
[glAccountList]="liabilityAccountData"
[required]="true"
[inputLabel]="'Interest Payable'"
>
</mifosx-gl-account-selector>
}
<mat-divider class="flex-98"></mat-divider>
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Expenses' | translate }}</h4>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="fixedDepositProductAccountingForm.controls.interestOnSavingsAccountId"
[glAccountList]="expenseAccountData"
[required]="true"
[inputLabel]="'Interest on savings'"
>
</mifosx-gl-account-selector>
<mat-divider class="flex-98"></mat-divider>
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Income' | translate }}</h4>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="fixedDepositProductAccountingForm.controls.incomeFromFeeAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from fees'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="fixedDepositProductAccountingForm.controls.incomeFromPenaltyAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from penalties'"
>
</mifosx-gl-account-selector>
<mat-divider class="flex-98"></mat-divider>
<h3 class="mat-h3 flex-23">{{ 'labels.heading.Advanced Accounting Rules' | translate }}</h3>
<mat-checkbox class="flex-73" formControlName="advancedAccountingRules"></mat-checkbox>
@if (fixedDepositProductAccountingForm.value.advancedAccountingRules) {
<div class="flex-fill layout-row-wrap gap-2percent responsive-column">
<div class="flex-100 layout-row-wrap gap-2percent layout-lt-md-column">
<h4 class="mat-h4 flex-63">
{{ 'labels.heading.Configure Fund Sources for Payment Channels' | translate }}
</h4>
<div class="flex-33">
<button
mat-icon-button
type="button"
mat-raised-button
color="primary"
(click)="edit('PaymentFundSource', paymentChannelToFundSourceMappings, i)"
(click)="add('PaymentFundSource', paymentChannelToFundSourceMappings)"
>
<fa-icon icon="edit"></fa-icon>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
<button mat-icon-button color="warn" (click)="delete(paymentChannelToFundSourceMappings, i)">
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="paymentFundSourceDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: paymentFundSourceDisplayedColumns"></tr>
</table>
</div>
<div class="flex-100" *ngIf="existCharges()">
<h4 class="mat-h4 flex-63">{{ 'labels.heading.Map Fees to Specific Income Accounts' | translate }}</h4>
<div class="flex-33">
<button
type="button"
mat-raised-button
color="primary"
(click)="add('FeesIncome', feeToIncomeAccountMappings)"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
<table
class="flex-98 mat-elevation-z1"
mat-table
[dataSource]="feeToIncomeAccountMappings.value"
*ngIf="feeToIncomeAccountMappings.value.length !== 0"
>
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.catalogs.Fees' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.chargeId | find: chargeData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.incomeAccountId | find: incomeAccountData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.buttons.Actions' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome; let i = index">
<button mat-icon-button color="primary" (click)="edit('FeesIncome', feeToIncomeAccountMappings, i)">
<fa-icon icon="edit"></fa-icon>
</button>
<button mat-icon-button color="warn" (click)="delete(feeToIncomeAccountMappings, i)">
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
</table>
</div>
<div class="flex-100" *ngIf="existCharges()">
<h4 class="mat-h4 flex-63">
{{ 'labels.catalogs.Penalties' | translate }}
{{ 'labels.heading.Map Penalties to Specific Income Accounts' | translate }}
</h4>
<div class="flex-33">
<button
type="button"
mat-raised-button
color="primary"
(click)="add('PenaltyIncome', penaltyToIncomeAccountMappings)"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
<table
class="flex-98 mat-elevation-z1"
mat-table
[dataSource]="penaltyToIncomeAccountMappings.value"
*ngIf="penaltyToIncomeAccountMappings.value.length !== 0"
>
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Penalty' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.chargeId | find: penaltyData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.incomeAccountId | find: incomeAccountData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.buttons.Actions' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome; let i = index">
<button
mat-icon-button
color="primary"
(click)="edit('PenaltyIncome', penaltyToIncomeAccountMappings, i)"
</div>
@if (paymentChannelToFundSourceMappings.value.length !== 0) {
<table
class="flex-98 mat-elevation-z1"
mat-table
[dataSource]="paymentChannelToFundSourceMappings.value"
>
<fa-icon icon="edit"></fa-icon>
</button>
<button mat-icon-button color="warn" (click)="delete(penaltyToIncomeAccountMappings, i)">
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
</table>
</div>
<ng-container matColumnDef="paymentTypeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.heading.Payment Type' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.paymentTypeId | find: paymentTypeData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="fundSourceAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Fund Source' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.fundSourceAccountId | find: assetAccountData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.buttons.Actions' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource; let i = index">
<button
mat-icon-button
color="primary"
(click)="edit('PaymentFundSource', paymentChannelToFundSourceMappings, i)"
>
<fa-icon icon="edit"></fa-icon>
</button>
<button mat-icon-button color="warn" (click)="delete(paymentChannelToFundSourceMappings, i)">
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="paymentFundSourceDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: paymentFundSourceDisplayedColumns"></tr>
</table>
}
</div>
@if (existCharges()) {
<div class="flex-100">
<h4 class="mat-h4 flex-63">{{ 'labels.heading.Map Fees to Specific Income Accounts' | translate }}</h4>
<div class="flex-33">
<button
type="button"
mat-raised-button
color="primary"
(click)="add('FeesIncome', feeToIncomeAccountMappings)"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
@if (feeToIncomeAccountMappings.value.length !== 0) {
<table class="flex-98 mat-elevation-z1" mat-table [dataSource]="feeToIncomeAccountMappings.value">
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.catalogs.Fees' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.chargeId | find: chargeData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.incomeAccountId | find: incomeAccountData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.buttons.Actions' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome; let i = index">
<button
mat-icon-button
color="primary"
(click)="edit('FeesIncome', feeToIncomeAccountMappings, i)"
>
<fa-icon icon="edit"></fa-icon>
</button>
<button mat-icon-button color="warn" (click)="delete(feeToIncomeAccountMappings, i)">
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
</table>
}
</div>
}
@if (existCharges()) {
<div class="flex-100">
<h4 class="mat-h4 flex-63">
{{ 'labels.catalogs.Penalties' | translate }}
{{ 'labels.heading.Map Penalties to Specific Income Accounts' | translate }}
</h4>
<div class="flex-33">
<button
type="button"
mat-raised-button
color="primary"
(click)="add('PenaltyIncome', penaltyToIncomeAccountMappings)"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
@if (penaltyToIncomeAccountMappings.value.length !== 0) {
<table class="flex-98 mat-elevation-z1" mat-table [dataSource]="penaltyToIncomeAccountMappings.value">
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Penalty' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.chargeId | find: penaltyData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.incomeAccountId | find: incomeAccountData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.buttons.Actions' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome; let i = index">
<button
mat-icon-button
color="primary"
(click)="edit('PenaltyIncome', penaltyToIncomeAccountMappings, i)"
>
<fa-icon icon="edit"></fa-icon>
</button>
<button mat-icon-button color="warn" (click)="delete(penaltyToIncomeAccountMappings, i)">
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
</table>
}
</div>
}
</div>
}
</div>
</div>
}
</div>
<div class="layout-row align-center gap-2percent margin-t responsive-column">
@@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnInit, inject } from '@angular/core';
import {
UntypedFormArray,
UntypedFormBuilder,
@@ -67,6 +67,11 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class FixedDepositProductAccountingStepComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
dialog = inject(MatDialog);
private accounting = inject(Accounting);
private translateService = inject(TranslateService);
@Input() fixedDepositProductsTemplate: any;
@Input() accountingRuleData: any;
@Input() fixedDepositProductFormValid: boolean;
@@ -92,12 +97,7 @@ export class FixedDepositProductAccountingStepComponent implements OnInit {
'actions'
];
constructor(
private formBuilder: UntypedFormBuilder,
public dialog: MatDialog,
private accounting: Accounting,
private translateService: TranslateService
) {
constructor() {
this.createfixedDepositProductAccountingForm();
this.setConditionalControls();
}
@@ -383,7 +383,6 @@ export class FixedDepositProductAccountingStepComponent implements OnInit {
required: true,
order: 2
})
];
return formfields;
}
@@ -406,7 +405,6 @@ export class FixedDepositProductAccountingStepComponent implements OnInit {
required: true,
order: 2
})
];
return formfields;
}
@@ -429,7 +427,6 @@ export class FixedDepositProductAccountingStepComponent implements OnInit {
required: true,
order: 2
})
];
return formfields;
}
@@ -2,12 +2,11 @@
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Charge' | translate }}</mat-label>
<mat-select #charge>
<mat-option
*ngFor="let charge of chargeData | chargesFilter: chargesDataSource : currencyCode.value"
[value]="charge"
>
{{ charge.name }}
</mat-option>
@for (charge of chargeData | chargesFilter: chargesDataSource : currencyCode.value; track charge) {
<mat-option [value]="charge">
{{ charge.name }}
</mat-option>
}
</mat-select>
</mat-form-field>
@@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnInit, inject } from '@angular/core';
import { UntypedFormControl } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
@@ -48,6 +48,9 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class FixedDepositProductChargesStepComponent implements OnInit {
dialog = inject(MatDialog);
private translateService = inject(TranslateService);
@Input() fixedDepositProductsTemplate: any;
@Input() currencyCode: UntypedFormControl;
@@ -62,11 +65,6 @@ export class FixedDepositProductChargesStepComponent implements OnInit {
'action'
];
constructor(
public dialog: MatDialog,
private translateService: TranslateService
) {}
ngOnInit() {
this.chargeData = this.fixedDepositProductsTemplate.chargeOptions;
if (!(this.fixedDepositProductsTemplate === undefined) && this.fixedDepositProductsTemplate.id) {
@@ -3,9 +3,11 @@
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Currency' | translate }}</mat-label>
<mat-select formControlName="currencyCode" required>
<mat-option *ngFor="let currency of currencyData" [value]="currency.code">
{{ currency.name }}
</mat-option>
@for (currency of currencyData; track currency) {
<mat-option [value]="currency.code">
{{ currency.name }}
</mat-option>
}
</mat-select>
<mat-error>
{{ 'labels.inputs.Currency' | translate }} {{ 'labels.commons.is' | translate }}
@@ -1,4 +1,4 @@
import { Component, OnInit, Input } from '@angular/core';
import { Component, OnInit, Input, inject } from '@angular/core';
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
@@ -16,13 +16,15 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class FixedDepositProductCurrencyStepComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
@Input() fixedDepositProductsTemplate: any;
fixedDepositProductCurrencyForm: UntypedFormGroup;
currencyData: any;
constructor(private formBuilder: UntypedFormBuilder) {
constructor() {
this.createFixedDepositProductCurrencyForm();
}
@@ -3,28 +3,34 @@
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Product Name' | translate }}</mat-label>
<input matInput formControlName="name" required />
<mat-error *ngIf="fixedDepositProductDetailsForm.controls.name.hasError('required')">
{{ 'labels.inputs.Product Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (fixedDepositProductDetailsForm.controls.name.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Product Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Short Name' | translate }}</mat-label>
<input matInput formControlName="shortName" maxlength="4" required />
<mat-error *ngIf="fixedDepositProductDetailsForm.controls.shortName.hasError('required')">
{{ 'labels.inputs.Short Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (fixedDepositProductDetailsForm.controls.shortName.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Short Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-98">
<mat-label>{{ 'labels.inputs.Description' | translate }}</mat-label>
<textarea matInput formControlName="description" required></textarea>
<mat-error *ngIf="fixedDepositProductDetailsForm.controls.description.hasError('required')">
{{ 'labels.inputs.Description' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (fixedDepositProductDetailsForm.controls.description.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Description' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
</div>
@@ -1,4 +1,4 @@
import { Component, OnInit, Input } from '@angular/core';
import { Component, OnInit, Input, inject } from '@angular/core';
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
@@ -16,11 +16,13 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class FixedDepositProductDetailsStepComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
@Input() fixedDepositProductsTemplate: any;
fixedDepositProductDetailsForm: UntypedFormGroup;
constructor(private formBuilder: UntypedFormBuilder) {
constructor() {
this.createFixedDepositProductDetailsForm();
}
@@ -12,276 +12,275 @@
</button>
</div>
<div
class="flex-fill layout-row-wrap responsive-column"
formArrayName="charts"
*ngFor="let chart of charts.controls; let chartIndex = index"
>
<mat-divider class="flex-98"></mat-divider>
<div class="flex-fill layout-row-wrap responsive-column" [formGroupName]="chartIndex">
<div class="flex-100" align="end">
<button
type="button"
mat-icon-button
color="warn"
(click)="delete(charts, chartIndex)"
matTooltip="{{ 'tooltips.Delete Interest Rate Chart' | translate }}"
matTooltipPosition="left"
>
<fa-icon icon="trash"></fa-icon>
</button>
</div>
<mat-form-field class="flex-28 m-r-5">
<mat-label>{{ 'labels.inputs.Name' | translate }}</mat-label>
<input matInput formControlName="name" required />
<mat-error *ngIf="chart.get('name')?.touched && chart.get('name')?.hasError('required')">
{{ 'labels.inputs.Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="flex-70">
<mat-label>{{ 'labels.inputs.Description' | translate }}</mat-label>
<textarea matInput formControlName="description" required></textarea>
<mat-error *ngIf="chart.get('description')?.touched && chart.get('description')?.hasError('required')">
{{ 'labels.inputs.Description' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="flex-48 m-r-5" (click)="validFromDatePicker.open()">
<mat-label>{{ 'labels.inputs.From Date' | translate }}</mat-label>
<input
matInput
[min]="minDate"
[max]="maxDate"
[matDatepicker]="validFromDatePicker"
formControlName="fromDate"
required
/>
<mat-datepicker-toggle matSuffix [for]="validFromDatePicker"></mat-datepicker-toggle>
<mat-datepicker #validFromDatePicker></mat-datepicker>
<mat-error>
{{ 'labels.inputs.Valid from Date' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="flex-48 m-r-5" (click)="endDatePicker.open()">
<mat-label>{{ 'labels.inputs.End Date' | translate }}</mat-label>
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="endDatePicker" formControlName="endDate" />
<mat-datepicker-toggle matSuffix [for]="endDatePicker"></mat-datepicker-toggle>
<mat-datepicker #endDatePicker></mat-datepicker>
</mat-form-field>
<div class="flex-100 layout-row align-between align-items-center">
<mat-checkbox labelPosition="before" formControlName="isPrimaryGroupingByAmount">
{{ 'labels.inputs.Is primary grouping by amount?' | translate }}
</mat-checkbox>
</div>
<div class="center flex-100">
<button type="button" mat-raised-button color="primary" (click)="addChartSlab(chart.controls.chartSlabs)">
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add Slab' | translate }}
</button>
</div>
<div class="flex-100" *ngIf="chart.value.chartSlabs.length === 0">
<h3 class="mat-h3">{{ 'labels.heading.It is required to add at least one Slab' | translate }}</h3>
</div>
<table
class="flex-98 mat-elevation-z1"
mat-table
[dataSource]="chart.value.chartSlabs"
*ngIf="chart.value.chartSlabs.length !== 0"
multiTemplateDataRows
>
<ng-container matColumnDef="period">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Period' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
{{
chartSlab.fromPeriod +
' - ' +
chartSlab.toPeriod +
' ' +
(chartSlab.periodType | find: periodTypeData : 'id' : 'value')
}}
</td>
</ng-container>
<ng-container matColumnDef="amountRange">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount Range' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
{{ chartSlab.amountRangeFrom + ' - ' + chartSlab.amountRangeTo }}
</td>
</ng-container>
<ng-container matColumnDef="annualInterestRate">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Interest' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">{{ chartSlab.annualInterestRate }} %</td>
</ng-container>
<ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Description' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
{{ chartSlab.description }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab; let chartSlabIndex = dataIndex">
<button
mat-icon-button
color="primary"
(click)="editChartSlab(chart.controls.chartSlabs, chartSlabIndex)"
>
<fa-icon icon="edit"></fa-icon>
</button>
<button mat-icon-button color="warn" (click)="delete(chart.controls.chartSlabs, chartSlabIndex)">
<fa-icon icon="trash"></fa-icon>
</button>
<button
mat-button
color="primary"
(click)="
expandChartSlabIndex[chartIndex] =
expandChartSlabIndex[chartIndex] === chartSlabIndex ? null : chartSlabIndex
"
>
<span *ngIf="expandChartSlabIndex[chartIndex] !== chartSlabIndex">
<fa-icon icon="eye" class="m-r-10"></fa-icon>
{{ 'labels.buttons.View Incentives' | translate }}
</span>
<span *ngIf="expandChartSlabIndex[chartIndex] === chartSlabIndex">
<fa-icon icon="eye-slash" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Hide Incentives' | translate }}
</span>
</button>
</td>
</ng-container>
<ng-container matColumnDef="incentives">
<td
mat-cell
*matCellDef="let chartSlab; let chartSlabIndex = dataIndex"
[attr.colspan]="chartSlabsDisplayedColumns[chartIndex].length"
@for (chart of charts.controls; track chart; let chartIndex = $index) {
<div class="flex-fill layout-row-wrap responsive-column" formArrayName="charts">
<mat-divider class="flex-98"></mat-divider>
<div class="flex-fill layout-row-wrap responsive-column" [formGroupName]="chartIndex">
<div class="flex-100" align="end">
<button
type="button"
mat-icon-button
color="warn"
(click)="delete(charts, chartIndex)"
matTooltip="{{ 'tooltips.Delete Interest Rate Chart' | translate }}"
matTooltipPosition="left"
>
<div
class="layout-row-wrap flex-fill incentives"
[@expandChartSlab]="chartSlabIndex === expandChartSlabIndex[chartIndex] ? 'expanded' : 'collapsed'"
>
<mat-card class="layout-row-wrap flex-fill">
<h4 class="mat-h4 flex-63">
{{ 'labels.heading.Incentives' | translate }}
</h4>
<div class="flex-13">
<button
mat-raised-button
color="primary"
(click)="addIncentive(getIncentives(chart.controls.chartSlabs, chartSlabIndex))"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
<table
class="mat-elevation-z1 flex-fill"
mat-table
[dataSource]="chartSlab.incentives"
*ngIf="chartSlab.incentives.length"
<fa-icon icon="trash"></fa-icon>
</button>
</div>
<mat-form-field class="flex-28 m-r-5">
<mat-label>{{ 'labels.inputs.Name' | translate }}</mat-label>
<input matInput formControlName="name" required />
@if (chart.get('name')?.touched && chart.get('name')?.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-70">
<mat-label>{{ 'labels.inputs.Description' | translate }}</mat-label>
<textarea matInput formControlName="description" required></textarea>
@if (chart.get('description')?.touched && chart.get('description')?.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Description' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field class="flex-48 m-r-5" (click)="validFromDatePicker.open()">
<mat-label>{{ 'labels.inputs.From Date' | translate }}</mat-label>
<input
matInput
[min]="minDate"
[max]="maxDate"
[matDatepicker]="validFromDatePicker"
formControlName="fromDate"
required
/>
<mat-datepicker-toggle matSuffix [for]="validFromDatePicker"></mat-datepicker-toggle>
<mat-datepicker #validFromDatePicker></mat-datepicker>
<mat-error>
{{ 'labels.inputs.Valid from Date' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="flex-48 m-r-5" (click)="endDatePicker.open()">
<mat-label>{{ 'labels.inputs.End Date' | translate }}</mat-label>
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="endDatePicker" formControlName="endDate" />
<mat-datepicker-toggle matSuffix [for]="endDatePicker"></mat-datepicker-toggle>
<mat-datepicker #endDatePicker></mat-datepicker>
</mat-form-field>
<div class="flex-100 layout-row align-between align-items-center">
<mat-checkbox labelPosition="before" formControlName="isPrimaryGroupingByAmount">
{{ 'labels.inputs.Is primary grouping by amount?' | translate }}
</mat-checkbox>
</div>
<div class="center flex-100">
<button type="button" mat-raised-button color="primary" (click)="addChartSlab(chart.controls.chartSlabs)">
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add Slab' | translate }}
</button>
</div>
@if (chart.value.chartSlabs.length === 0) {
<div class="flex-100">
<h3 class="mat-h3">{{ 'labels.heading.It is required to add at least one Slab' | translate }}</h3>
</div>
}
@if (chart.value.chartSlabs.length !== 0) {
<table
class="flex-98 mat-elevation-z1"
mat-table
[dataSource]="chart.value.chartSlabs"
multiTemplateDataRows
>
<ng-container matColumnDef="period">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Period' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
{{
chartSlab.fromPeriod +
' - ' +
chartSlab.toPeriod +
' ' +
(chartSlab.periodType | find: periodTypeData : 'id' : 'value')
}}
</td>
</ng-container>
<ng-container matColumnDef="amountRange">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount Range' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
{{ chartSlab.amountRangeFrom + ' - ' + chartSlab.amountRangeTo }}
</td>
</ng-container>
<ng-container matColumnDef="annualInterestRate">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Interest' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">{{ chartSlab.annualInterestRate }} %</td>
</ng-container>
<ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Description' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
{{ chartSlab.description }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab; let chartSlabIndex = dataIndex">
<button
mat-icon-button
color="primary"
(click)="editChartSlab(chart.controls.chartSlabs, chartSlabIndex)"
>
<ng-container matColumnDef="entityType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Entity Type' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{ incentive.entityType | find: entityTypeData : 'id' : 'value' }}
</td>
</ng-container>
<ng-container matColumnDef="attributeName">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Attribute Name' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{ incentive.attributeName | find: attributeNameData : 'id' : 'value' }}
</td>
</ng-container>
<ng-container matColumnDef="conditionType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Condition Type' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{ incentive.conditionType | find: conditionTypeData : 'id' : 'value' }}
</td>
</ng-container>
<ng-container matColumnDef="attributeValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Attribute Value' | translate }}</th>
<td mat-cell *matCellDef="let incentive" [ngSwitch]="incentive.attributeName">
<span *ngSwitchCase="2">{{ incentive.attributeValue | find: genderData : 'id' : 'name' }}</span>
<span *ngSwitchCase="3">{{ incentive.attributeValue }}</span>
<span *ngSwitchCase="4">{{
incentive.attributeValue | find: clientTypeData : 'id' : 'name'
}}</span>
<span *ngSwitchCase="5">{{
incentive.attributeValue | find: clientClassificationData : 'id' : 'name'
}}</span>
</td>
</ng-container>
<ng-container matColumnDef="incentiveType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Incentive Type' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{ incentive.incentiveType | find: incentiveTypeData : 'id' : 'value' }}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Interest' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{ incentive.amount }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let incentive; let incentiveIndex = index">
<fa-icon icon="edit"></fa-icon>
</button>
<button mat-icon-button color="warn" (click)="delete(chart.controls.chartSlabs, chartSlabIndex)">
<fa-icon icon="trash"></fa-icon>
</button>
<button
mat-button
color="primary"
(click)="
expandChartSlabIndex[chartIndex] =
expandChartSlabIndex[chartIndex] === chartSlabIndex ? null : chartSlabIndex
"
>
@if (expandChartSlabIndex[chartIndex] !== chartSlabIndex) {
<span>
<fa-icon icon="eye" class="m-r-10"></fa-icon>
{{ 'labels.buttons.View Incentives' | translate }}
</span>
}
@if (expandChartSlabIndex[chartIndex] === chartSlabIndex) {
<span>
<fa-icon icon="eye-slash" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Hide Incentives' | translate }}
</span>
}
</button>
</td>
</ng-container>
<ng-container matColumnDef="incentives">
<td
mat-cell
*matCellDef="let chartSlab; let chartSlabIndex = dataIndex"
[attr.colspan]="chartSlabsDisplayedColumns[chartIndex].length"
>
<div
class="layout-row-wrap flex-fill incentives"
[@expandChartSlab]="chartSlabIndex === expandChartSlabIndex[chartIndex] ? 'expanded' : 'collapsed'"
>
<mat-card class="layout-row-wrap flex-fill">
<h4 class="mat-h4 flex-63">
{{ 'labels.heading.Incentives' | translate }}
</h4>
<div class="flex-13">
<button
mat-icon-button
mat-raised-button
color="primary"
(click)="
editIncentive(getIncentives(chart.controls.chartSlabs, chartSlabIndex), incentiveIndex)
"
(click)="addIncentive(getIncentives(chart.controls.chartSlabs, chartSlabIndex))"
>
<fa-icon icon="edit"></fa-icon>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
<button
mat-icon-button
color="warn"
(click)="delete(getIncentives(chart.controls.chartSlabs, chartSlabIndex), incentiveIndex)"
>
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="incentivesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: incentivesDisplayedColumns"></tr>
</table>
</mat-card>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chartSlabsDisplayedColumns[chartIndex]"></tr>
<tr mat-row *matRowDef="let row; columns: chartSlabsDisplayedColumns[chartIndex]"></tr>
<tr mat-row *matRowDef="let row; columns: chartSlabsIncentivesDisplayedColumns" class="incentives-row"></tr>
</table>
</div>
@if (chartSlab.incentives.length) {
<table class="mat-elevation-z1 flex-fill" mat-table [dataSource]="chartSlab.incentives">
<ng-container matColumnDef="entityType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Entity Type' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{ incentive.entityType | find: entityTypeData : 'id' : 'value' }}
</td>
</ng-container>
<ng-container matColumnDef="attributeName">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Attribute Name' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{ incentive.attributeName | find: attributeNameData : 'id' : 'value' }}
</td>
</ng-container>
<ng-container matColumnDef="conditionType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Condition Type' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{ incentive.conditionType | find: conditionTypeData : 'id' : 'value' }}
</td>
</ng-container>
<ng-container matColumnDef="attributeValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Attribute Value' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
@switch (incentive.attributeName) {
@case (2) {
<span>{{ incentive.attributeValue | find: genderData : 'id' : 'name' }}</span>
}
@case (3) {
<span>{{ incentive.attributeValue }}</span>
}
@case (4) {
<span>{{ incentive.attributeValue | find: clientTypeData : 'id' : 'name' }}</span>
}
@case (5) {
<span>{{
incentive.attributeValue | find: clientClassificationData : 'id' : 'name'
}}</span>
}
}
</td>
</ng-container>
<ng-container matColumnDef="incentiveType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Incentive Type' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{ incentive.incentiveType | find: incentiveTypeData : 'id' : 'value' }}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Interest' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{ incentive.amount }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let incentive; let incentiveIndex = index">
<button
mat-icon-button
color="primary"
(click)="
editIncentive(
getIncentives(chart.controls.chartSlabs, chartSlabIndex),
incentiveIndex
)
"
>
<fa-icon icon="edit"></fa-icon>
</button>
<button
mat-icon-button
color="warn"
(click)="
delete(getIncentives(chart.controls.chartSlabs, chartSlabIndex), incentiveIndex)
"
>
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="incentivesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: incentivesDisplayedColumns"></tr>
</table>
}
</mat-card>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chartSlabsDisplayedColumns[chartIndex]"></tr>
<tr mat-row *matRowDef="let row; columns: chartSlabsDisplayedColumns[chartIndex]"></tr>
<tr
mat-row
*matRowDef="let row; columns: chartSlabsIncentivesDisplayedColumns"
class="incentives-row"
></tr>
</table>
}
</div>
</div>
</div>
}
</div>
<div class="layout-row align-center gap-2percent margin-t responsive-column">
@@ -1,6 +1,6 @@
/** Angular Imports */
import { animate, state, style, transition, trigger } from '@angular/animations';
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnInit, inject } from '@angular/core';
import {
UntypedFormArray,
UntypedFormBuilder,
@@ -27,7 +27,7 @@ import { SettingsService } from 'app/settings/settings.service';
import { MatTooltip } from '@angular/material/tooltip';
import { MatButton, MatIconButton } from '@angular/material/button';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { NgFor, NgIf, NgSwitch, NgSwitchCase } from '@angular/common';
import { MatDivider } from '@angular/material/divider';
import { MatCheckbox } from '@angular/material/checkbox';
import {
@@ -54,8 +54,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
trigger('expandChartSlab', [
state('collapsed', style({ height: '0px', minHeight: '0' })),
state('expanded', style({ height: '*' })),
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)'))])
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)'))
])
],
imports: [
...STANDALONE_SHARED_IMPORTS,
@@ -70,8 +70,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
MatHeaderCell,
MatCellDef,
MatCell,
NgSwitch,
NgSwitchCase,
MatHeaderRowDef,
MatHeaderRow,
MatRowDef,
@@ -82,6 +80,12 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class FixedDepositProductInterestRateChartStepComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
dialog = inject(MatDialog);
private dateUtils = inject(Dates);
private settingsService = inject(SettingsService);
private translateService = inject(TranslateService);
@Input() fixedDepositProductsTemplate: any;
fixedDepositProductInterestRateChartForm: UntypedFormGroup;
@@ -121,13 +125,7 @@ export class FixedDepositProductInterestRateChartStepComponent implements OnInit
* @param {SettingsService} settingsService Settings Service.
*/
constructor(
private formBuilder: UntypedFormBuilder,
public dialog: MatDialog,
private dateUtils: Dates,
private settingsService: SettingsService,
private translateService: TranslateService
) {
constructor() {
this.createFixedDepositProductInterestRateChartForm();
}
@@ -497,7 +495,6 @@ export class FixedDepositProductInterestRateChartStepComponent implements OnInit
required: true,
order: 7
})
];
return formfields;
}
@@ -10,10 +10,12 @@
<span class="flex-60">{{ fixedDepositProduct.shortName }}</span>
</div>
<div class="layout-row flex-100" *ngIf="fixedDepositProduct.description">
<span class="flex-40">{{ 'labels.inputs.Description' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProduct.description }}</span>
</div>
@if (fixedDepositProduct.description) {
<div class="layout-row flex-100">
<span class="flex-40">{{ 'labels.inputs.Description' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProduct.description }}</span>
</div>
}
<h3 class="mat-h3 flex-100">{{ 'labels.inputs.Currency' | translate }}</h3>
@@ -89,15 +91,17 @@
<h3 class="mat-h3 flex-100">{{ 'labels.heading.Settings' | translate }}</h3>
<mat-divider class="flex-100"></mat-divider>
<div class="layout-row flex-100" *ngIf="fixedDepositProduct.lockinPeriodFrequency">
<span class="flex-40">{{ 'labels.inputs.Lock-in Period' | translate }}:</span>
<span class="flex-60">{{
fixedDepositProduct.lockinPeriodFrequency +
' ' +
(fixedDepositProduct.lockinPeriodFrequencyType
| find: fixedDepositProductsTemplate.lockinPeriodFrequencyTypeOptions : 'id' : 'value')
}}</span>
</div>
@if (fixedDepositProduct.lockinPeriodFrequency) {
<div class="layout-row flex-100">
<span class="flex-40">{{ 'labels.inputs.Lock-in Period' | translate }}:</span>
<span class="flex-60">{{
fixedDepositProduct.lockinPeriodFrequency +
' ' +
(fixedDepositProduct.lockinPeriodFrequencyType
| find: fixedDepositProductsTemplate.lockinPeriodFrequencyTypeOptions : 'id' : 'value')
}}</span>
</div>
}
<div class="layout-row flex-100">
<span class="flex-40">{{ 'labels.inputs.Minimum Deposit Term' | translate }}:</span>
@@ -109,407 +113,405 @@
}}</span>
</div>
<div class="layout-row flex-100" *ngIf="fixedDepositProduct.inMultiplesOfDepositTerm">
<span class="flex-40">{{ 'labels.inputs.And thereafter, in Multiples of' | translate }}:</span>
<span class="flex-60">{{
fixedDepositProduct.inMultiplesOfDepositTerm +
' ' +
(fixedDepositProduct.inMultiplesOfDepositTermTypeId
| find: fixedDepositProductsTemplate.periodFrequencyTypeOptions : 'id' : 'value')
}}</span>
</div>
@if (fixedDepositProduct.inMultiplesOfDepositTerm) {
<div class="layout-row flex-100">
<span class="flex-40">{{ 'labels.inputs.And thereafter, in Multiples of' | translate }}:</span>
<span class="flex-60">{{
fixedDepositProduct.inMultiplesOfDepositTerm +
' ' +
(fixedDepositProduct.inMultiplesOfDepositTermTypeId
| find: fixedDepositProductsTemplate.periodFrequencyTypeOptions : 'id' : 'value')
}}</span>
</div>
}
<div class="layout-row flex-100" *ngIf="fixedDepositProduct.maxDepositTerm">
<span class="flex-40">{{ 'labels.inputs.Maximum Deposit Term' | translate }}:</span>
<span class="flex-60">{{
fixedDepositProduct.maxDepositTerm +
' ' +
(fixedDepositProduct.maxDepositTermTypeId
| find: fixedDepositProductsTemplate.periodFrequencyTypeOptions : 'id' : 'value')
}}</span>
</div>
@if (fixedDepositProduct.maxDepositTerm) {
<div class="layout-row flex-100">
<span class="flex-40">{{ 'labels.inputs.Maximum Deposit Term' | translate }}:</span>
<span class="flex-60">{{
fixedDepositProduct.maxDepositTerm +
' ' +
(fixedDepositProduct.maxDepositTermTypeId
| find: fixedDepositProductsTemplate.periodFrequencyTypeOptions : 'id' : 'value')
}}</span>
</div>
}
<!-- For Pre-mature closure -->
<div class="layout-row flex-100">
<span class="flex-40">{{ 'labels.inputs.Apply Penal Interest (less)' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProduct.preClosurePenalApplicable | yesNo }}</span>
</div>
<div class="layout-row flex-100" *ngIf="fixedDepositProduct.preClosurePenalApplicable">
<span class="flex-40">{{ 'labels.inputs.Penal Interest' | translate }} (%):</span>
<span class="flex-60">{{
fixedDepositProduct.preClosurePenalInterest +
'% (' +
(fixedDepositProduct.preClosurePenalInterestOnTypeId
| find: fixedDepositProductsTemplate.preClosurePenalInterestOnTypeOptions : 'id' : 'value') +
')'
}}</span>
</div>
@if (fixedDepositProduct.preClosurePenalApplicable) {
<div class="layout-row flex-100">
<span class="flex-40">{{ 'labels.inputs.Penal Interest' | translate }} (%):</span>
<span class="flex-60">{{
fixedDepositProduct.preClosurePenalInterest +
'% (' +
(fixedDepositProduct.preClosurePenalInterestOnTypeId
| find: fixedDepositProductsTemplate.preClosurePenalInterestOnTypeOptions : 'id' : 'value') +
')'
}}</span>
</div>
}
<!-- -->
<div class="layout-row flex-100">
<span class="flex-40">{{ 'labels.inputs.Withhold Tax is Applicable' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProduct.withHoldTax | yesNo }}</span>
</div>
<div class="layout-row flex-100" *ngIf="fixedDepositProduct.withHoldTax">
<span class="flex-40">{{ 'labels.inputs.Tax Group' | translate }}:</span>
<span class="flex-60">{{
fixedDepositProduct.taxGroupId | find: fixedDepositProductsTemplate.taxGroupOptions : 'id' : 'name'
}}</span>
</div>
<div class="layout-row-wrap responsive-column flex-100" *ngIf="fixedDepositProduct.charts.length !== 0">
<h3 class="mat-h3 flex-100">{{ 'labels.heading.Interest Rate Charts' | translate }}</h3>
<mat-divider class="flex-100"></mat-divider>
<div
*ngFor="let chart of fixedDepositProduct.charts; let chartIndex = index"
class="layout-row-wrap responsive-column flex-100"
>
<div class="layout-row flex-100" *ngIf="chart.name">
<span class="flex-40">{{ 'labels.inputs.Name' | translate }}:</span>
<span class="flex-60">{{ chart.name }}</span>
</div>
<div class="layout-row flex-100" *ngIf="chart.description">
<span class="flex-40">{{ 'labels.inputs.Description' | translate }}:</span>
<span class="flex-60">{{ chart.description }}</span>
</div>
<div class="layout-row flex-100">
<span class="flex-40">{{ 'labels.inputs.From Date' | translate }}:</span>
<span class="flex-60">{{ chart.fromDate | dateFormat }}</span>
</div>
<div class="layout-row flex-100" *ngIf="chart.endDate">
<span class="flex-40">{{ 'labels.inputs.End Date' | translate }}:</span>
<span class="flex-60">{{ chart.endDate | dateFormat }}</span>
</div>
<div class="flex-100">
<span class="flex-40">{{ 'labels.inputs.Primary Grouping by Amount' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProduct.isPrimaryGroupingByAmount | yesNo }}</span>
</div>
<table
class="mat-elevation-z1 flex-100"
mat-table
[dataSource]="chart.chartSlabs"
*ngIf="chart.chartSlabs.length !== 0"
multiTemplateDataRows
>
<ng-container matColumnDef="period">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Period' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
{{
chartSlab.fromPeriod +
' - ' +
chartSlab.toPeriod +
' ' +
(chartSlab.periodType | find: fixedDepositProductsTemplate.chartTemplate.periodTypes : 'id' : 'value')
}}
</td>
</ng-container>
<ng-container matColumnDef="amountRange">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount Range' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
{{ chartSlab.amountRangeFrom + ' - ' + chartSlab.amountRangeTo }}
</td>
</ng-container>
<ng-container matColumnDef="annualInterestRate">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Interest' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
{{ chartSlab.annualInterestRate }}
</td>
</ng-container>
<ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Description' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
{{ chartSlab.description }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab; let chartSlabIndex = dataIndex">
<button
mat-button
color="primary"
(click)="
expandChartSlabIndex[chartIndex] =
expandChartSlabIndex[chartIndex] === chartSlabIndex ? null : chartSlabIndex
"
[disabled]="chartSlab.incentives.length === 0"
>
<span *ngIf="expandChartSlabIndex[chartIndex] !== chartSlabIndex">
<fa-icon icon="eye" class="m-r-10"></fa-icon>
{{ 'labels.buttons.View Incentives' | translate }}
</span>
<span *ngIf="expandChartSlabIndex[chartIndex] === chartSlabIndex">
<fa-icon icon="eye-slash" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Hide Incentives' | translate }}
</span>
</button>
</td>
</ng-container>
<ng-container matColumnDef="incentives">
<td
mat-cell
*matCellDef="let chartSlab; let chartSlabIndex = dataIndex"
[attr.colspan]="chartSlabsDisplayedColumns[chartIndex].length"
>
<div
class="layout-row-wrap flex-100 incentives"
[@expandChartSlab]="chartSlabIndex === expandChartSlabIndex[chartIndex] ? 'expanded' : 'collapsed'"
>
<mat-card class="layout-row-wrap flex-100">
<h4 class="mat-h4 flex-23">
{{ 'labels.heading.Incentives' | translate }}
</h4>
<table class="flex-100 mat-elevation-z1" mat-table [dataSource]="chartSlab.incentives">
<ng-container matColumnDef="entityType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Entity Type' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{
incentive.entityType
| find: fixedDepositProductsTemplate.chartTemplate.entityTypeOptions : 'id' : 'value'
}}
</td>
</ng-container>
<ng-container matColumnDef="attributeName">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Attribute Name' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{
incentive.attributeName
| find: fixedDepositProductsTemplate.chartTemplate.attributeNameOptions : 'id' : 'value'
}}
</td>
</ng-container>
<ng-container matColumnDef="conditionType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Condition Type' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{
incentive.conditionType
| find: fixedDepositProductsTemplate.chartTemplate.conditionTypeOptions : 'id' : 'value'
}}
</td>
</ng-container>
<ng-container matColumnDef="attributeValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Attribute Value' | translate }}</th>
<td mat-cell *matCellDef="let incentive" [ngSwitch]="incentive.attributeName">
<span *ngSwitchCase="2">{{
incentive.attributeValue
| find: fixedDepositProductsTemplate.chartTemplate.genderOptions : 'id' : 'name'
}}</span>
<span *ngSwitchCase="3">{{ incentive.attributeValue }}</span>
<span *ngSwitchCase="4">{{
incentive.attributeValue
| find: fixedDepositProductsTemplate.chartTemplate.clientTypeOptions : 'id' : 'name'
}}</span>
<span *ngSwitchCase="5">{{
incentive.attributeValue
| find: fixedDepositProductsTemplate.chartTemplate.clientClassificationOptions : 'id' : 'name'
}}</span>
</td>
</ng-container>
<ng-container matColumnDef="incentiveType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Incentive Type' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{
incentive.incentiveType
| find: fixedDepositProductsTemplate.chartTemplate.incentiveTypeOptions : 'id' : 'value'
}}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{ incentive.amount | formatNumber }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="incentivesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: incentivesDisplayedColumns"></tr>
</table>
</mat-card>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chartSlabsDisplayedColumns[chartIndex]"></tr>
<tr mat-row *matRowDef="let row; columns: chartSlabsDisplayedColumns[chartIndex]"></tr>
<tr mat-row *matRowDef="let row; columns: chartSlabsIncentivesDisplayedColumns" class="incentives-row"></tr>
</table>
<mat-divider class="flex-100"></mat-divider>
@if (fixedDepositProduct.withHoldTax) {
<div class="layout-row flex-100">
<span class="flex-40">{{ 'labels.inputs.Tax Group' | translate }}:</span>
<span class="flex-60">{{
fixedDepositProduct.taxGroupId | find: fixedDepositProductsTemplate.taxGroupOptions : 'id' : 'name'
}}</span>
</div>
</div>
}
<div *ngIf="fixedDepositProduct.charges.length" class="layout-row-wrap responsive-column flex-100">
<h3 class="mat-h3 flex-100">{{ 'labels.heading.Charges' | translate }}</h3>
@if (fixedDepositProduct.charts.length !== 0) {
<div class="layout-row-wrap responsive-column flex-100">
<h3 class="mat-h3 flex-100">{{ 'labels.heading.Interest Rate Charts' | translate }}</h3>
<mat-divider class="flex-100"></mat-divider>
@for (chart of fixedDepositProduct.charts; track chart; let chartIndex = $index) {
<div class="layout-row-wrap responsive-column flex-100">
@if (chart.name) {
<div class="layout-row flex-100">
<span class="flex-40">{{ 'labels.inputs.Name' | translate }}:</span>
<span class="flex-60">{{ chart.name }}</span>
</div>
}
@if (chart.description) {
<div class="layout-row flex-100">
<span class="flex-40">{{ 'labels.inputs.Description' | translate }}:</span>
<span class="flex-60">{{ chart.description }}</span>
</div>
}
<div class="layout-row flex-100">
<span class="flex-40">{{ 'labels.inputs.From Date' | translate }}:</span>
<span class="flex-60">{{ chart.fromDate | dateFormat }}</span>
</div>
@if (chart.endDate) {
<div class="layout-row flex-100">
<span class="flex-40">{{ 'labels.inputs.End Date' | translate }}:</span>
<span class="flex-60">{{ chart.endDate | dateFormat }}</span>
</div>
}
<div class="flex-100">
<span class="flex-40">{{ 'labels.inputs.Primary Grouping by Amount' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProduct.isPrimaryGroupingByAmount | yesNo }}</span>
</div>
@if (chart.chartSlabs.length !== 0) {
<table class="mat-elevation-z1 flex-100" mat-table [dataSource]="chart.chartSlabs" multiTemplateDataRows>
<ng-container matColumnDef="period">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Period' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
{{
chartSlab.fromPeriod +
' - ' +
chartSlab.toPeriod +
' ' +
(chartSlab.periodType
| find: fixedDepositProductsTemplate.chartTemplate.periodTypes : 'id' : 'value')
}}
</td>
</ng-container>
<ng-container matColumnDef="amountRange">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount Range' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
{{ chartSlab.amountRangeFrom + ' - ' + chartSlab.amountRangeTo }}
</td>
</ng-container>
<ng-container matColumnDef="annualInterestRate">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Interest' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
{{ chartSlab.annualInterestRate }}
</td>
</ng-container>
<ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Description' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
{{ chartSlab.description }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab; let chartSlabIndex = dataIndex">
<button
mat-button
color="primary"
(click)="
expandChartSlabIndex[chartIndex] =
expandChartSlabIndex[chartIndex] === chartSlabIndex ? null : chartSlabIndex
"
[disabled]="chartSlab.incentives.length === 0"
>
@if (expandChartSlabIndex[chartIndex] !== chartSlabIndex) {
<span>
<fa-icon icon="eye" class="m-r-10"></fa-icon>
{{ 'labels.buttons.View Incentives' | translate }}
</span>
}
@if (expandChartSlabIndex[chartIndex] === chartSlabIndex) {
<span>
<fa-icon icon="eye-slash" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Hide Incentives' | translate }}
</span>
}
</button>
</td>
</ng-container>
<ng-container matColumnDef="incentives">
<td
mat-cell
*matCellDef="let chartSlab; let chartSlabIndex = dataIndex"
[attr.colspan]="chartSlabsDisplayedColumns[chartIndex].length"
>
<div
class="layout-row-wrap flex-100 incentives"
[@expandChartSlab]="chartSlabIndex === expandChartSlabIndex[chartIndex] ? 'expanded' : 'collapsed'"
>
<mat-card class="layout-row-wrap flex-100">
<h4 class="mat-h4 flex-23">
{{ 'labels.heading.Incentives' | translate }}
</h4>
<table class="flex-100 mat-elevation-z1" mat-table [dataSource]="chartSlab.incentives">
<ng-container matColumnDef="entityType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Entity Type' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{
incentive.entityType
| find: fixedDepositProductsTemplate.chartTemplate.entityTypeOptions : 'id' : 'value'
}}
</td>
</ng-container>
<ng-container matColumnDef="attributeName">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Attribute Name' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{
incentive.attributeName
| find: fixedDepositProductsTemplate.chartTemplate.attributeNameOptions : 'id' : 'value'
}}
</td>
</ng-container>
<ng-container matColumnDef="conditionType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Condition Type' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{
incentive.conditionType
| find: fixedDepositProductsTemplate.chartTemplate.conditionTypeOptions : 'id' : 'value'
}}
</td>
</ng-container>
<ng-container matColumnDef="attributeValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Attribute Value' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
@switch (incentive.attributeName) {
@case (2) {
<span>{{
incentive.attributeValue
| find: fixedDepositProductsTemplate.chartTemplate.genderOptions : 'id' : 'name'
}}</span>
}
@case (3) {
<span>{{ incentive.attributeValue }}</span>
}
@case (4) {
<span>{{
incentive.attributeValue
| find: fixedDepositProductsTemplate.chartTemplate.clientTypeOptions : 'id' : 'name'
}}</span>
}
@case (5) {
<span>{{
incentive.attributeValue
| find
: fixedDepositProductsTemplate.chartTemplate.clientClassificationOptions
: 'id'
: 'name'
}}</span>
}
}
</td>
</ng-container>
<ng-container matColumnDef="incentiveType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Incentive Type' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{
incentive.incentiveType
| find: fixedDepositProductsTemplate.chartTemplate.incentiveTypeOptions : 'id' : 'value'
}}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{ incentive.amount | formatNumber }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="incentivesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: incentivesDisplayedColumns"></tr>
</table>
</mat-card>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chartSlabsDisplayedColumns[chartIndex]"></tr>
<tr mat-row *matRowDef="let row; columns: chartSlabsDisplayedColumns[chartIndex]"></tr>
<tr
mat-row
*matRowDef="let row; columns: chartSlabsIncentivesDisplayedColumns"
class="incentives-row"
></tr>
</table>
}
<mat-divider class="flex-100"></mat-divider>
</div>
}
</div>
}
<mat-divider class="flex-100"></mat-divider>
<table class="flex-100 mat-elevation-z1" mat-table [dataSource]="fixedDepositProduct.charges">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Name' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.name + ', ' + charge.currency.displaySymbol }}
</td>
</ng-container>
<ng-container matColumnDef="chargeCalculationType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Type' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeCalculationType.value }}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.amount }}
</td>
</ng-container>
<ng-container matColumnDef="chargeTimeType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Collected On' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeTimeType.value }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chargesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chargesDisplayedColumns"></tr>
</table>
</div>
@if (fixedDepositProduct.charges.length) {
<div class="layout-row-wrap responsive-column flex-100">
<h3 class="mat-h3 flex-100">{{ 'labels.heading.Charges' | translate }}</h3>
<mat-divider class="flex-100"></mat-divider>
<table class="flex-100 mat-elevation-z1" mat-table [dataSource]="fixedDepositProduct.charges">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Name' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.name + ', ' + charge.currency.displaySymbol }}
</td>
</ng-container>
<ng-container matColumnDef="chargeCalculationType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Type' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeCalculationType.value }}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.amount }}
</td>
</ng-container>
<ng-container matColumnDef="chargeTimeType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Collected On' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeTimeType.value }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chargesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chargesDisplayedColumns"></tr>
</table>
</div>
}
<h3 class="mat-h3 flex-100">{{ 'labels.heading.Accounting' | translate }}</h3>
<mat-divider class="flex-100"></mat-divider>
<mifosx-view-savings-accounting-details
*ngIf="!isNoneAccounting()"
[accountingRule]="accountingRule"
[accountingMappings]="accountingMappings"
>
</mifosx-view-savings-accounting-details>
@if (!isNoneAccounting()) {
<mifosx-view-savings-accounting-details [accountingRule]="accountingRule" [accountingMappings]="accountingMappings">
</mifosx-view-savings-accounting-details>
}
<div
*ngIf="
fixedDepositProduct.advancedAccountingRules &&
(fixedDepositProduct.paymentChannelToFundSourceMappings?.length ||
fixedDepositProduct.feeToIncomeAccountMappings?.length ||
fixedDepositProduct.penaltyToIncomeAccountMappings?.length)
"
class="layout-row-wrap responsive-column flex-100"
>
<h3 class="mat-h3 flex-100">{{ 'labels.heading.Advanced Accounting Rules' | translate }}</h3>
<mat-divider class="flex-100"></mat-divider>
<div
*ngIf="fixedDepositProduct.paymentChannelToFundSourceMappings?.length"
class="flex-100 layout-row-wrap responsive-column"
>
<h4 class="mat-h4 flex-100">{{ 'labels.heading.Fund Sources for Payment Channels' | translate }}</h4>
<table
class="mat-elevation-z1 flex-100"
mat-table
[dataSource]="fixedDepositProduct.paymentChannelToFundSourceMappings"
>
<ng-container matColumnDef="paymentTypeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Payment Type' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource">
{{
paymentFundSource.paymentTypeId | find: fixedDepositProductsTemplate.paymentTypeOptions : 'id' : 'name'
}}
</td>
</ng-container>
<ng-container matColumnDef="fundSourceAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Fund Source' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource">
{{
paymentFundSource.fundSourceAccountId
| find: fixedDepositProductsTemplate.accountingMappingOptions.assetAccountOptions : 'id' : 'name'
}}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="paymentFundSourceDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: paymentFundSourceDisplayedColumns"></tr>
</table>
@if (
fixedDepositProduct.advancedAccountingRules &&
(fixedDepositProduct.paymentChannelToFundSourceMappings?.length ||
fixedDepositProduct.feeToIncomeAccountMappings?.length ||
fixedDepositProduct.penaltyToIncomeAccountMappings?.length)
) {
<div class="layout-row-wrap responsive-column flex-100">
<h3 class="mat-h3 flex-100">{{ 'labels.heading.Advanced Accounting Rules' | translate }}</h3>
<mat-divider class="flex-100"></mat-divider>
@if (fixedDepositProduct.paymentChannelToFundSourceMappings?.length) {
<div class="flex-100 layout-row-wrap responsive-column">
<h4 class="mat-h4 flex-100">{{ 'labels.heading.Fund Sources for Payment Channels' | translate }}</h4>
<table
class="mat-elevation-z1 flex-100"
mat-table
[dataSource]="fixedDepositProduct.paymentChannelToFundSourceMappings"
>
<ng-container matColumnDef="paymentTypeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Payment Type' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource">
{{
paymentFundSource.paymentTypeId
| find: fixedDepositProductsTemplate.paymentTypeOptions : 'id' : 'name'
}}
</td>
</ng-container>
<ng-container matColumnDef="fundSourceAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Fund Source' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource">
{{
paymentFundSource.fundSourceAccountId
| find: fixedDepositProductsTemplate.accountingMappingOptions.assetAccountOptions : 'id' : 'name'
}}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="paymentFundSourceDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: paymentFundSourceDisplayedColumns"></tr>
</table>
</div>
}
@if (fixedDepositProduct.feeToIncomeAccountMappings?.length) {
<div class="flex-100 layout-row-wrap responsive-column">
<h4 class="mat-h4 flex-100">{{ 'labels.heading.Fees to Specific Income Accounts' | translate }}</h4>
<table
class="mat-elevation-z1 flex-100"
mat-table
[dataSource]="fixedDepositProduct.feeToIncomeAccountMappings"
>
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Fees' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.chargeId | find: fixedDepositProductsTemplate.chargeOptions : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome">
{{
feesIncome.incomeAccountId
| find: fixedDepositProductsTemplate.accountingMappingOptions.incomeAccountOptions : 'id' : 'name'
}}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
</table>
</div>
}
@if (fixedDepositProduct.penaltyToIncomeAccountMappings?.length) {
<div class="flex-100 layout-row-wrap responsive-column">
<h4 class="mat-h4 flex-100">{{ 'labels.heading.Penalties to Specific Income Accounts' | translate }}</h4>
<table
class="mat-elevation-z1 flex-100"
mat-table
[dataSource]="fixedDepositProduct.penaltyToIncomeAccountMappings"
>
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Penalty' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.chargeId | find: fixedDepositProductsTemplate.penaltyOptions : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome">
{{
penaltyIncome.incomeAccountId
| find: fixedDepositProductsTemplate.accountingMappingOptions.incomeAccountOptions : 'id' : 'name'
}}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
</table>
</div>
}
</div>
<div
*ngIf="fixedDepositProduct.feeToIncomeAccountMappings?.length"
class="flex-100 layout-row-wrap responsive-column"
>
<h4 class="mat-h4 flex-100">{{ 'labels.heading.Fees to Specific Income Accounts' | translate }}</h4>
<table class="mat-elevation-z1 flex-100" mat-table [dataSource]="fixedDepositProduct.feeToIncomeAccountMappings">
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Fees' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.chargeId | find: fixedDepositProductsTemplate.chargeOptions : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome">
{{
feesIncome.incomeAccountId
| find: fixedDepositProductsTemplate.accountingMappingOptions.incomeAccountOptions : 'id' : 'name'
}}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
</table>
</div>
<div
*ngIf="fixedDepositProduct.penaltyToIncomeAccountMappings?.length"
class="flex-100 layout-row-wrap responsive-column"
>
<h4 class="mat-h4 flex-100">{{ 'labels.heading.Penalties to Specific Income Accounts' | translate }}</h4>
<table
class="mat-elevation-z1 flex-100"
mat-table
[dataSource]="fixedDepositProduct.penaltyToIncomeAccountMappings"
>
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Penalty' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.chargeId | find: fixedDepositProductsTemplate.penaltyOptions : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome">
{{
penaltyIncome.incomeAccountId
| find: fixedDepositProductsTemplate.accountingMappingOptions.incomeAccountOptions : 'id' : 'name'
}}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
</table>
</div>
</div>
}
</div>
<div class="layout-row responsive-column align-center gap-2px margin-t">
@@ -1,9 +1,9 @@
import { Component, OnInit, Input, Output, EventEmitter, SimpleChanges, OnChanges } from '@angular/core';
import { Component, OnInit, Input, Output, EventEmitter, SimpleChanges, OnChanges, inject } from '@angular/core';
import { trigger, state, transition, animate, style } from '@angular/animations';
import { Accounting } from 'app/core/utils/accounting';
import { OptionData } from 'app/shared/models/option-data.model';
import { MatDivider } from '@angular/material/divider';
import { NgIf, NgFor, NgSwitch, NgSwitchCase } from '@angular/common';
import {
MatTable,
MatColumnDef,
@@ -33,8 +33,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
trigger('expandChartSlab', [
state('collapsed', style({ height: '0px', minHeight: '0' })),
state('expanded', style({ height: '*' })),
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)'))])
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)'))
])
],
imports: [
...STANDALONE_SHARED_IMPORTS,
@@ -46,8 +46,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
MatCellDef,
MatCell,
FaIconComponent,
NgSwitch,
NgSwitchCase,
MatHeaderRowDef,
MatHeaderRow,
MatRowDef,
@@ -61,6 +59,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class FixedDepositProductPreviewStepComponent implements OnInit, OnChanges {
private accounting = inject(Accounting);
@Input() fixedDepositProductsTemplate: any;
@Input() chartSlabsDisplayedColumns: any[];
@Input() accountingRuleData: any;
@@ -96,8 +96,6 @@ export class FixedDepositProductPreviewStepComponent implements OnInit, OnChange
accountingMappings: any = {};
accountingRule: OptionData;
constructor(private accounting: Accounting) {}
ngOnInit() {
this.setCurrentValues();
}
@@ -16,12 +16,11 @@
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Type' | translate }}</mat-label>
<mat-select formControlName="lockinPeriodFrequencyType">
<mat-option
*ngFor="let lockinPeriodFrequencyType of lockinPeriodFrequencyTypeData"
[value]="lockinPeriodFrequencyType.id"
>
{{ lockinPeriodFrequencyType.value }}
</mat-option>
@for (lockinPeriodFrequencyType of lockinPeriodFrequencyTypeData; track lockinPeriodFrequencyType) {
<mat-option [value]="lockinPeriodFrequencyType.id">
{{ lockinPeriodFrequencyType.value }}
</mat-option>
}
</mat-select>
</mat-form-field>
@@ -42,9 +41,11 @@
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Frequency Type' | translate }}</mat-label>
<mat-select formControlName="minDepositTermTypeId" required>
<mat-option *ngFor="let periodFrequencyType of periodFrequencyTypeData" [value]="periodFrequencyType.id">
{{ periodFrequencyType.value }}
</mat-option>
@for (periodFrequencyType of periodFrequencyTypeData; track periodFrequencyType) {
<mat-option [value]="periodFrequencyType.id">
{{ periodFrequencyType.value }}
</mat-option>
}
</mat-select>
<mat-error>
{{ 'labels.inputs.Minimum Deposit Term Frequency Type' | translate }} {{ 'labels.commons.is' | translate }}
@@ -68,9 +69,11 @@
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Type' | translate }}</mat-label>
<mat-select formControlName="inMultiplesOfDepositTermTypeId">
<mat-option *ngFor="let periodFrequencyType of periodFrequencyTypeData" [value]="periodFrequencyType.id">
{{ periodFrequencyType.value }}
</mat-option>
@for (periodFrequencyType of periodFrequencyTypeData; track periodFrequencyType) {
<mat-option [value]="periodFrequencyType.id">
{{ periodFrequencyType.value }}
</mat-option>
}
</mat-select>
</mat-form-field>
@@ -87,9 +90,11 @@
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Type' | translate }}</mat-label>
<mat-select formControlName="maxDepositTermTypeId">
<mat-option *ngFor="let periodFrequencyType of periodFrequencyTypeData" [value]="periodFrequencyType.id">
{{ periodFrequencyType.value }}
</mat-option>
@for (periodFrequencyType of periodFrequencyTypeData; track periodFrequencyType) {
<mat-option [value]="periodFrequencyType.id">
{{ periodFrequencyType.value }}
</mat-option>
}
</mat-select>
</mat-form-field>
@@ -115,12 +120,11 @@
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Period' | translate }}</mat-label>
<mat-select formControlName="preClosurePenalInterestOnTypeId">
<mat-option
*ngFor="let preClosurePenalInterestOnType of preClosurePenalInterestOnTypeData"
[value]="preClosurePenalInterestOnType.id"
>
{{ preClosurePenalInterestOnType.value }}
</mat-option>
@for (preClosurePenalInterestOnType of preClosurePenalInterestOnTypeData; track preClosurePenalInterestOnType) {
<mat-option [value]="preClosurePenalInterestOnType.id">
{{ preClosurePenalInterestOnType.value }}
</mat-option>
}
</mat-select>
</mat-form-field>
@@ -135,18 +139,22 @@
{{ 'labels.inputs.Is Withhold Tax Applicable' | translate }}
</mat-checkbox>
<mat-form-field class="flex-48" *ngIf="fixedDepositProductSettingsForm.value.withHoldTax">
<mat-label>{{ 'labels.inputs.Tax Group' | translate }}</mat-label>
<mat-select formControlName="taxGroupId" required>
<mat-option *ngFor="let taxGroup of taxGroupData" [value]="taxGroup.id">
{{ taxGroup.name }}
</mat-option>
</mat-select>
<mat-error>
{{ 'labels.inputs.Tax Group' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
@if (fixedDepositProductSettingsForm.value.withHoldTax) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Tax Group' | translate }}</mat-label>
<mat-select formControlName="taxGroupId" required>
@for (taxGroup of taxGroupData; track taxGroup) {
<mat-option [value]="taxGroup.id">
{{ taxGroup.name }}
</mat-option>
}
</mat-select>
<mat-error>
{{ 'labels.inputs.Tax Group' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
}
</div>
<div class="layout-row align-center gap-2percent margin-t responsive-column">
@@ -1,4 +1,4 @@
import { Component, OnInit, Input } from '@angular/core';
import { Component, OnInit, Input, inject } from '@angular/core';
import {
UntypedFormGroup,
UntypedFormBuilder,
@@ -28,6 +28,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class FixedDepositProductSettingsStepComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
@Input() fixedDepositProductsTemplate: any;
fixedDepositProductSettingsForm: UntypedFormGroup;
@@ -37,7 +39,7 @@ export class FixedDepositProductSettingsStepComponent implements OnInit {
preClosurePenalInterestOnTypeData: any;
taxGroupData: any;
constructor(private formBuilder: UntypedFormBuilder) {
constructor() {
this.createFixedDepositProductSettingsForm();
this.setConditionalControls();
}
@@ -47,12 +47,11 @@
matTooltip="{{ 'tooltips.The period at which interest rate' | translate }}"
required
>
<mat-option
*ngFor="let interestCompoundingPeriodType of interestCompoundingPeriodTypeData"
[value]="interestCompoundingPeriodType.id"
>
{{ interestCompoundingPeriodType.value }}
</mat-option>
@for (interestCompoundingPeriodType of interestCompoundingPeriodTypeData; track interestCompoundingPeriodType) {
<mat-option [value]="interestCompoundingPeriodType.id">
{{ interestCompoundingPeriodType.value }}
</mat-option>
}
</mat-select>
<mat-error>
{{ 'labels.inputs.Interest Compounding Period' | translate }} {{ 'labels.commons.is' | translate }}
@@ -67,12 +66,11 @@
matTooltip="{{ 'tooltips.The period at which interest rate is posted or credited' | translate }}"
required
>
<mat-option
*ngFor="let interestPostingPeriodType of interestPostingPeriodTypeData"
[value]="interestPostingPeriodType.id"
>
{{ interestPostingPeriodType.value }}
</mat-option>
@for (interestPostingPeriodType of interestPostingPeriodTypeData; track interestPostingPeriodType) {
<mat-option [value]="interestPostingPeriodType.id">
{{ interestPostingPeriodType.value }}
</mat-option>
}
</mat-select>
<mat-error>
{{ 'labels.inputs.Interest Posting Period' | translate }} {{ 'labels.commons.is' | translate }}
@@ -87,12 +85,11 @@
matTooltip="{{ 'tooltips.The method used to calculate interest' | translate }}"
required
>
<mat-option
*ngFor="let interestCalculationType of interestCalculationTypeData"
[value]="interestCalculationType.id"
>
{{ interestCalculationType.value }}
</mat-option>
@for (interestCalculationType of interestCalculationTypeData; track interestCalculationType) {
<mat-option [value]="interestCalculationType.id">
{{ interestCalculationType.value }}
</mat-option>
}
</mat-select>
<mat-error>
{{ 'labels.inputs.Interest Calculated using' | translate }} {{ 'labels.commons.is' | translate }}
@@ -107,12 +104,14 @@
matTooltip="{{ 'tooltips.The setting for number of days' | translate }}"
required
>
<mat-option
*ngFor="let interestCalculationDaysInYearType of interestCalculationDaysInYearTypeData"
[value]="interestCalculationDaysInYearType.id"
>
{{ interestCalculationDaysInYearType.value }}
</mat-option>
@for (
interestCalculationDaysInYearType of interestCalculationDaysInYearTypeData;
track interestCalculationDaysInYearType
) {
<mat-option [value]="interestCalculationDaysInYearType.id">
{{ interestCalculationDaysInYearType.value }}
</mat-option>
}
</mat-select>
<mat-error>
{{ 'labels.inputs.Days in Year' | translate }} {{ 'labels.commons.is' | translate }}
@@ -1,4 +1,4 @@
import { Component, OnInit, Input } from '@angular/core';
import { Component, OnInit, Input, inject } from '@angular/core';
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
import { MatTooltip } from '@angular/material/tooltip';
import { MatDivider } from '@angular/material/divider';
@@ -20,6 +20,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class FixedDepositProductTermsStepComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
@Input() fixedDepositProductsTemplate: any;
fixedDepositProductTermsForm: UntypedFormGroup;
@@ -29,7 +31,7 @@ export class FixedDepositProductTermsStepComponent implements OnInit {
interestCalculationTypeData: any;
interestCalculationDaysInYearTypeData: any;
constructor(private formBuilder: UntypedFormBuilder) {
constructor() {
this.createFixedDepositProductTermsForm();
}
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
import { ActivatedRouteSnapshot } from '@angular/router';
/** rxjs Imports */
@@ -13,10 +13,7 @@ import { ProductsService } from '../products.service';
*/
@Injectable()
export class FixedDepositProductResolver {
/**
* @param {ProductsService} productsService Products service.
*/
constructor(private productsService: ProductsService) {}
private productsService = inject(ProductsService);
/**
* Returns the fixed deposit product data.
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
/** rxjs Imports */
import { Observable } from 'rxjs';
@@ -9,7 +9,7 @@ import { ProductsService } from '../products.service';
@Injectable()
export class FixedDepositProductsTemplateResolver {
constructor(private productsService: ProductsService) {}
private productsService = inject(ProductsService);
/**
* Returns the fixed deposit products template data.
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit, TemplateRef, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
import { Component, OnInit, TemplateRef, ElementRef, ViewChild, AfterViewInit, inject } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort, MatSortHeader } from '@angular/material/sort';
import {
@@ -52,6 +52,11 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class FixedDepositProductsComponent implements OnInit, AfterViewInit {
private route = inject(ActivatedRoute);
private router = inject(Router);
private configurationWizardService = inject(ConfigurationWizardService);
private popoverService = inject(PopoverService);
/** Fixed deposit products data. */
fixedDepositProductData: any;
/** Columns to be displayed in fixed deposit products table. */
@@ -83,12 +88,7 @@ export class FixedDepositProductsComponent implements OnInit, AfterViewInit {
* @param {ConfigurationWizardService} configurationWizardService ConfigurationWizard Service.
* @param {PopoverService} popoverService PopoverService.
*/
constructor(
private route: ActivatedRoute,
private router: Router,
private configurationWizardService: ConfigurationWizardService,
private popoverService: PopoverService
) {
constructor() {
this.route.data.subscribe((data: { fixedDepositProducts: any }) => {
this.fixedDepositProductData = data.fixedDepositProducts;
});
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
/** rxjs Imports */
import { Observable } from 'rxjs';
@@ -12,10 +12,7 @@ import { ProductsService } from '../products.service';
*/
@Injectable()
export class FixedDepositProductsResolver {
/**
* @param {ProductsService} productsService Products service.
*/
constructor(private productsService: ProductsService) {}
private productsService = inject(ProductsService);
/**
* Returns the fixed deposit products data.
@@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { EntityDatatableTabComponent } from '../../../../shared/tabs/entity-datatable-tab/entity-datatable-tab.component';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
@@ -13,11 +13,13 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class FixedDepositDatatableTabComponent {
private route = inject(ActivatedRoute);
entityId: string;
entityDatatable: any;
multiRowDatatableFlag: boolean;
constructor(private route: ActivatedRoute) {
constructor() {
this.entityId = this.route.parent.parent.snapshot.paramMap.get('productId');
this.route.data.subscribe((data: { fixedDepositDatatable: any }) => {
@@ -21,10 +21,12 @@
<span class="flex-60">{{ fixedDepositProductData.shortName }}</span>
</div>
<div class="flex-100 layout-row" *ngIf="fixedDepositProductData.description">
<span class="flex-40">{{ 'labels.inputs.Description' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProductData.description }}</span>
</div>
@if (fixedDepositProductData.description) {
<div class="flex-100 layout-row">
<span class="flex-40">{{ 'labels.inputs.Description' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProductData.description }}</span>
</div>
}
<h3 class="mat-h3 flex-100">{{ 'labels.inputs.Currency' | translate }}</h3>
@@ -91,300 +93,332 @@
<mat-divider [inset]="true"></mat-divider>
<div class="flex-100 layout-row" *ngIf="fixedDepositProductData.lockinPeriodFrequency">
<span class="flex-40">{{ 'labels.inputs.Lock-in Period' | translate }}:</span>
<span class="flex-60">
{{ fixedDepositProductData.lockinPeriodFrequency }}
{{ fixedDepositProductData.lockinPeriodFrequencyType.value }}</span
>
</div>
@if (fixedDepositProductData.lockinPeriodFrequency) {
<div class="flex-100 layout-row">
<span class="flex-40">{{ 'labels.inputs.Lock-in Period' | translate }}:</span>
<span class="flex-60">
{{ fixedDepositProductData.lockinPeriodFrequency }}
{{ fixedDepositProductData.lockinPeriodFrequencyType.value }}</span
>
</div>
}
<div class="flex-100 layout-row" *ngIf="fixedDepositProductData.minDepositTerm">
<span class="flex-40">{{ 'labels.inputs.Minimum Deposit Term' | translate }}:</span>
<span class="flex-60" *ngIf="fixedDepositProductData.minDepositTerm !== undefined"
>{{ fixedDepositProductData.minDepositTerm }}
&nbsp;
{{ fixedDepositProductData.minDepositTermType.value }}</span
>
</div>
@if (fixedDepositProductData.minDepositTerm) {
<div class="flex-100 layout-row">
<span class="flex-40">{{ 'labels.inputs.Minimum Deposit Term' | translate }}:</span>
@if (fixedDepositProductData.minDepositTerm !== undefined) {
<span class="flex-60"
>{{ fixedDepositProductData.minDepositTerm }}
&nbsp;
{{ fixedDepositProductData.minDepositTermType.value }}</span
>
}
</div>
}
<div class="flex-100 layout-row" *ngIf="fixedDepositProductData.maxDepositTerm">
<span class="flex-40">{{ 'labels.inputs.Maximum Deposit Term' | translate }}:</span>
<span class="flex-60" *ngIf="fixedDepositProductData.maxDepositTerm !== undefined"
>{{ fixedDepositProductData.maxDepositTerm }}
&nbsp;
{{ fixedDepositProductData.maxDepositTermType.value }}</span
>
</div>
@if (fixedDepositProductData.maxDepositTerm) {
<div class="flex-100 layout-row">
<span class="flex-40">{{ 'labels.inputs.Maximum Deposit Term' | translate }}:</span>
@if (fixedDepositProductData.maxDepositTerm !== undefined) {
<span class="flex-60"
>{{ fixedDepositProductData.maxDepositTerm }}
&nbsp;
{{ fixedDepositProductData.maxDepositTermType.value }}</span
>
}
</div>
}
<div class="flex-100 layout-row" *ngIf="fixedDepositProductData.inMultiplesOfDepositTerm">
<span class="flex-40">{{ 'labels.inputs.Deposit Term In multiple of' | translate }}:</span>
<span class="flex-60"
>{{ fixedDepositProductData.inMultiplesOfDepositTerm }}
-
{{ fixedDepositProductData.inMultiplesOfDepositTermType.value }}</span
>
</div>
@if (fixedDepositProductData.inMultiplesOfDepositTerm) {
<div class="flex-100 layout-row">
<span class="flex-40">{{ 'labels.inputs.Deposit Term In multiple of' | translate }}:</span>
<span class="flex-60"
>{{ fixedDepositProductData.inMultiplesOfDepositTerm }}
-
{{ fixedDepositProductData.inMultiplesOfDepositTermType.value }}</span
>
</div>
}
<div class="flex-100 layout-row">
<span class="flex-40">{{ 'labels.inputs.Apply Penal Interest (less)' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProductData.preClosurePenalApplicable | yesNo }}</span>
</div>
<div class="flex-100 layout-row" *ngIf="fixedDepositProductData.preClosurePenalApplicable">
<span class="flex-40">{{ 'labels.inputs.Penal Interest' | translate }} (%):</span>
<span class="flex-60"
>{{ fixedDepositProductData.preClosurePenalInterest }} &nbsp; &nbsp; % &nbsp; &nbsp; On &nbsp;&nbsp;
{{ fixedDepositProductData.preClosurePenalInterestOnType.value }}</span
>
</div>
@if (fixedDepositProductData.preClosurePenalApplicable) {
<div class="flex-100 layout-row">
<span class="flex-40">{{ 'labels.inputs.Penal Interest' | translate }} (%):</span>
<span class="flex-60"
>{{ fixedDepositProductData.preClosurePenalInterest }} &nbsp; &nbsp; % &nbsp; &nbsp; On &nbsp;&nbsp;
{{ fixedDepositProductData.preClosurePenalInterestOnType.value }}</span
>
</div>
}
<div class="flex-100 layout-row" *ngIf="fixedDepositProductData.minBalanceForInterestCalculation">
<span class="flex-40">{{ 'labels.inputs.Balance Required for Interest Calculation' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProductData.minBalanceForInterestCalculation | formatNumber }}</span>
</div>
@if (fixedDepositProductData.minBalanceForInterestCalculation) {
<div class="flex-100 layout-row">
<span class="flex-40">{{ 'labels.inputs.Balance Required for Interest Calculation' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProductData.minBalanceForInterestCalculation | formatNumber }}</span>
</div>
}
<div class="flex-100 layout-row">
<span class="flex-40">{{ 'labels.inputs.Withhold Tax is Applicable' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProductData.withHoldTax | yesNo }}</span>
</div>
<div class="flex-100 layout-row" *ngIf="fixedDepositProductData.withHoldTax">
<span class="flex-40">{{ 'labels.inputs.Withhold Tax group' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProductData.taxGroup.name }}</span>
</div>
<div *ngIf="fixedDepositProductData.activeChart" class="responsive-column flex-100">
<h3 class="mat-h3 flex-100">{{ 'labels.heading.Interest Rate Chart' | translate }}</h3>
<mat-divider [inset]="true"></mat-divider>
@if (fixedDepositProductData.withHoldTax) {
<div class="flex-100 layout-row">
<span class="flex-40">{{ 'labels.inputs.Withhold Tax group' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProductData.taxGroup.name }}</span>
</div>
}
@if (fixedDepositProductData.activeChart) {
<div class="responsive-column flex-100">
<div class="flex-100 layout-row" *ngIf="fixedDepositProductData.activeChart.name">
<span class="flex-40">{{ 'labels.inputs.Name' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProductData.activeChart.name }}</span>
</div>
<div class="flex-100 layout-row" *ngIf="fixedDepositProductData.activeChart.description">
<span class="flex-40">{{ 'labels.inputs.Description' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProductData.activeChart.description }}</span>
</div>
<div class="flex-100 layout-row">
<span class="flex-40">{{ 'labels.inputs.From Date' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProductData.activeChart.fromDate | dateFormat }}</span>
</div>
<div class="flex-100 layout-row" *ngIf="fixedDepositProductData.activeChart.endDate">
<span class="flex-40">{{ 'labels.inputs.End Date' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProductData.activeChart.endDate | dateFormat }}</span>
</div>
<div class="flex-100 layout-row">
<span class="flex-40">{{ 'labels.inputs.Primary Grouping by Amount' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProductData.activeChart.isPrimaryGroupingByAmount | yesNo }}</span>
</div>
<table
class="mat-elevation-z1 flex-100"
mat-table
[dataSource]="fixedDepositProductData.activeChart.chartSlabs"
multiTemplateDataRows
>
<ng-container matColumnDef="period">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Period' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
<div *ngIf="chartSlab.fromPeriod !== undefined">
{{ chartSlab.fromPeriod }} - {{ chartSlab.toPeriod }} {{ chartSlab.periodType.value }}
</div>
<div *ngIf="chartSlab.fromPeriod === undefined">&nbsp;</div>
</td>
</ng-container>
<ng-container matColumnDef="amountRange">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount Range' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
<div *ngIf="chartSlab.amountRangeFrom !== undefined">
{{ chartSlab.amountRangeFrom }} - {{ chartSlab.amountRangeTo }}
</div>
<div *ngIf="chartSlab.amountRangeFrom === undefined">&nbsp;</div>
</td>
</ng-container>
<ng-container matColumnDef="annualInterestRate">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Interest' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">{{ chartSlab.annualInterestRate }} %</td>
</ng-container>
<ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Description' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
{{ chartSlab.description }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab; let chartSlabIndex = dataIndex">
<button
mat-button
color="primary"
(click)="expandChartSlabIndex = expandChartSlabIndex === chartSlabIndex ? null : chartSlabIndex"
<h3 class="mat-h3 flex-100">{{ 'labels.heading.Interest Rate Chart' | translate }}</h3>
<mat-divider [inset]="true"></mat-divider>
<div class="responsive-column flex-100">
@if (fixedDepositProductData.activeChart.name) {
<div class="flex-100 layout-row">
<span class="flex-40">{{ 'labels.inputs.Name' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProductData.activeChart.name }}</span>
</div>
}
@if (fixedDepositProductData.activeChart.description) {
<div class="flex-100 layout-row">
<span class="flex-40">{{ 'labels.inputs.Description' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProductData.activeChart.description }}</span>
</div>
}
<div class="flex-100 layout-row">
<span class="flex-40">{{ 'labels.inputs.From Date' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProductData.activeChart.fromDate | dateFormat }}</span>
</div>
@if (fixedDepositProductData.activeChart.endDate) {
<div class="flex-100 layout-row">
<span class="flex-40">{{ 'labels.inputs.End Date' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProductData.activeChart.endDate | dateFormat }}</span>
</div>
}
<div class="flex-100 layout-row">
<span class="flex-40">{{ 'labels.inputs.Primary Grouping by Amount' | translate }}:</span>
<span class="flex-60">{{ fixedDepositProductData.activeChart.isPrimaryGroupingByAmount | yesNo }}</span>
</div>
<table
class="mat-elevation-z1 flex-100"
mat-table
[dataSource]="fixedDepositProductData.activeChart.chartSlabs"
multiTemplateDataRows
>
<ng-container matColumnDef="period">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Period' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
@if (chartSlab.fromPeriod !== undefined) {
<div>{{ chartSlab.fromPeriod }} - {{ chartSlab.toPeriod }} {{ chartSlab.periodType.value }}</div>
}
@if (chartSlab.fromPeriod === undefined) {
<div>&nbsp;</div>
}
</td>
</ng-container>
<ng-container matColumnDef="amountRange">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount Range' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
@if (chartSlab.amountRangeFrom !== undefined) {
<div>{{ chartSlab.amountRangeFrom }} - {{ chartSlab.amountRangeTo }}</div>
}
@if (chartSlab.amountRangeFrom === undefined) {
<div>&nbsp;</div>
}
</td>
</ng-container>
<ng-container matColumnDef="annualInterestRate">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Interest' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">{{ chartSlab.annualInterestRate }} %</td>
</ng-container>
<ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Description' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab">
{{ chartSlab.description }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let chartSlab; let chartSlabIndex = dataIndex">
<button
mat-button
color="primary"
(click)="expandChartSlabIndex = expandChartSlabIndex === chartSlabIndex ? null : chartSlabIndex"
>
@if (expandChartSlabIndex !== chartSlabIndex) {
<span>
<fa-icon icon="eye" class="m-r-10"></fa-icon>
{{ 'labels.buttons.View Incentives' | translate }}
</span>
}
@if (expandChartSlabIndex === chartSlabIndex) {
<span>
<fa-icon icon="eye-slash" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Hide Incentives' | translate }}
</span>
}
</button>
</td>
</ng-container>
<ng-container matColumnDef="incentives">
<td
mat-cell
*matCellDef="let chartSlab; let chartSlabIndex = dataIndex"
[attr.colspan]="chartSlabsDisplayedColumns.length"
>
<span *ngIf="expandChartSlabIndex !== chartSlabIndex">
<fa-icon icon="eye" class="m-r-10"></fa-icon>
{{ 'labels.buttons.View Incentives' | translate }}
</span>
<span *ngIf="expandChartSlabIndex === chartSlabIndex">
<fa-icon icon="eye-slash" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Hide Incentives' | translate }}
</span>
</button>
<div
class="incentives flex-100 layout-row-wrap"
[@expandChartSlab]="chartSlabIndex === expandChartSlabIndex ? 'expanded' : 'collapsed'"
>
<mat-card class="layout-row-wrap flex-100">
<h4 class="mat-h4 flex-23">
{{ 'labels.heading.Incentives' | translate }}
</h4>
<table class="flex-100 mat-elevation-z1" mat-table [dataSource]="chartSlab.incentives">
<ng-container matColumnDef="entityType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Entity Type' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{
incentive.entityType
| find: fixedDepositProductsTemplate.chartTemplate.entityTypeOptions : 'id' : 'value'
}}
</td>
</ng-container>
<ng-container matColumnDef="attributeName">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Attribute Name' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{
incentive.attributeName
| find
: fixedDepositProductsTemplate.chartTemplate.attributeNameOptions
: 'id'
: 'value'
}}
</td>
</ng-container>
<ng-container matColumnDef="conditionType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Condition Type' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{
incentive.conditionType
| find
: fixedDepositProductsTemplate.chartTemplate.conditionTypeOptions
: 'id'
: 'value'
}}
</td>
</ng-container>
<ng-container matColumnDef="attributeValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Attribute Value' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
@switch (incentive.attributeName) {
@case (2) {
<span>{{
incentive.attributeValue
| find: fixedDepositProductsTemplate.chartTemplate.genderOptions : 'id' : 'name'
}}</span>
}
@case (3) {
<span>{{ incentive.attributeValue }}</span>
}
@case (4) {
<span>{{
incentive.attributeValue
| find
: fixedDepositProductsTemplate.chartTemplate.clientTypeOptions
: 'id'
: 'name'
}}</span>
}
@case (5) {
<span>{{
incentive.attributeValue
| find
: fixedDepositProductsTemplate.chartTemplate.clientClassificationOptions
: 'id'
: 'name'
}}</span>
}
}
</td>
</ng-container>
<ng-container matColumnDef="incentiveType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Incentive Type' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{
incentive.incentiveType
| find
: fixedDepositProductsTemplate.chartTemplate.incentiveTypeOptions
: 'id'
: 'value'
}}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{ incentive.amount | formatNumber }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="incentivesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: incentivesDisplayedColumns"></tr>
</table>
</mat-card>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chartSlabsDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chartSlabsDisplayedColumns"></tr>
<tr
mat-row
*matRowDef="let row; columns: chartSlabsIncentivesDisplayedColumns"
class="incentives-row"
></tr>
</table>
</div>
</div>
}
@if (fixedDepositProductData.charges.length) {
<div class="layout-row-wrap responsive-column flex-100">
<h3 class="mat-h3 flex-100">{{ 'labels.inputs.Charges' | translate }}</h3>
<mat-divider class="flex-100"></mat-divider>
<table class="flex-100 mat-elevation-z1" mat-table [dataSource]="fixedDepositProductData.charges">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Name' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="incentives">
<td
mat-cell
*matCellDef="let chartSlab; let chartSlabIndex = dataIndex"
[attr.colspan]="chartSlabsDisplayedColumns.length"
>
<div
class="incentives flex-100 layout-row-wrap"
[@expandChartSlab]="chartSlabIndex === expandChartSlabIndex ? 'expanded' : 'collapsed'"
>
<mat-card class="layout-row-wrap flex-100">
<h4 class="mat-h4 flex-23">
{{ 'labels.heading.Incentives' | translate }}
</h4>
<table class="flex-100 mat-elevation-z1" mat-table [dataSource]="chartSlab.incentives">
<ng-container matColumnDef="entityType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Entity Type' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{
incentive.entityType
| find: fixedDepositProductsTemplate.chartTemplate.entityTypeOptions : 'id' : 'value'
}}
</td>
</ng-container>
<ng-container matColumnDef="attributeName">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Attribute Name' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{
incentive.attributeName
| find: fixedDepositProductsTemplate.chartTemplate.attributeNameOptions : 'id' : 'value'
}}
</td>
</ng-container>
<ng-container matColumnDef="conditionType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Condition Type' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{
incentive.conditionType
| find: fixedDepositProductsTemplate.chartTemplate.conditionTypeOptions : 'id' : 'value'
}}
</td>
</ng-container>
<ng-container matColumnDef="attributeValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Attribute Value' | translate }}</th>
<td mat-cell *matCellDef="let incentive" [ngSwitch]="incentive.attributeName">
<span *ngSwitchCase="2">{{
incentive.attributeValue
| find: fixedDepositProductsTemplate.chartTemplate.genderOptions : 'id' : 'name'
}}</span>
<span *ngSwitchCase="3">{{ incentive.attributeValue }}</span>
<span *ngSwitchCase="4">{{
incentive.attributeValue
| find: fixedDepositProductsTemplate.chartTemplate.clientTypeOptions : 'id' : 'name'
}}</span>
<span *ngSwitchCase="5">{{
incentive.attributeValue
| find
: fixedDepositProductsTemplate.chartTemplate.clientClassificationOptions
: 'id'
: 'name'
}}</span>
</td>
</ng-container>
<ng-container matColumnDef="incentiveType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Incentive Type' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{
incentive.incentiveType
| find: fixedDepositProductsTemplate.chartTemplate.incentiveTypeOptions : 'id' : 'value'
}}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
<td mat-cell *matCellDef="let incentive">
{{ incentive.amount | formatNumber }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="incentivesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: incentivesDisplayedColumns"></tr>
</table>
</mat-card>
</div>
<ng-container matColumnDef="type">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Type' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeCalculationType.value }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chartSlabsDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chartSlabsDisplayedColumns"></tr>
<tr
mat-row
*matRowDef="let row; columns: chartSlabsIncentivesDisplayedColumns"
class="incentives-row"
></tr>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.amount | formatNumber }}
</td>
</ng-container>
<ng-container matColumnDef="collectedon">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Collected On' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeTimeType.value }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chargesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chargesDisplayedColumns"></tr>
</table>
</div>
</div>
<div *ngIf="fixedDepositProductData.charges.length" class="layout-row-wrap responsive-column flex-100">
<h3 class="mat-h3 flex-100">{{ 'labels.inputs.Charges' | translate }}</h3>
<mat-divider class="flex-100"></mat-divider>
<table class="flex-100 mat-elevation-z1" mat-table [dataSource]="fixedDepositProductData.charges">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Name' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="type">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Type' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeCalculationType.value }}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.amount | formatNumber }}
</td>
</ng-container>
<ng-container matColumnDef="collectedon">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Collected On' | translate }}</th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeTimeType.value }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chargesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chargesDisplayedColumns"></tr>
</table>
</div>
}
<h3 class="mat-h3 flex-100">{{ 'labels.heading.Accounting' | translate }}</h3>
@@ -397,113 +431,97 @@
>
</mifosx-view-savings-accounting-details>
<div
class="flex-100 layout-row-wrap layout-lt-md-column"
*ngIf="
fixedDepositProductData.advancedAccountingRules &&
(fixedDepositProductData.paymentChannelToFundSourceMappings?.length ||
fixedDepositProductData.feeToIncomeAccountMappings?.length ||
fixedDepositProductData.penaltyToIncomeAccountMappings?.length)
"
>
<h3 class="mat-h3 flex-100">{{ 'labels.heading.Advanced Accounting Rules' | translate }}</h3>
<mat-divider [inset]="true"></mat-divider>
<hr />
<div
*ngIf="fixedDepositProductData.paymentChannelToFundSourceMappings?.length"
class="flex-100 layout-row-wrap layout-xs-column"
>
<h4 class="mat-h4 flex-100">
{{ 'labels.inputs.Configure Fund Sources for Payment Channels' | translate }}
</h4>
<table
class="mat-elevation-z1 flex-100"
mat-table
[dataSource]="fixedDepositProductData.paymentChannelToFundSourceMappings"
>
<ng-container matColumnDef="paymentTypeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Payment Type' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.paymentType.name }}
</td>
</ng-container>
<ng-container matColumnDef="fundSourceAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Fund Source' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.fundSourceAccount.name }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="paymentFundSourceDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: paymentFundSourceDisplayedColumns"></tr>
</table>
@if (
fixedDepositProductData.advancedAccountingRules &&
(fixedDepositProductData.paymentChannelToFundSourceMappings?.length ||
fixedDepositProductData.feeToIncomeAccountMappings?.length ||
fixedDepositProductData.penaltyToIncomeAccountMappings?.length)
) {
<div class="flex-100 layout-row-wrap layout-lt-md-column">
<h3 class="mat-h3 flex-100">{{ 'labels.heading.Advanced Accounting Rules' | translate }}</h3>
<mat-divider [inset]="true"></mat-divider>
<hr />
@if (fixedDepositProductData.paymentChannelToFundSourceMappings?.length) {
<div class="flex-100 layout-row-wrap layout-xs-column">
<h4 class="mat-h4 flex-100">
{{ 'labels.inputs.Configure Fund Sources for Payment Channels' | translate }}
</h4>
<table
class="mat-elevation-z1 flex-100"
mat-table
[dataSource]="fixedDepositProductData.paymentChannelToFundSourceMappings"
>
<ng-container matColumnDef="paymentTypeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Payment Type' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.paymentType.name }}
</td>
</ng-container>
<ng-container matColumnDef="fundSourceAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Fund Source' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.fundSourceAccount.name }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="paymentFundSourceDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: paymentFundSourceDisplayedColumns"></tr>
</table>
</div>
}
@if (fixedDepositProductData.feeToIncomeAccountMappings?.length) {
<div class="flex-100 layout-row-wrap layout-xs-column">
<h4 class="mat-h4 flex-100">{{ 'labels.inputs.Fees to Specific Income Accounts' | translate }}</h4>
<table
class="mat-elevation-z1 flex-100"
mat-table
[dataSource]="fixedDepositProductData.feeToIncomeAccountMappings"
>
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Fees' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.incomeAccount.name }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
</table>
</div>
}
@if (fixedDepositProductData.penaltyToIncomeAccountMappings?.length) {
<div class="flex-100 layout-row-wrap layout-xs-column">
<h4 class="mat-h4 flex-100">
{{ 'labels.heading.Penalties to Specific Income Accounts' | translate }}
</h4>
<table
class="mat-elevation-z1 flex-100"
mat-table
[dataSource]="fixedDepositProductData.penaltyToIncomeAccountMappings"
>
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Penalty' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.incomeAccount.name }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
</table>
</div>
}
</div>
<div
*ngIf="fixedDepositProductData.feeToIncomeAccountMappings?.length"
class="flex-100 layout-row-wrap layout-xs-column"
>
<h4 class="mat-h4 flex-100">{{ 'labels.inputs.Fees to Specific Income Accounts' | translate }}</h4>
<table
class="mat-elevation-z1 flex-100"
mat-table
[dataSource]="fixedDepositProductData.feeToIncomeAccountMappings"
>
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Fees' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.incomeAccount.name }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
</table>
</div>
<div
*ngIf="fixedDepositProductData.penaltyToIncomeAccountMappings?.length"
class="flex-100 layout-row-wrap layout-xs-column"
>
<h4 class="mat-h4 flex-100">{{ 'labels.heading.Penalties to Specific Income Accounts' | translate }}</h4>
<table
class="mat-elevation-z1 flex-100"
mat-table
[dataSource]="fixedDepositProductData.penaltyToIncomeAccountMappings"
>
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Penalty' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.incomeAccount.name }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
</table>
</div>
</div>
}
</div>
</mat-card-content>
</mat-card>
@@ -1,9 +1,9 @@
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { trigger, state, transition, animate, style } from '@angular/animations';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { MatDivider } from '@angular/material/divider';
import { NgIf, NgSwitch, NgSwitchCase } from '@angular/common';
import {
MatTable,
MatColumnDef,
@@ -31,8 +31,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
trigger('expandChartSlab', [
state('collapsed', style({ height: '0px', minHeight: '0' })),
state('expanded', style({ height: '*' })),
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)'))])
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)'))
])
],
imports: [
...STANDALONE_SHARED_IMPORTS,
@@ -44,8 +44,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
MatHeaderCell,
MatCellDef,
MatCell,
NgSwitch,
NgSwitchCase,
MatHeaderRowDef,
MatHeaderRow,
MatRowDef,
@@ -58,6 +56,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class FixedDepositGeneralTabComponent {
private route = inject(ActivatedRoute);
/** Fixed Deposit Product data. */
fixedDepositProductData: any;
fixedDepositProductsTemplate: any;
@@ -97,7 +97,7 @@ export class FixedDepositGeneralTabComponent {
* Retrieves the fixed deposit product data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
*/
constructor(private route: ActivatedRoute) {
constructor() {
this.route.data.subscribe((data: { fixedDepositProduct: any; fixedDepositProductsTemplate: any }) => {
this.fixedDepositProductData = data.fixedDepositProduct;
this.fixedDepositProductsTemplate = data.fixedDepositProductsTemplate;
@@ -10,7 +10,7 @@
>
{{ 'labels.heading.General' | translate }}
</a>
<ng-container *ngFor="let fixedDepositDatatable of fixedDepositDatatables">
@for (fixedDepositDatatable of fixedDepositDatatables; track fixedDepositDatatable) {
<a
mat-tab-link
[routerLink]="['./datatables', fixedDepositDatatable.registeredTableName]"
@@ -21,7 +21,7 @@
>
{{ fixedDepositDatatable.registeredTableName }}
</a>
</ng-container>
}
</nav>
<mat-tab-nav-panel #tabPanel>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import { ActivatedRoute, RouterLinkActive, RouterLink, RouterOutlet } from '@angular/router';
import { MatTabNav, MatTabLink, MatTabNavPanel } from '@angular/material/tabs';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
@@ -21,9 +21,11 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class ViewFixedDepositProductComponent {
private route = inject(ActivatedRoute);
fixedDepositDatatables: any = [];
constructor(private route: ActivatedRoute) {
constructor() {
this.route.data.subscribe((data: { fixedDepositDatatables: any }) => {
this.fixedDepositDatatables = [];
data.fixedDepositDatatables.forEach((datatable: any) => {
@@ -11,10 +11,12 @@
matTooltip="{{ 'tooltips.Unique name for the floating rate scheme' | translate }}"
formControlName="name"
/>
<mat-error *ngIf="floatingRateForm.controls.name.hasError('required')">
{{ 'labels.inputs.Floating Rate Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (floatingRateForm.controls.name.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Floating Rate Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<div class="checkbox-wrapper flex-30">
@@ -93,22 +95,24 @@
{{ 'labels.inputs.Is Differential' | translate }}?
</th>
<td mat-cell *matCellDef="let floatingRate">
<fa-icon
*ngIf="floatingRate.isDifferentialToBaseLendingRate"
icon="check-circle"
size="lg"
class="is-differential"
matTooltip="{{ 'tooltips.Yes' | translate }}"
matTooltipPosition="right"
></fa-icon>
<fa-icon
*ngIf="!floatingRate.isDifferentialToBaseLendingRate"
icon="times-circle"
size="lg"
class="not-is-differential"
matTooltip="{{ 'tooltips.No' | translate }}"
matTooltipPosition="right"
></fa-icon>
@if (floatingRate.isDifferentialToBaseLendingRate) {
<fa-icon
icon="check-circle"
size="lg"
class="is-differential"
matTooltip="{{ 'tooltips.Yes' | translate }}"
matTooltipPosition="right"
></fa-icon>
}
@if (!floatingRate.isDifferentialToBaseLendingRate) {
<fa-icon
icon="times-circle"
size="lg"
class="not-is-differential"
matTooltip="{{ 'tooltips.No' | translate }}"
matTooltipPosition="right"
></fa-icon>
}
</td>
</ng-container>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, OnInit, ViewChild, inject } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { MatPaginator } from '@angular/material/paginator';
@@ -70,6 +70,15 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class CreateFloatingRateComponent implements OnInit {
private router = inject(Router);
private formBuilder = inject(UntypedFormBuilder);
private productsService = inject(ProductsService);
private route = inject(ActivatedRoute);
private dateUtils = inject(Dates);
private dialog = inject(MatDialog);
private settingsService = inject(SettingsService);
private translateService = inject(TranslateService);
/** Floating Rate Period Data. */
floatingRatePeriodsData: any[] = [];
/** Minimum floating rate period date allowed. */
@@ -93,27 +102,6 @@ export class CreateFloatingRateComponent implements OnInit {
/** Sorter for floating rate periods table. */
@ViewChild(MatSort, { static: true }) sort: MatSort;
/**
* @param {Router} router Router for navigation.
* @param {FormBuilder} formBuilder Form Builder.
* @param {ProductsService} productsService Product Service.
* @param {ActivatedRoute} route Activated Route.
* @param {Dates} dateUtils Date Utils.
* @param {MatDialog} dialog Dialog reference.
* @param {SettingsService} settingsService Settings Service.
* @param {TranslateService} translateService Translate Service.
*/
constructor(
private router: Router,
private formBuilder: UntypedFormBuilder,
private productsService: ProductsService,
private route: ActivatedRoute,
private dateUtils: Dates,
private dialog: MatDialog,
private settingsService: SettingsService,
private translateService: TranslateService
) {}
/**
* Sets the floating rate periods table.
*/
@@ -11,10 +11,12 @@
matTooltip="{{ 'tooltips.Unique name for the floating rate scheme' | translate }}"
formControlName="name"
/>
<mat-error *ngIf="floatingRateForm.controls.name.hasError('required')">
{{ 'labels.inputs.Floating Rate Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (floatingRateForm.controls.name.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Floating Rate Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<div class="checkbox-wrapper flex-25">
@@ -97,22 +99,24 @@
{{ 'labels.inputs.Is Differential' | translate }}?
</th>
<td mat-cell *matCellDef="let floatingRate">
<fa-icon
*ngIf="floatingRate.isDifferentialToBaseLendingRate"
icon="check-circle"
size="lg"
class="is-differential"
matTooltip="{{ 'tooltips.Yes' | translate }}"
matTooltipPosition="right"
></fa-icon>
<fa-icon
*ngIf="!floatingRate.isDifferentialToBaseLendingRate"
icon="times-circle"
size="lg"
class="not-is-differential"
matTooltip="{{ 'tooltips.No' | translate }}"
matTooltipPosition="right"
></fa-icon>
@if (floatingRate.isDifferentialToBaseLendingRate) {
<fa-icon
icon="check-circle"
size="lg"
class="is-differential"
matTooltip="{{ 'tooltips.Yes' | translate }}"
matTooltipPosition="right"
></fa-icon>
}
@if (!floatingRate.isDifferentialToBaseLendingRate) {
<fa-icon
icon="times-circle"
size="lg"
class="not-is-differential"
matTooltip="{{ 'tooltips.No' | translate }}"
matTooltipPosition="right"
></fa-icon>
}
</td>
</ng-container>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, OnInit, ViewChild, inject } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { MatPaginator } from '@angular/material/paginator';
@@ -68,6 +68,15 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class EditFloatingRateComponent implements OnInit {
private router = inject(Router);
private formBuilder = inject(UntypedFormBuilder);
private productsService = inject(ProductsService);
private route = inject(ActivatedRoute);
private dateUtils = inject(Dates);
private dialog = inject(MatDialog);
private settingsService = inject(SettingsService);
private translateService = inject(TranslateService);
/** Floating Rate Form. */
floatingRateForm: UntypedFormGroup;
/** Floating Rate Data. */
@@ -106,16 +115,7 @@ export class EditFloatingRateComponent implements OnInit {
* @param {SettingsService} settingsService Settings Service.
* @param {TranslateService} translateService Translate Service.
*/
constructor(
private router: Router,
private formBuilder: UntypedFormBuilder,
private productsService: ProductsService,
private route: ActivatedRoute,
private dateUtils: Dates,
private dialog: MatDialog,
private settingsService: SettingsService,
private translateService: TranslateService
) {
constructor() {
this.route.data.subscribe((data: { floatingRate: any }) => {
this.floatingRateData = data.floatingRate;
this.floatingRatePeriodsData = data.floatingRate.ratePeriods ? data.floatingRate.ratePeriods : [];
@@ -8,19 +8,23 @@
<input required matInput formControlName="fromDate" [min]="minDate" [matDatepicker]="fromDatePicker" />
<mat-datepicker-toggle matSuffix [for]="fromDatePicker"></mat-datepicker-toggle>
<mat-datepicker #fromDatePicker></mat-datepicker>
<mat-error *ngIf="floatingRatePeriodForm.controls.fromDate.hasError('required')">
{{ 'labels.inputs.From Date' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (floatingRatePeriodForm.controls.fromDate.hasError('required')) {
<mat-error>
{{ 'labels.inputs.From Date' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'labels.inputs.Interest Rate' | translate }}</mat-label>
<input matInput type="number" required formControlName="interestRate" />
<mat-error *ngIf="floatingRatePeriodForm.controls.interestRate.hasError('required')">
{{ 'labels.inputs.Interest Rate' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (floatingRatePeriodForm.controls.interestRate.hasError('required')) {
<mat-error>
{{ 'labels.inputs.Interest Rate' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
}
</mat-form-field>
<mat-checkbox class="is-differential" formControlName="isDifferentialToBaseLendingRate" labelPosition="after">
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit, Inject } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import {
MAT_DIALOG_DATA,
MatDialogRef,
@@ -32,23 +32,16 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class FloatingRatePeriodDialogComponent implements OnInit {
dialogRef = inject<MatDialogRef<FloatingRatePeriodDialogComponent>>(MatDialogRef);
formBuilder = inject(UntypedFormBuilder);
private settingsService = inject(SettingsService);
data = inject(MAT_DIALOG_DATA);
/** Floating Rate Period Form. */
floatingRatePeriodForm: UntypedFormGroup;
/** Minimum floating rate period date allowed. */
minDate = new Date();
/**
* @param {MatDialogRef} dialogRef Component reference to dialog.
* @param {FormBuilder} formBuilder Form Builder.
* @param {any} data Provides values for the form (if available).
*/
constructor(
public dialogRef: MatDialogRef<FloatingRatePeriodDialogComponent>,
public formBuilder: UntypedFormBuilder,
private settingsService: SettingsService,
@Inject(MAT_DIALOG_DATA) public data: any
) {}
/**
* Creates the floating rate period form.
*/
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
import { ActivatedRouteSnapshot } from '@angular/router';
/** rxjs Imports */
@@ -13,10 +13,7 @@ import { ProductsService } from '../products.service';
*/
@Injectable()
export class FloatingRateResolver {
/**
* @param {ProductsService} productsService Products service.
*/
constructor(private productsService: ProductsService) {}
private productsService = inject(ProductsService);
/**
* Returns the floating rate data.
@@ -30,44 +30,48 @@
{{ 'labels.inputs.Is Base Lending Rate' | translate }}?
</th>
<td mat-cell *matCellDef="let floatingRate">
<fa-icon
*ngIf="floatingRate.isBaseLendingRate"
icon="check-circle"
size="lg"
class="is-base-lending-rate-or-active"
matTooltip="{{ 'tooltips.Yes' | translate }}"
matTooltipPosition="right"
></fa-icon>
<fa-icon
*ngIf="!floatingRate.isBaseLendingRate"
icon="times-circle"
size="lg"
class="not-is-base-lending-rate-or-active"
matTooltip="{{ 'tooltips.No' | translate }}"
matTooltipPosition="right"
></fa-icon>
@if (floatingRate.isBaseLendingRate) {
<fa-icon
icon="check-circle"
size="lg"
class="is-base-lending-rate-or-active"
matTooltip="{{ 'tooltips.Yes' | translate }}"
matTooltipPosition="right"
></fa-icon>
}
@if (!floatingRate.isBaseLendingRate) {
<fa-icon
icon="times-circle"
size="lg"
class="not-is-base-lending-rate-or-active"
matTooltip="{{ 'tooltips.No' | translate }}"
matTooltipPosition="right"
></fa-icon>
}
</td>
</ng-container>
<ng-container matColumnDef="isActive">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'labels.catalogs.Active' | translate }}</th>
<td mat-cell *matCellDef="let floatingRate">
<fa-icon
*ngIf="floatingRate.isActive"
icon="check-circle"
size="lg"
class="is-base-lending-rate-or-active"
matTooltip="{{ 'tooltips.Yes' | translate }}"
matTooltipPosition="right"
></fa-icon>
<fa-icon
*ngIf="!floatingRate.isActive"
icon="times-circle"
size="lg"
class="not-is-base-lending-rate-or-active"
matTooltip="{{ 'tooltips.No' | translate }}"
matTooltipPosition="right"
></fa-icon>
@if (floatingRate.isActive) {
<fa-icon
icon="check-circle"
size="lg"
class="is-base-lending-rate-or-active"
matTooltip="{{ 'tooltips.Yes' | translate }}"
matTooltipPosition="right"
></fa-icon>
}
@if (!floatingRate.isActive) {
<fa-icon
icon="times-circle"
size="lg"
class="not-is-base-lending-rate-or-active"
matTooltip="{{ 'tooltips.No' | translate }}"
matTooltipPosition="right"
></fa-icon>
}
</td>
</ng-container>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, OnInit, ViewChild, inject } from '@angular/core';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort, MatSortHeader } from '@angular/material/sort';
@@ -47,6 +47,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class FloatingRatesComponent implements OnInit {
private route = inject(ActivatedRoute);
/** Floating Rates data. */
floatingRatesData: any;
/** Columns to be displayed in floating rates table. */
@@ -68,7 +70,7 @@ export class FloatingRatesComponent implements OnInit {
* Retrieves the floating rates data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
*/
constructor(private route: ActivatedRoute) {
constructor() {
this.route.data.subscribe((data: { floatingrates: any }) => {
this.floatingRatesData = data.floatingrates;
});
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
/** rxjs Imports */
import { Observable } from 'rxjs';
@@ -12,10 +12,7 @@ import { ProductsService } from '../products.service';
*/
@Injectable()
export class FloatingRatesResolver {
/**
* @param {ProductsService} productsService Products service.
*/
constructor(private productsService: ProductsService) {}
private productsService = inject(ProductsService);
/**
* Returns the floating rates data.
@@ -53,22 +53,24 @@
{{ 'labels.inputs.Is Differential' | translate }}?
</th>
<td mat-cell *matCellDef="let floatingRate">
<fa-icon
*ngIf="floatingRate.isDifferentialToBaseLendingRate"
icon="check-circle"
size="lg"
class="is-differential"
matTooltip="{{ 'tooltips.Yes' | translate }}"
matTooltipPosition="right"
></fa-icon>
<fa-icon
*ngIf="!floatingRate.isDifferentialToBaseLendingRate"
icon="times-circle"
size="lg"
class="not-is-differential"
matTooltip="{{ 'tooltips.No' | translate }}"
matTooltipPosition="right"
></fa-icon>
@if (floatingRate.isDifferentialToBaseLendingRate) {
<fa-icon
icon="check-circle"
size="lg"
class="is-differential"
matTooltip="{{ 'tooltips.Yes' | translate }}"
matTooltipPosition="right"
></fa-icon>
}
@if (!floatingRate.isDifferentialToBaseLendingRate) {
<fa-icon
icon="times-circle"
size="lg"
class="not-is-differential"
matTooltip="{{ 'tooltips.No' | translate }}"
matTooltipPosition="right"
></fa-icon>
}
</td>
</ng-container>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, OnInit, ViewChild, inject } from '@angular/core';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort, MatSortHeader } from '@angular/material/sort';
@@ -18,7 +18,7 @@ import {
} from '@angular/material/table';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { MatDivider } from '@angular/material/divider';
import { NgIf, DecimalPipe } from '@angular/common';
import { DecimalPipe } from '@angular/common';
import { MatTooltip } from '@angular/material/tooltip';
import { DateFormatPipe } from '../../../pipes/date-format.pipe';
import { YesnoPipe } from '../../../pipes/yesno.pipe';
@@ -55,6 +55,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class ViewFloatingRateComponent implements OnInit {
private route = inject(ActivatedRoute);
/** Floating Rate Data. */
floatingRateData: any;
/** Columns to be displayed in floating rate periods table. */
@@ -75,7 +77,7 @@ export class ViewFloatingRateComponent implements OnInit {
* Retrieves the floating rate data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
*/
constructor(private route: ActivatedRoute) {
constructor() {
this.route.data.subscribe((data: { floatingRate: any }) => {
this.floatingRateData = data.floatingRate;
});
@@ -1,4 +1,4 @@
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { Component, Input, OnChanges, OnInit, SimpleChanges, inject } from '@angular/core';
import { AccountingMappingDTO, DelinquencyBucket, LoanProduct } from '../../models/loan-product.model';
import {
AccountingMapping,
@@ -71,6 +71,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class LoanProductSummaryComponent implements OnInit, OnChanges {
private accounting = inject(Accounting);
@Input() action: string;
@Input() loanProduct: LoanProduct;
@Input() loanProductsTemplate: any | null;
@@ -119,8 +121,6 @@ export class LoanProductSummaryComponent implements OnInit, OnChanges {
capitalizedIncomeClassificationToIncomeAccountMappings: ClassificationToIncomeAccountMapping[] = [];
writeOffReasonsToExpenseMappings: ChargeOffReasonToExpenseAccountMapping[] = [];
constructor(private accounting: Accounting) {}
ngOnInit() {
this.accountingRuleData = this.accounting.getAccountingRulesForLoans();
this.setCurrentValues();
@@ -53,34 +53,35 @@
</mifosx-loan-product-settings-step>
</mat-step>
<mat-step *ngIf="isAdvancedPaymentStrategy" [stepControl]="loanProductInterestRefundForm">
<ng-template matStepLabel>{{ 'labels.inputs.INTEREST REFUND' | translate }}</ng-template>
<mifosx-loan-product-interest-refund-step
[loanProductsTemplate]="loanProductsTemplate"
(supportedInterestRefundTypes)="setSupportedInterestRefundTypes($event)"
>
</mifosx-loan-product-interest-refund-step>
@if (isAdvancedPaymentStrategy) {
<mat-step [stepControl]="loanProductInterestRefundForm">
<ng-template matStepLabel>{{ 'labels.inputs.INTEREST REFUND' | translate }}</ng-template>
<mifosx-loan-product-interest-refund-step
[loanProductsTemplate]="loanProductsTemplate"
(supportedInterestRefundTypes)="setSupportedInterestRefundTypes($event)"
>
</mifosx-loan-product-interest-refund-step>
<mifosx-stepper-buttons></mifosx-stepper-buttons>
</mat-step>
}
<mifosx-stepper-buttons></mifosx-stepper-buttons>
</mat-step>
<mat-step *ngIf="isAdvancedPaymentStrategy">
<ng-template matStepLabel>{{ 'labels.inputs.PAYMENT ALLOCATION' | translate }}</ng-template>
<mifosx-loan-product-payment-strategy-step
[advancedPaymentAllocations]="advancedPaymentAllocations"
[advancedCreditAllocations]="advancedCreditAllocations"
[advancedPaymentAllocationTransactionTypes]="loanProductsTemplate.advancedPaymentAllocationTransactionTypes"
[paymentAllocationOrderDefault]="loanProductsTemplate.advancedPaymentAllocationTypes"
[advancedCreditAllocationTransactionTypes]="loanProductsTemplate.creditAllocationTransactionTypes"
[creditAllocationOrderDefault]="loanProductsTemplate.creditAllocationAllocationTypes"
(setPaymentAllocation)="setPaymentAllocation($event)"
(setCreditAllocation)="setCreditAllocation($event)"
>
</mifosx-loan-product-payment-strategy-step>
<mifosx-stepper-buttons></mifosx-stepper-buttons>
</mat-step>
@if (isAdvancedPaymentStrategy) {
<mat-step>
<ng-template matStepLabel>{{ 'labels.inputs.PAYMENT ALLOCATION' | translate }}</ng-template>
<mifosx-loan-product-payment-strategy-step
[advancedPaymentAllocations]="advancedPaymentAllocations"
[advancedCreditAllocations]="advancedCreditAllocations"
[advancedPaymentAllocationTransactionTypes]="loanProductsTemplate.advancedPaymentAllocationTransactionTypes"
[paymentAllocationOrderDefault]="loanProductsTemplate.advancedPaymentAllocationTypes"
[advancedCreditAllocationTransactionTypes]="loanProductsTemplate.creditAllocationTransactionTypes"
[creditAllocationOrderDefault]="loanProductsTemplate.creditAllocationAllocationTypes"
(setPaymentAllocation)="setPaymentAllocation($event)"
(setCreditAllocation)="setCreditAllocation($event)"
>
</mifosx-loan-product-payment-strategy-step>
<mifosx-stepper-buttons></mifosx-stepper-buttons>
</mat-step>
}
<mat-step [stepControl]="loanProductTermsForm">
<ng-template matStepLabel>{{ 'labels.inputs.TERMS' | translate }}</ng-template>
@@ -99,22 +100,23 @@
</mifosx-loan-product-charges-step>
</mat-step>
<mat-step *ngIf="isAdvancedPaymentStrategy" [stepControl]="loanIncomeCapitalizationForm">
<ng-template matStepLabel>{{ 'labels.inputs.DEFERRED INCOME RECOGNITION' | translate }}</ng-template>
<mifosx-loan-product-capitalized-income-step
[deferredIncomeRecognition]="deferredIncomeRecognition"
[capitalizedIncomeCalculationTypeOptions]="loanProductsTemplate.capitalizedIncomeCalculationTypeOptions"
[capitalizedIncomeStrategyOptions]="loanProductsTemplate.capitalizedIncomeStrategyOptions"
[capitalizedIncomeTypeOptions]="loanProductsTemplate.capitalizedIncomeTypeOptions"
[buyDownFeeCalculationTypeOptions]="loanProductsTemplate.buyDownFeeCalculationTypeOptions"
[buyDownFeeStrategyOptions]="loanProductsTemplate.buyDownFeeStrategyOptions"
[buyDownFeeIncomeTypeOptions]="loanProductsTemplate.buyDownFeeIncomeTypeOptions"
(setViewChildForm)="setViewChildForm($event)"
>
</mifosx-loan-product-capitalized-income-step>
<mifosx-stepper-buttons></mifosx-stepper-buttons>
</mat-step>
@if (isAdvancedPaymentStrategy) {
<mat-step [stepControl]="loanIncomeCapitalizationForm">
<ng-template matStepLabel>{{ 'labels.inputs.DEFERRED INCOME RECOGNITION' | translate }}</ng-template>
<mifosx-loan-product-capitalized-income-step
[deferredIncomeRecognition]="deferredIncomeRecognition"
[capitalizedIncomeCalculationTypeOptions]="loanProductsTemplate.capitalizedIncomeCalculationTypeOptions"
[capitalizedIncomeStrategyOptions]="loanProductsTemplate.capitalizedIncomeStrategyOptions"
[capitalizedIncomeTypeOptions]="loanProductsTemplate.capitalizedIncomeTypeOptions"
[buyDownFeeCalculationTypeOptions]="loanProductsTemplate.buyDownFeeCalculationTypeOptions"
[buyDownFeeStrategyOptions]="loanProductsTemplate.buyDownFeeStrategyOptions"
[buyDownFeeIncomeTypeOptions]="loanProductsTemplate.buyDownFeeIncomeTypeOptions"
(setViewChildForm)="setViewChildForm($event)"
>
</mifosx-loan-product-capitalized-income-step>
<mifosx-stepper-buttons></mifosx-stepper-buttons>
</mat-step>
}
<mat-step [stepControl]="loanProductAccountingForm">
<ng-template matStepLabel>{{ 'labels.inputs.ACCOUNTING' | translate }}</ng-template>
@@ -128,16 +130,17 @@
</mifosx-loan-product-accounting-step>
</mat-step>
<mat-step state="preview" *ngIf="loanProductFormValid" completed>
<ng-template matStepLabel>{{ 'labels.inputs.PREVIEW' | translate }}</ng-template>
<mifosx-loan-product-preview-step
[loanProductsTemplate]="loanProductsTemplate"
[accountingRuleData]="accountingRuleData"
[loanProduct]="loanProduct"
(submitEvent)="submit()"
>
</mifosx-loan-product-preview-step>
</mat-step>
@if (loanProductFormValid) {
<mat-step state="preview" completed>
<ng-template matStepLabel>{{ 'labels.inputs.PREVIEW' | translate }}</ng-template>
<mifosx-loan-product-preview-step
[loanProductsTemplate]="loanProductsTemplate"
[accountingRuleData]="accountingRuleData"
[loanProduct]="loanProduct"
(submitEvent)="submit()"
>
</mifosx-loan-product-preview-step>
</mat-step>
}
</mat-stepper>
</div>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, OnInit, ViewChild, inject } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
/** Custom Components */
@@ -58,6 +58,13 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class CreateLoanProductComponent implements OnInit {
private route = inject(ActivatedRoute);
private productsService = inject(ProductsService);
private loanProducts = inject(LoanProducts);
private router = inject(Router);
private accounting = inject(Accounting);
private advancedPaymentStrategy = inject(AdvancedPaymentStrategy);
@ViewChild(LoanProductDetailsStepComponent, { static: true }) loanProductDetailsStep: LoanProductDetailsStepComponent;
@ViewChild(LoanProductCurrencyStepComponent, { static: true })
loanProductCurrencyStep: LoanProductCurrencyStepComponent;
@@ -92,14 +99,9 @@ export class CreateLoanProductComponent implements OnInit {
* @param {LoanProducts} loanProducts LoanProducts
* @param {Router} router Router for navigation.
*/
constructor(
private route: ActivatedRoute,
private productsService: ProductsService,
private loanProducts: LoanProducts,
private router: Router,
private accounting: Accounting,
private advancedPaymentStrategy: AdvancedPaymentStrategy
) {
constructor() {
const loanProducts = this.loanProducts;
this.route.data.subscribe((data: { loanProductsTemplate: any; configurations: any }) => {
this.loanProductsTemplate = data.loanProductsTemplate;
const assetAccountData = this.loanProductsTemplate.accountingMappingOptions.assetAccountOptions || [];
@@ -53,34 +53,35 @@
</mifosx-loan-product-settings-step>
</mat-step>
<mat-step *ngIf="isAdvancedPaymentStrategy" [stepControl]="loanProductInterestRefundForm" completed>
<ng-template matStepLabel>{{ 'labels.inputs.INTEREST REFUND' | translate }}</ng-template>
<mifosx-loan-product-interest-refund-step
[loanProductsTemplate]="loanProductAndTemplate"
(supportedInterestRefundTypes)="setSupportedInterestRefundTypes($event)"
>
</mifosx-loan-product-interest-refund-step>
@if (isAdvancedPaymentStrategy) {
<mat-step [stepControl]="loanProductInterestRefundForm" completed>
<ng-template matStepLabel>{{ 'labels.inputs.INTEREST REFUND' | translate }}</ng-template>
<mifosx-loan-product-interest-refund-step
[loanProductsTemplate]="loanProductAndTemplate"
(supportedInterestRefundTypes)="setSupportedInterestRefundTypes($event)"
>
</mifosx-loan-product-interest-refund-step>
<mifosx-stepper-buttons></mifosx-stepper-buttons>
</mat-step>
}
<mifosx-stepper-buttons></mifosx-stepper-buttons>
</mat-step>
<mat-step *ngIf="isAdvancedPaymentStrategy" completed>
<ng-template matStepLabel>{{ 'labels.inputs.PAYMENT ALLOCATION' | translate }}</ng-template>
<mifosx-loan-product-payment-strategy-step
[advancedPaymentAllocations]="advancedPaymentAllocations"
[advancedCreditAllocations]="advancedCreditAllocations"
[advancedPaymentAllocationTransactionTypes]="loanProductAndTemplate.advancedPaymentAllocationTransactionTypes"
[paymentAllocationOrderDefault]="loanProductAndTemplate.advancedPaymentAllocationTypes"
[advancedCreditAllocationTransactionTypes]="loanProductAndTemplate.creditAllocationTransactionTypes"
[creditAllocationOrderDefault]="loanProductAndTemplate.creditAllocationAllocationTypes"
(setPaymentAllocation)="setPaymentAllocation($event)"
(setCreditAllocation)="setCreditAllocation($event)"
>
</mifosx-loan-product-payment-strategy-step>
<mifosx-stepper-buttons></mifosx-stepper-buttons>
</mat-step>
@if (isAdvancedPaymentStrategy) {
<mat-step completed>
<ng-template matStepLabel>{{ 'labels.inputs.PAYMENT ALLOCATION' | translate }}</ng-template>
<mifosx-loan-product-payment-strategy-step
[advancedPaymentAllocations]="advancedPaymentAllocations"
[advancedCreditAllocations]="advancedCreditAllocations"
[advancedPaymentAllocationTransactionTypes]="loanProductAndTemplate.advancedPaymentAllocationTransactionTypes"
[paymentAllocationOrderDefault]="loanProductAndTemplate.advancedPaymentAllocationTypes"
[advancedCreditAllocationTransactionTypes]="loanProductAndTemplate.creditAllocationTransactionTypes"
[creditAllocationOrderDefault]="loanProductAndTemplate.creditAllocationAllocationTypes"
(setPaymentAllocation)="setPaymentAllocation($event)"
(setCreditAllocation)="setCreditAllocation($event)"
>
</mifosx-loan-product-payment-strategy-step>
<mifosx-stepper-buttons></mifosx-stepper-buttons>
</mat-step>
}
<mat-step [stepControl]="loanProductTermsForm" completed>
<ng-template matStepLabel>{{ 'labels.inputs.TERMS' | translate }}</ng-template>
@@ -99,23 +100,23 @@
</mifosx-loan-product-charges-step>
</mat-step>
<mat-step *ngIf="isAdvancedPaymentStrategy" [stepControl]="loanIncomeCapitalizationForm" completed>
<ng-template matStepLabel>{{ 'labels.inputs.DEFERRED INCOME RECOGNITION' | translate }}</ng-template>
<mifosx-loan-product-capitalized-income-step
[deferredIncomeRecognition]="deferredIncomeRecognition"
[capitalizedIncomeCalculationTypeOptions]="loanProductAndTemplate.capitalizedIncomeCalculationTypeOptions"
[capitalizedIncomeStrategyOptions]="loanProductAndTemplate.capitalizedIncomeStrategyOptions"
[capitalizedIncomeTypeOptions]="loanProductAndTemplate.capitalizedIncomeTypeOptions"
[buyDownFeeCalculationTypeOptions]="loanProductAndTemplate.buyDownFeeCalculationTypeOptions"
[buyDownFeeStrategyOptions]="loanProductAndTemplate.buyDownFeeStrategyOptions"
[buyDownFeeIncomeTypeOptions]="loanProductAndTemplate.buyDownFeeIncomeTypeOptions"
(setViewChildForm)="setViewChildForm($event)"
>
</mifosx-loan-product-capitalized-income-step>
<mifosx-stepper-buttons></mifosx-stepper-buttons>
</mat-step>
@if (isAdvancedPaymentStrategy) {
<mat-step [stepControl]="loanIncomeCapitalizationForm" completed>
<ng-template matStepLabel>{{ 'labels.inputs.DEFERRED INCOME RECOGNITION' | translate }}</ng-template>
<mifosx-loan-product-capitalized-income-step
[deferredIncomeRecognition]="deferredIncomeRecognition"
[capitalizedIncomeCalculationTypeOptions]="loanProductAndTemplate.capitalizedIncomeCalculationTypeOptions"
[capitalizedIncomeStrategyOptions]="loanProductAndTemplate.capitalizedIncomeStrategyOptions"
[capitalizedIncomeTypeOptions]="loanProductAndTemplate.capitalizedIncomeTypeOptions"
[buyDownFeeCalculationTypeOptions]="loanProductAndTemplate.buyDownFeeCalculationTypeOptions"
[buyDownFeeStrategyOptions]="loanProductAndTemplate.buyDownFeeStrategyOptions"
[buyDownFeeIncomeTypeOptions]="loanProductAndTemplate.buyDownFeeIncomeTypeOptions"
(setViewChildForm)="setViewChildForm($event)"
>
</mifosx-loan-product-capitalized-income-step>
<mifosx-stepper-buttons></mifosx-stepper-buttons>
</mat-step>
}
<mat-step [stepControl]="loanProductAccountingForm" completed>
<ng-template matStepLabel>{{ 'labels.inputs.ACCOUNTING' | translate }}</ng-template>
@@ -129,16 +130,17 @@
</mifosx-loan-product-accounting-step>
</mat-step>
<mat-step state="preview" *ngIf="loanProductFormValidAndNotPristine" completed>
<ng-template matStepLabel>{{ 'labels.inputs.PREVIEW' | translate }}</ng-template>
<mifosx-loan-product-preview-step
[loanProductsTemplate]="loanProductAndTemplate"
[accountingRuleData]="accountingRuleData"
[loanProduct]="loanProduct"
(submitEvent)="submit()"
>
</mifosx-loan-product-preview-step>
</mat-step>
@if (loanProductFormValidAndNotPristine) {
<mat-step state="preview" completed>
<ng-template matStepLabel>{{ 'labels.inputs.PREVIEW' | translate }}</ng-template>
<mifosx-loan-product-preview-step
[loanProductsTemplate]="loanProductAndTemplate"
[accountingRuleData]="accountingRuleData"
[loanProduct]="loanProduct"
(submitEvent)="submit()"
>
</mifosx-loan-product-preview-step>
</mat-step>
}
</mat-stepper>
</div>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, OnInit, ViewChild, inject } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
/** Custom Components */
@@ -61,6 +61,13 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class EditLoanProductComponent implements OnInit {
private route = inject(ActivatedRoute);
private productsService = inject(ProductsService);
private loanProducts = inject(LoanProducts);
private router = inject(Router);
private accounting = inject(Accounting);
private advancedPaymentStrategy = inject(AdvancedPaymentStrategy);
@ViewChild(LoanProductDetailsStepComponent, { static: true }) loanProductDetailsStep: LoanProductDetailsStepComponent;
@ViewChild(LoanProductCurrencyStepComponent, { static: true })
loanProductCurrencyStep: LoanProductCurrencyStepComponent;
@@ -97,14 +104,9 @@ export class EditLoanProductComponent implements OnInit {
* @param {Router} router Router for navigation.
*/
constructor(
private route: ActivatedRoute,
private productsService: ProductsService,
private loanProducts: LoanProducts,
private router: Router,
private accounting: Accounting,
private advancedPaymentStrategy: AdvancedPaymentStrategy
) {
constructor() {
const loanProducts = this.loanProducts;
this.route.data.subscribe((data: { loanProductAndTemplate: any; configurations: any }) => {
this.loanProductAndTemplate = data.loanProductAndTemplate;
const assetAccountData = this.loanProductAndTemplate.accountingMappingOptions.assetAccountOptions || [];
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
import { ActivatedRouteSnapshot } from '@angular/router';
/** rxjs Imports */
@@ -13,10 +13,7 @@ import { ProductsService } from '../../products.service';
*/
@Injectable()
export class LoanProductAndTemplateResolver {
/**
* @param {ProductsService} productsService Products service.
*/
constructor(private productsService: ProductsService) {}
private productsService = inject(ProductsService);
/**
* Returns the loan product and template data.
@@ -1,4 +1,4 @@
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
import { ActivatedRouteSnapshot } from '@angular/router';
import { SystemService } from 'app/system/system.service';
import { Observable } from 'rxjs';
@@ -7,10 +7,7 @@ import { Observable } from 'rxjs';
providedIn: 'root'
})
export class LoanProductDatatableResolver {
/**
* @param {SystemService} systemService Products service.
*/
constructor(private systemService: SystemService) {}
private systemService = inject(SystemService);
/**
* Returns the loan product data.
@@ -1,4 +1,4 @@
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
import { ActivatedRouteSnapshot } from '@angular/router';
import { SystemService } from 'app/system/system.service';
import { Observable } from 'rxjs';
@@ -7,10 +7,7 @@ import { Observable } from 'rxjs';
providedIn: 'root'
})
export class LoanProductDatatablesResolver {
/**
* @param {SystemService} systemService Products service.
*/
constructor(private systemService: SystemService) {}
private systemService = inject(SystemService);
/**
* Returns the loan product data.
@@ -9,32 +9,31 @@
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
<table class="flex-98 mat-elevation-z1" mat-table [dataSource]="tableData" *ngIf="tableData.length !== 0">
<ng-container matColumnDef="codeValueId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.' + textField | translate }}</th>
<td mat-cell *matCellDef="let item">
{{ item.value.name }}
</td>
</ng-container>
<ng-container matColumnDef="glAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.GL Account Name or Code' | translate }}</th>
<td mat-cell *matCellDef="let item">({{ item.glAccount.glCode }}) {{ item.glAccount.name }}</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let item; let i = index">
<button mat-icon-button color="primary" (click)="edit(item, i)">
<fa-icon icon="edit"></fa-icon>
</button>
<button mat-icon-button color="warn" (click)="delete(i)">
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="tableDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: tableDisplayedColumns"></tr>
</table>
@if (tableData.length !== 0) {
<table class="flex-98 mat-elevation-z1" mat-table [dataSource]="tableData">
<ng-container matColumnDef="codeValueId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.' + textField | translate }}</th>
<td mat-cell *matCellDef="let item">
{{ item.value.name }}
</td>
</ng-container>
<ng-container matColumnDef="glAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.GL Account Name or Code' | translate }}</th>
<td mat-cell *matCellDef="let item">({{ item.glAccount.glCode }}) {{ item.glAccount.name }}</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let item; let i = index">
<button mat-icon-button color="primary" (click)="edit(item, i)">
<fa-icon icon="edit"></fa-icon>
</button>
<button mat-icon-button color="warn" (click)="delete(i)">
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="tableDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: tableDisplayedColumns"></tr>
</table>
}
</div>
@@ -1,4 +1,4 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core';
import { UntypedFormArray } from '@angular/forms';
import { MatIconButton } from '@angular/material/button';
import { MatDialog } from '@angular/material/dialog';
@@ -45,6 +45,9 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
styleUrl: './advanced-accounting-mapping-rule.component.scss'
})
export class AdvancedAccountingMappingRuleComponent implements OnInit {
dialog = inject(MatDialog);
translateService = inject(TranslateService);
@Input() formType: string;
@Input() formArray: UntypedFormArray;
@Input() textHeading: string;
@@ -73,11 +76,6 @@ export class AdvancedAccountingMappingRuleComponent implements OnInit {
'actions'
];
constructor(
public dialog: MatDialog,
public translateService: TranslateService
) {}
ngOnInit(): void {
this.tableData = this.formArray?.value || [];
this.sendParentData();
@@ -137,7 +135,8 @@ export class AdvancedAccountingMappingRuleComponent implements OnInit {
let newData = [
...this.tableData.slice(0, index),
updatedData,
...this.tableData.slice(index + 1)];
...this.tableData.slice(index + 1)
];
this.tableData = newData;
}
@@ -261,7 +260,6 @@ export class AdvancedAccountingMappingRuleComponent implements OnInit {
required: true,
order: 2
})
];
return formfields;
}
@@ -284,7 +282,6 @@ export class AdvancedAccountingMappingRuleComponent implements OnInit {
required: true,
order: 2
})
];
return formfields;
}
@@ -307,7 +304,6 @@ export class AdvancedAccountingMappingRuleComponent implements OnInit {
required: true,
order: 2
})
];
return formfields;
}
@@ -333,7 +329,6 @@ export class AdvancedAccountingMappingRuleComponent implements OnInit {
required: true,
order: 2
})
];
return formfields;
}
@@ -359,7 +354,6 @@ export class AdvancedAccountingMappingRuleComponent implements OnInit {
required: true,
order: 2
})
];
return formfields;
}
@@ -4,551 +4,493 @@
class="flex-98 layout-row gap-5percent layout-lt-md-column radio-group-spacing"
formControlName="accountingRule"
>
<mat-radio-button *ngFor="let accountingRule of accountingRuleData; let i = index" [value]="i + 1">
{{ 'labels.accounting.' + accountingRule | translate }}
</mat-radio-button>
@for (accountingRule of accountingRuleData; track accountingRule; let i = $index) {
<mat-radio-button [value]="i + 1">
{{ 'labels.accounting.' + accountingRule | translate }}
</mat-radio-button>
}
</mat-radio-group>
<mat-divider class="flex-98"></mat-divider>
<div
*ngIf="loanProductAccountingForm.value.accountingRule >= 2 && loanProductAccountingForm.value.accountingRule <= 4"
class="flex-100 layout-row-wrap responsive-column"
>
<mat-checkbox *ngIf="isAccountingAccrualBased" class="flex-73" formControlName="enableAccrualActivityPosting">{{
'labels.inputs.Enable Accrual Activity Posting on Installment Due Date' | translate
}}</mat-checkbox>
<h4 class="mat-h4 flex-98">
{{ 'labels.heading.Assets' | translate }} / {{ 'labels.heading.Liabilities' | translate }}
</h4>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.fundSourceAccountId"
[glAccountList]="assetAndLiabilityAccountData"
[required]="true"
[inputLabel]="'Fund source'"
>
</mifosx-gl-account-selector>
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Assets' | translate }}</h4>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.loanPortfolioAccountId"
[glAccountList]="assetAccountData"
[required]="true"
[inputLabel]="'Loan portfolio'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.transfersInSuspenseAccountId"
[glAccountList]="assetAccountData"
[required]="true"
[inputLabel]="'Transfer in suspense'"
>
</mifosx-gl-account-selector>
<div
*ngIf="
@if (loanProductAccountingForm.value.accountingRule >= 2 && loanProductAccountingForm.value.accountingRule <= 4) {
<div class="flex-100 layout-row-wrap responsive-column">
@if (isAccountingAccrualBased) {
<mat-checkbox class="flex-73" formControlName="enableAccrualActivityPosting">{{
'labels.inputs.Enable Accrual Activity Posting on Installment Due Date' | translate
}}</mat-checkbox>
}
<h4 class="mat-h4 flex-98">
{{ 'labels.heading.Assets' | translate }} / {{ 'labels.heading.Liabilities' | translate }}
</h4>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.fundSourceAccountId"
[glAccountList]="assetAndLiabilityAccountData"
[required]="true"
[inputLabel]="'Fund source'"
>
</mifosx-gl-account-selector>
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Assets' | translate }}</h4>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.loanPortfolioAccountId"
[glAccountList]="assetAccountData"
[required]="true"
[inputLabel]="'Loan portfolio'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.transfersInSuspenseAccountId"
[glAccountList]="assetAccountData"
[required]="true"
[inputLabel]="'Transfer in suspense'"
>
</mifosx-gl-account-selector>
@if (
loanProductAccountingForm.value.accountingRule === 3 || loanProductAccountingForm.value.accountingRule === 4
"
class="flex-100 layout-row-wrap responsive-column"
>
) {
<div class="flex-100 layout-row-wrap responsive-column">
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.receivableInterestAccountId"
[glAccountList]="assetAccountData"
[required]="true"
[inputLabel]="'Interest Receivable'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.receivableFeeAccountId"
[glAccountList]="assetAccountData"
[required]="true"
[inputLabel]="'Fees Receivable'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.receivablePenaltyAccountId"
[glAccountList]="assetAccountData"
[required]="true"
[inputLabel]="'Penalties Receivable'"
>
</mifosx-gl-account-selector>
</div>
}
<mat-divider class="flex-98"></mat-divider>
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Income' | translate }}</h4>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.receivableInterestAccountId"
[glAccountList]="assetAccountData"
[inputFormControl]="loanProductAccountingForm.controls.interestOnLoanAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Interest Receivable'"
[inputLabel]="'Income from Interest'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.receivableFeeAccountId"
[glAccountList]="assetAccountData"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromFeeAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Fees Receivable'"
[inputLabel]="'Income from fees'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.receivablePenaltyAccountId"
[glAccountList]="assetAccountData"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromPenaltyAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Penalties Receivable'"
[inputLabel]="'Income from penalties'"
>
</mifosx-gl-account-selector>
</div>
<mat-divider class="flex-98"></mat-divider>
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Income' | translate }}</h4>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.interestOnLoanAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from Interest'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromFeeAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from fees'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromPenaltyAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from penalties'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromRecoveryAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from Recovery Repayments'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromChargeOffInterestAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from ChargeOff Interest'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromChargeOffFeesAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from ChargeOff Fees'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromChargeOffPenaltyAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from ChargeOff Penalty'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromGoodwillCreditInterestAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from Goodwill Credit Interest'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromGoodwillCreditFeesAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from Goodwill Credit Fees'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromGoodwillCreditPenaltyAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from Goodwill Credit Penalty'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
*ngIf="deferredIncomeRecognition?.capitalizedIncome?.enableIncomeCapitalization"
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromCapitalizationAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income capitalization'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
*ngIf="deferredIncomeRecognition?.buyDownFee?.enableBuyDownFee"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromBuyDownAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from Buy down fees'"
>
</mifosx-gl-account-selector>
<mat-divider class="flex-98"></mat-divider>
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Expenses' | translate }}</h4>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.writeOffAccountId"
[glAccountList]="expenseAccountData"
[required]="true"
[inputLabel]="'Losses written off'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.goodwillCreditAccountId"
[glAccountList]="expenseAccountData"
[required]="true"
[inputLabel]="'Expenses from Goodwill Credit'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.chargeOffExpenseAccountId"
[glAccountList]="expenseAccountData"
[required]="true"
[inputLabel]="'ChargeOff Expense'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.chargeOffFraudExpenseAccountId"
[glAccountList]="expenseAccountData"
[required]="true"
[inputLabel]="'ChargeOff Fraud Expense'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
*ngIf="
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromRecoveryAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from Recovery Repayments'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromChargeOffInterestAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from ChargeOff Interest'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromChargeOffFeesAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from ChargeOff Fees'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromChargeOffPenaltyAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from ChargeOff Penalty'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromGoodwillCreditInterestAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from Goodwill Credit Interest'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromGoodwillCreditFeesAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from Goodwill Credit Fees'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromGoodwillCreditPenaltyAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from Goodwill Credit Penalty'"
>
</mifosx-gl-account-selector>
@if (deferredIncomeRecognition?.capitalizedIncome?.enableIncomeCapitalization) {
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromCapitalizationAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income capitalization'"
>
</mifosx-gl-account-selector>
}
@if (deferredIncomeRecognition?.buyDownFee?.enableBuyDownFee) {
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.incomeFromBuyDownAccountId"
[glAccountList]="incomeAccountData"
[required]="true"
[inputLabel]="'Income from Buy down fees'"
>
</mifosx-gl-account-selector>
}
<mat-divider class="flex-98"></mat-divider>
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Expenses' | translate }}</h4>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.writeOffAccountId"
[glAccountList]="expenseAccountData"
[required]="true"
[inputLabel]="'Losses written off'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.goodwillCreditAccountId"
[glAccountList]="expenseAccountData"
[required]="true"
[inputLabel]="'Expenses from Goodwill Credit'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.chargeOffExpenseAccountId"
[glAccountList]="expenseAccountData"
[required]="true"
[inputLabel]="'ChargeOff Expense'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.chargeOffFraudExpenseAccountId"
[glAccountList]="expenseAccountData"
[required]="true"
[inputLabel]="'ChargeOff Fraud Expense'"
>
</mifosx-gl-account-selector>
@if (
deferredIncomeRecognition?.buyDownFee?.enableBuyDownFee &&
deferredIncomeRecognition?.buyDownFee?.merchantBuyDownFee
"
[inputFormControl]="loanProductAccountingForm.controls.buyDownExpenseAccountId"
[glAccountList]="expenseAccountData"
[required]="true"
[inputLabel]="'Buy down fee Expense'"
>
</mifosx-gl-account-selector>
<mat-divider class="flex-98"></mat-divider>
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Liabilities' | translate }}</h4>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.overpaymentLiabilityAccountId"
[glAccountList]="liabilityAccountData"
[required]="true"
[inputLabel]="'Over payment liability'"
>
</mifosx-gl-account-selector>
<mifosx-gl-account-selector
*ngIf="
) {
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.buyDownExpenseAccountId"
[glAccountList]="expenseAccountData"
[required]="true"
[inputLabel]="'Buy down fee Expense'"
>
</mifosx-gl-account-selector>
}
<mat-divider class="flex-98"></mat-divider>
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Liabilities' | translate }}</h4>
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.overpaymentLiabilityAccountId"
[glAccountList]="liabilityAccountData"
[required]="true"
[inputLabel]="'Over payment liability'"
>
</mifosx-gl-account-selector>
@if (
deferredIncomeRecognition?.capitalizedIncome?.enableIncomeCapitalization ||
deferredIncomeRecognition?.buyDownFee?.enableBuyDownFee
"
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.deferredIncomeLiabilityAccountId"
[glAccountList]="liabilityAccountData"
[required]="true"
[inputLabel]="'Deferred income'"
>
</mifosx-gl-account-selector>
<mat-divider fxFlex="flex-98"></mat-divider>
<mat-checkbox class="flex-73" formControlName="advancedAccountingRules">{{
'labels.heading.Advanced Accounting Rules' | translate
}}</mat-checkbox>
<div
*ngIf="loanProductAccountingForm.value.advancedAccountingRules"
class="flex-100 layout-row-wrap responsive-column"
>
<h4 class="mat-h4 flex-33">
{{ 'labels.heading.Configure Fund Sources for Payment Channels' | translate }}
</h4>
<div class="flex-63">
<button
type="button"
mat-raised-button
color="primary"
(click)="add('PaymentFundSource', paymentChannelToFundSourceMappings)"
) {
<mifosx-gl-account-selector
class="flex-48"
[inputFormControl]="loanProductAccountingForm.controls.deferredIncomeLiabilityAccountId"
[glAccountList]="liabilityAccountData"
[required]="true"
[inputLabel]="'Deferred income'"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
<table
class="flex-98 mat-elevation-z1"
mat-table
[dataSource]="paymentChannelToFundSourceMappings.value"
*ngIf="paymentChannelToFundSourceMappings.value.length !== 0"
>
<ng-container matColumnDef="paymentTypeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Payment Type' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.paymentTypeId | find: paymentTypeData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="fundSourceAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Fund Source' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.fundSourceAccountId | find: assetAccountData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource; let i = index">
</mifosx-gl-account-selector>
}
<mat-divider fxFlex="flex-98"></mat-divider>
<mat-checkbox class="flex-73" formControlName="advancedAccountingRules">{{
'labels.heading.Advanced Accounting Rules' | translate
}}</mat-checkbox>
@if (loanProductAccountingForm.value.advancedAccountingRules) {
<div class="flex-100 layout-row-wrap responsive-column">
<h4 class="mat-h4 flex-33">
{{ 'labels.heading.Configure Fund Sources for Payment Channels' | translate }}
</h4>
<div class="flex-63">
<button
mat-icon-button
type="button"
mat-raised-button
color="primary"
(click)="edit('PaymentFundSource', paymentChannelToFundSourceMappings, i)"
(click)="add('PaymentFundSource', paymentChannelToFundSourceMappings)"
>
<fa-icon icon="edit"></fa-icon>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
@if (paymentChannelToFundSourceMappings.value.length !== 0) {
<table class="flex-98 mat-elevation-z1" mat-table [dataSource]="paymentChannelToFundSourceMappings.value">
<ng-container matColumnDef="paymentTypeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Payment Type' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.paymentTypeId | find: paymentTypeData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="fundSourceAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Fund Source' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.fundSourceAccountId | find: assetAccountData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let paymentFundSource; let i = index">
<button
mat-icon-button
color="primary"
(click)="edit('PaymentFundSource', paymentChannelToFundSourceMappings, i)"
>
<fa-icon icon="edit"></fa-icon>
</button>
<button
mat-icon-button
color="warn"
(click)="delete('PaymentFundSource', paymentChannelToFundSourceMappings, i)"
>
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="paymentFundSourceDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: paymentFundSourceDisplayedColumns"></tr>
</table>
}
<h4 class="mat-h4 flex-33">{{ 'labels.heading.Map Fees to Specific Income Accounts' | translate }}</h4>
<div class="flex-63">
<button
mat-icon-button
color="warn"
(click)="delete('PaymentFundSource', paymentChannelToFundSourceMappings, i)"
>
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="paymentFundSourceDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: paymentFundSourceDisplayedColumns"></tr>
</table>
<h4 class="mat-h4 flex-33">{{ 'labels.heading.Map Fees to Specific Income Accounts' | translate }}</h4>
<div class="flex-63">
<button
type="button"
mat-raised-button
color="primary"
(click)="add('FeesIncome', feeToIncomeAccountMappings)"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
<table
class="flex-98 mat-elevation-z1"
mat-table
[dataSource]="feeToIncomeAccountMappings.value"
*ngIf="feeToIncomeAccountMappings.value.length !== 0"
>
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Fees' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.chargeId | find: chargeData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.incomeAccountId | find: incomeAndLiabilityAccountData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome; let i = index">
<button mat-icon-button color="primary" (click)="edit('FeesIncome', feeToIncomeAccountMappings, i)">
<fa-icon icon="edit"></fa-icon>
</button>
<button mat-icon-button color="warn" (click)="delete('FeesIncome', feeToIncomeAccountMappings, i)">
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
</table>
<h4 class="mat-h4 flex-33">
{{ 'labels.heading.Map Penalties to Specific Income Accounts' | translate }}
</h4>
<div class="flex-63">
<button
type="button"
mat-raised-button
color="primary"
(click)="add('PenaltyIncome', penaltyToIncomeAccountMappings)"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
<table
class="flex-98 mat-elevation-z1"
mat-table
[dataSource]="penaltyToIncomeAccountMappings.value"
*ngIf="penaltyToIncomeAccountMappings.value.length !== 0"
>
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Penalty' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.chargeId | find: penaltyData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.incomeAccountId | find: incomeAccountData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome; let i = index">
<button
mat-icon-button
type="button"
mat-raised-button
color="primary"
(click)="edit('PenaltyIncome', penaltyToIncomeAccountMappings, i)"
(click)="add('FeesIncome', feeToIncomeAccountMappings)"
>
<fa-icon icon="edit"></fa-icon>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
<button mat-icon-button color="warn" (click)="delete('PenaltyIncome', penaltyToIncomeAccountMappings, i)">
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
</table>
<h4 class="mat-h4 flex-33">
{{ 'labels.heading.Map Charge-off reasons to Expense accounts' | translate }}
</h4>
<div class="flex-63">
<button
type="button"
mat-raised-button
color="primary"
[disabled]="!allowAddChargeOffReasonExpense"
(click)="add('ChargeOffReasonExpense', chargeOffReasonToExpenseAccountMappings)"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
<table
class="flex-98 mat-elevation-z1"
mat-table
[dataSource]="chargeOffReasonToExpenseAccountMappings.value"
*ngIf="chargeOffReasonToExpenseAccountMappings.value.length !== 0"
>
<ng-container matColumnDef="chargeOffReasonCodeValueId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Charge-off reason' | translate }}</th>
<td mat-cell *matCellDef="let chargeOffReasonExpense">
{{ chargeOffReasonExpense.chargeOffReasonCodeValueId | find: chargeOffReasonOptions : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="expenseAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Expense Account' | translate }}</th>
<td mat-cell *matCellDef="let chargeOffReasonExpense">
{{ chargeOffReasonExpense.expenseAccountId | find: expenseAccountData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let chargeOffReasonExpense; let i = index">
</div>
@if (feeToIncomeAccountMappings.value.length !== 0) {
<table class="flex-98 mat-elevation-z1" mat-table [dataSource]="feeToIncomeAccountMappings.value">
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Fees' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.chargeId | find: chargeData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.incomeAccountId | find: incomeAndLiabilityAccountData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let feesIncome; let i = index">
<button mat-icon-button color="primary" (click)="edit('FeesIncome', feeToIncomeAccountMappings, i)">
<fa-icon icon="edit"></fa-icon>
</button>
<button mat-icon-button color="warn" (click)="delete('FeesIncome', feeToIncomeAccountMappings, i)">
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
</table>
}
<h4 class="mat-h4 flex-33">
{{ 'labels.heading.Map Penalties to Specific Income Accounts' | translate }}
</h4>
<div class="flex-63">
<button
mat-icon-button
type="button"
mat-raised-button
color="primary"
(click)="edit('ChargeOffReasonExpense', chargeOffReasonToExpenseAccountMappings, i)"
(click)="add('PenaltyIncome', penaltyToIncomeAccountMappings)"
>
<fa-icon icon="edit"></fa-icon>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
@if (penaltyToIncomeAccountMappings.value.length !== 0) {
<table class="flex-98 mat-elevation-z1" mat-table [dataSource]="penaltyToIncomeAccountMappings.value">
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Penalty' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.chargeId | find: penaltyData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.incomeAccountId | find: incomeAccountData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let penaltyIncome; let i = index">
<button
mat-icon-button
color="primary"
(click)="edit('PenaltyIncome', penaltyToIncomeAccountMappings, i)"
>
<fa-icon icon="edit"></fa-icon>
</button>
<button
mat-icon-button
color="warn"
(click)="delete('PenaltyIncome', penaltyToIncomeAccountMappings, i)"
>
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
</table>
}
<h4 class="mat-h4 flex-33">
{{ 'labels.heading.Map Charge-off reasons to Expense accounts' | translate }}
</h4>
<div class="flex-63">
<button
mat-icon-button
color="warn"
(click)="delete('ChargeOffReasonExpense', chargeOffReasonToExpenseAccountMappings, i)"
type="button"
mat-raised-button
color="primary"
[disabled]="!allowAddChargeOffReasonExpense"
(click)="add('ChargeOffReasonExpense', chargeOffReasonToExpenseAccountMappings)"
>
<fa-icon icon="trash"></fa-icon>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chargeOffReasonExpenseDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chargeOffReasonExpenseDisplayedColumns"></tr>
</table>
<mifosx-advanced-accounting-mapping-rule
class="flex-100 m-t-10"
[textField]="'Classification'"
[formType]="'BuydownFeeClassificationToIncome'"
[formArray]="buydownfeeClassificationToIncomeAccountMappings"
[textHeading]="'Buydown Fee classifications to Income accounts'"
[incomeAccountData]="incomeAccountData"
[accountingMappingOptions]="buydownFeeClassificationOptions"
(formChangeEvent)="formChangeEvent($event)"
></mifosx-advanced-accounting-mapping-rule>
<mifosx-advanced-accounting-mapping-rule
class="flex-100 m-t-10"
[textField]="'Classification'"
[formType]="'CapitalizedIncomeClassificationToIncome'"
[formArray]="capitalizedIncomeClassificationToIncomeAccountMappings"
[textHeading]="'Capitalized Income classifications to Income accounts'"
[incomeAccountData]="incomeAccountData"
[accountingMappingOptions]="capitalizedIncomeClassificationOptions"
(formChangeEvent)="formChangeEvent($event)"
></mifosx-advanced-accounting-mapping-rule>
<mifosx-advanced-accounting-mapping-rule
class="flex-100 m-t-10"
[textField]="'WriteOff Reason'"
[formType]="'WriteOffReasonToExpense'"
[formArray]="writeOffReasonsToExpenseMappings"
[textHeading]="'WriteOff reasons to Expense accounts'"
[expenseAccountData]="expenseAccountData"
[accountingMappingOptions]="writeOffReasonOptions"
(formChangeEvent)="formChangeEvent($event)"
></mifosx-advanced-accounting-mapping-rule>
</div>
@if (chargeOffReasonToExpenseAccountMappings.value.length !== 0) {
<table
class="flex-98 mat-elevation-z1"
mat-table
[dataSource]="chargeOffReasonToExpenseAccountMappings.value"
>
<ng-container matColumnDef="chargeOffReasonCodeValueId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Charge-off reason' | translate }}</th>
<td mat-cell *matCellDef="let chargeOffReasonExpense">
{{
chargeOffReasonExpense.chargeOffReasonCodeValueId | find: chargeOffReasonOptions : 'id' : 'name'
}}
</td>
</ng-container>
<ng-container matColumnDef="expenseAccountId">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Expense Account' | translate }}</th>
<td mat-cell *matCellDef="let chargeOffReasonExpense">
{{ chargeOffReasonExpense.expenseAccountId | find: expenseAccountData : 'id' : 'name' }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let chargeOffReasonExpense; let i = index">
<button
mat-icon-button
color="primary"
(click)="edit('ChargeOffReasonExpense', chargeOffReasonToExpenseAccountMappings, i)"
>
<fa-icon icon="edit"></fa-icon>
</button>
<button
mat-icon-button
color="warn"
(click)="delete('ChargeOffReasonExpense', chargeOffReasonToExpenseAccountMappings, i)"
>
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chargeOffReasonExpenseDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chargeOffReasonExpenseDisplayedColumns"></tr>
</table>
}
<mifosx-advanced-accounting-mapping-rule
class="flex-100 m-t-10"
[textField]="'Classification'"
[formType]="'BuydownFeeClassificationToIncome'"
[formArray]="buydownfeeClassificationToIncomeAccountMappings"
[textHeading]="'Buydown Fee classifications to Income accounts'"
[incomeAccountData]="incomeAccountData"
[accountingMappingOptions]="buydownFeeClassificationOptions"
(formChangeEvent)="formChangeEvent($event)"
></mifosx-advanced-accounting-mapping-rule>
<mifosx-advanced-accounting-mapping-rule
class="flex-100 m-t-10"
[textField]="'Classification'"
[formType]="'CapitalizedIncomeClassificationToIncome'"
[formArray]="capitalizedIncomeClassificationToIncomeAccountMappings"
[textHeading]="'Capitalized Income classifications to Income accounts'"
[incomeAccountData]="incomeAccountData"
[accountingMappingOptions]="capitalizedIncomeClassificationOptions"
(formChangeEvent)="formChangeEvent($event)"
></mifosx-advanced-accounting-mapping-rule>
<mifosx-advanced-accounting-mapping-rule
class="flex-100 m-t-10"
[textField]="'WriteOff Reason'"
[formType]="'WriteOffReasonToExpense'"
[formArray]="writeOffReasonsToExpenseMappings"
[textHeading]="'WriteOff reasons to Expense accounts'"
[expenseAccountData]="expenseAccountData"
[accountingMappingOptions]="writeOffReasonOptions"
(formChangeEvent)="formChangeEvent($event)"
></mifosx-advanced-accounting-mapping-rule>
</div>
}
</div>
</div>
}
</div>
<div class="layout-row align-center margin-t responsive-column gap-2percent">
@@ -1,4 +1,4 @@
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { Component, Input, OnChanges, OnInit, SimpleChanges, inject } from '@angular/core';
import { UntypedFormArray, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
@@ -67,6 +67,10 @@ import { AccountingMappingDTO, AdvancedMappingDTO } from '../../models/loan-prod
]
})
export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
private formBuilder = inject(UntypedFormBuilder);
dialog = inject(MatDialog);
private translateService = inject(TranslateService);
@Input() loanProductsTemplate: any;
@Input() accountingRuleData: any;
@Input() loanProductFormValid: boolean;
@@ -107,11 +111,7 @@ export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
'actions'
];
constructor(
private formBuilder: UntypedFormBuilder,
public dialog: MatDialog,
private translateService: TranslateService
) {
constructor() {
this.createLoanProductAccountingForm();
this.setConditionalControls();
}
@@ -592,7 +592,6 @@ export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
required: true,
order: 2
})
];
return formfields;
}
@@ -615,7 +614,6 @@ export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
required: true,
order: 2
})
];
return formfields;
}
@@ -638,7 +636,6 @@ export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
required: true,
order: 2
})
];
return formfields;
}
@@ -662,7 +659,6 @@ export class LoanProductAccountingStepComponent implements OnInit, OnChanges {
required: true,
order: 2
})
];
return formfields;
}
@@ -4,75 +4,92 @@
{{ 'labels.inputs.Enable income capitalization' | translate }}
</mat-checkbox>
<mat-form-field class="flex-48" *ngIf="enableIncomeCapitalization">
<mat-label>{{ 'labels.inputs.Income capitalization calculation type' | translate }}</mat-label>
<mat-select formControlName="capitalizedIncomeCalculationType" required>
<mat-option
*ngFor="let capitalizedIncomeCalculationType of capitalizedIncomeCalculationTypeOptions"
[value]="capitalizedIncomeCalculationType.id"
>
{{ capitalizedIncomeCalculationType.value | translateKey: 'catalogs' }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="flex-48" *ngIf="enableIncomeCapitalization">
<mat-label>{{ 'labels.inputs.Income capitalization strategy' | translate }}</mat-label>
<mat-select formControlName="capitalizedIncomeStrategy" required>
<mat-option
*ngFor="let capitalizedIncomeStrategy of capitalizedIncomeStrategyOptions"
[value]="capitalizedIncomeStrategy.id"
>
{{ capitalizedIncomeStrategy.value | translateKey: 'catalogs' }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="flex-48" *ngIf="enableIncomeCapitalization">
<mat-label>{{ 'labels.inputs.Income type' | translate }}</mat-label>
<mat-select formControlName="capitalizedIncomeType" required>
<mat-option
*ngFor="let capitalizedIncomeType of capitalizedIncomeTypeOptions"
[value]="capitalizedIncomeType.id"
>
{{ capitalizedIncomeType.value | translateKey: 'catalogs' }}
</mat-option>
</mat-select>
</mat-form-field>
@if (enableIncomeCapitalization) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Income capitalization calculation type' | translate }}</mat-label>
<mat-select formControlName="capitalizedIncomeCalculationType" required>
@for (
capitalizedIncomeCalculationType of capitalizedIncomeCalculationTypeOptions;
track capitalizedIncomeCalculationType
) {
<mat-option [value]="capitalizedIncomeCalculationType.id">
{{ capitalizedIncomeCalculationType.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
</mat-form-field>
}
@if (enableIncomeCapitalization) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Income capitalization strategy' | translate }}</mat-label>
<mat-select formControlName="capitalizedIncomeStrategy" required>
@for (capitalizedIncomeStrategy of capitalizedIncomeStrategyOptions; track capitalizedIncomeStrategy) {
<mat-option [value]="capitalizedIncomeStrategy.id">
{{ capitalizedIncomeStrategy.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
</mat-form-field>
}
@if (enableIncomeCapitalization) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Income type' | translate }}</mat-label>
<mat-select formControlName="capitalizedIncomeType" required>
@for (capitalizedIncomeType of capitalizedIncomeTypeOptions; track capitalizedIncomeType) {
<mat-option [value]="capitalizedIncomeType.id">
{{ capitalizedIncomeType.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
</mat-form-field>
}
</div>
<div class="layout-row-wrap gap-2percent layout-column-lt-md">
<mat-checkbox class="flex-98" labelPosition="before" formControlName="enableBuyDownFee">
{{ 'labels.inputs.Enable Buy down fee' | translate }}
</mat-checkbox>
<mat-form-field class="flex-48" *ngIf="enableBuyDownFee">
<mat-label>{{ 'labels.inputs.Buy down fee calculation type' | translate }}</mat-label>
<mat-select formControlName="buyDownFeeCalculationType" required>
<mat-option
*ngFor="let buyDownFeeCalculationType of buyDownFeeCalculationTypeOptions"
[value]="buyDownFeeCalculationType.id"
>
{{ buyDownFeeCalculationType.value | translateKey: 'catalogs' }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="flex-48" *ngIf="enableBuyDownFee">
<mat-label>{{ 'labels.inputs.Buy down fee strategy' | translate }}</mat-label>
<mat-select formControlName="buyDownFeeStrategy" required>
<mat-option *ngFor="let buyDownFeeStrategy of buyDownFeeStrategyOptions" [value]="buyDownFeeStrategy.id">
{{ buyDownFeeStrategy.value | translateKey: 'catalogs' }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="flex-48" *ngIf="enableBuyDownFee">
<mat-label>{{ 'labels.inputs.Buy down fee income type' | translate }}</mat-label>
<mat-select formControlName="buyDownFeeIncomeType" required>
<mat-option *ngFor="let buyDownFeeIncomeType of buyDownFeeIncomeTypeOptions" [value]="buyDownFeeIncomeType.id">
{{ buyDownFeeIncomeType.value | translateKey: 'catalogs' }}
</mat-option>
</mat-select>
</mat-form-field>
@if (enableBuyDownFee) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Buy down fee calculation type' | translate }}</mat-label>
<mat-select formControlName="buyDownFeeCalculationType" required>
@for (buyDownFeeCalculationType of buyDownFeeCalculationTypeOptions; track buyDownFeeCalculationType) {
<mat-option [value]="buyDownFeeCalculationType.id">
{{ buyDownFeeCalculationType.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
</mat-form-field>
}
@if (enableBuyDownFee) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Buy down fee strategy' | translate }}</mat-label>
<mat-select formControlName="buyDownFeeStrategy" required>
@for (buyDownFeeStrategy of buyDownFeeStrategyOptions; track buyDownFeeStrategy) {
<mat-option [value]="buyDownFeeStrategy.id">
{{ buyDownFeeStrategy.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
</mat-form-field>
}
@if (enableBuyDownFee) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Buy down fee income type' | translate }}</mat-label>
<mat-select formControlName="buyDownFeeIncomeType" required>
@for (buyDownFeeIncomeType of buyDownFeeIncomeTypeOptions; track buyDownFeeIncomeType) {
<mat-option [value]="buyDownFeeIncomeType.id">
{{ buyDownFeeIncomeType.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
</mat-form-field>
}
<mat-checkbox class="flex-48" *ngIf="enableBuyDownFee" labelPosition="before" formControlName="merchantBuyDownFee">
{{ 'labels.inputs.Merchant Buy down fee' | translate }}
</mat-checkbox>
@if (enableBuyDownFee) {
<mat-checkbox class="flex-48" labelPosition="before" formControlName="merchantBuyDownFee">
{{ 'labels.inputs.Merchant Buy down fee' | translate }}
</mat-checkbox>
}
</div>
</form>
@@ -1,4 +1,4 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core';
import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
import { DeferredIncomeRecognition } from '../loan-product-payment-strategy-step/payment-allocation-model';
import { StringEnumOptionData } from 'app/shared/models/option-data.model';
@@ -15,6 +15,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class LoanProductDeferredIncomeRecognitionStepComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
@Input() deferredIncomeRecognition: DeferredIncomeRecognition;
@Input() capitalizedIncomeCalculationTypeOptions: StringEnumOptionData[];
@Input() capitalizedIncomeStrategyOptions: StringEnumOptionData[];
@@ -30,7 +32,7 @@ export class LoanProductDeferredIncomeRecognitionStepComponent implements OnInit
@Output() setViewChildForm = new EventEmitter<UntypedFormGroup>();
constructor(private formBuilder: UntypedFormBuilder) {
constructor() {
this.enableIncomeCapitalization =
this.deferredIncomeRecognition != null
? this.deferredIncomeRecognition.capitalizedIncome.enableIncomeCapitalization
@@ -2,14 +2,14 @@
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Charge' | translate }}</mat-label>
<mat-select #charge>
<mat-option
*ngFor="
let charge of chargeData | chargesFilter: chargesDataSource : currencyCode.value : multiDisburseLoan.value
"
[value]="charge"
>
{{ charge.name }}
</mat-option>
@for (
charge of chargeData | chargesFilter: chargesDataSource : currencyCode.value : multiDisburseLoan.value;
track charge
) {
<mat-option [value]="charge">
{{ charge.name }}
</mat-option>
}
</mat-select>
</mat-form-field>
@@ -77,12 +77,14 @@
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Overdue Charge' | translate }}</mat-label>
<mat-select #overdueCharge>
<mat-option
*ngFor="let overdueCharge of overdueChargeData | chargesFilter: chargesDataSource : currencyCode.value"
[value]="overdueCharge"
>
{{ overdueCharge.name }}
</mat-option>
@for (
overdueCharge of overdueChargeData | chargesFilter: chargesDataSource : currencyCode.value;
track overdueCharge
) {
<mat-option [value]="overdueCharge">
{{ overdueCharge.name }}
</mat-option>
}
</mat-select>
</mat-form-field>
@@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnInit, inject } from '@angular/core';
import { UntypedFormControl } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
@@ -52,6 +52,9 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class LoanProductChargesStepComponent implements OnInit {
dialog = inject(MatDialog);
private translateService = inject(TranslateService);
@Input() loanProductsTemplate: any;
@Input() currencyCode: UntypedFormControl;
@Input() multiDisburseLoan: UntypedFormControl;
@@ -70,11 +73,6 @@ export class LoanProductChargesStepComponent implements OnInit {
pristine = true;
constructor(
public dialog: MatDialog,
private translateService: TranslateService
) {}
ngOnInit() {
this.chargeData = this.loanProductsTemplate.chargeOptions;
this.overdueChargeData = this.loanProductsTemplate.penaltyOptions
@@ -7,9 +7,11 @@
matTooltip="{{ 'tooltips.The currency in which the loan will be disbursed' | translate }}"
required
>
<mat-option *ngFor="let currency of currencyData" [value]="currency.code">
{{ currency.name }}
</mat-option>
@for (currency of currencyData; track currency) {
<mat-option [value]="currency.code">
{{ currency.name }}
</mat-option>
}
</mat-select>
<mat-error>
{{ 'labels.inputs.Currency' | translate }} {{ 'labels.commons.is' | translate }}
@@ -1,4 +1,4 @@
import { Component, OnInit, Input } from '@angular/core';
import { Component, OnInit, Input, inject } from '@angular/core';
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
import { MatTooltip } from '@angular/material/tooltip';
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
@@ -18,13 +18,15 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class LoanProductCurrencyStepComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
@Input() loanProductsTemplate: any;
loanProductCurrencyForm: UntypedFormGroup;
currencyData: any;
constructor(private formBuilder: UntypedFormBuilder) {
constructor() {
this.createLoanProductCurrencyForm();
}
@@ -41,9 +41,11 @@
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Fund' | translate }}</mat-label>
<mat-select matTooltip="{{ 'tooltips.Loan products may be assigned' | translate }}" formControlName="fundId">
<mat-option *ngFor="let fund of fundData" [value]="fund.id">
{{ fund.name }}
</mat-option>
@for (fund of fundData; track fund) {
<mat-option [value]="fund.id">
{{ fund.name }}
</mat-option>
}
</mat-select>
</mat-form-field>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit, Input } from '@angular/core';
import { Component, OnInit, Input, inject } from '@angular/core';
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
import { Dates } from 'app/core/utils/dates';
@@ -27,6 +27,10 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class LoanProductDetailsStepComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
private dateUtils = inject(Dates);
private settingsService = inject(SettingsService);
@Input() loanProductsTemplate: any;
loanProductDetailsForm: UntypedFormGroup;
@@ -42,11 +46,7 @@ export class LoanProductDetailsStepComponent implements OnInit {
* @param {SettingsService} settingsService Settings Service.
*/
constructor(
private formBuilder: UntypedFormBuilder,
private dateUtils: Dates,
private settingsService: SettingsService
) {
constructor() {
this.createLoanProductDetailsForm();
}
@@ -9,12 +9,11 @@
'tooltips.Refund transactions where interest refund will automatically be calculated' | translate
}}"
>
<mat-option
*ngFor="let supportedTransaction of supportedInterestRefundTypesOptions"
[value]="supportedTransaction.id"
>
{{ supportedTransaction.value | translateKey: 'catalogs' }}
</mat-option>
@for (supportedTransaction of supportedInterestRefundTypesOptions; track supportedTransaction) {
<mat-option [value]="supportedTransaction.id">
{{ supportedTransaction.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
</mat-form-field>
</div>
@@ -1,4 +1,4 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup, ReactiveFormsModule } from '@angular/forms';
import { StringEnumOptionData } from '../../../../shared/models/option-data.model';
import { MatTooltip } from '@angular/material/tooltip';
@@ -14,6 +14,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class LoanProductInterestRefundStepComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
@Input() loanProductsTemplate: any;
@Output() supportedInterestRefundTypes = new EventEmitter<StringEnumOptionData[]>();
@@ -21,7 +23,7 @@ export class LoanProductInterestRefundStepComponent implements OnInit {
supportedInterestRefundTypesOptions: StringEnumOptionData[];
constructor(private formBuilder: UntypedFormBuilder) {
constructor() {
this.createLoanProductInterestRefundForm();
this.setConditionalControls();
}
@@ -3,86 +3,87 @@
{{ 'labels.heading.You can drag and drop the rows to set a Payment Allocations order' | translate }}
</h4>
<div class="right flex-4" *ngIf="!isDefault()">
<button mat-button color="warn" (click)="removeTransaction()">
<fa-icon icon="trash" class="m-r-10"></fa-icon>
</button>
</div>
@if (!isDefault()) {
<div class="right flex-4">
<button mat-button color="warn" (click)="removeTransaction()">
<fa-icon icon="trash" class="m-r-10"></fa-icon>
</button>
</div>
}
<div class="mat-elevation-z8 container m-t-15" *ngIf="paymentAllocationsData">
<table
mat-table
[dataSource]="paymentAllocationsData"
#table
cdkDropList
[cdkDropListData]="paymentAllocationsData"
(cdkDropListDropped)="dropTable($event, false)"
>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let paymentAllocation">
<fa-icon icon="bars"></fa-icon>
</td>
</ng-container>
<ng-container matColumnDef="order">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Order' | translate }}</th>
<td mat-cell *matCellDef="let paymentAllocation; let rowIndex = index">{{ rowIndex + 1 }}</td>
</ng-container>
<ng-container matColumnDef="allocationRule">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Payment Allocation Rule' | translate }}</th>
<td mat-cell *matCellDef="let paymentAllocation">{{ paymentAllocation.value | translateKey: 'catalogs' }}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row cdkDrag [cdkDragData]="row" *matRowDef="let row; columns: displayedColumns"></tr>
</table>
</div>
<div class="mat-elevation-z8 container m-t-15 m-b-15" *ngIf="creditAllocationsData">
<table
mat-table
[dataSource]="creditAllocationsData"
#table
cdkDropList
[cdkDropListData]="creditAllocationsData"
(cdkDropListDropped)="dropTable($event, true)"
>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let creditAllocation">
<fa-icon icon="bars"></fa-icon>
</td>
</ng-container>
<ng-container matColumnDef="order">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Order' | translate }}</th>
<td mat-cell *matCellDef="let creditAllocation; let rowIndex = index">{{ rowIndex + 1 }}</td>
</ng-container>
<ng-container matColumnDef="allocationRule">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Credit Allocation Rule' | translate }}</th>
<td mat-cell *matCellDef="let creditAllocation">{{ creditAllocation.value | translateKey: 'catalogs' }}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row cdkDrag [cdkDragData]="row" *matRowDef="let row; columns: displayedColumns"></tr>
</table>
</div>
<mat-form-field
class="m-t-20 flex-33"
*ngIf="advancedPaymentAllocation && advancedPaymentAllocation.futureInstallmentAllocationRules"
>
<mat-label>{{ 'labels.inputs.Future Installment Allocation Rule' | translate }}</mat-label>
<mat-select [formControl]="futureInstallmentAllocationRule">
<mat-option
*ngFor="let futureInstallmentAllocationRule of advancedPaymentAllocation.futureInstallmentAllocationRules"
[value]="futureInstallmentAllocationRule.code"
@if (paymentAllocationsData) {
<div class="mat-elevation-z8 container m-t-15">
<table
mat-table
[dataSource]="paymentAllocationsData"
#table
cdkDropList
[cdkDropListData]="paymentAllocationsData"
(cdkDropListDropped)="dropTable($event, false)"
>
{{ futureInstallmentAllocationRule.value | translateKey: 'catalogs' }}
</mat-option>
</mat-select>
</mat-form-field>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let paymentAllocation">
<fa-icon icon="bars"></fa-icon>
</td>
</ng-container>
<ng-container matColumnDef="order">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Order' | translate }}</th>
<td mat-cell *matCellDef="let paymentAllocation; let rowIndex = index">{{ rowIndex + 1 }}</td>
</ng-container>
<ng-container matColumnDef="allocationRule">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Payment Allocation Rule' | translate }}</th>
<td mat-cell *matCellDef="let paymentAllocation">{{ paymentAllocation.value | translateKey: 'catalogs' }}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row cdkDrag [cdkDragData]="row" *matRowDef="let row; columns: displayedColumns"></tr>
</table>
</div>
}
@if (creditAllocationsData) {
<div class="mat-elevation-z8 container m-t-15 m-b-15">
<table
mat-table
[dataSource]="creditAllocationsData"
#table
cdkDropList
[cdkDropListData]="creditAllocationsData"
(cdkDropListDropped)="dropTable($event, true)"
>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let creditAllocation">
<fa-icon icon="bars"></fa-icon>
</td>
</ng-container>
<ng-container matColumnDef="order">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Order' | translate }}</th>
<td mat-cell *matCellDef="let creditAllocation; let rowIndex = index">{{ rowIndex + 1 }}</td>
</ng-container>
<ng-container matColumnDef="allocationRule">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Credit Allocation Rule' | translate }}</th>
<td mat-cell *matCellDef="let creditAllocation">{{ creditAllocation.value | translateKey: 'catalogs' }}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row cdkDrag [cdkDragData]="row" *matRowDef="let row; columns: displayedColumns"></tr>
</table>
</div>
}
@if (advancedPaymentAllocation && advancedPaymentAllocation.futureInstallmentAllocationRules) {
<mat-form-field class="m-t-20 flex-33">
<mat-label>{{ 'labels.inputs.Future Installment Allocation Rule' | translate }}</mat-label>
<mat-select [formControl]="futureInstallmentAllocationRule">
@for (
futureInstallmentAllocationRule of advancedPaymentAllocation.futureInstallmentAllocationRules;
track futureInstallmentAllocationRule
) {
<mat-option [value]="futureInstallmentAllocationRule.code">
{{ futureInstallmentAllocationRule.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
</mat-form-field>
}
</div>
@@ -1,5 +1,5 @@
import { CdkDragDrop, moveItemInArray, CdkDropList, CdkDrag } from '@angular/cdk/drag-drop';
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
import { Component, EventEmitter, Input, OnInit, Output, ViewChild, inject } from '@angular/core';
import { UntypedFormControl, Validators, ReactiveFormsModule } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import {
@@ -50,6 +50,10 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class AdvancePaymentAllocationTabComponent implements OnInit {
private dialog = inject(MatDialog);
private advancedPaymentStrategy = inject(AdvancedPaymentStrategy);
private translateService = inject(TranslateService);
@Input() advancedPaymentAllocation: AdvancedPaymentAllocation;
@Input() advancedCreditAllocation: AdvancedCreditAllocation;
@@ -70,12 +74,6 @@ export class AdvancePaymentAllocationTabComponent implements OnInit {
@ViewChild('table') table: MatTable<any>;
constructor(
private dialog: MatDialog,
private advancedPaymentStrategy: AdvancedPaymentStrategy,
private translateService: TranslateService
) {}
ngOnInit(): void {
if (this.advancedCreditAllocation) {
this.creditAllocationsData = this.advancedCreditAllocation?.creditAllocationOrder;
@@ -1,27 +1,31 @@
<mat-tab-group animationDuration="0ms" class="layout-row-wrap gap-2percent layout-lt-md-column">
<mat-tab *ngFor="let advancedPaymentAllocation of advancedPaymentAllocations">
<ng-template mat-tab-label>
{{ advancedPaymentAllocation.transaction.value | translateKey: 'catalogs' }}
</ng-template>
<mifosx-advance-payment-allocation-tab
[advancedPaymentAllocation]="advancedPaymentAllocation"
(allocationChanged)="allocationChanged($event)"
(transactionTypeRemoved)="transactionTypeRemoved($event)"
>
</mifosx-advance-payment-allocation-tab>
</mat-tab>
@for (advancedPaymentAllocation of advancedPaymentAllocations; track advancedPaymentAllocation) {
<mat-tab>
<ng-template mat-tab-label>
{{ advancedPaymentAllocation.transaction.value | translateKey: 'catalogs' }}
</ng-template>
<mifosx-advance-payment-allocation-tab
[advancedPaymentAllocation]="advancedPaymentAllocation"
(allocationChanged)="allocationChanged($event)"
(transactionTypeRemoved)="transactionTypeRemoved($event)"
>
</mifosx-advance-payment-allocation-tab>
</mat-tab>
}
<mat-tab *ngFor="let advancedCreditAllocation of advancedCreditAllocations">
<ng-template mat-tab-label>
{{ advancedCreditAllocation.transaction.value | translateKey: 'catalogs' }}
</ng-template>
<mifosx-advance-payment-allocation-tab
[advancedCreditAllocation]="advancedCreditAllocation"
(allocationChanged)="allocationChanged($event)"
(transactionTypeRemoved)="transactionTypeRemoved($event)"
>
</mifosx-advance-payment-allocation-tab>
</mat-tab>
@for (advancedCreditAllocation of advancedCreditAllocations; track advancedCreditAllocation) {
<mat-tab>
<ng-template mat-tab-label>
{{ advancedCreditAllocation.transaction.value | translateKey: 'catalogs' }}
</ng-template>
<mifosx-advance-payment-allocation-tab
[advancedCreditAllocation]="advancedCreditAllocation"
(allocationChanged)="allocationChanged($event)"
(transactionTypeRemoved)="transactionTypeRemoved($event)"
>
</mifosx-advance-payment-allocation-tab>
</mat-tab>
}
<mat-tab>
<ng-template mat-tab-label>
@@ -1,4 +1,4 @@
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
import { Component, EventEmitter, Input, OnInit, Output, ViewChild, inject } from '@angular/core';
import {
AdvancedCreditAllocation,
AdvancedPaymentAllocation,
@@ -38,6 +38,10 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class LoanProductPaymentStrategyStepComponent implements OnInit {
private dialog = inject(MatDialog);
private advancedPaymentStrategy = inject(AdvancedPaymentStrategy);
private translateService = inject(TranslateService);
@Input() advancedPaymentAllocations: AdvancedPaymentAllocation[] = [];
@Input() advancedCreditAllocations: AdvancedCreditAllocation[] = [];
@Input() advancedPaymentAllocationTransactionTypes: PaymentAllocationTransactionType[] = [];
@@ -51,12 +55,6 @@ export class LoanProductPaymentStrategyStepComponent implements OnInit {
@ViewChild(MatTabGroup) tabGroup: MatTabGroup;
constructor(
private dialog: MatDialog,
private advancedPaymentStrategy: AdvancedPaymentStrategy,
private translateService: TranslateService
) {}
ngOnInit(): void {
this.sendAllocations();
}
@@ -105,7 +103,6 @@ export class LoanProductPaymentStrategyStepComponent implements OnInit {
options: { label: 'value', value: 'code', data: transactionTypesOptions },
order: 1
})
];
const data = {
title: this.translateService.instant('labels.inputs.Advanced Payment Allocation Transaction Type'),
@@ -1,4 +1,4 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { Component, OnInit, Input, Output, EventEmitter, inject } from '@angular/core';
import {
UntypedFormGroup,
UntypedFormBuilder,
@@ -35,6 +35,9 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class LoanProductSettingsStepComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
private processingStrategyService = inject(ProcessingStrategyService);
DAYS_BEFORE_REPAYMENT_IS_DUE = LoanProducts.DAYS_BEFORE_REPAYMENT_IS_DUE;
DAYS_AFTER_REPAYMENT_IS_OVERDUE = LoanProducts.DAYS_AFTER_REPAYMENT_IS_OVERDUE;
@@ -74,10 +77,7 @@ export class LoanProductSettingsStepComponent implements OnInit {
/** Values to Days for Repayments */
defaultConfigValues: GlobalConfiguration[] = [];
constructor(
private formBuilder: UntypedFormBuilder,
private processingStrategyService: ProcessingStrategyService
) {
constructor() {
this.createLoanProductSettingsForm();
this.setConditionalControls();
}
@@ -563,7 +563,8 @@ export class LoanProductSettingsStepComponent implements OnInit {
'disbursedAmountPercentageForDownPayment',
new UntypedFormControl(0, [
Validators.required,
rangeValidator(0, 100)])
rangeValidator(0, 100)
])
);
this.loanProductSettingsForm.addControl('enableAutoRepaymentForDownPayment', new UntypedFormControl(false, []));
} else {
@@ -43,28 +43,25 @@
</mat-checkbox>
<div class="flex-98 layout-row-wrap responsive-column gap-2percent">
<mat-form-field
class="flex-fill flex-32"
*ngIf="loanProductTermsForm.value.allowApprovedDisbursedAmountsOverApplied"
>
<mat-label>{{ 'labels.inputs.Over Amount Calculation Type' | translate }}</mat-label>
<mat-select formControlName="overAppliedCalculationType" required>
<mat-option
*ngFor="let overAppliedCalculationType of overAppliedCalculationTypeData"
[value]="overAppliedCalculationType.id"
>
{{ overAppliedCalculationType.value | translateKey: 'catalogs' }}
</mat-option>
</mat-select>
</mat-form-field>
@if (loanProductTermsForm.value.allowApprovedDisbursedAmountsOverApplied) {
<mat-form-field class="flex-fill flex-32">
<mat-label>{{ 'labels.inputs.Over Amount Calculation Type' | translate }}</mat-label>
<mat-select formControlName="overAppliedCalculationType" required>
@for (overAppliedCalculationType of overAppliedCalculationTypeData; track overAppliedCalculationType) {
<mat-option [value]="overAppliedCalculationType.id">
{{ overAppliedCalculationType.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
</mat-form-field>
}
<mat-form-field
class="flex-fill flex-32"
*ngIf="loanProductTermsForm.value.allowApprovedDisbursedAmountsOverApplied"
>
<mat-label>{{ 'labels.inputs.Over Amount' | translate }}</mat-label>
<input type="number" matInput formControlName="overAppliedNumber" required />
</mat-form-field>
@if (loanProductTermsForm.value.allowApprovedDisbursedAmountsOverApplied) {
<mat-form-field class="flex-fill flex-32">
<mat-label>{{ 'labels.inputs.Over Amount' | translate }}</mat-label>
<input type="number" matInput formControlName="overAppliedNumber" required />
</mat-form-field>
}
</div>
<mat-form-field class="flex-31">
@@ -76,12 +73,11 @@
></i
></mat-label>
<mat-select formControlName="repaymentStartDateType" required>
<mat-option
*ngFor="let repaymentStartDateType of repaymentStartDateTypeOptions"
[value]="repaymentStartDateType.id"
>
{{ repaymentStartDateType.value | translateKey: 'catalogs' }}
</mat-option>
@for (repaymentStartDateType of repaymentStartDateTypeOptions; track repaymentStartDateType) {
<mat-option [value]="repaymentStartDateType.id">
{{ repaymentStartDateType.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
</mat-form-field>
@@ -133,171 +129,154 @@
<h3 class="mat-h3 flex-23">{{ 'labels.inputs.Interest Rates' | translate }}</h3>
<mat-checkbox
[formControl]="zeroInterest"
class="flex-23"
labelPosition="before"
*ngIf="!loanProductTermsForm.value.isLinkedToFloatingInterestRates"
>
{{ 'labels.inputs.Is Zero Interest Rate?' | translate }}
</mat-checkbox>
<mat-checkbox
class="flex-32"
labelPosition="before"
formControlName="isLinkedToFloatingInterestRates"
*ngIf="!isZeroInterest()"
>
{{ 'labels.inputs.Is Linked to floating interest rates?' | translate }}
</mat-checkbox>
<div
*ngIf="!loanProductTermsForm.value.isLinkedToFloatingInterestRates"
class="flex-fill layout-row-wrap gap-2percent responsive-column"
>
<h4 class="mat-h4 flex-98">
{{ 'labels.inputs.Nominal interest rate' | translate }}
<i
class="fas fa-question"
matTooltip="{{
'tooltips.Define the minimum, default, maximum, and period for the nominal interest rate' | translate
}}"
></i>
</h4>
<mat-form-field class="flex-fill flex-23">
<mat-label>{{ 'labels.inputs.Minimum' | translate }}</mat-label>
<input
type="number"
matInput
formControlName="minInterestRatePerPeriod"
[min]="0"
[attr.disabled]="isZeroInterest()"
/>
<mat-error>
{{ 'labels.commons.Minimum Value must be' | translate }}
<strong>{{ 'labels.commons.greater equal to than 0' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="flex-fill flex-23">
<mat-label>{{ 'labels.inputs.Default' | translate }}</mat-label>
<input
type="number"
matInput
formControlName="interestRatePerPeriod"
required
[attr.disabled]="isZeroInterest()"
/>
<mat-error>
{{ 'labels.catalogs.Default' | translate }} {{ 'labels.inputs.Nominal interest rate' | translate }}
{{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="flex-fill flex-23">
<mat-label>{{ 'labels.inputs.Maximum' | translate }}</mat-label>
<input
type="number"
matInput
formControlName="maxInterestRatePerPeriod"
[min]="0"
[attr.disabled]="isZeroInterest()"
/>
<mat-error>
{{ 'labels.commons.Maximum Value must be' | translate }}
<strong>{{ 'labels.commons.greater equal to than 0' | translate }}</strong>
{{ 'labels.commons.and must be greater than' | translate }}
<strong>{{ 'labels.commons.Minimum Principal' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="flex-fill flex-23">
<mat-label>{{ 'labels.inputs.Frequency' | translate }}</mat-label>
<mat-select formControlName="interestRateFrequencyType" required [disabled]="isZeroInterest()">
<mat-option
*ngFor="let interestRateFrequencyType of interestRateFrequencyTypeData"
[value]="interestRateFrequencyType.id"
>
{{ interestRateFrequencyType.value | translateKey: 'catalogs' }}
</mat-option>
</mat-select>
<mat-error>
{{ 'labels.inputs.Nominal interest rate frequency' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
</div>
<div
*ngIf="loanProductTermsForm.value.isLinkedToFloatingInterestRates && !isZeroInterest()"
class="flex-fill layout-row-wrap gap-2percent responsive-column align-gt-sm-start-center"
>
<h4 class="mat-h4 flex-98">
{{ 'labels.inputs.Floating Interest Rate' | translate }}
<i
class="fas fa-question"
matTooltip="{{
'tooltips.Define the minimum, default, maximum, and period for the floating interest rate' | translate
}}"
></i>
</h4>
<mat-form-field class="flex-31">
<mat-label>{{ 'labels.inputs.Floating Rate' | translate }}</mat-label>
<mat-select formControlName="floatingRatesId" required>
<mat-option *ngFor="let floatingRate of floatingRateData" [value]="floatingRate.id">
{{ floatingRate.name }}
</mat-option>
</mat-select>
<mat-error>
{{ 'labels.inputs.Floating rate' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="flex-31">
<mat-label>{{ 'labels.inputs.Differential Rate' | translate }}</mat-label>
<input type="number" matInput formControlName="interestRateDifferential" required />
<mat-error>
{{ 'labels.inputs.Differential rate' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-checkbox class="flex-31" labelPosition="before" formControlName="isFloatingInterestRateCalculationAllowed">
{{ 'labels.inputs.Is Floating calculation allowed?' | translate }}
@if (!loanProductTermsForm.value.isLinkedToFloatingInterestRates) {
<mat-checkbox [formControl]="zeroInterest" class="flex-23" labelPosition="before">
{{ 'labels.inputs.Is Zero Interest Rate?' | translate }}
</mat-checkbox>
}
<mat-form-field class="flex-31">
<mat-label>{{ 'labels.inputs.Minimum' | translate }}</mat-label>
<input type="number" matInput formControlName="minDifferentialLendingRate" [min]="0" required />
<mat-error>
{{ 'labels.inputs.Minimum interest rate' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
@if (!isZeroInterest()) {
<mat-checkbox class="flex-32" labelPosition="before" formControlName="isLinkedToFloatingInterestRates">
{{ 'labels.inputs.Is Linked to floating interest rates?' | translate }}
</mat-checkbox>
}
<mat-form-field class="flex-31">
<mat-label>{{ 'labels.inputs.Default' | translate }}</mat-label>
<input type="number" matInput formControlName="defaultDifferentialLendingRate" required />
<mat-error>
{{ 'labels.catalogs.Default' | translate }} {{ 'labels.inputs.Interest rate' | translate }}
{{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
@if (!loanProductTermsForm.value.isLinkedToFloatingInterestRates) {
<div class="flex-fill layout-row-wrap gap-2percent responsive-column">
<h4 class="mat-h4 flex-98">
{{ 'labels.inputs.Nominal interest rate' | translate }}
<i
class="fas fa-question"
matTooltip="{{
'tooltips.Define the minimum, default, maximum, and period for the nominal interest rate' | translate
}}"
></i>
</h4>
<mat-form-field class="flex-fill flex-23">
<mat-label>{{ 'labels.inputs.Minimum' | translate }}</mat-label>
<input
type="number"
matInput
formControlName="minInterestRatePerPeriod"
[min]="0"
[attr.disabled]="isZeroInterest()"
/>
<mat-error>
{{ 'labels.commons.Minimum Value must be' | translate }}
<strong>{{ 'labels.commons.greater equal to than 0' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="flex-fill flex-23">
<mat-label>{{ 'labels.inputs.Default' | translate }}</mat-label>
<input
type="number"
matInput
formControlName="interestRatePerPeriod"
required
[attr.disabled]="isZeroInterest()"
/>
<mat-error>
{{ 'labels.catalogs.Default' | translate }} {{ 'labels.inputs.Nominal interest rate' | translate }}
{{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="flex-fill flex-23">
<mat-label>{{ 'labels.inputs.Maximum' | translate }}</mat-label>
<input
type="number"
matInput
formControlName="maxInterestRatePerPeriod"
[min]="0"
[attr.disabled]="isZeroInterest()"
/>
<mat-error>
{{ 'labels.commons.Maximum Value must be' | translate }}
<strong>{{ 'labels.commons.greater equal to than 0' | translate }}</strong>
{{ 'labels.commons.and must be greater than' | translate }}
<strong>{{ 'labels.commons.Minimum Principal' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="flex-fill flex-23">
<mat-label>{{ 'labels.inputs.Frequency' | translate }}</mat-label>
<mat-select formControlName="interestRateFrequencyType" required [disabled]="isZeroInterest()">
@for (interestRateFrequencyType of interestRateFrequencyTypeData; track interestRateFrequencyType) {
<mat-option [value]="interestRateFrequencyType.id">
{{ interestRateFrequencyType.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
<mat-error>
{{ 'labels.inputs.Nominal interest rate frequency' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
</div>
}
<mat-form-field class="flex-31">
<mat-label>{{ 'labels.inputs.Maximum' | translate }}</mat-label>
<input type="number" matInput formControlName="maxDifferentialLendingRate" required />
<mat-error>
{{ 'labels.inputs.Maximum interest rate' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
</div>
@if (loanProductTermsForm.value.isLinkedToFloatingInterestRates && !isZeroInterest()) {
<div class="flex-fill layout-row-wrap gap-2percent responsive-column align-gt-sm-start-center">
<h4 class="mat-h4 flex-98">
{{ 'labels.inputs.Floating Interest Rate' | translate }}
<i
class="fas fa-question"
matTooltip="{{
'tooltips.Define the minimum, default, maximum, and period for the floating interest rate' | translate
}}"
></i>
</h4>
<mat-form-field class="flex-31">
<mat-label>{{ 'labels.inputs.Floating Rate' | translate }}</mat-label>
<mat-select formControlName="floatingRatesId" required>
@for (floatingRate of floatingRateData; track floatingRate) {
<mat-option [value]="floatingRate.id">
{{ floatingRate.name }}
</mat-option>
}
</mat-select>
<mat-error>
{{ 'labels.inputs.Floating rate' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="flex-31">
<mat-label>{{ 'labels.inputs.Differential Rate' | translate }}</mat-label>
<input type="number" matInput formControlName="interestRateDifferential" required />
<mat-error>
{{ 'labels.inputs.Differential rate' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-checkbox class="flex-31" labelPosition="before" formControlName="isFloatingInterestRateCalculationAllowed">
{{ 'labels.inputs.Is Floating calculation allowed?' | translate }}
</mat-checkbox>
<mat-form-field class="flex-31">
<mat-label>{{ 'labels.inputs.Minimum' | translate }}</mat-label>
<input type="number" matInput formControlName="minDifferentialLendingRate" [min]="0" required />
<mat-error>
{{ 'labels.inputs.Minimum interest rate' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="flex-31">
<mat-label>{{ 'labels.inputs.Default' | translate }}</mat-label>
<input type="number" matInput formControlName="defaultDifferentialLendingRate" required />
<mat-error>
{{ 'labels.catalogs.Default' | translate }} {{ 'labels.inputs.Interest rate' | translate }}
{{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="flex-31">
<mat-label>{{ 'labels.inputs.Maximum' | translate }}</mat-label>
<input type="number" matInput formControlName="maxDifferentialLendingRate" required />
<mat-error>
{{ 'labels.inputs.Maximum interest rate' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
</div>
}
<mat-divider class="flex-98"></mat-divider>
@@ -307,249 +286,219 @@
{{ 'labels.inputs.Terms vary based on loan cycle' | translate }}
</mat-checkbox>
<div
*ngIf="loanProductTermsForm.value.useBorrowerCycle"
class="flex-fill layout-row-wrap gap-2percent responsive-column"
>
<h4 class="mat-h4 flex-73">{{ 'labels.inputs.Principal by loan cycle' | translate }}</h4>
<div class="flex-23">
<button
type="button"
mat-raised-button
color="primary"
(click)="addVariationsForBorrowerCycle('Principal', principalVariationsForBorrowerCycle)"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
@if (loanProductTermsForm.value.useBorrowerCycle) {
<div class="flex-fill layout-row-wrap gap-2percent responsive-column">
<h4 class="mat-h4 flex-73">{{ 'labels.inputs.Principal by loan cycle' | translate }}</h4>
<div class="flex-23">
<button
type="button"
mat-raised-button
color="primary"
(click)="addVariationsForBorrowerCycle('Principal', principalVariationsForBorrowerCycle)"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
@if (principalVariationsForBorrowerCycle.value.length) {
<table class="flex-98 mat-elevation-z1" mat-table [dataSource]="principalVariationsForBorrowerCycle.value">
<ng-container matColumnDef="valueConditionType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Condition' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.valueConditionType | find: valueConditionTypeData : 'id' : 'value' }}
</td>
</ng-container>
<ng-container matColumnDef="borrowerCycleNumber">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Loan Cycle' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.borrowerCycleNumber }}
</td>
</ng-container>
<ng-container matColumnDef="minValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Minimum' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.minValue }}
</td>
</ng-container>
<ng-container matColumnDef="defaultValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Default' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.defaultValue }}
</td>
</ng-container>
<ng-container matColumnDef="maxValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Maximum' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.maxValue }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let variation; let i = index">
<button
mat-icon-button
color="primary"
(click)="editVariationsForBorrowerCycle('Principal', principalVariationsForBorrowerCycle, i)"
>
<fa-icon icon="edit"></fa-icon>
</button>
<button
mat-icon-button
color="warn"
(click)="deleteVariationsForBorrowerCycle(principalVariationsForBorrowerCycle, i)"
>
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
}
<h4 class="mat-h4 flex-73">{{ 'labels.inputs.Number of repayments by loan cycle' | translate }}</h4>
<div class="flex-23">
<button
type="button"
mat-raised-button
color="primary"
(click)="addVariationsForBorrowerCycle('NumberOfRepayments', numberOfRepaymentVariationsForBorrowerCycle)"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
@if (numberOfRepaymentVariationsForBorrowerCycle.value.length) {
<table
class="flex-98 mat-elevation-z1"
mat-table
[dataSource]="numberOfRepaymentVariationsForBorrowerCycle.value"
>
<ng-container matColumnDef="valueConditionType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Condition' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.valueConditionType | find: valueConditionTypeData : 'id' : 'value' }}
</td>
</ng-container>
<ng-container matColumnDef="borrowerCycleNumber">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Loan Cycle' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.borrowerCycleNumber }}
</td>
</ng-container>
<ng-container matColumnDef="minValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Minimum' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.minValue }}
</td>
</ng-container>
<ng-container matColumnDef="defaultValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Default' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.defaultValue }}
</td>
</ng-container>
<ng-container matColumnDef="maxValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Maximum' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.maxValue }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let variation; let i = index">
<button
mat-icon-button
color="primary"
(click)="
editVariationsForBorrowerCycle('NumberOfRepayments', numberOfRepaymentVariationsForBorrowerCycle, i)
"
>
<fa-icon icon="edit"></fa-icon>
</button>
<button
mat-icon-button
color="warn"
(click)="deleteVariationsForBorrowerCycle(numberOfRepaymentVariationsForBorrowerCycle, i)"
>
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
}
<h4 class="mat-h4 flex-73">{{ 'labels.inputs.Nominal interest rate by loan cycle' | translate }}</h4>
<div class="flex-23">
<button
type="button"
mat-raised-button
color="primary"
(click)="addVariationsForBorrowerCycle('NominalInterestRate', interestRateVariationsForBorrowerCycle)"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
@if (interestRateVariationsForBorrowerCycle.value.length) {
<table class="flex-98 mat-elevation-z1" mat-table [dataSource]="interestRateVariationsForBorrowerCycle.value">
<ng-container matColumnDef="valueConditionType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Condition' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.valueConditionType | find: valueConditionTypeData : 'id' : 'value' }}
</td>
</ng-container>
<ng-container matColumnDef="borrowerCycleNumber">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Loan Cycle' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.borrowerCycleNumber }}
</td>
</ng-container>
<ng-container matColumnDef="minValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Minimum' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.minValue }}
</td>
</ng-container>
<ng-container matColumnDef="defaultValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Default' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.defaultValue }}
</td>
</ng-container>
<ng-container matColumnDef="maxValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Maximum' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.maxValue }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let element; let i = index">
<button
mat-icon-button
color="primary"
(click)="
editVariationsForBorrowerCycle('NominalInterestRate', interestRateVariationsForBorrowerCycle, i)
"
>
<fa-icon icon="edit"></fa-icon>
</button>
<button
mat-icon-button
color="warn"
(click)="deleteVariationsForBorrowerCycle(interestRateVariationsForBorrowerCycle, i)"
>
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
}
</div>
<table
class="flex-98 mat-elevation-z1"
mat-table
[dataSource]="principalVariationsForBorrowerCycle.value"
*ngIf="principalVariationsForBorrowerCycle.value.length"
>
<ng-container matColumnDef="valueConditionType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Condition' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.valueConditionType | find: valueConditionTypeData : 'id' : 'value' }}
</td>
</ng-container>
<ng-container matColumnDef="borrowerCycleNumber">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Loan Cycle' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.borrowerCycleNumber }}
</td>
</ng-container>
<ng-container matColumnDef="minValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Minimum' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.minValue }}
</td>
</ng-container>
<ng-container matColumnDef="defaultValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Default' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.defaultValue }}
</td>
</ng-container>
<ng-container matColumnDef="maxValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Maximum' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.maxValue }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let variation; let i = index">
<button
mat-icon-button
color="primary"
(click)="editVariationsForBorrowerCycle('Principal', principalVariationsForBorrowerCycle, i)"
>
<fa-icon icon="edit"></fa-icon>
</button>
<button
mat-icon-button
color="warn"
(click)="deleteVariationsForBorrowerCycle(principalVariationsForBorrowerCycle, i)"
>
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
<h4 class="mat-h4 flex-73">{{ 'labels.inputs.Number of repayments by loan cycle' | translate }}</h4>
<div class="flex-23">
<button
type="button"
mat-raised-button
color="primary"
(click)="addVariationsForBorrowerCycle('NumberOfRepayments', numberOfRepaymentVariationsForBorrowerCycle)"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
<table
class="flex-98 mat-elevation-z1"
mat-table
[dataSource]="numberOfRepaymentVariationsForBorrowerCycle.value"
*ngIf="numberOfRepaymentVariationsForBorrowerCycle.value.length"
>
<ng-container matColumnDef="valueConditionType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Condition' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.valueConditionType | find: valueConditionTypeData : 'id' : 'value' }}
</td>
</ng-container>
<ng-container matColumnDef="borrowerCycleNumber">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Loan Cycle' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.borrowerCycleNumber }}
</td>
</ng-container>
<ng-container matColumnDef="minValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Minimum' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.minValue }}
</td>
</ng-container>
<ng-container matColumnDef="defaultValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Default' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.defaultValue }}
</td>
</ng-container>
<ng-container matColumnDef="maxValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Maximum' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.maxValue }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let variation; let i = index">
<button
mat-icon-button
color="primary"
(click)="
editVariationsForBorrowerCycle('NumberOfRepayments', numberOfRepaymentVariationsForBorrowerCycle, i)
"
>
<fa-icon icon="edit"></fa-icon>
</button>
<button
mat-icon-button
color="warn"
(click)="deleteVariationsForBorrowerCycle(numberOfRepaymentVariationsForBorrowerCycle, i)"
>
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
<h4 class="mat-h4 flex-73">{{ 'labels.inputs.Nominal interest rate by loan cycle' | translate }}</h4>
<div class="flex-23">
<button
type="button"
mat-raised-button
color="primary"
(click)="addVariationsForBorrowerCycle('NominalInterestRate', interestRateVariationsForBorrowerCycle)"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }}
</button>
</div>
<table
class="flex-98 mat-elevation-z1"
mat-table
[dataSource]="interestRateVariationsForBorrowerCycle.value"
*ngIf="interestRateVariationsForBorrowerCycle.value.length"
>
<ng-container matColumnDef="valueConditionType">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Condition' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.valueConditionType | find: valueConditionTypeData : 'id' : 'value' }}
</td>
</ng-container>
<ng-container matColumnDef="borrowerCycleNumber">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Loan Cycle' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.borrowerCycleNumber }}
</td>
</ng-container>
<ng-container matColumnDef="minValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Minimum' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.minValue }}
</td>
</ng-container>
<ng-container matColumnDef="defaultValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Default' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.defaultValue }}
</td>
</ng-container>
<ng-container matColumnDef="maxValue">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Maximum' | translate }}</th>
<td mat-cell *matCellDef="let variation">
{{ variation.maxValue }}
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let element; let i = index">
<button
mat-icon-button
color="primary"
(click)="editVariationsForBorrowerCycle('NominalInterestRate', interestRateVariationsForBorrowerCycle, i)"
>
<fa-icon icon="edit"></fa-icon>
</button>
<button
mat-icon-button
color="warn"
(click)="deleteVariationsForBorrowerCycle(interestRateVariationsForBorrowerCycle, i)"
>
<fa-icon icon="trash"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
</div>
}
<mat-divider class="flex-98"></mat-divider>
@@ -574,12 +523,11 @@
<mat-form-field class="flex-30">
<mat-label>{{ 'labels.inputs.Frequency Type' | translate }}</mat-label>
<mat-select formControlName="repaymentFrequencyType" required>
<mat-option
*ngFor="let repaymentFrequencyType of repaymentFrequencyTypeData"
[value]="repaymentFrequencyType.id"
>
{{ repaymentFrequencyType.value | translateKey: 'catalogs' }}
</mat-option>
@for (repaymentFrequencyType of repaymentFrequencyTypeData; track repaymentFrequencyType) {
<mat-option [value]="repaymentFrequencyType.id">
{{ repaymentFrequencyType.value | translateKey: 'catalogs' }}
</mat-option>
}
</mat-select>
<mat-error>
{{ 'labels.inputs.Repaid every type' | translate }} {{ 'labels.commons.is' | translate }}
@@ -587,23 +535,29 @@
</mat-error>
</mat-form-field>
<h4 class="mat-h4 flex-30" *ngIf="allowFixedLength()">
{{ 'labels.inputs.Fixed Length' | translate }}
<i
class="fas fa-question"
matTooltip="{{ 'tooltips.Due to regulatory requirements in some countries' | translate }}"
></i>
</h4>
@if (allowFixedLength()) {
<h4 class="mat-h4 flex-30">
{{ 'labels.inputs.Fixed Length' | translate }}
<i
class="fas fa-question"
matTooltip="{{ 'tooltips.Due to regulatory requirements in some countries' | translate }}"
></i>
</h4>
}
<mat-form-field class="flex-30" *ngIf="allowFixedLength()">
<mat-label>{{ 'labels.inputs.Fixed Length' | translate }}</mat-label>
<input type="number" matInput formControlName="fixedLength" />
</mat-form-field>
<span *ngIf="allowFixedLength()" class="label-field flex-30">{{
loanProductTermsForm.value.repaymentFrequencyType
| find: repaymentFrequencyTypeData : 'id' : 'value'
| translateKey: 'catalogs'
}}</span>
@if (allowFixedLength()) {
<mat-form-field class="flex-30">
<mat-label>{{ 'labels.inputs.Fixed Length' | translate }}</mat-label>
<input type="number" matInput formControlName="fixedLength" />
</mat-form-field>
}
@if (allowFixedLength()) {
<span class="label-field flex-30">{{
loanProductTermsForm.value.repaymentFrequencyType
| find: repaymentFrequencyTypeData : 'id' : 'value'
| translateKey: 'catalogs'
}}</span>
}
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Minimum days between disbursal and first repayment date' | translate }}</mat-label>
@@ -1,4 +1,4 @@
import { Component, OnInit, Input, OnChanges, SimpleChanges } from '@angular/core';
import { Component, OnInit, Input, OnChanges, SimpleChanges, inject } from '@angular/core';
import {
UntypedFormGroup,
UntypedFormBuilder,
@@ -65,6 +65,11 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class LoanProductTermsStepComponent implements OnInit, OnChanges {
private formBuilder = inject(UntypedFormBuilder);
private processingStrategyService = inject(ProcessingStrategyService);
private dialog = inject(MatDialog);
private translateService = inject(TranslateService);
@Input() loanProductsTemplate: any;
loanProductTermsForm: UntypedFormGroup;
@@ -89,12 +94,7 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
];
isAdvancedTransactionProcessingStrategy = false;
constructor(
private formBuilder: UntypedFormBuilder,
private processingStrategyService: ProcessingStrategyService,
private dialog: MatDialog,
private translateService: TranslateService
) {
constructor() {
this.createLoanProductTermsForm();
this.setConditionalControls();
}
@@ -456,7 +456,6 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
type: 'number',
order: 5
})
];
return formfields;
}
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
import { ActivatedRouteSnapshot } from '@angular/router';
/** rxjs Imports */
@@ -13,10 +13,7 @@ import { ProductsService } from '../products.service';
*/
@Injectable()
export class LoanProductResolver {
/**
* @param {ProductsService} productsService Products service.
*/
constructor(private productsService: ProductsService) {}
private productsService = inject(ProductsService);
/**
* Returns the loan product data.
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
/** rxjs Imports */
import { Observable } from 'rxjs';
@@ -9,7 +9,7 @@ import { ProductsService } from '../products.service';
@Injectable()
export class LoanProductsTemplateResolver {
constructor(private productsService: ProductsService) {}
private productsService = inject(ProductsService);
/**
* Returns the loan products template data.
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit, TemplateRef, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
import { Component, OnInit, TemplateRef, ElementRef, ViewChild, AfterViewInit, inject } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort, MatSortHeader } from '@angular/material/sort';
import {
@@ -52,6 +52,11 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class LoanProductsComponent implements OnInit, AfterViewInit {
private route = inject(ActivatedRoute);
private router = inject(Router);
private configurationWizardService = inject(ConfigurationWizardService);
private popoverService = inject(PopoverService);
loanProductsData: any;
displayedColumns: string[] = [
'name',
@@ -79,12 +84,7 @@ export class LoanProductsComponent implements OnInit, AfterViewInit {
* @param {ConfigurationWizardService} configurationWizardService ConfigurationWizard Service.
* @param {PopoverService} popoverService PopoverService.
*/
constructor(
private route: ActivatedRoute,
private router: Router,
private configurationWizardService: ConfigurationWizardService,
private popoverService: PopoverService
) {
constructor() {
this.route.data.subscribe((data: { loanProducts: any }) => {
this.loanProductsData = data.loanProducts;
});

Some files were not shown because too many files have changed in this diff Show More