From 861cf7a0002c40bda2469c4108d454e6f68456b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Alberto=20Hern=C3=A1ndez?= <44206706+josehernandezfintecheandomx@users.noreply.github.com> Date: Mon, 7 Aug 2023 16:41:50 -0600 Subject: [PATCH] Down payment configuration for Loan Products (#1836) Co-authored-by: Jose Alberto Hernandez --- .../collections/collections-routing.module.ts | 8 ++--- .../get-offices.resolver.ts | 30 ------------------- ...individual-collection-sheet.component.html | 2 +- .../loan-account-actions.component.html | 2 +- .../loan-account-actions.component.ts | 4 +-- .../loans-view/loan-accounts-button-config.ts | 2 +- .../loan-product-preview-step.component.html | 14 +++++++++ .../loan-product-settings-step.component.html | 24 ++++++++++++++- .../loan-product-settings-step.component.ts | 22 ++++++++++++-- .../general-tab/general-tab.component.html | 14 +++++++++ .../shared/validators/percentage.validator.ts | 11 +++++++ 11 files changed, 90 insertions(+), 43 deletions(-) delete mode 100644 src/app/collections/individual-collection-sheet/get-offices.resolver.ts create mode 100644 src/app/shared/validators/percentage.validator.ts diff --git a/src/app/collections/collections-routing.module.ts b/src/app/collections/collections-routing.module.ts index 84841176c..9177909e0 100644 --- a/src/app/collections/collections-routing.module.ts +++ b/src/app/collections/collections-routing.module.ts @@ -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 { } diff --git a/src/app/collections/individual-collection-sheet/get-offices.resolver.ts b/src/app/collections/individual-collection-sheet/get-offices.resolver.ts deleted file mode 100644 index dd5e6d841..000000000 --- a/src/app/collections/individual-collection-sheet/get-offices.resolver.ts +++ /dev/null @@ -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 { - - /** - * @param {CollectionsService} CollectionsService Collections service. - */ - constructor(private collectionsService: CollectionsService) { } - - /** - * Returns the Collection Office Data. - * @returns {Observable} - */ - resolve(): Observable { - return this.collectionsService.getOffices(); - } - -} diff --git a/src/app/collections/individual-collection-sheet/individual-collection-sheet.component.html b/src/app/collections/individual-collection-sheet/individual-collection-sheet.component.html index 0dcb738ea..ea57ada4f 100644 --- a/src/app/collections/individual-collection-sheet/individual-collection-sheet.component.html +++ b/src/app/collections/individual-collection-sheet/individual-collection-sheet.component.html @@ -50,7 +50,7 @@ diff --git a/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.html b/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.html index 4b73cd76d..877e18f54 100644 --- a/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.html +++ b/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.html @@ -27,4 +27,4 @@ - + diff --git a/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.ts b/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.ts index 40a018638..9cfb7c247 100644 --- a/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.ts @@ -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 }; diff --git a/src/app/loans/loans-view/loan-accounts-button-config.ts b/src/app/loans/loans-view/loan-accounts-button-config.ts index fa5f9ac37..95677fce4 100644 --- a/src/app/loans/loans-view/loan-accounts-button-config.ts +++ b/src/app/loans/loans-view/loan-accounts-button-config.ts @@ -191,7 +191,7 @@ export class LoansAccountButtonConfiguration { taskPermissionName: 'RECOVERGUARANTEES_LOAN', }, { - name: 'Sale Loan', + name: 'Sell Loan', taskPermissionName: 'SALE_LOAN', } ]; diff --git a/src/app/products/loan-products/loan-product-stepper/loan-product-preview-step/loan-product-preview-step.component.html b/src/app/products/loan-products/loan-product-stepper/loan-product-preview-step/loan-product-preview-step.component.html index 6ef69df95..00285a45f 100644 --- a/src/app/products/loan-products/loan-product-stepper/loan-product-preview-step/loan-product-preview-step.component.html +++ b/src/app/products/loan-products/loan-product-stepper/loan-product-preview-step/loan-product-preview-step.component.html @@ -473,6 +473,20 @@ {{ loanProduct.disallowExpectedDisbursements ? 'Yes' : 'No' }} +

Down Payments

+ + + +
+ Enable Down Payments: + {{ loanProduct.enableDownPayment ? 'Yes' : 'No' }} +
+ +
+ Disbursed Amount Percentage Down Payment (%): + {{ loanProduct.disbursedAmountPercentageForDownPayment }} % +
+

Event Settings

diff --git a/src/app/products/loan-products/loan-product-stepper/loan-product-settings-step/loan-product-settings-step.component.html b/src/app/products/loan-products/loan-product-stepper/loan-product-settings-step/loan-product-settings-step.component.html index 8c388376a..bc1398029 100644 --- a/src/app/products/loan-products/loan-product-stepper/loan-product-settings-step/loan-product-settings-step.component.html +++ b/src/app/products/loan-products/loan-product-stepper/loan-product-settings-step/loan-product-settings-step.component.html @@ -399,7 +399,7 @@ Maximum Tranche count - + Maximum Tranche count is required @@ -416,6 +416,28 @@ +

Down Payment

+ + + Enable Down Payment + + +
+ + Disbursed Amount Percentage Down Payment (%) + + + Disbursed Amount Percentage Down Payment is required + + + Disbursed Amount Percentage Down Payment is out percentage range + + +
+ + +

Event Settings

diff --git a/src/app/products/loan-products/loan-product-stepper/loan-product-settings-step/loan-product-settings-step.component.ts b/src/app/products/loan-products/loan-product-stepper/loan-product-settings-step/loan-product-settings-step.component.ts index 2e985e239..ca3380361 100644 --- a/src/app/products/loan-products/loan-product-stepper/loan-product-settings-step/loan-product-settings-step.component.ts +++ b/src/app/products/loan-products/loan-product-stepper/loan-product-settings-step/loan-product-settings-step.component.ts @@ -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) { diff --git a/src/app/products/loan-products/view-loan-product/general-tab/general-tab.component.html b/src/app/products/loan-products/view-loan-product/general-tab/general-tab.component.html index 4c56af48a..b02b09ddb 100644 --- a/src/app/products/loan-products/view-loan-product/general-tab/general-tab.component.html +++ b/src/app/products/loan-products/view-loan-product/general-tab/general-tab.component.html @@ -506,6 +506,20 @@
+

Down Payments

+ + + +
+ Enable Down Payments: + {{ loanProduct.enableDownPayment ? 'Yes' : 'No' }} +
+ +
+ Disbursed Amount Percentage Down Payment (%): + {{ loanProduct.disbursedAmountPercentageForDownPayment }} % +
+

Event Settings

diff --git a/src/app/shared/validators/percentage.validator.ts b/src/app/shared/validators/percentage.validator.ts new file mode 100644 index 000000000..d919c458e --- /dev/null +++ b/src/app/shared/validators/percentage.validator.ts @@ -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; + }; +}