feat: add edit loan product component (#451)
- Update loan product stepper components to support editing - Add edit loan product component - Add pristine property to form dialog Fixes: #439
This commit is contained in:
@@ -8,7 +8,7 @@ export class ChargesFilterPipe implements PipeTransform {
|
||||
transform(charges: any, chargesDataSource: any, currencyCode: string, multiDisburseLoan?: boolean): any {
|
||||
if (charges) {
|
||||
charges = charges.filter((charge: any) => {
|
||||
if ((charge.currency.code !== currencyCode) || (!!multiDisburseLoan && charge.chargeTimeType.id === 12) || chargesDataSource.includes(charge)) {
|
||||
if ((charge.currency.code !== currencyCode) || (!!multiDisburseLoan && charge.chargeTimeType.id === 12) || chargesDataSource.filter((chargeData: any) => chargeData.id === charge.id).length) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
+3
-2
@@ -64,8 +64,8 @@
|
||||
|
||||
<mifosx-loan-product-charges-step
|
||||
[loanProductsTemplate]="loanProductsTemplate"
|
||||
[currencyCode]="loanProductCurrencyForm.value.currencyCode"
|
||||
[multiDisburseLoan]="loanProductSettingsForm.value.multiDisburseLoan"
|
||||
[currencyCode]="loanProductCurrencyForm.get('currencyCode')"
|
||||
[multiDisburseLoan]="loanProductSettingsForm.get('multiDisburseLoan')"
|
||||
>
|
||||
</mifosx-loan-product-charges-step>
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
<mifosx-loan-product-accounting-step
|
||||
[loanProductsTemplate]="loanProductsTemplate"
|
||||
[accountingRuleData]="accountingRuleData"
|
||||
[loanProductFormValid]="loanProductFormValid"
|
||||
>
|
||||
</mifosx-loan-product-accounting-step>
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ export class CreateLoanProductComponent implements OnInit {
|
||||
...this.loanProductCurrencyStep.loanProductCurrency,
|
||||
...this.loanProductTermsStep.loanProductTerms,
|
||||
...this.loanProductSettingsStep.loanProductSettings,
|
||||
...this.loanProductChargesStep.charges,
|
||||
...this.loanProductChargesStep.loanProductCharges,
|
||||
...this.loanProductAccountingStep.loanProductAccounting
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
<div class="container">
|
||||
|
||||
<mat-horizontal-stepper class="mat-elevation-z8" labelPosition="bottom" #loanProductStepper>
|
||||
|
||||
<ng-template matStepperIcon="number">
|
||||
<fa-icon icon="pencil-alt" size="sm"></fa-icon>
|
||||
</ng-template>
|
||||
|
||||
<ng-template matStepperIcon="edit">
|
||||
<fa-icon icon="pencil-alt" size="sm"></fa-icon>
|
||||
</ng-template>
|
||||
|
||||
<ng-template matStepperIcon="done">
|
||||
<fa-icon icon="check" size="sm"></fa-icon>
|
||||
</ng-template>
|
||||
|
||||
<ng-template matStepperIcon="error">
|
||||
<fa-icon icon="exclamation-triangle" size="lg"></fa-icon>
|
||||
</ng-template>
|
||||
|
||||
<ng-template matStepperIcon="preview">
|
||||
<fa-icon icon="eye" size="sm"></fa-icon>
|
||||
</ng-template>
|
||||
|
||||
<mat-step [stepControl]="loanProductDetailsForm" completed>
|
||||
|
||||
<ng-template matStepLabel>DETAILS</ng-template>
|
||||
|
||||
<mifosx-loan-product-details-step [loanProductsTemplate]="loanProductAndTemplate"></mifosx-loan-product-details-step>
|
||||
|
||||
</mat-step>
|
||||
|
||||
<mat-step [stepControl]="loanProductCurrencyForm" completed>
|
||||
|
||||
<ng-template matStepLabel>CURRENCY</ng-template>
|
||||
|
||||
<mifosx-loan-product-currency-step [loanProductsTemplate]="loanProductAndTemplate"></mifosx-loan-product-currency-step>
|
||||
|
||||
</mat-step>
|
||||
|
||||
<mat-step [stepControl]="loanProductTermsForm" completed>
|
||||
|
||||
<ng-template matStepLabel>TERMS</ng-template>
|
||||
|
||||
<mifosx-loan-product-terms-step [loanProductsTemplate]="loanProductAndTemplate"></mifosx-loan-product-terms-step>
|
||||
|
||||
</mat-step>
|
||||
|
||||
<mat-step [stepControl]="loanProductSettingsForm" completed>
|
||||
|
||||
<ng-template matStepLabel>SETTINGS</ng-template>
|
||||
|
||||
<mifosx-loan-product-settings-step
|
||||
[loanProductsTemplate]="loanProductAndTemplate"
|
||||
[isLinkedToFloatingInterestRates]="loanProductTermsForm.get('isLinkedToFloatingInterestRates')"
|
||||
>
|
||||
</mifosx-loan-product-settings-step>
|
||||
|
||||
</mat-step>
|
||||
|
||||
<mat-step completed>
|
||||
|
||||
<ng-template matStepLabel>CHARGES</ng-template>
|
||||
|
||||
<mifosx-loan-product-charges-step
|
||||
[loanProductsTemplate]="loanProductAndTemplate"
|
||||
[currencyCode]="loanProductCurrencyForm.get('currencyCode')"
|
||||
[multiDisburseLoan]="loanProductSettingsForm.get('multiDisburseLoan')"
|
||||
>
|
||||
</mifosx-loan-product-charges-step>
|
||||
|
||||
</mat-step>
|
||||
|
||||
<mat-step [stepControl]="loanProductAccountingForm" completed>
|
||||
|
||||
<ng-template matStepLabel>ACCOUNTING</ng-template>
|
||||
|
||||
<mifosx-loan-product-accounting-step
|
||||
[loanProductsTemplate]="loanProductAndTemplate"
|
||||
[accountingRuleData]="accountingRuleData"
|
||||
[loanProductFormValid]="loanProductFormValidAndNotPristine"
|
||||
>
|
||||
</mifosx-loan-product-accounting-step>
|
||||
|
||||
</mat-step>
|
||||
|
||||
<mat-step state="preview" *ngIf="loanProductFormValidAndNotPristine" completed>
|
||||
|
||||
<ng-template matStepLabel>PREVIEW</ng-template>
|
||||
|
||||
<mifosx-loan-product-preview-step
|
||||
[loanProductsTemplate]="loanProductAndTemplate"
|
||||
[accountingRuleData]="accountingRuleData"
|
||||
[loanProduct]="loanProduct"
|
||||
(submit)="submit()"
|
||||
>
|
||||
</mifosx-loan-product-preview-step>
|
||||
|
||||
</mat-step>
|
||||
|
||||
</mat-horizontal-stepper>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { EditLoanProductComponent } from './edit-loan-product.component';
|
||||
|
||||
describe('EditLoanProductComponent', () => {
|
||||
let component: EditLoanProductComponent;
|
||||
let fixture: ComponentFixture<EditLoanProductComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ EditLoanProductComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(EditLoanProductComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,108 @@
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
|
||||
import { LoanProductDetailsStepComponent } from '../loan-product-stepper/loan-product-details-step/loan-product-details-step.component';
|
||||
import { LoanProductCurrencyStepComponent } from '../loan-product-stepper/loan-product-currency-step/loan-product-currency-step.component';
|
||||
import { LoanProductTermsStepComponent } from '../loan-product-stepper/loan-product-terms-step/loan-product-terms-step.component';
|
||||
import { LoanProductSettingsStepComponent } from '../loan-product-stepper/loan-product-settings-step/loan-product-settings-step.component';
|
||||
import { LoanProductChargesStepComponent } from '../loan-product-stepper/loan-product-charges-step/loan-product-charges-step.component';
|
||||
import { LoanProductAccountingStepComponent } from '../loan-product-stepper/loan-product-accounting-step/loan-product-accounting-step.component';
|
||||
|
||||
import { ProductsService } from 'app/products/products.service';
|
||||
|
||||
@Component({
|
||||
selector: 'mifosx-edit-loan-product',
|
||||
templateUrl: './edit-loan-product.component.html',
|
||||
styleUrls: ['./edit-loan-product.component.scss']
|
||||
})
|
||||
export class EditLoanProductComponent implements OnInit {
|
||||
|
||||
@ViewChild(LoanProductDetailsStepComponent) loanProductDetailsStep: LoanProductDetailsStepComponent;
|
||||
@ViewChild(LoanProductCurrencyStepComponent) loanProductCurrencyStep: LoanProductCurrencyStepComponent;
|
||||
@ViewChild(LoanProductTermsStepComponent) loanProductTermsStep: LoanProductTermsStepComponent;
|
||||
@ViewChild(LoanProductSettingsStepComponent) loanProductSettingsStep: LoanProductSettingsStepComponent;
|
||||
@ViewChild(LoanProductChargesStepComponent) loanProductChargesStep: LoanProductChargesStepComponent;
|
||||
@ViewChild(LoanProductAccountingStepComponent) loanProductAccountingStep: LoanProductAccountingStepComponent;
|
||||
|
||||
loanProductAndTemplate: any;
|
||||
accountingRuleData = ['None', 'Cash', 'Accrual (periodic)', 'Accrual (upfront)'];
|
||||
|
||||
constructor(private route: ActivatedRoute,
|
||||
private productsService: ProductsService,
|
||||
private router: Router) {
|
||||
this.route.data.subscribe((data: { loanProductAndTemplate: any }) => {
|
||||
this.loanProductAndTemplate = data.loanProductAndTemplate;
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
get loanProductDetailsForm() {
|
||||
return this.loanProductDetailsStep.loanProductDetailsForm;
|
||||
}
|
||||
|
||||
get loanProductCurrencyForm() {
|
||||
return this.loanProductCurrencyStep.loanProductCurrencyForm;
|
||||
}
|
||||
|
||||
get loanProductTermsForm() {
|
||||
return this.loanProductTermsStep.loanProductTermsForm;
|
||||
}
|
||||
|
||||
get loanProductSettingsForm() {
|
||||
return this.loanProductSettingsStep.loanProductSettingsForm;
|
||||
}
|
||||
|
||||
get loanProductAccountingForm() {
|
||||
return this.loanProductAccountingStep.loanProductAccountingForm;
|
||||
}
|
||||
|
||||
get loanProductFormValidAndNotPristine() {
|
||||
return (
|
||||
this.loanProductDetailsForm.valid &&
|
||||
this.loanProductCurrencyForm.valid &&
|
||||
this.loanProductTermsForm.valid &&
|
||||
this.loanProductSettingsForm.valid &&
|
||||
this.loanProductAccountingForm.valid &&
|
||||
(
|
||||
!this.loanProductDetailsForm.pristine ||
|
||||
!this.loanProductCurrencyForm.pristine ||
|
||||
!this.loanProductTermsForm.pristine ||
|
||||
!this.loanProductSettingsForm.pristine ||
|
||||
!this.loanProductChargesStep.pristine ||
|
||||
!this.loanProductAccountingForm.pristine
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
get loanProduct() {
|
||||
return {
|
||||
...this.loanProductDetailsStep.loanProductDetails,
|
||||
...this.loanProductCurrencyStep.loanProductCurrency,
|
||||
...this.loanProductTermsStep.loanProductTerms,
|
||||
...this.loanProductSettingsStep.loanProductSettings,
|
||||
...this.loanProductChargesStep.loanProductCharges,
|
||||
...this.loanProductAccountingStep.loanProductAccounting
|
||||
};
|
||||
}
|
||||
|
||||
submit() {
|
||||
// TODO: Update once language and date settings are setup
|
||||
const dateFormat = 'yyyy-MM-dd';
|
||||
const loanProduct = {
|
||||
...this.loanProduct,
|
||||
charges: this.loanProduct.charges.map((charge: any) => ({ id: charge.id })),
|
||||
dateFormat,
|
||||
locale: 'en'
|
||||
};
|
||||
delete loanProduct.allowAttributeConfiguration;
|
||||
delete loanProduct.advancedAccountingRules;
|
||||
this.productsService.updateLoanProduct(this.loanProductAndTemplate.id, loanProduct)
|
||||
.subscribe((response: any) => {
|
||||
this.router.navigate(['../../', response.resourceId], { relativeTo: this.route });
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/** Angular Imports */
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
|
||||
|
||||
/** rxjs Imports */
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
/** Custom Services */
|
||||
import { ProductsService } from '../../products.service';
|
||||
|
||||
/**
|
||||
* Loan product and template data resolver.
|
||||
*/
|
||||
@Injectable()
|
||||
export class LoanProductAndTemplateResolver implements Resolve<Object> {
|
||||
|
||||
/**
|
||||
* @param {ProductsService} productsService Products service.
|
||||
*/
|
||||
constructor(private productsService: ProductsService) {}
|
||||
|
||||
/**
|
||||
* Returns the loan product and template data.
|
||||
* @returns {Observable<any>}
|
||||
*/
|
||||
resolve(route: ActivatedRouteSnapshot): Observable<any> {
|
||||
const loanProductId = route.paramMap.get('id');
|
||||
return this.productsService.getLoanProduct(loanProductId, true);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -320,7 +320,7 @@
|
||||
<fa-icon icon="arrow-left"></fa-icon>
|
||||
Previous
|
||||
</button>
|
||||
<button mat-raised-button matStepperNext>
|
||||
<button mat-raised-button matStepperNext [disabled]="!loanProductFormValid">
|
||||
Next
|
||||
<fa-icon icon="arrow-right"></fa-icon>
|
||||
</button>
|
||||
|
||||
+50
-2
@@ -17,6 +17,7 @@ export class LoanProductAccountingStepComponent implements OnInit {
|
||||
|
||||
@Input() loanProductsTemplate: any;
|
||||
@Input() accountingRuleData: any;
|
||||
@Input() loanProductFormValid: boolean;
|
||||
|
||||
loanProductAccountingForm: FormGroup;
|
||||
|
||||
@@ -47,6 +48,44 @@ export class LoanProductAccountingStepComponent implements OnInit {
|
||||
this.expenseAccountData = this.loanProductsTemplate.accountingMappingOptions.expenseAccountOptions || [];
|
||||
this.liabilityAccountData = this.loanProductsTemplate.accountingMappingOptions.liabilityAccountOptions || [];
|
||||
this.incomeAndLiabilityAccountData = this.incomeAccountData.concat(this.liabilityAccountData);
|
||||
|
||||
this.loanProductAccountingForm.patchValue({
|
||||
'accountingRule': this.loanProductsTemplate.accountingRule.id
|
||||
});
|
||||
|
||||
switch (this.loanProductsTemplate.accountingRule.id) {
|
||||
case 3:
|
||||
case 4:
|
||||
this.loanProductAccountingForm.patchValue({
|
||||
'receivableInterestAccountId': this.loanProductsTemplate.accountingMappings.receivableInterestAccount.id,
|
||||
'receivableFeeAccountId': this.loanProductsTemplate.accountingMappings.receivableFeeAccount.id,
|
||||
'receivablePenaltyAccountId': this.loanProductsTemplate.accountingMappings.receivablePenaltyAccount.id,
|
||||
});
|
||||
/* falls through */
|
||||
case 2:
|
||||
this.loanProductAccountingForm.patchValue({
|
||||
'fundSourceAccountId': this.loanProductsTemplate.accountingMappings.fundSourceAccount.id,
|
||||
'loanPortfolioAccountId': this.loanProductsTemplate.accountingMappings.loanPortfolioAccount.id,
|
||||
'transfersInSuspenseAccountId': this.loanProductsTemplate.accountingMappings.transfersInSuspenseAccount.id,
|
||||
'interestOnLoanAccountId': this.loanProductsTemplate.accountingMappings.interestOnLoanAccount.id,
|
||||
'incomeFromFeeAccountId': this.loanProductsTemplate.accountingMappings.incomeFromFeeAccount.id,
|
||||
'incomeFromPenaltyAccountId': this.loanProductsTemplate.accountingMappings.incomeFromPenaltyAccount.id,
|
||||
'incomeFromRecoveryAccountId': this.loanProductsTemplate.accountingMappings.incomeFromRecoveryAccount.id,
|
||||
'writeOffAccountId': this.loanProductsTemplate.accountingMappings.writeOffAccount.id,
|
||||
'overpaymentLiabilityAccountId': this.loanProductsTemplate.accountingMappings.overpaymentLiabilityAccount.id,
|
||||
'advancedAccountingRules': (this.loanProductsTemplate.paymentChannelToFundSourceMappings || this.loanProductsTemplate.feeToIncomeAccountMappings || this.loanProductsTemplate.penaltyToIncomeAccountMappings) ? true : false
|
||||
});
|
||||
|
||||
this.loanProductAccountingForm.setControl('paymentChannelToFundSourceMappings',
|
||||
this.formBuilder.array((this.loanProductsTemplate.paymentChannelToFundSourceMappings || []).map((paymentFundSource: any) =>
|
||||
({ paymentTypeId: paymentFundSource.paymentType.id, fundSourceAccountId: paymentFundSource.fundSourceAccount.id }))));
|
||||
this.loanProductAccountingForm.setControl('feeToIncomeAccountMappings',
|
||||
this.formBuilder.array((this.loanProductsTemplate.feeToIncomeAccountMappings || []).map((feesIncome: any) =>
|
||||
({ chargeId: feesIncome.charge.id, incomeAccountId: feesIncome.incomeAccount.id }))));
|
||||
this.loanProductAccountingForm.setControl('penaltyToIncomeAccountMappings',
|
||||
this.formBuilder.array((this.loanProductsTemplate.penaltyToIncomeAccountMappings || []).map((penaltyIncome: any) =>
|
||||
({ chargeId: penaltyIncome.charge.id, incomeAccountId: penaltyIncome.incomeAccount.id }))));
|
||||
}
|
||||
}
|
||||
|
||||
createLoanProductAccountingForm() {
|
||||
@@ -74,7 +113,7 @@ export class LoanProductAccountingStepComponent implements OnInit {
|
||||
.subscribe((advancedAccountingRules: boolean) => {
|
||||
if (advancedAccountingRules) {
|
||||
this.loanProductAccountingForm.addControl('paymentChannelToFundSourceMappings', this.formBuilder.array([]));
|
||||
this.loanProductAccountingForm.addControl('feeToIncomeAccountMappings', this.formBuilder.array([] ));
|
||||
this.loanProductAccountingForm.addControl('feeToIncomeAccountMappings', this.formBuilder.array([]));
|
||||
this.loanProductAccountingForm.addControl('penaltyToIncomeAccountMappings', this.formBuilder.array([]));
|
||||
} else {
|
||||
this.loanProductAccountingForm.removeControl('paymentChannelToFundSourceMappings');
|
||||
@@ -119,12 +158,19 @@ export class LoanProductAccountingStepComponent implements OnInit {
|
||||
return this.loanProductAccountingForm.get('penaltyToIncomeAccountMappings') as FormArray;
|
||||
}
|
||||
|
||||
setLoanProductAccountingFormDirty() {
|
||||
if (this.loanProductAccountingForm.pristine) {
|
||||
this.loanProductAccountingForm.markAsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
add(formType: string, formArray: FormArray) {
|
||||
const data = this.getData(formType);
|
||||
const data = { ...this.getData(formType), pristine: false };
|
||||
const dialogRef = this.dialog.open(FormDialogComponent, { data });
|
||||
dialogRef.afterClosed().subscribe((response: any) => {
|
||||
if (response.data) {
|
||||
formArray.push(response.data);
|
||||
this.setLoanProductAccountingFormDirty();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -135,6 +181,7 @@ export class LoanProductAccountingStepComponent implements OnInit {
|
||||
dialogRef.afterClosed().subscribe((response: any) => {
|
||||
if (response.data) {
|
||||
formArray.at(index).patchValue(response.data.value);
|
||||
this.setLoanProductAccountingFormDirty();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -146,6 +193,7 @@ export class LoanProductAccountingStepComponent implements OnInit {
|
||||
dialogRef.afterClosed().subscribe((response: any) => {
|
||||
if (response.delete) {
|
||||
formArray.removeAt(index);
|
||||
this.setLoanProductAccountingFormDirty();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-label>Charge</mat-label>
|
||||
<mat-select #charge>
|
||||
<mat-option *ngFor="let charge of chargeData | chargesFilter:chargesDataSource:currencyCode:multiDisburseLoan" [value]="charge">
|
||||
<mat-option *ngFor="let charge of chargeData | chargesFilter:chargesDataSource:currencyCode.value:multiDisburseLoan.value" [value]="charge">
|
||||
{{ charge.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
@@ -69,7 +69,7 @@
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-label>Overdue Charge</mat-label>
|
||||
<mat-select #overdueCharge>
|
||||
<mat-option *ngFor="let overdueCharge of overdueChargeData | chargesFilter:chargesDataSource:currencyCode" [value]="overdueCharge">
|
||||
<mat-option *ngFor="let overdueCharge of overdueChargeData | chargesFilter:chargesDataSource:currencyCode.value" [value]="overdueCharge">
|
||||
{{ overdueCharge.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
|
||||
+15
-4
@@ -1,5 +1,6 @@
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material';
|
||||
import { FormControl } from '@angular/forms';
|
||||
|
||||
import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component';
|
||||
|
||||
@@ -11,26 +12,35 @@ import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.co
|
||||
export class LoanProductChargesStepComponent implements OnInit {
|
||||
|
||||
@Input() loanProductsTemplate: any;
|
||||
@Input() currencyCode: any;
|
||||
@Input() multiDisburseLoan: any;
|
||||
@Input() currencyCode: FormControl;
|
||||
@Input() multiDisburseLoan: FormControl;
|
||||
|
||||
chargeData: any;
|
||||
overdueChargeData: any;
|
||||
|
||||
chargesDataSource: {}[] = [];
|
||||
chargesDataSource: {}[];
|
||||
displayedColumns: string[] = ['name', 'chargeCalculationType', 'amount', 'chargeTimeType', 'action'];
|
||||
|
||||
pristine = true;
|
||||
|
||||
constructor(public dialog: MatDialog) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.chargeData = this.loanProductsTemplate.chargeOptions;
|
||||
this.overdueChargeData = this.loanProductsTemplate.penaltyOptions.filter((penalty: any) => penalty.chargeTimeType.code === 'chargeTimeType.overdueInstallment');
|
||||
|
||||
this.chargesDataSource = this.loanProductsTemplate.charges || [];
|
||||
this.pristine = true;
|
||||
|
||||
this.currencyCode.valueChanges.subscribe(() => this.chargesDataSource = []);
|
||||
this.multiDisburseLoan.valueChanges.subscribe(() => this.chargesDataSource = []);
|
||||
}
|
||||
|
||||
addCharge(charge: any) {
|
||||
this.chargesDataSource = this.chargesDataSource.concat([charge.value]);
|
||||
charge.value = '';
|
||||
this.pristine = false;
|
||||
}
|
||||
|
||||
deleteCharge(charge: any) {
|
||||
@@ -41,11 +51,12 @@ export class LoanProductChargesStepComponent implements OnInit {
|
||||
if (response.delete) {
|
||||
this.chargesDataSource.splice(this.chargesDataSource.indexOf(charge), 1);
|
||||
this.chargesDataSource = this.chargesDataSource.concat([]);
|
||||
this.pristine = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
get charges() {
|
||||
get loanProductCharges() {
|
||||
return {
|
||||
charges: this.chargesDataSource
|
||||
};
|
||||
|
||||
+8
-2
@@ -20,13 +20,19 @@ export class LoanProductCurrencyStepComponent implements OnInit {
|
||||
|
||||
ngOnInit() {
|
||||
this.currencyData = this.loanProductsTemplate.currencyOptions;
|
||||
this.loanProductCurrencyForm.patchValue({ 'currencyCode': this.currencyData[0].code });
|
||||
|
||||
this.loanProductCurrencyForm.patchValue({
|
||||
'currencyCode': this.loanProductsTemplate.currency.code || this.currencyData[0].code,
|
||||
'digitsAfterDecimal': this.loanProductsTemplate.installmentAmountInMultiplesOf ? this.loanProductsTemplate.currency.decimalPlaces : 2,
|
||||
'inMultiplesOf': this.loanProductsTemplate.currency.inMultiplesOf,
|
||||
'installmentAmountInMultiplesOf': this.loanProductsTemplate.installmentAmountInMultiplesOf
|
||||
});
|
||||
}
|
||||
|
||||
createLoanProductCurrencyForm() {
|
||||
this.loanProductCurrencyForm = this.formBuilder.group({
|
||||
'currencyCode': ['', Validators.required],
|
||||
'digitsAfterDecimal': [2, Validators.required],
|
||||
'digitsAfterDecimal': ['', Validators.required],
|
||||
'inMultiplesOf': ['', Validators.required],
|
||||
'installmentAmountInMultiplesOf': ['', Validators.required]
|
||||
});
|
||||
|
||||
+10
@@ -25,6 +25,16 @@ export class LoanProductDetailsStepComponent implements OnInit {
|
||||
|
||||
ngOnInit() {
|
||||
this.fundData = this.loanProductsTemplate.fundOptions;
|
||||
|
||||
this.loanProductDetailsForm.patchValue({
|
||||
'name': this.loanProductsTemplate.name,
|
||||
'shortName': this.loanProductsTemplate.shortName,
|
||||
'description': this.loanProductsTemplate.description,
|
||||
'fundId': this.loanProductsTemplate.fundId,
|
||||
'startDate': this.loanProductsTemplate.startDate && new Date(this.loanProductsTemplate.startDate),
|
||||
'closeDate': this.loanProductsTemplate.closeDate && new Date(this.loanProductsTemplate.closeDate),
|
||||
'includeInBorrowerCycle': this.loanProductsTemplate.includeInBorrowerCycle
|
||||
});
|
||||
}
|
||||
|
||||
createLoanProductDetailsForm() {
|
||||
|
||||
+4
-22
@@ -115,7 +115,7 @@
|
||||
<h4 fxFlex="48%" class="mat-h4">Number of days a loan may be overdue before moving into arrears</h4>
|
||||
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-label>On arrears aging</mat-label>
|
||||
<mat-label>On arrears ageing</mat-label>
|
||||
<input type="number" matInput formControlName="graceOnArrearsAgeing">
|
||||
</mat-form-field>
|
||||
|
||||
@@ -210,9 +210,9 @@
|
||||
|
||||
<span fxFlex="48%" fxHide.lt-md></span>
|
||||
|
||||
<div *ngIf="loanProductSettingsForm.value.interestRecalculationCompoundingMethod !== 0 && loanProductSettingsForm.value.recalculationCompoundingFrequencyType !== 1" fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||
<div fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-form-field fxFlex="48%" *ngIf="loanProductSettingsForm.value.interestRecalculationCompoundingMethod !== 0 && loanProductSettingsForm.value.recalculationCompoundingFrequencyType !== 1">
|
||||
<mat-label>Frequency Interval for compounding</mat-label>
|
||||
<input type="number" matInput formControlName="recalculationCompoundingFrequencyInterval" required>
|
||||
<mat-error>
|
||||
@@ -220,18 +220,7 @@
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-label>Compounding Frequency Date</mat-label>
|
||||
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="recalculationCompoundingFrequencyDatePicker" formControlName="recalculationCompoundingFrequencyDate">
|
||||
<mat-datepicker-toggle matSuffix [for]="recalculationCompoundingFrequencyDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #recalculationCompoundingFrequencyDatePicker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
|
||||
</div>
|
||||
|
||||
<div *ngIf="loanProductSettingsForm.value.recalculationRestFrequencyType !== 1" fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-form-field fxFlex="48%" *ngIf="loanProductSettingsForm.value.recalculationRestFrequencyType !== 1">
|
||||
<mat-label>Frequency Interval for recalculation</mat-label>
|
||||
<input type="number" matInput formControlName="recalculationRestFrequencyInterval" required>
|
||||
<mat-error>
|
||||
@@ -239,13 +228,6 @@
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-label>Rest Frequency Date</mat-label>
|
||||
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="recalculationRestFrequencyDatePicker" formControlName="recalculationRestFrequencyDate">
|
||||
<mat-datepicker-toggle matSuffix [for]="recalculationRestFrequencyDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #recalculationRestFrequencyDatePicker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
|
||||
</div>
|
||||
|
||||
<div *ngIf="loanProductSettingsForm.value.interestRecalculationCompoundingMethod !== 0" fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||
|
||||
+89
-48
@@ -1,6 +1,5 @@
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms';
|
||||
import { DatePipe } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'mifosx-loan-product-settings-step',
|
||||
@@ -28,11 +27,7 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
||||
interestRecalculationDayOfWeekTypeData: any;
|
||||
interestRecalculationOnDayTypeData: any;
|
||||
|
||||
minDate = new Date(2000, 0, 1);
|
||||
maxDate = new Date(new Date().setFullYear(new Date().getFullYear() + 10));
|
||||
|
||||
constructor(private formBuilder: FormBuilder,
|
||||
private datePipe: DatePipe) {
|
||||
constructor(private formBuilder: FormBuilder) {
|
||||
this.createLoanProductSettingsForm();
|
||||
this.setConditionalControls();
|
||||
}
|
||||
@@ -41,8 +36,8 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
||||
this.isLinkedToFloatingInterestRates.valueChanges
|
||||
.subscribe((isLinkedToFloatingInterestRates: any) => {
|
||||
if (isLinkedToFloatingInterestRates) {
|
||||
this.loanProductSettingsForm.get('isInterestRecalculationEnabled').setValue(true);
|
||||
}
|
||||
this.loanProductSettingsForm.get('isInterestRecalculationEnabled').setValue(true);
|
||||
}
|
||||
});
|
||||
|
||||
this.amortizationTypeData = this.loanProductsTemplate.amortizationTypeOptions;
|
||||
@@ -61,13 +56,83 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
||||
this.interestRecalculationOnDayTypeData = Array.from({ length: 28 }, (_, index) => index + 1);
|
||||
|
||||
this.loanProductSettingsForm.patchValue({
|
||||
'amortizationType': this.amortizationTypeData[0].id,
|
||||
'interestType': this.interestTypeData[0].id,
|
||||
'interestCalculationPeriodType': this.interestCalculationPeriodTypeData[0].id,
|
||||
'transactionProcessingStrategyId': this.transactionProcessingStrategyData[0].id,
|
||||
'daysInYearType': this.daysInYearTypeData[0].id,
|
||||
'daysInMonthType': this.daysInMonthTypeData[0].id,
|
||||
'amortizationType': this.loanProductsTemplate.amortizationType.id,
|
||||
'interestType': this.loanProductsTemplate.interestType.id,
|
||||
'isEqualAmortization': this.loanProductsTemplate.isEqualAmortization,
|
||||
'interestCalculationPeriodType': this.loanProductsTemplate.interestCalculationPeriodType.id,
|
||||
'allowPartialPeriodInterestCalcualtion': this.loanProductsTemplate.allowPartialPeriodInterestCalcualtion,
|
||||
'transactionProcessingStrategyId': this.loanProductsTemplate.transactionProcessingStrategyId || this.transactionProcessingStrategyData[0].id,
|
||||
'graceOnPrincipalPayment': this.loanProductsTemplate.graceOnPrincipalPayment,
|
||||
'graceOnInterestPayment': this.loanProductsTemplate.graceOnInterestPayment,
|
||||
'graceOnInterestCharged': this.loanProductsTemplate.graceOnInterestCharged,
|
||||
'inArrearsTolerance': this.loanProductsTemplate.inArrearsTolerance,
|
||||
'daysInYearType': this.loanProductsTemplate.daysInYearType.id,
|
||||
'daysInMonthType': this.loanProductsTemplate.daysInMonthType.id,
|
||||
'canDefineInstallmentAmount': this.loanProductsTemplate.canDefineInstallmentAmount,
|
||||
'graceOnArrearsAgeing': this.loanProductsTemplate.graceOnArrearsAgeing,
|
||||
'overdueDaysForNPA': this.loanProductsTemplate.overdueDaysForNPA,
|
||||
'accountMovesOutOfNPAOnlyOnArrearsCompletion': this.loanProductsTemplate.accountMovesOutOfNPAOnlyOnArrearsCompletion,
|
||||
'principalThresholdForLastInstallment': this.loanProductsTemplate.principalThresholdForLastInstallment,
|
||||
'allowVariableInstallments': this.loanProductsTemplate.allowVariableInstallments,
|
||||
'minimumGap': this.loanProductsTemplate.minimumGap,
|
||||
'maximumGap': this.loanProductsTemplate.maximumGap,
|
||||
'canUseForTopup': this.loanProductsTemplate.canUseForTopup,
|
||||
'isInterestRecalculationEnabled': this.loanProductsTemplate.isInterestRecalculationEnabled,
|
||||
'holdGuaranteeFunds': this.loanProductsTemplate.holdGuaranteeFunds,
|
||||
'multiDisburseLoan': this.loanProductsTemplate.multiDisburseLoan,
|
||||
'maxTrancheCount': this.loanProductsTemplate.maxTrancheCount,
|
||||
'outstandingLoanBalance': this.loanProductsTemplate.outstandingLoanBalance
|
||||
});
|
||||
|
||||
if (this.loanProductsTemplate.isInterestRecalculationEnabled) {
|
||||
this.loanProductSettingsForm.patchValue({
|
||||
'preClosureInterestCalculationStrategy': this.loanProductsTemplate.interestRecalculationData.preClosureInterestCalculationStrategy.id,
|
||||
'rescheduleStrategyMethod': this.loanProductsTemplate.interestRecalculationData.rescheduleStrategyType.id,
|
||||
'interestRecalculationCompoundingMethod': this.loanProductsTemplate.interestRecalculationData.interestRecalculationCompoundingType.id,
|
||||
'recalculationRestFrequencyType': this.loanProductsTemplate.interestRecalculationData.recalculationRestFrequencyType.id,
|
||||
'isArrearsBasedOnOriginalSchedule': this.loanProductsTemplate.interestRecalculationData.isArrearsBasedOnOriginalSchedule,
|
||||
'recalculationCompoundingFrequencyType': this.loanProductsTemplate.interestRecalculationData.interestRecalculationCompoundingType.id && this.loanProductsTemplate.interestRecalculationData.recalculationCompoundingFrequencyType.id,
|
||||
'recalculationCompoundingFrequencyInterval': this.loanProductsTemplate.interestRecalculationData.recalculationCompoundingFrequencyInterval,
|
||||
'recalculationRestFrequencyInterval': this.loanProductsTemplate.interestRecalculationData.recalculationRestFrequencyInterval,
|
||||
'recalculationRestFrequencyNthDayType': this.loanProductsTemplate.interestRecalculationData.recalculationRestFrequencyType.id === 4 && this.loanProductsTemplate.interestRecalculationData.recalculationRestFrequencyOnDay ?
|
||||
-2 : this.loanProductsTemplate.interestRecalculationData.recalculationRestFrequencyNthDay && this.loanProductsTemplate.interestRecalculationData.recalculationRestFrequencyNthDay.id,
|
||||
'recalculationCompoundingFrequencyNthDayType': this.loanProductsTemplate.interestRecalculationData.interestRecalculationCompoundingType.id && this.loanProductsTemplate.interestRecalculationData.recalculationCompoundingFrequencyType.id === 4
|
||||
&& this.loanProductsTemplate.interestRecalculationData.recalculationCompoundingFrequencyOnDay ? -2 : this.loanProductsTemplate.interestRecalculationData.recalculationCompoundingFrequencyNthDay
|
||||
&& this.loanProductsTemplate.interestRecalculationData.recalculationCompoundingFrequencyNthDay.id,
|
||||
'recalculationCompoundingFrequencyDayOfWeekType': this.loanProductsTemplate.interestRecalculationData.interestRecalculationCompoundingType.id && ((this.loanProductsTemplate.interestRecalculationData.recalculationCompoundingFrequencyType.id
|
||||
=== 4 && !this.loanProductsTemplate.interestRecalculationData.recalculationCompoundingFrequencyOnDay) || this.loanProductsTemplate.interestRecalculationData.recalculationCompoundingFrequencyType.id === 3)
|
||||
&& this.loanProductsTemplate.interestRecalculationData.recalculationCompoundingFrequencyWeekday && this.loanProductsTemplate.interestRecalculationData.recalculationCompoundingFrequencyWeekday.id,
|
||||
'recalculationRestFrequencyDayOfWeekType': ((this.loanProductsTemplate.interestRecalculationData.recalculationRestFrequencyType.id === 4 && !this.loanProductsTemplate.interestRecalculationData.recalculationRestFrequencyOnDay)
|
||||
|| this.loanProductsTemplate.interestRecalculationData.recalculationRestFrequencyType.id === 3) && this.loanProductsTemplate.interestRecalculationData.recalculationRestFrequencyWeekday
|
||||
&& this.loanProductsTemplate.interestRecalculationData.recalculationRestFrequencyWeekday.id,
|
||||
'recalculationCompoundingFrequencyOnDayType': this.loanProductsTemplate.interestRecalculationData.recalculationCompoundingFrequencyOnDay,
|
||||
'recalculationRestFrequencyOnDayType': this.loanProductsTemplate.interestRecalculationData.recalculationRestFrequencyOnDay
|
||||
});
|
||||
}
|
||||
|
||||
if (this.loanProductsTemplate.holdGuaranteeFunds) {
|
||||
this.loanProductSettingsForm.patchValue({
|
||||
'mandatoryGuarantee': this.loanProductsTemplate.productGuaranteeData.mandatoryGuarantee,
|
||||
'minimumGuaranteeFromOwnFunds': this.loanProductsTemplate.productGuaranteeData.minimumGuaranteeFromOwnFunds,
|
||||
'minimumGuaranteeFromGuarantor': this.loanProductsTemplate.productGuaranteeData.minimumGuaranteeFromGuarantor
|
||||
});
|
||||
}
|
||||
|
||||
if (this.loanProductsTemplate.allowAttributeOverrides) {
|
||||
this.loanProductSettingsForm.patchValue({
|
||||
'allowAttributeConfiguration': Object.values(this.loanProductsTemplate.allowAttributeOverrides).some((attribute: boolean) => attribute),
|
||||
'allowAttributeOverrides': {
|
||||
'amortizationType': this.loanProductsTemplate.allowAttributeOverrides.amortizationType,
|
||||
'interestType': this.loanProductsTemplate.allowAttributeOverrides.interestType,
|
||||
'transactionProcessingStrategyId': this.loanProductsTemplate.allowAttributeOverrides.transactionProcessingStrategyId,
|
||||
'interestCalculationPeriodType': this.loanProductsTemplate.allowAttributeOverrides.interestCalculationPeriodType,
|
||||
'inArrearsTolerance': this.loanProductsTemplate.allowAttributeOverrides.inArrearsTolerance,
|
||||
'repaymentEvery': this.loanProductsTemplate.allowAttributeOverrides.repaymentEvery,
|
||||
'graceOnPrincipalAndInterestPayment': this.loanProductsTemplate.allowAttributeOverrides.graceOnPrincipalAndInterestPayment,
|
||||
'graceOnArrearsAgeing': this.loanProductsTemplate.allowAttributeOverrides.graceOnArrearsAgeing
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
createLoanProductSettingsForm() {
|
||||
@@ -139,34 +204,27 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
||||
this.loanProductSettingsForm.addControl('recalculationRestFrequencyType', new FormControl(this.interestRecalculationFrequencyTypeData[0].id, Validators.required));
|
||||
this.loanProductSettingsForm.addControl('isArrearsBasedOnOriginalSchedule', new FormControl(''));
|
||||
|
||||
// interestRecalculationCompoundingMethod (initially 0)
|
||||
this.loanProductSettingsForm.get('interestRecalculationCompoundingMethod').valueChanges
|
||||
.subscribe((interestRecalculationCompoundingMethod: any) => {
|
||||
if (interestRecalculationCompoundingMethod !== 0) {
|
||||
this.loanProductSettingsForm.addControl('recalculationCompoundingFrequencyType', new FormControl(this.interestRecalculationFrequencyTypeData[0].id, Validators.required));
|
||||
|
||||
// recalculationCompoundingFrequencyType (initially 1)
|
||||
this.loanProductSettingsForm.get('recalculationCompoundingFrequencyType').valueChanges
|
||||
.subscribe((recalculationCompoundingFrequencyType: any) => {
|
||||
if (recalculationCompoundingFrequencyType !== 1) {
|
||||
this.loanProductSettingsForm.addControl('recalculationCompoundingFrequencyInterval', new FormControl('', Validators.required));
|
||||
this.loanProductSettingsForm.addControl('recalculationCompoundingFrequencyDate', new FormControl(''));
|
||||
} else {
|
||||
this.loanProductSettingsForm.removeControl('recalculationCompoundingFrequencyInterval');
|
||||
this.loanProductSettingsForm.removeControl('recalculationCompoundingFrequencyDate');
|
||||
}
|
||||
|
||||
if (recalculationCompoundingFrequencyType === 3) {
|
||||
this.loanProductSettingsForm.addControl('recalculationCompoundingFrequencyDayOfWeekType', new FormControl(''));
|
||||
} else {
|
||||
this.loanProductSettingsForm.removeControl('recalculationCompoundingFrequencyDayOfWeekType');
|
||||
}
|
||||
|
||||
if (recalculationCompoundingFrequencyType === 4) {
|
||||
this.loanProductSettingsForm.removeControl('recalculationCompoundingFrequencyNthDayType');
|
||||
this.loanProductSettingsForm.removeControl('recalculationCompoundingFrequencyOnDayType');
|
||||
} else if (recalculationCompoundingFrequencyType === 4) {
|
||||
this.loanProductSettingsForm.addControl('recalculationCompoundingFrequencyNthDayType', new FormControl(''));
|
||||
this.loanProductSettingsForm.addControl('recalculationCompoundingFrequencyDayOfWeekType', new FormControl(''));
|
||||
|
||||
// recalculationCompoundingFrequencyNthDayType
|
||||
this.loanProductSettingsForm.get('recalculationCompoundingFrequencyNthDayType').valueChanges
|
||||
.subscribe((recalculationCompoundingFrequencyNthDayType: any) => {
|
||||
if (recalculationCompoundingFrequencyNthDayType === -2) {
|
||||
@@ -177,9 +235,10 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
||||
this.loanProductSettingsForm.removeControl('recalculationCompoundingFrequencyOnDayType');
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
this.loanProductSettingsForm.removeControl('recalculationCompoundingFrequencyNthDayType');
|
||||
this.loanProductSettingsForm.removeControl('recalculationCompoundingFrequencyDayOfWeekType');
|
||||
this.loanProductSettingsForm.removeControl('recalculationCompoundingFrequencyOnDayType');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -188,28 +247,22 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
||||
}
|
||||
});
|
||||
|
||||
// recalculationRestFrequencyType
|
||||
this.loanProductSettingsForm.get('recalculationRestFrequencyType').valueChanges
|
||||
.subscribe((recalculationRestFrequencyType: any) => {
|
||||
if (recalculationRestFrequencyType !== 1) {
|
||||
this.loanProductSettingsForm.addControl('recalculationRestFrequencyInterval', new FormControl('', Validators.required));
|
||||
this.loanProductSettingsForm.addControl('recalculationRestFrequencyDate', new FormControl(''));
|
||||
} else {
|
||||
this.loanProductSettingsForm.removeControl('recalculationRestFrequencyInterval');
|
||||
this.loanProductSettingsForm.removeControl('recalculationRestFrequencyDate');
|
||||
}
|
||||
|
||||
if (recalculationRestFrequencyType === 3) {
|
||||
this.loanProductSettingsForm.addControl('recalculationRestFrequencyDayOfWeekType', new FormControl(''));
|
||||
} else {
|
||||
this.loanProductSettingsForm.removeControl('recalculationRestFrequencyDayOfWeekType');
|
||||
}
|
||||
|
||||
if (recalculationRestFrequencyType === 4) {
|
||||
this.loanProductSettingsForm.removeControl('recalculationRestFrequencyNthDayType');
|
||||
this.loanProductSettingsForm.removeControl('recalculationRestFrequencyOnDayType');
|
||||
} else if (recalculationRestFrequencyType === 4) {
|
||||
this.loanProductSettingsForm.addControl('recalculationRestFrequencyNthDayType', new FormControl(''));
|
||||
this.loanProductSettingsForm.addControl('recalculationRestFrequencyDayOfWeekType', new FormControl(''));
|
||||
|
||||
// recalculationRestFrequencyNthDayType
|
||||
this.loanProductSettingsForm.get('recalculationRestFrequencyNthDayType').valueChanges
|
||||
.subscribe((recalculationRestFrequencyNthDayType: any) => {
|
||||
if (recalculationRestFrequencyNthDayType === -2) {
|
||||
@@ -223,6 +276,8 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
||||
|
||||
} else {
|
||||
this.loanProductSettingsForm.removeControl('recalculationRestFrequencyNthDayType');
|
||||
this.loanProductSettingsForm.removeControl('recalculationRestFrequencyDayOfWeekType');
|
||||
this.loanProductSettingsForm.removeControl('recalculationRestFrequencyOnDayType');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -288,20 +343,6 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
||||
}
|
||||
|
||||
get loanProductSettings() {
|
||||
const prevCompoundingFrequencyDate: Date = this.loanProductSettingsForm.value.recalculationCompoundingFrequencyDate;
|
||||
const prevRestFrequencyDate: Date = this.loanProductSettingsForm.value.recalculationRestFrequencyDate;
|
||||
// TODO: Update once language and date settings are setup
|
||||
const dateFormat = 'yyyy-MM-dd';
|
||||
if (prevCompoundingFrequencyDate) {
|
||||
this.loanProductSettingsForm.patchValue({
|
||||
recalculationCompoundingFrequencyDate: this.datePipe.transform(prevCompoundingFrequencyDate, dateFormat)
|
||||
});
|
||||
}
|
||||
if (prevRestFrequencyDate) {
|
||||
this.loanProductSettingsForm.patchValue({
|
||||
recalculationRestFrequencyDate: this.datePipe.transform(prevRestFrequencyDate, dateFormat)
|
||||
});
|
||||
}
|
||||
return this.loanProductSettingsForm.value;
|
||||
}
|
||||
|
||||
|
||||
+39
-3
@@ -38,10 +38,37 @@ export class LoanProductTermsStepComponent implements OnInit {
|
||||
this.floatingRateData = this.loanProductsTemplate.floatingRateOptions;
|
||||
this.interestRateFrequencyTypeData = this.loanProductsTemplate.interestRateFrequencyTypeOptions;
|
||||
this.repaymentFrequencyTypeData = this.loanProductsTemplate.repaymentFrequencyTypeOptions;
|
||||
|
||||
this.loanProductTermsForm.patchValue({
|
||||
'interestRateFrequencyType': this.interestRateFrequencyTypeData[0].id,
|
||||
'repaymentFrequencyType': this.repaymentFrequencyTypeData[0].id
|
||||
'minPrincipal': this.loanProductsTemplate.minPrincipal,
|
||||
'principal': this.loanProductsTemplate.principal,
|
||||
'maxPrincipal': this.loanProductsTemplate.maxPrincipal,
|
||||
'minNumberOfRepayments': this.loanProductsTemplate.minNumberOfRepayments,
|
||||
'numberOfRepayments': this.loanProductsTemplate.numberOfRepayments,
|
||||
'maxNumberOfRepayments': this.loanProductsTemplate.maxNumberOfRepayments,
|
||||
'isLinkedToFloatingInterestRates': this.loanProductsTemplate.isLinkedToFloatingInterestRates,
|
||||
'minInterestRatePerPeriod': this.loanProductsTemplate.minInterestRatePerPeriod,
|
||||
'interestRatePerPeriod': this.loanProductsTemplate.interestRatePerPeriod,
|
||||
'maxInterestRatePerPeriod': this.loanProductsTemplate.maxInterestRatePerPeriod,
|
||||
'interestRateFrequencyType': this.loanProductsTemplate.interestRateFrequencyType.id,
|
||||
'floatingRatesId': this.loanProductsTemplate.floatingRateId,
|
||||
'interestRateDifferential': this.loanProductsTemplate.interestRateDifferential,
|
||||
'isFloatingInterestRateCalculationAllowed': this.loanProductsTemplate.isFloatingInterestRateCalculationAllowed,
|
||||
'minDifferentialLendingRate': this.loanProductsTemplate.minDifferentialLendingRate,
|
||||
'defaultDifferentialLendingRate': this.loanProductsTemplate.defaultDifferentialLendingRate,
|
||||
'maxDifferentialLendingRate': this.loanProductsTemplate.maxDifferentialLendingRate,
|
||||
'useBorrowerCycle': this.loanProductsTemplate.useBorrowerCycle,
|
||||
'repaymentEvery': this.loanProductsTemplate.repaymentEvery,
|
||||
'repaymentFrequencyType': this.loanProductsTemplate.repaymentFrequencyType.id,
|
||||
'minimumDaysBetweenDisbursalAndFirstRepayment': this.loanProductsTemplate.minimumDaysBetweenDisbursalAndFirstRepayment
|
||||
});
|
||||
|
||||
this.loanProductTermsForm.setControl('principalVariationsForBorrowerCycle',
|
||||
this.formBuilder.array(this.loanProductsTemplate.principalVariationsForBorrowerCycle.map((variation: any) => ({ ...variation, valueConditionType: variation.valueConditionType.id }))));
|
||||
this.loanProductTermsForm.setControl('numberOfRepaymentVariationsForBorrowerCycle',
|
||||
this.formBuilder.array(this.loanProductsTemplate.numberOfRepaymentVariationsForBorrowerCycle.map((variation: any) => ({ ...variation, valueConditionType: variation.valueConditionType.id }))));
|
||||
this.loanProductTermsForm.setControl('interestRateVariationsForBorrowerCycle',
|
||||
this.formBuilder.array(this.loanProductsTemplate.interestRateVariationsForBorrowerCycle.map((variation: any) => ({ ...variation, valueConditionType: variation.valueConditionType.id }))));
|
||||
}
|
||||
|
||||
createLoanProductTermsForm() {
|
||||
@@ -82,7 +109,7 @@ export class LoanProductTermsStepComponent implements OnInit {
|
||||
this.loanProductTermsForm.addControl('minInterestRatePerPeriod', new FormControl(''));
|
||||
this.loanProductTermsForm.addControl('interestRatePerPeriod', new FormControl('', Validators.required));
|
||||
this.loanProductTermsForm.addControl('maxInterestRatePerPeriod', new FormControl(''));
|
||||
this.loanProductTermsForm.addControl('interestRateFrequencyType', new FormControl(this.interestRateFrequencyTypeData[0].id, Validators.required));
|
||||
this.loanProductTermsForm.addControl('interestRateFrequencyType', new FormControl(this.interestRateFrequencyTypeData.id, Validators.required));
|
||||
this.loanProductTermsForm.removeControl('floatingRatesId');
|
||||
this.loanProductTermsForm.removeControl('interestRateDifferential');
|
||||
this.loanProductTermsForm.removeControl('isFloatingInterestRateCalculationAllowed');
|
||||
@@ -118,12 +145,19 @@ export class LoanProductTermsStepComponent implements OnInit {
|
||||
return this.loanProductTermsForm.get('interestRateVariationsForBorrowerCycle') as FormArray;
|
||||
}
|
||||
|
||||
setLoanProductTermsFormDirty() {
|
||||
if (this.loanProductTermsForm.pristine) {
|
||||
this.loanProductTermsForm.markAsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
addVariationsForBorrowerCycle(formType: string, variationsForBorrowerCycleFormArray: FormArray) {
|
||||
const data = this.getData(formType);
|
||||
const addVariationsForBorrowerCycleDialogRef = this.dialog.open(FormDialogComponent, { data });
|
||||
addVariationsForBorrowerCycleDialogRef.afterClosed().subscribe((response: any) => {
|
||||
if (response.data) {
|
||||
variationsForBorrowerCycleFormArray.push(response.data);
|
||||
this.setLoanProductTermsFormDirty();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -134,6 +168,7 @@ export class LoanProductTermsStepComponent implements OnInit {
|
||||
addVariationsForBorrowerCycleDialogRef.afterClosed().subscribe((response: any) => {
|
||||
if (response.data) {
|
||||
variationsForBorrowerCycleFormArray.at(index).patchValue(response.data.value);
|
||||
this.setLoanProductTermsFormDirty();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -145,6 +180,7 @@ export class LoanProductTermsStepComponent implements OnInit {
|
||||
deleteVariationsForBorrowerCycleDialogRef.afterClosed().subscribe((response: any) => {
|
||||
if (response.delete) {
|
||||
variationsForBorrowerCycleFormArray.removeAt(index);
|
||||
this.setLoanProductTermsFormDirty();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div fxLayout="row" fxLayoutAlign="end" fxLayoutGap="2%" fxLayout.lt-md="column" class="container m-b-20">
|
||||
<button mat-raised-button color="primary">
|
||||
<button mat-raised-button color="primary" [routerLink]="['edit']">
|
||||
<fa-icon icon="edit"></fa-icon>
|
||||
Edit
|
||||
</button>
|
||||
@@ -393,8 +393,8 @@
|
||||
<span fxFlex="40%">Frequency for compounding:</span>
|
||||
<span fxFlex="60%">
|
||||
{{ loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.value }}
|
||||
<span *ngIf="loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.id === 4 && loanProduct.interestRecalculationData.recalculationCompoundingFrequencyNthDay"> {{ 'on ' + loanProduct.interestRecalculationData.recalculationCompoundingFrequencyNthDay.value }}</span>
|
||||
<span *ngIf="(loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.id === 4 && !loanProduct.interestRecalculationData.recalculationCompoundingFrequencyOnDay) || loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.id === 3"> {{ loanProduct.interestRecalculationData.recalculationCompoundingFrequencyWeekday.value }}</span>
|
||||
<span *ngIf="loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.id === 4 && loanProduct.interestRecalculationData.recalculationCompoundingFrequencyNthDay"> {{ 'on ' + loanProduct.interestRecalculationData.recalculationCompoundingFrequencyNthDay?.value }}</span>
|
||||
<span *ngIf="(loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.id === 4 && !loanProduct.interestRecalculationData.recalculationCompoundingFrequencyOnDay) || loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.id === 3"> {{ loanProduct.interestRecalculationData.recalculationCompoundingFrequencyWeekday?.value }}</span>
|
||||
<span *ngIf="loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.id === 4 && loanProduct.interestRecalculationData.recalculationCompoundingFrequencyOnDay"> {{ 'on day ' + loanProduct.interestRecalculationData.recalculationCompoundingFrequencyOnDay }}</span>
|
||||
</span>
|
||||
<div fxFlexFill *ngIf="loanProduct.interestRecalculationData.recalculationCompoundingFrequencyType.id !== 1" fxLayout="row wrap" fxLayout.lt-md="column">
|
||||
@@ -410,8 +410,8 @@
|
||||
<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"> {{ 'on ' + loanProduct.interestRecalculationData.recalculationRestFrequencyNthDay.value }}</span>
|
||||
<span *ngIf="(loanProduct.interestRecalculationData.recalculationRestFrequencyType.id === 4 && !loanProduct.interestRecalculationData.recalculationRestFrequencyOnDay) || loanProduct.interestRecalculationData.recalculationRestFrequencyType.id === 3"> {{ loanProduct.interestRecalculationData.recalculationRestFrequencyWeekday.value }}</span>
|
||||
<span *ngIf="loanProduct.interestRecalculationData.recalculationRestFrequencyType.id === 4 && loanProduct.interestRecalculationData.recalculationRestFrequencyNthDay"> {{ 'on ' + loanProduct.interestRecalculationData.recalculationRestFrequencyNthDay?.value }}</span>
|
||||
<span *ngIf="(loanProduct.interestRecalculationData.recalculationRestFrequencyType.id === 4 && !loanProduct.interestRecalculationData.recalculationRestFrequencyOnDay) || loanProduct.interestRecalculationData.recalculationRestFrequencyType.id === 3"> {{ loanProduct.interestRecalculationData.recalculationRestFrequencyWeekday?.value }}</span>
|
||||
<span *ngIf="loanProduct.interestRecalculationData.recalculationRestFrequencyType.id === 4 && loanProduct.interestRecalculationData.recalculationRestFrequencyOnDay"> {{ 'on day ' + loanProduct.interestRecalculationData.recalculationRestFrequencyOnDay }}</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -13,6 +13,7 @@ import { ProductsComponent } from './products.component';
|
||||
import { LoanProductsComponent } from './loan-products/loan-products.component';
|
||||
import { CreateLoanProductComponent } from './loan-products/create-loan-product/create-loan-product.component';
|
||||
import { ViewLoanProductComponent } from './loan-products/view-loan-product/view-loan-product.component';
|
||||
import { EditLoanProductComponent } from './loan-products/edit-loan-product/edit-loan-product.component';
|
||||
import { ManageTaxConfigurationsComponent } from './manage-tax-configurations/manage-tax-configurations.component';
|
||||
import { RecurringDepositProductsComponent } from './recurring-deposit-products/recurring-deposit-products.component';
|
||||
import { ChargesComponent } from './charges/charges.component';
|
||||
@@ -24,6 +25,7 @@ import { ManageTaxComponentsComponent } from './manage-tax-components/manage-tax
|
||||
import { LoanProductsResolver } from './loan-products/loan-products.resolver';
|
||||
import { LoanProductsTemplateResolver } from './loan-products/loan-products-template.resolver';
|
||||
import { LoanProductResolver } from './loan-products/loan-product.resolver';
|
||||
import { LoanProductAndTemplateResolver } from './loan-products/edit-loan-product/loan-product-and-template.resolver';
|
||||
import { RecurringDepositProductsResolver } from './recurring-deposit-products/recurring-deposit-products.resolver';
|
||||
import { ChargesResolver } from './charges/charges.resolver';
|
||||
import { FixedDepositProductsResolver } from './fixed-deposit-products/fixed-deposit-products.resolver';
|
||||
@@ -62,11 +64,24 @@ const routes: Routes = [
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
component: ViewLoanProductComponent,
|
||||
data: { title: extract('View Loan Product'), routeParamBreadcrumb: 'id' },
|
||||
resolve: {
|
||||
loanProduct: LoanProductResolver
|
||||
}
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: ViewLoanProductComponent,
|
||||
resolve: {
|
||||
loanProduct: LoanProductResolver
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'edit',
|
||||
component: EditLoanProductComponent,
|
||||
data: { title: extract('Edit Loan Product'), breadcrumb: 'Edit', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanProductAndTemplate: LoanProductAndTemplateResolver
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -137,6 +152,7 @@ const routes: Routes = [
|
||||
LoanProductsResolver,
|
||||
LoanProductsTemplateResolver,
|
||||
LoanProductResolver,
|
||||
LoanProductAndTemplateResolver,
|
||||
RecurringDepositProductsResolver,
|
||||
ChargesResolver,
|
||||
FixedDepositProductsResolver,
|
||||
|
||||
@@ -25,6 +25,7 @@ import { FixedDepositProductsComponent } from './fixed-deposit-products/fixed-de
|
||||
import { ProductsMixComponent } from './products-mix/products-mix.component';
|
||||
import { ManageTaxComponentsComponent } from './manage-tax-components/manage-tax-components.component';
|
||||
import { ViewLoanProductComponent } from './loan-products/view-loan-product/view-loan-product.component';
|
||||
import { EditLoanProductComponent } from './loan-products/edit-loan-product/edit-loan-product.component';
|
||||
|
||||
/**
|
||||
* Products Module
|
||||
@@ -54,7 +55,8 @@ import { ViewLoanProductComponent } from './loan-products/view-loan-product/view
|
||||
FixedDepositProductsComponent,
|
||||
ProductsMixComponent,
|
||||
ManageTaxComponentsComponent,
|
||||
ViewLoanProductComponent
|
||||
ViewLoanProductComponent,
|
||||
EditLoanProductComponent
|
||||
],
|
||||
entryComponents: [
|
||||
],
|
||||
|
||||
@@ -33,8 +33,13 @@ export class ProductsService {
|
||||
return this.http.get('/loanproducts/template');
|
||||
}
|
||||
|
||||
getLoanProduct(loanProductId: string): Observable<any> {
|
||||
return this.http.get(`/loanproducts/${loanProductId}`);
|
||||
getLoanProduct(loanProductId: string, template: boolean = false): Observable<any> {
|
||||
const httpParams = new HttpParams().set('template', template.toString());
|
||||
return this.http.get(`/loanproducts/${loanProductId}`, { params: httpParams });
|
||||
}
|
||||
|
||||
updateLoanProduct(loanProductId: string, loanProduct: any): Observable<any> {
|
||||
return this.http.put(`/loanproducts/${loanProductId}`, loanProduct);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,12 +32,14 @@ export class FormDialogComponent implements OnInit {
|
||||
|
||||
form: FormGroup;
|
||||
formfields: FormfieldBase[];
|
||||
pristine: boolean;
|
||||
|
||||
constructor(public dialogRef: MatDialogRef<FormDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
private formGroupService: FormGroupService) {
|
||||
this.dialogRef.disableClose = !data.disableClose;
|
||||
this.dialogRef.disableClose = data.disableClose !== undefined ? data.disableClose : true;
|
||||
this.formfields = data.formfields.sort((formfieldA: FormfieldBase, formfieldB: FormfieldBase) => formfieldA.order - formfieldB.order);
|
||||
this.pristine = data.pristine !== undefined ? data.pristine : true;
|
||||
this.layout = { ...this.layout, ...data.layout };
|
||||
this.layout.gap = this.layout.columns > 1 ? layoutGap : 0;
|
||||
this.layout.flex = (this.layout.flex / this.layout.columns) - this.layout.gap;
|
||||
@@ -46,6 +48,9 @@ export class FormDialogComponent implements OnInit {
|
||||
ngOnInit() {
|
||||
this.dialogRef.updateSize(`${this.layout.columnWidth * this.layout.columns}px`);
|
||||
this.form = this.formGroupService.createFormGroup(this.formfields);
|
||||
if (!this.pristine) {
|
||||
this.form.markAsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user