Advanced payment allocation supports Cumulative or Progressive Loan Schedule (#1904)

Co-authored-by: Jose Alberto Hernandez <alberto@blue-daemon.local>
This commit is contained in:
José Alberto Hernández
2023-11-18 17:03:46 -06:00
committed by GitHub
co-authored by Jose Alberto Hernandez
parent d8a279fc51
commit df71736fd6
22 changed files with 1624 additions and 1921 deletions
@@ -116,7 +116,7 @@
</mat-form-field>
<mat-form-field fxFlex="98%">
<mat-label>{{"labels.inputs.Destination" | translate}}</mat-label>
<mat-label>{{"labels.inputs.Description" | translate}}</mat-label>
<textarea matInput formControlName="transferDescription" cdkTextareaAutosize
cdkAutosizeMinRows="2"></textarea>
<mat-error *ngIf="makeAccountTransferForm.controls.transferDescription.hasError('required')">
@@ -0,0 +1,905 @@
<div class="tab-container mat-typography" *ngIf="loanProduct">
<h3 class="mat-h3" fxFlexFill>Details</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="47%">Name:</span>
<span fxFlex="53%"><b>{{ loanProduct.name }}</b></span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Short Name:</span>
<span fxFlex="53%">{{ loanProduct.shortName }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.fundId">
<span fxFlex="47%">Fund Name:</span>
<span fxFlex="53%">{{ loanProduct.fundName }}</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Include in Customer Loan Counter:</span>
<span fxFlex="53%">{{ loanProduct.includeInBorrowerCycle | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.startDate">
<span fxFlex="47%">Start Date:</span>
<span fxFlex="53%">{{ loanProduct.startDate | dateFormat }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.closeDate">
<span fxFlex="47%">Close Date:</span>
<span fxFlex="53%">{{ loanProduct.closeDate | dateFormat }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.description">
<span fxFlex="47%">Description:</span>
<span fxFlex="53%">{{ loanProduct.description }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Currency</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill *ngIf="loanProduct.currencyCode">
<span fxFlex="47%">Currency:</span>
<span fxFlex="53%">{{ loanProduct.currencyCode | find:loanProductsTemplate.currencyOptions:'code':'name' }}</span>
</div>
<div fxFlexFill *ngIf="!loanProduct.currencyCode">
<span fxFlex="47%">Currency:</span>
<span fxFlex="53%">{{ loanProduct.currency.name }}</span>
</div>
<div fxFlexFill *ngIf="!loanProduct.currencyCode">
<span fxFlex="47%">Decimal Places:</span>
<span fxFlex="53%">{{ loanProduct.currency.decimalPlaces }}</span>
</div>
<div fxFlexFill *ngIf="!loanProduct.currencyCode">
<span fxFlex="47%">Currency in multiples of:</span>
<span fxFlex="53%">{{ loanProduct.currency.inMultiplesOf }}</span>
</div>
<div fxFlexFill *ngIf="!loanProduct.currencyCode">
<span fxFlex="47%">Installment in multiples of:</span>
<span fxFlex="53%">{{ loanProduct.installmentAmountInMultiplesOf }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Terms</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="47%">Principal:</span>
<span fxFlex="53%">{{ loanProduct.principal | formatNumber }}
(Min {{ (loanProduct.minPrincipal ? loanProduct.minPrincipal : loanProduct.principal) | formatNumber }}
: Max {{ (loanProduct.maxPrincipal ? loanProduct.maxPrincipal : loanProduct.principal) | formatNumber }})
</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Allow Approved / Disbursed Amounts Over Applied:</span>
<span fxFlex="53%">{{ loanProduct.allowApprovedDisbursedAmountsOverApplied | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.allowApprovedDisbursedAmountsOverApplied">
<span fxFlex="47%">Over Applied Amount:</span>
<span fxFlex="53%" *ngIf="loanProduct.overAppliedCalculationType === 'percentage'">{{ loanProduct.overAppliedNumber
| formatNumber
}} %</span>
<span fxFlex="53%" *ngIf="loanProduct.overAppliedCalculationType === 'flat'">{{ loanProduct.overAppliedNumber |
formatNumber }} {{
loanProduct.currencyCode }}</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Installment day calculation from:</span>
<span fxFlex="53%">{{ loanProduct.repaymentStartDateType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Number of Repayments:</span>
<span fxFlex="53%">{{ loanProduct.numberOfRepayments + ' (Min: ' + (loanProduct.minNumberOfRepayments ?
loanProduct.minNumberOfRepayments : loanProduct.numberOfRepayments) + ', Max: ' +
(loanProduct.maxNumberOfRepayments ? loanProduct.maxNumberOfRepayments : loanProduct.numberOfRepayments) + ')'
}}</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Linked to floating interest rates:</span>
<span fxFlex="53%">{{ loanProduct.isLinkedToFloatingInterestRates | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="!loanProduct.isLinkedToFloatingInterestRates">
<span fxFlex="47%">Nominal interest rate:</span>
<span fxFlex="53%">{{ loanProduct.interestRatePerPeriod + ' (Min: ' + (loanProduct.minInterestRatePerPeriod ?
loanProduct.minInterestRatePerPeriod : loanProduct.interestRatePerPeriod) + ', Max: ' +
(loanProduct.maxInterestRatePerPeriod ? loanProduct.maxInterestRatePerPeriod : loanProduct.interestRatePerPeriod)
+ ')' + ' ' + loanProduct.interestRateFrequencyType.value }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.isLinkedToFloatingInterestRates" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="47%">Floating Lending Interest Rate:</span>
<span fxFlex="53%">{{ loanProduct.floatingRateName }}</span>
<span fxFlex="47%">Interest Rate Differential:</span>
<span fxFlex="53%">{{ loanProduct.interestRateDifferential }}</span>
<span fxFlex="47%">Floating Interest Rate Calculation Allowed:</span>
<span fxFlex="53%">{{ loanProduct.isFloatingInterestRateCalculationAllowed | yesNo }}</span>
<span fxFlex="47%">Floating Interest Rate:</span>
<span fxFlex="53%">{{ loanProduct.defaultDifferentialLendingRate + ' (Min: ' +
(loanProduct.minDifferentialLendingRate ? loanProduct.minDifferentialLendingRate :
loanProduct.defaultDifferentialLendingRate) + ', Max: ' + (loanProduct.maxDifferentialLendingRate ?
loanProduct.maxDifferentialLendingRate : loanProduct.defaultDifferentialLendingRate) + ')' }}</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Terms vary based on loan cycle:</span>
<span fxFlex="53%">{{ loanProduct.useBorrowerCycle | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.principalVariationsForBorrowerCycle?.length">
<h4 class="mat-h4" fxFlexFill>Principal by loan cycle</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="loanProduct.principalVariationsForBorrowerCycle">
<ng-container matColumnDef="valueConditionType">
<th mat-header-cell *matHeaderCellDef> Condition </th>
<td mat-cell *matCellDef="let variation">
{{ variation.valueConditionType.value }}
</td>
</ng-container>
<ng-container matColumnDef="borrowerCycleNumber">
<th mat-header-cell *matHeaderCellDef> Loan Cycle </th>
<td mat-cell *matCellDef="let variation">
{{ variation.borrowerCycleNumber }}
</td>
</ng-container>
<ng-container matColumnDef="minValue">
<th mat-header-cell *matHeaderCellDef> Minimum </th>
<td mat-cell *matCellDef="let variation">
{{ variation.minValue }}
</td>
</ng-container>
<ng-container matColumnDef="defaultValue">
<th mat-header-cell *matHeaderCellDef> Default </th>
<td mat-cell *matCellDef="let variation">
{{ variation.defaultValue }}
</td>
</ng-container>
<ng-container matColumnDef="maxValue">
<th mat-header-cell *matHeaderCellDef> Maximum </th>
<td mat-cell *matCellDef="let variation">
{{ variation.maxValue }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="variationsDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: variationsDisplayedColumns;"></tr>
</table>
</div>
<div fxFlexFill *ngIf="loanProduct.numberOfRepaymentVariationsForBorrowerCycle?.length">
<h4 class="mat-h4" fxFlexFill>Number of Repayments by loan cycle</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table
[dataSource]="loanProduct.numberOfRepaymentVariationsForBorrowerCycle">
<ng-container matColumnDef="valueConditionType">
<th mat-header-cell *matHeaderCellDef> Condition </th>
<td mat-cell *matCellDef="let variation">
{{ variation.valueConditionType.value }}
</td>
</ng-container>
<ng-container matColumnDef="borrowerCycleNumber">
<th mat-header-cell *matHeaderCellDef> Loan Cycle </th>
<td mat-cell *matCellDef="let variation">
{{ variation.borrowerCycleNumber }}
</td>
</ng-container>
<ng-container matColumnDef="minValue">
<th mat-header-cell *matHeaderCellDef> Minimum </th>
<td mat-cell *matCellDef="let variation">
{{ variation.minValue }}
</td>
</ng-container>
<ng-container matColumnDef="defaultValue">
<th mat-header-cell *matHeaderCellDef> Default </th>
<td mat-cell *matCellDef="let variation">
{{ variation.defaultValue }}
</td>
</ng-container>
<ng-container matColumnDef="maxValue">
<th mat-header-cell *matHeaderCellDef> Maximum </th>
<td mat-cell *matCellDef="let variation">
{{ variation.maxValue }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="variationsDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: variationsDisplayedColumns;"></tr>
</table>
</div>
<div fxFlexFill *ngIf="loanProduct.interestRateVariationsForBorrowerCycle?.length">
<h4 class="mat-h4" fxFlexFill>Nominal Interest Rate by loan cycle</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table
[dataSource]="loanProduct.interestRateVariationsForBorrowerCycle">
<ng-container matColumnDef="valueConditionType">
<th mat-header-cell *matHeaderCellDef> Condition </th>
<td mat-cell *matCellDef="let variation">
{{ variation.valueConditionType.value }}
</td>
</ng-container>
<ng-container matColumnDef="borrowerCycleNumber">
<th mat-header-cell *matHeaderCellDef> Loan Cycle </th>
<td mat-cell *matCellDef="let variation">
{{ variation.borrowerCycleNumber }}
</td>
</ng-container>
<ng-container matColumnDef="minValue">
<th mat-header-cell *matHeaderCellDef> Minimum </th>
<td mat-cell *matCellDef="let variation">
{{ variation.minValue }}
</td>
</ng-container>
<ng-container matColumnDef="defaultValue">
<th mat-header-cell *matHeaderCellDef> Default </th>
<td mat-cell *matCellDef="let variation">
{{ variation.defaultValue }}
</td>
</ng-container>
<ng-container matColumnDef="maxValue">
<th mat-header-cell *matHeaderCellDef> Maximum </th>
<td mat-cell *matCellDef="let variation">
{{ variation.maxValue }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="variationsDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: variationsDisplayedColumns;"></tr>
</table>
</div>
<div fxFlexFill>
<span fxFlex="47%">Repay Every:</span>
<span fxFlex="53%">{{ loanProduct.repaymentEvery + ' ' + loanProduct.repaymentFrequencyType.value }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.minimumDaysBetweenDisbursalAndFirstRepayment">
<span fxFlex="47%">Minimum days between disbursal and first repayment date:</span>
<span fxFlex="53%">{{ loanProduct.minimumDaysBetweenDisbursalAndFirstRepayment }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Settings</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="47%">Amortization:</span>
<span fxFlex="53%">{{ loanProduct.amortizationType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Is Equal Amortization:</span>
<span fxFlex="53%">{{ loanProduct.isEqualAmortization | yesNo }}</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Interest Method:</span>
<span fxFlex="53%">{{ loanProduct.interestType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Interest Calculation Period:</span>
<span fxFlex="53%">{{ loanProduct.interestCalculationPeriodType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Allow Partial Interest Calculation with same as repayment:</span>
<span fxFlex="53%">{{ loanProduct.allowPartialPeriodInterestCalculation | yesNo }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Loan Schedule</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="47%">Repayment Strategy:</span>
<span fxFlex="53%" class="repayment-strategy">{{ loanProduct.transactionProcessingStrategyName }}</span>
</div>
<div fxFlexFill *ngIf="isAdvancedPaymentAllocationStrategy()">
<span fxFlex="47%">Advanced Payment Allocation Transactions:</span>
<span fxFlex="53%">
<mat-accordion>
<mifosx-view-advance-paymeny-allocation *ngFor="let paymentAllocation of paymentAllocations"
[paymentAllocation]="paymentAllocation"
[advancePaymentAllocationData]="advancePaymentAllocationData">
</mifosx-view-advance-paymeny-allocation>
</mat-accordion>
</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Loan Schedule Type:</span>
<span fxFlex="53%">{{ loanProduct.loanScheduleType.value }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.loanScheduleProcessingType">
<span fxFlex="47%">Loan Schedule Processing Type:</span>
<span fxFlex="53%">{{ loanProduct.loanScheduleProcessingType.value }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Down Payments</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="47%">Enable Down Payments:</span>
<span fxFlex="53%">{{ loanProduct.enableDownPayment | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.enableDownPayment" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="47%">Disbursed Amount Percentage Down Payment (%):</span>
<span fxFlex="53%">{{ loanProduct.disbursedAmountPercentageForDownPayment }} %</span>
</div>
<div fxFlexFill *ngIf="loanProduct.enableDownPayment" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="47%">Enable Auto Repayment for Down Payment:</span>
<span fxFlex="53%">{{ loanProduct.enableAutoRepaymentForDownPayment | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.enableDownPayment" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="47%">Do not extend loan schedule for multi disbursal:</span>
<span fxFlex="53%">{{ loanProduct.disableScheduleExtensionForDownPayment | yesNo }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Moratorium</h3>
<div fxFlexFill *ngIf="loanProduct.delinquencyBucket">
<span fxFlex="47%">Delinquency Bucket:</span>
<span fxFlex="53%">{{ loanProduct.delinquencyBucket.name }}</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Enable installment level Delinquency:</span>
<span fxFlex="53%">{{ loanProduct.enableInstallmentLevelDelinquency | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.graceOnPrincipalPayment">
<span fxFlex="47%">Grace on principal payment:</span>
<span fxFlex="53%">{{ loanProduct.graceOnPrincipalPayment }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.graceOnInterestPayment">
<span fxFlex="47%">Grace on interest payment:</span>
<span fxFlex="53%">{{ loanProduct.graceOnInterestPayment }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.graceOnInterestCharged">
<span fxFlex="47%">Interest free period:</span>
<span fxFlex="53%">{{ loanProduct.graceOnInterestCharged }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.inArrearsTolerance">
<span fxFlex="47%">Arrears tolerance:</span>
<span fxFlex="53%">{{ loanProduct.inArrearsTolerance }}</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Days in year:</span>
<span fxFlex="53%">{{ loanProduct.daysInYearType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Days in month:</span>
<span fxFlex="53%">{{ loanProduct.daysInMonthType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Allow fixing of the installment amount:</span>
<span fxFlex="53%">{{ loanProduct.canDefineInstallmentAmount | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.graceOnArrearsAgeing">
<span fxFlex="47%">Number of days a loan may be overdue before moving into arrears:</span>
<span fxFlex="53%">{{ loanProduct.graceOnArrearsAgeing }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.overdueDaysForNPA">
<span fxFlex="47%">Maximum number of days a loan may be overdue before becoming a NPA (non performing asset):</span>
<span fxFlex="53%">{{ loanProduct.overdueDaysForNPA }}</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Account moves out of NPA only after all arrears have been cleared:</span>
<span fxFlex="53%">{{ loanProduct.accountMovesOutOfNPAOnlyOnArrearsCompletion | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.principalThresholdForLastInstallment">
<span fxFlex="47%">Principal Threshold (%) for Last Instalment:</span>
<span fxFlex="53%">{{ loanProduct.principalThresholdForLastInstallment }}</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Variable Installments allowed:</span>
<span fxFlex="53%">{{ loanProduct.allowVariableInstallments | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.allowVariableInstallments">
<span fxFlex="47%">Variable Installments:</span>
<span fxFlex="53%">{{ '(Min: ' + loanProduct.minimumGap + ', Max: ' + (loanProduct.maximumGap ?
loanProduct.maximumGap : loanProduct.minimumGap) + ')' }}</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Allowed to be used for providing Topup Loans:</span>
<span fxFlex="53%">{{ loanProduct.canUseForTopup | yesNo }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Interest Recalculation</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="47%">Recalculate Interest:</span>
<span fxFlex="53%">{{ loanProduct.isInterestRecalculationEnabled | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.isInterestRecalculationEnabled" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="47%">Pre-closure interest calculation rule:</span>
<span fxFlex="53%">{{ loanProduct.interestRecalculationData.preClosureInterestCalculationStrategy.value }}</span>
<span fxFlex="47%">Advance payments adjustment type:</span>
<span fxFlex="53%">{{ loanProduct.interestRecalculationData.rescheduleStrategyType.value }}</span>
<span fxFlex="47%">Interest recalculation compounding on:</span>
<span fxFlex="53%">{{ loanProduct.interestRecalculationData.interestRecalculationCompoundingType.value }}</span>
<div fxFlexFill *ngIf="loanProduct.interestRecalculationData.interestRecalculationCompoundingType.id !== 0"
fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="47%">Frequency for compounding:</span>
<span fxFlex="53%">
{{ loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.value }}
<span
*ngIf="loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.id === 4 && loanProduct.interestRecalculationData.recalculationCompoundingFrequencyNthDay">&nbsp;&nbsp;{{
'on ' + loanProduct.interestRecalculationData.recalculationCompoundingFrequencyNthDay?.value }}</span>
<span
*ngIf="(loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.id === 4 && !loanProduct.interestRecalculationData.recalculationCompoundingFrequencyOnDay) || loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.id === 3">&nbsp;&nbsp;{{
loanProduct.interestRecalculationData.recalculationCompoundingFrequencyWeekday?.value }}</span>
<span
*ngIf="loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.id === 4 && loanProduct.interestRecalculationData.recalculationCompoundingFrequencyOnDay">&nbsp;&nbsp;{{
'on day ' + loanProduct.interestRecalculationData.recalculationCompoundingFrequencyOnDay }}</span>
</span>
<div fxFlexFill *ngIf="loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.id !== 1"
fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="47%">Frequency Interval for compounding:</span>
<span fxFlex="53%">{{ loanProduct.interestRecalculationData.recalculationCompoundingFrequencyInterval }}</span>
</div>
</div>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="47%">Frequency for recalculate Outstanding Principal:</span>
<span fxFlex="53%">
{{ loanProduct.interestRecalculationData.recalculationRestFrequencyType.value }}
<span
*ngIf="loanProduct.interestRecalculationData.recalculationRestFrequencyType.id === 4 && loanProduct.interestRecalculationData.recalculationRestFrequencyNthDay">&nbsp;&nbsp;{{
'on ' + loanProduct.interestRecalculationData.recalculationRestFrequencyNthDay?.value }}</span>
<span
*ngIf="(loanProduct.interestRecalculationData.recalculationRestFrequencyType.id === 4 && !loanProduct.interestRecalculationData.recalculationRestFrequencyOnDay) || loanProduct.interestRecalculationData.recalculationRestFrequencyType.id === 3">&nbsp;&nbsp;{{
loanProduct.interestRecalculationData.recalculationRestFrequencyWeekday?.value }}</span>
<span
*ngIf="loanProduct.interestRecalculationData.recalculationRestFrequencyType.id === 4 && loanProduct.interestRecalculationData.recalculationRestFrequencyOnDay">&nbsp;&nbsp;{{
'on day ' + loanProduct.interestRecalculationData.recalculationRestFrequencyOnDay }}</span>
</span>
</div>
<div fxFlexFill *ngIf="loanProduct.interestRecalculationData.recalculationRestFrequencyType.id !== 1"
fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="47%">Frequency Interval for recalculation:</span>
<span fxFlex="53%">{{ loanProduct.interestRecalculationData.recalculationRestFrequencyInterval }}</span>
<div fxFlexFill *ngIf="loanProduct.recalculationRestFrequencyDate">
<span fxFlex="47%">Rest Frequency Date:</span>
<span fxFlex="53%">{{ loanProduct.interestRecalculationData.recalculationRestFrequencyDate }}</span>
</div>
</div>
<div fxFlexFill>
<span fxFlex="47%">Is Arrears recognization based on original schedule:</span>
<span fxFlex="53%">{{ loanProduct.isArrearsBasedOnOriginalSchedule | yesNo }}</span>
</div>
</div>
<h3 class="mat-h3" fxFlexFill>Guarantee Requirements</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="47%">Place Guarantee Funds On-Hold:</span>
<span fxFlex="53%">{{ loanProduct.holdGuaranteeFunds | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.holdGuaranteeFunds" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="47%">Mandatory Guarantee(%):</span>
<span fxFlex="53%">{{ loanProduct.productGuaranteeData.mandatoryGuarantee }}</span>
<div fxFlexFill *ngIf="loanProduct.productGuaranteeData.minimumGuaranteeFromOwnFunds">
<span fxFlex="47%">Minimum Guarantee from Own Funds(%):</span>
<span fxFlex="53%">{{ loanProduct.productGuaranteeData.minimumGuaranteeFromOwnFunds }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.productGuaranteeData.minimumGuaranteeFromGuarantor">
<span fxFlex="47%">Minimum Guarantee from Guarantor Funds(%):</span>
<span fxFlex="53%">{{ loanProduct.productGuaranteeData.minimumGuaranteeFromGuarantor }}</span>
</div>
</div>
<h3 class="mat-h3" fxFlexFill>Loan Tranche Details</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="47%">Enable Multiple Disbursals:</span>
<span fxFlex="53%">{{ loanProduct.multiDisburseLoan | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.multiDisburseLoan" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="47%">Maximum Tranche count:</span>
<span fxFlex="53%">{{ loanProduct.maxTrancheCount }}</span>
<div fxFlexFill *ngIf="loanProduct.outstandingLoanBalance">
<span fxFlex="47%">Maximum allowed outstanding balance:</span>
<span fxFlex="53%">{{ loanProduct.outstandingLoanBalance }}</span>
</div>
<div fxFlexFill>
<span fxFlex="47%">Disallow Expected Disbursements:</span>
<span fxFlex="53%">{{ loanProduct.disallowExpectedDisbursements | yesNo }}</span>
</div>
</div>
<h3 class="mat-h3" fxFlexFill>Event Settings</h3>
<div fxFlexFill>
<span fxFlex="47%">Use the Global Configurations values to the Repayment Event (notifications):</span>
<span fxFlex="53%">{{ useDueForRepaymentsConfigurations | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.dueDaysForRepaymentEvent">
<span fxFlex="47%">Due days for repayment event:</span>
<span fxFlex="53%">{{ loanProduct.dueDaysForRepaymentEvent | number }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.overDueDaysForRepaymentEvent">
<span fxFlex="47%">OverDue days for repayment event:</span>
<span fxFlex="53%">{{ loanProduct.overDueDaysForRepaymentEvent | number }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Configurable Terms and Settings</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="47%">Allow overriding select terms and settings in loan accounts:</span>
<span fxFlex="53%">{{ loanProduct.allowAttributeConfiguration | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.allowAttributeConfiguration" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="47%">Amortization:</span>
<span fxFlex="53%">{{ loanProduct.allowAttributeOverrides.amortizationType | yesNo }}</span>
<span fxFlex="47%">Interest method:</span>
<span fxFlex="53%">{{ loanProduct.allowAttributeOverrides.interestType | yesNo }}</span>
<span fxFlex="47%">Repayment strategy:</span>
<span fxFlex="53%">{{ loanProduct.allowAttributeOverrides.transactionProcessingStrategyCode | yesNo }}</span>
<span fxFlex="47%">Interest calculation period:</span>
<span fxFlex="53%">{{ loanProduct.allowAttributeOverrides.interestCalculationPeriodType | yesNo }}</span>
<span fxFlex="47%">Arrears tolerance:</span>
<span fxFlex="53%">{{ loanProduct.allowAttributeOverrides.inArrearsTolerance | yesNo }}</span>
<span fxFlex="47%">Repaid every:</span>
<span fxFlex="53%">{{ loanProduct.allowAttributeOverrides.repaymentEvery | yesNo }}</span>
<span fxFlex="47%">Moratorium:</span>
<span fxFlex="53%">{{ loanProduct.allowAttributeOverrides.graceOnPrincipalAndInterestPayment | yesNo }}</span>
<span fxFlex="47%">Number of days a loan may be overdue before moving into arrears:</span>
<span fxFlex="53%">{{ loanProduct.allowAttributeOverrides.graceOnArrearsAgeing | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.charges.length" fxLayout="row wrap" fxLayout.lt-md="column">
<h3 class="mat-h3" fxFlexFill>Charges</h3>
<mat-divider [inset]="true"></mat-divider>
<table fxFlexFill class="mat-elevation-z1" mat-table
[dataSource]="loanProduct.charges | chargesPenaltyFilter:false">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let charge">
{{ charge.name + ', ' + charge.currency.displaySymbol }}
</td>
</ng-container>
<ng-container matColumnDef="chargeCalculationType">
<th mat-header-cell *matHeaderCellDef> Type </th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeCalculationType.value }}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef> Amount </th>
<td mat-cell *matCellDef="let charge">
{{ charge.amount }}
</td>
</ng-container>
<ng-container matColumnDef="chargeTimeType">
<th mat-header-cell *matHeaderCellDef> Collected On </th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeTimeType.value }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chargesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chargesDisplayedColumns;"></tr>
</table>
<h3 class="mat-h3" fxFlexFill>Overdue Charges</h3>
<mat-divider [inset]="true"></mat-divider>
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="loanProduct.charges | chargesPenaltyFilter:true">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let overdueCharge">
{{ overdueCharge.name + ', ' + overdueCharge.currency.displaySymbol }}
</td>
</ng-container>
<ng-container matColumnDef="chargeCalculationType">
<th mat-header-cell *matHeaderCellDef> Type </th>
<td mat-cell *matCellDef="let overdueCharge">
{{ overdueCharge.chargeCalculationType.value }}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef> Amount </th>
<td mat-cell *matCellDef="let overdueCharge">
{{ overdueCharge.amount }}
</td>
</ng-container>
<ng-container matColumnDef="chargeTimeType">
<th mat-header-cell *matHeaderCellDef> Collected On </th>
<td mat-cell *matCellDef="let overdueCharge">
{{ overdueCharge.chargeTimeType.value }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chargesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chargesDisplayedColumns;"></tr>
</table>
</div>
<h3 class="mat-h3" fxFlexFill>Accounting</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="47%">Type:</span>
<span fxFlex="53%">{{ accountingRuleData[accountingRule() - 1] }}</span>
</div>
<div fxFlexFill *ngIf="isAccountingEnabled()" fxLayout="row wrap"
fxLayout.lt-md="column">
<h4 fxFlexFill class="mat-h4">Assets / Liabilities</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="47%">Fund source:</span>
<span fxFlex="53%">({{accountingMappings.fundSourceAccount.glCode}}) {{
accountingMappings.fundSourceAccount.name }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Assets</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="47%">Loan portfolio:</span>
<span fxFlex="53%">({{accountingMappings.loanPortfolioAccount.glCode}}) {{
accountingMappings.loanPortfolioAccount.name }}</span>
<div fxFlexFill *ngIf="loanProduct.accountingRule.id === 3 || loanProduct.accountingRule.id === 4"
fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="47%">Interest Receivable:</span>
<span fxFlex="53%">({{accountingMappings.receivableInterestAccount.glCode}}) {{
accountingMappings.receivableInterestAccount.name }}</span>
<span fxFlex="47%">Fees Receivable:</span>
<span fxFlex="53%">({{accountingMappings.receivableFeeAccount.glCode}}) {{
accountingMappings.receivableInterestAccount.name }}</span>
<span fxFlex="47%">Penalties Receivable:</span>
<span fxFlex="53%">({{accountingMappings.receivablePenaltyAccount.glCode}}) {{
accountingMappings.receivablePenaltyAccount.name }}</span>
</div>
<span fxFlex="47%">Transfer in suspense:</span>
<span fxFlex="53%">({{accountingMappings.transfersInSuspenseAccount.glCode}}) {{
accountingMappings.transfersInSuspenseAccount.name }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Income</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="47%">Income from Interest:</span>
<span fxFlex="53%">({{accountingMappings.interestOnLoanAccount.glCode}}) {{
accountingMappings.interestOnLoanAccount.name }}</span>
<span fxFlex="47%">Income from fees:</span>
<span fxFlex="53%">({{accountingMappings.incomeFromFeeAccount.glCode}}) {{
accountingMappings.incomeFromFeeAccount.name }}</span>
<span fxFlex="47%">Income from penalties:</span>
<span fxFlex="53%">({{accountingMappings.incomeFromPenaltyAccount.glCode}}) {{
accountingMappings.incomeFromPenaltyAccount.name }}</span>
<span fxFlex="47%">Income from Recovery Repayments:</span>
<span fxFlex="53%">({{accountingMappings.incomeFromRecoveryAccount.glCode}}) {{
accountingMappings.incomeFromRecoveryAccount.name }}</span>
<span *ngIf="accountingMappings.incomeFromChargeOffInterestAccount" fxFlex="47%">Income from ChargeOff
Interest:</span>
<span *ngIf="accountingMappings.incomeFromChargeOffInterestAccount" fxFlex="53%">
({{accountingMappings.incomeFromChargeOffInterestAccount.glCode}}) {{
accountingMappings.incomeFromChargeOffInterestAccount.name }}</span>
<span fxFlex="47%" *ngIf="accountingMappings.incomeFromChargeOffFeesAccount">Income from ChargeOff
Fees:</span>
<span fxFlex="53%" *ngIf="accountingMappings.incomeFromChargeOffFeesAccount">
({{accountingMappings.incomeFromChargeOffFeesAccount.glCode}}) {{
accountingMappings.incomeFromChargeOffFeesAccount.name }}</span>
<span fxFlex="47%" *ngIf="accountingMappings.incomeFromChargeOffPenaltyAccount">Income from ChargeOff
Penalty:</span>
<span fxFlex="53%" *ngIf="accountingMappings.incomeFromChargeOffPenaltyAccount">
({{accountingMappings.incomeFromChargeOffPenaltyAccount.glCode}}) {{
accountingMappings.incomeFromChargeOffPenaltyAccount.name }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Expenses</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="47%">Losses written off:</span>
<span fxFlex="53%">({{accountingMappings.writeOffAccount.glCode}}) {{
accountingMappings.writeOffAccount.name }}</span>
<span fxFlex="47%">Expenses from Goodwill Credit:</span>
<span fxFlex="53%">({{accountingMappings.goodwillCreditAccount.glCode}}) {{
accountingMappings.goodwillCreditAccount.name }}</span>
<span *ngIf="accountingMappings.chargeOffExpenseAccount" fxFlex="47%">ChargeOff Expense:</span>
<span *ngIf="accountingMappings.chargeOffExpenseAccount" fxFlex="53%">
({{accountingMappings.chargeOffExpenseAccount.glCode}}) {{
accountingMappings.chargeOffExpenseAccount.name }}</span>
<span *ngIf="accountingMappings.chargeOffFraudExpenseAccount" fxFlex="47%">ChargeOff Fraud
Expense:</span>
<span *ngIf="accountingMappings.chargeOffFraudExpenseAccount" fxFlex="53%">
({{accountingMappings.chargeOffFraudExpenseAccount.glCode}}) {{
accountingMappings.chargeOffFraudExpenseAccount.name }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Liabilities</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="47%">Over payment liability:</span>
<span fxFlex="53%">({{accountingMappings.overpaymentLiabilityAccount.glCode}}) {{
accountingMappings.overpaymentLiabilityAccount.name }}</span>
</div>
<div
*ngIf="isAdvancedAccountingEnabled()"
fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<h3 class="mat-h3" fxFlexFill>Advanced Accounting Rules</h3>
<mat-divider [inset]="true"></mat-divider>
<div *ngIf="paymentChannelToFundSourceMappings.length" fxFlexFill fxLayout="row wrap"
fxLayout.lt-md="column">
<h4 class="mat-h4" fxFlexFill>Fund Sources for Payment Channels</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table
[dataSource]="paymentChannelToFundSourceMappings">
<ng-container matColumnDef="paymentTypeId">
<th mat-header-cell *matHeaderCellDef> Payment Type </th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.paymentType.name }}
</td>
</ng-container>
<ng-container matColumnDef="fundSourceAccountId">
<th mat-header-cell *matHeaderCellDef> Fund Source </th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.fundSourceAccount.name }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="paymentFundSourceDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: paymentFundSourceDisplayedColumns;"></tr>
</table>
</div>
<div *ngIf="feeToIncomeAccountMappings.length" fxFlexFill fxLayout="row wrap"
fxLayout.lt-md="column">
<h4 class="mat-h4" fxFlexFill>Fees to Specific Income Accounts</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="feeToIncomeAccountMappings">
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef> Fees </th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef> Income Account </th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.incomeAccount.name }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns;"></tr>
</table>
</div>
<div *ngIf="penaltyToIncomeAccountMappings.length" fxFlexFill fxLayout="row wrap"
fxLayout.lt-md="column">
<h4 class="mat-h4" fxFlexFill>Penalties to Specific Income Accounts</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="penaltyToIncomeAccountMappings">
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef> Penalty </th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef> Income Account </th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.incomeAccount.name }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns;"></tr>
</table>
</div>
</div>
</div>
</div>
@@ -0,0 +1,47 @@
@import "assets/styles/colours";
.tab-container {
padding: 1%;
margin: 1%;
div: {
margin-top: 3px;
}
}
table {
width: 100%;
}
.mat-elevation-z1 {
margin: 1em 0 1.5em 0;
}
h2, h3, h4 {
margin: 0;
font-weight: 500;
}
span {
margin: 0.5em 0;
}
mat-divider {
margin: 0 0 0.5em 0;
}
.mat-h3 {
margin-top: 10px !important;
font-weight: 300;
color: $status-approved;
}
.mat-h4 {
margin-top: 10px !important;
font-weight: 200;
color: $status-approved;
}
.repayment-strategy {
color: $status-approved;
}
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LoanProductSummaryComponent } from './loan-product-summary.component';
describe('LoanProductSummaryComponent', () => {
let component: LoanProductSummaryComponent;
let fixture: ComponentFixture<LoanProductSummaryComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ LoanProductSummaryComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(LoanProductSummaryComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,218 @@
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { LoanProduct } from '../../models/loan-product.model';
import { AccountingMapping, Charge, ChargeToIncomeAccountMapping, GLAccount, PaymentChannelToFundSourceMapping, PaymentType, PaymentTypeOption } from '../../../../shared/models/general.model';
import { AdvancePaymentAllocationData, PaymentAllocation } from '../../loan-product-stepper/loan-product-payment-strategy-step/payment-allocation-model';
import { LoanProducts } from '../../loan-products';
import { OptionData } from '../../../../shared/models/option-data.model';
@Component({
selector: 'mifosx-loan-product-summary',
templateUrl: './loan-product-summary.component.html',
styleUrls: ['./loan-product-summary.component.scss']
})
export class LoanProductSummaryComponent implements OnInit, OnChanges {
@Input() loanProduct: LoanProduct;
@Input() loanProductsTemplate: any | null;
@Input() useDueForRepaymentsConfigurations: boolean;
@Input() paymentAllocations: PaymentAllocation | null;
variationsDisplayedColumns: string[] = ['valueConditionType', 'borrowerCycleNumber', 'minValue', 'defaultValue', 'maxValue'];
chargesDisplayedColumns: string[] = ['name', 'chargeCalculationType', 'amount', 'chargeTimeType'];
paymentFundSourceDisplayedColumns: string[] = ['paymentTypeId', 'fundSourceAccountId'];
feesPenaltyIncomeDisplayedColumns: string[] = ['chargeId', 'incomeAccountId'];
accountingRuleData = ['None', 'Cash', 'Accrual (periodic)', 'Accrual (upfront)'];
isAdvancedPaymentAllocation = false;
advancePaymentAllocationData: AdvancePaymentAllocationData;
accountingMappings: any = {};
paymentChannelToFundSourceMappings: PaymentChannelToFundSourceMapping[] = [];
feeToIncomeAccountMappings: ChargeToIncomeAccountMapping[] = [];
penaltyToIncomeAccountMappings: ChargeToIncomeAccountMapping[] = [];
constructor() { }
ngOnInit() {
this.setCurrentValues();
}
ngOnChanges(changes: SimpleChanges): void {
this.setCurrentValues();
}
setCurrentValues(): void {
if (this.loanProduct.accountingMappings) {
this.accountingMappings = this.loanProduct.accountingMappings;
this.paymentChannelToFundSourceMappings = this.loanProduct.paymentChannelToFundSourceMappings || [];
this.feeToIncomeAccountMappings = this.loanProduct.feeToIncomeAccountMappings || [];
this.penaltyToIncomeAccountMappings = this.loanProduct.penaltyToIncomeAccountMappings || [];
} else {
const assetAccountData = this.loanProductsTemplate.accountingMappingOptions.assetAccountOptions || [];
const incomeAccountData = this.loanProductsTemplate.accountingMappingOptions.incomeAccountOptions || [];
const expenseAccountData = this.loanProductsTemplate.accountingMappingOptions.expenseAccountOptions || [];
const liabilityAccountData = this.loanProductsTemplate.accountingMappingOptions.liabilityAccountOptions || [];
const assetAndLiabilityAccountData = this.loanProductsTemplate.accountingMappingOptions.assetAndLiabilityAccountOptions || [];
this.accountingMappings = {
'fundSourceAccount': this.glAccountLookUp(this.loanProduct.fundSourceAccountId, assetAndLiabilityAccountData),
'loanPortfolioAccount': this.glAccountLookUp(this.loanProduct.loanPortfolioAccountId, assetAccountData),
'receivableInterestAccount': this.glAccountLookUp(this.loanProduct.receivableInterestAccountId, assetAccountData),
'receivableFeeAccount': this.glAccountLookUp(this.loanProduct.receivableFeeAccountId, assetAccountData),
'receivablePenaltyAccount': this.glAccountLookUp(this.loanProduct.receivablePenaltyAccountId, assetAccountData),
'transfersInSuspenseAccount': this.glAccountLookUp(this.loanProduct.transfersInSuspenseAccountId, assetAccountData),
'interestOnLoanAccount': this.glAccountLookUp(this.loanProduct.interestOnLoanAccountId, incomeAccountData),
'incomeFromFeeAccount': this.glAccountLookUp(this.loanProduct.incomeFromFeeAccountId, incomeAccountData),
'incomeFromPenaltyAccount': this.glAccountLookUp(this.loanProduct.incomeFromPenaltyAccountId, incomeAccountData),
'incomeFromRecoveryAccount': this.glAccountLookUp(this.loanProduct.incomeFromRecoveryAccountId, incomeAccountData),
'incomeFromChargeOffInterestAccount': this.glAccountLookUp(this.loanProduct.incomeFromChargeOffInterestAccountId, incomeAccountData),
'incomeFromChargeOffFeesAccount': this.glAccountLookUp(this.loanProduct.incomeFromChargeOffFeesAccountId, incomeAccountData),
'incomeFromChargeOffPenaltyAccount': this.glAccountLookUp(this.loanProduct.incomeFromChargeOffPenaltyAccountId, incomeAccountData),
'writeOffAccount': this.glAccountLookUp(this.loanProduct.writeOffAccountId, expenseAccountData),
'goodwillCreditAccount': this.glAccountLookUp(this.loanProduct.goodwillCreditAccountId, expenseAccountData),
'chargeOffExpenseAccount': this.glAccountLookUp(this.loanProduct.writeOffAccountId, expenseAccountData),
'chargeOffFraudExpenseAccount': this.glAccountLookUp(this.loanProduct.writeOffAccountId, expenseAccountData),
'overpaymentLiabilityAccount': this.glAccountLookUp(this.loanProduct.overpaymentLiabilityAccountId, liabilityAccountData),
};
const paymentTypesData = this.loanProductsTemplate.paymentTypeOptions || [];
this.loanProduct.paymentChannelToFundSourceMappings.forEach((m: any) => {
this.paymentChannelToFundSourceMappings.push({
fundSourceAccount: this.glAccountLookUp(m.fundSourceAccountId, assetAndLiabilityAccountData),
paymentType: this.paymentTypeLookUp(m.paymentTypeId, paymentTypesData)
});
});
this.feeToIncomeAccountMappings = [];
this.loanProduct.feeToIncomeAccountMappings.forEach((m: any) => {
this.feeToIncomeAccountMappings.push({
incomeAccount: this.glAccountLookUp(m.incomeAccountId, incomeAccountData),
charge: this.chargeLookUp(m.chargeId, this.loanProductsTemplate.chargeOptions)
});
});
this.penaltyToIncomeAccountMappings = [];
this.loanProduct.penaltyToIncomeAccountMappings.forEach((m: any) => {
this.penaltyToIncomeAccountMappings.push({
incomeAccount: this.glAccountLookUp(m.incomeAccountId, incomeAccountData),
charge: this.chargeLookUp(m.chargeId, this.loanProductsTemplate.penaltyOptions)
});
});
if (this.loanProduct.isInterestRecalculationEnabled) {
this.loanProduct.interestRecalculationData = {
interestRecalculationCompoundingType: this.optionDataLookUp(this.loanProduct.interestRecalculationCompoundingMethod,
this.loanProductsTemplate.interestRecalculationCompoundingTypeOptions),
rescheduleStrategyType: this.optionDataLookUp(this.loanProduct.rescheduleStrategyMethod,
this.loanProductsTemplate.rescheduleStrategyTypeOptions),
recalculationCompoundingFrequencyType: this.optionDataLookUp(this.loanProduct.recalculationCompoundingFrequencyType,
this.loanProductsTemplate.interestRecalculationFrequencyTypeOptions),
recalculationRestFrequencyType: this.optionDataLookUp(this.loanProduct.recalculationRestFrequencyType,
this.loanProductsTemplate.interestRecalculationFrequencyTypeOptions),
preClosureInterestCalculationStrategy: this.optionDataLookUp(this.loanProduct.preClosureInterestCalculationStrategy,
this.loanProductsTemplate.preClosureInterestCalculationStrategyOptions),
allowCompoundingOnEod: this.loanProduct.allowCompoundingOnEod,
isArrearsBasedOnOriginalSchedule: this.loanProduct.isArrearsBasedOnOriginalSchedule,
isCompoundingToBePostedAsTransaction: this.loanProduct.isCompoundingToBePostedAsTransaction,
recalculationRestFrequencyInterval: this.loanProduct.recalculationRestFrequencyInterval
};
}
}
this.isAdvancedPaymentAllocation = LoanProducts.isAdvancedPaymentAllocationStrategy(this.loanProduct.transactionProcessingStrategyCode);
if (this.loanProduct.advancedPaymentAllocationTransactionTypes) {
this.advancePaymentAllocationData = {
transactionTypes: this.loanProduct.advancedPaymentAllocationTransactionTypes,
allocationTypes: this.loanProduct.advancedPaymentAllocationTypes,
futureInstallmentAllocationRules: this.loanProduct.advancedPaymentAllocationFutureInstallmentAllocationRules
};
} else {
this.advancePaymentAllocationData = {
transactionTypes: this.loanProductsTemplate.advancedPaymentAllocationTransactionTypes,
allocationTypes: this.loanProductsTemplate.advancedPaymentAllocationTypes,
futureInstallmentAllocationRules: this.loanProductsTemplate.advancedPaymentAllocationFutureInstallmentAllocationRules
};
}
}
optionDataLookUp(itemId: number, optionsData: any[]): OptionData {
let optionData: OptionData | null;
optionsData.some((o: any) => {
if (o.id === itemId) {
optionData = {
id: o.id,
code: o.code,
value: o.value
};
}
});
return optionData;
}
glAccountLookUp(glAccountId: number, glAccounts: GLAccount[]): AccountingMapping {
let accountMapping: AccountingMapping | null = null;
if (glAccountId) {
glAccounts.some((glAccount: GLAccount) => {
if (glAccount.id === glAccountId) {
accountMapping = {id: glAccount.id, name: glAccount.name, glCode: glAccount.glCode};
}
});
}
return accountMapping;
}
chargeLookUp(chargeId: number, charges: Charge[]): Charge {
let chargeData: Charge | null = null;
if (chargeId) {
charges.some((charge: Charge) => {
if (charge.id === chargeId) {
chargeData = {id: charge.id, name: charge.name, penalty: charge.penalty};
}
});
}
return chargeData;
}
paymentTypeLookUp(paymentTypeId: number, paymentTypes: PaymentTypeOption[]): PaymentType {
let paymentType: PaymentType | null = null;
if (paymentTypeId) {
paymentTypes.some((payment: any) => {
if (payment.id === paymentTypeId) {
paymentType = {
id: payment.id,
name: payment.name,
isSystemDefined: false
};
}
});
}
return paymentType;
}
accountingRule(): number {
return this.loanProduct.accountingRule.id ?
this.loanProduct.accountingRule.id : this.loanProduct.accountingRule;
}
isAccountingEnabled(): boolean {
return (this.accountingRule() >= 2);
}
isAdvancedAccountingEnabled(): boolean {
return (this.loanProduct.paymentChannelToFundSourceMappings?.length > 0
|| this.loanProduct.feeToIncomeAccountMappings?.length > 0
|| this.loanProduct.penaltyToIncomeAccountMappings?.length > 0);
}
isAdvancedPaymentAllocationStrategy(): boolean {
return LoanProducts.isAdvancedPaymentAllocationStrategy(this.loanProduct.transactionProcessingStrategyCode);
}
}
@@ -79,7 +79,7 @@ export class CreateLoanProductComponent implements OnInit {
}
advancePaymentStrategy(value: string) {
this.isAdvancedPaymentStrategy = (value === 'advanced-payment-allocation-strategy');
this.isAdvancedPaymentStrategy = LoanProducts.isAdvancedPaymentAllocationStrategy(value);
}
buildAdvancedPaymentAllocation(): void {
@@ -65,6 +65,10 @@ export class EditLoanProductComponent implements OnInit {
ngOnInit() {
this.buildAdvancedPaymentAllocation();
this.advancePaymentStrategy(this.loanProductAndTemplate.transactionProcessingStrategyCode);
if (this.isAdvancedPaymentStrategy) {
this.paymentAllocation = this.loanProductAndTemplate.paymentAllocation;
}
}
get loanProductDetailsForm() {
@@ -84,7 +88,7 @@ export class EditLoanProductComponent implements OnInit {
}
advancePaymentStrategy(value: string): void {
this.isAdvancedPaymentStrategy = (value === 'advanced-payment-allocation-strategy');
this.isAdvancedPaymentStrategy = LoanProducts.isAdvancedPaymentAllocationStrategy(value);
}
buildAdvancedPaymentAllocation(): void {
@@ -1,905 +1,11 @@
<div fxLayout="row wrap" fxLayout.lt-md="column">
<h2 class="mat-h2" fxFlexFill>{{ loanProduct.name }}</h2>
<mat-divider fxFlexFill></mat-divider>
<h3 class="mat-h3" fxFlexFill>Details</h3>
<mat-divider fxFlexFill></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Short Name:</span>
<span fxFlex="60%">{{ loanProduct.shortName }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.fundId">
<span fxFlex="40%">Fund Name:</span>
<span fxFlex="60%">{{ loanProduct.fundId | find:loanProductsTemplate.fundOptions:'id':'name' }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Include in Customer Loan Counter:</span>
<span fxFlex="60%">{{ loanProduct.includeInBorrowerCycle | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.startDate">
<span fxFlex="40%">Start Date:</span>
<span fxFlex="60%">{{ loanProduct.startDate }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.closeDate">
<span fxFlex="40%">Close Date:</span>
<span fxFlex="60%">{{ loanProduct.closeDate }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.description">
<span fxFlex="40%">Description:</span>
<span fxFlex="60%">{{ loanProduct.description }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Currency</h3>
<mat-divider fxFlexFill></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Currency:</span>
<span fxFlex="60%">{{ loanProduct.currencyCode | find:loanProductsTemplate.currencyOptions:'code':'name' }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Decimal Places:</span>
<span fxFlex="60%">{{ loanProduct.digitsAfterDecimal }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Currency in multiples of:</span>
<span fxFlex="60%">{{ loanProduct.inMultiplesOf }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Installment in multiples of:</span>
<span fxFlex="60%">{{ loanProduct.installmentAmountInMultiplesOf }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Terms</h3>
<mat-divider fxFlexFill></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Principal:</span>
<span fxFlex="60%">{{ loanProduct.principal + ' (Min: ' + (loanProduct.minPrincipal ? loanProduct.minPrincipal :
loanProduct.principal) + ', Max: ' + (loanProduct.maxPrincipal ? loanProduct.maxPrincipal : loanProduct.principal)
+ ')' }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Allow Approved / Disbursed Amounts Over Applied:</span>
<span fxFlex="60%">{{ loanProduct.allowApprovedDisbursedAmountsOverApplied | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.allowApprovedDisbursedAmountsOverApplied">
<span fxFlex="40%">Over Applied:</span>
<span fxFlex="60%" *ngIf="loanProduct.overAppliedCalculationType === 'percentage'">{{ loanProduct.overAppliedNumber
}} %</span>
<span fxFlex="60%" *ngIf="loanProduct.overAppliedCalculationType === 'flat'">{{ loanProduct.overAppliedNumber }} {{
loanProduct.currencyCode }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Installment day calculation from:</span>
<span fxFlex="60%">{{ loanProduct.repaymentStartDateType }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Number of Repayments:</span>
<span fxFlex="60%">{{ loanProduct.numberOfRepayments + ' (Min: ' + (loanProduct.minNumberOfRepayments ?
loanProduct.minNumberOfRepayments : loanProduct.numberOfRepayments) + ', Max: ' +
(loanProduct.maxNumberOfRepayments ? loanProduct.maxNumberOfRepayments : loanProduct.numberOfRepayments) + ')'
}}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Linked to floating interest rates:</span>
<span fxFlex="60%">{{ loanProduct.isLinkedToFloatingInterestRates | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="!loanProduct.isLinkedToFloatingInterestRates">
<span fxFlex="40%">Nominal interest rate:</span>
<span fxFlex="60%">{{ loanProduct.interestRatePerPeriod + ' (Min: ' + (loanProduct.minInterestRatePerPeriod ?
loanProduct.minInterestRatePerPeriod : loanProduct.interestRatePerPeriod) + ', Max: ' +
(loanProduct.maxInterestRatePerPeriod ? loanProduct.maxInterestRatePerPeriod : loanProduct.interestRatePerPeriod)
+ ')' + ' ' + (loanProduct.interestRateFrequencyType |
find:loanProductsTemplate.interestRateFrequencyTypeOptions:'id':'value') }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.isLinkedToFloatingInterestRates" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Floating Lending Interest Rate:</span>
<span fxFlex="60%">{{ loanProduct.floatingRatesId | find:loanProductsTemplate.floatingRateOptions:'id':'name'
}}</span>
<span fxFlex="40%">Interest Rate Differential:</span>
<span fxFlex="60%">{{ loanProduct.interestRateDifferential }}</span>
<span fxFlex="40%">Floating Interest Rate Calculation Allowed:</span>
<span fxFlex="60%">{{ loanProduct.isFloatingInterestRateCalculationAllowed | yesNo }}</span>
<span fxFlex="40%">Floating Interest Rate:</span>
<span fxFlex="60%">{{ loanProduct.defaultDifferentialLendingRate + ' (Min: ' +
(loanProduct.minDifferentialLendingRate ? loanProduct.minDifferentialLendingRate :
loanProduct.defaultDifferentialLendingRate) + ', Max: ' + (loanProduct.maxDifferentialLendingRate ?
loanProduct.maxDifferentialLendingRate : loanProduct.defaultDifferentialLendingRate) + ')' }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Terms vary based on loan cycle:</span>
<span fxFlex="60%">{{ loanProduct.useBorrowerCycle | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.principalVariationsForBorrowerCycle?.length">
<h4 class="mat-h4" fxFlexFill>Principal by loan cycle</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="loanProduct.principalVariationsForBorrowerCycle">
<ng-container matColumnDef="valueConditionType">
<th mat-header-cell *matHeaderCellDef> Condition </th>
<td mat-cell *matCellDef="let variation">
{{ variation.valueConditionType | find:loanProductsTemplate.valueConditionTypeOptions:'id':'value' }}
</td>
</ng-container>
<ng-container matColumnDef="borrowerCycleNumber">
<th mat-header-cell *matHeaderCellDef> Loan Cycle </th>
<td mat-cell *matCellDef="let variation">
{{ variation.borrowerCycleNumber }}
</td>
</ng-container>
<ng-container matColumnDef="minValue">
<th mat-header-cell *matHeaderCellDef> Minimum </th>
<td mat-cell *matCellDef="let variation">
{{ variation.minValue }}
</td>
</ng-container>
<ng-container matColumnDef="defaultValue">
<th mat-header-cell *matHeaderCellDef> Default </th>
<td mat-cell *matCellDef="let variation">
{{ variation.defaultValue }}
</td>
</ng-container>
<ng-container matColumnDef="maxValue">
<th mat-header-cell *matHeaderCellDef> Maximum </th>
<td mat-cell *matCellDef="let variation">
{{ variation.maxValue }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="variationsDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: variationsDisplayedColumns;"></tr>
</table>
</div>
<div fxFlexFill *ngIf="loanProduct.numberOfRepaymentVariationsForBorrowerCycle?.length">
<h4 class="mat-h4" fxFlexFill>Number of Repayments by loan cycle</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table
[dataSource]="loanProduct.numberOfRepaymentVariationsForBorrowerCycle">
<ng-container matColumnDef="valueConditionType">
<th mat-header-cell *matHeaderCellDef> Condition </th>
<td mat-cell *matCellDef="let variation">
{{ variation.valueConditionType | find:loanProductsTemplate.valueConditionTypeOptions:'id':'value' }}
</td>
</ng-container>
<ng-container matColumnDef="borrowerCycleNumber">
<th mat-header-cell *matHeaderCellDef> Loan Cycle </th>
<td mat-cell *matCellDef="let variation">
{{ variation.borrowerCycleNumber }}
</td>
</ng-container>
<ng-container matColumnDef="minValue">
<th mat-header-cell *matHeaderCellDef> Minimum </th>
<td mat-cell *matCellDef="let variation">
{{ variation.minValue }}
</td>
</ng-container>
<ng-container matColumnDef="defaultValue">
<th mat-header-cell *matHeaderCellDef> Default </th>
<td mat-cell *matCellDef="let variation">
{{ variation.defaultValue }}
</td>
</ng-container>
<ng-container matColumnDef="maxValue">
<th mat-header-cell *matHeaderCellDef> Maximum </th>
<td mat-cell *matCellDef="let variation">
{{ variation.maxValue }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="variationsDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: variationsDisplayedColumns;"></tr>
</table>
</div>
<div fxFlexFill *ngIf="loanProduct.interestRateVariationsForBorrowerCycle?.length">
<h4 class="mat-h4" fxFlexFill>Nominal Interest Rate by loan cycle</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table
[dataSource]="loanProduct.interestRateVariationsForBorrowerCycle">
<ng-container matColumnDef="valueConditionType">
<th mat-header-cell *matHeaderCellDef> Condition </th>
<td mat-cell *matCellDef="let variation">
{{ variation.valueConditionType | find:loanProductsTemplate.valueConditionTypeOptions:'id':'value' }}
</td>
</ng-container>
<ng-container matColumnDef="borrowerCycleNumber">
<th mat-header-cell *matHeaderCellDef> Loan Cycle </th>
<td mat-cell *matCellDef="let variation">
{{ variation.borrowerCycleNumber }}
</td>
</ng-container>
<ng-container matColumnDef="minValue">
<th mat-header-cell *matHeaderCellDef> Minimum </th>
<td mat-cell *matCellDef="let variation">
{{ variation.minValue }}
</td>
</ng-container>
<ng-container matColumnDef="defaultValue">
<th mat-header-cell *matHeaderCellDef> Default </th>
<td mat-cell *matCellDef="let variation">
{{ variation.defaultValue }}
</td>
</ng-container>
<ng-container matColumnDef="maxValue">
<th mat-header-cell *matHeaderCellDef> Maximum </th>
<td mat-cell *matCellDef="let variation">
{{ variation.maxValue }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="variationsDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: variationsDisplayedColumns;"></tr>
</table>
</div>
<div fxFlexFill>
<span fxFlex="40%">Repay Every:</span>
<span fxFlex="60%">{{ loanProduct.repaymentEvery + ' ' + (loanProduct.repaymentFrequencyType |
find:loanProductsTemplate.repaymentFrequencyTypeOptions:'id':'value') }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.minimumDaysBetweenDisbursalAndFirstRepayment">
<span fxFlex="40%">Minimum days between disbursal and first repayment date:</span>
<span fxFlex="60%">{{ loanProduct.minimumDaysBetweenDisbursalAndFirstRepayment }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Settings</h3>
<mat-divider fxFlexFill></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Amortization:</span>
<span fxFlex="60%">{{ loanProduct.amortizationType | find:loanProductsTemplate.amortizationTypeOptions:'id':'value'
}}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Is Equal Amortization:</span>
<span fxFlex="60%">{{ loanProduct.isEqualAmortization | yesNo }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Interest Method:</span>
<span fxFlex="60%">{{ loanProduct.interestType | find:loanProductsTemplate.interestTypeOptions:'id':'value'
}}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Interest Calculation Period:</span>
<span fxFlex="60%">{{ loanProduct.interestCalculationPeriodType |
find:loanProductsTemplate.interestCalculationPeriodTypeOptions:'id':'value' }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Allow Partial Interest Calculation with same as repayment:</span>
<span fxFlex="60%">{{ loanProduct.allowPartialPeriodInterestCalcualtion | yesNo }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Repayment Strategy:</span>
<span fxFlex="60%" class="repayment-strategy">{{ loanProduct.transactionProcessingStrategyCode |
find:loanProductsTemplate.transactionProcessingStrategyOptions:'code':'name' }}</span>
</div>
<div fxFlexFill *ngIf="isAdvancedPaymentAllocation">
<span fxFlex="40%">Advanced Payment Allocation Transactions:</span>
<span fxFlex="60%">
<mat-accordion>
<mifosx-view-advance-paymeny-allocation *ngFor="let paymentAllocation of loanProduct.paymentAllocation"
[paymentAllocation]="paymentAllocation"
[advancePaymentAllocationData]="advancePaymentAllocationData">
</mifosx-view-advance-paymeny-allocation>
</mat-accordion>
</span>
</div>
<div fxFlexFill *ngIf="loanProduct.graceOnPrincipalPayment">
<span fxFlex="40%">Grace on principal payment:</span>
<span fxFlex="60%">{{ loanProduct.graceOnPrincipalPayment }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.graceOnInterestPayment">
<span fxFlex="40%">Grace on interest payment:</span>
<span fxFlex="60%">{{ loanProduct.graceOnInterestPayment }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.graceOnInterestCharged">
<span fxFlex="40%">Interest free period:</span>
<span fxFlex="60%">{{ loanProduct.graceOnInterestCharged }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.inArrearsTolerance">
<span fxFlex="40%">Arrears tolerance:</span>
<span fxFlex="60%">{{ loanProduct.inArrearsTolerance }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Days in year:</span>
<span fxFlex="60%">{{ loanProduct.daysInYearType | find:loanProductsTemplate.daysInYearTypeOptions:'id':'value'
}}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Days in month:</span>
<span fxFlex="60%">{{ loanProduct.daysInMonthType | find:loanProductsTemplate.daysInMonthTypeOptions:'id':'value'
}}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Allow fixing of the installment amount:</span>
<span fxFlex="60%">{{ loanProduct.canDefineInstallmentAmount | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.graceOnArrearsAgeing">
<span fxFlex="40%">Number of days a loan may be overdue before moving into arrears:</span>
<span fxFlex="60%">{{ loanProduct.graceOnArrearsAgeing }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.overdueDaysForNPA">
<span fxFlex="40%">Maximum number of days a loan may be overdue before becoming a NPA (non performing asset):</span>
<span fxFlex="60%">{{ loanProduct.overdueDaysForNPA }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Delinquency Bucket:</span>
<span fxFlex="60%">{{ loanProduct.delinquencyBucketId }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Enable installment level Delinquency:</span>
<span fxFlex="60%">{{ loanProduct.enableInstallmentLevelDelinquency | yesNo }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Account moves out of NPA only after all arrears have been cleared:</span>
<span fxFlex="60%">{{ loanProduct.accountMovesOutOfNPAOnlyOnArrearsCompletion | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.principalThresholdForLastInstallment">
<span fxFlex="40%">Principal Threshold (%) for Last Instalment:</span>
<span fxFlex="60%">{{ loanProduct.principalThresholdForLastInstallment }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Variable Installments allowed:</span>
<span fxFlex="60%">{{ loanProduct.allowVariableInstallments | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.allowVariableInstallments">
<span fxFlex="40%">Variable Installments:</span>
<span fxFlex="60%">{{ '(Min: ' + loanProduct.minimumGap + ', Max: ' + (loanProduct.maximumGap ?
loanProduct.maximumGap : loanProduct.minimumGap) + ')' }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Allowed to be used for providing Topup Loans:</span>
<span fxFlex="60%">{{ loanProduct.canUseForTopup | yesNo }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Interest Recalculation</h3>
<mat-divider fxFlexFill></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Recalculate Interest:</span>
<span fxFlex="60%">{{ loanProduct.isInterestRecalculationEnabled | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.isInterestRecalculationEnabled" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Pre-closure interest calculation rule:</span>
<span fxFlex="60%">{{ loanProduct.preClosureInterestCalculationStrategy |
find:loanProductsTemplate.preClosureInterestCalculationStrategyOptions:'id':'value' }}</span>
<span fxFlex="40%">Advance payments adjustment type:</span>
<span fxFlex="60%">{{ loanProduct.rescheduleStrategyMethod |
find:loanProductsTemplate.rescheduleStrategyTypeOptions:'id':'value' }}</span>
<span fxFlex="40%">Interest recalculation compounding on:</span>
<span fxFlex="60%">{{ loanProduct.interestRecalculationCompoundingMethod |
find:loanProductsTemplate.interestRecalculationCompoundingTypeOptions:'id':'value' }}</span>
<div fxFlexFill *ngIf="loanProduct.interestRecalculationCompoundingMethod !== 0" fxLayout="row wrap"
fxLayout.lt-md="column">
<span fxFlex="40%">Frequency for compounding:</span>
<span fxFlex="60%">
{{ loanProduct.recalculationCompoundingFrequencyType |
find:loanProductsTemplate.interestRecalculationFrequencyTypeOptions:'id':'value' }}
<span *ngIf="loanProduct.recalculationCompoundingFrequencyType === 4">&nbsp;&nbsp;{{
loanProduct.recalculationCompoundingFrequencyNthDayType |
find:loanProductsTemplate.interestRecalculationNthDayTypeOptions:'id':'value' }}</span>
<span
*ngIf="(loanProduct.recalculationCompoundingFrequencyType === 4 && loanProduct.recalculationCompoundingFrequencyNthDayType !== -2) || loanProduct.recalculationCompoundingFrequencyType === 3">&nbsp;&nbsp;{{
loanProduct.recalculationCompoundingFrequencyDayOfWeekType |
find:loanProductsTemplate.interestRecalculationDayOfWeekTypeOptions:'id':'value' }}</span>
<span
*ngIf="loanProduct.recalculationCompoundingFrequencyType === 4 && loanProduct.recalculationCompoundingFrequencyNthDayType === -2">&nbsp;&nbsp;{{
loanProduct.recalculationCompoundingFrequencyOnDayType }}</span>
</span>
<div fxFlexFill *ngIf="loanProduct.recalculationCompoundingFrequencyType !== 1" fxLayout="row wrap"
fxLayout.lt-md="column">
<span fxFlex="40%">Frequency Interval for compounding:</span>
<span fxFlex="60%">{{ loanProduct.recalculationCompoundingFrequencyInterval }}</span>
</div>
</div>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Frequency for recalculate Outstanding Principal:</span>
<span fxFlex="60%">
{{ loanProduct.recalculationRestFrequencyType |
find:loanProductsTemplate.interestRecalculationFrequencyTypeOptions:'id':'value' }}
<span *ngIf="loanProduct.recalculationRestFrequencyType === 4">&nbsp;&nbsp;{{
loanProduct.recalculationRestFrequencyNthDayType |
find:loanProductsTemplate.interestRecalculationNthDayTypeOptions:'id':'value' }}</span>
<span
*ngIf="(loanProduct.recalculationRestFrequencyType === 4 && loanProduct.recalculationRestFrequencyNthDayType !== -2) || loanProduct.recalculationRestFrequencyType === 3">&nbsp;&nbsp;{{
loanProduct.recalculationRestFrequencyDayOfWeekType |
find:loanProductsTemplate.interestRecalculationDayOfWeekTypeOptions:'id':'value' }}</span>
<span
*ngIf="loanProduct.recalculationRestFrequencyType === 4 && loanProduct.recalculationRestFrequencyNthDayType === -2">&nbsp;&nbsp;{{
loanProduct.recalculationRestFrequencyOnDayType }}</span>
</span>
</div>
<div fxFlexFill *ngIf="loanProduct.recalculationRestFrequencyType !== 1" fxLayout="row wrap"
fxLayout.lt-md="column">
<span fxFlex="40%">Frequency Interval for recalculation:</span>
<span fxFlex="60%">{{ loanProduct.recalculationRestFrequencyInterval }}</span>
<div fxFlexFill *ngIf="loanProduct.recalculationRestFrequencyDate">
<span fxFlex="40%">Rest Frequency Date:</span>
<span fxFlex="60%">{{ loanProduct.recalculationRestFrequencyDate }}</span>
</div>
</div>
<div fxFlexFill>
<span fxFlex="40%">Is Arrears recognization based on original schedule:</span>
<span fxFlex="60%">{{ loanProduct.isArrearsBasedOnOriginalSchedule | yesNo }}</span>
</div>
</div>
<h3 class="mat-h3" fxFlexFill>Guarantee Requirements</h3>
<mat-divider fxFlexFill></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Place Guarantee Funds On-Hold:</span>
<span fxFlex="60%">{{ loanProduct.holdGuaranteeFunds | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.holdGuaranteeFunds" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Mandatory Guarantee(%):</span>
<span fxFlex="60%">{{ loanProduct.mandatoryGuarantee }}</span>
<div fxFlexFill *ngIf="loanProduct.minimumGuaranteeFromOwnFunds">
<span fxFlex="40%">Minimum Guarantee from Own Funds(%):</span>
<span fxFlex="60%">{{ loanProduct.minimumGuaranteeFromOwnFunds }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.minimumGuaranteeFromGuarantor">
<span fxFlex="40%">Minimum Guarantee from Guarantor Funds(%):</span>
<span fxFlex="60%">{{ loanProduct.minimumGuaranteeFromGuarantor }}</span>
</div>
</div>
<h3 class="mat-h3" fxFlexFill>Loan Tranche Details</h3>
<mat-divider fxFlexFill></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Enable Multiple Disbursals:</span>
<span fxFlex="60%">{{ loanProduct.multiDisburseLoan | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.multiDisburseLoan" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Maximum Tranche count:</span>
<span fxFlex="60%">{{ loanProduct.maxTrancheCount }}</span>
<div fxFlexFill *ngIf="loanProduct.outstandingLoanBalance">
<span fxFlex="40%">Maximum allowed outstanding balance:</span>
<span fxFlex="60%">{{ loanProduct.outstandingLoanBalance }}</span>
</div>
</div>
<div fxFlexFill>
<span fxFlex="40%">Disallow Expected Disbursements:</span>
<span fxFlex="60%">{{ loanProduct.disallowExpectedDisbursements | yesNo }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Down Payments</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Enable Down Payments:</span>
<span fxFlex="60%">{{ loanProduct.enableDownPayment | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.enableDownPayment" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Disbursed Amount Percentage Down Payment (%):</span>
<span fxFlex="60%">{{ loanProduct.disbursedAmountPercentageForDownPayment }} %</span>
</div>
<div fxFlexFill *ngIf="loanProduct.enableDownPayment" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Enable Auto Repayment for Down Payment:</span>
<span fxFlex="60%">{{ loanProduct.enableAutoRepaymentForDownPayment | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.enableDownPayment" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Do not extend loan schedule for multi disbursal:</span>
<span fxFlex="60%">{{ loanProduct.disableScheduleExtensionForDownPayment | yesNo }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Event Settings</h3>
<div fxFlexFill>
<span fxFlex="40%">Use the Global Configurations values to the Repayment Event (notifications):</span>
<span fxFlex="60%">{{ loanProduct.useDueForRepaymentsConfigurations | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="!loanProduct.useDueForRepaymentsConfigurations">
<span fxFlex="40%">Due days for repayment event:</span>
<span fxFlex="60%">{{ loanProduct.dueDaysForRepaymentEvent | number }}</span>
</div>
<div fxFlexFill *ngIf="!loanProduct.useDueForRepaymentsConfigurations">
<span fxFlex="40%">OverDue days for repayment event:</span>
<span fxFlex="60%">{{ loanProduct.overDueDaysForRepaymentEvent | number }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Configurable Terms and Settings</h3>
<mat-divider fxFlexFill></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Allow overriding select terms and settings in loan accounts:</span>
<span fxFlex="60%">{{ loanProduct.allowAttributeConfiguration | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.allowAttributeConfiguration" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Amortization:</span>
<span fxFlex="60%">{{ loanProduct.allowAttributeOverrides.amortizationType | yesNo }}</span>
<span fxFlex="40%">Interest method:</span>
<span fxFlex="60%">{{ loanProduct.allowAttributeOverrides.interestType | yesNo }}</span>
<span fxFlex="40%">Repayment strategy:</span>
<span fxFlex="60%">{{ loanProduct.allowAttributeOverrides.transactionProcessingStrategyCode | yesNo }}</span>
<span fxFlex="40%">Interest calculation period:</span>
<span fxFlex="60%">{{ loanProduct.allowAttributeOverrides.interestCalculationPeriodType | yesNo }}</span>
<span fxFlex="40%">Arrears tolerance:</span>
<span fxFlex="60%">{{ loanProduct.allowAttributeOverrides.inArrearsTolerance | yesNo }}</span>
<span fxFlex="40%">Repaid every:</span>
<span fxFlex="60%">{{ loanProduct.allowAttributeOverrides.repaymentEvery | yesNo }}</span>
<span fxFlex="40%">Moratorium:</span>
<span fxFlex="60%">{{ loanProduct.allowAttributeOverrides.graceOnPrincipalAndInterestPayment | yesNo
}}</span>
<span fxFlex="40%">Number of days a loan may be overdue before moving into arrears:</span>
<span fxFlex="60%">{{ loanProduct.allowAttributeOverrides.graceOnArrearsAgeing | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.charges.length" fxLayout="row wrap" fxLayout.lt-md="column">
<h3 class="mat-h3" fxFlexFill>Charges</h3>
<mat-divider fxFlexFill></mat-divider>
<table fxFlexFill class="mat-elevation-z1" mat-table
[dataSource]="loanProduct.charges | chargesPenaltyFilter:false">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let charge">
{{ charge.name + ', ' + charge.currency.displaySymbol }}
</td>
</ng-container>
<ng-container matColumnDef="chargeCalculationType">
<th mat-header-cell *matHeaderCellDef> Type </th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeCalculationType.value }}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef> Amount </th>
<td mat-cell *matCellDef="let charge">
{{ charge.amount }}
</td>
</ng-container>
<ng-container matColumnDef="chargeTimeType">
<th mat-header-cell *matHeaderCellDef> Collected On </th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeTimeType.value }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chargesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chargesDisplayedColumns;"></tr>
</table>
<h3 class="mat-h3" fxFlexFill>Overdue Charges</h3>
<mat-divider fxFlexFill></mat-divider>
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="loanProduct.charges | chargesPenaltyFilter:true">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let overdueCharge">
{{ overdueCharge.name + ', ' + overdueCharge.currency.displaySymbol }}
</td>
</ng-container>
<ng-container matColumnDef="chargeCalculationType">
<th mat-header-cell *matHeaderCellDef> Type </th>
<td mat-cell *matCellDef="let overdueCharge">
{{ overdueCharge.chargeCalculationType.value }}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef> Amount </th>
<td mat-cell *matCellDef="let overdueCharge">
{{ overdueCharge.amount }}
</td>
</ng-container>
<ng-container matColumnDef="chargeTimeType">
<th mat-header-cell *matHeaderCellDef> Collected On </th>
<td mat-cell *matCellDef="let overdueCharge">
{{ overdueCharge.chargeTimeType.value }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chargesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chargesDisplayedColumns;"></tr>
</table>
</div>
<h3 class="mat-h3" fxFlexFill>Accounting</h3>
<mat-divider fxFlexFill></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Type:</span>
<span fxFlex="60%">{{ accountingRuleData[loanProduct.accountingRule-1] }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.accountingRule >= 2 && loanProduct.accountingRule <= 4" fxLayout="row wrap"
fxLayout.lt-md="column">
<h4 fxFlexFill class="mat-h4">Assets / Liabilities</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Fund source:</span>
<span fxFlex="60%">{{ loanProduct.fundSourceAccountId |
find:loanProductsTemplate.accountingMappingOptions.assetAndLiabilityAccountOptions:'id':'name' }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Assets</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Loan portfolio:</span>
<span fxFlex="60%">{{ loanProduct.loanPortfolioAccountId |
find:loanProductsTemplate.accountingMappingOptions.assetAccountOptions:'id':'name' }}</span>
<div fxFlexFill *ngIf="loanProduct.accountingRule === 3 || loanProduct.accountingRule === 4" fxLayout="row wrap"
fxLayout.lt-md="column">
<span fxFlex="40%">Interest Receivable:</span>
<span fxFlex="60%">{{ loanProduct.receivableInterestAccountId |
find:loanProductsTemplate.accountingMappingOptions.assetAccountOptions:'id':'name' }}</span>
<span fxFlex="40%">Fees Receivable:</span>
<span fxFlex="60%">{{ loanProduct.receivableFeeAccountId |
find:loanProductsTemplate.accountingMappingOptions.assetAccountOptions:'id':'name' }}</span>
<span fxFlex="40%">Penalties Receivable:</span>
<span fxFlex="60%">{{ loanProduct.receivablePenaltyAccountId |
find:loanProductsTemplate.accountingMappingOptions.assetAccountOptions:'id':'name' }}</span>
</div>
<span fxFlex="40%">Transfer in suspense:</span>
<span fxFlex="60%">{{ loanProduct.transfersInSuspenseAccountId |
find:loanProductsTemplate.accountingMappingOptions.assetAccountOptions:'id':'name' }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Income</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Income from Interest:</span>
<span fxFlex="60%">{{ loanProduct.interestOnLoanAccountId |
find:loanProductsTemplate.accountingMappingOptions.incomeAccountOptions:'id':'name' }}</span>
<span fxFlex="40%">Income from fees:</span>
<span fxFlex="60%">{{ loanProduct.incomeFromFeeAccountId |
find:loanProductsTemplate.accountingMappingOptions.incomeAccountOptions:'id':'name' }}</span>
<span fxFlex="40%">Income from penalties:</span>
<span fxFlex="60%">{{ loanProduct.incomeFromPenaltyAccountId |
find:loanProductsTemplate.accountingMappingOptions.incomeAccountOptions:'id':'name' }}</span>
<span fxFlex="40%">Income from Recovery Repayments:</span>
<span fxFlex="60%">{{ loanProduct.incomeFromRecoveryAccountId |
find:loanProductsTemplate.accountingMappingOptions.incomeAccountOptions:'id':'name' }}</span>
<span fxFlex="40%">Income from ChargeOff Interest:</span>
<span fxFlex="60%">{{ loanProduct.incomeFromChargeOffInterestAccountId |
find:loanProductsTemplate.accountingMappingOptions.incomeAccountOptions:'id':'name' }}</span>
<span fxFlex="40%">Income from ChargeOff Fees:</span>
<span fxFlex="60%">{{ loanProduct.incomeFromChargeOffFeesAccountId |
find:loanProductsTemplate.accountingMappingOptions.incomeAccountOptions:'id':'name' }}</span>
<span fxFlex="40%">Income from ChargeOff Penalty:</span>
<span fxFlex="60%">{{ loanProduct.incomeFromChargeOffPenaltyAccountId |
find:loanProductsTemplate.accountingMappingOptions.incomeAccountOptions:'id':'name' }}</span>
<span fxFlex="40%">Income from Goodwill Credit Interest:</span>
<span fxFlex="60%">{{ loanProduct.incomeFromGoodwillCreditInterestAccountId |
find:loanProductsTemplate.accountingMappingOptions.incomeAccountOptions:'id':'name' }}</span>
<span fxFlex="40%">Income from Goodwill Credit Fees:</span>
<span fxFlex="60%">{{ loanProduct.incomeFromGoodwillCreditFeesAccountId |
find:loanProductsTemplate.accountingMappingOptions.incomeAccountOptions:'id':'name' }}</span>
<span fxFlex="40%">Income from Goodwill Credit Penalty:</span>
<span fxFlex="60%">{{ loanProduct.incomeFromGoodwillCreditPenaltyAccountId |
find:loanProductsTemplate.accountingMappingOptions.incomeAccountOptions:'id':'name' }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Expenses</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Losses written off:</span>
<span fxFlex="60%">{{ loanProduct.writeOffAccountId |
find:loanProductsTemplate.accountingMappingOptions.expenseAccountOptions:'id':'name' }}</span>
<span fxFlex="40%">Expenses from Goodwill Credit:</span>
<span fxFlex="60%">{{ loanProduct.goodwillCreditAccountId |
find:loanProductsTemplate.accountingMappingOptions.expenseAccountOptions:'id':'name' }}</span>
<span fxFlex="40%">ChargeOff Expense:</span>
<span fxFlex="60%">{{ loanProduct.chargeOffExpenseAccountId |
find:loanProductsTemplate.accountingMappingOptions.expenseAccountOptions:'id':'name' }}</span>
<span fxFlex="40%">ChargeOff Fraud Expense:</span>
<span fxFlex="60%">{{ loanProduct.chargeOffFraudExpenseAccountId |
find:loanProductsTemplate.accountingMappingOptions.expenseAccountOptions:'id':'name' }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Liabilities</h4>
<div fxFlexFill>
<span fxFlex="40%">Over payment liability:</span>
<span fxFlex="60%">{{ loanProduct.overpaymentLiabilityAccountId |
find:loanProductsTemplate.accountingMappingOptions.liabilityAccountOptions:'id':'name' }}</span>
</div>
<div
*ngIf="loanProduct.advancedAccountingRules && (loanProduct.paymentChannelToFundSourceMappings?.length || loanProduct.feeToIncomeAccountMappings?.length || loanProduct.penaltyToIncomeAccountMappings?.length)"
fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<h3 class="mat-h3" fxFlexFill>Advanced Accounting Rules</h3>
<mat-divider fxFlexFill></mat-divider>
<div *ngIf="loanProduct.paymentChannelToFundSourceMappings?.length" fxFlexFill fxLayout="row wrap"
fxLayout.lt-md="column">
<h4 class="mat-h4" fxFlexFill>Fund Sources for Payment Channels</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table
[dataSource]="loanProduct.paymentChannelToFundSourceMappings">
<ng-container matColumnDef="paymentTypeId">
<th mat-header-cell *matHeaderCellDef> Payment Type </th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.paymentTypeId | find:loanProductsTemplate.paymentTypeOptions:'id':'name' }}
</td>
</ng-container>
<ng-container matColumnDef="fundSourceAccountId">
<th mat-header-cell *matHeaderCellDef> Fund Source </th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.fundSourceAccountId |
find:loanProductsTemplate.accountingMappingOptions.assetAccountOptions:'id':'name' }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="paymentFundSourceDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: paymentFundSourceDisplayedColumns;"></tr>
</table>
</div>
<div *ngIf="loanProduct.feeToIncomeAccountMappings?.length" fxFlexFill fxLayout="row wrap"
fxLayout.lt-md="column">
<h4 class="mat-h4" fxFlexFill>Fees to Specific Income Accounts</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="loanProduct.feeToIncomeAccountMappings">
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef> Fees </th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.chargeId | find:loanProductsTemplate.chargeOptions:'id':'name' }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef> Income Account </th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.incomeAccountId |
find:loanProductsTemplate.accountingMappingOptions.incomeAccountOptions.concat(loanProductsTemplate.accountingMappingOptions.liabilityAccountOptions):'id':'name'
}}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns;"></tr>
</table>
</div>
<div *ngIf="loanProduct.penaltyToIncomeAccountMappings?.length" fxFlexFill fxLayout="row wrap"
fxLayout.lt-md="column">
<h4 class="mat-h4" fxFlexFill>Penalties to Specific Income Accounts</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="loanProduct.penaltyToIncomeAccountMappings">
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef> Penalty </th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.chargeId | find:loanProductsTemplate.penaltyOptions:'id':'name' }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef> Income Account </th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.incomeAccountId |
find:loanProductsTemplate.accountingMappingOptions.incomeAccountOptions:'id':'name' }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns;"></tr>
</table>
</div>
</div>
</div>
</div>
<mifosx-loan-product-summary
[loanProduct]="loanProduct"
[loanProductsTemplate]="loanProductsTemplate"
[useDueForRepaymentsConfigurations]="loanProduct.useDueForRepaymentsConfigurations"
[paymentAllocations]="loanProduct.paymentAllocation"
>
</mifosx-loan-product-summary>
<div fxLayout="row" class="margin-t" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="2%">
<button mat-raised-button matStepperPrevious>
@@ -1,5 +1,5 @@
import { Component, OnInit, Input, Output, EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
import { AdvancePaymentAllocationData } from '../loan-product-payment-strategy-step/payment-allocation-model';
import { LoanProducts } from '../../loan-products';
@Component({
selector: 'mifosx-loan-product-preview-step',
@@ -13,28 +13,20 @@ export class LoanProductPreviewStepComponent implements OnInit, OnChanges {
@Input() loanProduct: any;
@Output() submit = new EventEmitter();
variationsDisplayedColumns: string[] = ['valueConditionType', 'borrowerCycleNumber', 'minValue', 'defaultValue', 'maxValue'];
chargesDisplayedColumns: string[] = ['name', 'chargeCalculationType', 'amount', 'chargeTimeType'];
paymentFundSourceDisplayedColumns: string[] = ['paymentTypeId', 'fundSourceAccountId'];
feesPenaltyIncomeDisplayedColumns: string[] = ['chargeId', 'incomeAccountId'];
isAdvancedPaymentAllocation = false;
advancePaymentAllocationData: AdvancePaymentAllocationData;
constructor() { }
ngOnInit() {
this.isAdvancedPaymentAllocation = (this.loanProduct.transactionProcessingStrategyCode === 'advanced-payment-allocation-strategy');
this.advancePaymentAllocationData = {
transactionTypes: this.loanProductsTemplate.advancedPaymentAllocationTransactionTypes,
allocationTypes: this.loanProductsTemplate.advancedPaymentAllocationTypes,
futureInstallmentAllocationRules: this.loanProductsTemplate.advancedPaymentAllocationFutureInstallmentAllocationRules
};
this.advancedPaymentAllocation();
}
ngOnChanges(changes: SimpleChanges): void {
this.isAdvancedPaymentAllocation = (this.loanProduct.transactionProcessingStrategyCode === 'advanced-payment-allocation-strategy');
this.advancedPaymentAllocation();
}
advancedPaymentAllocation() {
this.isAdvancedPaymentAllocation = LoanProducts.isAdvancedPaymentAllocationStrategy(this.loanProduct.transactionProcessingStrategyCode);
}
}
@@ -50,6 +50,19 @@
Calculate interest for exact days in partial period
</mat-checkbox>
<mat-divider fxFlex="98%"></mat-divider>
<h4 fxFlex="98%" class="mat-h4">Loan Schedule</h4>
<mat-form-field fxFlex="48%">
<mat-label>Loan Schedule Type</mat-label>
<mat-select formControlName="loanScheduleType" required>
<mat-option *ngFor="let loanScheduleType of loanScheduleTypeData" [value]="loanScheduleType.code">
{{ loanScheduleType.value }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="48%">
<mat-label>Repayment strategy</mat-label>
<mat-select formControlName="transactionProcessingStrategyCode" matTooltip="The repayment strategy determines the sequence in which each of the components is paid." required>
@@ -62,6 +75,75 @@
</mat-error>
</mat-form-field>
<mat-form-field fxFlex="48%">
<mat-label>Loan Schedule Processing Type</mat-label>
<mat-select formControlName="loanScheduleProcessingType" required>
<mat-option *ngFor="let loanScheduleProcessingType of loanScheduleProcessingTypeData" [value]="loanScheduleProcessingType.code">
{{ loanScheduleProcessingType.value }}
</mat-option>
</mat-select>
</mat-form-field>
<h3 fxFlex="96%" class="mat-h3">Loan Tranche Details</h3>
<mat-checkbox fxFlex="73%" labelPosition="before" formControlName="multiDisburseLoan" matTooltip="Leave this checkbox unchecked if the loan is a single disburse loan. Check this
checkbox if the loan is a multi disburse loan. See additional fields for additional information required for this type of loan." class="margin-b">
Enable Multiple Disbursals
</mat-checkbox>
<div *ngIf="loanProductSettingsForm.value.multiDisburseLoan" fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
<mat-form-field fxFlex="48%">
<mat-label>Maximum Tranche count</mat-label>
<input type="number" matInput matTooltip="The maximum number of disbursements allowed for a loan account." formControlName="maxTrancheCount" required>
<mat-error *ngIf="loanProductSettingsForm.controls.maxTrancheCount.hasError('required')">
Maximum Tranche count is <strong>required</strong>
</mat-error>
</mat-form-field>
<mat-form-field fxFlex="48%">
<mat-label>Maximum allowed outstanding balance</mat-label>
<input type="number" matInput matTooltip="The maximum outstanding loan account balance allowed at a point in time." formControlName="outstandingLoanBalance">
</mat-form-field>
<mat-checkbox fxFlex="48%" labelPosition="before" formControlName="disallowExpectedDisbursements" class="margin-v">
Disallow Expected Disbursements
</mat-checkbox>
</div>
<h3 fxFlex="23%" class="mat-h3">Down Payment</h3>
<mat-checkbox fxFlex="73%" labelPosition="before" formControlName="enableDownPayment" matTooltip="Leave this checkbox checked if the loan has Down Payment, A Down Payment is
a sum a buyer pays upfront when purchasing a good. It represents a percentage of the total purchase price, and the balance is usually financed" class="margin-b">
Enable Down Payment
</mat-checkbox>
<div *ngIf="loanProductSettingsForm.value.enableDownPayment" fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
<mat-form-field fxFlex="48%">
<mat-label>Disbursed Amount Percentage Down Payment (%)</mat-label>
<input type="number" matInput matTooltip="The percentage of disbursements amount for Down Payment" formControlName="disbursedAmountPercentageForDownPayment" required [min]="0" [max]="100">
<mat-error *ngIf="loanProductSettingsForm.controls.disbursedAmountPercentageForDownPayment.hasError('required')">
Disbursed Amount Percentage Down Payment is <strong>required</strong>
</mat-error>
<mat-error *ngIf="loanProductSettingsForm.controls.disbursedAmountPercentageForDownPayment.errors?.range">
Disbursed Amount Percentage Down Payment is out <strong>percentage range</strong>
</mat-error>
</mat-form-field>
<mat-checkbox fxFlex="48%" labelPosition="before" formControlName="enableAutoRepaymentForDownPayment" matTooltip="Enable or disable the auto repayment of down-payment.
When “auto repayment for the down-payments“ is enabled, the disbursements will trigger an auto down payment transaction for the down payment amount" class="margin-b">
Enable Auto Repayment for Down Payment
</mat-checkbox>
</div>
<div *ngIf="loanProductSettingsForm.value.multiDisburseLoan && loanProductSettingsForm.value.enableDownPayment" fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
<mat-checkbox fxFlex="48%" labelPosition="before" formControlName="disableScheduleExtensionForDownPayment" matTooltip="Enable or disable If Fineract extends the
repayment schedule to the exact number of repayments configured for that loan account" class="margin-b">
Do not extend loan schedule for multi disbursal
</mat-checkbox>
</div>
<mat-divider fxFlex="98%"></mat-divider>
<span fxFlex="48%" fxHide.lt-md></span>
<h4 fxFlex="98%" class="mat-h4">Moratorium <i class="fas fa-question" matTooltip="The moratorium information will default from the loan product settings, but can be changed for this loan account"></i></h4>
@@ -394,68 +476,6 @@
<mat-divider fxFlex="98%"></mat-divider>
<h3 fxFlex="23%" class="mat-h3">Loan Tranche Details</h3>
<mat-checkbox fxFlex="73%" labelPosition="before" formControlName="multiDisburseLoan" matTooltip="Leave this checkbox unchecked if the loan is a single disburse loan. Check this
checkbox if the loan is a multi disburse loan. See additional fields for additional information required for this type of loan." class="margin-b">
Enable Multiple Disbursals
</mat-checkbox>
<div *ngIf="loanProductSettingsForm.value.multiDisburseLoan" fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
<mat-form-field fxFlex="48%">
<mat-label>Maximum Tranche count</mat-label>
<input type="number" matInput matTooltip="The maximum number of disbursements allowed for a loan account." formControlName="maxTrancheCount" required>
<mat-error *ngIf="loanProductSettingsForm.controls.maxTrancheCount.hasError('required')">
Maximum Tranche count is <strong>required</strong>
</mat-error>
</mat-form-field>
<mat-form-field fxFlex="48%">
<mat-label>Maximum allowed outstanding balance</mat-label>
<input type="number" matInput matTooltip="The maximum outstanding loan account balance allowed at a point in time." formControlName="outstandingLoanBalance">
</mat-form-field>
<mat-checkbox fxFlex="48%" labelPosition="before" formControlName="disallowExpectedDisbursements" class="margin-v">
Disallow Expected Disbursements
</mat-checkbox>
</div>
<mat-divider fxFlex="98%"></mat-divider>
<h3 fxFlex="23%" class="mat-h3">Down Payment</h3>
<mat-checkbox fxFlex="73%" labelPosition="before" formControlName="enableDownPayment" matTooltip="Leave this checkbox checked if the loan has Down Payment, A Down Payment is
a sum a buyer pays upfront when purchasing a good. It represents a percentage of the total purchase price, and the balance is usually financed" class="margin-b">
Enable Down Payment
</mat-checkbox>
<div *ngIf="loanProductSettingsForm.value.enableDownPayment" fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
<mat-form-field fxFlex="48%">
<mat-label>Disbursed Amount Percentage Down Payment (%)</mat-label>
<input type="number" matInput matTooltip="The percentage of disbursements amount for Down Payment" formControlName="disbursedAmountPercentageForDownPayment" required [min]="0" [max]="100">
<mat-error *ngIf="loanProductSettingsForm.controls.disbursedAmountPercentageForDownPayment.hasError('required')">
Disbursed Amount Percentage Down Payment is <strong>required</strong>
</mat-error>
<mat-error *ngIf="loanProductSettingsForm.controls.disbursedAmountPercentageForDownPayment.errors?.range">
Disbursed Amount Percentage Down Payment is out <strong>percentage range</strong>
</mat-error>
</mat-form-field>
<mat-checkbox fxFlex="48%" labelPosition="before" formControlName="enableAutoRepaymentForDownPayment" matTooltip="Enable or disable the auto repayment of down-payment.
When “auto repayment for the down-payments“ is enabled, the disbursements will trigger an auto down payment transaction for the down payment amount" class="margin-b">
Enable Auto Repayment for Down Payment
</mat-checkbox>
</div>
<div *ngIf="loanProductSettingsForm.value.multiDisburseLoan && loanProductSettingsForm.value.enableDownPayment" fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
<mat-checkbox fxFlex="48%" labelPosition="before" formControlName="disableScheduleExtensionForDownPayment" matTooltip="Enable or disable If Fineract extends the
repayment schedule to the exact number of repayments configured for that loan account" class="margin-b">
Do not extend loan schedule for multi disbursal
</mat-checkbox>
</div>
<mat-divider fxFlex="98%"></mat-divider>
<h3 fxFlex="23%" class="mat-h3">Event Settings <i class="fas fa-question"
matTooltip="Setting for event notifications to be sent before or after repayments. Blue color means default value from global configurations."></i></h3>
@@ -3,6 +3,7 @@ import { UntypedFormGroup, UntypedFormBuilder, Validators, UntypedFormControl }
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 } from 'app/shared/models/option-data.model';
@Component({
@@ -25,7 +26,8 @@ export class LoanProductSettingsStepComponent implements OnInit {
amortizationTypeData: any;
interestTypeData: any;
interestCalculationPeriodTypeData: any;
transactionProcessingStrategyData: any;
transactionProcessingStrategyData: CodeName[] = [];
transactionProcessingStrategyDataBase: CodeName[] = [];
daysInYearTypeData: any;
daysInMonthTypeData: any;
preClosureInterestCalculationStrategyData: any;
@@ -36,6 +38,8 @@ export class LoanProductSettingsStepComponent implements OnInit {
interestRecalculationDayOfWeekTypeData: any;
interestRecalculationOnDayTypeData: any;
delinquencyBucketData: any;
loanScheduleTypeData: OptionData[] = [];
loanScheduleProcessingTypeData: OptionData[] = [];
/** Values to Days for Repayments */
defaultConfigValues: GlobalConfiguration[] = [];
@@ -59,6 +63,7 @@ export class LoanProductSettingsStepComponent implements OnInit {
this.interestTypeData = this.loanProductsTemplate.interestTypeOptions;
this.interestCalculationPeriodTypeData = this.loanProductsTemplate.interestCalculationPeriodTypeOptions;
this.transactionProcessingStrategyData = this.loanProductsTemplate.transactionProcessingStrategyOptions;
this.transactionProcessingStrategyDataBase = this.loanProductsTemplate.transactionProcessingStrategyOptions;
this.daysInYearTypeData = this.loanProductsTemplate.daysInYearTypeOptions;
this.daysInMonthTypeData = this.loanProductsTemplate.daysInMonthTypeOptions;
this.preClosureInterestCalculationStrategyData = this.loanProductsTemplate.preClosureInterestCalculationStrategyOptions;
@@ -70,6 +75,8 @@ export class LoanProductSettingsStepComponent implements OnInit {
this.interestRecalculationDayOfWeekTypeData = this.loanProductsTemplate.interestRecalculationDayOfWeekTypeOptions;
this.interestRecalculationOnDayTypeData = Array.from({ length: 28 }, (_, index) => index + 1);
this.delinquencyBucketData = this.loanProductsTemplate.delinquencyBucketOptions;
this.loanScheduleTypeData = this.loanProductsTemplate.loanScheduleTypeOptions;
this.loanScheduleProcessingTypeData = this.loanProductsTemplate.loanScheduleProcessingTypeOptions;
this.loanProductSettingsForm.patchValue({
'amortizationType': this.loanProductsTemplate.amortizationType.id,
@@ -100,7 +107,9 @@ export class LoanProductSettingsStepComponent implements OnInit {
'maxTrancheCount': this.loanProductsTemplate.maxTrancheCount,
'outstandingLoanBalance': this.loanProductsTemplate.outstandingLoanBalance,
'enableDownPayment': this.loanProductsTemplate.enableDownPayment,
'enableInstallmentLevelDelinquency': this.loanProductsTemplate.enableInstallmentLevelDelinquency
'enableInstallmentLevelDelinquency': this.loanProductsTemplate.enableInstallmentLevelDelinquency,
'loanScheduleType': this.loanProductsTemplate.loanScheduleType.code,
'loanScheduleProcessingType': this.loanProductsTemplate.loanScheduleProcessingType.code
});
if (this.loanProductsTemplate.dueDaysForRepaymentEvent != null &&
@@ -224,6 +233,8 @@ export class LoanProductSettingsStepComponent implements OnInit {
'useDueForRepaymentsConfigurations': [false],
'dueDaysForRepaymentEvent': [''],
'overDueDaysForRepaymentEvent': [''],
'loanScheduleType': [LoanProducts.LOAN_SCHEDULE_TYPE_CUMULATIVE, Validators.required],
'loanScheduleProcessingType': [LoanProducts.LOAN_SCHEDULE_PROCESSING_TYPE_HORIZONTAL, Validators.required]
});
}
@@ -427,6 +438,30 @@ export class LoanProductSettingsStepComponent implements OnInit {
});
}
});
this.loanProductSettingsForm.get('loanScheduleType').valueChanges
.subscribe((loanScheduleType: string) => {
this.transactionProcessingStrategyData = [];
if (loanScheduleType === LoanProducts.LOAN_SCHEDULE_TYPE_CUMULATIVE) {
// Filter Advanced Payment Allocation Strategy
this.transactionProcessingStrategyData = this.transactionProcessingStrategyDataBase.filter(
(cn: CodeName) => !LoanProducts.isAdvancedPaymentAllocationStrategy(cn.code)
);
if (LoanProducts.isAdvancedPaymentAllocationStrategy(this.loanProductSettingsForm.value.transactionProcessingStrategyCode)) {
this.loanProductSettingsForm.patchValue({
'transactionProcessingStrategyCode': this.transactionProcessingStrategyData[0].code
});
}
} else {
// Only Advanced Payment Allocation Strategy
this.transactionProcessingStrategyDataBase.some(
(cn: CodeName) => {
if (LoanProducts.isAdvancedPaymentAllocationStrategy(cn.code)) {
this.transactionProcessingStrategyData.push(cn);
}
});
}
});
}
private getGlobalConfigValue(configName: string): number {
@@ -7,12 +7,24 @@ import { GlobalConfiguration } from 'app/system/configurations/global-configurat
})
export class LoanProducts {
public static LOAN_SCHEDULE_TYPE_CUMULATIVE = 'CUMULATIVE';
public static LOAN_SCHEDULE_TYPE_PROGRESSIVE = 'PROGRESSIVE';
public static LOAN_SCHEDULE_PROCESSING_TYPE_HORIZONTAL = 'HORIZONTAL';
public static LOAN_SCHEDULE_PROCESSING_TYPE_VERTICAL = 'VERTICAL';
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);
}
constructor(private settingsService: SettingsService) { }
public setItemsByDefault(configurations: any) {
@@ -0,0 +1,164 @@
import { AccountingMapping, ChargeToIncomeAccountMapping, Currency, PaymentChannelToFundSourceMapping } from 'app/shared/models/general.model';
import { OptionData } from 'app/shared/models/option-data.model';
import { PaymentAllocation } from '../loan-product-stepper/loan-product-payment-strategy-step/payment-allocation-model';
export interface LoanProduct {
id: number;
name: string;
shortName: string;
includeInBorrowerCycle: boolean;
useBorrowerCycle: boolean;
status: string;
currency: Currency;
fundId?: number;
fundName?: string;
startDate?: string;
closeDate?: string;
description?: string;
installmentAmountInMultiplesOf?: number;
principal: number;
minPrincipal?: number;
maxPrincipal?: number;
numberOfRepayments: number;
minNumberOfRepayments?: number;
maxNumberOfRepayments?: number;
repaymentEvery: number;
repaymentFrequencyType: OptionData;
minimumDaysBetweenDisbursalAndFirstRepayment?: number;
interestRatePerPeriod: number;
interestRateFrequencyType: OptionData;
annualInterestRate: number;
isLinkedToFloatingInterestRates: boolean;
isFloatingInterestRateCalculationAllowed: boolean;
allowVariableInstallments: boolean;
minimumGap: number;
maximumGap: number;
amortizationType: OptionData;
interestType: OptionData;
interestCalculationPeriodType: OptionData;
allowPartialPeriodInterestCalculation: boolean;
transactionProcessingStrategyCode: string;
transactionProcessingStrategyName: string;
paymentAllocation?: PaymentAllocation[];
daysInMonthType: OptionData;
daysInYearType: OptionData;
isInterestRecalculationEnabled: boolean;
interestRecalculationData?: InterestRecalculationData;
interestRecalculationCompoundingMethod?: number;
preClosureInterestCalculationStrategy?: number;
rescheduleStrategyMethod?: number;
recalculationCompoundingFrequencyType?: number;
recalculationRestFrequencyType?: number;
allowCompoundingOnEod?: boolean;
isArrearsBasedOnOriginalSchedule?: boolean;
isCompoundingToBePostedAsTransaction?: boolean;
recalculationRestFrequencyInterval?: number;
canDefineInstallmentAmount: boolean;
graceOnArrearsAgeing?: number;
overdueDaysForNPA?: number;
repaymentStartDateType: OptionData;
charges: any[];
principalVariationsForBorrowerCycle: any[];
interestRateVariationsForBorrowerCycle: any[];
numberOfRepaymentVariationsForBorrowerCycle: any[];
canUseForTopup: boolean;
isRatesEnabled: boolean;
rates: any[];
advancedPaymentAllocationTransactionTypes: OptionData[];
advancedPaymentAllocationFutureInstallmentAllocationRules: OptionData[];
advancedPaymentAllocationTypes: OptionData[];
multiDisburseLoan: boolean;
maxTrancheCount: number;
disallowExpectedDisbursements: boolean;
allowApprovedDisbursedAmountsOverApplied: boolean;
overAppliedNumber: number;
principalThresholdForLastInstallment: number;
holdGuaranteeFunds: boolean;
accountMovesOutOfNPAOnlyOnArrearsCompletion: boolean;
allowAttributeOverrides: AllowAttributeOverrides;
syncExpectedWithDisbursementDate: boolean;
isEqualAmortization: boolean;
delinquencyBucketOptions: DelinquencyBucket[];
delinquencyBucket: DelinquencyBucket;
graceOnPrincipalPayment?: number;
graceOnInterestPayment?: number;
graceOnInterestCharged?: number;
inArrearsTolerance?: number;
dueDaysForRepaymentEvent: number;
overDueDaysForRepaymentEvent: number;
enableDownPayment: boolean;
enableAutoRepaymentForDownPayment: boolean;
disableScheduleExtensionForDownPayment: boolean;
enableInstallmentLevelDelinquency: boolean;
loanScheduleType: OptionData;
loanScheduleProcessingType: OptionData;
allowAttributeConfiguration?: boolean;
// Accounting
accountingRule: any;
accountingMappings?: { [key: string]: AccountingMapping };
fundSourceAccountId?: number;
goodwillCreditAccountId?: number;
incomeFromChargeOffFeesAccountId?: number;
incomeFromChargeOffInterestAccountId?: number;
incomeFromChargeOffPenaltyAccountId?: number;
incomeFromFeeAccountId?: number;
incomeFromGoodwillCreditFeesAccountId?: number;
incomeFromGoodwillCreditInterestAccountId?: number;
incomeFromGoodwillCreditPenaltyAccountId?: number;
incomeFromPenaltyAccountId?: number;
incomeFromRecoveryAccountId?: number;
interestOnLoanAccountId?: number;
loanPortfolioAccountId?: number;
overpaymentLiabilityAccountId?: number;
receivableInterestAccountId?: number;
receivableFeeAccountId?: number;
receivablePenaltyAccountId?: number;
transfersInSuspenseAccountId?: number;
writeOffAccountId?: number;
// Advanced Accounting
paymentChannelToFundSourceMappings?: PaymentChannelToFundSourceMapping[];
feeToIncomeAccountMappings?: ChargeToIncomeAccountMapping[];
penaltyToIncomeAccountMappings?: ChargeToIncomeAccountMapping[];
}
export interface AllowAttributeOverrides {
amortizationType: boolean;
interestType: boolean;
transactionProcessingStrategyCode: boolean;
interestCalculationPeriodType: boolean;
inArrearsTolerance: boolean;
repaymentEvery: boolean;
graceOnPrincipalAndInterestPayment: boolean;
graceOnArrearsAgeing: boolean;
isNew: boolean;
}
export interface DelinquencyBucket {
id: number;
name: string;
ranges: Range[];
}
export interface Range {
id: number;
classification: string;
minimumAgeDays: number;
maximumAgeDays?: number;
}
export interface InterestRecalculationData {
id?: number;
productId?: number;
recalculationCompoundingFrequencyType: OptionData;
interestRecalculationCompoundingType: OptionData;
rescheduleStrategyType: OptionData;
recalculationRestFrequencyType: OptionData;
recalculationRestFrequencyInterval: number;
isArrearsBasedOnOriginalSchedule: boolean;
isCompoundingToBePostedAsTransaction: boolean;
preClosureInterestCalculationStrategy: OptionData;
allowCompoundingOnEod: boolean;
}
@@ -4,887 +4,9 @@
</button>
</div>
<div class="tab-container mat-typography">
<h3 class="mat-h3" fxFlexFill>Details</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Name:</span>
<span fxFlex="60%"><b>{{ loanProduct.name }}</b></span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Short Name:</span>
<span fxFlex="60%">{{ loanProduct.shortName }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.fundId">
<span fxFlex="40%">Fund Name:</span>
<span fxFlex="60%">{{ loanProduct.fundName }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Include in Customer Loan Counter:</span>
<span fxFlex="60%">{{ loanProduct.includeInBorrowerCycle | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.startDate">
<span fxFlex="40%">Start Date:</span>
<span fxFlex="60%">{{ loanProduct.startDate | dateFormat }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.closeDate">
<span fxFlex="40%">Close Date:</span>
<span fxFlex="60%">{{ loanProduct.closeDate | dateFormat }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.description">
<span fxFlex="40%">Description:</span>
<span fxFlex="60%">{{ loanProduct.description }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Currency</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Currency:</span>
<span fxFlex="60%">{{ loanProduct.currency.name }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Decimal Places:</span>
<span fxFlex="60%">{{ loanProduct.currency.decimalPlaces }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Currency in multiples of:</span>
<span fxFlex="60%">{{ loanProduct.currency.inMultiplesOf }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Installment in multiples of:</span>
<span fxFlex="60%">{{ loanProduct.installmentAmountInMultiplesOf }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Terms</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Principal:</span>
<span fxFlex="60%">{{ loanProduct.principal | formatNumber }}
(Min {{ (loanProduct.minPrincipal ? loanProduct.minPrincipal : loanProduct.principal) | formatNumber }}
: Max {{ (loanProduct.maxPrincipal ? loanProduct.maxPrincipal : loanProduct.principal) | formatNumber }})
</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Allow Approved / Disbursed Amounts Over Applied:</span>
<span fxFlex="60%">{{ loanProduct.allowApprovedDisbursedAmountsOverApplied | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.allowApprovedDisbursedAmountsOverApplied">
<span fxFlex="40%">Over Applied Amount:</span>
<span fxFlex="60%" *ngIf="loanProduct.overAppliedCalculationType === 'percentage'">{{ loanProduct.overAppliedNumber
| formatNumber
}} %</span>
<span fxFlex="60%" *ngIf="loanProduct.overAppliedCalculationType === 'flat'">{{ loanProduct.overAppliedNumber |
formatNumber }} {{
loanProduct.currencyCode }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Installment day calculation from:</span>
<span fxFlex="60%">{{ loanProduct.repaymentStartDateType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Number of Repayments:</span>
<span fxFlex="60%">{{ loanProduct.numberOfRepayments + ' (Min: ' + (loanProduct.minNumberOfRepayments ?
loanProduct.minNumberOfRepayments : loanProduct.numberOfRepayments) + ', Max: ' +
(loanProduct.maxNumberOfRepayments ? loanProduct.maxNumberOfRepayments : loanProduct.numberOfRepayments) + ')'
}}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Linked to floating interest rates:</span>
<span fxFlex="60%">{{ loanProduct.isLinkedToFloatingInterestRates | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="!loanProduct.isLinkedToFloatingInterestRates">
<span fxFlex="40%">Nominal interest rate:</span>
<span fxFlex="60%">{{ loanProduct.interestRatePerPeriod + ' (Min: ' + (loanProduct.minInterestRatePerPeriod ?
loanProduct.minInterestRatePerPeriod : loanProduct.interestRatePerPeriod) + ', Max: ' +
(loanProduct.maxInterestRatePerPeriod ? loanProduct.maxInterestRatePerPeriod : loanProduct.interestRatePerPeriod)
+ ')' + ' ' + loanProduct.interestRateFrequencyType.value }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.isLinkedToFloatingInterestRates" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Floating Lending Interest Rate:</span>
<span fxFlex="60%">{{ loanProduct.floatingRateName }}</span>
<span fxFlex="40%">Interest Rate Differential:</span>
<span fxFlex="60%">{{ loanProduct.interestRateDifferential }}</span>
<span fxFlex="40%">Floating Interest Rate Calculation Allowed:</span>
<span fxFlex="60%">{{ loanProduct.isFloatingInterestRateCalculationAllowed | yesNo }}</span>
<span fxFlex="40%">Floating Interest Rate:</span>
<span fxFlex="60%">{{ loanProduct.defaultDifferentialLendingRate + ' (Min: ' +
(loanProduct.minDifferentialLendingRate ? loanProduct.minDifferentialLendingRate :
loanProduct.defaultDifferentialLendingRate) + ', Max: ' + (loanProduct.maxDifferentialLendingRate ?
loanProduct.maxDifferentialLendingRate : loanProduct.defaultDifferentialLendingRate) + ')' }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Terms vary based on loan cycle:</span>
<span fxFlex="60%">{{ loanProduct.useBorrowerCycle | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.principalVariationsForBorrowerCycle?.length">
<h4 class="mat-h4" fxFlexFill>Principal by loan cycle</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="loanProduct.principalVariationsForBorrowerCycle">
<ng-container matColumnDef="valueConditionType">
<th mat-header-cell *matHeaderCellDef> Condition </th>
<td mat-cell *matCellDef="let variation">
{{ variation.valueConditionType.value }}
</td>
</ng-container>
<ng-container matColumnDef="borrowerCycleNumber">
<th mat-header-cell *matHeaderCellDef> Loan Cycle </th>
<td mat-cell *matCellDef="let variation">
{{ variation.borrowerCycleNumber }}
</td>
</ng-container>
<ng-container matColumnDef="minValue">
<th mat-header-cell *matHeaderCellDef> Minimum </th>
<td mat-cell *matCellDef="let variation">
{{ variation.minValue }}
</td>
</ng-container>
<ng-container matColumnDef="defaultValue">
<th mat-header-cell *matHeaderCellDef> Default </th>
<td mat-cell *matCellDef="let variation">
{{ variation.defaultValue }}
</td>
</ng-container>
<ng-container matColumnDef="maxValue">
<th mat-header-cell *matHeaderCellDef> Maximum </th>
<td mat-cell *matCellDef="let variation">
{{ variation.maxValue }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="variationsDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: variationsDisplayedColumns;"></tr>
</table>
</div>
<div fxFlexFill *ngIf="loanProduct.numberOfRepaymentVariationsForBorrowerCycle?.length">
<h4 class="mat-h4" fxFlexFill>Number of Repayments by loan cycle</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table
[dataSource]="loanProduct.numberOfRepaymentVariationsForBorrowerCycle">
<ng-container matColumnDef="valueConditionType">
<th mat-header-cell *matHeaderCellDef> Condition </th>
<td mat-cell *matCellDef="let variation">
{{ variation.valueConditionType.value }}
</td>
</ng-container>
<ng-container matColumnDef="borrowerCycleNumber">
<th mat-header-cell *matHeaderCellDef> Loan Cycle </th>
<td mat-cell *matCellDef="let variation">
{{ variation.borrowerCycleNumber }}
</td>
</ng-container>
<ng-container matColumnDef="minValue">
<th mat-header-cell *matHeaderCellDef> Minimum </th>
<td mat-cell *matCellDef="let variation">
{{ variation.minValue }}
</td>
</ng-container>
<ng-container matColumnDef="defaultValue">
<th mat-header-cell *matHeaderCellDef> Default </th>
<td mat-cell *matCellDef="let variation">
{{ variation.defaultValue }}
</td>
</ng-container>
<ng-container matColumnDef="maxValue">
<th mat-header-cell *matHeaderCellDef> Maximum </th>
<td mat-cell *matCellDef="let variation">
{{ variation.maxValue }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="variationsDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: variationsDisplayedColumns;"></tr>
</table>
</div>
<div fxFlexFill *ngIf="loanProduct.interestRateVariationsForBorrowerCycle?.length">
<h4 class="mat-h4" fxFlexFill>Nominal Interest Rate by loan cycle</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table
[dataSource]="loanProduct.interestRateVariationsForBorrowerCycle">
<ng-container matColumnDef="valueConditionType">
<th mat-header-cell *matHeaderCellDef> Condition </th>
<td mat-cell *matCellDef="let variation">
{{ variation.valueConditionType.value }}
</td>
</ng-container>
<ng-container matColumnDef="borrowerCycleNumber">
<th mat-header-cell *matHeaderCellDef> Loan Cycle </th>
<td mat-cell *matCellDef="let variation">
{{ variation.borrowerCycleNumber }}
</td>
</ng-container>
<ng-container matColumnDef="minValue">
<th mat-header-cell *matHeaderCellDef> Minimum </th>
<td mat-cell *matCellDef="let variation">
{{ variation.minValue }}
</td>
</ng-container>
<ng-container matColumnDef="defaultValue">
<th mat-header-cell *matHeaderCellDef> Default </th>
<td mat-cell *matCellDef="let variation">
{{ variation.defaultValue }}
</td>
</ng-container>
<ng-container matColumnDef="maxValue">
<th mat-header-cell *matHeaderCellDef> Maximum </th>
<td mat-cell *matCellDef="let variation">
{{ variation.maxValue }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="variationsDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: variationsDisplayedColumns;"></tr>
</table>
</div>
<div fxFlexFill>
<span fxFlex="40%">Repay Every:</span>
<span fxFlex="60%">{{ loanProduct.repaymentEvery + ' ' + loanProduct.repaymentFrequencyType.value }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.minimumDaysBetweenDisbursalAndFirstRepayment">
<span fxFlex="40%">Minimum days between disbursal and first repayment date:</span>
<span fxFlex="60%">{{ loanProduct.minimumDaysBetweenDisbursalAndFirstRepayment }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Settings</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Amortization:</span>
<span fxFlex="60%">{{ loanProduct.amortizationType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Is Equal Amortization:</span>
<span fxFlex="60%">{{ loanProduct.isEqualAmortization | yesNo }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Interest Method:</span>
<span fxFlex="60%">{{ loanProduct.interestType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Interest Calculation Period:</span>
<span fxFlex="60%">{{ loanProduct.interestCalculationPeriodType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Allow Partial Interest Calculation with same as repayment:</span>
<span fxFlex="60%">{{ loanProduct.allowPartialPeriodInterestCalculation | yesNo }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Repayment Strategy:</span>
<span fxFlex="60%" class="repayment-strategy">{{ loanProduct.transactionProcessingStrategyName }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.paymentAllocation?.length">
<span fxFlex="40%">Advanced Payment Allocation Transactions:</span>
<span fxFlex="60%">
<mat-accordion>
<mifosx-view-advance-paymeny-allocation *ngFor="let paymentAllocation of loanProduct.paymentAllocation"
[paymentAllocation]="paymentAllocation"
[advancePaymentAllocationData]="advancePaymentAllocationData">
</mifosx-view-advance-paymeny-allocation>
</mat-accordion>
</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Delinquency Bucket:</span>
<span fxFlex="60%">{{ loanProduct.delinquencyBucket.name }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Enable installment level Delinquency:</span>
<span fxFlex="60%">{{ loanProduct.enableInstallmentLevelDelinquency | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.graceOnPrincipalPayment">
<span fxFlex="40%">Grace on principal payment:</span>
<span fxFlex="60%">{{ loanProduct.graceOnPrincipalPayment }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.graceOnInterestPayment">
<span fxFlex="40%">Grace on interest payment:</span>
<span fxFlex="60%">{{ loanProduct.graceOnInterestPayment }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.graceOnInterestCharged">
<span fxFlex="40%">Interest free period:</span>
<span fxFlex="60%">{{ loanProduct.graceOnInterestCharged }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.inArrearsTolerance">
<span fxFlex="40%">Arrears tolerance:</span>
<span fxFlex="60%">{{ loanProduct.inArrearsTolerance }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Days in year:</span>
<span fxFlex="60%">{{ loanProduct.daysInYearType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Days in month:</span>
<span fxFlex="60%">{{ loanProduct.daysInMonthType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Allow fixing of the installment amount:</span>
<span fxFlex="60%">{{ loanProduct.canDefineInstallmentAmount | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.graceOnArrearsAgeing">
<span fxFlex="40%">Number of days a loan may be overdue before moving into arrears:</span>
<span fxFlex="60%">{{ loanProduct.graceOnArrearsAgeing }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.overdueDaysForNPA">
<span fxFlex="40%">Maximum number of days a loan may be overdue before becoming a NPA (non performing asset):</span>
<span fxFlex="60%">{{ loanProduct.overdueDaysForNPA }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Account moves out of NPA only after all arrears have been cleared:</span>
<span fxFlex="60%">{{ loanProduct.accountMovesOutOfNPAOnlyOnArrearsCompletion | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.principalThresholdForLastInstallment">
<span fxFlex="40%">Principal Threshold (%) for Last Instalment:</span>
<span fxFlex="60%">{{ loanProduct.principalThresholdForLastInstallment }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Variable Installments allowed:</span>
<span fxFlex="60%">{{ loanProduct.allowVariableInstallments | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.allowVariableInstallments">
<span fxFlex="40%">Variable Installments:</span>
<span fxFlex="60%">{{ '(Min: ' + loanProduct.minimumGap + ', Max: ' + (loanProduct.maximumGap ?
loanProduct.maximumGap : loanProduct.minimumGap) + ')' }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Allowed to be used for providing Topup Loans:</span>
<span fxFlex="60%">{{ loanProduct.canUseForTopup | yesNo }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Interest Recalculation</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Recalculate Interest:</span>
<span fxFlex="60%">{{ loanProduct.isInterestRecalculationEnabled | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.isInterestRecalculationEnabled" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Pre-closure interest calculation rule:</span>
<span fxFlex="60%">{{ loanProduct.interestRecalculationData.preClosureInterestCalculationStrategy.value }}</span>
<span fxFlex="40%">Advance payments adjustment type:</span>
<span fxFlex="60%">{{ loanProduct.interestRecalculationData.rescheduleStrategyType.value }}</span>
<span fxFlex="40%">Interest recalculation compounding on:</span>
<span fxFlex="60%">{{ loanProduct.interestRecalculationData.interestRecalculationCompoundingType.value }}</span>
<div fxFlexFill *ngIf="loanProduct.interestRecalculationData.interestRecalculationCompoundingType.id !== 0"
fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Frequency for compounding:</span>
<span fxFlex="60%">
{{ loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.value }}
<span
*ngIf="loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.id === 4 && loanProduct.interestRecalculationData.recalculationCompoundingFrequencyNthDay">&nbsp;&nbsp;{{
'on ' + loanProduct.interestRecalculationData.recalculationCompoundingFrequencyNthDay?.value }}</span>
<span
*ngIf="(loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.id === 4 && !loanProduct.interestRecalculationData.recalculationCompoundingFrequencyOnDay) || loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.id === 3">&nbsp;&nbsp;{{
loanProduct.interestRecalculationData.recalculationCompoundingFrequencyWeekday?.value }}</span>
<span
*ngIf="loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.id === 4 && loanProduct.interestRecalculationData.recalculationCompoundingFrequencyOnDay">&nbsp;&nbsp;{{
'on day ' + loanProduct.interestRecalculationData.recalculationCompoundingFrequencyOnDay }}</span>
</span>
<div fxFlexFill *ngIf="loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.id !== 1"
fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Frequency Interval for compounding:</span>
<span fxFlex="60%">{{ loanProduct.interestRecalculationData.recalculationCompoundingFrequencyInterval }}</span>
</div>
</div>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Frequency for recalculate Outstanding Principal:</span>
<span fxFlex="60%">
{{ loanProduct.interestRecalculationData.recalculationRestFrequencyType.value }}
<span
*ngIf="loanProduct.interestRecalculationData.recalculationRestFrequencyType.id === 4 && loanProduct.interestRecalculationData.recalculationRestFrequencyNthDay">&nbsp;&nbsp;{{
'on ' + loanProduct.interestRecalculationData.recalculationRestFrequencyNthDay?.value }}</span>
<span
*ngIf="(loanProduct.interestRecalculationData.recalculationRestFrequencyType.id === 4 && !loanProduct.interestRecalculationData.recalculationRestFrequencyOnDay) || loanProduct.interestRecalculationData.recalculationRestFrequencyType.id === 3">&nbsp;&nbsp;{{
loanProduct.interestRecalculationData.recalculationRestFrequencyWeekday?.value }}</span>
<span
*ngIf="loanProduct.interestRecalculationData.recalculationRestFrequencyType.id === 4 && loanProduct.interestRecalculationData.recalculationRestFrequencyOnDay">&nbsp;&nbsp;{{
'on day ' + loanProduct.interestRecalculationData.recalculationRestFrequencyOnDay }}</span>
</span>
</div>
<div fxFlexFill *ngIf="loanProduct.interestRecalculationData.recalculationRestFrequencyType.id !== 1"
fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Frequency Interval for recalculation:</span>
<span fxFlex="60%">{{ loanProduct.interestRecalculationData.recalculationRestFrequencyInterval }}</span>
<div fxFlexFill *ngIf="loanProduct.recalculationRestFrequencyDate">
<span fxFlex="40%">Rest Frequency Date:</span>
<span fxFlex="60%">{{ loanProduct.interestRecalculationData.recalculationRestFrequencyDate }}</span>
</div>
</div>
<div fxFlexFill>
<span fxFlex="40%">Is Arrears recognization based on original schedule:</span>
<span fxFlex="60%">{{ loanProduct.isArrearsBasedOnOriginalSchedule | yesNo }}</span>
</div>
</div>
<h3 class="mat-h3" fxFlexFill>Guarantee Requirements</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Place Guarantee Funds On-Hold:</span>
<span fxFlex="60%">{{ loanProduct.holdGuaranteeFunds | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.holdGuaranteeFunds" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Mandatory Guarantee(%):</span>
<span fxFlex="60%">{{ loanProduct.productGuaranteeData.mandatoryGuarantee }}</span>
<div fxFlexFill *ngIf="loanProduct.productGuaranteeData.minimumGuaranteeFromOwnFunds">
<span fxFlex="40%">Minimum Guarantee from Own Funds(%):</span>
<span fxFlex="60%">{{ loanProduct.productGuaranteeData.minimumGuaranteeFromOwnFunds }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.productGuaranteeData.minimumGuaranteeFromGuarantor">
<span fxFlex="40%">Minimum Guarantee from Guarantor Funds(%):</span>
<span fxFlex="60%">{{ loanProduct.productGuaranteeData.minimumGuaranteeFromGuarantor }}</span>
</div>
</div>
<h3 class="mat-h3" fxFlexFill>Loan Tranche Details</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Enable Multiple Disbursals:</span>
<span fxFlex="60%">{{ loanProduct.multiDisburseLoan | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.multiDisburseLoan" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Maximum Tranche count:</span>
<span fxFlex="60%">{{ loanProduct.maxTrancheCount }}</span>
<div fxFlexFill *ngIf="loanProduct.outstandingLoanBalance">
<span fxFlex="40%">Maximum allowed outstanding balance:</span>
<span fxFlex="60%">{{ loanProduct.outstandingLoanBalance }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Disallow Expected Disbursements:</span>
<span fxFlex="60%">{{ loanProduct.disallowExpectedDisbursements | yesNo }}</span>
</div>
</div>
<h3 class="mat-h3" fxFlexFill>Down Payments</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Enable Down Payments:</span>
<span fxFlex="60%">{{ loanProduct.enableDownPayment | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.enableDownPayment" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Disbursed Amount Percentage Down Payment (%):</span>
<span fxFlex="60%">{{ loanProduct.disbursedAmountPercentageForDownPayment }} %</span>
</div>
<div fxFlexFill *ngIf="loanProduct.enableDownPayment" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Enable Auto Repayment for Down Payment:</span>
<span fxFlex="60%">{{ loanProduct.enableAutoRepaymentForDownPayment | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.enableDownPayment" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Do not extend loan schedule for multi disbursal:</span>
<span fxFlex="60%">{{ loanProduct.disableScheduleExtensionForDownPayment | yesNo }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Event Settings</h3>
<div fxFlexFill>
<span fxFlex="40%">Use the Global Configurations values to the Repayment Event (notifications):</span>
<span fxFlex="60%">{{ useDueForRepaymentsConfigurations | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.dueDaysForRepaymentEvent">
<span fxFlex="40%">Due days for repayment event:</span>
<span fxFlex="60%">{{ loanProduct.dueDaysForRepaymentEvent | number }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.overDueDaysForRepaymentEvent">
<span fxFlex="40%">OverDue days for repayment event:</span>
<span fxFlex="60%">{{ loanProduct.overDueDaysForRepaymentEvent | number }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Configurable Terms and Settings</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Allow overriding select terms and settings in loan accounts:</span>
<span fxFlex="60%">{{ loanProduct.allowAttributeConfiguration | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.allowAttributeConfiguration" fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Amortization:</span>
<span fxFlex="60%">{{ loanProduct.allowAttributeOverrides.amortizationType | yesNo }}</span>
<span fxFlex="40%">Interest method:</span>
<span fxFlex="60%">{{ loanProduct.allowAttributeOverrides.interestType | yesNo }}</span>
<span fxFlex="40%">Repayment strategy:</span>
<span fxFlex="60%">{{ loanProduct.allowAttributeOverrides.transactionProcessingStrategyCode | yesNo }}</span>
<span fxFlex="40%">Interest calculation period:</span>
<span fxFlex="60%">{{ loanProduct.allowAttributeOverrides.interestCalculationPeriodType | yesNo }}</span>
<span fxFlex="40%">Arrears tolerance:</span>
<span fxFlex="60%">{{ loanProduct.allowAttributeOverrides.inArrearsTolerance | yesNo }}</span>
<span fxFlex="40%">Repaid every:</span>
<span fxFlex="60%">{{ loanProduct.allowAttributeOverrides.repaymentEvery | yesNo }}</span>
<span fxFlex="40%">Moratorium:</span>
<span fxFlex="60%">{{ loanProduct.allowAttributeOverrides.graceOnPrincipalAndInterestPayment | yesNo }}</span>
<span fxFlex="40%">Number of days a loan may be overdue before moving into arrears:</span>
<span fxFlex="60%">{{ loanProduct.allowAttributeOverrides.graceOnArrearsAgeing | yesNo }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.charges.length" fxLayout="row wrap" fxLayout.lt-md="column">
<h3 class="mat-h3" fxFlexFill>Charges</h3>
<mat-divider [inset]="true"></mat-divider>
<table fxFlexFill class="mat-elevation-z1" mat-table
[dataSource]="loanProduct.charges | chargesPenaltyFilter:false">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let charge">
{{ charge.name + ', ' + charge.currency.displaySymbol }}
</td>
</ng-container>
<ng-container matColumnDef="chargeCalculationType">
<th mat-header-cell *matHeaderCellDef> Type </th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeCalculationType.value }}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef> Amount </th>
<td mat-cell *matCellDef="let charge">
{{ charge.amount }}
</td>
</ng-container>
<ng-container matColumnDef="chargeTimeType">
<th mat-header-cell *matHeaderCellDef> Collected On </th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeTimeType.value }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chargesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chargesDisplayedColumns;"></tr>
</table>
<h3 class="mat-h3" fxFlexFill>Overdue Charges</h3>
<mat-divider [inset]="true"></mat-divider>
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="loanProduct.charges | chargesPenaltyFilter:true">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let overdueCharge">
{{ overdueCharge.name + ', ' + overdueCharge.currency.displaySymbol }}
</td>
</ng-container>
<ng-container matColumnDef="chargeCalculationType">
<th mat-header-cell *matHeaderCellDef> Type </th>
<td mat-cell *matCellDef="let overdueCharge">
{{ overdueCharge.chargeCalculationType.value }}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef> Amount </th>
<td mat-cell *matCellDef="let overdueCharge">
{{ overdueCharge.amount }}
</td>
</ng-container>
<ng-container matColumnDef="chargeTimeType">
<th mat-header-cell *matHeaderCellDef> Collected On </th>
<td mat-cell *matCellDef="let overdueCharge">
{{ overdueCharge.chargeTimeType.value }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chargesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chargesDisplayedColumns;"></tr>
</table>
</div>
<h3 class="mat-h3" fxFlexFill>Accounting</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Type:</span>
<span fxFlex="60%">{{ loanProduct.accountingRule.value }}</span>
</div>
<div fxFlexFill *ngIf="loanProduct.accountingRule.id >= 2 && loanProduct.accountingRule.id <= 4" fxLayout="row wrap"
fxLayout.lt-md="column">
<h4 fxFlexFill class="mat-h4">Assets / Liabilities</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Fund source:</span>
<span fxFlex="60%">({{loanProduct.accountingMappings.fundSourceAccount.glCode}}) {{
loanProduct.accountingMappings.fundSourceAccount.name }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Assets</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Loan portfolio:</span>
<span fxFlex="60%">({{loanProduct.accountingMappings.loanPortfolioAccount.glCode}}) {{
loanProduct.accountingMappings.loanPortfolioAccount.name }}</span>
<div fxFlexFill *ngIf="loanProduct.accountingRule.id === 3 || loanProduct.accountingRule.id === 4"
fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Interest Receivable:</span>
<span fxFlex="60%">({{loanProduct.accountingMappings.receivableInterestAccount.glCode}}) {{
loanProduct.accountingMappings.receivableInterestAccount.name }}</span>
<span fxFlex="40%">Fees Receivable:</span>
<span fxFlex="60%">({{loanProduct.accountingMappings.receivableFeeAccount.glCode}}) {{
loanProduct.accountingMappings.receivableInterestAccount.name }}</span>
<span fxFlex="40%">Penalties Receivable:</span>
<span fxFlex="60%">({{loanProduct.accountingMappings.receivablePenaltyAccount.glCode}}) {{
loanProduct.accountingMappings.receivablePenaltyAccount.name }}</span>
</div>
<span fxFlex="40%">Transfer in suspense:</span>
<span fxFlex="60%">({{loanProduct.accountingMappings.transfersInSuspenseAccount.glCode}}) {{
loanProduct.accountingMappings.transfersInSuspenseAccount.name }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Income</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Income from Interest:</span>
<span fxFlex="60%">({{loanProduct.accountingMappings.interestOnLoanAccount.glCode}}) {{
loanProduct.accountingMappings.interestOnLoanAccount.name }}</span>
<span fxFlex="40%">Income from fees:</span>
<span fxFlex="60%">({{loanProduct.accountingMappings.incomeFromFeeAccount.glCode}}) {{
loanProduct.accountingMappings.incomeFromFeeAccount.name }}</span>
<span fxFlex="40%">Income from penalties:</span>
<span fxFlex="60%">({{loanProduct.accountingMappings.incomeFromPenaltyAccount.glCode}}) {{
loanProduct.accountingMappings.incomeFromPenaltyAccount.name }}</span>
<span fxFlex="40%">Income from Recovery Repayments:</span>
<span fxFlex="60%">({{loanProduct.accountingMappings.incomeFromRecoveryAccount.glCode}}) {{
loanProduct.accountingMappings.incomeFromRecoveryAccount.name }}</span>
<span *ngIf="loanProduct.accountingMappings.incomeFromChargeOffInterestAccount" fxFlex="40%">Income from ChargeOff
Interest:</span>
<span *ngIf="loanProduct.accountingMappings.incomeFromChargeOffInterestAccount" fxFlex="60%">
({{loanProduct.accountingMappings.incomeFromChargeOffInterestAccount.glCode}}) {{
loanProduct.accountingMappings.incomeFromChargeOffInterestAccount.name }}</span>
<span fxFlex="40%" *ngIf="loanProduct.accountingMappings.incomeFromChargeOffFeesAccount">Income from ChargeOff
Fees:</span>
<span fxFlex="60%" *ngIf="loanProduct.accountingMappings.incomeFromChargeOffFeesAccount">
({{loanProduct.accountingMappings.incomeFromChargeOffFeesAccount.glCode}}) {{
loanProduct.accountingMappings.incomeFromChargeOffFeesAccount.name }}</span>
<span fxFlex="40%" *ngIf="loanProduct.accountingMappings.incomeFromChargeOffPenaltyAccount">Income from ChargeOff
Penalty:</span>
<span fxFlex="60%" *ngIf="loanProduct.accountingMappings.incomeFromChargeOffPenaltyAccount">
({{loanProduct.accountingMappings.incomeFromChargeOffPenaltyAccount.glCode}}) {{
loanProduct.accountingMappings.incomeFromChargeOffPenaltyAccount.name }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Expenses</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Losses written off:</span>
<span fxFlex="60%">({{loanProduct.accountingMappings.writeOffAccount.glCode}}) {{
loanProduct.accountingMappings.writeOffAccount.name }}</span>
<span fxFlex="40%">Expenses from Goodwill Credit:</span>
<span fxFlex="60%">({{loanProduct.accountingMappings.goodwillCreditAccount.glCode}}) {{
loanProduct.accountingMappings.goodwillCreditAccount.name }}</span>
<span *ngIf="loanProduct.accountingMappings.chargeOffExpenseAccount" fxFlex="40%">ChargeOff Expense:</span>
<span *ngIf="loanProduct.accountingMappings.chargeOffExpenseAccount" fxFlex="60%">
({{loanProduct.accountingMappings.chargeOffExpenseAccount.glCode}}) {{
loanProduct.accountingMappings.chargeOffExpenseAccount.name }}</span>
<span *ngIf="loanProduct.accountingMappings.chargeOffFraudExpenseAccount" fxFlex="40%">ChargeOff Fraud
Expense:</span>
<span *ngIf="loanProduct.accountingMappings.chargeOffFraudExpenseAccount" fxFlex="60%">
({{loanProduct.accountingMappings.chargeOffFraudExpenseAccount.glCode}}) {{
loanProduct.accountingMappings.chargeOffFraudExpenseAccount.name }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Liabilities</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Over payment liability:</span>
<span fxFlex="60%">({{loanProduct.accountingMappings.overpaymentLiabilityAccount.glCode}}) {{
loanProduct.accountingMappings.overpaymentLiabilityAccount.name }}</span>
</div>
<div
*ngIf="loanProduct.paymentChannelToFundSourceMappings?.length || loanProduct.feeToIncomeAccountMappings?.length || loanProduct.penaltyToIncomeAccountMappings?.length"
fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<h3 class="mat-h3" fxFlexFill>Advanced Accounting Rules</h3>
<mat-divider [inset]="true"></mat-divider>
<div *ngIf="loanProduct.paymentChannelToFundSourceMappings?.length" fxFlexFill fxLayout="row wrap"
fxLayout.lt-md="column">
<h4 class="mat-h4" fxFlexFill>Fund Sources for Payment Channels</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table
[dataSource]="loanProduct.paymentChannelToFundSourceMappings">
<ng-container matColumnDef="paymentTypeId">
<th mat-header-cell *matHeaderCellDef> Payment Type </th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.paymentType.name }}
</td>
</ng-container>
<ng-container matColumnDef="fundSourceAccountId">
<th mat-header-cell *matHeaderCellDef> Fund Source </th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.fundSourceAccount.name }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="paymentFundSourceDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: paymentFundSourceDisplayedColumns;"></tr>
</table>
</div>
<div *ngIf="loanProduct.feeToIncomeAccountMappings?.length" fxFlexFill fxLayout="row wrap"
fxLayout.lt-md="column">
<h4 class="mat-h4" fxFlexFill>Fees to Specific Income Accounts</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="loanProduct.feeToIncomeAccountMappings">
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef> Fees </th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef> Income Account </th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.incomeAccount.name }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns;"></tr>
</table>
</div>
<div *ngIf="loanProduct.penaltyToIncomeAccountMappings?.length" fxFlexFill fxLayout="row wrap"
fxLayout.lt-md="column">
<h4 class="mat-h4" fxFlexFill>Penalties to Specific Income Accounts</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="loanProduct.penaltyToIncomeAccountMappings">
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef> Penalty </th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef> Income Account </th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.incomeAccount.name }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns;"></tr>
</table>
</div>
</div>
</div>
</div>
<mifosx-loan-product-summary
[loanProduct]="loanProduct"
[useDueForRepaymentsConfigurations]="useDueForRepaymentsConfigurations"
[paymentAllocations]="loanProduct.paymentAllocation"
>
</mifosx-loan-product-summary>
@@ -1,26 +0,0 @@
@import "assets/styles/helper";
.tab-container {
padding: 1%;
margin: 1%;
div: {
margin-top: 3px;
}
}
.mat-h3 {
margin-top: 10px !important;
font-weight: 300;
color: $status-approved;
}
.mat-h4 {
margin-top: 10px !important;
font-weight: 200;
color: $status-approved;
}
.repayment-strategy {
color: $status-approved;
}
@@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { AdvancePaymentAllocationData } from '../../loan-product-stepper/loan-product-payment-strategy-step/payment-allocation-model';
import { LoanProduct } from '../../models/loan-product.model';
@Component({
selector: 'mifosx-general-tab',
@@ -9,26 +9,13 @@ import { AdvancePaymentAllocationData } from '../../loan-product-stepper/loan-pr
})
export class GeneralTabComponent implements OnInit {
loanProduct: any;
variationsDisplayedColumns: string[] = ['valueConditionType', 'borrowerCycleNumber', 'minValue', 'defaultValue', 'maxValue'];
chargesDisplayedColumns: string[] = ['name', 'chargeCalculationType', 'amount', 'chargeTimeType'];
paymentFundSourceDisplayedColumns: string[] = ['paymentTypeId', 'fundSourceAccountId'];
feesPenaltyIncomeDisplayedColumns: string[] = ['chargeId', 'incomeAccountId'];
advancePaymentAllocationData: AdvancePaymentAllocationData;
loanProduct: LoanProduct;
useDueForRepaymentsConfigurations = false;
constructor(private route: ActivatedRoute) {
this.route.data.subscribe((data: { loanProduct: any }) => {
this.loanProduct = data.loanProduct;
this.useDueForRepaymentsConfigurations = (!this.loanProduct.dueDaysForRepaymentEvent && !this.loanProduct.overDueDaysForRepaymentEvent);
this.advancePaymentAllocationData = {
transactionTypes: this.loanProduct.advancedPaymentAllocationTransactionTypes,
allocationTypes: this.loanProduct.advancedPaymentAllocationTypes,
futureInstallmentAllocationRules: this.loanProduct.advancedPaymentAllocationFutureInstallmentAllocationRules
};
});
}
+3 -1
View File
@@ -119,6 +119,7 @@ import { ShareProductDatatableTabComponent } from './share-products/view-share-p
import { LoanProductPaymentStrategyStepComponent } from './loan-products/loan-product-stepper/loan-product-payment-strategy-step/loan-product-payment-strategy-step.component';
import { ViewAdvancePaymenyAllocationComponent } from './loan-products/view-loan-product/shared/view-advance-paymeny-allocation/view-advance-paymeny-allocation.component';
import { AdvancePaymentAllocationTabComponent } from './loan-products/loan-product-stepper/loan-product-payment-strategy-step/advance-payment-allocation-tab/advance-payment-allocation-tab.component';
import { LoanProductSummaryComponent } from './loan-products/common/loan-product-summary/loan-product-summary.component';
/**
* Products Module
@@ -245,7 +246,8 @@ import { AdvancePaymentAllocationTabComponent } from './loan-products/loan-produ
ShareProductGeneralTabComponent,
ShareProductDatatableTabComponent,
ViewAdvancePaymenyAllocationComponent,
AdvancePaymentAllocationTabComponent
AdvancePaymentAllocationTabComponent,
LoanProductSummaryComponent
]
})
export class ProductsModule { }
@@ -73,7 +73,7 @@ export class TransactionsTabComponent implements OnInit {
*/
showTransactions(transactionsData: any) {
if (transactionsData.transfer) {
this.router.navigate([`account-transfers/account-transfers/${transactionsData.transfer.id}`], { relativeTo: this.route });
this.router.navigate([`../transfer-funds/account-transfers/${transactionsData.transfer.id}`], { relativeTo: this.route });
} else {
this.router.navigate([transactionsData.id, 'general'], { relativeTo: this.route });
}
@@ -1,10 +1,12 @@
<div fxLayoutAlign="end" class="container m-b-20" fxLayoutGap="2%"
*ngIf="!(transactionData.interestedPostedAsOn === false && (transactionData.transactionType.id === 17 || transactionData.transactionType.id === 3))">
<span *mifosxHasPermission="'ADJUSTTRANSACTION_SAVINGSACCOUNT'">
<button mat-raised-button color="primary" *ngIf="transactionData.transactionType.value == 'Transfer' || transactionData.reversed == 'true'
|| transactionData.transactionType.id==3 || transactionData.transactionType.id==17" [routerLink]="'edit'">
<fa-icon icon="edit" class="m-r-10"></fa-icon>Edit
</button>
<div fxLayoutAlign="end" class="container m-b-20" fxLayoutGap="2%">
<span
*ngIf="!(transactionData.interestedPostedAsOn === false && (transactionData.transactionType.id === 17 || transactionData.transactionType.id === 3))">
<span *mifosxHasPermission="'ADJUSTTRANSACTION_SAVINGSACCOUNT'">
<button mat-raised-button color="primary" *ngIf="transactionData.transactionType.value == 'Transfer' || transactionData.reversed == 'true'
|| transactionData.transactionType.id==3 || transactionData.transactionType.id==17" [routerLink]="'edit'">
<fa-icon icon="edit" class="m-r-10"></fa-icon>Edit
</button>
</span>
</span>
<span *ngIf="!transactionData.reversed && transactionData.transactionType.amountHold">
<button mat-raised-button color="primary" *mifosxHasPermission="'RELEASEAMOUNT_SAVINGSACCOUNT'"
@@ -12,10 +14,12 @@
<fa-icon icon="lock-open" class="m-r-10"></fa-icon>Release Amount
</button>
</span>
<button mat-raised-button color="warn" *mifosxHasPermission="'UNDOTRANSACTION_SAVINGSACCOUNT'"
(click)="undoTransaction()" [disabled]="transactionData.reversed">
<fa-icon icon="undo" class="m-r-10"></fa-icon>Undo
</button>
<span *ngIf="allowUndo()">
<button mat-raised-button color="warn" *mifosxHasPermission="'UNDOTRANSACTION_SAVINGSACCOUNT'"
(click)="undoTransaction()">
<fa-icon icon="undo" class="m-r-10"></fa-icon>Undo
</button>
</span>
</div>
<div class="container">
@@ -33,6 +33,13 @@ export class SavingsTransactionGeneralTabComponent implements OnInit {
ngOnInit(): void {
}
allowUndo(): boolean {
if (this.transactionData.reversed && this.transactionData.transactionType.amountHold) {
return false;
}
return !this.transactionData.reversed;
}
releaseAmount(): void {
const releaseAmountDialogRef = this.dialog.open(ReleaseAmountDialogComponent);
releaseAmountDialogRef.afterClosed().subscribe((response: any) => {
+71
View File
@@ -0,0 +1,71 @@
import { OptionData } from './option-data.model';
export interface Currency {
code: string;
name: string;
decimalPlaces?: number;
inMultiplesOf?: number;
displaySymbol?: string;
nameCode?: string;
displayLabel?: string;
}
export interface GLAccount {
id: number;
name: string;
glCode: string;
description: string;
disabled: boolean;
manualEntriesAllowed: boolean;
type: OptionData;
usage: OptionData;
}
export interface AccountingMapping {
id: number;
name: string;
glCode: string;
}
export interface ChargeToIncomeAccountMapping {
charge: Charge;
incomeAccount: AccountingMapping;
}
export interface PaymentChannelToFundSourceMapping {
paymentType: PaymentType;
fundSourceAccount: AccountingMapping;
}
export interface PaymentType {
id: number;
name: string;
isSystemDefined: boolean;
}
export interface PaymentTypeOption {
id: number;
name: string;
description: string;
isCashPayment: boolean;
isSystemDefined: boolean;
position: number;
}
export interface Charge {
id: number;
name: string;
active?: boolean;
penalty: boolean;
freeWithdrawal?: boolean;
freeWithdrawalChargeFrequency?: number;
restartFrequency?: number;
restartFrequencyEnum?: number;
isPaymentType?: boolean;
currency?: Currency;
amount?: number;
chargeTimeType?: Charge;
chargeAppliesTo?: Charge;
chargeCalculationType?: Charge;
chargePaymentMode?: Charge;
}
@@ -0,0 +1,10 @@
export interface OptionData {
code: string;
id: number;
value: string;
}
export interface CodeName {
code: string;
name: string;
}