diff --git a/src/app/loans/glim-account/create-glim-account/create-glim-account.component.html b/src/app/loans/glim-account/create-glim-account/create-glim-account.component.html
index 0407e0545..ac11c8cd3 100644
--- a/src/app/loans/glim-account/create-glim-account/create-glim-account.component.html
+++ b/src/app/loans/glim-account/create-glim-account/create-glim-account.component.html
@@ -27,6 +27,7 @@
[loansAccountTemplate]="loansAccountTemplate"
(loansAccountProductTemplate)="setTemplate($event)"
[gsimData]="gsimData"
+ #loansAccountDetailsForm
>
@@ -35,8 +36,10 @@
{{ 'labels.inputs.TERMS' | translate }}
@@ -45,8 +48,10 @@
{{ 'labels.inputs.CHARGES' | translate }}
diff --git a/src/app/loans/glim-account/create-glim-account/create-glim-account.component.ts b/src/app/loans/glim-account/create-glim-account/create-glim-account.component.ts
index 02a856642..24bc7b806 100644
--- a/src/app/loans/glim-account/create-glim-account/create-glim-account.component.ts
+++ b/src/app/loans/glim-account/create-glim-account/create-glim-account.component.ts
@@ -1,9 +1,12 @@
-import { Component, ViewChild } from '@angular/core';
-import { MatDialog } from '@angular/material/dialog';
+/** Angular Imports */
+import { Component, ViewChild, /* Felix: added: */ QueryList, ViewChildren } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
-import { Dates } from 'app/core/utils/dates';
+
+/** Custom Services */
import { LoansService } from 'app/loans/loans.service';
import { SettingsService } from 'app/settings/settings.service';
+
+/** Step Components */
import { GlimChargesStepComponent } from './glim-account-stepper/glim-charges-step/glim-charges-step.component';
import { GlimDetailsStepComponent } from './glim-account-stepper/glim-details-step/glim-details-step.component';
import { GlimTermsStepComponent } from './glim-account-stepper/glim-terms-step/glim-terms-step.component';
@@ -14,7 +17,7 @@ import { GlimTermsStepComponent } from './glim-account-stepper/glim-terms-step/g
styleUrls: ['./create-glim-account.component.scss']
})
export class CreateGlimAccountComponent {
- /** Imports all the step component */
+ /** Imports all the step components */
@ViewChild(GlimDetailsStepComponent, { static: true }) loansAccountDetailsStep: GlimDetailsStepComponent;
@ViewChild(GlimTermsStepComponent, { static: true }) loansAccountTermsStep: GlimTermsStepComponent;
@ViewChild(GlimChargesStepComponent, { static: true }) loansAccountChargesStep: GlimChargesStepComponent;
@@ -22,38 +25,39 @@ export class CreateGlimAccountComponent {
/** Loans Account Template */
loansAccountTemplate: any;
/** Loans Account Product Template */
- loansAccountProductTemplate: any;
- /** Collateral Options */
- collateralOptions: any;
+ loansAccountProductTemplate: any | null = null;
/** Multi Disburse Loan */
multiDisburseLoan: any;
/** Principal Amount */
principal: any;
+ /** Currency Code */
+ currencyCode: string;
- accountLinkingOptions: any;
+ // accountLinkingOptions: any;
- totalLoan: any;
+ // totalLoan: any;
- /** Table Data Source */
- dataSource: any;
- /** Selected Members */
+ // /** Table Data Source */
+ // dataSource: any;
+ // /** Selected Members */
selectedMembers: any;
- /** Selected Members */
+ // /** Selected Members */
activeClientMembers: any;
gsimData: any;
+
/**
- * Sets loans account details form.
- * @param {FormBuilder} formBuilder Form Builder.
- * @param {LoansService} loansService Loans Service.
- * @param {SettingsService} settingsService SettingsService
+ * Sets loans account create form.
+ * @param {route} ActivatedRoute Activated Route.
+ * @param {router} Router Router.
+ * @param {loansService} LoansService Loans Service
+ * @param {SettingsService} settingsService Settings Service
+ * @param {ClientsService} clientService Client Service
*/
constructor(
private route: ActivatedRoute,
private router: Router,
private loansService: LoansService,
- private settingsService: SettingsService,
- public dialog: MatDialog,
- private dateUtils: Dates
+ private settingsService: SettingsService
) {
this.route.data.subscribe((data: { loansAccountTemplate: any; gsimData: any; groupsData: any }) => {
this.loansAccountTemplate = data.loansAccountTemplate;
@@ -63,11 +67,19 @@ export class CreateGlimAccountComponent {
}
/**
- * Sets loans account product template and collateral template
+ * Sets glim account product template and collateral template
* @param {any} $event API response
*/
setTemplate($event: any) {
this.loansAccountProductTemplate = $event;
+ this.currencyCode = this.loansAccountProductTemplate.currency.code;
+ const entityId = this.loansAccountTemplate.clientId
+ ? this.loansAccountTemplate.clientId
+ : this.loansAccountTemplate.group.id;
+ const productId = this.loansAccountProductTemplate.loanProductId;
+ this.loansService.getLoansAccountTemplateResource(entityId, true, productId).subscribe((response: any) => {
+ this.multiDisburseLoan = response.multiDisburseLoan;
+ });
}
/** Get Loans Account Details Form Data */
@@ -80,86 +92,102 @@ export class CreateGlimAccountComponent {
return this.loansAccountTermsStep.loansAccountTermsForm;
}
- /** Checks wheter all the forms in different steps are valid or not */
+ /** Checks whether all the forms in different steps are valid or not */
get loansAccountFormValid() {
- return this.loansAccountDetailsForm.valid && this.loansAccountTermsForm.valid;
+ return (
+ this.loansAccountDetailsForm.valid && this.loansAccountTermsForm.valid && this.loansAccountChargesStep.isValid
+ );
}
/** Gets principal Amount */
get loanPrincipal() {
- return this.loansAccountTermsStep.loansAccountTermsForm.value.principal;
+ return this.loansAccountChargesStep.selectedClientMembers.selectedMembers.reduce(
+ (acc: number, member: any) => acc + member.principal,
+ 0
+ );
}
/** Retrieves Data of all forms except Currency to submit the data */
get loansAccount() {
- this.selectedMembers = this.loansAccountChargesStep.selectedClientMembers;
return {
...this.loansAccountDetailsStep.loansAccountDetails,
...this.loansAccountTermsStep.loansAccountTerms,
- ...this.loansAccountChargesStep.loansAccountCharges
+ ...this.loansAccountChargesStep.loansAccountCharges,
+ ...this.loansAccountTermsStep.disbursementData
};
}
- setData(client: any): any {
- const locale = this.settingsService.language.code;
- const dateFormat = this.settingsService.dateFormat;
- // const monthDayFormat = 'dd MMMM';
- const data = {
- ...this.loansAccount,
- charges: this.loansAccount.charges.map((charge: any) => ({
- chargeId: charge.id,
- amount: charge.amount
- })),
- clientId: client.id,
- totalLoan: this.totalLoan,
- loanType: 'glim',
- amortizationType: 1,
- isParentAccount: true,
- principal: client.principal,
- syncDisbursementWithMeeting: false,
- expectedDisbursementDate: this.dateUtils.formatDate(this.loansAccount.expectedDisbursementDate, dateFormat),
- submittedOnDate: this.dateUtils.formatDate(this.loansAccount.submittedOnDate, dateFormat),
- dateFormat,
- // monthDayFormat,
- locale
- };
- data.groupId = this.loansAccountTemplate.group.id;
+ // setData(client: any): any {
+ // const locale = this.settingsService.language.code;
+ // const dateFormat = this.settingsService.dateFormat;
+ // // const monthDayFormat = 'dd MMMM';
+ // const data = {
+ // ...this.loansAccount,
+ // charges: this.loansAccount.charges.map((charge: any) => ({
+ // chargeId: charge.id,
+ // amount: charge.amount
+ // })),
+ // clientId: client.id,
+ // totalLoan: this.totalLoan,
+ // loanType: 'glim',
+ // amortizationType: 1,
+ // isParentAccount: true,
+ // principal: client.principal,
+ // syncDisbursementWithMeeting: false,
+ // expectedDisbursementDate: this.dateUtils.formatDate(this.loansAccount.expectedDisbursementDate, dateFormat),
+ // submittedOnDate: this.dateUtils.formatDate(this.loansAccount.submittedOnDate, dateFormat),
+ // dateFormat,
+ // // monthDayFormat,
+ // locale
+ // };
+ // data.groupId = this.loansAccountTemplate.group.id;
- return JSON.stringify(data);
- }
-
- /** Request Body Data */
- buildRequestData(): any[] {
- const requestData = [];
- const memberSelected = this.selectedMembers.selectedMembers;
- this.totalLoanAmount();
- for (let index = 0; index < memberSelected.length; index++) {
- requestData.push({
- requestId: index.toString(),
- method: 'POST',
- relativeUrl: 'loans',
- body: this.setData(memberSelected[index])
- });
- }
- return requestData;
- }
-
- totalLoanAmount(): any {
- let total = 0;
- const memberSelected = this.selectedMembers.selectedMembers;
- for (let index = 0; index < memberSelected.length; index++) {
- total += memberSelected[index].principal;
- }
- this.totalLoan = total;
- }
+ // return JSON.stringify(data);
+ // }
/**
- * Creates a new GSIM account.
+ * Creates a new GLIM account.
*/
submit() {
- const data = this.buildRequestData();
- this.loansService.createGlimAccount(data).subscribe((response: any) => {
- this.router.navigate(['../../../'], { relativeTo: this.route });
+ const locale = this.settingsService.language.code;
+ const dateFormat = this.settingsService.dateFormat;
+
+ const totalLoan = this.loanPrincipal;
+ const payloadData: any[] = [];
+ this.loansAccountChargesStep.selectedClientMembers.selectedMembers.forEach((member: any, index: number) => {
+ this.loansAccountTemplate.clientId = member.id;
+ this.loansAccountTemplate.loanPurposeId = member.loanPurposeId;
+ this.loansAccountTemplate.principal = member.principal;
+ this.loansAccountTemplate.totalLoan = totalLoan;
+
+ const payload = this.loansService.buildLoanRequestPayload(
+ this.loansAccount,
+ this.loansAccountTemplate,
+ this.loansAccountProductTemplate.calendarOptions,
+ locale,
+ dateFormat
+ );
+
+ payloadData.push(this.getWrapper(payload, index));
+ });
+
+ this.loansService.createGlimAccount(payloadData).subscribe((response: any) => {
+ this.router.navigate(
+ [
+ '../',
+ JSON.parse(response[0].body).glimId
+ ],
+ { relativeTo: this.route }
+ );
});
}
+
+ getWrapper(payload: any, requestId: number): any {
+ return {
+ body: JSON.stringify(payload),
+ method: 'POST',
+ relativeUrl: 'loans',
+ requestId: requestId
+ };
+ }
}
diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.html b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.html
index 8bdc35a5d..d411cac88 100644
--- a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.html
+++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.html
@@ -91,21 +91,6 @@
-
- | {{ 'labels.inputs.Repayments Every' | translate }} |
-
- {{ charge.feeInterval || 'Not Provided' }}
-
- |
-
-
{{ 'labels.inputs.Actions' | translate }} |
@@ -115,8 +100,35 @@
|
-
-
+
+
+
+
+ {{ 'labels.heading.Overdue Charges' | translate }}
+
+
+
+ | {{ 'labels.inputs.name' | translate }} |
+ {{ charge.name }},{{ charge.currency.displaySymbol }} |
+
+
+
+ {{ 'labels.inputs.Type' | translate }} |
+ {{ charge.chargeCalculationType.value }} |
+
+
+
+ {{ 'labels.inputs.Amount' | translate }} |
+ {{ charge.amount | formatNumber }} |
+
+
+
+ {{ 'labels.inputs.Collected On' | translate }} |
+ {{ charge.chargeTimeType.value }} |
+
+
+
+
@@ -179,8 +191,11 @@
{{ 'labels.buttons.Previous' | translate }}
-
diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.scss b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.scss
index e69de29bb..b66af2377 100644
--- a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.scss
+++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.scss
@@ -0,0 +1,3 @@
+.margin-t {
+ margin-top: 2em;
+}
diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.ts b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.ts
index eba57fe25..f258ec13b 100644
--- a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.ts
+++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.ts
@@ -1,13 +1,23 @@
+/** Angular Imports */
import { Component, Input, OnInit, OnChanges } from '@angular/core';
-import { FormControl } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { MatTableDataSource } from '@angular/material/table';
-import { Dates } from 'app/core/utils/dates';
+
+/** Dialog Components */
+import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component';
import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component';
+
+/** Custom Services */
import { DatepickerBase } from 'app/shared/form-dialog/formfield/model/datepicker-base';
import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield-base';
import { InputBase } from 'app/shared/form-dialog/formfield/model/input-base';
+import { SettingsService } from 'app/settings/settings.service';
+import { Dates } from 'app/core/utils/dates';
+import { ActivatedRoute } from '@angular/router';
+/**
+ * GLIM Account Charges Step
+ */
@Component({
selector: 'mifosx-glim-charges-step',
templateUrl: './glim-charges-step.component.html',
@@ -18,29 +28,34 @@ export class GlimChargesStepComponent implements OnInit, OnChanges {
@Input() loansAccountProductTemplate: any;
/** Savings Account Template */
@Input() loansAccountTemplate: any;
- /** Currency Code */
- // @Input() currencyCode: FormControl;
- // /** active Client Members in case of GLIM Account */
+ // @Input() loansAccountFormValid: LoansAccountFormValid
+ @Input() loansAccountFormValid: boolean;
+ // active Client Members in case of GLIM Account
@Input() activeClientMembers?: any;
/** Charge Data */
chargeData: any = [];
/** Charges Data Source */
chargesDataSource: {}[] = [];
- /** Component is pristine if there has been no changes by user interaction */
- pristine = true;
- /** For Edit Savings Account Form */
- isChargesPatched = false;
+ /** Overdue Charges Data Source */
+ overDueChargesDataSource: {}[] = [];
/** Display columns for charges table */
- displayedColumns: string[] = [
+ chargesDisplayedColumns: string[] = [
'name',
'chargeCalculationType',
'amount',
'chargeTimeType',
'date',
- 'repaymentsEvery',
'action'
];
+ /** Columns to be displayed in overdue charges table. */
+ overdueChargesDisplayedColumns: string[] = [
+ 'name',
+ 'type',
+ 'amount',
+ 'collectedon'
+ ];
+
/** Table Data Source */
dataSource: any;
/** Check for select all the Clients List */
@@ -55,22 +70,53 @@ export class GlimChargesStepComponent implements OnInit, OnChanges {
'purpose',
'amount'
];
+ /** Component is pristine if there has been no changes by user interaction */
+ pristine = true;
+ loanId: any = null;
/**
- * @param {MatDialog} dialog Mat Dialog
+ * GLIM Account Charges Form Step
+ * @param {dialog} MatDialog Mat Dialog
+ * @param {Dates} dateUtils Date Utils
+ * @param {ActivatedRoute} route Activated Route
+ * @param {SettingsService} settingsService Settings Service
*/
constructor(
public dialog: MatDialog,
- private dateUtils: Dates
- ) {}
+ private dateUtils: Dates,
+ private route: ActivatedRoute,
+ private settingsService: SettingsService
+ ) {
+ this.loanId = this.route.snapshot.params['loanId'];
+ }
ngOnInit() {
+ // TODO: This might still need adjustments due to GLIM
this.dataSource = new MatTableDataSource(this.activeClientMembers);
+
+ // Loan Account code:
+ if (this.loansAccountTemplate.charges) {
+ this.chargesDataSource =
+ this.loansAccountTemplate.charges.map((charge: any) => ({ ...charge, id: charge.chargeId })) || [];
+ }
}
ngOnChanges() {
if (this.loansAccountProductTemplate) {
+ this.loanPurposeOptions = this.loansAccountProductTemplate.loanPurposeOptions;
+
this.chargeData = this.loansAccountProductTemplate.chargeOptions;
+ if (this.loansAccountProductTemplate.overdueCharges) {
+ this.overDueChargesDataSource = this.loansAccountProductTemplate.overdueCharges;
+ }
+ if (
+ this.loansAccountProductTemplate.charges &&
+ this.loansAccountProductTemplate.charges.length > 0 &&
+ this.chargesDataSource.length === 0
+ ) {
+ this.chargesDataSource =
+ this.loansAccountProductTemplate.charges.map((charge: any) => ({ ...charge, id: charge.chargeId })) || [];
+ }
}
}
@@ -139,7 +185,7 @@ export class GlimChargesStepComponent implements OnInit, OnChanges {
editNoteDialogRef.afterClosed().subscribe((response: any) => {
if (response.data) {
let newCharge: any;
- const dateFormat = 'dd MMMM yyyy';
+ const dateFormat = this.settingsService.dateFormat;
const date = this.dateUtils.formatDate(response.data.value.date, dateFormat);
switch (charge.chargeTimeType.value) {
case 'Specified due date':
@@ -193,9 +239,16 @@ export class GlimChargesStepComponent implements OnInit, OnChanges {
* @param {any} charge Charge
*/
deleteCharge(charge: any) {
- this.chargesDataSource.splice(this.chargesDataSource.indexOf(charge), 1);
- this.chargesDataSource = this.chargesDataSource.concat([]);
- this.pristine = false;
+ const deleteChargeDialogRef = this.dialog.open(DeleteDialogComponent, {
+ data: { deleteContext: `charge ${charge.name}` }
+ });
+ deleteChargeDialogRef.afterClosed().subscribe((response: any) => {
+ if (response.delete) {
+ this.chargesDataSource.splice(this.chargesDataSource.indexOf(charge), 1);
+ this.chargesDataSource = this.chargesDataSource.concat([]);
+ this.pristine = false;
+ }
+ });
}
/**
@@ -209,14 +262,19 @@ export class GlimChargesStepComponent implements OnInit, OnChanges {
return { selectedMembers: this.activeClientMembers.filter((item: any) => item.selected) };
}
- /** Toggle all checks */
+ get isValid() {
+ const sum = this.activeClientMembers
+ ?.filter((item: any) => item.selected)
+ .reduce((acc: number, member: any) => acc + member.principal, 0);
+ return sum > 0;
+ }
+
toggleSelects() {
for (const member of this.activeClientMembers) {
member.selected = this.selectAllItems;
}
}
- /** Check if all the checks are selected */
toggleSelect() {
const len = this.activeClientMembers.length;
this.selectAllItems =
diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.html b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.html
index de9eb3b9c..a4a122e08 100644
--- a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.html
+++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.html
@@ -1,9 +1,16 @@
diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.ts b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.ts
index 39398ff59..8f4f51b16 100644
--- a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.ts
+++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.ts
@@ -1,14 +1,28 @@
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
-import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
-import { LoansService } from 'app/loans/loans.service';
+/** Angular Imports */
+import { Component, OnInit, Input, Output, EventEmitter, OnDestroy } from '@angular/core';
+import { UntypedFormGroup, UntypedFormBuilder, Validators, UntypedFormControl } from '@angular/forms';
+import { ActivatedRoute } from '@angular/router';
import { SettingsService } from 'app/settings/settings.service';
+/** Custom Services */
+import { LoansService } from '../../../../loans.service';
+import { Commons } from 'app/core/utils/commons';
+import { takeUntil } from 'rxjs/operators';
+import { ReplaySubject, Subject } from 'rxjs';
+
+// Felix: TODO's:
+// - gsimData was already declared, when I found this file. Apparently,
+// glim accounts can only be linked to gsim accounts. Needs to be tested
+// as soon as gsim accounts are implemented.
+/**
+ * GLIM Account Details Step
+ */
@Component({
selector: 'mifosx-glim-details-step',
templateUrl: './glim-details-step.component.html',
styleUrls: ['./glim-details-step.component.scss']
})
-export class GlimDetailsStepComponent implements OnInit {
+export class GlimDetailsStepComponent implements OnInit, OnDestroy {
/** Loans Account Template */
@Input() loansAccountTemplate: any;
@Input() gsimData: any;
@@ -17,7 +31,7 @@ export class GlimDetailsStepComponent implements OnInit {
/** Maximum date allowed. */
maxDate = new Date(2100, 0, 1);
/** Product Data */
- productData: any;
+ productList: any;
/** Loan Officer Data */
loanOfficerOptions: any;
/** Loan Purpose Options */
@@ -31,6 +45,16 @@ export class GlimDetailsStepComponent implements OnInit {
/** Loans Account Details Form */
loansAccountDetailsForm: UntypedFormGroup;
+ loanId: any = null;
+
+ loanProductSelected = false;
+ /** Currency data. */
+ protected productData: ReplaySubject = new ReplaySubject(1);
+ /** control for the filter select */
+ protected filterFormCtrl: UntypedFormControl = new UntypedFormControl('');
+ /** Subject that emits when the component has been destroyed. */
+ protected _onDestroy = new Subject();
+
/** Loans Account Template with product data */
@Output() loansAccountProductTemplate = new EventEmitter();
/**
@@ -42,17 +66,21 @@ export class GlimDetailsStepComponent implements OnInit {
constructor(
private formBuilder: UntypedFormBuilder,
private loansService: LoansService,
- private settingsService: SettingsService
+ private route: ActivatedRoute,
+ private settingsService: SettingsService,
+ private commons: Commons
) {
- this.createLoansAccountDetailsForm();
+ this.loanId = this.route.snapshot.params['loanId'];
}
ngOnInit(): void {
- this.maxDate = this.settingsService.businessDate;
+ this.createLoansAccountDetailsForm();
+ this.maxDate = this.settingsService.maxFutureDate; // Felix: originally: businessDate;
this.buildDependencies();
if (this.loansAccountTemplate) {
- this.productData = this.loansAccountTemplate.productOptions;
+ this.productList = this.loansAccountTemplate.productOptions.sort(this.commons.dynamicSort('name'));
if (this.loansAccountTemplate.loanProductId) {
+ console.log('this.loansAccountTemplate.loanOfficerId: ', this.loansAccountTemplate.loanOfficerId);
this.loansAccountDetailsForm.patchValue({
productId: this.loansAccountTemplate.loanProductId,
submittedOnDate:
@@ -68,6 +96,31 @@ export class GlimDetailsStepComponent implements OnInit {
});
}
}
+ this.filterFormCtrl.valueChanges.pipe(takeUntil(this._onDestroy)).subscribe(() => {
+ this.searchItem();
+ });
+ this.productData.next(this.productList.slice());
+ }
+
+ ngOnDestroy(): void {
+ this._onDestroy.next();
+ this._onDestroy.complete();
+ }
+
+ searchItem(): void {
+ if (this.productList) {
+ const search: string = this.filterFormCtrl.value.toLowerCase();
+
+ if (!search) {
+ this.productData.next(this.productList.slice());
+ } else {
+ this.productData.next(
+ this.productList.filter((option: any) => {
+ return option['name'].toLowerCase().indexOf(search) >= 0;
+ })
+ );
+ }
+ }
}
/**
@@ -80,6 +133,7 @@ export class GlimDetailsStepComponent implements OnInit {
Validators.required
],
loanOfficerId: [''],
+ // Felix: found: loanPurposeId: [''], - not sure, where we add this list...
fundId: [''],
submittedOnDate: [
new Date(),
@@ -89,7 +143,9 @@ export class GlimDetailsStepComponent implements OnInit {
'',
Validators.required
],
- linkAccountId: ['']
+ externalId: [''],
+ linkAccountId: [''],
+ createStandingInstructionAtDisbursement: ['']
});
}
@@ -105,6 +161,7 @@ export class GlimDetailsStepComponent implements OnInit {
this.loanPurposeOptions = response.loanPurposeOptions;
this.fundOptions = response.fundOptions;
this.accountLinkingOptions = response.accountLinkingOptions;
+ this.loanProductSelected = true;
});
});
}
@@ -113,6 +170,6 @@ export class GlimDetailsStepComponent implements OnInit {
* Returns loans account details form value.
*/
get loansAccountDetails() {
- return this.loansAccountDetailsForm.value;
+ return this.loansAccountDetailsForm.getRawValue(); // Felix: was: value;
}
}
diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.html b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.html
index 98712759a..134c04b53 100644
--- a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.html
+++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.html
@@ -1,8 +1,6 @@
{{ 'labels.heading.Details' | translate }}
-
-
{{ 'labels.inputs.Product' | translate }}:
{{ loansAccount.productId | find: loansAccountTemplate.productOptions : 'id' : 'name' }}
@@ -50,11 +48,16 @@
{{ 'labels.inputs.Principal' | translate }}:
- {{ loansAccount.principal }} {{ loansAccountProductTemplate.currency.DisplaySymbol }}
+
+ {{
+ loansAccount.principalAmount | currency: loansAccountProductTemplate.currency.code : 'symbol-narrow' : '1.2-2'
+ }}
+ {{ loansAccountProductTemplate.currency.code }}
+
- {{ 'labels.inputs.Loan term' | translate }}:
+ {{ 'labels.inputs.Loan Term' | translate }}:
{{ loansAccount.loanTermFrequency }}
{{
@@ -86,6 +89,11 @@
>
+
+ {{ 'labels.inputs.Enable Down Payments' | translate }}:
+ {{ loansAccount.enableDownPayment | yesNo }}
+
+
{{ 'labels.inputs.First repayment on' | translate }}:
{{ loansAccount.repaymentsStartingFromDate | dateFormat }}
@@ -137,9 +145,7 @@
{{ 'labels.inputs.Arrears tolerance' | translate }}:
- {{ loansAccount.inArrearsTolerance }} {{ loansAccountProductTemplate.currency.displaySymbol }}
+ {{ loansAccount.inArrearsTolerance }}
@@ -151,14 +157,24 @@
{{ 'labels.inputs.Repayment strategy' | translate }}:
{{
loansAccount.transactionProcessingStrategyCode
- | find: loansAccountTemplate.transactionProcessingStrategyOptions : 'code' : 'name'
+ | find: loansAccountProductTemplate.transactionProcessingStrategyOptions : 'code' : 'name'
}}
-
{{ 'labels.heading.Moratorium' | translate }}
+
+ {{ 'labels.inputs.Installment Amount' | translate }}
+ {{ loansAccount.fixedEmiAmount | formatNumber }}
+
+
+
+ {{ 'labels.inputs.Balloon Repayment Amount' | translate }}
+ {{ loansAccount.balloonRepaymentAmount | formatNumber }}
+
+
{{ 'labels.heading.Moratorium' | translate }}
+
{{ 'labels.inputs.On principal payment' | translate }}:
{{ loansAccount.graceOnPrincipalPayment }}
@@ -174,6 +190,11 @@
{{ loansAccount.graceOnArrearsAgeing }}
+
+ {{ 'labels.inputs.Enable installment level Delinquency' | translate }}
+ {{ loansAccount.enableInstallmentLevelDelinquency | yesNo }}
+
+
{{ 'labels.inputs.Is Topup Loan' | translate }}?
{{ loansAccount.isTopup }}
@@ -291,7 +312,7 @@
{{ 'labels.buttons.Previous' | translate }}
-
+
{{ 'labels.buttons.Cancel' | translate }}
diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.ts b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.ts
index 6eb58456f..67d563d06 100644
--- a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.ts
+++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.ts
@@ -1,13 +1,16 @@
-import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { Component, EventEmitter, Input, Output, OnChanges, SimpleChanges } from '@angular/core';
+/**
+ * Create GLIM Account Preview Step
+ */
@Component({
selector: 'mifosx-glim-preview-step',
templateUrl: './glim-preview-step.component.html',
styleUrls: ['./glim-preview-step.component.scss']
})
-export class GlimPreviewStepComponent {
+export class GlimPreviewStepComponent implements OnChanges {
/** Loans Account Template */
- @Input() loansAccountTemplate: any;
+ @Input() loansAccountTemplate: any = [];
/** Loans Account Product Template */
@Input() loansAccountProductTemplate: any;
/** Loans Account Data */
@@ -31,5 +34,11 @@ export class GlimPreviewStepComponent {
'collectedon'
];
+ productEnableDownPayment = false;
+
constructor() {}
+
+ ngOnChanges(changes: SimpleChanges): void {
+ this.productEnableDownPayment = this.loansAccountProductTemplate.product.enableDownPayment;
+ }
}
diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.html b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.html
index db897a126..0c107079b 100644
--- a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.html
+++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.html
@@ -1,21 +1,38 @@
diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.scss b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.scss
index e69de29bb..b66af2377 100644
--- a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.scss
+++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.scss
@@ -0,0 +1,3 @@
+.margin-t {
+ margin-top: 2em;
+}
diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.ts b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.ts
index 6e5cfac16..76c19446d 100644
--- a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.ts
+++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.ts
@@ -1,17 +1,45 @@
+/** Angular Imports */
import { Component, Input, OnInit, OnChanges } from '@angular/core';
-import { UntypedFormGroup, UntypedFormBuilder, Validators, FormArray } from '@angular/forms';
-import { SettingsService } from 'app/settings/settings.service';
+import { UntypedFormGroup, UntypedFormBuilder, Validators, UntypedFormControl } from '@angular/forms';
+import { MatDialog } from '@angular/material/dialog';
+import { ActivatedRoute } from '@angular/router';
+/** Custom Services */
+// import { LoansAccountAddCollateralDialogComponent } from 'app/loans/custom-dialog/loans-account-add-collateral-dialog/loans-account-add-collateral-dialog.component';
+import { LoanProducts } from 'app/products/loan-products/loan-products';
+import { LoanProduct } from 'app/products/loan-products/models/loan-product.model';
+import { SettingsService } from 'app/settings/settings.service';
+import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component';
+import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component';
+import { DatepickerBase } from 'app/shared/form-dialog/formfield/model/datepicker-base';
+import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield-base';
+import { InputBase } from 'app/shared/form-dialog/formfield/model/input-base';
+// import { Currency } from 'app/shared/models/general.model';
+import { CodeName, OptionData } from 'app/shared/models/option-data.model';
+
+/**
+ * Create GLIM Terms Step
+ */
@Component({
selector: 'mifosx-glim-terms-step',
templateUrl: './glim-terms-step.component.html',
styleUrls: ['./glim-terms-step.component.scss']
})
export class GlimTermsStepComponent implements OnInit, OnChanges {
+ /** Loans Product Options */
+ @Input() loansProductOptions: any;
/** Loans Account Product Template */
@Input() loansAccountProductTemplate: any;
/** Loans Account Template */
@Input() loansAccountTemplate: any;
+ loansAccountTermsData: any;
+
+ /** Is Multi Disburse Loan */
+ multiDisburseLoan: any;
+ // @Input() loansAccountFormValid: LoansAccountFormValid
+ @Input() loansAccountFormValid: boolean;
+ // @Input loanPrincipal: Loan Principle
+ @Input() loanPrincipal: any;
/** Minimum date allowed. */
minDate = new Date(2000, 0, 1);
@@ -31,86 +59,292 @@ export class GlimTermsStepComponent implements OnInit, OnChanges {
amortizationTypeData: any;
/** Interest Calculation Period Type Data */
interestCalculationPeriodTypeData: any;
- /** Transaction Processing Strategy Data */
- transactionProcessingStrategyData: any;
/** Client Active Loan Data */
clientActiveLoanData: any;
+ /** Multi Disbursement Data */
+ disbursementDataSource: {}[] = [];
+ /** Loan repayment strategies */
+ transactionProcessingStrategyOptions: any = [];
+ repaymentStrategyDisabled = false;
+ /** Disbursement Data Displayed Columns */
+ disbursementDisplayedColumns: string[] = [
+ 'expectedDisbursementDate',
+ 'principal',
+ 'actions'
+ ];
+ /** Multi Disbursement Control */
+ totalMultiDisbursed: any = 0;
+ isMultiDisbursedCompleted = false;
+
+ /** Component is pristine if there has been no changes by user interaction */
+ pristine = true;
+
+ loanId: any = null;
+ loanScheduleType: OptionData | null = null;
+ loanProduct: LoanProduct | null = null;
+ interestRateFrequencyTypeData: any[] = [];
+ // currency: Currency;
+
+ productEnableDownPayment = false;
+ isProgressive = false;
/**
* Create Loans Account Terms Form
* @param formBuilder FormBuilder
* @param {SettingsService} settingsService SettingsService
+ * @param {ActivatedRoute} route ActivatedRoute
+ * @param {MatDialog} dialog MatDialog
*/
constructor(
private formBuilder: UntypedFormBuilder,
- private settingsService: SettingsService
+ private settingsService: SettingsService,
+ private route: ActivatedRoute,
+ public dialog: MatDialog
) {
- this.createloansAccountTermsForm();
+ this.loanId = this.route.snapshot.params['loanId'];
+ this.createGLIMTermsForm();
}
/**
* Executes on change of input values
*/
ngOnChanges() {
if (this.loansAccountProductTemplate) {
+ // this.currency = this.loansAccountProductTemplate.currency;
+
+ this.loansAccountTermsData = this.loansAccountProductTemplate;
+ if (this.loanId != null && this.loansAccountTemplate.accountNo) {
+ this.loansAccountTermsData = this.loansAccountTemplate;
+ }
+ this.productEnableDownPayment = this.loansAccountTermsData.product.enableDownPayment;
+ this.isProgressive =
+ this.loansAccountTermsData.loanScheduleType.code == LoanProducts.LOAN_SCHEDULE_TYPE_PROGRESSIVE;
+ if (this.loansAccountTermsData.product) {
+ this.loanProduct = this.loansAccountTermsData.product;
+ }
+
+ this.interestRateFrequencyTypeData = this.loansAccountTermsData.interestRateFrequencyTypeOptions;
+
this.loansAccountTermsForm.patchValue({
- principal: this.loansAccountProductTemplate.principal,
- loanTermFrequency: this.loansAccountProductTemplate.termFrequency,
- loanTermFrequencyType: this.loansAccountProductTemplate.termPeriodFrequencyType.id,
- numberOfRepayments: this.loansAccountProductTemplate.numberOfRepayments,
- repaymentEvery: this.loansAccountProductTemplate.repaymentEvery,
- repaymentFrequencyType: this.loansAccountProductTemplate.repaymentFrequencyType.id,
- interestRatePerPeriod: this.loansAccountProductTemplate.interestRatePerPeriod,
- interestType: this.loansAccountProductTemplate.interestType.id,
- interestCalculationPeriodType: this.loansAccountProductTemplate.interestCalculationPeriodType.id,
- transactionProcessingStrategyCode: this.loansAccountProductTemplate.transactionProcessingStrategyCode
+ principalAmount: this.loansAccountTermsData.principal,
+ loanTermFrequency: this.loansAccountTermsData.termFrequency,
+ loanTermFrequencyType: this.loansAccountTermsData.termPeriodFrequencyType.id,
+ numberOfRepayments: this.loansAccountTermsData.numberOfRepayments,
+ repaymentEvery: this.loansAccountTermsData.repaymentEvery,
+ repaymentFrequencyType: this.loansAccountTermsData.repaymentFrequencyType.id,
+ amortizationType: this.loansAccountTermsData.amortizationType.id,
+ isEqualAmortization: this.loansAccountTermsData.isEqualAmortization,
+ interestType: this.loansAccountTermsData.interestType.id,
+ isFloatingInterestRate: this.loansAccountTermsData.isLoanProductLinkedToFloatingRate ? false : '',
+ interestCalculationPeriodType: this.loansAccountTermsData.interestCalculationPeriodType.id,
+ allowPartialPeriodInterestCalculation: this.loansAccountTermsData.allowPartialPeriodInterestCalculation,
+ inArrearsTolerance: this.loansAccountTermsData.inArrearsTolerance,
+ graceOnInterestCharged: this.loansAccountTermsData.graceOnInterestCharged,
+ fixedEmiAmount: this.loansAccountTermsData.fixedEmiAmount,
+ maxOutstandingLoanBalance: this.loansAccountTermsData.maxOutstandingLoanBalance,
+ transactionProcessingStrategyCode: this.loansAccountTermsData.transactionProcessingStrategyCode,
+ interestRateDifferential: this.loansAccountTermsData.interestRateDifferential,
+ multiDisburseLoan: this.loansAccountTermsData.multiDisburseLoan,
+ interestRateFrequencyType: this.loansAccountTermsData.interestRateFrequencyType.id,
+ balloonRepaymentAmount: this.loansAccountTermsData.balloonRepaymentAmount,
+ interestRecognitionOnDisbursementDate: this.loansAccountTermsData.interestRecognitionOnDisbursementDate || false
});
+
+ this.setAdvancedPaymentStrategyControls();
+
+ if (this.loansAccountTermsData.loanScheduleType.code == LoanProducts.LOAN_SCHEDULE_TYPE_CUMULATIVE) {
+ this.loansAccountTermsForm.removeControl('interestRecognitionOnDisbursementDate');
+ }
+
+ if (this.loansAccountTermsData.isLoanProductLinkedToFloatingRate) {
+ this.loansAccountTermsForm.removeControl('interestRatePerPeriod');
+ }
+
+ this.multiDisburseLoan = this.loansAccountTermsData.multiDisburseLoan;
+ if (this.loansAccountTermsData.disbursementDetails) {
+ this.disbursementDataSource = this.loansAccountTermsData.disbursementDetails;
+ this.totalMultiDisbursed = 0;
+ this.disbursementDataSource.forEach((item: any) => {
+ this.totalMultiDisbursed += item.principal;
+ });
+ }
+ if (this.isDelinquencyEnabled()) {
+ this.loansAccountTermsForm.addControl(
+ 'enableInstallmentLevelDelinquency',
+ new UntypedFormControl(
+ this.loansAccountTermsData.enableInstallmentLevelDelinquency ||
+ this.loanProduct.enableInstallmentLevelDelinquency
+ )
+ );
+ }
+ if (this.productEnableDownPayment) {
+ const enableDownPayment = this.loansAccountTermsData['enableDownPayment'] === false ? false : true;
+ this.loansAccountTermsForm.addControl('enableDownPayment', new UntypedFormControl(enableDownPayment));
+ }
+
+ const allowAttributeOverrides = this.loansAccountTermsData.product.allowAttributeOverrides;
+ if (!allowAttributeOverrides.repaymentEvery) {
+ this.loansAccountTermsForm.controls.repaymentEvery.disable();
+ this.loansAccountTermsForm.controls.repaymentFrequencyType.disable();
+ }
+ if (!allowAttributeOverrides.interestType) {
+ this.loansAccountTermsForm.controls.interestType.disable();
+ }
+ if (!allowAttributeOverrides.amortizationType) {
+ this.loansAccountTermsForm.controls.amortizationType.disable();
+ }
+ if (!allowAttributeOverrides.interestCalculationPeriodType) {
+ this.loansAccountTermsForm.controls.interestCalculationPeriodType.disable();
+ this.loansAccountTermsForm.controls.allowPartialPeriodInterestCalculation.disable();
+ }
+ if (!allowAttributeOverrides.inArrearsTolerance) {
+ this.loansAccountTermsForm.controls.inArrearsTolerance.disable();
+ }
+ if (!allowAttributeOverrides.transactionProcessingStrategyCode) {
+ this.loansAccountTermsForm.controls.transactionProcessingStrategyCode.disable();
+ }
this.setOptions();
}
}
ngOnInit() {
- this.maxDate = this.settingsService.businessDate;
- if (this.loansAccountTemplate) {
- if (this.loansAccountTemplate.loanProductId) {
+ this.maxDate = this.settingsService.maxFutureDate;
+ this.loansAccountTermsData = this.loansAccountProductTemplate;
+ if (this.loanId != null && this.loansAccountTemplate.accountNo) {
+ this.loansAccountTermsData = this.loansAccountTemplate;
+ }
+
+ if (this.loansAccountTermsData) {
+ if (this.loansAccountTermsData.loanProductId) {
this.loansAccountTermsForm.patchValue({
repaymentsStartingFromDate:
- this.loansAccountTemplate.expectedFirstRepaymentOnDate &&
- new Date(this.loansAccountTemplate.expectedFirstRepaymentOnDate)
+ this.loansAccountTermsData.expectedFirstRepaymentOnDate &&
+ new Date(this.loansAccountTermsData.expectedFirstRepaymentOnDate)
});
}
+ this.loansAccountTermsForm.patchValue({
+ principalAmount: this.loansAccountTermsData.principal,
+ loanTermFrequency: this.loansAccountTermsData.termFrequency,
+ loanTermFrequencyType: this.loansAccountTermsData.termPeriodFrequencyType.id,
+ numberOfRepayments: this.loansAccountTermsData.numberOfRepayments,
+ repaymentEvery: this.loansAccountTermsData.repaymentEvery,
+ repaymentFrequencyType: this.loansAccountTermsData.repaymentFrequencyType.id,
+ amortizationType: this.loansAccountTermsData.amortizationType.id,
+ isEqualAmortization: this.loansAccountTermsData.isEqualAmortization,
+ interestType: this.loansAccountTermsData.interestType.id,
+ isFloatingInterestRate: this.loansAccountTermsData.isLoanProductLinkedToFloatingRate ? false : '',
+ interestCalculationPeriodType: this.loansAccountTermsData.interestCalculationPeriodType.id,
+ allowPartialPeriodInterestCalculation: this.loansAccountTermsData.allowPartialPeriodInterestCalculation,
+ inArrearsTolerance: this.loansAccountTermsData.inArrearsTolerance,
+ graceOnInterestCharged: this.loansAccountTermsData.graceOnInterestCharged,
+ fixedEmiAmount: this.loansAccountTermsData.fixedEmiAmount,
+ maxOutstandingLoanBalance: this.loansAccountTermsData.maxOutstandingLoanBalance,
+ transactionProcessingStrategyCode: this.loansAccountTermsData.transactionProcessingStrategyCode,
+ interestRateDifferential: this.loansAccountTermsData.interestRateDifferential,
+ multiDisburseLoan: this.loansAccountTermsData.multiDisburseLoan,
+ interestRateFrequencyType: this.loansAccountTermsData.interestRateFrequencyType.id,
+ balloonRepaymentAmount: this.loansAccountTermsData.balloonRepaymentAmount,
+ interestRecognitionOnDisbursementDate: this.loansAccountTermsData.interestRecognitionOnDisbursementDate || false
+ });
}
- this.createloansAccountTermsForm();
- this.setCustomValidators();
+ this.createGLIMTermsForm();
+ this.setAdvancedPaymentStrategyControls();
+ // this.setCustomValidators();
+ this.setLoanTermListener();
+ }
+
+ allowAddDisbursementDetails() {
+ return this.multiDisburseLoan && !this.loansAccountTermsData.disallowExpectedDisbursements;
}
/** Custom Validators for the form */
- setCustomValidators() {
- const repaymentFrequencyNthDayType = this.loansAccountTermsForm.get('repaymentFrequencyNthDayType');
- const repaymentFrequencyDayOfWeekType = this.loansAccountTermsForm.get('repaymentFrequencyDayOfWeekType');
+ // setCustomValidators() {
+ // const repaymentFrequencyNthDayType = this.loansAccountTermsForm.get('repaymentFrequencyNthDayType');
+ // const repaymentFrequencyDayOfWeekType = this.loansAccountTermsForm.get('repaymentFrequencyDayOfWeekType');
- this.loansAccountTermsForm.get('repaymentFrequencyType').valueChanges.subscribe((repaymentFrequencyType) => {
- if (repaymentFrequencyType === 2) {
- repaymentFrequencyNthDayType.setValidators([Validators.required]);
- repaymentFrequencyDayOfWeekType.setValidators([Validators.required]);
+ // this.loansAccountTermsForm.get('repaymentFrequencyType').valueChanges.subscribe((repaymentFrequencyType) => {
+ // if (repaymentFrequencyType === 2) {
+ // repaymentFrequencyNthDayType.setValidators([Validators.required]);
+ // repaymentFrequencyDayOfWeekType.setValidators([Validators.required]);
+ // } else {
+ // repaymentFrequencyNthDayType.setValidators(null);
+ // repaymentFrequencyDayOfWeekType.setValidators(null);
+ // }
+
+ // repaymentFrequencyNthDayType.updateValueAndValidity();
+ // repaymentFrequencyDayOfWeekType.updateValueAndValidity();
+ // });
+ // }
+
+ /** Custom Listeners for the form to calculate Loan Term */
+ setLoanTermListener() {
+ this.loansAccountTermsForm.get('numberOfRepayments').valueChanges.subscribe((numberOfRepayments) => {
+ const repaymentEvery: number = this.loansAccountTermsForm.value.repaymentEvery;
+ this.calculateLoanTerm(numberOfRepayments, repaymentEvery);
+ });
+
+ this.loansAccountTermsForm.get('repaymentEvery').valueChanges.subscribe((repaymentEvery) => {
+ const numberOfRepayments: number = this.loansAccountTermsForm.value.numberOfRepayments;
+ this.calculateLoanTerm(numberOfRepayments, repaymentEvery);
+ });
+
+ this.loansAccountTermsForm.get('loanTermFrequencyType').valueChanges.subscribe((loanTermFrequencyType) => {
+ this.loansAccountTermsForm.patchValue({ repaymentFrequencyType: loanTermFrequencyType });
+ });
+
+ this.loansAccountTermsForm.get('amortizationType').valueChanges.subscribe((amortizationType) => {
+ if (amortizationType === 0) {
+ // Equal Principal Payments
+ this.loansAccountTermsForm.addControl('fixedPrincipalPercentagePerInstallment', new UntypedFormControl(''));
} else {
- repaymentFrequencyNthDayType.setValidators(null);
- repaymentFrequencyDayOfWeekType.setValidators(null);
+ // Equal Installments
+ this.loansAccountTermsForm.removeControl('fixedPrincipalPercentagePerInstallment');
}
-
- repaymentFrequencyNthDayType.updateValueAndValidity();
- repaymentFrequencyDayOfWeekType.updateValueAndValidity();
});
}
+ setAdvancedPaymentStrategyControls(): void {
+ // Fixed Length validation
+ if (this.loansAccountTermsData) {
+ this.loansAccountTermsForm.removeControl('interestRatePerPeriod');
+ this.loansAccountTermsForm.removeControl('fixedLength');
+ if (this.loansAccountTermsData.product.fixedLength) {
+ this.loansAccountTermsForm.addControl(
+ 'interestRatePerPeriod',
+ new UntypedFormControl({ value: 0, disabled: true }, Validators.required)
+ );
+ this.loansAccountTermsForm.addControl(
+ 'fixedLength',
+ new UntypedFormControl(this.loansAccountTermsData.product.fixedLength)
+ );
+ } else {
+ this.loansAccountTermsForm.addControl(
+ 'interestRatePerPeriod',
+ new UntypedFormControl(this.loansAccountTermsData.interestRatePerPeriod, Validators.required)
+ );
+ }
+ }
+ }
+
+ hasFixedLength(): boolean {
+ if (this.loansAccountTermsData) {
+ return this.loansAccountTermsData.product?.fixedLength ? true : false;
+ }
+ return false;
+ }
+
+ isEqualPrincipalPayments(): boolean {
+ return this.loansAccountTermsForm.value.amortizationType === 0;
+ }
+
/** Create Loans Account Terms Form */
- createloansAccountTermsForm() {
+ createGLIMTermsForm() {
this.loansAccountTermsForm = this.formBuilder.group({
- principal: [
+ principalAmount: [
'',
Validators.required
],
loanTermFrequency: [
- '',
+ { value: '', disabled: true },
Validators.required
],
loanTermFrequencyType: [
@@ -126,7 +360,7 @@ export class GlimTermsStepComponent implements OnInit, OnChanges {
Validators.required
],
repaymentFrequencyType: [
- '',
+ { value: '', disabled: true },
Validators.required
],
repaymentFrequencyNthDayType: [''],
@@ -135,8 +369,109 @@ export class GlimTermsStepComponent implements OnInit, OnChanges {
interestChargedFromDate: [''],
interestRatePerPeriod: [''],
interestType: [''],
+ isFloatingInterestRate: [''],
+ isEqualAmortization: [''],
+ amortizationType: [
+ '',
+ Validators.required
+ ],
interestCalculationPeriodType: [''],
- transactionProcessingStrategyCode: ['']
+ allowPartialPeriodInterestCalculation: [''],
+ inArrearsTolerance: [''],
+ graceOnInterestCharged: [''],
+ loanIdToClose: [''],
+ fixedEmiAmount: [''],
+ isTopup: [''],
+ maxOutstandingLoanBalance: [''],
+ interestRateDifferential: [''],
+ transactionProcessingStrategyCode: [
+ '',
+ Validators.required
+ ],
+ multiDisburseLoan: [false],
+ interestRateFrequencyType: [''],
+ balloonRepaymentAmount: [''],
+ interestRecognitionOnDisbursementDate: [false]
+ });
+ }
+
+ calculateLoanTerm(numberOfRepayments: number, repaymentEvery: number): void {
+ const loanTerm = numberOfRepayments * repaymentEvery;
+ this.loansAccountTermsForm.patchValue({ loanTermFrequency: loanTerm });
+ }
+
+ /**
+ * Gets the Disbursement Data array.
+ * @returns {Array} Disbursement Data array.
+ */
+ get disbursementData() {
+ return {
+ disbursementData: this.disbursementDataSource
+ };
+ }
+
+ /**
+ * Adds the Disbursement Data entry form to given Disbursement Data entry.
+ */
+ addDisbursementDataEntry() {
+ const currentPrincipalAmount = this.loansAccountTermsForm.get('principalAmount').value;
+ const formfields: FormfieldBase[] = [
+ new DatepickerBase({
+ controlName: 'expectedDisbursementDate',
+ label: 'Expected Disbursement Date',
+ value: new Date() || '',
+ type: 'datetime-local',
+ minDate: this.minDate,
+ maxDate: this.maxDate,
+ required: true,
+ order: 1
+ }),
+ new InputBase({
+ controlName: 'principal',
+ label: `Principal(It should be less than equal to the ${currentPrincipalAmount})`,
+ value: '',
+ type: 'number',
+ required: true,
+ order: 2
+ })
+
+ ];
+ const data = {
+ title: 'Add Disbursement Details',
+ layout: { addButtonText: 'Add' },
+ formfields: formfields
+ };
+ const disbursementDialogRef = this.dialog.open(FormDialogComponent, { data });
+ disbursementDialogRef.afterClosed().subscribe((response: any) => {
+ if (response.data) {
+ const principal = response.data.value.principal * 1;
+ if (this.totalMultiDisbursed + principal <= currentPrincipalAmount) {
+ this.disbursementDataSource = this.disbursementDataSource.concat(response.data.value);
+ this.totalMultiDisbursed += principal;
+ this.isMultiDisbursedCompleted = this.totalMultiDisbursed === currentPrincipalAmount;
+ this.pristine = false;
+ }
+ }
+ });
+ }
+
+ /**
+ * Removes the Disbursement Data entry form from given Disbursement Data entry form array at given index.
+ * @param {number} index Array index from where Disbursement Data entry form needs to be removed.
+ */
+ removeDisbursementDataEntry(index: number) {
+ const currentPrincipalAmount = this.loansAccountTermsForm.get('principalAmount').value;
+ const dialogRef = this.dialog.open(DeleteDialogComponent, {
+ data: { deleteContext: `this` }
+ });
+ dialogRef.afterClosed().subscribe((response: any) => {
+ if (response.delete) {
+ const principal = this.disbursementDataSource[index]['principal'] * 1;
+ this.disbursementDataSource.splice(index, 1);
+ this.disbursementDataSource = this.disbursementDataSource.concat([]);
+ this.totalMultiDisbursed -= principal;
+ this.isMultiDisbursedCompleted = this.totalMultiDisbursed === currentPrincipalAmount;
+ }
});
}
@@ -151,14 +486,35 @@ export class GlimTermsStepComponent implements OnInit, OnChanges {
this.interestTypeData = this.loansAccountProductTemplate.interestTypeOptions;
this.amortizationTypeData = this.loansAccountProductTemplate.amortizationTypeOptions;
this.interestCalculationPeriodTypeData = this.loansAccountProductTemplate.interestCalculationPeriodTypeOptions;
- this.transactionProcessingStrategyData = this.loansAccountProductTemplate.transactionProcessingStrategyOptions;
this.clientActiveLoanData = this.loansAccountProductTemplate.clientActiveLoanOptions;
+ this.loanScheduleType = this.loansAccountProductTemplate.loanScheduleType;
+ this.transactionProcessingStrategyOptions = [];
+ if (this.loanScheduleType.code === LoanProducts.LOAN_SCHEDULE_TYPE_CUMULATIVE) {
+ // Filter Advanced Payment Allocation Strategy
+ this.transactionProcessingStrategyOptions =
+ this.loansAccountProductTemplate.transactionProcessingStrategyOptions.filter(
+ (cn: CodeName) => !LoanProducts.isAdvancedPaymentAllocationStrategy(cn.code)
+ );
+ this.repaymentStrategyDisabled = false;
+ } else {
+ // Only Advanced Payment Allocation Strategy
+ this.loansAccountProductTemplate.transactionProcessingStrategyOptions.some((cn: CodeName) => {
+ if (LoanProducts.isAdvancedPaymentAllocationStrategy(cn.code)) {
+ this.transactionProcessingStrategyOptions.push(cn);
+ }
+ });
+ this.repaymentStrategyDisabled = true;
+ }
+ }
+
+ isDelinquencyEnabled(): boolean {
+ return !!this.loanProduct?.delinquencyBucket?.name;
}
/**
* Returns loans account terms form value.
*/
get loansAccountTerms() {
- return this.loansAccountTermsForm.value;
+ return this.loansAccountTermsForm.getRawValue();
}
}
diff --git a/src/app/loans/loans.service.ts b/src/app/loans/loans.service.ts
index 63394e17b..93c0c2ee4 100644
--- a/src/app/loans/loans.service.ts
+++ b/src/app/loans/loans.service.ts
@@ -563,13 +563,15 @@ export class LoansService {
getGLIMLoanAccountTemplate(groupId: any): Observable {
const httpParams = new HttpParams()
.set('groupId', groupId)
- .set('lendingStrategy', '300')
+ // Commenting parameter, because it doesn't exist:
+ // https://localhost:8443/fineract-provider/swagger-ui/index.html#/Loans/template_10
+ // .set('lendingStrategy', '300')
.set('templateType', 'jlgbulk');
return this.http.get('/loans/template', { params: httpParams });
}
- createGlimAccount(glimAccount: any): Observable {
- return this.http.post('/batches?enclosingTransaction=true', glimAccount);
+ createGlimAccount(payload: any): Observable {
+ return this.http.post('/batches?enclosingTransaction=true', payload);
}
calculateLoanSchedule(payload: any): Observable {
@@ -598,10 +600,6 @@ export class LoansService {
amount: charge.amount,
dueDate: charge.dueDate && this.dateUtils.formatDate(charge.dueDate, dateFormat)
})),
- collateral: loansAccount.collateral.map((collateralEle: any) => ({
- clientCollateralId: collateralEle.type.collateralId,
- quantity: collateralEle.value
- })),
disbursementData: loansAccount.disbursementData.map((item: any) => ({
expectedDisbursementDate: this.dateUtils.formatDate(item.expectedDisbursementDate, dateFormat),
principal: item.principal
@@ -613,7 +611,19 @@ export class LoansService {
dateFormat,
locale
};
- if (loansAccountTemplate.clientId) {
+
+ if (loansAccount.collateral) {
+ loansAccountData.collateral = loansAccount.collateral.map((collateralEle: any) => ({
+ clientCollateralId: collateralEle.type.collateralId,
+ quantity: collateralEle.value
+ }));
+ }
+
+ if (loansAccountTemplate.clientId && loansAccountTemplate.group.id) {
+ loansAccountData.clientId = loansAccountTemplate.clientId;
+ loansAccountData.groupId = loansAccountTemplate.group.id;
+ loansAccountData.loanType = 'glim';
+ } else if (loansAccountTemplate.clientId) {
loansAccountData.clientId = loansAccountTemplate.clientId;
loansAccountData.loanType = 'individual';
} else {
@@ -651,7 +661,6 @@ export class LoansService {
// allowPartialPeriodInterestCalculation. Until that is fixed, we need to replace the field name in the payload.
loansAccountData.allowPartialPeriodInterestCalcualtion = loansAccountData.allowPartialPeriodInterestCalculation;
delete loansAccountData.allowPartialPeriodInterestCalculation;
-
return loansAccountData;
}
}