Down payment configuration for Loan Products (#1836)
Co-authored-by: Jose Alberto Hernandez <alberto@blue-daemon.local>
This commit is contained in:
co-authored by
Jose Alberto Hernandez
parent
a9b8543120
commit
861cf7a000
@@ -9,9 +9,7 @@ import { extract } from '../core/i18n/i18n.service';
|
||||
|
||||
/** Custom Components */
|
||||
import { IndividualCollectionSheetComponent } from './individual-collection-sheet/individual-collection-sheet.component';
|
||||
|
||||
/** Custom Resolvers */
|
||||
import { GetOfficesResolver } from './individual-collection-sheet/get-offices.resolver';
|
||||
import { OfficesResolver } from 'app/organization/offices/common-resolvers/offices.resolver';
|
||||
|
||||
const routes: Routes = [
|
||||
Route.withShell([
|
||||
@@ -23,7 +21,7 @@ const routes: Routes = [
|
||||
data: { title: extract('Individual Collection Sheet'), breadcrumb: 'Individual Collection Sheet', routeParamBreadcrumb: false },
|
||||
component: IndividualCollectionSheetComponent,
|
||||
resolve: {
|
||||
officesData: GetOfficesResolver
|
||||
officesData: OfficesResolver
|
||||
}
|
||||
},
|
||||
]
|
||||
@@ -33,7 +31,7 @@ const routes: Routes = [
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
providers: [GetOfficesResolver],
|
||||
providers: [],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class CollectionsRoutingModule { }
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/** Angular Imports */
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Resolve } from '@angular/router';
|
||||
|
||||
/** rxjs Imports */
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
/** Custom Services */
|
||||
import { CollectionsService } from '../collections.service';
|
||||
|
||||
/**
|
||||
* Returns all the offices data.
|
||||
*/
|
||||
@Injectable()
|
||||
export class GetOfficesResolver implements Resolve<Object> {
|
||||
|
||||
/**
|
||||
* @param {CollectionsService} CollectionsService Collections service.
|
||||
*/
|
||||
constructor(private collectionsService: CollectionsService) { }
|
||||
|
||||
/**
|
||||
* Returns the Collection Office Data.
|
||||
* @returns {Observable<any>}
|
||||
*/
|
||||
resolve(): Observable<any> {
|
||||
return this.collectionsService.getOffices();
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -50,7 +50,7 @@
|
||||
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
|
||||
<button type="button" mat-raised-button [routerLink]="['../']">Cancel</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!collectionSheetForm.valid">
|
||||
<fa-icon icon="search"></fa-icon> Collection Sheet
|
||||
<fa-icon icon="search" class="m-r-10"></fa-icon> Collection Sheet
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
|
||||
|
||||
@@ -27,4 +27,4 @@
|
||||
<mifosx-edit-repayment-schedule *ngIf="actions['Edit Repayment Schedule']"></mifosx-edit-repayment-schedule>
|
||||
<mifosx-charge-off [dataObject]="actionButtonData" *ngIf="actions['Charge-Off']"></mifosx-charge-off>
|
||||
<mifosx-undo-command [actionName]="actionName" *ngIf="actions['Undo Charge-Off']"></mifosx-undo-command>
|
||||
<mifosx-asset-transfer-loan *ngIf="actions['Sale Loan'] || actions['Buy Back Loan']"></mifosx-asset-transfer-loan>
|
||||
<mifosx-asset-transfer-loan *ngIf="actions['Sell Loan'] || actions['Buy Back Loan']"></mifosx-asset-transfer-loan>
|
||||
|
||||
@@ -43,7 +43,7 @@ export class LoanAccountActionsComponent {
|
||||
'Edit Repayment Schedule': boolean,
|
||||
'Charge-Off': boolean,
|
||||
'Undo Charge-Off': boolean,
|
||||
'Sale Loan': boolean,
|
||||
'Sell Loan': boolean,
|
||||
'Buy Back Loan': boolean
|
||||
} = {
|
||||
'Close': false,
|
||||
@@ -76,7 +76,7 @@ export class LoanAccountActionsComponent {
|
||||
'Edit Repayment Schedule': false,
|
||||
'Charge-Off': false,
|
||||
'Undo Charge-Off': false,
|
||||
'Sale Loan': false,
|
||||
'Sell Loan': false,
|
||||
'Buy Back Loan': false
|
||||
};
|
||||
|
||||
|
||||
@@ -191,7 +191,7 @@ export class LoansAccountButtonConfiguration {
|
||||
taskPermissionName: 'RECOVERGUARANTEES_LOAN',
|
||||
},
|
||||
{
|
||||
name: 'Sale Loan',
|
||||
name: 'Sell Loan',
|
||||
taskPermissionName: 'SALE_LOAN',
|
||||
}
|
||||
];
|
||||
|
||||
+14
@@ -473,6 +473,20 @@
|
||||
<span fxFlex="60%">{{ loanProduct.disallowExpectedDisbursements ? 'Yes' : 'No' }}</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 ? 'Yes' : 'No' }}</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>
|
||||
|
||||
<h3 class="mat-h3" fxFlexFill>Event Settings</h3>
|
||||
|
||||
<div fxFlexFill>
|
||||
|
||||
+23
-1
@@ -399,7 +399,7 @@
|
||||
<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>
|
||||
<mat-error *ngIf="loanProductSettingsForm.controls.maxTrancheCount.hasError('required')">
|
||||
Maximum Tranche count is <strong>required</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
@@ -416,6 +416,28 @@
|
||||
|
||||
<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>
|
||||
</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>
|
||||
<div fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||
|
||||
+20
-2
@@ -1,6 +1,7 @@
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms';
|
||||
import { LoanProducts } from '../../loan-products';
|
||||
import { rangeValidator } from 'app/shared/validators/percentage.validator';
|
||||
|
||||
@Component({
|
||||
selector: 'mifosx-loan-product-settings-step',
|
||||
@@ -89,10 +90,17 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
||||
'maxTrancheCount': this.loanProductsTemplate.maxTrancheCount,
|
||||
'outstandingLoanBalance': this.loanProductsTemplate.outstandingLoanBalance,
|
||||
'dueDaysForRepaymentEvent': this.loanProductsTemplate.dueDaysForRepaymentEvent,
|
||||
'overDueDaysForRepaymentEvent': this.loanProductsTemplate.overDueDaysForRepaymentEvent
|
||||
'overDueDaysForRepaymentEvent': this.loanProductsTemplate.overDueDaysForRepaymentEvent,
|
||||
'enableDownPayment': this.loanProductsTemplate.enableDownPayment
|
||||
});
|
||||
|
||||
if (this.loanProductsTemplate.delinquencyBucket) {
|
||||
this.loanProductSettingsForm.patchValue({
|
||||
'disbursedAmountPercentageForDownPayment': this.loanProductsTemplate.disbursedAmountPercentageForDownPayment || 0
|
||||
});
|
||||
}
|
||||
|
||||
if (this.loanProductsTemplate.enableDownPayment) {
|
||||
this.loanProductSettingsForm.patchValue({
|
||||
'delinquencyBucketId': this.loanProductsTemplate.delinquencyBucket.id
|
||||
});
|
||||
@@ -187,7 +195,8 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
||||
}),
|
||||
'delinquencyBucketId': ['', Validators.required],
|
||||
'dueDaysForRepaymentEvent': [''],
|
||||
'overDueDaysForRepaymentEvent': ['']
|
||||
'overDueDaysForRepaymentEvent': [''],
|
||||
'enableDownPayment': [false]
|
||||
});
|
||||
}
|
||||
|
||||
@@ -332,6 +341,15 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
||||
}
|
||||
});
|
||||
|
||||
this.loanProductSettingsForm.get('enableDownPayment').valueChanges
|
||||
.subscribe(enableDownPayment => {
|
||||
if (enableDownPayment) {
|
||||
this.loanProductSettingsForm.addControl('disbursedAmountPercentageForDownPayment', new FormControl(0, [Validators.required, rangeValidator(0, 100) ]));
|
||||
} else {
|
||||
this.loanProductSettingsForm.removeControl('disbursedAmountPercentageForDownPayment');
|
||||
}
|
||||
});
|
||||
|
||||
this.loanProductSettingsForm.get('allowAttributeConfiguration').valueChanges
|
||||
.subscribe((allowAttributeConfiguration: any) => {
|
||||
if (allowAttributeConfiguration) {
|
||||
|
||||
+14
@@ -506,6 +506,20 @@
|
||||
</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 ? 'Yes' : 'No' }}</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>
|
||||
|
||||
<h3 class="mat-h3" fxFlexFill>Event Settings</h3>
|
||||
|
||||
<div fxFlexFill>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { AbstractControl, ValidatorFn } from '@angular/forms';
|
||||
|
||||
export function rangeValidator(min: number, max: number): ValidatorFn {
|
||||
|
||||
return (control: AbstractControl): { [key: string]: boolean } | null => {
|
||||
if (control.value !== undefined && (isNaN(control.value) || control.value < min || control.value > max)) {
|
||||
return { 'range': true };
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user