update loan product code
This commit is contained in:
-95
@@ -15,22 +15,6 @@
|
|||||||
<span class="flex-40">{{ 'labels.inputs.Short Name' | translate }}:</span>
|
<span class="flex-40">{{ 'labels.inputs.Short Name' | translate }}:</span>
|
||||||
<span class="flex-60">{{ loanProduct.shortName }}</span>
|
<span class="flex-60">{{ loanProduct.shortName }}</span>
|
||||||
</div>
|
</div>
|
||||||
@if (loanProduct.externalId) {
|
|
||||||
<div class="flex-fill layout-row">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.External Id' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{ loanProduct.externalId }}</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (loanProduct.fundId) {
|
|
||||||
<div class="flex-fill layout-row">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.Fund' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{ loanProduct.fundName }}</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<div class="flex-fill layout-row">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.Include in Customer Loan Counter' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{ loanProduct.includeInBorrowerCycle | yesNo }}</span>
|
|
||||||
</div>
|
|
||||||
@if (loanProduct.startDate) {
|
@if (loanProduct.startDate) {
|
||||||
<div class="flex-fill layout-row">
|
<div class="flex-fill layout-row">
|
||||||
<span class="flex-40">{{ 'labels.inputs.Start Date' | translate }}:</span>
|
<span class="flex-40">{{ 'labels.inputs.Start Date' | translate }}:</span>
|
||||||
@@ -63,18 +47,6 @@
|
|||||||
<span class="flex-40">{{ 'labels.inputs.Decimal Places' | translate }}:</span>
|
<span class="flex-40">{{ 'labels.inputs.Decimal Places' | translate }}:</span>
|
||||||
<span class="flex-60">{{ loanProduct.digitsAfterDecimal ?? loanProduct.currency.decimalPlaces }}</span>
|
<span class="flex-60">{{ loanProduct.digitsAfterDecimal ?? loanProduct.currency.decimalPlaces }}</span>
|
||||||
</div>
|
</div>
|
||||||
@if (loanProduct.inMultiplesOf || loanProduct.currency?.inMultiplesOf) {
|
|
||||||
<div class="flex-fill layout-row">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.Currency in multiples of' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{ loanProduct.inMultiplesOf ?? loanProduct.currency.inMultiplesOf }}</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (loanProduct.installmentAmountInMultiplesOf) {
|
|
||||||
<div class="flex-fill layout-row">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.Installment in multiples of' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{ loanProduct.installmentAmountInMultiplesOf }}</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<h3 class="mat-h3 flex-fill">{{ 'labels.heading.Terms' | translate }}</h3>
|
<h3 class="mat-h3 flex-fill">{{ 'labels.heading.Terms' | translate }}</h3>
|
||||||
<mat-divider [inset]="true"></mat-divider>
|
<mat-divider [inset]="true"></mat-divider>
|
||||||
<div class="flex-fill layout-row">
|
<div class="flex-fill layout-row">
|
||||||
@@ -414,24 +386,6 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<h3 class="mat-h3 flex-fill">{{ 'labels.inputs.Down Payments' | translate }}</h3>
|
|
||||||
<mat-divider [inset]="true"></mat-divider>
|
|
||||||
<div class="flex-fill layout-row">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.Enable Down Payments' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{ loanProduct.enableDownPayment | yesNo }}</span>
|
|
||||||
</div>
|
|
||||||
@if (loanProduct.enableDownPayment) {
|
|
||||||
<div class="flex-fill layout-row-wrap responsive-column">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.Disbursed Amount Percentage Down Payment' | translate }} (%):</span>
|
|
||||||
<span class="flex-60">{{ loanProduct.disbursedAmountPercentageForDownPayment }} %</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (loanProduct.enableDownPayment) {
|
|
||||||
<div class="flex-fill layout-row-wrap responsive-column">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.Enable Auto Repayment for Down Payment' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{ loanProduct.enableAutoRepaymentForDownPayment | yesNo }}</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (isAdvancedPaymentAllocation) {
|
@if (isAdvancedPaymentAllocation) {
|
||||||
<div class="flex-100 layout-row-wrap responsive-column">
|
<div class="flex-100 layout-row-wrap responsive-column">
|
||||||
<h3 class="mat-h3 flex-100">{{ 'labels.inputs.Loan Charge-off behaviour' | translate }}</h3>
|
<h3 class="mat-h3 flex-100">{{ 'labels.inputs.Loan Charge-off behaviour' | translate }}</h3>
|
||||||
@@ -737,55 +691,6 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<h3 class="mat-h3 flex-fill">{{ 'labels.heading.Loan Tranche Details' | translate }}</h3>
|
|
||||||
<mat-divider [inset]="true"></mat-divider>
|
|
||||||
<div class="flex-fill layout-row">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.Enable Multiple Disbursals' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{ loanProduct.multiDisburseLoan | yesNo }}</span>
|
|
||||||
</div>
|
|
||||||
@if (loanProduct.multiDisburseLoan) {
|
|
||||||
<div class="flex-fill layout-row">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.Maximum Tranche count' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{ loanProduct.maxTrancheCount }}</span>
|
|
||||||
</div>
|
|
||||||
@if (loanProduct.outstandingLoanBalance) {
|
|
||||||
<div class="flex-fill layout-row">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.Maximum allowed outstanding balance' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{ loanProduct.outstandingLoanBalance }}</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<div class="flex-fill layout-row">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.Disallow Expected Disbursements' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{ loanProduct.disallowExpectedDisbursements | yesNo }}</span>
|
|
||||||
</div>
|
|
||||||
@if (loanProduct.loanScheduleType && loanProduct.loanScheduleType.code === 'PROGRESSIVE') {
|
|
||||||
<div class="flex-fill layout-row">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.Allow full term for each tranche' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{ loanProduct.allowFullTermForTranche | yesNo }}</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
<h3 class="mat-h3 flex-fill">{{ 'labels.heading.Event Settings' | translate }}</h3>
|
|
||||||
<div class="flex-100">
|
|
||||||
<span class="flex-40"
|
|
||||||
>{{
|
|
||||||
'labels.inputs.Use the Global Configurations values to the Repayment Event (notifications)' | translate
|
|
||||||
}}:</span
|
|
||||||
>
|
|
||||||
<span class="flex-60">{{ useDueForRepaymentsConfigurations | yesNo }}</span>
|
|
||||||
</div>
|
|
||||||
@if (loanProduct.dueDaysForRepaymentEvent) {
|
|
||||||
<div class="flex-fill layout-row">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.Due days for repayment event' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{ loanProduct.dueDaysForRepaymentEvent | number }}</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (loanProduct.overDueDaysForRepaymentEvent) {
|
|
||||||
<div class="flex-fill layout-row">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.OverDue days for repayment event' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{ loanProduct.overDueDaysForRepaymentEvent | number }}</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<h3 class="mat-h3 flex-fill">{{ 'labels.inputs.Configurable Terms and Settings' | translate }}</h3>
|
<h3 class="mat-h3 flex-fill">{{ 'labels.inputs.Configurable Terms and Settings' | translate }}</h3>
|
||||||
<mat-divider [inset]="true"></mat-divider>
|
<mat-divider [inset]="true"></mat-divider>
|
||||||
<div class="flex-fill layout-row">
|
<div class="flex-fill layout-row">
|
||||||
|
|||||||
-1
@@ -84,7 +84,6 @@ export class LoanProductSummaryComponent implements OnInit, OnChanges {
|
|||||||
@Input() action: string;
|
@Input() action: string;
|
||||||
@Input() loanProduct: LoanProduct;
|
@Input() loanProduct: LoanProduct;
|
||||||
@Input() loanProductsTemplate: any | null;
|
@Input() loanProductsTemplate: any | null;
|
||||||
@Input() useDueForRepaymentsConfigurations: boolean;
|
|
||||||
@Input() paymentAllocations: PaymentAllocation | null;
|
@Input() paymentAllocations: PaymentAllocation | null;
|
||||||
@Input() creditAllocations: CreditAllocation | null;
|
@Input() creditAllocations: CreditAllocation | null;
|
||||||
@Input() supportedInterestRefundTypes: StringEnumOptionData[] | null;
|
@Input() supportedInterestRefundTypes: StringEnumOptionData[] | null;
|
||||||
|
|||||||
@@ -304,10 +304,6 @@ export class CreateLoanProductComponent implements OnInit {
|
|||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
const loanProduct = this.loanProducts.buildPayload(this.loanProduct, this.itemsByDefault);
|
const loanProduct = this.loanProducts.buildPayload(this.loanProduct, this.itemsByDefault);
|
||||||
if (loanProduct['useDueForRepaymentsConfigurations'] === true) {
|
|
||||||
loanProduct['dueDaysForRepaymentEvent'] = null;
|
|
||||||
loanProduct['overDueDaysForRepaymentEvent'] = null;
|
|
||||||
}
|
|
||||||
if (this.isAdvancedPaymentStrategy) {
|
if (this.isAdvancedPaymentStrategy) {
|
||||||
loanProduct['supportedInterestRefundTypes'] = this.mapStringEnumOptionToIdList(
|
loanProduct['supportedInterestRefundTypes'] = this.mapStringEnumOptionToIdList(
|
||||||
loanProduct['supportedInterestRefundTypes']
|
loanProduct['supportedInterestRefundTypes']
|
||||||
@@ -316,7 +312,6 @@ export class CreateLoanProductComponent implements OnInit {
|
|||||||
delete loanProduct['supportedInterestRefundTypes'];
|
delete loanProduct['supportedInterestRefundTypes'];
|
||||||
delete loanProduct['daysInYearCustomStrategy'];
|
delete loanProduct['daysInYearCustomStrategy'];
|
||||||
}
|
}
|
||||||
delete loanProduct['useDueForRepaymentsConfigurations'];
|
|
||||||
|
|
||||||
this.productsService.createLoanProduct(loanProduct).subscribe((response: any) => {
|
this.productsService.createLoanProduct(loanProduct).subscribe((response: any) => {
|
||||||
this.router.navigate(
|
this.router.navigate(
|
||||||
|
|||||||
@@ -353,10 +353,6 @@ export class EditLoanProductComponent implements OnInit {
|
|||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
const loanProduct = this.loanProducts.buildPayload(this.loanProduct, this.itemsByDefault);
|
const loanProduct = this.loanProducts.buildPayload(this.loanProduct, this.itemsByDefault);
|
||||||
if (loanProduct['useDueForRepaymentsConfigurations']) {
|
|
||||||
loanProduct['dueDaysForRepaymentEvent'] = null;
|
|
||||||
loanProduct['overDueDaysForRepaymentEvent'] = null;
|
|
||||||
}
|
|
||||||
if (this.isAdvancedPaymentStrategy) {
|
if (this.isAdvancedPaymentStrategy) {
|
||||||
loanProduct['supportedInterestRefundTypes'] = this.mapStringEnumOptionToIdList(
|
loanProduct['supportedInterestRefundTypes'] = this.mapStringEnumOptionToIdList(
|
||||||
loanProduct['supportedInterestRefundTypes']
|
loanProduct['supportedInterestRefundTypes']
|
||||||
@@ -365,7 +361,6 @@ export class EditLoanProductComponent implements OnInit {
|
|||||||
delete loanProduct['supportedInterestRefundTypes'];
|
delete loanProduct['supportedInterestRefundTypes'];
|
||||||
delete loanProduct['daysInYearCustomStrategy'];
|
delete loanProduct['daysInYearCustomStrategy'];
|
||||||
}
|
}
|
||||||
delete loanProduct['useDueForRepaymentsConfigurations'];
|
|
||||||
|
|
||||||
this.productsService.updateLoanProduct(this.loanProductAndTemplate.id, loanProduct).subscribe((response: any) => {
|
this.productsService.updateLoanProduct(this.loanProductAndTemplate.id, loanProduct).subscribe((response: any) => {
|
||||||
this.router.navigate(
|
this.router.navigate(
|
||||||
|
|||||||
+396
-531
@@ -7,542 +7,407 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<form [formGroup]="loanProductAccountingForm">
|
<form [formGroup]="loanProductAccountingForm">
|
||||||
<!-- Accounting Rule Section -->
|
|
||||||
<div class="lpa-section">
|
<div class="lpa-section">
|
||||||
<div class="lpa-section-header">
|
<div class="lpa-section__header">
|
||||||
<i class="fas fa-book lpa-section-icon"></i>
|
<span class="lpa-section__icon">
|
||||||
<h3>{{ 'labels.heading.Accounting Rule' | translate }}</h3>
|
<i class="fas fa-book"></i>
|
||||||
|
</span>
|
||||||
|
<h3>Accounting</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="lpa-section-body">
|
|
||||||
<div class="lpa-full-width">
|
<div class="lpa-section__body">
|
||||||
<mat-radio-group class="lpa-radio-group" formControlName="accountingRule">
|
<!-- Accounting Rule Section -->
|
||||||
@for (accountingRule of accountingRuleData; track accountingRule; let i = $index) {
|
<div class="lpa-group">
|
||||||
<mat-radio-button [value]="i + 1">
|
<div class="lpa-group__header">
|
||||||
{{ 'labels.accounting.' + accountingRule | translate }}
|
<h4>Accounting Rule</h4>
|
||||||
</mat-radio-button>
|
</div>
|
||||||
}
|
<div class="lpa-radio-group">
|
||||||
</mat-radio-group>
|
<mat-radio-button [value]="2" [checked]="true" [disabled]="true">Cash</mat-radio-button>
|
||||||
|
</div>
|
||||||
|
@if (isAccrualAccounting()) {
|
||||||
|
<div class="lpa-checkbox-row">
|
||||||
|
<mat-checkbox formControlName="enableAccrualActivityPosting">{{
|
||||||
|
'labels.inputs.Enable Accrual Activity Posting on Installment Due Date' | translate
|
||||||
|
}}</mat-checkbox>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
@if (isAccountingAccrualBased) {
|
|
||||||
<div class="lpa-full-width lpa-checkbox-row">
|
<!-- Main Accounting Sections -->
|
||||||
<mat-checkbox formControlName="enableAccrualActivityPosting">{{
|
@for (section of accountingSectionConfigs; track section.key) {
|
||||||
'labels.inputs.Enable Accrual Activity Posting on Installment Due Date' | translate
|
<div class="lpa-group">
|
||||||
}}</mat-checkbox>
|
<div class="lpa-group__header">
|
||||||
|
<h4>{{ section.title }}</h4>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="lpa-add-other-btn"
|
||||||
|
(click)="addOtherGlMapping(section.otherMappingsControlName)"
|
||||||
|
>
|
||||||
|
+ Add Other
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="lpa-list">
|
||||||
|
@for (row of section.rows; track row.key) {
|
||||||
|
@if (
|
||||||
|
(!row.accrualOnly || isAccrualAccounting()) &&
|
||||||
|
(!row.deferredOnly || isDeferredOnly()) &&
|
||||||
|
(!row.deferredCapitalizationOnly || isDeferredCapitalizationOnly()) &&
|
||||||
|
(!row.deferredBuyDownOnly || isDeferredBuyDownOnly()) &&
|
||||||
|
(!row.deferredBuyDownMerchantOnly || isDeferredBuyDownMerchantOnly())
|
||||||
|
) {
|
||||||
|
<div class="lpa-row">
|
||||||
|
<div class="lpa-row__meta">
|
||||||
|
<span
|
||||||
|
class="lpa-pill"
|
||||||
|
[class.lpa-pill--green]="section.pillClass === 'green'"
|
||||||
|
[class.lpa-pill--amber]="section.pillClass === 'amber'"
|
||||||
|
[class.lpa-pill--blue]="section.pillClass === 'blue'"
|
||||||
|
>
|
||||||
|
{{ section.pillLabel }}
|
||||||
|
</span>
|
||||||
|
<span class="lpa-row__label">{{ row.label }}</span>
|
||||||
|
</div>
|
||||||
|
<mifosx-gl-account-selector
|
||||||
|
class="lpa-row__input"
|
||||||
|
[inputFormControl]="loanProductAccountingForm.get(row.controlName)"
|
||||||
|
[glAccountList]="row.options"
|
||||||
|
[required]="row.required"
|
||||||
|
[inputLabel]="row.inputLabel"
|
||||||
|
></mifosx-gl-account-selector>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Other GL Mappings -->
|
||||||
|
<div class="lpa-list" [formArrayName]="section.otherMappingsControlName">
|
||||||
|
@for (
|
||||||
|
otherRow of getOtherGlMappingsArray(section.otherMappingsControlName).controls;
|
||||||
|
track $index;
|
||||||
|
let i = $index
|
||||||
|
) {
|
||||||
|
<div class="lpa-other-row-wrap">
|
||||||
|
<div class="lpa-row lpa-row--other" [formGroupName]="i">
|
||||||
|
<div class="lpa-row__meta lpa-row__meta--other">
|
||||||
|
<span
|
||||||
|
class="lpa-pill"
|
||||||
|
[class.lpa-pill--green]="section.pillClass === 'green'"
|
||||||
|
[class.lpa-pill--amber]="section.pillClass === 'amber'"
|
||||||
|
[class.lpa-pill--blue]="section.pillClass === 'blue'"
|
||||||
|
>
|
||||||
|
{{ section.pillLabel }}
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
class="lpa-row__name lpa-row__name--other-account"
|
||||||
|
formControlName="accountName"
|
||||||
|
placeholder="Enter account name..."
|
||||||
|
type="text"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="lpa-row__actions lpa-row__actions--other">
|
||||||
|
<mat-form-field class="lpa-row__other-field" appearance="outline" subscriptSizing="dynamic">
|
||||||
|
<mat-label>GL Code</mat-label>
|
||||||
|
<mat-select
|
||||||
|
[formControl]="getOtherGlMappingControl(section.otherMappingsControlName, i, 'glAccountId')"
|
||||||
|
>
|
||||||
|
@for (glAccount of section.otherAccountOptions; track glAccount.id) {
|
||||||
|
<mat-option [value]="glAccount.id">
|
||||||
|
{{ '(' + glAccount.glCode + ') ' + glAccount.name }}
|
||||||
|
</mat-option>
|
||||||
|
}
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="lpa-remove-btn lpa-remove-btn--side"
|
||||||
|
(click)="removeOtherGlMapping(section.otherMappingsControlName, i)"
|
||||||
|
>
|
||||||
|
<i class="fas fa-times"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- Advanced Accounting Rules Section -->
|
||||||
|
@if (loanProductAccountingForm.value.accountingRule >= 2 && loanProductAccountingForm.value.accountingRule <= 4) {
|
||||||
|
<div class="lpa-group">
|
||||||
|
<div class="lpa-group__header">
|
||||||
|
<h4>Advanced Accounting Rules</h4>
|
||||||
|
</div>
|
||||||
|
<div class="lpa-checkbox-row">
|
||||||
|
<mat-checkbox formControlName="advancedAccountingRules">{{
|
||||||
|
'labels.heading.Advanced Accounting Rules' | translate
|
||||||
|
}}</mat-checkbox>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (loanProductAccountingForm.value.advancedAccountingRules) {
|
||||||
|
<!-- Payment Fund Sources -->
|
||||||
|
<div class="lpa-subsection">
|
||||||
|
<div class="lpa-subsection-header">
|
||||||
|
<h4>{{ 'labels.heading.Configure Fund Sources for Payment Channels' | translate }}</h4>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
mat-raised-button
|
||||||
|
color="primary"
|
||||||
|
class="lpa-add-btn"
|
||||||
|
(click)="add('PaymentFundSource', paymentChannelToFundSourceMappings)"
|
||||||
|
>
|
||||||
|
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||||
|
{{ 'labels.buttons.Add' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
@if (paymentChannelToFundSourceMappings.value.length !== 0) {
|
||||||
|
<div class="lpa-table-wrapper">
|
||||||
|
<table 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>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Fees to Income -->
|
||||||
|
<div class="lpa-subsection">
|
||||||
|
<div class="lpa-subsection-header">
|
||||||
|
<h4>{{ 'labels.heading.Map Fees to Specific Income Accounts' | translate }}</h4>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
mat-raised-button
|
||||||
|
color="primary"
|
||||||
|
class="lpa-add-btn"
|
||||||
|
(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) {
|
||||||
|
<div class="lpa-table-wrapper">
|
||||||
|
<table 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>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Penalties to Income -->
|
||||||
|
<div class="lpa-subsection">
|
||||||
|
<div class="lpa-subsection-header">
|
||||||
|
<h4>{{ 'labels.heading.Map Penalties to Specific Income Accounts' | translate }}</h4>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
mat-raised-button
|
||||||
|
color="primary"
|
||||||
|
class="lpa-add-btn"
|
||||||
|
(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) {
|
||||||
|
<div class="lpa-table-wrapper">
|
||||||
|
<table 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>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Charge-off Reasons to Expense -->
|
||||||
|
<div class="lpa-subsection">
|
||||||
|
<div class="lpa-subsection-header">
|
||||||
|
<h4>{{ 'labels.heading.Map Charge-off reasons to Expense accounts' | translate }}</h4>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
mat-raised-button
|
||||||
|
color="primary"
|
||||||
|
class="lpa-add-btn"
|
||||||
|
[disabled]="!allowAddChargeOffReasonExpense"
|
||||||
|
(click)="add('ChargeOffReasonExpense', chargeOffReasonToExpenseAccountMappings)"
|
||||||
|
>
|
||||||
|
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||||
|
{{ 'labels.buttons.Add' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
@if (chargeOffReasonToExpenseAccountMappings.value.length !== 0) {
|
||||||
|
<div class="lpa-table-wrapper">
|
||||||
|
<table 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>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Advanced Mapping Rule Components -->
|
||||||
|
<mifosx-advanced-accounting-mapping-rule
|
||||||
|
class="lpa-full-width"
|
||||||
|
[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="lpa-full-width"
|
||||||
|
[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="lpa-full-width"
|
||||||
|
[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>
|
</div>
|
||||||
|
|
||||||
@if (loanProductAccountingForm.value.accountingRule >= 2 && loanProductAccountingForm.value.accountingRule <= 4) {
|
|
||||||
<!-- Assets / Liabilities Section -->
|
|
||||||
<div class="lpa-section">
|
|
||||||
<div class="lpa-section-header">
|
|
||||||
<i class="fas fa-university lpa-section-icon"></i>
|
|
||||||
<h3>{{ 'labels.heading.Assets' | translate }} / {{ 'labels.heading.Liabilities' | translate }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="lpa-section-body lpa-grid">
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.fundSourceAccountId"
|
|
||||||
[glAccountList]="assetAndLiabilityAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Fund source'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Assets Section -->
|
|
||||||
<div class="lpa-section">
|
|
||||||
<div class="lpa-section-header">
|
|
||||||
<i class="fas fa-university lpa-section-icon"></i>
|
|
||||||
<h3>{{ 'labels.heading.Assets' | translate }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="lpa-section-body lpa-grid">
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.loanPortfolioAccountId"
|
|
||||||
[glAccountList]="assetAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Loan portfolio'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[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
|
|
||||||
) {
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.receivableInterestAccountId"
|
|
||||||
[glAccountList]="assetAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Interest Receivable'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.receivableFeeAccountId"
|
|
||||||
[glAccountList]="assetAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Fees Receivable'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.receivablePenaltyAccountId"
|
|
||||||
[glAccountList]="assetAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Penalties Receivable'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Income Section -->
|
|
||||||
<div class="lpa-section">
|
|
||||||
<div class="lpa-section-header">
|
|
||||||
<i class="fas fa-chart-line lpa-section-icon"></i>
|
|
||||||
<h3>{{ 'labels.heading.Income' | translate }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="lpa-section-body lpa-grid">
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.interestOnLoanAccountId"
|
|
||||||
[glAccountList]="incomeAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Income from Interest'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromFeeAccountId"
|
|
||||||
[glAccountList]="incomeAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Income from fees'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromPenaltyAccountId"
|
|
||||||
[glAccountList]="incomeAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Income from penalties'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromRecoveryAccountId"
|
|
||||||
[glAccountList]="incomeAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Income from Recovery Repayments'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromChargeOffInterestAccountId"
|
|
||||||
[glAccountList]="incomeAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Income from ChargeOff Interest'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromChargeOffFeesAccountId"
|
|
||||||
[glAccountList]="incomeAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Income from ChargeOff Fees'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromChargeOffPenaltyAccountId"
|
|
||||||
[glAccountList]="incomeAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Income from ChargeOff Penalty'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromGoodwillCreditInterestAccountId"
|
|
||||||
[glAccountList]="incomeAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Income from Goodwill Credit Interest'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromGoodwillCreditFeesAccountId"
|
|
||||||
[glAccountList]="incomeAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Income from Goodwill Credit Fees'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[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
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromCapitalizationAccountId"
|
|
||||||
[glAccountList]="incomeAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Income capitalization'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
}
|
|
||||||
@if (deferredIncomeRecognition?.buyDownFee?.enableBuyDownFee) {
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromBuyDownAccountId"
|
|
||||||
[glAccountList]="incomeAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Income from Buy down fees'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Expenses Section -->
|
|
||||||
<div class="lpa-section">
|
|
||||||
<div class="lpa-section-header">
|
|
||||||
<i class="fas fa-money-bill-wave lpa-section-icon"></i>
|
|
||||||
<h3>{{ 'labels.heading.Expenses' | translate }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="lpa-section-body lpa-grid">
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.writeOffAccountId"
|
|
||||||
[glAccountList]="expenseAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Losses written off'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.goodwillCreditAccountId"
|
|
||||||
[glAccountList]="expenseAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Expenses from Goodwill Credit'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.chargeOffExpenseAccountId"
|
|
||||||
[glAccountList]="expenseAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'ChargeOff Expense'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.chargeOffFraudExpenseAccountId"
|
|
||||||
[glAccountList]="expenseAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'ChargeOff Fraud Expense'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
@if (
|
|
||||||
deferredIncomeRecognition?.buyDownFee?.enableBuyDownFee &&
|
|
||||||
deferredIncomeRecognition?.buyDownFee?.merchantBuyDownFee
|
|
||||||
) {
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.buyDownExpenseAccountId"
|
|
||||||
[glAccountList]="expenseAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Buy down fee Expense'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Liabilities Section -->
|
|
||||||
<div class="lpa-section">
|
|
||||||
<div class="lpa-section-header">
|
|
||||||
<i class="fas fa-file-invoice-dollar lpa-section-icon"></i>
|
|
||||||
<h3>{{ 'labels.heading.Liabilities' | translate }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="lpa-section-body lpa-grid">
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.overpaymentLiabilityAccountId"
|
|
||||||
[glAccountList]="liabilityAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Over payment liability'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
@if (
|
|
||||||
deferredIncomeRecognition?.capitalizedIncome?.enableIncomeCapitalization ||
|
|
||||||
deferredIncomeRecognition?.buyDownFee?.enableBuyDownFee
|
|
||||||
) {
|
|
||||||
<mifosx-gl-account-selector
|
|
||||||
[inputFormControl]="loanProductAccountingForm.controls.deferredIncomeLiabilityAccountId"
|
|
||||||
[glAccountList]="liabilityAccountData"
|
|
||||||
[required]="true"
|
|
||||||
[inputLabel]="'Deferred income'"
|
|
||||||
>
|
|
||||||
</mifosx-gl-account-selector>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Advanced Accounting Rules Section -->
|
|
||||||
<div class="lpa-section">
|
|
||||||
<div class="lpa-section-header">
|
|
||||||
<i class="fas fa-cogs lpa-section-icon"></i>
|
|
||||||
<h3>{{ 'labels.heading.Advanced Accounting Rules' | translate }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="lpa-section-body">
|
|
||||||
<div class="lpa-full-width lpa-checkbox-row">
|
|
||||||
<mat-checkbox formControlName="advancedAccountingRules">{{
|
|
||||||
'labels.heading.Advanced Accounting Rules' | translate
|
|
||||||
}}</mat-checkbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (loanProductAccountingForm.value.advancedAccountingRules) {
|
|
||||||
<!-- Payment Fund Sources -->
|
|
||||||
<div class="lpa-subsection">
|
|
||||||
<div class="lpa-subsection-header">
|
|
||||||
<h4>{{ 'labels.heading.Configure Fund Sources for Payment Channels' | translate }}</h4>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
mat-raised-button
|
|
||||||
color="primary"
|
|
||||||
class="lpa-add-btn"
|
|
||||||
(click)="add('PaymentFundSource', paymentChannelToFundSourceMappings)"
|
|
||||||
>
|
|
||||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
|
||||||
{{ 'labels.buttons.Add' | translate }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
@if (paymentChannelToFundSourceMappings.value.length !== 0) {
|
|
||||||
<div class="lpa-table-wrapper">
|
|
||||||
<table 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>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Fees to Income -->
|
|
||||||
<div class="lpa-subsection">
|
|
||||||
<div class="lpa-subsection-header">
|
|
||||||
<h4>{{ 'labels.heading.Map Fees to Specific Income Accounts' | translate }}</h4>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
mat-raised-button
|
|
||||||
color="primary"
|
|
||||||
class="lpa-add-btn"
|
|
||||||
(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) {
|
|
||||||
<div class="lpa-table-wrapper">
|
|
||||||
<table 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>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Penalties to Income -->
|
|
||||||
<div class="lpa-subsection">
|
|
||||||
<div class="lpa-subsection-header">
|
|
||||||
<h4>{{ 'labels.heading.Map Penalties to Specific Income Accounts' | translate }}</h4>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
mat-raised-button
|
|
||||||
color="primary"
|
|
||||||
class="lpa-add-btn"
|
|
||||||
(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) {
|
|
||||||
<div class="lpa-table-wrapper">
|
|
||||||
<table 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>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Charge-off Reasons to Expense -->
|
|
||||||
<div class="lpa-subsection">
|
|
||||||
<div class="lpa-subsection-header">
|
|
||||||
<h4>{{ 'labels.heading.Map Charge-off reasons to Expense accounts' | translate }}</h4>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
mat-raised-button
|
|
||||||
color="primary"
|
|
||||||
class="lpa-add-btn"
|
|
||||||
[disabled]="!allowAddChargeOffReasonExpense"
|
|
||||||
(click)="add('ChargeOffReasonExpense', chargeOffReasonToExpenseAccountMappings)"
|
|
||||||
>
|
|
||||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
|
||||||
{{ 'labels.buttons.Add' | translate }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
@if (chargeOffReasonToExpenseAccountMappings.value.length !== 0) {
|
|
||||||
<div class="lpa-table-wrapper">
|
|
||||||
<table 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>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Advanced Mapping Rule Components -->
|
|
||||||
<mifosx-advanced-accounting-mapping-rule
|
|
||||||
class="lpa-full-width"
|
|
||||||
[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="lpa-full-width"
|
|
||||||
[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="lpa-full-width"
|
|
||||||
[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>
|
|
||||||
}
|
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
+283
-79
@@ -6,124 +6,328 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Section cards
|
$border: #e2e8f0;
|
||||||
|
$gray-50: #f8f9fa;
|
||||||
|
$gray-200: #e8eaed;
|
||||||
|
$gray-500: #6b7280;
|
||||||
|
$gray-700: #334155;
|
||||||
|
$gray-900: #202124;
|
||||||
|
$primary: #1353a0;
|
||||||
|
|
||||||
.lpa-section {
|
.lpa-section {
|
||||||
border: 1px solid #e2e8f0;
|
border: 1px solid $border;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|
||||||
& + & {
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Section header
|
.lpa-section__header {
|
||||||
.lpa-section-header {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
padding: 12px 24px;
|
padding: 12px 24px;
|
||||||
background: #f8f9fa;
|
background: $gray-50;
|
||||||
border-bottom: 1px solid #e8eaed;
|
border-bottom: 1px solid $gray-200;
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
|
margin: 0;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #202124;
|
color: $gray-900;
|
||||||
margin: 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.lpa-section-icon {
|
.lpa-section__icon {
|
||||||
color: #0ea5e9;
|
display: inline-flex;
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Section body
|
|
||||||
.lpa-section-body {
|
|
||||||
padding: 16px 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2-column grid
|
|
||||||
.lpa-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
gap: 4px 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Full width utility
|
|
||||||
.lpa-full-width {
|
|
||||||
grid-column: 1 / -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Radio group
|
|
||||||
.lpa-radio-group {
|
|
||||||
display: flex;
|
|
||||||
gap: 24px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checkbox row
|
|
||||||
.lpa-checkbox-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 4px 0;
|
justify-content: center;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: #eff6ff;
|
||||||
|
color: #2563eb;
|
||||||
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subsections inside advanced rules
|
.lpa-section__body {
|
||||||
.lpa-subsection {
|
padding: 16px 24px 20px;
|
||||||
padding: 16px 24px;
|
|
||||||
border-top: 1px solid #e8eaed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.lpa-subsection-header {
|
.lpa-group {
|
||||||
display: flex;
|
& + & {
|
||||||
justify-content: space-between;
|
margin-top: 20px;
|
||||||
align-items: center;
|
}
|
||||||
margin-bottom: 12px;
|
|
||||||
|
&__header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 16px;
|
||||||
|
margin: 0 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #202124;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: #94a3b8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add buttons
|
.lpa-add-other-btn {
|
||||||
.lpa-add-btn {
|
border: 0;
|
||||||
height: 32px;
|
background: transparent;
|
||||||
border-radius: 8px;
|
color: #2563eb;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Table wrapper
|
.lpa-list {
|
||||||
.lpa-table-wrapper {
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
& + & {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lpa-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 16px;
|
||||||
|
padding: 10px 12px;
|
||||||
border: 1px solid #e2e8f0;
|
border: 1px solid #e2e8f0;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
@media (width <= 900px) {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:has(mifosx-gl-account-selector) {
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lpa-row--other {
|
||||||
|
border-style: dashed;
|
||||||
|
border-color: #cbd5e1;
|
||||||
|
background: #f8fafc;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
|
||||||
|
align-items: center;
|
||||||
|
padding: 12px 16px;
|
||||||
|
|
||||||
|
@media (width <= 1100px) {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lpa-other-row-wrap {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
@media (width <= 1100px) {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lpa-row__meta {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
min-width: 0;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
|
||||||
|
&--other {
|
||||||
|
min-width: 0;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lpa-row__label {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: $gray-700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lpa-row__input {
|
||||||
|
flex: 0 0 22rem;
|
||||||
|
max-width: 22rem;
|
||||||
|
min-width: 18rem;
|
||||||
|
|
||||||
|
@media (width <= 900px) {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(mifosx-gl-account-selector) {
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
:is(.layout-column) {
|
||||||
|
width: 100%;
|
||||||
|
margin-right: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(mat-form-field) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lpa-row__actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
min-width: 0;
|
||||||
|
|
||||||
|
&--other {
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-self: stretch;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
@media (width <= 1100px) {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lpa-row__name {
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 24rem;
|
||||||
|
height: 40px;
|
||||||
|
border: 1px solid #cbd5e1;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 0 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
@media (width <= 900px) {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--other-account {
|
||||||
|
max-width: 100%;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
height: 48px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lpa-row__other-field {
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
|
||||||
|
:is(mat-form-field) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:is(.mat-mdc-form-field-required-marker) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lpa-remove-btn {
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: #ef4444;
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0 4px;
|
||||||
|
|
||||||
|
&--side {
|
||||||
|
place-self: center end;
|
||||||
|
margin-right: 4px;
|
||||||
|
|
||||||
|
@media (width <= 1100px) {
|
||||||
|
justify-self: start;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lpa-pill {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 999px;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&--green {
|
||||||
|
background: #dcfce7;
|
||||||
|
color: #16a34a;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--amber {
|
||||||
|
background: #fef3c7;
|
||||||
|
color: #d97706;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--blue {
|
||||||
|
background: #dbeafe;
|
||||||
|
color: #2563eb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advanced Accounting Subsection styles
|
||||||
|
.lpa-subsection {
|
||||||
|
margin-top: 24px;
|
||||||
|
padding-top: 24px;
|
||||||
|
border-top: 1px solid $border;
|
||||||
|
|
||||||
|
&-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
margin: 0;
|
||||||
|
color: $gray-700;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lpa-table-wrapper {
|
||||||
|
border: 1px solid $border;
|
||||||
|
border-radius: 8px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin-top: 8px;
|
|
||||||
|
|
||||||
table {
|
table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Responsive
|
.lpa-checkbox-row {
|
||||||
@media (width <= 600px) {
|
margin-top: 12px;
|
||||||
.lpa-grid {
|
}
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lpa-radio-group {
|
.lpa-radio-group {
|
||||||
flex-direction: column;
|
display: flex;
|
||||||
}
|
gap: 16px;
|
||||||
|
|
||||||
.lpa-subsection-header {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+550
-417
File diff suppressed because it is too large
Load Diff
-57
@@ -57,61 +57,4 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lpc-section">
|
|
||||||
<div class="lpc-section__header">
|
|
||||||
<i class="fas fa-calculator"></i>
|
|
||||||
<h3>{{ 'labels.inputs.Multiples' | translate }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="lpc-grid">
|
|
||||||
<div class="lpc-field--full lpc-checkbox-row">
|
|
||||||
<mat-checkbox labelPosition="before" formControlName="setMultiples">
|
|
||||||
{{ 'labels.inputs.Set the multiples of the loan and its installment' | translate }}
|
|
||||||
</mat-checkbox>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (loanProductCurrencyForm.value.setMultiples) {
|
|
||||||
<mat-form-field appearance="outline" class="lpc-field">
|
|
||||||
<mat-label>{{ 'labels.inputs.Currency in multiples of' | translate }}</mat-label>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
min="1"
|
|
||||||
matInput
|
|
||||||
matTooltip="{{ 'tooltips.Enter multiples of currency value' | translate }}"
|
|
||||||
formControlName="inMultiplesOf"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
@if (loanProductCurrencyForm.get('inMultiplesOf')?.hasError('required')) {
|
|
||||||
<mat-error>
|
|
||||||
{{ 'labels.inputs.Currency in multiples of' | translate }} {{ 'labels.commons.is' | translate }}
|
|
||||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
|
||||||
</mat-error>
|
|
||||||
}
|
|
||||||
@if (loanProductCurrencyForm.get('inMultiplesOf')?.hasError('min')) {
|
|
||||||
<mat-error>
|
|
||||||
{{ 'labels.inputs.Currency in multiples of' | translate }}
|
|
||||||
{{ 'labels.commons.Minimum Value must be' | translate }} <strong>1</strong>
|
|
||||||
</mat-error>
|
|
||||||
}
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<mat-form-field appearance="outline" class="lpc-field">
|
|
||||||
<mat-label>{{ 'labels.inputs.Installment in multiples of' | translate }}</mat-label>
|
|
||||||
<input type="number" min="1" matInput formControlName="installmentAmountInMultiplesOf" required />
|
|
||||||
@if (loanProductCurrencyForm.get('installmentAmountInMultiplesOf')?.hasError('required')) {
|
|
||||||
<mat-error>
|
|
||||||
{{ 'labels.inputs.Installment in multiples of' | translate }} {{ 'labels.commons.is' | translate }}
|
|
||||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
|
||||||
</mat-error>
|
|
||||||
}
|
|
||||||
@if (loanProductCurrencyForm.get('installmentAmountInMultiplesOf')?.hasError('min')) {
|
|
||||||
<mat-error>
|
|
||||||
{{ 'labels.inputs.Installment in multiples of' | translate }}
|
|
||||||
{{ 'labels.commons.Minimum Value must be' | translate }} <strong>1</strong>
|
|
||||||
</mat-error>
|
|
||||||
}
|
|
||||||
</mat-form-field>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
+3
-86
@@ -9,8 +9,6 @@
|
|||||||
import { Component, OnInit, Input, inject } from '@angular/core';
|
import { Component, OnInit, Input, inject } from '@angular/core';
|
||||||
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { MatTooltip } from '@angular/material/tooltip';
|
import { MatTooltip } from '@angular/material/tooltip';
|
||||||
import { MatCheckbox } from '@angular/material/checkbox';
|
|
||||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
|
||||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -19,9 +17,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
|||||||
styleUrls: ['./loan-product-currency-step.component.scss'],
|
styleUrls: ['./loan-product-currency-step.component.scss'],
|
||||||
imports: [
|
imports: [
|
||||||
...STANDALONE_SHARED_IMPORTS,
|
...STANDALONE_SHARED_IMPORTS,
|
||||||
MatTooltip,
|
MatTooltip
|
||||||
MatCheckbox,
|
|
||||||
FaIconComponent
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class LoanProductCurrencyStepComponent implements OnInit {
|
export class LoanProductCurrencyStepComponent implements OnInit {
|
||||||
@@ -46,69 +42,8 @@ export class LoanProductCurrencyStepComponent implements OnInit {
|
|||||||
this.loanProductsTemplate.currency.decimalPlaces === undefined ||
|
this.loanProductsTemplate.currency.decimalPlaces === undefined ||
|
||||||
this.loanProductsTemplate.currency.decimalPlaces === null
|
this.loanProductsTemplate.currency.decimalPlaces === null
|
||||||
? ''
|
? ''
|
||||||
: this.loanProductsTemplate.currency.decimalPlaces,
|
: this.loanProductsTemplate.currency.decimalPlaces
|
||||||
setMultiples: !!(
|
|
||||||
(this.loanProductsTemplate.currency.inMultiplesOf && this.loanProductsTemplate.currency.inMultiplesOf !== 0) ||
|
|
||||||
(this.loanProductsTemplate.installmentAmountInMultiplesOf &&
|
|
||||||
this.loanProductsTemplate.installmentAmountInMultiplesOf !== 0)
|
|
||||||
),
|
|
||||||
inMultiplesOf:
|
|
||||||
this.loanProductsTemplate.currency.inMultiplesOf === 0 ||
|
|
||||||
this.loanProductsTemplate.currency.inMultiplesOf === undefined ||
|
|
||||||
this.loanProductsTemplate.currency.inMultiplesOf === null
|
|
||||||
? ''
|
|
||||||
: this.loanProductsTemplate.currency.inMultiplesOf,
|
|
||||||
installmentAmountInMultiplesOf:
|
|
||||||
this.loanProductsTemplate.installmentAmountInMultiplesOf === 0 ||
|
|
||||||
this.loanProductsTemplate.installmentAmountInMultiplesOf === undefined ||
|
|
||||||
this.loanProductsTemplate.installmentAmountInMultiplesOf === null
|
|
||||||
? ''
|
|
||||||
: this.loanProductsTemplate.installmentAmountInMultiplesOf
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setupConditionalValidation();
|
|
||||||
}
|
|
||||||
|
|
||||||
setupConditionalValidation() {
|
|
||||||
this.loanProductCurrencyForm.get('setMultiples')?.valueChanges.subscribe((setMultiples: boolean) => {
|
|
||||||
const inMultiplesOfControl = this.loanProductCurrencyForm.get('inMultiplesOf');
|
|
||||||
const installmentControl = this.loanProductCurrencyForm.get('installmentAmountInMultiplesOf');
|
|
||||||
|
|
||||||
if (setMultiples) {
|
|
||||||
inMultiplesOfControl?.setValidators([
|
|
||||||
Validators.required,
|
|
||||||
Validators.min(1)
|
|
||||||
]);
|
|
||||||
installmentControl?.setValidators([
|
|
||||||
Validators.required,
|
|
||||||
Validators.min(1)
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
inMultiplesOfControl?.clearValidators();
|
|
||||||
installmentControl?.clearValidators();
|
|
||||||
inMultiplesOfControl?.setValue('');
|
|
||||||
installmentControl?.setValue('');
|
|
||||||
}
|
|
||||||
|
|
||||||
inMultiplesOfControl?.updateValueAndValidity();
|
|
||||||
installmentControl?.updateValueAndValidity();
|
|
||||||
});
|
|
||||||
|
|
||||||
const initialSetMultiples = this.loanProductCurrencyForm.get('setMultiples')?.value;
|
|
||||||
if (initialSetMultiples) {
|
|
||||||
const inMultiplesOfControl = this.loanProductCurrencyForm.get('inMultiplesOf');
|
|
||||||
const installmentControl = this.loanProductCurrencyForm.get('installmentAmountInMultiplesOf');
|
|
||||||
inMultiplesOfControl?.setValidators([
|
|
||||||
Validators.required,
|
|
||||||
Validators.min(1)
|
|
||||||
]);
|
|
||||||
installmentControl?.setValidators([
|
|
||||||
Validators.required,
|
|
||||||
Validators.min(1)
|
|
||||||
]);
|
|
||||||
inMultiplesOfControl?.updateValueAndValidity();
|
|
||||||
installmentControl?.updateValueAndValidity();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createLoanProductCurrencyForm() {
|
createLoanProductCurrencyForm() {
|
||||||
@@ -123,10 +58,7 @@ export class LoanProductCurrencyStepComponent implements OnInit {
|
|||||||
Validators.required,
|
Validators.required,
|
||||||
Validators.min(0)
|
Validators.min(0)
|
||||||
]
|
]
|
||||||
],
|
]
|
||||||
setMultiples: [false],
|
|
||||||
inMultiplesOf: [''],
|
|
||||||
installmentAmountInMultiplesOf: ['']
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,21 +68,6 @@ export class LoanProductCurrencyStepComponent implements OnInit {
|
|||||||
currencyCode: formValue.currencyCode,
|
currencyCode: formValue.currencyCode,
|
||||||
digitsAfterDecimal: formValue.digitsAfterDecimal
|
digitsAfterDecimal: formValue.digitsAfterDecimal
|
||||||
};
|
};
|
||||||
|
|
||||||
if (formValue.setMultiples) {
|
|
||||||
if (formValue.inMultiplesOf !== '' && formValue.inMultiplesOf !== null && formValue.inMultiplesOf !== undefined) {
|
|
||||||
result.inMultiplesOf = formValue.inMultiplesOf;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
formValue.installmentAmountInMultiplesOf !== '' &&
|
|
||||||
formValue.installmentAmountInMultiplesOf !== null &&
|
|
||||||
formValue.installmentAmountInMultiplesOf !== undefined
|
|
||||||
) {
|
|
||||||
result.installmentAmountInMultiplesOf = formValue.installmentAmountInMultiplesOf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-30
@@ -41,36 +41,6 @@
|
|||||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field appearance="outline" class="lpd-field">
|
|
||||||
<mat-label>{{ 'labels.inputs.External Id' | translate }}</mat-label>
|
|
||||||
<input
|
|
||||||
matInput
|
|
||||||
formControlName="externalId"
|
|
||||||
matTooltip="{{ 'tooltips.External Id is a unique identifier' | translate }}"
|
|
||||||
/>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<mat-form-field appearance="outline" class="lpd-field">
|
|
||||||
<mat-label>{{ 'labels.inputs.Fund' | translate }}</mat-label>
|
|
||||||
<mat-select matTooltip="{{ 'tooltips.Loan products may be assigned' | translate }}" formControlName="fundId">
|
|
||||||
@for (fund of fundData; track fund) {
|
|
||||||
<mat-option [value]="fund.id">
|
|
||||||
{{ fund.name }}
|
|
||||||
</mat-option>
|
|
||||||
}
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<div class="lpd-field lpd-checkbox-row">
|
|
||||||
<mat-checkbox
|
|
||||||
labelPosition="before"
|
|
||||||
matTooltip="{{ 'tooltips.A borrower loan counter (cycle)' | translate }}"
|
|
||||||
formControlName="includeInBorrowerCycle"
|
|
||||||
>
|
|
||||||
{{ 'labels.inputs.Include in Customer Loan Counter' | translate }}
|
|
||||||
</mat-checkbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
+3
-17
@@ -14,9 +14,7 @@ import { Dates } from 'app/core/utils/dates';
|
|||||||
/** Custom Services */
|
/** Custom Services */
|
||||||
import { SettingsService } from 'app/settings/settings.service';
|
import { SettingsService } from 'app/settings/settings.service';
|
||||||
import { MatTooltip } from '@angular/material/tooltip';
|
import { MatTooltip } from '@angular/material/tooltip';
|
||||||
import { MatCheckbox } from '@angular/material/checkbox';
|
|
||||||
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
||||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
|
||||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -26,9 +24,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
|||||||
imports: [
|
imports: [
|
||||||
...STANDALONE_SHARED_IMPORTS,
|
...STANDALONE_SHARED_IMPORTS,
|
||||||
MatTooltip,
|
MatTooltip,
|
||||||
MatCheckbox,
|
CdkTextareaAutosize
|
||||||
CdkTextareaAutosize,
|
|
||||||
FaIconComponent
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class LoanProductDetailsStepComponent implements OnInit {
|
export class LoanProductDetailsStepComponent implements OnInit {
|
||||||
@@ -40,8 +36,6 @@ export class LoanProductDetailsStepComponent implements OnInit {
|
|||||||
|
|
||||||
loanProductDetailsForm: UntypedFormGroup;
|
loanProductDetailsForm: UntypedFormGroup;
|
||||||
|
|
||||||
fundData: any;
|
|
||||||
|
|
||||||
minDate = new Date(2000, 0, 1);
|
minDate = new Date(2000, 0, 1);
|
||||||
maxDate = new Date(new Date().setFullYear(new Date().getFullYear() + 10));
|
maxDate = new Date(new Date().setFullYear(new Date().getFullYear() + 10));
|
||||||
|
|
||||||
@@ -56,17 +50,12 @@ export class LoanProductDetailsStepComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.fundData = this.loanProductsTemplate.fundOptions;
|
|
||||||
|
|
||||||
this.loanProductDetailsForm.patchValue({
|
this.loanProductDetailsForm.patchValue({
|
||||||
name: this.loanProductsTemplate.name,
|
name: this.loanProductsTemplate.name,
|
||||||
shortName: this.loanProductsTemplate.shortName,
|
shortName: this.loanProductsTemplate.shortName,
|
||||||
description: this.loanProductsTemplate.description,
|
description: this.loanProductsTemplate.description,
|
||||||
externalId: this.loanProductsTemplate.externalId,
|
|
||||||
fundId: this.loanProductsTemplate.fundId,
|
|
||||||
startDate: this.loanProductsTemplate.startDate && new Date(this.loanProductsTemplate.startDate),
|
startDate: this.loanProductsTemplate.startDate && new Date(this.loanProductsTemplate.startDate),
|
||||||
closeDate: this.loanProductsTemplate.closeDate && new Date(this.loanProductsTemplate.closeDate),
|
closeDate: this.loanProductsTemplate.closeDate && new Date(this.loanProductsTemplate.closeDate)
|
||||||
includeInBorrowerCycle: this.loanProductsTemplate.includeInBorrowerCycle
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,11 +70,8 @@ export class LoanProductDetailsStepComponent implements OnInit {
|
|||||||
Validators.required
|
Validators.required
|
||||||
],
|
],
|
||||||
description: [''],
|
description: [''],
|
||||||
externalId: [''],
|
|
||||||
fundId: [''],
|
|
||||||
startDate: [''],
|
startDate: [''],
|
||||||
closeDate: [''],
|
closeDate: ['']
|
||||||
includeInBorrowerCycle: [false]
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-1
@@ -10,7 +10,6 @@
|
|||||||
[action]="'preview'"
|
[action]="'preview'"
|
||||||
[loanProduct]="loanProduct"
|
[loanProduct]="loanProduct"
|
||||||
[loanProductsTemplate]="loanProductsTemplate"
|
[loanProductsTemplate]="loanProductsTemplate"
|
||||||
[useDueForRepaymentsConfigurations]="loanProduct.useDueForRepaymentsConfigurations"
|
|
||||||
[paymentAllocations]="loanProduct.paymentAllocation"
|
[paymentAllocations]="loanProduct.paymentAllocation"
|
||||||
[creditAllocations]="loanProduct.creditAllocation"
|
[creditAllocations]="loanProduct.creditAllocation"
|
||||||
[supportedInterestRefundTypes]="loanProduct.supportedInterestRefundTypes"
|
[supportedInterestRefundTypes]="loanProduct.supportedInterestRefundTypes"
|
||||||
|
|||||||
+507
-174
@@ -235,147 +235,528 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Loan Tranche Details -->
|
<!-- Cheque Book Settings -->
|
||||||
<div class="lps-section">
|
<div class="lps-section">
|
||||||
<div class="lps-section__header">
|
<div class="lps-section__header">
|
||||||
<i class="fas fa-layer-group lps-section__icon"></i>
|
<i class="fas fa-money-check lps-section__icon"></i>
|
||||||
<h3 class="lps-section__title">{{ 'labels.inputs.Loan Tranche Details' | translate }}</h3>
|
<h3 class="lps-section__title">Cheque Book Settings</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="lps-section__body">
|
<div class="lps-section__body lps-grid-4">
|
||||||
<div class="lps-checkbox-row lps-full-width">
|
<mat-form-field appearance="outline">
|
||||||
<mat-checkbox
|
<mat-label>Cheque Book Issue Enabled</mat-label>
|
||||||
labelPosition="before"
|
<mat-select formControlName="chequeBookIssueEnabled">
|
||||||
formControlName="multiDisburseLoan"
|
<mat-option value="YES">YES</mat-option>
|
||||||
matTooltip="{{ 'tooltips.Leave this checkbox unchecked' | translate }}"
|
<mat-option value="NO">NO</mat-option>
|
||||||
>
|
</mat-select>
|
||||||
{{ 'labels.inputs.Enable Multiple Disbursals' | translate }}
|
</mat-form-field>
|
||||||
</mat-checkbox>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (loanProductSettingsForm.value.multiDisburseLoan) {
|
<mat-form-field appearance="outline">
|
||||||
<mat-form-field appearance="outline">
|
<mat-label>Cheque Validation Required</mat-label>
|
||||||
<mat-label>{{ 'labels.inputs.Maximum Tranche count' | translate }}</mat-label>
|
<mat-select formControlName="chequeValidationRequired">
|
||||||
<input
|
<mat-option value="YES">YES</mat-option>
|
||||||
type="number"
|
<mat-option value="NO">NO</mat-option>
|
||||||
matInput
|
</mat-select>
|
||||||
matTooltip="{{ 'tooltips.Maximum number of disbursements' | translate }}"
|
</mat-form-field>
|
||||||
formControlName="maxTrancheCount"
|
|
||||||
required
|
<mat-form-field appearance="outline">
|
||||||
/>
|
<mat-label>Is First Cheque Book Free</mat-label>
|
||||||
@if (loanProductSettingsForm.controls.maxTrancheCount.hasError('required')) {
|
<mat-select formControlName="isFirstChequeBookFree">
|
||||||
<mat-error>
|
<mat-option value="YES">YES</mat-option>
|
||||||
{{ 'labels.inputs.Maximum Tranche count' | translate }} {{ 'labels.commons.is' | translate }}
|
<mat-option value="NO">NO</mat-option>
|
||||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
</mat-select>
|
||||||
</mat-error>
|
</mat-form-field>
|
||||||
}
|
|
||||||
</mat-form-field>
|
<mat-form-field appearance="outline">
|
||||||
<mat-form-field appearance="outline">
|
<mat-label>Cheque Printing Account Type</mat-label>
|
||||||
<mat-label>{{ 'labels.inputs.Maximum allowed outstanding balance' | translate }}</mat-label>
|
<mat-select formControlName="chequePrintingAccountType">
|
||||||
<input
|
<mat-option value="SAVINGS_BANK">Savings Bank</mat-option>
|
||||||
type="number"
|
<mat-option value="CURRENT_ACCOUNT">Current Account</mat-option>
|
||||||
matInput
|
<mat-option value="CASH_CREDIT">Cash Credit</mat-option>
|
||||||
matTooltip="{{ 'tooltips.Maximum outstanding loan account balance' | translate }}"
|
<mat-option value="OVERDRAFT">Overdraft</mat-option>
|
||||||
formControlName="outstandingLoanBalance"
|
</mat-select>
|
||||||
/>
|
</mat-form-field>
|
||||||
</mat-form-field>
|
|
||||||
<div class="lps-checkbox-row">
|
<mat-form-field appearance="outline">
|
||||||
<mat-checkbox labelPosition="before" formControlName="disallowExpectedDisbursements">
|
<mat-label>Allow Withdrawal Slip Usage</mat-label>
|
||||||
{{ 'labels.inputs.Disallow Expected Disbursements' | translate }}
|
<mat-select formControlName="allowWithdrawalSlipUsage">
|
||||||
</mat-checkbox>
|
<mat-option value="YES">YES</mat-option>
|
||||||
</div>
|
<mat-option value="NO">NO</mat-option>
|
||||||
@if (loanProductSettingsForm.value.loanScheduleType === 'PROGRESSIVE') {
|
</mat-select>
|
||||||
<div class="lps-checkbox-row">
|
</mat-form-field>
|
||||||
<mat-checkbox
|
|
||||||
labelPosition="before"
|
<mat-form-field appearance="outline">
|
||||||
formControlName="allowFullTermForTranche"
|
<mat-label>Maintain Cheque Book Stock Registry</mat-label>
|
||||||
matTooltip="{{ 'tooltips.Allow full term length for each tranche disbursement' | translate }}"
|
<mat-select formControlName="maintainChequeBookStockRegistry">
|
||||||
>
|
<mat-option value="YES">YES</mat-option>
|
||||||
{{ 'labels.inputs.Allow full term for each tranche' | translate }}
|
<mat-option value="NO">NO</mat-option>
|
||||||
</mat-checkbox>
|
</mat-select>
|
||||||
</div>
|
</mat-form-field>
|
||||||
}
|
|
||||||
}
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Free Cheque Books Per Year</mat-label>
|
||||||
|
<input type="number" matInput formControlName="freeChequeBooksPerYear" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Allow Credit By Cheque Number</mat-label>
|
||||||
|
<mat-select formControlName="allowCreditByChequeNumber">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Credit Cheque Validation Required</mat-label>
|
||||||
|
<mat-select formControlName="creditChequeValidationRequired">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Grace Days For Stock Statement</mat-label>
|
||||||
|
<input type="number" matInput formControlName="graceDaysForStockStatement" />
|
||||||
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Down Payment -->
|
<!-- Additional Product Settings -->
|
||||||
<div class="lps-section">
|
<div class="lps-section">
|
||||||
<div class="lps-section__header">
|
<div class="lps-section__header">
|
||||||
<i class="fas fa-hand-holding-usd lps-section__icon"></i>
|
<i class="fas fa-cogs lps-section__icon"></i>
|
||||||
<h3 class="lps-section__title">{{ 'labels.heading.Down Payment' | translate }}</h3>
|
<h3 class="lps-section__title">Additional Product Settings</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="lps-section__body">
|
<div class="lps-section__body lps-grid-4">
|
||||||
<div class="lps-checkbox-row lps-full-width">
|
<mat-form-field appearance="outline">
|
||||||
<mat-checkbox
|
<mat-label>Account Type Active For Transactions</mat-label>
|
||||||
labelPosition="before"
|
<mat-select formControlName="accountTypeActiveForTransactions">
|
||||||
formControlName="enableDownPayment"
|
<mat-option value="YES">YES</mat-option>
|
||||||
matTooltip="{{ 'tooltips.Leave this checkbox unchecked' | translate }}"
|
<mat-option value="NO">NO</mat-option>
|
||||||
>
|
</mat-select>
|
||||||
{{ 'labels.inputs.Enable Down Payment' | translate }}
|
</mat-form-field>
|
||||||
</mat-checkbox>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (loanProductSettingsForm.value.enableDownPayment) {
|
<mat-form-field appearance="outline">
|
||||||
<mat-form-field appearance="outline">
|
<mat-label>Sub Type Activity Enabled</mat-label>
|
||||||
<mat-label>{{ 'labels.inputs.Disbursed Amount Percentage Down Payment' | translate }} (%)</mat-label>
|
<mat-select formControlName="subTypeActivityEnabled">
|
||||||
<input
|
<mat-option value="YES">YES</mat-option>
|
||||||
type="number"
|
<mat-option value="NO">NO</mat-option>
|
||||||
matInput
|
</mat-select>
|
||||||
matTooltip="{{ 'tooltips.The percentage of disbursements amount for Down Payment' | translate }}"
|
</mat-form-field>
|
||||||
formControlName="disbursedAmountPercentageForDownPayment"
|
|
||||||
required
|
<mat-form-field appearance="outline">
|
||||||
[min]="0"
|
<mat-label>Account Opening Charges</mat-label>
|
||||||
[max]="100"
|
<input type="number" matInput formControlName="accountOpeningCharges" />
|
||||||
/>
|
</mat-form-field>
|
||||||
@if (loanProductSettingsForm.controls.disbursedAmountPercentageForDownPayment.hasError('required')) {
|
|
||||||
<mat-error>
|
<mat-form-field appearance="outline">
|
||||||
{{ 'labels.inputs.Disbursed Amount Percentage Down Payment' | translate }}
|
<mat-label>Maximum Gold Loan Limit</mat-label>
|
||||||
{{ 'labels.commons.is' | translate }} <strong>{{ 'labels.commons.required' | translate }}</strong>
|
<input type="number" matInput formControlName="maximumGoldLoanLimit" />
|
||||||
</mat-error>
|
</mat-form-field>
|
||||||
}
|
|
||||||
@if (loanProductSettingsForm.controls.disbursedAmountPercentageForDownPayment.errors?.range) {
|
<mat-form-field appearance="outline">
|
||||||
<mat-error>
|
<mat-label>Last Account Number Opened</mat-label>
|
||||||
{{ 'labels.inputs.Disbursed Amount Percentage Down Payment' | translate }}
|
<input type="text" matInput formControlName="lastAccountNumberOpened" />
|
||||||
{{ 'labels.commons.is' | translate }} {{ 'labels.text.out' | translate }}
|
</mat-form-field>
|
||||||
<strong>{{ 'labels.text.percentage range' | translate }}</strong>
|
|
||||||
</mat-error>
|
<mat-form-field appearance="outline">
|
||||||
}
|
<mat-label>Customer Termination Allowed</mat-label>
|
||||||
</mat-form-field>
|
<mat-select formControlName="customerTerminationAllowed">
|
||||||
<div class="lps-checkbox-row">
|
<mat-option value="YES">YES</mat-option>
|
||||||
<mat-checkbox
|
<mat-option value="NO">NO</mat-option>
|
||||||
labelPosition="before"
|
</mat-select>
|
||||||
formControlName="enableAutoRepaymentForDownPayment"
|
</mat-form-field>
|
||||||
matTooltip="{{ 'tooltips.Enable or disable the auto repayment of down-payment.' | translate }}"
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Charges For Cash Credit Above Limit</mat-label>
|
||||||
|
<input type="number" matInput formControlName="chargesForCashCreditAboveLimit" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Death Interest GL Account</mat-label>
|
||||||
|
<input type="text" matInput formControlName="deathInterestGLAccount" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Starting Ledger Number</mat-label>
|
||||||
|
<input type="number" matInput formControlName="startingLedgerNumber" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Ending Ledger Number</mat-label>
|
||||||
|
<input type="number" matInput formControlName="endingLedgerNumber" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Current Ledger Number</mat-label>
|
||||||
|
<input type="number" matInput formControlName="currentLedgerNumber" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Remittance Account Number</mat-label>
|
||||||
|
<input type="text" matInput formControlName="remittanceAccountNumber" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Is Non Resident Indian Account</mat-label>
|
||||||
|
<mat-select formControlName="isNonResidentIndianAccount">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Debit Clearing GL Account</mat-label>
|
||||||
|
<input type="text" matInput formControlName="debitClearingGLAccount" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Missed Call Alert Service Active</mat-label>
|
||||||
|
<mat-select formControlName="missedCallAlertServiceActive">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Standing Instruction Charge GL Account</mat-label>
|
||||||
|
<input type="text" matInput formControlName="standingInstructionChargeGLAccount" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Standing Instruction Debit Charge Skip Option</mat-label>
|
||||||
|
<mat-select formControlName="standingInstructionDebitChargeSkipOption">
|
||||||
|
<mat-option value="SKIP_ALWAYS">Skip Always</mat-option>
|
||||||
|
<mat-option value="SKIP_ON_FIRST_FAILURE">Skip on First Failure</mat-option>
|
||||||
|
<mat-option value="NEVER_SKIP">Never Skip</mat-option>
|
||||||
|
<mat-option value="RETRY_AFTER_24_HOURS">Retry after 24 Hours</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Opening Balance Multiplier For Remittance Charges</mat-label>
|
||||||
|
<input type="number" matInput formControlName="openingBalanceMultiplierForRemittanceCharges" />
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Interest Related Parameters (Page 3) -->
|
||||||
|
<div class="lps-section">
|
||||||
|
<div class="lps-section__header">
|
||||||
|
<i class="fas fa-percent lps-section__icon"></i>
|
||||||
|
<h3 class="lps-section__title">Interest Related Parameters</h3>
|
||||||
|
</div>
|
||||||
|
<div class="lps-section__body lps-grid-4">
|
||||||
|
<mat-form-field appearance="outline" class="lps-full-width">
|
||||||
|
<mat-label>Drawing Power And Limit Generation Procedure</mat-label>
|
||||||
|
<mat-select formControlName="drawingPowerAndLimitGenerationProcedure">
|
||||||
|
<mat-option value="NORMAL D.P. ENTRY IS CONSIDER">Normal D.P. Entry Is Considered</mat-option>
|
||||||
|
<mat-option value="AGAINST F.D. INTEREST WITH CERTIFICATE WISE INTEREST RATE"
|
||||||
|
>Against F.D. Interest with Certificate Wise Interest Rate</mat-option
|
||||||
>
|
>
|
||||||
{{ 'labels.inputs.Enable Auto Repayment for Down Payment' | translate }}
|
<mat-option value="BASED ON ASSET VALUE">Based on Asset Value</mat-option>
|
||||||
</mat-checkbox>
|
<mat-option value="MONTHLY STOCK STATEMENT BASIS">Monthly Stock Statement Basis</mat-option>
|
||||||
</div>
|
</mat-select>
|
||||||
}
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline" class="lps-full-width">
|
||||||
|
<mat-label>Advances Interest Calculation Method</mat-label>
|
||||||
|
<mat-select formControlName="advancesInterestCalculationMethod">
|
||||||
|
<mat-option value="DEBIT CLOSING BALANCE CONSIDER AS PRODUCT"
|
||||||
|
>Debit Closing Balance Considered as Product</mat-option
|
||||||
|
>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Against Interest Calculation Enabled</mat-label>
|
||||||
|
<mat-select formControlName="againstInterestCalculationEnabled">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Day Wise Against Clearing Interest Rounding</mat-label>
|
||||||
|
<mat-select formControlName="dayWiseAgainstClearingInterestRounding">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Interest Calculation One Fourth Method</mat-label>
|
||||||
|
<mat-select formControlName="interestCalculationOneFourthMethod">
|
||||||
|
<mat-option value="0">0 (Standard)</mat-option>
|
||||||
|
<mat-option value="1">1 (Custom A)</mat-option>
|
||||||
|
<mat-option value="2">2 (Custom B)</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline" class="lps-full-width">
|
||||||
|
<mat-label>Against Clearing Interest Procedure Type</mat-label>
|
||||||
|
<mat-select formControlName="againstClearingInterestProcedureType">
|
||||||
|
<mat-option value="NORMAL AGAINST CLEARING INTEREST">Normal Against Clearing Interest</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Consider Debit Closing Amount For Against Clearing</mat-label>
|
||||||
|
<mat-select formControlName="considerDebitClosingAmountForAgainstClearing">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Interest Rounding Method</mat-label>
|
||||||
|
<mat-select formControlName="interestRoundingMethod">
|
||||||
|
<mat-option value="All Int. Round">All Int. Round</mat-option>
|
||||||
|
<mat-option value="Nearest Rupee">Nearest Rupee</mat-option>
|
||||||
|
<mat-option value="Round Up">Round Up</mat-option>
|
||||||
|
<mat-option value="Round Down">Round Down</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Penalty Interest Calculation Enabled</mat-label>
|
||||||
|
<mat-select formControlName="penaltyInterestCalculationEnabled">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Penalty Interest Calculation Method</mat-label>
|
||||||
|
<mat-select formControlName="penaltyInterestCalculationMethod">
|
||||||
|
<mat-option value="Daywise ( 36500 )">Daywise ( 36500 )</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline" class="lps-full-width">
|
||||||
|
<mat-label>Penalty Interest Procedure Number</mat-label>
|
||||||
|
<mat-select formControlName="penaltyInterestProcedureNumber">
|
||||||
|
<mat-option value="ON DB., PENALTY PRODUCT IS CLOSING BALANCE"
|
||||||
|
>On Debit, Penalty Product is Closing Balance</mat-option
|
||||||
|
>
|
||||||
|
<mat-option value="LIMIT IS CONSIDER FOR PENALTY PRODUCT">Limit is Considered for Penalty Product</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Overdrawn Interest Calculation Method</mat-label>
|
||||||
|
<mat-select formControlName="overdrawnInterestCalculationMethod">
|
||||||
|
<mat-option value="OVERDRAWN = BALANCE - LIMIT">Overdrawn = Balance - Limit</mat-option>
|
||||||
|
<mat-option value="OVERDRAWN = BALANCE - D.P.">Overdrawn = Balance - D.P.</mat-option>
|
||||||
|
<mat-option value="DON'T CALCULATE">Don't Calculate</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Calculate Overdrawn Interest After Renewal</mat-label>
|
||||||
|
<mat-select formControlName="calculateOverdrawnInterestAfterRenewal">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Interest On Credit Balance</mat-label>
|
||||||
|
<mat-select formControlName="interestOnCreditBalance">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Penalty Interest Date Different Than Regular Interest</mat-label>
|
||||||
|
<mat-select formControlName="penaltyInterestDateDifferentThanRegularInterest">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Fixed Deposit Overdraft Certificate Sort Order</mat-label>
|
||||||
|
<mat-select formControlName="fixedDepositOverdraftCertificateSortOrder">
|
||||||
|
<mat-option value="ORDER ON INTEREST RATE">Order on Interest Rate</mat-option>
|
||||||
|
<mat-option value="ORDER ON D.P.">Order on Drawing Power</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Use Document Submission Date For Interest</mat-label>
|
||||||
|
<mat-select formControlName="useDocumentSubmissionDateForInterest">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Loan Management System Renewal Penalty Active</mat-label>
|
||||||
|
<mat-select formControlName="loanManagementSystemRenewalPenaltyActive">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Minimum Normal Interest Amount</mat-label>
|
||||||
|
<input type="number" matInput formControlName="minimumNormalInterestAmount" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Minimum Interest Calculation Method</mat-label>
|
||||||
|
<mat-select formControlName="minimumInterestCalculationMethod">
|
||||||
|
<mat-option value="Flat Amount">Flat Amount</mat-option>
|
||||||
|
<mat-option value="Percentage of Balance">Percentage of Balance</mat-option>
|
||||||
|
<mat-option value="Tier Based">Tier Based</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Minimum Against Clearing Interest Amount</mat-label>
|
||||||
|
<input type="number" matInput formControlName="minimumAgainstClearingInterestAmount" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Limit Increase Upto Interest Amount In Interest Calculation</mat-label>
|
||||||
|
<mat-select formControlName="limitIncreaseUptoInterestAmountInInterestCalculation">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Minimum Penalty Interest Amount</mat-label>
|
||||||
|
<input type="number" matInput formControlName="minimumPenaltyInterestAmount" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Days For Limit Increase Upto Interest Amount</mat-label>
|
||||||
|
<input type="number" matInput formControlName="daysForLimitIncreaseUptoInterestAmount" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Additional Interest Rate For Fixed Deposit Overdraft</mat-label>
|
||||||
|
<input type="number" matInput formControlName="additionalInterestRateForFixedDepositOverdraft" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Consider DD/Payorder In Against Clearing Interest Calculation</mat-label>
|
||||||
|
<mat-select formControlName="considerDdPayorderInAgainstClearingInterestCalculation">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Grace Days After Renewal Date</mat-label>
|
||||||
|
<input type="number" matInput formControlName="graceDaysAfterRenewDate" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Apply Undebited Interest Concept Enabled</mat-label>
|
||||||
|
<mat-select formControlName="applyUndebitedInterestConceptEnabled">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline" class="lps-full-width">
|
||||||
|
<mat-label>Interest Register Print Format Type</mat-label>
|
||||||
|
<mat-select formControlName="interestRegisterPrintFormatType">
|
||||||
|
<mat-option value="INTEREST AMOUNT WITH OPENING BALANCE">Interest Amount with Opening Balance</mat-option>
|
||||||
|
<mat-option value="INTEREST ONLY">Interest Only</mat-option>
|
||||||
|
<mat-option value="FULL LEDGER FORMAT">Full Ledger Format</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Normal Grace Days After Overdue</mat-label>
|
||||||
|
<input type="number" matInput formControlName="normalGraceDaysAfterOverdue" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Allow Against Clearing Entry</mat-label>
|
||||||
|
<mat-select formControlName="allowAgainstClearingEntry">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Allow No Balance Entry</mat-label>
|
||||||
|
<mat-select formControlName="allowNoBalanceEntry">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Fixed Deposit Overdraft Penalty Interest Combined With Normal Interest</mat-label>
|
||||||
|
<mat-select formControlName="fixedDepositOverdraftPenaltyInterestCombinedWithNormalInterest">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Allow No Balance Entry With Password</mat-label>
|
||||||
|
<mat-select formControlName="allowNoBalanceEntryWithPassword">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Undebited Simple Interest Account Wise</mat-label>
|
||||||
|
<mat-select formControlName="undebitedSimpleInterestAccountWise">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Daily Interest Calculation Enabled</mat-label>
|
||||||
|
<mat-select formControlName="dailyInterestCalculationEnabled">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Daily Interest Calculation Start Date</mat-label>
|
||||||
|
<input type="text" matInput formControlName="dailyInterestCalculationStartDate" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Non Performing Asset Penal Interest Rate Update</mat-label>
|
||||||
|
<mat-select formControlName="nonPerformingAssetPenalInterestRateUpdate">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Non Performing Asset Penal Interest Rate</mat-label>
|
||||||
|
<input type="number" matInput formControlName="nonPerformingAssetPenalInterestRate" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Fixed Deposit Overdraft Penal Interest Rate Update In Branch Process</mat-label>
|
||||||
|
<mat-select formControlName="fixedDepositOverdraftPenalInterestRateUpdateInBranchProcess">
|
||||||
|
<mat-option value="YES">YES</mat-option>
|
||||||
|
<mat-option value="NO">NO</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Add Penal Interest Rate</mat-label>
|
||||||
|
<input type="number" matInput formControlName="addPenalInterestRate" />
|
||||||
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Loan Charge-off behaviour (only for advanced) -->
|
|
||||||
@if (isAdvancedTransactionProcessingStrategy) {
|
|
||||||
<div class="lps-section">
|
|
||||||
<div class="lps-section__header">
|
|
||||||
<i class="fas fa-ban lps-section__icon"></i>
|
|
||||||
<h3 class="lps-section__title">{{ 'labels.inputs.Loan Charge-off behaviour' | translate }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="lps-section__body">
|
|
||||||
<mat-form-field appearance="outline">
|
|
||||||
<mat-label>{{ 'labels.inputs.Loan Charge-off behaviour' | translate }}</mat-label>
|
|
||||||
<mat-select formControlName="chargeOffBehaviour" required>
|
|
||||||
@for (chargeOffBehaviour of chargeOffBehaviourData; track chargeOffBehaviour) {
|
|
||||||
<mat-option [value]="chargeOffBehaviour.id">
|
|
||||||
{{ chargeOffBehaviour.value | translateKey: 'catalogs' }}
|
|
||||||
</mat-option>
|
|
||||||
}
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<!-- Moratorium & Grace -->
|
<!-- Moratorium & Grace -->
|
||||||
<div class="lps-section">
|
<div class="lps-section">
|
||||||
<div class="lps-section__header">
|
<div class="lps-section__header">
|
||||||
@@ -807,54 +1188,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Event Settings -->
|
|
||||||
<div class="lps-section">
|
|
||||||
<div class="lps-section__header">
|
|
||||||
<i class="fas fa-bell lps-section__icon"></i>
|
|
||||||
<h3 class="lps-section__title">
|
|
||||||
{{ 'labels.heading.Event Settings' | translate }}
|
|
||||||
<i
|
|
||||||
class="fas fa-question lps-question-icon"
|
|
||||||
matTooltip="{{ 'tooltips.Setting for event notifications to be sent' | translate }}"
|
|
||||||
></i>
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div class="lps-section__body">
|
|
||||||
<div class="lps-checkbox-row lps-full-width">
|
|
||||||
<mat-checkbox
|
|
||||||
labelPosition="before"
|
|
||||||
formControlName="useDueForRepaymentsConfigurations"
|
|
||||||
matTooltip="{{ 'tooltips.Use or not the Global Configurations' | translate }}"
|
|
||||||
>
|
|
||||||
{{ 'labels.inputs.Use the Global Configurations values to the Repayment Event (notifications)' | translate }}
|
|
||||||
</mat-checkbox>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (!loanProductSettingsForm.value.useDueForRepaymentsConfigurations) {
|
|
||||||
<mat-form-field appearance="outline">
|
|
||||||
<mat-label>{{ 'labels.inputs.Due days for repayment event' | translate }}</mat-label>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
min="0"
|
|
||||||
matInput
|
|
||||||
matTooltip="{{ 'tooltips.Maximum outstanding loan account balance' | translate }}"
|
|
||||||
formControlName="dueDaysForRepaymentEvent"
|
|
||||||
/>
|
|
||||||
</mat-form-field>
|
|
||||||
<mat-form-field appearance="outline">
|
|
||||||
<mat-label>{{ 'labels.inputs.OverDue days for repayment event' | translate }}</mat-label>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
min="0"
|
|
||||||
matInput
|
|
||||||
matTooltip="{{ 'tooltips.Maximum outstanding loan account balance' | translate }}"
|
|
||||||
formControlName="overDueDaysForRepaymentEvent"
|
|
||||||
/>
|
|
||||||
</mat-form-field>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Configurable Terms -->
|
<!-- Configurable Terms -->
|
||||||
<div class="lps-section">
|
<div class="lps-section">
|
||||||
<div class="lps-section__header">
|
<div class="lps-section__header">
|
||||||
|
|||||||
+12
@@ -57,6 +57,18 @@
|
|||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__body.lps-grid-4 {
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
|
||||||
|
@media (width <= 1100px) {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width <= 600px) {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.lps-full-width {
|
.lps-full-width {
|
||||||
|
|||||||
+79
-79
@@ -15,7 +15,6 @@ import {
|
|||||||
ReactiveFormsModule
|
ReactiveFormsModule
|
||||||
} from '@angular/forms';
|
} from '@angular/forms';
|
||||||
import { LoanProducts } from '../../loan-products';
|
import { LoanProducts } from '../../loan-products';
|
||||||
import { rangeValidator } from 'app/shared/validators/percentage.validator';
|
|
||||||
import { GlobalConfiguration } from 'app/system/configurations/global-configurations-tab/configuration.model';
|
import { GlobalConfiguration } from 'app/system/configurations/global-configurations-tab/configuration.model';
|
||||||
import { CodeName, OptionData, StringEnumOptionData } from 'app/shared/models/option-data.model';
|
import { CodeName, OptionData, StringEnumOptionData } from 'app/shared/models/option-data.model';
|
||||||
import { ProcessingStrategyService } from '../../services/processing-strategy.service';
|
import { ProcessingStrategyService } from '../../services/processing-strategy.service';
|
||||||
@@ -29,21 +28,20 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
|||||||
selector: 'mifosx-loan-product-settings-step',
|
selector: 'mifosx-loan-product-settings-step',
|
||||||
templateUrl: './loan-product-settings-step.component.html',
|
templateUrl: './loan-product-settings-step.component.html',
|
||||||
styleUrls: ['./loan-product-settings-step.component.scss'],
|
styleUrls: ['./loan-product-settings-step.component.scss'],
|
||||||
|
standalone: true,
|
||||||
imports: [
|
imports: [
|
||||||
...STANDALONE_SHARED_IMPORTS,
|
...STANDALONE_SHARED_IMPORTS,
|
||||||
MatTooltip,
|
MatTooltip,
|
||||||
MatCheckbox,
|
MatCheckbox,
|
||||||
MatIconButton,
|
MatIconButton,
|
||||||
FaIconComponent
|
FaIconComponent,
|
||||||
|
ReactiveFormsModule
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class LoanProductSettingsStepComponent implements OnInit {
|
export class LoanProductSettingsStepComponent implements OnInit {
|
||||||
private formBuilder = inject(UntypedFormBuilder);
|
private formBuilder = inject(UntypedFormBuilder);
|
||||||
private processingStrategyService = inject(ProcessingStrategyService);
|
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;
|
|
||||||
|
|
||||||
@Input() toEdit: boolean;
|
@Input() toEdit: boolean;
|
||||||
@Input() loanProductsTemplate: any;
|
@Input() loanProductsTemplate: any;
|
||||||
@Input() isLinkedToFloatingInterestRates: UntypedFormControl;
|
@Input() isLinkedToFloatingInterestRates: UntypedFormControl;
|
||||||
@@ -71,7 +69,6 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
|||||||
loanScheduleProcessingTypeData: OptionData[] = [];
|
loanScheduleProcessingTypeData: OptionData[] = [];
|
||||||
isAdvancedTransactionProcessingStrategy = false;
|
isAdvancedTransactionProcessingStrategy = false;
|
||||||
advancedTransactionProcessingStrategyDisabled = true;
|
advancedTransactionProcessingStrategyDisabled = true;
|
||||||
useDueForRepaymentsConfigurations = false;
|
|
||||||
rescheduleStrategyTypeDisabled = false;
|
rescheduleStrategyTypeDisabled = false;
|
||||||
chargeOffBehaviourData: StringEnumOptionData[] = [];
|
chargeOffBehaviourData: StringEnumOptionData[] = [];
|
||||||
daysInYearCustomStrategyOptions: OptionData[] = [];
|
daysInYearCustomStrategyOptions: OptionData[] = [];
|
||||||
@@ -150,12 +147,10 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
|||||||
maxTrancheCount: this.loanProductsTemplate.maxTrancheCount,
|
maxTrancheCount: this.loanProductsTemplate.maxTrancheCount,
|
||||||
outstandingLoanBalance: this.loanProductsTemplate.outstandingLoanBalance,
|
outstandingLoanBalance: this.loanProductsTemplate.outstandingLoanBalance,
|
||||||
allowFullTermForTranche: this.loanProductsTemplate.allowFullTermForTranche,
|
allowFullTermForTranche: this.loanProductsTemplate.allowFullTermForTranche,
|
||||||
enableDownPayment: this.loanProductsTemplate.enableDownPayment,
|
|
||||||
enableInstallmentLevelDelinquency: this.loanProductsTemplate.enableInstallmentLevelDelinquency,
|
enableInstallmentLevelDelinquency: this.loanProductsTemplate.enableInstallmentLevelDelinquency,
|
||||||
allowCompoundingOnEod: this.loanProductsTemplate.allowCompoundingOnEod,
|
allowCompoundingOnEod: this.loanProductsTemplate.allowCompoundingOnEod,
|
||||||
isCompoundingToBePostedAsTransaction: this.loanProductsTemplate.isCompoundingToBePostedAsTransaction,
|
isCompoundingToBePostedAsTransaction: this.loanProductsTemplate.isCompoundingToBePostedAsTransaction,
|
||||||
loanScheduleType: this.loanProductsTemplate.loanScheduleType.code,
|
loanScheduleType: this.loanProductsTemplate.loanScheduleType.code,
|
||||||
useDueForRepaymentsConfigurations: this.loanProductsTemplate.useDueForRepaymentsConfigurations,
|
|
||||||
allowAccrualPostingInArrears: this.loanProductsTemplate.allowAccrualPostingInArrears,
|
allowAccrualPostingInArrears: this.loanProductsTemplate.allowAccrualPostingInArrears,
|
||||||
chargeOffBehaviour: this.loanProductsTemplate.chargeOffBehaviour.id
|
chargeOffBehaviour: this.loanProductsTemplate.chargeOffBehaviour.id
|
||||||
});
|
});
|
||||||
@@ -166,23 +161,6 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
|||||||
this.processingStrategyService.initialize(this.isAdvancedTransactionProcessingStrategy);
|
this.processingStrategyService.initialize(this.isAdvancedTransactionProcessingStrategy);
|
||||||
this.validateAdvancedPaymentStrategyControls();
|
this.validateAdvancedPaymentStrategyControls();
|
||||||
|
|
||||||
if (
|
|
||||||
this.loanProductsTemplate.dueDaysForRepaymentEvent != null &&
|
|
||||||
this.loanProductsTemplate.overDueDaysForRepaymentEvent != null
|
|
||||||
) {
|
|
||||||
this.loanProductSettingsForm.patchValue({
|
|
||||||
useDueForRepaymentsConfigurations: false,
|
|
||||||
dueDaysForRepaymentEvent: this.loanProductsTemplate.dueDaysForRepaymentEvent,
|
|
||||||
overDueDaysForRepaymentEvent: this.loanProductsTemplate.overDueDaysForRepaymentEvent
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.loanProductSettingsForm.patchValue({
|
|
||||||
useDueForRepaymentsConfigurations: true,
|
|
||||||
dueDaysForRepaymentEvent: null,
|
|
||||||
overDueDaysForRepaymentEvent: null
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.loanProductsTemplate.delinquencyBucket) {
|
if (this.loanProductsTemplate.delinquencyBucket) {
|
||||||
this.loanProductSettingsForm.patchValue({
|
this.loanProductSettingsForm.patchValue({
|
||||||
delinquencyBucketId:
|
delinquencyBucketId:
|
||||||
@@ -190,13 +168,6 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.loanProductsTemplate.enableDownPayment) {
|
|
||||||
this.loanProductSettingsForm.patchValue({
|
|
||||||
disbursedAmountPercentageForDownPayment: this.loanProductsTemplate.disbursedAmountPercentageForDownPayment || 0,
|
|
||||||
enableAutoRepaymentForDownPayment: this.loanProductsTemplate.enableAutoRepaymentForDownPayment || false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.loanProductsTemplate.isInterestRecalculationEnabled) {
|
if (this.loanProductsTemplate.isInterestRecalculationEnabled) {
|
||||||
this.loanProductSettingsForm.patchValue({
|
this.loanProductSettingsForm.patchValue({
|
||||||
preClosureInterestCalculationStrategy:
|
preClosureInterestCalculationStrategy:
|
||||||
@@ -355,24 +326,89 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
|||||||
graceOnArrearsAgeing: [true]
|
graceOnArrearsAgeing: [true]
|
||||||
}),
|
}),
|
||||||
delinquencyBucketId: [''],
|
delinquencyBucketId: [''],
|
||||||
enableDownPayment: [false],
|
|
||||||
enableInstallmentLevelDelinquency: [false],
|
enableInstallmentLevelDelinquency: [false],
|
||||||
allowCompoundingOnEod: [false],
|
allowCompoundingOnEod: [false],
|
||||||
isCompoundingToBePostedAsTransaction: [false],
|
isCompoundingToBePostedAsTransaction: [false],
|
||||||
useDueForRepaymentsConfigurations: [false],
|
|
||||||
dueDaysForRepaymentEvent: [
|
|
||||||
'',
|
|
||||||
[Validators.min(0)]
|
|
||||||
],
|
|
||||||
overDueDaysForRepaymentEvent: [
|
|
||||||
'',
|
|
||||||
[Validators.min(0)]
|
|
||||||
],
|
|
||||||
loanScheduleType: [
|
loanScheduleType: [
|
||||||
LoanProducts.LOAN_SCHEDULE_TYPE_CUMULATIVE,
|
LoanProducts.LOAN_SCHEDULE_TYPE_CUMULATIVE,
|
||||||
Validators.required
|
Validators.required
|
||||||
],
|
],
|
||||||
allowAccrualPostingInArrears: [false]
|
allowAccrualPostingInArrears: [false],
|
||||||
|
|
||||||
|
// Cheque Book Settings
|
||||||
|
chequeBookIssueEnabled: ['NO'],
|
||||||
|
chequeValidationRequired: ['NO'],
|
||||||
|
isFirstChequeBookFree: ['NO'],
|
||||||
|
chequePrintingAccountType: [''],
|
||||||
|
allowWithdrawalSlipUsage: ['NO'],
|
||||||
|
maintainChequeBookStockRegistry: ['NO'],
|
||||||
|
freeChequeBooksPerYear: [''],
|
||||||
|
allowCreditByChequeNumber: ['NO'],
|
||||||
|
creditChequeValidationRequired: ['NO'],
|
||||||
|
graceDaysForStockStatement: [''],
|
||||||
|
|
||||||
|
// Additional Product Settings
|
||||||
|
accountTypeActiveForTransactions: ['YES'],
|
||||||
|
subTypeActivityEnabled: ['NO'],
|
||||||
|
accountOpeningCharges: [''],
|
||||||
|
maximumGoldLoanLimit: [''],
|
||||||
|
lastAccountNumberOpened: [''],
|
||||||
|
customerTerminationAllowed: ['NO'],
|
||||||
|
chargesForCashCreditAboveLimit: [''],
|
||||||
|
deathInterestGLAccount: [''],
|
||||||
|
startingLedgerNumber: [''],
|
||||||
|
endingLedgerNumber: [''],
|
||||||
|
currentLedgerNumber: [''],
|
||||||
|
remittanceAccountNumber: [''],
|
||||||
|
isNonResidentIndianAccount: ['NO'],
|
||||||
|
debitClearingGLAccount: [''],
|
||||||
|
missedCallAlertServiceActive: ['NO'],
|
||||||
|
standingInstructionChargeGLAccount: [''],
|
||||||
|
standingInstructionDebitChargeSkipOption: [''],
|
||||||
|
openingBalanceMultiplierForRemittanceCharges: [''],
|
||||||
|
|
||||||
|
// Interest Related Parameters
|
||||||
|
drawingPowerAndLimitGenerationProcedure: ['NORMAL D.P. ENTRY IS CONSIDER'],
|
||||||
|
advancesInterestCalculationMethod: ['DEBIT CLOSING BALANCE CONSIDER AS PRODUCT'],
|
||||||
|
againstInterestCalculationEnabled: ['NO'],
|
||||||
|
dayWiseAgainstClearingInterestRounding: ['YES'],
|
||||||
|
interestCalculationOneFourthMethod: ['0'],
|
||||||
|
againstClearingInterestProcedureType: ['NORMAL AGAINST CLEARING INTEREST'],
|
||||||
|
considerDebitClosingAmountForAgainstClearing: ['NO'],
|
||||||
|
interestRoundingMethod: [''],
|
||||||
|
penaltyInterestCalculationEnabled: ['NO'],
|
||||||
|
penaltyInterestCalculationMethod: [''],
|
||||||
|
penaltyInterestProcedureNumber: [''],
|
||||||
|
overdrawnInterestCalculationMethod: [''],
|
||||||
|
calculateOverdrawnInterestAfterRenewal: ['NO'],
|
||||||
|
interestOnCreditBalance: ['NO'],
|
||||||
|
penaltyInterestDateDifferentThanRegularInterest: ['YES'],
|
||||||
|
fixedDepositOverdraftCertificateSortOrder: ['ORDER ON INTEREST RATE'],
|
||||||
|
useDocumentSubmissionDateForInterest: ['NO'],
|
||||||
|
loanManagementSystemRenewalPenaltyActive: [''],
|
||||||
|
minimumNormalInterestAmount: [''],
|
||||||
|
minimumInterestCalculationMethod: [''],
|
||||||
|
minimumAgainstClearingInterestAmount: [''],
|
||||||
|
limitIncreaseUptoInterestAmountInInterestCalculation: ['NO'],
|
||||||
|
minimumPenaltyInterestAmount: [''],
|
||||||
|
daysForLimitIncreaseUptoInterestAmount: [''],
|
||||||
|
additionalInterestRateForFixedDepositOverdraft: [''],
|
||||||
|
considerDdPayorderInAgainstClearingInterestCalculation: ['YES'],
|
||||||
|
graceDaysAfterRenewDate: [''],
|
||||||
|
applyUndebitedInterestConceptEnabled: ['YES'],
|
||||||
|
interestRegisterPrintFormatType: ['INTEREST AMOUNT WITH OPENING BALANCE'],
|
||||||
|
normalGraceDaysAfterOverdue: [''],
|
||||||
|
allowAgainstClearingEntry: [''],
|
||||||
|
allowNoBalanceEntry: ['YES'],
|
||||||
|
fixedDepositOverdraftPenaltyInterestCombinedWithNormalInterest: ['NO'],
|
||||||
|
allowNoBalanceEntryWithPassword: ['NO'],
|
||||||
|
undebitedSimpleInterestAccountWise: ['NO'],
|
||||||
|
dailyInterestCalculationEnabled: ['YES'],
|
||||||
|
dailyInterestCalculationStartDate: ['01/02/2023'],
|
||||||
|
nonPerformingAssetPenalInterestRateUpdate: ['YES'],
|
||||||
|
nonPerformingAssetPenalInterestRate: [''],
|
||||||
|
fixedDepositOverdraftPenalInterestRateUpdateInBranchProcess: ['YES'],
|
||||||
|
addPenalInterestRate: ['']
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -595,22 +631,6 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.loanProductSettingsForm.get('enableDownPayment').valueChanges.subscribe((enableDownPayment) => {
|
|
||||||
if (enableDownPayment) {
|
|
||||||
this.loanProductSettingsForm.addControl(
|
|
||||||
'disbursedAmountPercentageForDownPayment',
|
|
||||||
new UntypedFormControl(0, [
|
|
||||||
Validators.required,
|
|
||||||
rangeValidator(0, 100)
|
|
||||||
])
|
|
||||||
);
|
|
||||||
this.loanProductSettingsForm.addControl('enableAutoRepaymentForDownPayment', new UntypedFormControl(false, []));
|
|
||||||
} else {
|
|
||||||
this.loanProductSettingsForm.removeControl('disbursedAmountPercentageForDownPayment');
|
|
||||||
this.loanProductSettingsForm.removeControl('enableAutoRepaymentForDownPayment');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.loanProductSettingsForm
|
this.loanProductSettingsForm
|
||||||
.get('transactionProcessingStrategyCode')
|
.get('transactionProcessingStrategyCode')
|
||||||
.valueChanges.subscribe((transactionProcessingStrategyCode: string) => {
|
.valueChanges.subscribe((transactionProcessingStrategyCode: string) => {
|
||||||
@@ -650,22 +670,6 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.loanProductSettingsForm
|
|
||||||
.get('useDueForRepaymentsConfigurations')
|
|
||||||
.valueChanges.subscribe((useDueForRepaymentsConfigurations: boolean) => {
|
|
||||||
if (useDueForRepaymentsConfigurations) {
|
|
||||||
this.loanProductSettingsForm.patchValue({
|
|
||||||
dueDaysForRepaymentEvent: null,
|
|
||||||
overDueDaysForRepaymentEvent: null
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.loanProductSettingsForm.patchValue({
|
|
||||||
dueDaysForRepaymentEvent: this.getGlobalConfigValue(LoanProducts.DAYS_BEFORE_REPAYMENT_IS_DUE),
|
|
||||||
overDueDaysForRepaymentEvent: this.getGlobalConfigValue(LoanProducts.DAYS_AFTER_REPAYMENT_IS_OVERDUE)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.loanProductSettingsForm.get('loanScheduleType').valueChanges.subscribe((loanScheduleType: string) => {
|
this.loanProductSettingsForm.get('loanScheduleType').valueChanges.subscribe((loanScheduleType: string) => {
|
||||||
this.transactionProcessingStrategyData = [];
|
this.transactionProcessingStrategyData = [];
|
||||||
if (loanScheduleType === LoanProducts.LOAN_SCHEDULE_TYPE_CUMULATIVE) {
|
if (loanScheduleType === LoanProducts.LOAN_SCHEDULE_TYPE_CUMULATIVE) {
|
||||||
@@ -771,10 +775,6 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
|||||||
|
|
||||||
get loanProductSettings() {
|
get loanProductSettings() {
|
||||||
const productSettings = this.loanProductSettingsForm.value;
|
const productSettings = this.loanProductSettingsForm.value;
|
||||||
if (this.loanProductSettingsForm.value.useDueForRepaymentsConfigurations) {
|
|
||||||
productSettings['dueDaysForRepaymentEvent'] = null;
|
|
||||||
productSettings['overDueDaysForRepaymentEvent'] = null;
|
|
||||||
}
|
|
||||||
if (productSettings['delinquencyBucketId'] === '') {
|
if (productSettings['delinquencyBucketId'] === '') {
|
||||||
productSettings['delinquencyBucketId'] = null;
|
productSettings['delinquencyBucketId'] = null;
|
||||||
}
|
}
|
||||||
|
|||||||
-332
@@ -18,43 +18,6 @@
|
|||||||
></i>
|
></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="lpt-grid">
|
<div class="lpt-grid">
|
||||||
<mat-form-field appearance="outline">
|
|
||||||
<mat-label>{{ 'labels.inputs.Minimum' | translate }}</mat-label>
|
|
||||||
<input type="number" matInput formControlName="minPrincipal" [min]="1" step="0.01" />
|
|
||||||
<mat-error *ngIf="loanProductTermsForm.get('minPrincipal')?.hasError('min')">
|
|
||||||
{{ 'labels.commons.Minimum Value must be' | translate }}
|
|
||||||
<strong>{{ loanProductTermsForm.get('minPrincipal')?.errors?.['min']?.min || 1 }}</strong>
|
|
||||||
</mat-error>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<mat-form-field appearance="outline">
|
|
||||||
<mat-label>{{ 'labels.inputs.Default' | translate }}</mat-label>
|
|
||||||
<input type="number" matInput formControlName="principal" required [min]="1" step="0.01" />
|
|
||||||
<mat-error
|
|
||||||
*ngIf="
|
|
||||||
loanProductTermsForm.get('principal')?.hasError('required') &&
|
|
||||||
(loanProductTermsForm.get('principal')?.touched || loanProductTermsForm.get('principal')?.dirty)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
{{ 'labels.catalogs.Default' | translate }} {{ 'labels.inputs.Principal' | translate }}
|
|
||||||
{{ 'labels.commons.is required' | translate }}
|
|
||||||
</mat-error>
|
|
||||||
<mat-error *ngIf="loanProductTermsForm.get('principal')?.hasError('min')">
|
|
||||||
{{ 'labels.catalogs.Default' | translate }} {{ 'labels.inputs.Principal' | translate }}
|
|
||||||
{{ 'labels.commons.is' | translate }}
|
|
||||||
<strong>{{ loanProductTermsForm.get('principal')?.errors?.['min']?.min || 1 }}</strong>
|
|
||||||
</mat-error>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<mat-form-field appearance="outline">
|
|
||||||
<mat-label>{{ 'labels.inputs.Maximum' | translate }}</mat-label>
|
|
||||||
<input type="number" matInput formControlName="maxPrincipal" [min]="1" step="0.01" />
|
|
||||||
<mat-error *ngIf="loanProductTermsForm.get('maxPrincipal')?.hasError('min')">
|
|
||||||
{{ 'labels.commons.Minimum Value must be' | translate }}
|
|
||||||
<strong>{{ loanProductTermsForm.get('maxPrincipal')?.errors?.['min']?.min || 1 }}</strong>
|
|
||||||
</mat-error>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<div class="lpt-checkbox-row lpt-full-width">
|
<div class="lpt-checkbox-row lpt-full-width">
|
||||||
<mat-checkbox labelPosition="before" formControlName="allowApprovedDisbursedAmountsOverApplied">
|
<mat-checkbox labelPosition="before" formControlName="allowApprovedDisbursedAmountsOverApplied">
|
||||||
{{ 'labels.inputs.Allow approval / disbursal above loan applied amount' | translate }}
|
{{ 'labels.inputs.Allow approval / disbursal above loan applied amount' | translate }}
|
||||||
@@ -119,57 +82,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Repayments Section -->
|
|
||||||
<div class="lpt-section">
|
|
||||||
<div class="lpt-section-header">
|
|
||||||
<i class="fas fa-calendar-alt lpt-section-icon"></i>
|
|
||||||
<h3>{{ 'labels.inputs.Number of repayments' | translate }}</h3>
|
|
||||||
<i
|
|
||||||
class="fas fa-question-circle lpt-help-icon"
|
|
||||||
matTooltip="{{
|
|
||||||
'tooltips.Fields are used to define the minimum, default, and maximum number of repayments' | translate
|
|
||||||
}}"
|
|
||||||
></i>
|
|
||||||
</div>
|
|
||||||
<div class="lpt-grid lpt-grid-3">
|
|
||||||
<mat-form-field appearance="outline">
|
|
||||||
<mat-label>{{ 'labels.inputs.Minimum' | translate }}</mat-label>
|
|
||||||
<input type="number" matInput formControlName="minNumberOfRepayments" [min]="1" />
|
|
||||||
<mat-error>
|
|
||||||
{{ 'labels.commons.Minimum Value must be' | translate }}
|
|
||||||
<strong>1</strong>
|
|
||||||
</mat-error>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<mat-form-field appearance="outline">
|
|
||||||
<mat-label>{{ 'labels.inputs.Default' | translate }}</mat-label>
|
|
||||||
<input type="number" matInput formControlName="numberOfRepayments" required [min]="1" />
|
|
||||||
<mat-error>
|
|
||||||
{{ 'labels.catalogs.Default' | translate }} {{ 'labels.inputs.Number of repayments' | translate }}
|
|
||||||
{{ 'labels.commons.is' | translate }}
|
|
||||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
|
||||||
</mat-error>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<mat-form-field appearance="outline">
|
|
||||||
<mat-label>{{ 'labels.inputs.Maximum' | translate }}</mat-label>
|
|
||||||
<input type="number" matInput formControlName="maxNumberOfRepayments" [min]="1" />
|
|
||||||
<mat-error>
|
|
||||||
{{ 'labels.commons.Maximum Value must be' | translate }}
|
|
||||||
<strong>1</strong>
|
|
||||||
{{ 'labels.commons.and must be greater than' | translate }}
|
|
||||||
<strong>{{ 'labels.inputs.Minimum' | translate }}</strong>
|
|
||||||
</mat-error>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<div class="lpt-checkbox-row lpt-full-width">
|
|
||||||
<mat-checkbox labelPosition="before" formControlName="interestRecognitionOnDisbursementDate">
|
|
||||||
{{ 'labels.inputs.Is interest recognition on disbursement date?' | translate }}
|
|
||||||
</mat-checkbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Interest Rate Section -->
|
<!-- Interest Rate Section -->
|
||||||
<div class="lpt-section">
|
<div class="lpt-section">
|
||||||
<div class="lpt-section-header">
|
<div class="lpt-section-header">
|
||||||
@@ -352,250 +264,6 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Loan Cycle Variations Section -->
|
|
||||||
<div class="lpt-section">
|
|
||||||
<div class="lpt-section-header">
|
|
||||||
<i class="fas fa-sync lpt-section-icon"></i>
|
|
||||||
<h3>{{ 'labels.inputs.Variations' | translate }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="lpt-grid">
|
|
||||||
<div class="lpt-checkbox-row lpt-full-width">
|
|
||||||
<mat-checkbox labelPosition="before" formControlName="useBorrowerCycle">
|
|
||||||
{{ 'labels.inputs.Terms vary based on loan cycle' | translate }}
|
|
||||||
</mat-checkbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (loanProductTermsForm.value.useBorrowerCycle) {
|
|
||||||
<!-- Principal by loan cycle -->
|
|
||||||
<div class="lpt-subsection">
|
|
||||||
<div class="lpt-subsection-header">
|
|
||||||
<h4 class="lpt-subsection-title">{{ 'labels.inputs.Principal by loan cycle' | translate }}</h4>
|
|
||||||
<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) {
|
|
||||||
<div class="lpt-table-wrapper">
|
|
||||||
<table 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>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Number of repayments by loan cycle -->
|
|
||||||
<div class="lpt-subsection">
|
|
||||||
<div class="lpt-subsection-header">
|
|
||||||
<h4 class="lpt-subsection-title">{{ 'labels.inputs.Number of repayments by loan cycle' | translate }}</h4>
|
|
||||||
<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) {
|
|
||||||
<div class="lpt-table-wrapper">
|
|
||||||
<table 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>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nominal interest rate by loan cycle -->
|
|
||||||
<div class="lpt-subsection">
|
|
||||||
<div class="lpt-subsection-header">
|
|
||||||
<h4 class="lpt-subsection-title">{{ 'labels.inputs.Nominal interest rate by loan cycle' | translate }}</h4>
|
|
||||||
<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) {
|
|
||||||
<div class="lpt-table-wrapper">
|
|
||||||
<table 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>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Repayment Schedule Section -->
|
<!-- Repayment Schedule Section -->
|
||||||
<div class="lpt-section">
|
<div class="lpt-section">
|
||||||
<div class="lpt-section-header">
|
<div class="lpt-section-header">
|
||||||
|
|||||||
+4
-259
@@ -11,36 +11,14 @@ import {
|
|||||||
UntypedFormGroup,
|
UntypedFormGroup,
|
||||||
UntypedFormBuilder,
|
UntypedFormBuilder,
|
||||||
Validators,
|
Validators,
|
||||||
UntypedFormArray,
|
|
||||||
UntypedFormControl,
|
UntypedFormControl,
|
||||||
ReactiveFormsModule
|
ReactiveFormsModule
|
||||||
} from '@angular/forms';
|
} from '@angular/forms';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
|
||||||
|
|
||||||
import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component';
|
|
||||||
import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component';
|
|
||||||
|
|
||||||
import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield-base';
|
|
||||||
import { InputBase } from 'app/shared/form-dialog/formfield/model/input-base';
|
|
||||||
import { SelectBase } from 'app/shared/form-dialog/formfield/model/select-base';
|
|
||||||
import { ProcessingStrategyService } from '../../services/processing-strategy.service';
|
import { ProcessingStrategyService } from '../../services/processing-strategy.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { MatTooltip } from '@angular/material/tooltip';
|
import { MatTooltip } from '@angular/material/tooltip';
|
||||||
import { MatCheckbox } from '@angular/material/checkbox';
|
import { MatCheckbox } from '@angular/material/checkbox';
|
||||||
import { MatButton, MatIconButton } from '@angular/material/button';
|
|
||||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||||
import {
|
|
||||||
MatTable,
|
|
||||||
MatColumnDef,
|
|
||||||
MatHeaderCellDef,
|
|
||||||
MatHeaderCell,
|
|
||||||
MatCellDef,
|
|
||||||
MatCell,
|
|
||||||
MatHeaderRowDef,
|
|
||||||
MatHeaderRow,
|
|
||||||
MatRowDef,
|
|
||||||
MatRow
|
|
||||||
} from '@angular/material/table';
|
|
||||||
import { FindPipe } from '../../../../pipes/find.pipe';
|
import { FindPipe } from '../../../../pipes/find.pipe';
|
||||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||||
|
|
||||||
@@ -53,24 +31,12 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
|||||||
MatTooltip,
|
MatTooltip,
|
||||||
MatCheckbox,
|
MatCheckbox,
|
||||||
FaIconComponent,
|
FaIconComponent,
|
||||||
MatTable,
|
|
||||||
MatColumnDef,
|
|
||||||
MatHeaderCellDef,
|
|
||||||
MatHeaderCell,
|
|
||||||
MatCellDef,
|
|
||||||
MatCell,
|
|
||||||
MatIconButton,
|
|
||||||
MatHeaderRowDef,
|
|
||||||
MatHeaderRow,
|
|
||||||
MatRowDef,
|
|
||||||
MatRow,
|
|
||||||
FindPipe
|
FindPipe
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class LoanProductTermsStepComponent implements OnInit, OnChanges {
|
export class LoanProductTermsStepComponent implements OnInit, OnChanges {
|
||||||
private formBuilder = inject(UntypedFormBuilder);
|
private formBuilder = inject(UntypedFormBuilder);
|
||||||
private processingStrategyService = inject(ProcessingStrategyService);
|
private processingStrategyService = inject(ProcessingStrategyService);
|
||||||
private dialog = inject(MatDialog);
|
|
||||||
private translateService = inject(TranslateService);
|
private translateService = inject(TranslateService);
|
||||||
|
|
||||||
@Input() loanProductsTemplate: any;
|
@Input() loanProductsTemplate: any;
|
||||||
@@ -80,30 +46,20 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
|
|||||||
/** Zero Interest control. */
|
/** Zero Interest control. */
|
||||||
zeroInterest = new UntypedFormControl(false);
|
zeroInterest = new UntypedFormControl(false);
|
||||||
|
|
||||||
valueConditionTypeData: any;
|
isAdvancedTransactionProcessingStrategy = false;
|
||||||
|
|
||||||
floatingRateData: any;
|
floatingRateData: any;
|
||||||
interestRateFrequencyTypeData: any;
|
interestRateFrequencyTypeData: any;
|
||||||
overAppliedCalculationTypeData: any;
|
overAppliedCalculationTypeData: any;
|
||||||
repaymentFrequencyTypeData: any;
|
repaymentFrequencyTypeData: any;
|
||||||
repaymentStartDateTypeOptions: any;
|
repaymentStartDateTypeOptions: any;
|
||||||
|
|
||||||
displayedColumns: string[] = [
|
|
||||||
'valueConditionType',
|
|
||||||
'borrowerCycleNumber',
|
|
||||||
'minValue',
|
|
||||||
'defaultValue',
|
|
||||||
'maxValue',
|
|
||||||
'actions'
|
|
||||||
];
|
|
||||||
isAdvancedTransactionProcessingStrategy = false;
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.createLoanProductTermsForm();
|
this.createLoanProductTermsForm();
|
||||||
this.setConditionalControls();
|
this.setConditionalControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.valueConditionTypeData = this.loanProductsTemplate.valueConditionTypeOptions;
|
|
||||||
this.floatingRateData = this.loanProductsTemplate.floatingRateOptions;
|
this.floatingRateData = this.loanProductsTemplate.floatingRateOptions;
|
||||||
this.interestRateFrequencyTypeData = this.loanProductsTemplate.interestRateFrequencyTypeOptions;
|
this.interestRateFrequencyTypeData = this.loanProductsTemplate.interestRateFrequencyTypeOptions;
|
||||||
this.repaymentFrequencyTypeData = this.loanProductsTemplate.repaymentFrequencyTypeOptions;
|
this.repaymentFrequencyTypeData = this.loanProductsTemplate.repaymentFrequencyTypeOptions;
|
||||||
@@ -114,12 +70,6 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
|
|||||||
];
|
];
|
||||||
|
|
||||||
this.loanProductTermsForm.patchValue({
|
this.loanProductTermsForm.patchValue({
|
||||||
minPrincipal: this.loanProductsTemplate.minPrincipal,
|
|
||||||
principal: this.loanProductsTemplate.principal,
|
|
||||||
maxPrincipal: this.loanProductsTemplate.maxPrincipal,
|
|
||||||
minNumberOfRepayments: this.loanProductsTemplate.minNumberOfRepayments,
|
|
||||||
numberOfRepayments: this.loanProductsTemplate.numberOfRepayments,
|
|
||||||
maxNumberOfRepayments: this.loanProductsTemplate.maxNumberOfRepayments,
|
|
||||||
isLinkedToFloatingInterestRates: this.loanProductsTemplate.isLinkedToFloatingInterestRates,
|
isLinkedToFloatingInterestRates: this.loanProductsTemplate.isLinkedToFloatingInterestRates,
|
||||||
minInterestRatePerPeriod: this.loanProductsTemplate.minInterestRatePerPeriod,
|
minInterestRatePerPeriod: this.loanProductsTemplate.minInterestRatePerPeriod,
|
||||||
interestRatePerPeriod: this.loanProductsTemplate.interestRatePerPeriod,
|
interestRatePerPeriod: this.loanProductsTemplate.interestRatePerPeriod,
|
||||||
@@ -132,13 +82,11 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
|
|||||||
minDifferentialLendingRate: this.loanProductsTemplate.minDifferentialLendingRate,
|
minDifferentialLendingRate: this.loanProductsTemplate.minDifferentialLendingRate,
|
||||||
defaultDifferentialLendingRate: this.loanProductsTemplate.defaultDifferentialLendingRate,
|
defaultDifferentialLendingRate: this.loanProductsTemplate.defaultDifferentialLendingRate,
|
||||||
maxDifferentialLendingRate: this.loanProductsTemplate.maxDifferentialLendingRate,
|
maxDifferentialLendingRate: this.loanProductsTemplate.maxDifferentialLendingRate,
|
||||||
useBorrowerCycle: this.loanProductsTemplate.useBorrowerCycle,
|
|
||||||
repaymentEvery: this.loanProductsTemplate.repaymentEvery,
|
repaymentEvery: this.loanProductsTemplate.repaymentEvery,
|
||||||
repaymentFrequencyType: this.loanProductsTemplate.repaymentFrequencyType.id,
|
repaymentFrequencyType: this.loanProductsTemplate.repaymentFrequencyType.id,
|
||||||
minimumDaysBetweenDisbursalAndFirstRepayment:
|
minimumDaysBetweenDisbursalAndFirstRepayment:
|
||||||
this.loanProductsTemplate.minimumDaysBetweenDisbursalAndFirstRepayment,
|
this.loanProductsTemplate.minimumDaysBetweenDisbursalAndFirstRepayment,
|
||||||
repaymentStartDateType: this.loanProductsTemplate.repaymentStartDateType.id || 1,
|
repaymentStartDateType: this.loanProductsTemplate.repaymentStartDateType.id || 1
|
||||||
interestRecognitionOnDisbursementDate: this.loanProductsTemplate.interestRecognitionOnDisbursementDate || false
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.loanProductsTemplate.allowApprovedDisbursedAmountsOverApplied) {
|
if (this.loanProductsTemplate.allowApprovedDisbursedAmountsOverApplied) {
|
||||||
@@ -148,34 +96,6 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loanProductTermsForm.setControl(
|
|
||||||
'principalVariationsForBorrowerCycle',
|
|
||||||
this.formBuilder.array(
|
|
||||||
this.loanProductsTemplate.principalVariationsForBorrowerCycle.map((variation: any) => ({
|
|
||||||
...variation,
|
|
||||||
valueConditionType: variation.valueConditionType.id
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
this.loanProductTermsForm.setControl(
|
|
||||||
'numberOfRepaymentVariationsForBorrowerCycle',
|
|
||||||
this.formBuilder.array(
|
|
||||||
this.loanProductsTemplate.numberOfRepaymentVariationsForBorrowerCycle.map((variation: any) => ({
|
|
||||||
...variation,
|
|
||||||
valueConditionType: variation.valueConditionType.id
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
this.loanProductTermsForm.setControl(
|
|
||||||
'interestRateVariationsForBorrowerCycle',
|
|
||||||
this.formBuilder.array(
|
|
||||||
this.loanProductsTemplate.interestRateVariationsForBorrowerCycle.map((variation: any) => ({
|
|
||||||
...variation,
|
|
||||||
valueConditionType: variation.valueConditionType.id
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
this.zeroInterest.patchValue(
|
this.zeroInterest.patchValue(
|
||||||
this.loanProductsTemplate.minInterestRatePerPeriod === 0 &&
|
this.loanProductsTemplate.minInterestRatePerPeriod === 0 &&
|
||||||
this.loanProductsTemplate.interestRatePerPeriod === 0 &&
|
this.loanProductsTemplate.interestRatePerPeriod === 0 &&
|
||||||
@@ -190,45 +110,6 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
|
|||||||
|
|
||||||
createLoanProductTermsForm() {
|
createLoanProductTermsForm() {
|
||||||
this.loanProductTermsForm = this.formBuilder.group({
|
this.loanProductTermsForm = this.formBuilder.group({
|
||||||
useBorrowerCycle: [false],
|
|
||||||
minPrincipal: [
|
|
||||||
'',
|
|
||||||
[
|
|
||||||
Validators.min(1)
|
|
||||||
]
|
|
||||||
],
|
|
||||||
principal: [
|
|
||||||
'',
|
|
||||||
[
|
|
||||||
Validators.required,
|
|
||||||
Validators.min(1)
|
|
||||||
]
|
|
||||||
],
|
|
||||||
maxPrincipal: [
|
|
||||||
'',
|
|
||||||
[
|
|
||||||
Validators.min(1)
|
|
||||||
]
|
|
||||||
],
|
|
||||||
minNumberOfRepayments: [
|
|
||||||
'',
|
|
||||||
[
|
|
||||||
Validators.pattern('^[1-9]\\d*$')
|
|
||||||
]
|
|
||||||
],
|
|
||||||
numberOfRepayments: [
|
|
||||||
'',
|
|
||||||
[
|
|
||||||
Validators.required,
|
|
||||||
Validators.pattern('^[1-9]\\d*$')
|
|
||||||
]
|
|
||||||
],
|
|
||||||
maxNumberOfRepayments: [
|
|
||||||
'',
|
|
||||||
[
|
|
||||||
Validators.pattern('^[1-9]\\d*$')
|
|
||||||
]
|
|
||||||
],
|
|
||||||
isLinkedToFloatingInterestRates: [false],
|
isLinkedToFloatingInterestRates: [false],
|
||||||
allowApprovedDisbursedAmountsOverApplied: [false],
|
allowApprovedDisbursedAmountsOverApplied: [false],
|
||||||
overAppliedCalculationType: [{ value: null, disabled: true }],
|
overAppliedCalculationType: [{ value: null, disabled: true }],
|
||||||
@@ -275,8 +156,7 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
|
|||||||
[]
|
[]
|
||||||
],
|
],
|
||||||
repaymentStartDateType: [1],
|
repaymentStartDateType: [1],
|
||||||
fixedLength: [null],
|
fixedLength: [null]
|
||||||
interestRecognitionOnDisbursementDate: [false]
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,18 +230,6 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.loanProductTermsForm.get('useBorrowerCycle').valueChanges.subscribe((useBorrowerCycle) => {
|
|
||||||
if (useBorrowerCycle) {
|
|
||||||
this.loanProductTermsForm.addControl('principalVariationsForBorrowerCycle', this.formBuilder.array([]));
|
|
||||||
this.loanProductTermsForm.addControl('numberOfRepaymentVariationsForBorrowerCycle', this.formBuilder.array([]));
|
|
||||||
this.loanProductTermsForm.addControl('interestRateVariationsForBorrowerCycle', this.formBuilder.array([]));
|
|
||||||
} else {
|
|
||||||
this.loanProductTermsForm.removeControl('principalVariationsForBorrowerCycle');
|
|
||||||
this.loanProductTermsForm.removeControl('numberOfRepaymentVariationsForBorrowerCycle');
|
|
||||||
this.loanProductTermsForm.removeControl('interestRateVariationsForBorrowerCycle');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.zeroInterest.valueChanges.subscribe((zeroInterest) => {
|
this.zeroInterest.valueChanges.subscribe((zeroInterest) => {
|
||||||
if (zeroInterest) {
|
if (zeroInterest) {
|
||||||
this.loanProductTermsForm.get('minInterestRatePerPeriod').patchValue(0);
|
this.loanProductTermsForm.get('minInterestRatePerPeriod').patchValue(0);
|
||||||
@@ -388,129 +256,6 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get principalVariationsForBorrowerCycle(): UntypedFormArray {
|
|
||||||
return this.loanProductTermsForm.get('principalVariationsForBorrowerCycle') as UntypedFormArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
get numberOfRepaymentVariationsForBorrowerCycle(): UntypedFormArray {
|
|
||||||
return this.loanProductTermsForm.get('numberOfRepaymentVariationsForBorrowerCycle') as UntypedFormArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
get interestRateVariationsForBorrowerCycle(): UntypedFormArray {
|
|
||||||
return this.loanProductTermsForm.get('interestRateVariationsForBorrowerCycle') as UntypedFormArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
setLoanProductTermsFormDirty() {
|
|
||||||
if (this.loanProductTermsForm.pristine) {
|
|
||||||
this.loanProductTermsForm.markAsDirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addVariationsForBorrowerCycle(formType: string, variationsForBorrowerCycleFormArray: UntypedFormArray) {
|
|
||||||
const data = this.getData(formType);
|
|
||||||
const addVariationsForBorrowerCycleDialogRef = this.dialog.open(FormDialogComponent, { data });
|
|
||||||
addVariationsForBorrowerCycleDialogRef.afterClosed().subscribe((response: any) => {
|
|
||||||
if (response.data) {
|
|
||||||
variationsForBorrowerCycleFormArray.push(response.data);
|
|
||||||
this.setLoanProductTermsFormDirty();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
editVariationsForBorrowerCycle(
|
|
||||||
formType: string,
|
|
||||||
variationsForBorrowerCycleFormArray: UntypedFormArray,
|
|
||||||
index: number
|
|
||||||
) {
|
|
||||||
const data = {
|
|
||||||
...this.getData(formType, variationsForBorrowerCycleFormArray.at(index).value),
|
|
||||||
layout: { addButtonText: 'Edit' }
|
|
||||||
};
|
|
||||||
const addVariationsForBorrowerCycleDialogRef = this.dialog.open(FormDialogComponent, { data });
|
|
||||||
addVariationsForBorrowerCycleDialogRef.afterClosed().subscribe((response: any) => {
|
|
||||||
if (response.data) {
|
|
||||||
variationsForBorrowerCycleFormArray.at(index).patchValue(response.data.value);
|
|
||||||
this.setLoanProductTermsFormDirty();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteVariationsForBorrowerCycle(variationsForBorrowerCycleFormArray: UntypedFormArray, index: number) {
|
|
||||||
const deleteVariationsForBorrowerCycleDialogRef = this.dialog.open(DeleteDialogComponent, {
|
|
||||||
data: { deleteContext: `this` }
|
|
||||||
});
|
|
||||||
deleteVariationsForBorrowerCycleDialogRef.afterClosed().subscribe((response: any) => {
|
|
||||||
if (response.delete) {
|
|
||||||
variationsForBorrowerCycleFormArray.removeAt(index);
|
|
||||||
this.setLoanProductTermsFormDirty();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getData(formType: string, values?: any) {
|
|
||||||
switch (formType) {
|
|
||||||
case 'Principal':
|
|
||||||
return {
|
|
||||||
title: this.translateService.instant('labels.heading.Principal by loan cycle'),
|
|
||||||
formfields: this.getFormfields(values)
|
|
||||||
};
|
|
||||||
case 'NumberOfRepayments':
|
|
||||||
return {
|
|
||||||
title: this.translateService.instant('labels.heading.Number of Repayments by loan cycle'),
|
|
||||||
formfields: this.getFormfields(values)
|
|
||||||
};
|
|
||||||
case 'NominalInterestRate':
|
|
||||||
return {
|
|
||||||
title: this.translateService.instant('labels.heading.Nominal Interest Rate by loan cycle'),
|
|
||||||
formfields: this.getFormfields(values)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getFormfields(values?: any) {
|
|
||||||
const formfields: FormfieldBase[] = [
|
|
||||||
new SelectBase({
|
|
||||||
controlName: 'valueConditionType',
|
|
||||||
label: this.translateService.instant('labels.inputs.Condition'),
|
|
||||||
value: values ? values.valueConditionType : this.valueConditionTypeData[0].id,
|
|
||||||
options: { label: 'value', value: 'id', data: this.valueConditionTypeData },
|
|
||||||
required: true,
|
|
||||||
order: 1
|
|
||||||
}),
|
|
||||||
new InputBase({
|
|
||||||
controlName: 'borrowerCycleNumber',
|
|
||||||
label: this.translateService.instant('labels.inputs.Loan Cycle'),
|
|
||||||
value: values ? values.borrowerCycleNumber : undefined,
|
|
||||||
type: 'number',
|
|
||||||
required: true,
|
|
||||||
order: 2
|
|
||||||
}),
|
|
||||||
new InputBase({
|
|
||||||
controlName: 'minValue',
|
|
||||||
label: this.translateService.instant('labels.inputs.Minimum'),
|
|
||||||
value: values ? values.minValue : undefined,
|
|
||||||
type: 'number',
|
|
||||||
order: 3
|
|
||||||
}),
|
|
||||||
new InputBase({
|
|
||||||
controlName: 'defaultValue',
|
|
||||||
label: this.translateService.instant('labels.inputs.Default'),
|
|
||||||
value: values ? values.defaultValue : undefined,
|
|
||||||
type: 'number',
|
|
||||||
required: true,
|
|
||||||
order: 4
|
|
||||||
}),
|
|
||||||
new InputBase({
|
|
||||||
controlName: 'maxValue',
|
|
||||||
label: this.translateService.instant('labels.inputs.Maximum'),
|
|
||||||
value: values ? values.maxValue : undefined,
|
|
||||||
type: 'number',
|
|
||||||
order: 5
|
|
||||||
})
|
|
||||||
];
|
|
||||||
return formfields;
|
|
||||||
}
|
|
||||||
|
|
||||||
get loanProductTerms() {
|
get loanProductTerms() {
|
||||||
const formValue = this.loanProductTermsForm.getRawValue();
|
const formValue = this.loanProductTermsForm.getRawValue();
|
||||||
// Normalize decimal separators: convert comma to dot for backend compatibility
|
// Normalize decimal separators: convert comma to dot for backend compatibility
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
import { Injectable, inject } from '@angular/core';
|
import { Injectable, inject } from '@angular/core';
|
||||||
import { SettingsService } from 'app/settings/settings.service';
|
import { SettingsService } from 'app/settings/settings.service';
|
||||||
import { GlobalConfiguration } from 'app/system/configurations/global-configurations-tab/configuration.model';
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@@ -24,46 +23,15 @@ export class LoanProducts {
|
|||||||
|
|
||||||
public static ADVANCED_PAYMENT_ALLOCATION_STRATEGY = 'advanced-payment-allocation-strategy';
|
public static ADVANCED_PAYMENT_ALLOCATION_STRATEGY = 'advanced-payment-allocation-strategy';
|
||||||
|
|
||||||
public static DAYS_BEFORE_REPAYMENT_IS_DUE = 'days-before-repayment-is-due';
|
|
||||||
public static DAYS_AFTER_REPAYMENT_IS_OVERDUE = 'days-after-repayment-is-overdue';
|
|
||||||
|
|
||||||
globalConfigurations: string[] = [
|
|
||||||
LoanProducts.DAYS_BEFORE_REPAYMENT_IS_DUE,
|
|
||||||
LoanProducts.DAYS_AFTER_REPAYMENT_IS_OVERDUE
|
|
||||||
];
|
|
||||||
propertyNames: string[] = [
|
|
||||||
'dueDaysForRepaymentEvent',
|
|
||||||
'overDueDaysForRepaymentEvent'
|
|
||||||
];
|
|
||||||
|
|
||||||
public static isAdvancedPaymentAllocationStrategy(code: string): boolean {
|
public static isAdvancedPaymentAllocationStrategy(code: string): boolean {
|
||||||
return code === this.ADVANCED_PAYMENT_ALLOCATION_STRATEGY;
|
return code === this.ADVANCED_PAYMENT_ALLOCATION_STRATEGY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setItemsByDefault(configurations: any) {
|
public setItemsByDefault(configurations: any): any[] {
|
||||||
const itemsByDefault: GlobalConfiguration[] = [];
|
return [];
|
||||||
configurations.globalConfiguration.forEach((config: GlobalConfiguration) => {
|
|
||||||
if (this.globalConfigurations.includes(config.name)) {
|
|
||||||
itemsByDefault.push(config);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return itemsByDefault;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateLoanProductDefaults(loanProductTemplate: any, isForUpdate: boolean) {
|
public updateLoanProductDefaults(loanProductTemplate: any, isForUpdate: boolean) {
|
||||||
const itemsByDefault: GlobalConfiguration[] = loanProductTemplate['itemsByDefault'];
|
|
||||||
itemsByDefault.forEach((config: GlobalConfiguration) => {
|
|
||||||
const propertyName = this.resolvePropertyName(config.name);
|
|
||||||
if (propertyName !== '') {
|
|
||||||
if (isForUpdate) {
|
|
||||||
if (!loanProductTemplate[propertyName] || loanProductTemplate[propertyName] === '') {
|
|
||||||
loanProductTemplate[propertyName] = config.value;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
loanProductTemplate[propertyName] = config.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return loanProductTemplate;
|
return loanProductTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,34 +54,14 @@ export class LoanProducts {
|
|||||||
loanProduct.allowPartialPeriodInterestCalculation = loanProduct.allowPartialPeriodInterestCalculation;
|
loanProduct.allowPartialPeriodInterestCalculation = loanProduct.allowPartialPeriodInterestCalculation;
|
||||||
delete loanProduct.allowPartialPeriodInterestCalculation;
|
delete loanProduct.allowPartialPeriodInterestCalculation;
|
||||||
|
|
||||||
// Set Default values If they were not set
|
|
||||||
itemsByDefault.forEach((config: GlobalConfiguration) => {
|
|
||||||
const propertyName = this.resolvePropertyName(config.name);
|
|
||||||
if (propertyName !== '') {
|
|
||||||
if (!loanProduct[propertyName] || loanProduct[propertyName] === '') {
|
|
||||||
loanProduct[propertyName] = config.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return loanProduct;
|
return loanProduct;
|
||||||
}
|
}
|
||||||
|
|
||||||
public isItemByDefault(propertyName: string): boolean {
|
public isItemByDefault(propertyName: string): boolean {
|
||||||
return this.propertyNames.includes(propertyName);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public isGlobalConfigurations(propertyName: string): boolean {
|
public isGlobalConfigurations(propertyName: string): boolean {
|
||||||
return this.globalConfigurations.includes(propertyName);
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
private resolvePropertyName(configName: string): string {
|
|
||||||
if (this.globalConfigurations.includes(configName)) {
|
|
||||||
const idx = this.globalConfigurations.indexOf(configName);
|
|
||||||
if (idx > -1) {
|
|
||||||
return this.propertyNames[idx];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,17 +26,13 @@ export interface LoanProduct {
|
|||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
shortName: string;
|
shortName: string;
|
||||||
includeInBorrowerCycle: boolean;
|
|
||||||
useBorrowerCycle: boolean;
|
useBorrowerCycle: boolean;
|
||||||
status: string;
|
status: string;
|
||||||
currency: Currency;
|
currency: Currency;
|
||||||
currencyCode?: string;
|
currencyCode?: string;
|
||||||
fundId?: number;
|
|
||||||
fundName?: string;
|
|
||||||
startDate?: string;
|
startDate?: string;
|
||||||
closeDate?: string;
|
closeDate?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
installmentAmountInMultiplesOf?: number;
|
|
||||||
principal: number;
|
principal: number;
|
||||||
minPrincipal?: number;
|
minPrincipal?: number;
|
||||||
maxPrincipal?: number;
|
maxPrincipal?: number;
|
||||||
@@ -123,8 +119,6 @@ export interface LoanProduct {
|
|||||||
graceOnInterestPayment?: number;
|
graceOnInterestPayment?: number;
|
||||||
graceOnInterestCharged?: number;
|
graceOnInterestCharged?: number;
|
||||||
inArrearsTolerance?: number;
|
inArrearsTolerance?: number;
|
||||||
dueDaysForRepaymentEvent: number;
|
|
||||||
overDueDaysForRepaymentEvent: number;
|
|
||||||
enableDownPayment: boolean;
|
enableDownPayment: boolean;
|
||||||
enableAutoRepaymentForDownPayment: boolean;
|
enableAutoRepaymentForDownPayment: boolean;
|
||||||
enableInstallmentLevelDelinquency: boolean;
|
enableInstallmentLevelDelinquency: boolean;
|
||||||
|
|||||||
-1
@@ -23,7 +23,6 @@
|
|||||||
<mifosx-loan-product-summary
|
<mifosx-loan-product-summary
|
||||||
[action]="'view'"
|
[action]="'view'"
|
||||||
[loanProduct]="loanProduct"
|
[loanProduct]="loanProduct"
|
||||||
[useDueForRepaymentsConfigurations]="useDueForRepaymentsConfigurations"
|
|
||||||
[paymentAllocations]="loanProduct.paymentAllocation"
|
[paymentAllocations]="loanProduct.paymentAllocation"
|
||||||
[creditAllocations]="loanProduct.creditAllocation"
|
[creditAllocations]="loanProduct.creditAllocation"
|
||||||
[supportedInterestRefundTypes]="loanProduct.supportedInterestRefundTypes"
|
[supportedInterestRefundTypes]="loanProduct.supportedInterestRefundTypes"
|
||||||
|
|||||||
@@ -39,13 +39,10 @@ export class GeneralTabComponent implements OnInit {
|
|||||||
private translateService = inject(TranslateService);
|
private translateService = inject(TranslateService);
|
||||||
|
|
||||||
loanProduct: LoanProduct;
|
loanProduct: LoanProduct;
|
||||||
useDueForRepaymentsConfigurations = false;
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.route.data.subscribe((data: { loanProduct: any }) => {
|
this.route.data.subscribe((data: { loanProduct: any }) => {
|
||||||
this.loanProduct = data.loanProduct;
|
this.loanProduct = data.loanProduct;
|
||||||
this.useDueForRepaymentsConfigurations =
|
|
||||||
!this.loanProduct.dueDaysForRepaymentEvent && !this.loanProduct.overDueDaysForRepaymentEvent;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user