@@ -0,0 +1,29 @@
|
||||
/** Angular Imports */
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
|
||||
|
||||
/** rxjs Imports */
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
/** Custom Services */
|
||||
import { LoansService } from '../loans.service';
|
||||
|
||||
/**
|
||||
* Loan accounts template data resolver.
|
||||
*/
|
||||
@Injectable()
|
||||
export class LoansAccountAndTemplateResolver implements Resolve<Object> {
|
||||
/**
|
||||
* @param {ProductsService} productsService Products service.
|
||||
*/
|
||||
constructor(private loansService: LoansService) { }
|
||||
|
||||
/**
|
||||
* Returns the loan account template data.
|
||||
* @returns {Observable<any>}
|
||||
*/
|
||||
resolve(route: ActivatedRouteSnapshot): Observable<any> {
|
||||
const loanId = route.parent.paramMap.get('loanId');
|
||||
return this.loansService.getLoansAccountAndTemplateResource(loanId);
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,8 @@
|
||||
|
||||
<ng-template matStepLabel>TERMS</ng-template>
|
||||
|
||||
<mifosx-loans-account-terms-step [loansAccountProductTemplate]="loansAccountProductTemplate">
|
||||
<mifosx-loans-account-terms-step [loansAccountProductTemplate]="loansAccountProductTemplate"
|
||||
[loansAccountTemplate] = "loansAccountTemplate">
|
||||
</mifosx-loans-account-terms-step>
|
||||
|
||||
</mat-step>
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
<div class="container">
|
||||
|
||||
<mat-horizontal-stepper class="mat-elevation-z8" labelPosition="bottom" #loansAccountStepper>
|
||||
<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]="loansAccountDetailsForm">
|
||||
|
||||
<ng-template matStepLabel>DETAILS</ng-template>
|
||||
|
||||
<mifosx-loans-account-details-step [loansAccountTemplate]="loansAccountAndTemplate"
|
||||
(loansAccountProductTemplate)="setTemplate($event)">
|
||||
</mifosx-loans-account-details-step>
|
||||
|
||||
</mat-step>
|
||||
|
||||
<mat-step [stepControl]="loansAccountTermsForm">
|
||||
|
||||
<ng-template matStepLabel>TERMS</ng-template>
|
||||
|
||||
<mifosx-loans-account-terms-step [loansAccountProductTemplate]="loansAccountProductTemplate"
|
||||
[loansAccountTemplate]="loansAccountAndTemplate">
|
||||
</mifosx-loans-account-terms-step>
|
||||
|
||||
</mat-step>
|
||||
|
||||
<mat-step>
|
||||
|
||||
<ng-template matStepLabel>CHARGES</ng-template>
|
||||
|
||||
<mifosx-loans-account-charges-step [loansAccountProductTemplate]="loansAccountProductTemplate"
|
||||
[loansAccountTemplate]="loansAccountAndTemplate" [collateralOptions]="collateralOptions"
|
||||
[loansAccountFormValid]="loansAccountFormValidAndNotPristine">
|
||||
</mifosx-loans-account-charges-step>
|
||||
|
||||
</mat-step>
|
||||
|
||||
<mat-step state="preview" *ngIf="loansAccountFormValidAndNotPristine" completed>
|
||||
|
||||
<ng-template matStepLabel>PREVIEW</ng-template>
|
||||
|
||||
<mifosx-loans-account-preview-step [loansAccountTemplate]="loansAccountAndTemplate"
|
||||
[loansAccountProductTemplate]="loansAccountProductTemplate" [loansAccount]="loansAccount" (submit)="submit()">
|
||||
</mifosx-loans-account-preview-step>
|
||||
|
||||
</mat-step>
|
||||
|
||||
</mat-horizontal-stepper>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { EditLoansAccountComponent } from './edit-loans-account.component';
|
||||
|
||||
describe('EditLoansAccountComponent', () => {
|
||||
let component: EditLoansAccountComponent;
|
||||
let fixture: ComponentFixture<EditLoansAccountComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ EditLoansAccountComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(EditLoansAccountComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,146 @@
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { LoansService } from '../loans.service';
|
||||
import { LoansAccountDetailsStepComponent } from '../loans-account-stepper/loans-account-details-step/loans-account-details-step.component';
|
||||
import { LoansAccountTermsStepComponent } from '../loans-account-stepper/loans-account-terms-step/loans-account-terms-step.component';
|
||||
import { LoansAccountChargesStepComponent } from '../loans-account-stepper/loans-account-charges-step/loans-account-charges-step.component';
|
||||
|
||||
@Component({
|
||||
selector: 'mifosx-edit-loans-account',
|
||||
templateUrl: './edit-loans-account.component.html',
|
||||
styleUrls: ['./edit-loans-account.component.scss']
|
||||
})
|
||||
export class EditLoansAccountComponent implements OnInit {
|
||||
|
||||
@ViewChild(LoansAccountDetailsStepComponent) loansAccountDetailsStep: LoansAccountDetailsStepComponent;
|
||||
@ViewChild(LoansAccountTermsStepComponent) loansAccountTermsStep: LoansAccountTermsStepComponent;
|
||||
@ViewChild(LoansAccountChargesStepComponent) loansAccountChargesStep: LoansAccountChargesStepComponent;
|
||||
|
||||
loansAccountAndTemplate: any;
|
||||
/** Loans Account Product Template */
|
||||
loansAccountProductTemplate: any;
|
||||
/** Collateral Options */
|
||||
collateralOptions: any;
|
||||
/** Loan Id */
|
||||
loanId: any;
|
||||
|
||||
/**
|
||||
* Sets loans account edit form.
|
||||
* @param {route} ActivatedRoute Activated Route.
|
||||
* @param {router} Router Router.
|
||||
* @param {datePipe} DatePipe Date Pipe
|
||||
* @param {loansService} LoansService Loans Service
|
||||
*/
|
||||
constructor(private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private datePipe: DatePipe,
|
||||
private loansService: LoansService
|
||||
) {
|
||||
this.route.data.subscribe((data: { loansAccountAndTemplate: any }) => {
|
||||
this.loansAccountAndTemplate = data.loansAccountAndTemplate;
|
||||
});
|
||||
this.loanId = this.route.parent.snapshot.params['loanId'];
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets loans account product template and collateral template
|
||||
* @param {any} $event API response
|
||||
*/
|
||||
setTemplate($event: any) {
|
||||
this.loansAccountProductTemplate = $event;
|
||||
this.loansService.getLoansCollateralTemplateResource(this.loansAccountProductTemplate.loanProductId).subscribe((response: any) => {
|
||||
this.collateralOptions = response.loanCollateralOptions;
|
||||
});
|
||||
}
|
||||
|
||||
/** Get Loans Account Details Form Data */
|
||||
get loansAccountDetailsForm() {
|
||||
return this.loansAccountDetailsStep.loansAccountDetailsForm;
|
||||
}
|
||||
|
||||
/** Get Loans Account Terms Form Data */
|
||||
get loansAccountTermsForm() {
|
||||
return this.loansAccountTermsStep.loansAccountTermsForm;
|
||||
}
|
||||
|
||||
/** Checks wheter all the forms in different steps are valid and not pristine */
|
||||
get loansAccountFormValidAndNotPristine() {
|
||||
return (
|
||||
this.loansAccountDetailsForm.valid &&
|
||||
this.loansAccountTermsForm.valid &&
|
||||
(
|
||||
!this.loansAccountDetailsForm.pristine ||
|
||||
!this.loansAccountTermsForm.pristine ||
|
||||
!this.loansAccountChargesStep.pristine
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/** Retrieves Data of all forms except Currency to submit the data */
|
||||
get loansAccount() {
|
||||
return {
|
||||
...this.loansAccountDetailsStep.loansAccountDetails,
|
||||
...this.loansAccountTermsStep.loansAccountTerms,
|
||||
...this.loansAccountChargesStep.loansAccountCharges,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits Data to create loan account
|
||||
*/
|
||||
submit() {
|
||||
const locale = 'en';
|
||||
const dateFormat = 'dd MMMM yyyy';
|
||||
const loanType = 'individual';
|
||||
const loansAccountData = {
|
||||
...this.loansAccount,
|
||||
clientId: this.loansAccountAndTemplate.clientId,
|
||||
charges: this.loansAccount.charges.map((charge: any) => ({
|
||||
chargeId: charge.id,
|
||||
amount: charge.amount,
|
||||
dueDate: charge.dueDate && this.datePipe.transform(charge.dueDate, dateFormat),
|
||||
})),
|
||||
collateral: this.loansAccount.collateral.map((collateralEle: any) => ({
|
||||
type: collateralEle.type,
|
||||
value: collateralEle.value,
|
||||
description: collateralEle.description
|
||||
})),
|
||||
interestChargedFromDate: this.datePipe.transform(this.loansAccount.interestChargedFromDate, dateFormat),
|
||||
repaymentsStartingFromDate: this.datePipe.transform(this.loansAccount.repaymentsStartingFromDate, dateFormat),
|
||||
submittedOnDate: this.datePipe.transform(this.loansAccount.submittedOnDate, dateFormat),
|
||||
expectedDisbursementDate: this.datePipe.transform(this.loansAccount.expectedDisbursementDate, dateFormat),
|
||||
dateFormat,
|
||||
locale,
|
||||
loanType
|
||||
};
|
||||
|
||||
if (loansAccountData.syncRepaymentsWithMeeting) {
|
||||
loansAccountData.calendarId = this.loansAccountProductTemplate.calendarOptions[0].id;
|
||||
delete loansAccountData.syncRepaymentsWithMeeting;
|
||||
}
|
||||
|
||||
if (loansAccountData.recalculationRestFrequencyDate) {
|
||||
loansAccountData.recalculationRestFrequencyDate = this.datePipe.transform(this.loansAccount.recalculationRestFrequencyDate, dateFormat);
|
||||
}
|
||||
|
||||
if (loansAccountData.recalculationCompoundingFrequencyDate) {
|
||||
loansAccountData.recalculationCompoundingFrequencyDate = this.datePipe.transform(this.loansAccount.recalculationCompoundingFrequencyDate, dateFormat);
|
||||
}
|
||||
|
||||
if (loansAccountData.interestCalculationPeriodType === 0) {
|
||||
loansAccountData.allowPartialPeriodInterestCalcualtion = false;
|
||||
}
|
||||
if (!(loansAccountData.isFloatingInterestRate === false)) {
|
||||
delete loansAccountData.isFloatingInterestRate;
|
||||
}
|
||||
|
||||
this.loansService.updateLoansAccount(this.loanId, loansAccountData).subscribe((response: any) => {
|
||||
this.router.navigate(['../'], { relativeTo: this.route });
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
+5
@@ -59,6 +59,11 @@ export class LoansAccountDetailsStepComponent implements OnInit {
|
||||
this.loansAccountDetailsForm.patchValue({
|
||||
'productId': this.loansAccountTemplate.loanProductId,
|
||||
'submittedOnDate': this.loansAccountTemplate.timeline.submittedOnDate && new Date(this.loansAccountTemplate.timeline.submittedOnDate),
|
||||
'loanOfficerId': this.loansAccountTemplate.loanOfficerId,
|
||||
'loanPurposeId': this.loansAccountTemplate.loanPurposeId,
|
||||
'fundId': this.loansAccountTemplate.fundId,
|
||||
'expectedDisbursementDate': this.loansAccountTemplate.timeline.expectedDisbursementDate && new Date(this.loansAccountTemplate.timeline.expectedDisbursementDate),
|
||||
'externalId': this.loansAccountTemplate.externalId
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+39
-39
@@ -9,19 +9,19 @@
|
||||
<span fxFlex="60%">{{ loansAccount.productId | find:loansAccountTemplate.productOptions:'id':'name' }}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill *ngIf="loansAccountProductTemplate">
|
||||
<span fxFlex="40%">Loan officer: :</span>
|
||||
<div fxFlexFill *ngIf="loansAccount.loanOfficerId">
|
||||
<span fxFlex="40%">Loan officer:</span>
|
||||
<span
|
||||
fxFlex="60%">{{ loansAccount.loanOfficerId | find:loansAccountProductTemplate.loanOfficerOptions:'id':'name'}}</span>
|
||||
fxFlex="60%">{{ loansAccount.loanOfficerId | find:loansAccountProductTemplate.loanOfficerOptions:'id':'displayName'}}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<div fxFlexFill *ngIf="loansAccount.loanPurposeId">
|
||||
<span fxFlex="40%">Loan purpose:</span>
|
||||
<span
|
||||
fxFlex="60%">{{ loansAccount.loanPurposeId | find:loansAccountProductTemplate.loanPurposeOptions:'id':'name'}}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<div fxFlexFill *ngIf="loansAccount.fundId">
|
||||
<span fxFlex="40%">Fund:</span>
|
||||
<span fxFlex="60%">{{ loansAccount.fundId | find:loansAccountProductTemplate.fundOptions:'id':'name'}}</span>
|
||||
</div>
|
||||
@@ -36,8 +36,8 @@
|
||||
<span fxFlex="60%">{{ loansAccount.expectedDisbursementDate | date }}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">External id</span>
|
||||
<div fxFlexFill *ngIf="loansAccount.externalId">
|
||||
<span fxFlex="40%">External id:</span>
|
||||
<span fxFlex="60%">{{ loansAccount.externalId }}</span>
|
||||
</div>
|
||||
|
||||
@@ -57,74 +57,74 @@
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">Number of repayments</span>
|
||||
<span fxFlex="40%">Number of repayments:</span>
|
||||
<span fxFlex="60%">{{ loansAccount.numberOfRepayments }}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">Repaid every</span>
|
||||
<span fxFlex="40%">Repaid every:</span>
|
||||
<span fxFlex="60%">{{loansAccount.repaymentEvery}}
|
||||
{{loansAccount.repaymentFrequencyType | find: loansAccountProductTemplate.termFrequencyTypeOptions:'id':'name'}}
|
||||
{{loansAccount.repaymentFrequencyNthDayType | find: loansAccountProductTemplate.repaymentFrequencyNthDayTypeOptions:'id': 'name'}}
|
||||
{{loansAccount.repaymentFrequencyDayOfWeekType | find: loansAccountProductTemplate.repaymentFrequencyDaysOfWeekTypeOptions:'id': 'name'}}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">First repayment on</span>
|
||||
<div fxFlexFill *ngIf="loansAccount.repaymentsStartingFromDate">
|
||||
<span fxFlex="40%">First repayment on:</span>
|
||||
<span fxFlex="60%">{{ loansAccount.repaymentsStartingFromDate | date }}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">Interest charged from</span>
|
||||
<div fxFlexFill *ngIf="loansAccount.interestChargedFromDate">
|
||||
<span fxFlex="40%">Interest charged from:</span>
|
||||
<span fxFlex="60%">{{ loansAccount.interestChargedFromDate | date }}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">Nominal interest rate</span>
|
||||
<div fxFlexFill *ngIf="loansAccount.interestRatePerPeriod">
|
||||
<span fxFlex="40%">Nominal interest rate:</span>
|
||||
<span
|
||||
fxFlex="60%">{{loansAccount.interestRatePerPeriod}} {{loansAccountProductTemplate.interestRateFrequencyType.value}}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">Interest method </span>
|
||||
<div fxFlexFill *ngIf="loansAccount.interestType">
|
||||
<span fxFlex="40%">Interest method: </span>
|
||||
<span fxFlex="60%">{{loansAccount.interestType}}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">Is Equal Amortization</span>
|
||||
<div fxFlexFill *ngIf="loansAccount.isEqualAmortization">
|
||||
<span fxFlex="40%">Is Equal Amortization:</span>
|
||||
<span fxFlex="60%">{{loansAccount.isEqualAmortization}}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">Amortization</span>
|
||||
<span
|
||||
fxFlex="60%">{{ loansAccount.amortizationType | find:loansAccountTemplate.amortizationTypeOptions:'id':'name' }}</span>
|
||||
fxFlex="60%">{{ loansAccount.amortizationType | find:loansAccountProductTemplate.amortizationTypeOptions:'id':'value' }}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">Interest calculation period </span>
|
||||
<span fxFlex="40%">Interest calculation period: </span>
|
||||
<span
|
||||
fxFlex="60%">{{ loansAccount.interestCalculationPeriodType | find:loansAccountTemplate.interestCalculationPeriodTypeOptions:'id':'name' }}</span>
|
||||
fxFlex="60%">{{ loansAccount.interestCalculationPeriodType | find:loansAccountProductTemplate.interestCalculationPeriodTypeOptions:'id':'value' }}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">Calculate interest for exact days in partial period</span>
|
||||
<div fxFlexFill *ngIf="loansAccount.allowPartialPeriodInterestCalcualtion">
|
||||
<span fxFlex="40%">Calculate interest for exact days in partial period:</span>
|
||||
<span fxFlex="60%">{{ loansAccount.allowPartialPeriodInterestCalcualtion }}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">Arrears tolerance </span>
|
||||
<div fxFlexFill *ngIf="loansAccount.inArrearsTolerance">
|
||||
<span fxFlex="40%">Arrears tolerance: </span>
|
||||
<span
|
||||
fxFlex="60%">{{loansAccount.inArrearsTolerance}} {{loansAccountProductTemplate.currency.displaySymbol}}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">Interest free period </span>
|
||||
<div fxFlexFill *ngIf="loansAccount.graceOnInterestCharged">
|
||||
<span fxFlex="40%">Interest free period: </span>
|
||||
<span fxFlex="60%">{{ loansAccount.graceOnInterestCharged }}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">Repayment strategy </span>
|
||||
<span fxFlex="40%">Repayment strategy: </span>
|
||||
<span
|
||||
fxFlex="60%">{{ loansAccount.transactionProcessingStrategyId | find:loansAccountTemplate.transactionProcessingStrategyOptions:'id':'name' }}</span>
|
||||
</div>
|
||||
@@ -133,33 +133,33 @@
|
||||
|
||||
<mat-divider fxFlexFill></mat-divider>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">On principal payment </span>
|
||||
<div fxFlexFill *ngIf="loansAccount.graceOnPrincipalPayment">
|
||||
<span fxFlex="40%">On principal payment: </span>
|
||||
<span fxFlex="60%">{{ loansAccount.graceOnPrincipalPayment }}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">On interest payment </span>
|
||||
<div fxFlexFill *ngIf="loansAccount.graceOnInterestPayment">
|
||||
<span fxFlex="40%">On interest payment: </span>
|
||||
<span fxFlex="60%">{{ loansAccount.graceOnInterestPayment }}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">On Arrears Aging </span>
|
||||
<div fxFlexFill *ngIf="loansAccount.graceOnArrearsAgeing">
|
||||
<span fxFlex="40%">On Arrears Aging: </span>
|
||||
<span fxFlex="60%">{{ loansAccount.graceOnArrearsAgeing }}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<div fxFlexFill *ngIf="loansAccount.isTopup">
|
||||
<span fxFlex="40%">Is Topup Loan? </span>
|
||||
<span fxFlex="60%">{{ loansAccount.isTopup }}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">Recalculate Interest </span>
|
||||
<span fxFlex="40%">Recalculate Interest: </span>
|
||||
<span fxFlex="60%">{{ loansAccountProductTemplate?.isInterestRecalculationEnabled? 'Yes' : 'No' }}</span>
|
||||
</div>
|
||||
|
||||
<div fxFlexFill>
|
||||
<span fxFlex="40%">Days in month </span>
|
||||
<div fxFlexFill *ngIf="loansAccountProductTemplate?.daysInMonthType">
|
||||
<span fxFlex="40%">Days in month: </span>
|
||||
<span fxFlex="60%">{{ loansAccountProductTemplate?.daysInMonthType.value }}</span>
|
||||
</div>
|
||||
|
||||
|
||||
+23
-3
@@ -48,6 +48,8 @@
|
||||
<mat-datepicker #repaymentsPicker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
|
||||
<h4 fxFlex="98%" class="mat-h4">Repaid Every</h4>
|
||||
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-label>Repaid every</mat-label>
|
||||
<input matInput required formControlName="repaymentEvery"
|
||||
@@ -152,13 +154,16 @@
|
||||
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-label>Amortization</mat-label>
|
||||
<mat-select [disabled]="!loansAccountProductTemplate?.product.allowAttributeOverrides.amortizationType"
|
||||
<mat-select required [disabled]="!loansAccountProductTemplate?.product.allowAttributeOverrides.amortizationType"
|
||||
formControlName="amortizationType">
|
||||
<mat-option *ngFor="let amortizationType of amortizationTypeData"
|
||||
[value]="amortizationType.id">
|
||||
{{ amortizationType.value }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="loansAccountTermsForm.controls.amortizationType.hasError('required')">
|
||||
Amortization Type is <strong>required</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<h4 fxFlex="98%" class="mat-h4">Interest Calculations</h4>
|
||||
@@ -196,15 +201,18 @@
|
||||
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-label>Repayment strategy</mat-label>
|
||||
<mat-select
|
||||
<mat-select required
|
||||
[disabled]="!loansAccountProductTemplate?.product.allowAttributeOverrides.transactionProcessingStrategyId"
|
||||
formControlName="transactionProcessingStrategyId">
|
||||
<mat-option
|
||||
*ngFor="let transactionProcessingStrategy of transactionProcessingStrategyData"
|
||||
[value]="transactionProcessingStrategy.id">
|
||||
{{ transactionProcessingStrategy.value }}
|
||||
{{ transactionProcessingStrategy.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="loansAccountTermsForm.controls.transactionProcessingStrategyId.hasError('required')">
|
||||
Repayment Strategy is <strong>required</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<h4 fxFlex="98%" class="mat-h4">Moratorium</h4>
|
||||
@@ -245,6 +253,18 @@
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field fxFlex="48%"
|
||||
*ngIf="loansAccountProductTemplate.isInterestRecalculationEnabled && loansAccountProductTemplate.interestRecalculationData.interestRecalculationCompoundingType.id != 0 && loansAccountProductTemplate.interestRecalculationData.recalculationCompoundingFrequencyType.id != 1">
|
||||
<mat-label>Frequency Date for recalculation</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-error *ngIf="loansAccountTermsForm.controls.recalculationCompoundingFrequencyDate.hasError('required')">
|
||||
Frequency Data for recalculation is <strong>required</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
</ng-container>
|
||||
|
||||
<mat-divider fxFlex="98%"></mat-divider>
|
||||
|
||||
+16
-5
@@ -1,6 +1,6 @@
|
||||
/** Angular Imports */
|
||||
import { Component, OnInit, Input, OnChanges } from '@angular/core';
|
||||
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
|
||||
import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
|
||||
/**
|
||||
@@ -15,6 +15,8 @@ export class LoansAccountTermsStepComponent implements OnInit, OnChanges {
|
||||
|
||||
/** Loans Account Product Template */
|
||||
@Input() loansAccountProductTemplate: any;
|
||||
/** Loans Account Template */
|
||||
@Input() loansAccountTemplate: any;
|
||||
|
||||
/** Minimum date allowed. */
|
||||
minDate = new Date(2000, 0, 1);
|
||||
@@ -82,7 +84,15 @@ export class LoansAccountTermsStepComponent implements OnInit, OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() { }
|
||||
ngOnInit() {
|
||||
if (this.loansAccountTemplate) {
|
||||
if (this.loansAccountTemplate.loanProductId) {
|
||||
this.loansAccountTermsForm.patchValue({
|
||||
'repaymentsStartingFromDate': this.loansAccountTemplate.expectedFirstRepaymentOnDate && new Date(this.loansAccountTemplate.expectedFirstRepaymentOnDate)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Create Loans Account Terms Form */
|
||||
createloansAccountTermsForm() {
|
||||
@@ -102,19 +112,20 @@ export class LoansAccountTermsStepComponent implements OnInit, OnChanges {
|
||||
// 'interestRateDifferential': [''],
|
||||
'isFloatingInterestRate': [''],
|
||||
'isEqualAmortization': [''],
|
||||
'amortizationType': [''],
|
||||
'amortizationType': ['', Validators.required],
|
||||
'interestCalculationPeriodType': [''],
|
||||
'allowPartialPeriodInterestCalcualtion': [''],
|
||||
'inArrearsTolerance': [''],
|
||||
'graceOnInterestCharged': [''],
|
||||
'transactionProcessingStrategyId': [''],
|
||||
'transactionProcessingStrategyId': ['', Validators.required],
|
||||
'graceOnPrincipalPayment': [''],
|
||||
'graceOnInterestPayment': [''],
|
||||
'graceOnArrearsAgeing': [''],
|
||||
'loanIdToClose': [''],
|
||||
'fixedEmiAmount': [''],
|
||||
'isTopup': [''],
|
||||
'maxOutstandingLoanBalance': ['']
|
||||
'maxOutstandingLoanBalance': [''],
|
||||
'recalculationCompoundingFrequencyDate': ['']
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import { LoanCollateralTabComponent } from './loans-view/loan-collateral-tab/loa
|
||||
import { CreateLoansAccountComponent } from './create-loans-account/create-loans-account.component';
|
||||
import { LoanDocumentsTabComponent } from './loans-view/loan-documents-tab/loan-documents-tab.component';
|
||||
import { StandingInstructionsTabComponent } from 'app/loans/loans-view/standing-instructions-tab/standing-instructions-tab.component';
|
||||
import { EditLoansAccountComponent } from './edit-loans-account/edit-loans-account.component';
|
||||
|
||||
/** Custom Resolvers */
|
||||
import { LoanChargeTemplateResolver } from './common-resolvers/loan-charge-template.resolver';
|
||||
@@ -36,6 +37,7 @@ import { LoanDatatableResolver } from './common-resolvers/loan-datatable.resolve
|
||||
import { LoanActionButtonResolver } from './common-resolvers/loan-action-button.resolver';
|
||||
import { LoansAccountTemplateResolver } from './common-resolvers/loans-account-template.resolver';
|
||||
import { LoanDocumentsResolver } from './common-resolvers/loan-documents.resolver';
|
||||
import { LoansAccountAndTemplateResolver } from './common-resolvers/loans-account-and-template.resolver';
|
||||
|
||||
/** Loans Route. */
|
||||
const routes: Routes = [
|
||||
@@ -54,143 +56,156 @@ const routes: Routes = [
|
||||
{
|
||||
path: ':loanId',
|
||||
data: { title: extract('Loan View'), routeParamBreadcrumb: 'loanId' },
|
||||
component: LoansViewComponent,
|
||||
resolve: {
|
||||
loanDetailsData: LoanDetailsResolver,
|
||||
loanDatatables: LoanDatatablesResolver,
|
||||
},
|
||||
// Component For Loan View Comes Here
|
||||
children: [
|
||||
{
|
||||
path: 'general',
|
||||
component: GeneralTabComponent,
|
||||
data: { title: extract('General'), breadcrumb: 'General', routeParamBreadcrumb: false },
|
||||
path: '',
|
||||
component: LoansViewComponent,
|
||||
resolve: {
|
||||
loanDetailsData: LoanDetailsGeneralResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'accountdetail',
|
||||
component: AccountDetailsComponent,
|
||||
data: { title: extract('Account Detail'), breadcrumb: 'Account Detail', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsData: LoanDetailsGeneralResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'original-schedule',
|
||||
component: OriginalScheduleTabComponent,
|
||||
data: { title: extract('Original Schedule'), breadcrumb: 'Original Schedule', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsAssociationData: LoanDetailsChargesResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'repayment-schedule',
|
||||
component: RepaymentScheduleTabComponent,
|
||||
data: { title: extract('Repayment Schedule'), breadcrumb: 'Repayment Schedule', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsAssociationData: LoanDetailsChargesResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'transactions',
|
||||
component: TransactionsTabComponent,
|
||||
data: { title: extract('Transactions'), breadcrumb: 'Transactions', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsAssociationData: LoanDetailsChargesResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'loan-collateral',
|
||||
component: LoanCollateralTabComponent,
|
||||
data: { title: extract('Loan Collateral Details'), breadcrumb: 'Loan Collateral Details', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsAssociationData: LoanDetailsChargesResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'loan-tranche-details',
|
||||
component: LoanTrancheDetailsComponent,
|
||||
data: { title: extract('Loan Tranche Details'), breadcrumb: 'Loan Tranche Details', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsAssociationData: LoanDetailsChargesResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'overdue-charges',
|
||||
component: OverdueChargesTabComponent,
|
||||
data: { title: extract('Overdue Charges'), breadcrumb: 'Overdue Charges', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsData: LoanDetailsGeneralResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'floating-interest-rates',
|
||||
component: FloatingInterestRatesComponent,
|
||||
data: { title: extract('Floating Interest Rates'), breadcrumb: 'Floating Interest Rates', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsAssociationData: LoanDetailsChargesResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'charges',
|
||||
component: ChargesTabComponent,
|
||||
data: { title: extract('Charges'), breadcrumb: 'Charges', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsAssociationData: LoanDetailsChargesResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'loan-documents',
|
||||
component: LoanDocumentsTabComponent,
|
||||
data: { title: extract('Loan Documents'), breadcrumb: 'Loan Documents', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDocuments: LoanDocumentsResolver,
|
||||
loanDetailsData: LoanDetailsGeneralResolver
|
||||
loanDetailsData: LoanDetailsResolver,
|
||||
loanDatatables: LoanDatatablesResolver,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'general',
|
||||
component: GeneralTabComponent,
|
||||
data: { title: extract('General'), breadcrumb: 'General', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsData: LoanDetailsGeneralResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'accountdetail',
|
||||
component: AccountDetailsComponent,
|
||||
data: { title: extract('Account Detail'), breadcrumb: 'Account Detail', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsData: LoanDetailsGeneralResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'original-schedule',
|
||||
component: OriginalScheduleTabComponent,
|
||||
data: { title: extract('Original Schedule'), breadcrumb: 'Original Schedule', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsAssociationData: LoanDetailsChargesResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'repayment-schedule',
|
||||
component: RepaymentScheduleTabComponent,
|
||||
data: { title: extract('Repayment Schedule'), breadcrumb: 'Repayment Schedule', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsAssociationData: LoanDetailsChargesResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'transactions',
|
||||
component: TransactionsTabComponent,
|
||||
data: { title: extract('Transactions'), breadcrumb: 'Transactions', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsAssociationData: LoanDetailsChargesResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'loan-collateral',
|
||||
component: LoanCollateralTabComponent,
|
||||
data: { title: extract('Loan Collateral Details'), breadcrumb: 'Loan Collateral Details', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsAssociationData: LoanDetailsChargesResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'loan-tranche-details',
|
||||
component: LoanTrancheDetailsComponent,
|
||||
data: { title: extract('Loan Tranche Details'), breadcrumb: 'Loan Tranche Details', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsAssociationData: LoanDetailsChargesResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'overdue-charges',
|
||||
component: OverdueChargesTabComponent,
|
||||
data: { title: extract('Overdue Charges'), breadcrumb: 'Overdue Charges', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsData: LoanDetailsGeneralResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'floating-interest-rates',
|
||||
component: FloatingInterestRatesComponent,
|
||||
data: { title: extract('Floating Interest Rates'), breadcrumb: 'Floating Interest Rates', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsAssociationData: LoanDetailsChargesResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'charges',
|
||||
component: ChargesTabComponent,
|
||||
data: { title: extract('Charges'), breadcrumb: 'Charges', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsAssociationData: LoanDetailsChargesResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'loan-documents',
|
||||
component: LoanDocumentsTabComponent,
|
||||
data: { title: extract('Loan Documents'), breadcrumb: 'Loan Documents', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDocuments: LoanDocumentsResolver,
|
||||
loanDetailsData: LoanDetailsGeneralResolver
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'notes',
|
||||
component: NotesTabComponent,
|
||||
data: { title: extract('Notes'), breadcrumb: 'Notes', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanNotes: LoanNotesResolver
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'standing-instruction',
|
||||
component: StandingInstructionsTabComponent,
|
||||
data: { title: extract('Standing Instructions'), breadcrumb: 'Standing Instructions', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsData: LoanDetailsGeneralResolver
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'datatables',
|
||||
children: [{
|
||||
path: ':datatableName',
|
||||
component: DatatableTabComponent,
|
||||
data: { title: extract('Data Table View'), routeParamBreadcrumb: 'datatableName' },
|
||||
resolve: {
|
||||
loanDatatable: LoanDatatableResolver
|
||||
}
|
||||
}]
|
||||
},
|
||||
{
|
||||
path: 'add-loan-charge',
|
||||
component: AddLoanChargeComponent,
|
||||
data: { title: extract('Add Loan Charge'), breadcrumb: 'Add Loan Charge', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanChargeTemplate: LoanChargeTemplateResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'actions/:action',
|
||||
component: LoanAccountActionsComponent,
|
||||
data: { title: extract('Loan Account Actions'), routeParamBreadcrumb: 'action' },
|
||||
resolve: {
|
||||
actionButtonData: LoanActionButtonResolver
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'notes',
|
||||
component: NotesTabComponent,
|
||||
data: { title: extract('Notes'), breadcrumb: 'Notes', routeParamBreadcrumb: false },
|
||||
path: 'edit-loans-account',
|
||||
data: { title: extract('Edit Loans Account'), breadcrumb: 'Edit Loans Account', routeParamBreadcrumb: 'Edit' },
|
||||
component: EditLoansAccountComponent,
|
||||
resolve: {
|
||||
loanNotes: LoanNotesResolver
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'standing-instruction',
|
||||
component: StandingInstructionsTabComponent,
|
||||
data: { title: extract('Standing Instructions'), breadcrumb: 'Standing Instructions', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDetailsData: LoanDetailsGeneralResolver
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'datatables',
|
||||
children: [{
|
||||
path: ':datatableName',
|
||||
component: DatatableTabComponent,
|
||||
data: { title: extract('Data Table View'), routeParamBreadcrumb: 'datatableName' },
|
||||
resolve: {
|
||||
loanDatatable: LoanDatatableResolver
|
||||
}
|
||||
}]
|
||||
},
|
||||
{
|
||||
path: 'add-loan-charge',
|
||||
component: AddLoanChargeComponent,
|
||||
data: { title: extract('Add Loan Charge'), breadcrumb: 'Add Loan Charge', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanChargeTemplate: LoanChargeTemplateResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: ':action',
|
||||
component: LoanAccountActionsComponent,
|
||||
data: { title: extract('Loan Account Actions'), routeParamBreadcrumb: 'action' },
|
||||
resolve: {
|
||||
actionButtonData: LoanActionButtonResolver
|
||||
loansAccountAndTemplate: LoansAccountAndTemplateResolver
|
||||
}
|
||||
},
|
||||
]
|
||||
@@ -211,7 +226,8 @@ const routes: Routes = [
|
||||
LoanDatatableResolver,
|
||||
LoanActionButtonResolver,
|
||||
LoansAccountTemplateResolver,
|
||||
LoanDocumentsResolver
|
||||
LoanDocumentsResolver,
|
||||
LoansAccountAndTemplateResolver
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
@@ -130,11 +130,14 @@ export class LoansViewComponent implements OnInit {
|
||||
case 'Delete':
|
||||
this.deleteLoanAccount();
|
||||
break;
|
||||
case 'Modify Application':
|
||||
this.router.navigate(['edit-loans-account'], { relativeTo: this.route});
|
||||
break;
|
||||
default:
|
||||
button = button.replace(/\s/g, '-').toLowerCase();
|
||||
button = button.replace(/\(/g, '');
|
||||
button = button.replace(/\)/g, '');
|
||||
this.router.navigate([button], { relativeTo: this.route });
|
||||
this.router.navigate(['actions', button], { relativeTo: this.route });
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ import { LoansAccountAddCollateralDialogComponent } from './custom-dialog/loans-
|
||||
import { LoansConfirmationDialogBoxComponent } from './custom-dialog/loans-confirmation-dialog-box/loans-confirmation-dialog-box.component';
|
||||
import { LoanAccountLoadDocumentsDialogComponent } from './custom-dialog/loan-account-load-documents-dialog/loan-account-load-documents-dialog.component';
|
||||
import { StandingInstructionsTabComponent } from './loans-view/standing-instructions-tab/standing-instructions-tab.component';
|
||||
import { EditLoansAccountComponent } from './edit-loans-account/edit-loans-account.component';
|
||||
|
||||
/**
|
||||
* Loans Module
|
||||
@@ -114,6 +115,7 @@ import { StandingInstructionsTabComponent } from './loans-view/standing-instruct
|
||||
LoanDocumentsTabComponent,
|
||||
LoanAccountLoadDocumentsDialogComponent,
|
||||
StandingInstructionsTabComponent,
|
||||
EditLoansAccountComponent,
|
||||
],
|
||||
entryComponents: [
|
||||
LoansAccountAddCollateralDialogComponent,
|
||||
|
||||
@@ -266,6 +266,13 @@ export class LoansService {
|
||||
return this.http.get('/loans/template', { params: httpParams });
|
||||
}
|
||||
|
||||
getLoansAccountAndTemplateResource(loanId: any): Observable<any> {
|
||||
const httpParams = new HttpParams().set('associations', 'charges,collateral,meeting,multiDisburseDetails')
|
||||
.set('staffInSelectedOfficeOnly', 'true')
|
||||
.set('template', 'true');
|
||||
return this.http.get(`/loans/${loanId}`, { params: httpParams });
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Loans Collateral Template
|
||||
* @param {any} productId Product ID
|
||||
@@ -320,4 +327,8 @@ export class LoansService {
|
||||
return this.http.get(`/standinginstructions`, { params: httpParams });
|
||||
}
|
||||
|
||||
updateLoansAccount(loanId: any, loanData: any): Observable<any> {
|
||||
return this.http.put(`/loans/${loanId}`, loanData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user