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-60">{{ loanProduct.shortName }}</span>
|
||||
</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) {
|
||||
<div class="flex-fill layout-row">
|
||||
<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-60">{{ loanProduct.digitsAfterDecimal ?? loanProduct.currency.decimalPlaces }}</span>
|
||||
</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>
|
||||
<mat-divider [inset]="true"></mat-divider>
|
||||
<div class="flex-fill layout-row">
|
||||
@@ -414,24 +386,6 @@
|
||||
</span>
|
||||
</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) {
|
||||
<div class="flex-100 layout-row-wrap responsive-column">
|
||||
<h3 class="mat-h3 flex-100">{{ 'labels.inputs.Loan Charge-off behaviour' | translate }}</h3>
|
||||
@@ -737,55 +691,6 @@
|
||||
}
|
||||
</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>
|
||||
<mat-divider [inset]="true"></mat-divider>
|
||||
<div class="flex-fill layout-row">
|
||||
|
||||
-1
@@ -84,7 +84,6 @@ export class LoanProductSummaryComponent implements OnInit, OnChanges {
|
||||
@Input() action: string;
|
||||
@Input() loanProduct: LoanProduct;
|
||||
@Input() loanProductsTemplate: any | null;
|
||||
@Input() useDueForRepaymentsConfigurations: boolean;
|
||||
@Input() paymentAllocations: PaymentAllocation | null;
|
||||
@Input() creditAllocations: CreditAllocation | null;
|
||||
@Input() supportedInterestRefundTypes: StringEnumOptionData[] | null;
|
||||
|
||||
@@ -304,10 +304,6 @@ export class CreateLoanProductComponent implements OnInit {
|
||||
|
||||
submit() {
|
||||
const loanProduct = this.loanProducts.buildPayload(this.loanProduct, this.itemsByDefault);
|
||||
if (loanProduct['useDueForRepaymentsConfigurations'] === true) {
|
||||
loanProduct['dueDaysForRepaymentEvent'] = null;
|
||||
loanProduct['overDueDaysForRepaymentEvent'] = null;
|
||||
}
|
||||
if (this.isAdvancedPaymentStrategy) {
|
||||
loanProduct['supportedInterestRefundTypes'] = this.mapStringEnumOptionToIdList(
|
||||
loanProduct['supportedInterestRefundTypes']
|
||||
@@ -316,7 +312,6 @@ export class CreateLoanProductComponent implements OnInit {
|
||||
delete loanProduct['supportedInterestRefundTypes'];
|
||||
delete loanProduct['daysInYearCustomStrategy'];
|
||||
}
|
||||
delete loanProduct['useDueForRepaymentsConfigurations'];
|
||||
|
||||
this.productsService.createLoanProduct(loanProduct).subscribe((response: any) => {
|
||||
this.router.navigate(
|
||||
|
||||
@@ -353,10 +353,6 @@ export class EditLoanProductComponent implements OnInit {
|
||||
|
||||
submit() {
|
||||
const loanProduct = this.loanProducts.buildPayload(this.loanProduct, this.itemsByDefault);
|
||||
if (loanProduct['useDueForRepaymentsConfigurations']) {
|
||||
loanProduct['dueDaysForRepaymentEvent'] = null;
|
||||
loanProduct['overDueDaysForRepaymentEvent'] = null;
|
||||
}
|
||||
if (this.isAdvancedPaymentStrategy) {
|
||||
loanProduct['supportedInterestRefundTypes'] = this.mapStringEnumOptionToIdList(
|
||||
loanProduct['supportedInterestRefundTypes']
|
||||
@@ -365,7 +361,6 @@ export class EditLoanProductComponent implements OnInit {
|
||||
delete loanProduct['supportedInterestRefundTypes'];
|
||||
delete loanProduct['daysInYearCustomStrategy'];
|
||||
}
|
||||
delete loanProduct['useDueForRepaymentsConfigurations'];
|
||||
|
||||
this.productsService.updateLoanProduct(this.loanProductAndTemplate.id, loanProduct).subscribe((response: any) => {
|
||||
this.router.navigate(
|
||||
|
||||
+396
-531
@@ -7,542 +7,407 @@
|
||||
-->
|
||||
|
||||
<form [formGroup]="loanProductAccountingForm">
|
||||
<!-- Accounting Rule Section -->
|
||||
<div class="lpa-section">
|
||||
<div class="lpa-section-header">
|
||||
<i class="fas fa-book lpa-section-icon"></i>
|
||||
<h3>{{ 'labels.heading.Accounting Rule' | translate }}</h3>
|
||||
<div class="lpa-section__header">
|
||||
<span class="lpa-section__icon">
|
||||
<i class="fas fa-book"></i>
|
||||
</span>
|
||||
<h3>Accounting</h3>
|
||||
</div>
|
||||
<div class="lpa-section-body">
|
||||
<div class="lpa-full-width">
|
||||
<mat-radio-group class="lpa-radio-group" formControlName="accountingRule">
|
||||
@for (accountingRule of accountingRuleData; track accountingRule; let i = $index) {
|
||||
<mat-radio-button [value]="i + 1">
|
||||
{{ 'labels.accounting.' + accountingRule | translate }}
|
||||
</mat-radio-button>
|
||||
}
|
||||
</mat-radio-group>
|
||||
|
||||
<div class="lpa-section__body">
|
||||
<!-- Accounting Rule Section -->
|
||||
<div class="lpa-group">
|
||||
<div class="lpa-group__header">
|
||||
<h4>Accounting Rule</h4>
|
||||
</div>
|
||||
<div class="lpa-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>
|
||||
@if (isAccountingAccrualBased) {
|
||||
<div class="lpa-full-width lpa-checkbox-row">
|
||||
<mat-checkbox formControlName="enableAccrualActivityPosting">{{
|
||||
'labels.inputs.Enable Accrual Activity Posting on Installment Due Date' | translate
|
||||
}}</mat-checkbox>
|
||||
|
||||
<!-- Main Accounting Sections -->
|
||||
@for (section of accountingSectionConfigs; track section.key) {
|
||||
<div class="lpa-group">
|
||||
<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>
|
||||
|
||||
@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>
|
||||
|
||||
+283
-79
@@ -6,124 +6,328 @@
|
||||
* 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 {
|
||||
border: 1px solid #e2e8f0;
|
||||
border: 1px solid $border;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
& + & {
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
// Section header
|
||||
.lpa-section-header {
|
||||
.lpa-section__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
background: $gray-50;
|
||||
border-bottom: 1px solid $gray-200;
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
color: $gray-900;
|
||||
}
|
||||
}
|
||||
|
||||
.lpa-section-icon {
|
||||
color: #0ea5e9;
|
||||
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;
|
||||
.lpa-section__icon {
|
||||
display: inline-flex;
|
||||
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-subsection {
|
||||
padding: 16px 24px;
|
||||
border-top: 1px solid #e8eaed;
|
||||
.lpa-section__body {
|
||||
padding: 16px 24px 20px;
|
||||
}
|
||||
|
||||
.lpa-subsection-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
.lpa-group {
|
||||
& + & {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
margin: 0 0 12px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: #94a3b8;
|
||||
}
|
||||
}
|
||||
|
||||
// Add buttons
|
||||
.lpa-add-btn {
|
||||
height: 32px;
|
||||
border-radius: 8px;
|
||||
.lpa-add-other-btn {
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: #2563eb;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
font-weight: 700;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
// Table wrapper
|
||||
.lpa-table-wrapper {
|
||||
.lpa-list {
|
||||
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-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;
|
||||
margin-top: 8px;
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// Responsive
|
||||
@media (width <= 600px) {
|
||||
.lpa-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.lpa-checkbox-row {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.lpa-radio-group {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.lpa-subsection-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
}
|
||||
.lpa-radio-group {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
+550
-417
File diff suppressed because it is too large
Load Diff
-57
@@ -57,61 +57,4 @@
|
||||
</mat-form-field>
|
||||
</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>
|
||||
|
||||
+3
-86
@@ -9,8 +9,6 @@
|
||||
import { Component, OnInit, Input, inject } from '@angular/core';
|
||||
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||
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';
|
||||
|
||||
@Component({
|
||||
@@ -19,9 +17,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
styleUrls: ['./loan-product-currency-step.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatTooltip,
|
||||
MatCheckbox,
|
||||
FaIconComponent
|
||||
MatTooltip
|
||||
]
|
||||
})
|
||||
export class LoanProductCurrencyStepComponent implements OnInit {
|
||||
@@ -46,69 +42,8 @@ export class LoanProductCurrencyStepComponent implements OnInit {
|
||||
this.loanProductsTemplate.currency.decimalPlaces === undefined ||
|
||||
this.loanProductsTemplate.currency.decimalPlaces === null
|
||||
? ''
|
||||
: 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.loanProductsTemplate.currency.decimalPlaces
|
||||
});
|
||||
|
||||
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() {
|
||||
@@ -123,10 +58,7 @@ export class LoanProductCurrencyStepComponent implements OnInit {
|
||||
Validators.required,
|
||||
Validators.min(0)
|
||||
]
|
||||
],
|
||||
setMultiples: [false],
|
||||
inMultiplesOf: [''],
|
||||
installmentAmountInMultiplesOf: ['']
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
@@ -136,21 +68,6 @@ export class LoanProductCurrencyStepComponent implements OnInit {
|
||||
currencyCode: formValue.currencyCode,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
-30
@@ -41,36 +41,6 @@
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</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>
|
||||
|
||||
|
||||
+3
-17
@@ -14,9 +14,7 @@ import { Dates } from 'app/core/utils/dates';
|
||||
/** Custom Services */
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
@Component({
|
||||
@@ -26,9 +24,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatTooltip,
|
||||
MatCheckbox,
|
||||
CdkTextareaAutosize,
|
||||
FaIconComponent
|
||||
CdkTextareaAutosize
|
||||
]
|
||||
})
|
||||
export class LoanProductDetailsStepComponent implements OnInit {
|
||||
@@ -40,8 +36,6 @@ export class LoanProductDetailsStepComponent implements OnInit {
|
||||
|
||||
loanProductDetailsForm: UntypedFormGroup;
|
||||
|
||||
fundData: any;
|
||||
|
||||
minDate = new Date(2000, 0, 1);
|
||||
maxDate = new Date(new Date().setFullYear(new Date().getFullYear() + 10));
|
||||
|
||||
@@ -56,17 +50,12 @@ export class LoanProductDetailsStepComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.fundData = this.loanProductsTemplate.fundOptions;
|
||||
|
||||
this.loanProductDetailsForm.patchValue({
|
||||
name: this.loanProductsTemplate.name,
|
||||
shortName: this.loanProductsTemplate.shortName,
|
||||
description: this.loanProductsTemplate.description,
|
||||
externalId: this.loanProductsTemplate.externalId,
|
||||
fundId: this.loanProductsTemplate.fundId,
|
||||
startDate: this.loanProductsTemplate.startDate && new Date(this.loanProductsTemplate.startDate),
|
||||
closeDate: this.loanProductsTemplate.closeDate && new Date(this.loanProductsTemplate.closeDate),
|
||||
includeInBorrowerCycle: this.loanProductsTemplate.includeInBorrowerCycle
|
||||
closeDate: this.loanProductsTemplate.closeDate && new Date(this.loanProductsTemplate.closeDate)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -81,11 +70,8 @@ export class LoanProductDetailsStepComponent implements OnInit {
|
||||
Validators.required
|
||||
],
|
||||
description: [''],
|
||||
externalId: [''],
|
||||
fundId: [''],
|
||||
startDate: [''],
|
||||
closeDate: [''],
|
||||
includeInBorrowerCycle: [false]
|
||||
closeDate: ['']
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -10,7 +10,6 @@
|
||||
[action]="'preview'"
|
||||
[loanProduct]="loanProduct"
|
||||
[loanProductsTemplate]="loanProductsTemplate"
|
||||
[useDueForRepaymentsConfigurations]="loanProduct.useDueForRepaymentsConfigurations"
|
||||
[paymentAllocations]="loanProduct.paymentAllocation"
|
||||
[creditAllocations]="loanProduct.creditAllocation"
|
||||
[supportedInterestRefundTypes]="loanProduct.supportedInterestRefundTypes"
|
||||
|
||||
+507
-174
@@ -235,147 +235,528 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Loan Tranche Details -->
|
||||
<!-- Cheque Book Settings -->
|
||||
<div class="lps-section">
|
||||
<div class="lps-section__header">
|
||||
<i class="fas fa-layer-group lps-section__icon"></i>
|
||||
<h3 class="lps-section__title">{{ 'labels.inputs.Loan Tranche Details' | translate }}</h3>
|
||||
<i class="fas fa-money-check lps-section__icon"></i>
|
||||
<h3 class="lps-section__title">Cheque Book Settings</h3>
|
||||
</div>
|
||||
<div class="lps-section__body">
|
||||
<div class="lps-checkbox-row lps-full-width">
|
||||
<mat-checkbox
|
||||
labelPosition="before"
|
||||
formControlName="multiDisburseLoan"
|
||||
matTooltip="{{ 'tooltips.Leave this checkbox unchecked' | translate }}"
|
||||
>
|
||||
{{ 'labels.inputs.Enable Multiple Disbursals' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<div class="lps-section__body lps-grid-4">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Cheque Book Issue Enabled</mat-label>
|
||||
<mat-select formControlName="chequeBookIssueEnabled">
|
||||
<mat-option value="YES">YES</mat-option>
|
||||
<mat-option value="NO">NO</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
@if (loanProductSettingsForm.value.multiDisburseLoan) {
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Maximum Tranche count' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
matInput
|
||||
matTooltip="{{ 'tooltips.Maximum number of disbursements' | translate }}"
|
||||
formControlName="maxTrancheCount"
|
||||
required
|
||||
/>
|
||||
@if (loanProductSettingsForm.controls.maxTrancheCount.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Maximum Tranche count' | 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 allowed outstanding balance' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
matInput
|
||||
matTooltip="{{ 'tooltips.Maximum outstanding loan account balance' | translate }}"
|
||||
formControlName="outstandingLoanBalance"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<div class="lps-checkbox-row">
|
||||
<mat-checkbox labelPosition="before" formControlName="disallowExpectedDisbursements">
|
||||
{{ 'labels.inputs.Disallow Expected Disbursements' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
@if (loanProductSettingsForm.value.loanScheduleType === 'PROGRESSIVE') {
|
||||
<div class="lps-checkbox-row">
|
||||
<mat-checkbox
|
||||
labelPosition="before"
|
||||
formControlName="allowFullTermForTranche"
|
||||
matTooltip="{{ 'tooltips.Allow full term length for each tranche disbursement' | translate }}"
|
||||
>
|
||||
{{ 'labels.inputs.Allow full term for each tranche' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Cheque Validation Required</mat-label>
|
||||
<mat-select formControlName="chequeValidationRequired">
|
||||
<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>Is First Cheque Book Free</mat-label>
|
||||
<mat-select formControlName="isFirstChequeBookFree">
|
||||
<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>Cheque Printing Account Type</mat-label>
|
||||
<mat-select formControlName="chequePrintingAccountType">
|
||||
<mat-option value="SAVINGS_BANK">Savings Bank</mat-option>
|
||||
<mat-option value="CURRENT_ACCOUNT">Current Account</mat-option>
|
||||
<mat-option value="CASH_CREDIT">Cash Credit</mat-option>
|
||||
<mat-option value="OVERDRAFT">Overdraft</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Allow Withdrawal Slip Usage</mat-label>
|
||||
<mat-select formControlName="allowWithdrawalSlipUsage">
|
||||
<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>Maintain Cheque Book Stock Registry</mat-label>
|
||||
<mat-select formControlName="maintainChequeBookStockRegistry">
|
||||
<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>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>
|
||||
|
||||
<!-- Down Payment -->
|
||||
<!-- Additional Product Settings -->
|
||||
<div class="lps-section">
|
||||
<div class="lps-section__header">
|
||||
<i class="fas fa-hand-holding-usd lps-section__icon"></i>
|
||||
<h3 class="lps-section__title">{{ 'labels.heading.Down Payment' | translate }}</h3>
|
||||
<i class="fas fa-cogs lps-section__icon"></i>
|
||||
<h3 class="lps-section__title">Additional Product Settings</h3>
|
||||
</div>
|
||||
<div class="lps-section__body">
|
||||
<div class="lps-checkbox-row lps-full-width">
|
||||
<mat-checkbox
|
||||
labelPosition="before"
|
||||
formControlName="enableDownPayment"
|
||||
matTooltip="{{ 'tooltips.Leave this checkbox unchecked' | translate }}"
|
||||
>
|
||||
{{ 'labels.inputs.Enable Down Payment' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<div class="lps-section__body lps-grid-4">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Account Type Active For Transactions</mat-label>
|
||||
<mat-select formControlName="accountTypeActiveForTransactions">
|
||||
<mat-option value="YES">YES</mat-option>
|
||||
<mat-option value="NO">NO</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
@if (loanProductSettingsForm.value.enableDownPayment) {
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Disbursed Amount Percentage Down Payment' | translate }} (%)</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
matInput
|
||||
matTooltip="{{ 'tooltips.The percentage of disbursements amount for Down Payment' | translate }}"
|
||||
formControlName="disbursedAmountPercentageForDownPayment"
|
||||
required
|
||||
[min]="0"
|
||||
[max]="100"
|
||||
/>
|
||||
@if (loanProductSettingsForm.controls.disbursedAmountPercentageForDownPayment.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Disbursed Amount Percentage Down Payment' | translate }}
|
||||
{{ 'labels.commons.is' | translate }} <strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
@if (loanProductSettingsForm.controls.disbursedAmountPercentageForDownPayment.errors?.range) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Disbursed Amount Percentage Down Payment' | translate }}
|
||||
{{ 'labels.commons.is' | translate }} {{ 'labels.text.out' | translate }}
|
||||
<strong>{{ 'labels.text.percentage range' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<div class="lps-checkbox-row">
|
||||
<mat-checkbox
|
||||
labelPosition="before"
|
||||
formControlName="enableAutoRepaymentForDownPayment"
|
||||
matTooltip="{{ 'tooltips.Enable or disable the auto repayment of down-payment.' | translate }}"
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Sub Type Activity Enabled</mat-label>
|
||||
<mat-select formControlName="subTypeActivityEnabled">
|
||||
<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>Account Opening Charges</mat-label>
|
||||
<input type="number" matInput formControlName="accountOpeningCharges" />
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Maximum Gold Loan Limit</mat-label>
|
||||
<input type="number" matInput formControlName="maximumGoldLoanLimit" />
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Last Account Number Opened</mat-label>
|
||||
<input type="text" matInput formControlName="lastAccountNumberOpened" />
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Customer Termination Allowed</mat-label>
|
||||
<mat-select formControlName="customerTerminationAllowed">
|
||||
<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>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-checkbox>
|
||||
</div>
|
||||
}
|
||||
<mat-option value="BASED ON ASSET VALUE">Based on Asset Value</mat-option>
|
||||
<mat-option value="MONTHLY STOCK STATEMENT BASIS">Monthly Stock Statement Basis</mat-option>
|
||||
</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>
|
||||
|
||||
<!-- 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 -->
|
||||
<div class="lps-section">
|
||||
<div class="lps-section__header">
|
||||
@@ -807,54 +1188,6 @@
|
||||
</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 -->
|
||||
<div class="lps-section">
|
||||
<div class="lps-section__header">
|
||||
|
||||
+12
@@ -57,6 +57,18 @@
|
||||
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 {
|
||||
|
||||
+79
-79
@@ -15,7 +15,6 @@ import {
|
||||
ReactiveFormsModule
|
||||
} from '@angular/forms';
|
||||
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 { CodeName, OptionData, StringEnumOptionData } from 'app/shared/models/option-data.model';
|
||||
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',
|
||||
templateUrl: './loan-product-settings-step.component.html',
|
||||
styleUrls: ['./loan-product-settings-step.component.scss'],
|
||||
standalone: true,
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatTooltip,
|
||||
MatCheckbox,
|
||||
MatIconButton,
|
||||
FaIconComponent
|
||||
FaIconComponent,
|
||||
ReactiveFormsModule
|
||||
]
|
||||
})
|
||||
export class LoanProductSettingsStepComponent implements OnInit {
|
||||
private formBuilder = inject(UntypedFormBuilder);
|
||||
private processingStrategyService = inject(ProcessingStrategyService);
|
||||
|
||||
DAYS_BEFORE_REPAYMENT_IS_DUE = LoanProducts.DAYS_BEFORE_REPAYMENT_IS_DUE;
|
||||
DAYS_AFTER_REPAYMENT_IS_OVERDUE = LoanProducts.DAYS_AFTER_REPAYMENT_IS_OVERDUE;
|
||||
|
||||
@Input() toEdit: boolean;
|
||||
@Input() loanProductsTemplate: any;
|
||||
@Input() isLinkedToFloatingInterestRates: UntypedFormControl;
|
||||
@@ -71,7 +69,6 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
||||
loanScheduleProcessingTypeData: OptionData[] = [];
|
||||
isAdvancedTransactionProcessingStrategy = false;
|
||||
advancedTransactionProcessingStrategyDisabled = true;
|
||||
useDueForRepaymentsConfigurations = false;
|
||||
rescheduleStrategyTypeDisabled = false;
|
||||
chargeOffBehaviourData: StringEnumOptionData[] = [];
|
||||
daysInYearCustomStrategyOptions: OptionData[] = [];
|
||||
@@ -150,12 +147,10 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
||||
maxTrancheCount: this.loanProductsTemplate.maxTrancheCount,
|
||||
outstandingLoanBalance: this.loanProductsTemplate.outstandingLoanBalance,
|
||||
allowFullTermForTranche: this.loanProductsTemplate.allowFullTermForTranche,
|
||||
enableDownPayment: this.loanProductsTemplate.enableDownPayment,
|
||||
enableInstallmentLevelDelinquency: this.loanProductsTemplate.enableInstallmentLevelDelinquency,
|
||||
allowCompoundingOnEod: this.loanProductsTemplate.allowCompoundingOnEod,
|
||||
isCompoundingToBePostedAsTransaction: this.loanProductsTemplate.isCompoundingToBePostedAsTransaction,
|
||||
loanScheduleType: this.loanProductsTemplate.loanScheduleType.code,
|
||||
useDueForRepaymentsConfigurations: this.loanProductsTemplate.useDueForRepaymentsConfigurations,
|
||||
allowAccrualPostingInArrears: this.loanProductsTemplate.allowAccrualPostingInArrears,
|
||||
chargeOffBehaviour: this.loanProductsTemplate.chargeOffBehaviour.id
|
||||
});
|
||||
@@ -166,23 +161,6 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
||||
this.processingStrategyService.initialize(this.isAdvancedTransactionProcessingStrategy);
|
||||
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) {
|
||||
this.loanProductSettingsForm.patchValue({
|
||||
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) {
|
||||
this.loanProductSettingsForm.patchValue({
|
||||
preClosureInterestCalculationStrategy:
|
||||
@@ -355,24 +326,89 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
||||
graceOnArrearsAgeing: [true]
|
||||
}),
|
||||
delinquencyBucketId: [''],
|
||||
enableDownPayment: [false],
|
||||
enableInstallmentLevelDelinquency: [false],
|
||||
allowCompoundingOnEod: [false],
|
||||
isCompoundingToBePostedAsTransaction: [false],
|
||||
useDueForRepaymentsConfigurations: [false],
|
||||
dueDaysForRepaymentEvent: [
|
||||
'',
|
||||
[Validators.min(0)]
|
||||
],
|
||||
overDueDaysForRepaymentEvent: [
|
||||
'',
|
||||
[Validators.min(0)]
|
||||
],
|
||||
loanScheduleType: [
|
||||
LoanProducts.LOAN_SCHEDULE_TYPE_CUMULATIVE,
|
||||
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
|
||||
.get('transactionProcessingStrategyCode')
|
||||
.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.transactionProcessingStrategyData = [];
|
||||
if (loanScheduleType === LoanProducts.LOAN_SCHEDULE_TYPE_CUMULATIVE) {
|
||||
@@ -771,10 +775,6 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
||||
|
||||
get loanProductSettings() {
|
||||
const productSettings = this.loanProductSettingsForm.value;
|
||||
if (this.loanProductSettingsForm.value.useDueForRepaymentsConfigurations) {
|
||||
productSettings['dueDaysForRepaymentEvent'] = null;
|
||||
productSettings['overDueDaysForRepaymentEvent'] = null;
|
||||
}
|
||||
if (productSettings['delinquencyBucketId'] === '') {
|
||||
productSettings['delinquencyBucketId'] = null;
|
||||
}
|
||||
|
||||
-332
@@ -18,43 +18,6 @@
|
||||
></i>
|
||||
</div>
|
||||
<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">
|
||||
<mat-checkbox labelPosition="before" formControlName="allowApprovedDisbursedAmountsOverApplied">
|
||||
{{ 'labels.inputs.Allow approval / disbursal above loan applied amount' | translate }}
|
||||
@@ -119,57 +82,6 @@
|
||||
</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 -->
|
||||
<div class="lpt-section">
|
||||
<div class="lpt-section-header">
|
||||
@@ -352,250 +264,6 @@
|
||||
}
|
||||
</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 -->
|
||||
<div class="lpt-section">
|
||||
<div class="lpt-section-header">
|
||||
|
||||
+4
-259
@@ -11,36 +11,14 @@ import {
|
||||
UntypedFormGroup,
|
||||
UntypedFormBuilder,
|
||||
Validators,
|
||||
UntypedFormArray,
|
||||
UntypedFormControl,
|
||||
ReactiveFormsModule
|
||||
} 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 { TranslateService } from '@ngx-translate/core';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { MatButton, MatIconButton } from '@angular/material/button';
|
||||
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 { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
@@ -53,24 +31,12 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
MatTooltip,
|
||||
MatCheckbox,
|
||||
FaIconComponent,
|
||||
MatTable,
|
||||
MatColumnDef,
|
||||
MatHeaderCellDef,
|
||||
MatHeaderCell,
|
||||
MatCellDef,
|
||||
MatCell,
|
||||
MatIconButton,
|
||||
MatHeaderRowDef,
|
||||
MatHeaderRow,
|
||||
MatRowDef,
|
||||
MatRow,
|
||||
FindPipe
|
||||
]
|
||||
})
|
||||
export class LoanProductTermsStepComponent implements OnInit, OnChanges {
|
||||
private formBuilder = inject(UntypedFormBuilder);
|
||||
private processingStrategyService = inject(ProcessingStrategyService);
|
||||
private dialog = inject(MatDialog);
|
||||
private translateService = inject(TranslateService);
|
||||
|
||||
@Input() loanProductsTemplate: any;
|
||||
@@ -80,30 +46,20 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
|
||||
/** Zero Interest control. */
|
||||
zeroInterest = new UntypedFormControl(false);
|
||||
|
||||
valueConditionTypeData: any;
|
||||
isAdvancedTransactionProcessingStrategy = false;
|
||||
|
||||
floatingRateData: any;
|
||||
interestRateFrequencyTypeData: any;
|
||||
overAppliedCalculationTypeData: any;
|
||||
repaymentFrequencyTypeData: any;
|
||||
repaymentStartDateTypeOptions: any;
|
||||
|
||||
displayedColumns: string[] = [
|
||||
'valueConditionType',
|
||||
'borrowerCycleNumber',
|
||||
'minValue',
|
||||
'defaultValue',
|
||||
'maxValue',
|
||||
'actions'
|
||||
];
|
||||
isAdvancedTransactionProcessingStrategy = false;
|
||||
|
||||
constructor() {
|
||||
this.createLoanProductTermsForm();
|
||||
this.setConditionalControls();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.valueConditionTypeData = this.loanProductsTemplate.valueConditionTypeOptions;
|
||||
this.floatingRateData = this.loanProductsTemplate.floatingRateOptions;
|
||||
this.interestRateFrequencyTypeData = this.loanProductsTemplate.interestRateFrequencyTypeOptions;
|
||||
this.repaymentFrequencyTypeData = this.loanProductsTemplate.repaymentFrequencyTypeOptions;
|
||||
@@ -114,12 +70,6 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
|
||||
];
|
||||
|
||||
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,
|
||||
minInterestRatePerPeriod: this.loanProductsTemplate.minInterestRatePerPeriod,
|
||||
interestRatePerPeriod: this.loanProductsTemplate.interestRatePerPeriod,
|
||||
@@ -132,13 +82,11 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
|
||||
minDifferentialLendingRate: this.loanProductsTemplate.minDifferentialLendingRate,
|
||||
defaultDifferentialLendingRate: this.loanProductsTemplate.defaultDifferentialLendingRate,
|
||||
maxDifferentialLendingRate: this.loanProductsTemplate.maxDifferentialLendingRate,
|
||||
useBorrowerCycle: this.loanProductsTemplate.useBorrowerCycle,
|
||||
repaymentEvery: this.loanProductsTemplate.repaymentEvery,
|
||||
repaymentFrequencyType: this.loanProductsTemplate.repaymentFrequencyType.id,
|
||||
minimumDaysBetweenDisbursalAndFirstRepayment:
|
||||
this.loanProductsTemplate.minimumDaysBetweenDisbursalAndFirstRepayment,
|
||||
repaymentStartDateType: this.loanProductsTemplate.repaymentStartDateType.id || 1,
|
||||
interestRecognitionOnDisbursementDate: this.loanProductsTemplate.interestRecognitionOnDisbursementDate || false
|
||||
repaymentStartDateType: this.loanProductsTemplate.repaymentStartDateType.id || 1
|
||||
});
|
||||
|
||||
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.loanProductsTemplate.minInterestRatePerPeriod === 0 &&
|
||||
this.loanProductsTemplate.interestRatePerPeriod === 0 &&
|
||||
@@ -190,45 +110,6 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
|
||||
|
||||
createLoanProductTermsForm() {
|
||||
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],
|
||||
allowApprovedDisbursedAmountsOverApplied: [false],
|
||||
overAppliedCalculationType: [{ value: null, disabled: true }],
|
||||
@@ -275,8 +156,7 @@ export class LoanProductTermsStepComponent implements OnInit, OnChanges {
|
||||
[]
|
||||
],
|
||||
repaymentStartDateType: [1],
|
||||
fixedLength: [null],
|
||||
interestRecognitionOnDisbursementDate: [false]
|
||||
fixedLength: [null]
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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) => {
|
||||
if (zeroInterest) {
|
||||
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() {
|
||||
const formValue = this.loanProductTermsForm.getRawValue();
|
||||
// Normalize decimal separators: convert comma to dot for backend compatibility
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { GlobalConfiguration } from 'app/system/configurations/global-configurations-tab/configuration.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@@ -24,46 +23,15 @@ export class LoanProducts {
|
||||
|
||||
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 {
|
||||
return code === this.ADVANCED_PAYMENT_ALLOCATION_STRATEGY;
|
||||
}
|
||||
|
||||
public setItemsByDefault(configurations: any) {
|
||||
const itemsByDefault: GlobalConfiguration[] = [];
|
||||
configurations.globalConfiguration.forEach((config: GlobalConfiguration) => {
|
||||
if (this.globalConfigurations.includes(config.name)) {
|
||||
itemsByDefault.push(config);
|
||||
}
|
||||
});
|
||||
return itemsByDefault;
|
||||
public setItemsByDefault(configurations: any): any[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -86,34 +54,14 @@ export class LoanProducts {
|
||||
loanProduct.allowPartialPeriodInterestCalculation = 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;
|
||||
}
|
||||
|
||||
public isItemByDefault(propertyName: string): boolean {
|
||||
return this.propertyNames.includes(propertyName);
|
||||
return false;
|
||||
}
|
||||
|
||||
public isGlobalConfigurations(propertyName: string): boolean {
|
||||
return this.globalConfigurations.includes(propertyName);
|
||||
}
|
||||
|
||||
private resolvePropertyName(configName: string): string {
|
||||
if (this.globalConfigurations.includes(configName)) {
|
||||
const idx = this.globalConfigurations.indexOf(configName);
|
||||
if (idx > -1) {
|
||||
return this.propertyNames[idx];
|
||||
}
|
||||
}
|
||||
return '';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,17 +26,13 @@ export interface LoanProduct {
|
||||
id: number;
|
||||
name: string;
|
||||
shortName: string;
|
||||
includeInBorrowerCycle: boolean;
|
||||
useBorrowerCycle: boolean;
|
||||
status: string;
|
||||
currency: Currency;
|
||||
currencyCode?: string;
|
||||
fundId?: number;
|
||||
fundName?: string;
|
||||
startDate?: string;
|
||||
closeDate?: string;
|
||||
description?: string;
|
||||
installmentAmountInMultiplesOf?: number;
|
||||
principal: number;
|
||||
minPrincipal?: number;
|
||||
maxPrincipal?: number;
|
||||
@@ -123,8 +119,6 @@ export interface LoanProduct {
|
||||
graceOnInterestPayment?: number;
|
||||
graceOnInterestCharged?: number;
|
||||
inArrearsTolerance?: number;
|
||||
dueDaysForRepaymentEvent: number;
|
||||
overDueDaysForRepaymentEvent: number;
|
||||
enableDownPayment: boolean;
|
||||
enableAutoRepaymentForDownPayment: boolean;
|
||||
enableInstallmentLevelDelinquency: boolean;
|
||||
|
||||
-1
@@ -23,7 +23,6 @@
|
||||
<mifosx-loan-product-summary
|
||||
[action]="'view'"
|
||||
[loanProduct]="loanProduct"
|
||||
[useDueForRepaymentsConfigurations]="useDueForRepaymentsConfigurations"
|
||||
[paymentAllocations]="loanProduct.paymentAllocation"
|
||||
[creditAllocations]="loanProduct.creditAllocation"
|
||||
[supportedInterestRefundTypes]="loanProduct.supportedInterestRefundTypes"
|
||||
|
||||
@@ -39,13 +39,10 @@ export class GeneralTabComponent implements OnInit {
|
||||
private translateService = inject(TranslateService);
|
||||
|
||||
loanProduct: LoanProduct;
|
||||
useDueForRepaymentsConfigurations = false;
|
||||
|
||||
constructor() {
|
||||
this.route.data.subscribe((data: { loanProduct: any }) => {
|
||||
this.loanProduct = data.loanProduct;
|
||||
this.useDueForRepaymentsConfigurations =
|
||||
!this.loanProduct.dueDaysForRepaymentEvent && !this.loanProduct.overDueDaysForRepaymentEvent;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user