From 7c64c849d3bbbe9237aafde5ca609e868eb3e046 Mon Sep 17 00:00:00 2001 From: Karan Takalkar Date: Sat, 20 Jun 2020 17:34:38 +0530 Subject: [PATCH] feat: add edit savings account page (#884) Fixes: #222 --- .../savings-account-and-template.resolver.ts | 32 +++++ .../edit-savings-account.component.html | 78 +++++++++++ .../edit-savings-account.component.scss | 0 .../edit-savings-account.component.spec.ts | 25 ++++ .../edit-savings-account.component.ts | 129 ++++++++++++++++++ ...avings-account-charges-step.component.html | 4 +- .../savings-account-charges-step.component.ts | 4 +- .../savings-account-details-step.component.ts | 16 ++- ...avings-account-preview-step.component.html | 14 +- .../savings-account-terms-step.component.ts | 25 +++- .../savings-account-view.component.html | 2 +- .../savings-account-view.component.ts | 15 +- .../savings-buttons.config.ts | 2 - src/app/savings/savings-routing.module.ts | 72 ++++++---- src/app/savings/savings.module.ts | 4 +- src/app/savings/savings.service.ts | 21 ++- .../shares-account-charges-step.component.ts | 4 +- .../shares-account-terms-step.component.ts | 4 +- 18 files changed, 397 insertions(+), 54 deletions(-) create mode 100644 src/app/savings/common-resolvers/savings-account-and-template.resolver.ts create mode 100644 src/app/savings/edit-savings-account/edit-savings-account.component.html create mode 100644 src/app/savings/edit-savings-account/edit-savings-account.component.scss create mode 100644 src/app/savings/edit-savings-account/edit-savings-account.component.spec.ts create mode 100644 src/app/savings/edit-savings-account/edit-savings-account.component.ts diff --git a/src/app/savings/common-resolvers/savings-account-and-template.resolver.ts b/src/app/savings/common-resolvers/savings-account-and-template.resolver.ts new file mode 100644 index 000000000..b7b95fc9b --- /dev/null +++ b/src/app/savings/common-resolvers/savings-account-and-template.resolver.ts @@ -0,0 +1,32 @@ +/** Angular Imports */ +import { Injectable } from '@angular/core'; +import { Resolve, ActivatedRouteSnapshot } from '@angular/router'; + +/** rxjs Imports */ +import { Observable } from 'rxjs'; + +/** Custom Services */ +import { SavingsService } from '../savings.service'; + +/** + * Savings Account data and template resolver. + */ +@Injectable() +export class SavingsAccountAndTemplateResolver implements Resolve { + + /** + * @param {SavingsService} SavingsService Savings service. + */ + constructor(private savingsService: SavingsService) { } + + /** + * Returns the Savings Account data and template. + * @param {ActivatedRouteSnapshot} route Route Snapshot + * @returns {Observable} + */ + resolve(route: ActivatedRouteSnapshot): Observable { + const savingAccountId = route.paramMap.get('savingAccountId'); + return this.savingsService.getSavingsAccountAndTemplate(savingAccountId, true); + } + +} diff --git a/src/app/savings/edit-savings-account/edit-savings-account.component.html b/src/app/savings/edit-savings-account/edit-savings-account.component.html new file mode 100644 index 000000000..c91ea85dc --- /dev/null +++ b/src/app/savings/edit-savings-account/edit-savings-account.component.html @@ -0,0 +1,78 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + DETAILS + + + + + + + + + TERMS + + + + + + + + CHARGES + + + + + + + + + PREVIEW + + + + + + + + +
diff --git a/src/app/savings/edit-savings-account/edit-savings-account.component.scss b/src/app/savings/edit-savings-account/edit-savings-account.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/savings/edit-savings-account/edit-savings-account.component.spec.ts b/src/app/savings/edit-savings-account/edit-savings-account.component.spec.ts new file mode 100644 index 000000000..0e1eb0a76 --- /dev/null +++ b/src/app/savings/edit-savings-account/edit-savings-account.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EditSavingsAccountComponent } from './edit-savings-account.component'; + +describe('EditSavingsAccountComponent', () => { + let component: EditSavingsAccountComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ EditSavingsAccountComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(EditSavingsAccountComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/savings/edit-savings-account/edit-savings-account.component.ts b/src/app/savings/edit-savings-account/edit-savings-account.component.ts new file mode 100644 index 000000000..45374d387 --- /dev/null +++ b/src/app/savings/edit-savings-account/edit-savings-account.component.ts @@ -0,0 +1,129 @@ +/** Angular Imports */ +import { Component, ViewChild } from '@angular/core'; +import { Router, ActivatedRoute } from '@angular/router'; +import { DatePipe } from '@angular/common'; + +/** Custom Components */ +import { SavingsAccountDetailsStepComponent } from '../savings-account-stepper/savings-account-details-step/savings-account-details-step.component'; +import { SavingsAccountTermsStepComponent } from '../savings-account-stepper/savings-account-terms-step/savings-account-terms-step.component'; +import { SavingsAccountChargesStepComponent } from '../savings-account-stepper/savings-account-charges-step/savings-account-charges-step.component'; + +/** Custom Services */ +import { SavingsService } from '../savings.service'; + +/** + * Edit Savings Account Component + */ +@Component({ + selector: 'mifosx-edit-savings-account', + templateUrl: './edit-savings-account.component.html', + styleUrls: ['./edit-savings-account.component.scss'] +}) +export class EditSavingsAccountComponent { + + /** Savings Account Template */ + savingsAccountAndTemplate: any; + /** Savings Account Product Template */ + savingsAccountProductTemplate: any; + + /** Savings Account Details Step */ + @ViewChild(SavingsAccountDetailsStepComponent) savingsAccountDetailsStep: SavingsAccountDetailsStepComponent; + /** Savings Account Terms Step */ + @ViewChild(SavingsAccountTermsStepComponent) savingsAccountTermsStep: SavingsAccountTermsStepComponent; + /** Savings Account Charges Step */ + @ViewChild(SavingsAccountChargesStepComponent) savingsAccountChargesStep: SavingsAccountChargesStepComponent; + + /** + * Fetches savings account template from `resolve` + * @param {ActivatedRoute} route Activated Route + * @param {Router} router Router + * @param {DatePipe} datePipe Date Pipe + * @param {SavingsService} savingsService Savings Service + */ + constructor(private route: ActivatedRoute, + private router: Router, + private datePipe: DatePipe, + private savingsService: SavingsService + ) { + this.route.data.subscribe((data: { savingsAccountAndTemplate: any }) => { + this.savingsAccountAndTemplate = data.savingsAccountAndTemplate; + }); + } + + /** + * Sets savings account product template. + * @param {any} $event API response + */ + setTemplate($event: any) { + this.savingsAccountProductTemplate = $event; + } + + /** + * Retrieves savings account details form. + */ + get savingsAccountDetailsForm() { + return this.savingsAccountDetailsStep.savingsAccountDetailsForm; + } + + /** + * Retrieves savings account terms form. + */ + get savingsAccountTermsForm() { + return this.savingsAccountTermsStep.savingsAccountTermsForm; + } + + /** + * Checks validity and pristinity of overall savings account form . + */ + get savingsAccountFormValidAndNotPristine() { + return ( + this.savingsAccountDetailsForm.valid && + this.savingsAccountTermsForm.valid && + ( + !this.savingsAccountDetailsForm.pristine || + !this.savingsAccountTermsForm.pristine || + !this.savingsAccountChargesStep.pristine + ) + ); + } + + /** + * Retrieves savings account object. + */ + get savingsAccount() { + return { + ...this.savingsAccountDetailsStep.savingsAccountDetails, + ...this.savingsAccountTermsStep.savingsAccountTerms, + ...this.savingsAccountChargesStep.savingsAccountCharges + }; + } + + /** + * Creates a new share account. + */ + submit() { + // TODO: Update once language and date settings are setup + const locale = 'en'; + const dateFormat = 'dd MMMM yyyy'; + const monthDayFormat = 'dd MMMM'; + const savingsAccount = { + ...this.savingsAccount, + clientId: this.savingsAccountAndTemplate.clientId, + charges: this.savingsAccount.charges.map((charge: any) => ({ + chargeId: charge.id, + amount: charge.amount, + dueDate: this.datePipe.transform(charge.dueDate, dateFormat), + feeOnMonthDay: this.datePipe.transform(charge.feeOnMonthDay, dateFormat), + feeInterval: charge.feeInterval + })), + submittedOnDate: this.datePipe.transform(this.savingsAccount.submittedOnDate, dateFormat), + dateFormat, + monthDayFormat, + locale + }; + this.savingsService.updateSavingsAccount(this.savingsAccountAndTemplate.id, savingsAccount).subscribe((response: any) => { + this.router.navigate(['../'], { relativeTo: this.route }); + }); + } + +} diff --git a/src/app/savings/savings-account-stepper/savings-account-charges-step/savings-account-charges-step.component.html b/src/app/savings/savings-account-stepper/savings-account-charges-step/savings-account-charges-step.component.html index 054b05dd2..5fd757bee 100644 --- a/src/app/savings/savings-account-stepper/savings-account-charges-step/savings-account-charges-step.component.html +++ b/src/app/savings/savings-account-stepper/savings-account-charges-step/savings-account-charges-step.component.html @@ -53,10 +53,10 @@ Date - {{charge.dueDate || 'Unassigned'}} + {{(charge.dueDate | date) || 'Unassigned'}} - {{charge.feeOnMonthDay || 'Unassigned'}} + {{(charge.feeOnMonthDay | date) || 'Unassigned'}} {{ savingsAccountTermsForm.get('decimal').value }} +
+ Currency in multiples of + {{ savingsAccountTermsForm.get('currencyMultiple').value }} +
+
Nominal Annual Interest Rate: {{ savingsAccount.nominalAnnualInterestRate }} @@ -48,11 +53,6 @@ {{ savingsAccount.interestCompoundingPeriodType | find:savingsAccountProductTemplate.interestCompoundingPeriodTypeOptions:'id':'value' }}
-
- Currency in multiples of - {{ savingsAccountTermsForm.get('currencyMultiple').value }} -
-
Interest Posting Period: {{ savingsAccount.interestPostingPeriodType | find:savingsAccountProductTemplate.interestPostingPeriodTypeOptions:'id':'value' }} @@ -146,10 +146,10 @@ Date - {{charge.dueDate || 'Unassigned'}} + {{(charge.dueDate | date) || 'Unassigned'}} - {{charge.feeOnMonthDay || 'Unassigned'}} + {{(charge.feeOnMonthDay | date) || 'Unassigned'}} - diff --git a/src/app/savings/savings-account-view/savings-account-view.component.ts b/src/app/savings/savings-account-view/savings-account-view.component.ts index e1bdf4290..d8f4cf0ea 100644 --- a/src/app/savings/savings-account-view/savings-account-view.component.ts +++ b/src/app/savings/savings-account-view/savings-account-view.component.ts @@ -1,6 +1,6 @@ /** Angular Imports */ import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; /** Custom Buttons Configuration */ import { SavingsButtonsConfiguration } from './savings-buttons.config'; @@ -26,7 +26,8 @@ export class SavingsAccountViewComponent implements OnInit { * Fetches savings account data from `resolve` * @param {ActivatedRoute} route Activated Route */ - constructor(private route: ActivatedRoute) { + constructor(private route: ActivatedRoute, + private router: Router) { this.route.data.subscribe((data: { savingsAccountData: any, savingsDatatables: any }) => { this.savingsAccountData = data.savingsAccountData; this.savingsDatatables = data.savingsDatatables; @@ -65,7 +66,7 @@ export class SavingsAccountViewComponent implements OnInit { charges.forEach((charge: any) => { if (charge.name === 'Annual fee - INR') { this.buttonConfig.addOption({ - name: 'Apply Anuual Fees', + name: 'Apply Annual Fees', taskPermissionName: 'APPLYANNUALFEE_SAVINGSACCOUNT' }); } @@ -86,4 +87,12 @@ export class SavingsAccountViewComponent implements OnInit { } } + doAction(name: string) { + switch (name) { + case 'Modify Application': + this.router.navigate(['edit-savings-account'], { relativeTo: this.route }); + break; + } + } + } diff --git a/src/app/savings/savings-account-view/savings-buttons.config.ts b/src/app/savings/savings-account-view/savings-buttons.config.ts index 85eea50b4..9d892412a 100644 --- a/src/app/savings/savings-account-view/savings-buttons.config.ts +++ b/src/app/savings/savings-account-view/savings-buttons.config.ts @@ -4,14 +4,12 @@ export class SavingsButtonsConfiguration { optionArray: { name: string, taskPermissionName: string, - action?: Function }[]; buttonsArray: { name: string, icon: string, taskPermissionName: string, - action?: Function }[]; constructor(status: string) { diff --git a/src/app/savings/savings-routing.module.ts b/src/app/savings/savings-routing.module.ts index 21aaa5e57..5d319e0ea 100644 --- a/src/app/savings/savings-routing.module.ts +++ b/src/app/savings/savings-routing.module.ts @@ -14,6 +14,7 @@ import { ChargesTabComponent } from './savings-account-view/charges-tab/charges- import { StandingInstructionsTabComponent } from './savings-account-view/standing-instructions-tab/standing-instructions-tab.component'; import { DatatableTabsComponent } from './savings-account-view/datatable-tabs/datatable-tabs.component'; import { CreateSavingsAccountComponent } from './create-savings-account/create-savings-account.component'; +import { EditSavingsAccountComponent } from './edit-savings-account/edit-savings-account.component'; /** Custom Resolvers */ import { SavingAccountTransactionTemplateResolver } from './common-resolvers/saving-transaction-template.resolver'; @@ -22,6 +23,7 @@ import { SavingsAccountViewResolver } from './common-resolvers/savings-account-v import { SavingsDatatableResolver } from './common-resolvers/savings-datatable.resolver'; import { SavingsDatatablesResolver } from './common-resolvers/savings-datatables.resolver'; import { SavingsAccountTemplateResolver } from './common-resolvers/savings-account-template.resolver'; +import { SavingsAccountAndTemplateResolver } from './common-resolvers/savings-account-and-template.resolver'; const routes: Routes = [ { @@ -39,40 +41,53 @@ const routes: Routes = [ { path: ':savingAccountId', data: { title: extract('Saving Account View'), routeParamBreadcrumb: 'savingAccountId' }, - component: SavingsAccountViewComponent, - resolve: { - savingsAccountData: SavingsAccountViewResolver, - savingsDatatables: SavingsDatatablesResolver - }, children: [ { - path: 'transactions', - component: TransactionsTabComponent, - data: { title: extract('Savings Account Transactions'), breadcrumb: 'Transactions', routeParamBreadcrumb: false } - }, - { - path: 'charges', - component: ChargesTabComponent, - data: { title: extract('Savings Account Charges'), breadcrumb: 'Charges', routeParamBreadcrumb: false } - }, - { - path: 'standing-instructions', - component: StandingInstructionsTabComponent, - data: { title: extract('Savings Account SIH'), breadcrumb: 'Standing Instructions', routeParamBreadcrumb: false } - }, - { - path: 'datatables', + path: '', + component: SavingsAccountViewComponent, + resolve: { + savingsAccountData: SavingsAccountViewResolver, + savingsDatatables: SavingsDatatablesResolver + }, children: [ { - path: ':datatableName', - component: DatatableTabsComponent, - data: { title: extract('View Data Table'), routeParamBreadcrumb: 'datatableName' }, - resolve: { - savingsDatatable: SavingsDatatableResolver - } + path: 'transactions', + component: TransactionsTabComponent, + data: { title: extract('Savings Account Transactions'), breadcrumb: 'Transactions', routeParamBreadcrumb: false } + }, + { + path: 'charges', + component: ChargesTabComponent, + data: { title: extract('Savings Account Charges'), breadcrumb: 'Charges', routeParamBreadcrumb: false } + }, + { + path: 'standing-instructions', + component: StandingInstructionsTabComponent, + data: { title: extract('Savings Account SIH'), breadcrumb: 'Standing Instructions', routeParamBreadcrumb: false } + }, + { + path: 'datatables', + children: [ + { + path: ':datatableName', + component: DatatableTabsComponent, + data: { title: extract('View Data Table'), routeParamBreadcrumb: 'datatableName' }, + resolve: { + savingsDatatable: SavingsDatatableResolver + } + } + ] } ] }, + { + path: 'edit-savings-account', + data: { title: extract('Edit Savings Account'), breadcrumb: 'Edit', routeParamBreadcrumb: false }, + component: EditSavingsAccountComponent, + resolve: { + savingsAccountAndTemplate: SavingsAccountAndTemplateResolver + } + }, { path: 'add-savings-charge', component: AddSavingsChargeComponent, @@ -103,6 +118,7 @@ const routes: Routes = [ SavingsAccountViewResolver, SavingsDatatablesResolver, SavingsDatatableResolver, - SavingsAccountTemplateResolver] + SavingsAccountTemplateResolver, + SavingsAccountAndTemplateResolver] }) export class SavingsRoutingModule {} diff --git a/src/app/savings/savings.module.ts b/src/app/savings/savings.module.ts index e173cfc44..553b3bd10 100644 --- a/src/app/savings/savings.module.ts +++ b/src/app/savings/savings.module.ts @@ -24,6 +24,7 @@ import { SavingsAccountDetailsStepComponent } from './savings-account-stepper/sa import { SavingsAccountChargesStepComponent } from './savings-account-stepper/savings-account-charges-step/savings-account-charges-step.component'; import { SavingsAccountTermsStepComponent } from './savings-account-stepper/savings-account-terms-step/savings-account-terms-step.component'; import { SavingsAccountPreviewStepComponent } from './savings-account-stepper/savings-account-preview-step/savings-account-preview-step.component'; +import { EditSavingsAccountComponent } from './edit-savings-account/edit-savings-account.component'; /** * Savings Module @@ -52,7 +53,8 @@ import { SavingsAccountPreviewStepComponent } from './savings-account-stepper/sa SavingsAccountDetailsStepComponent, SavingsAccountChargesStepComponent, SavingsAccountTermsStepComponent, - SavingsAccountPreviewStepComponent + SavingsAccountPreviewStepComponent, + EditSavingsAccountComponent ], providers: [DatePipe] }) diff --git a/src/app/savings/savings.service.ts b/src/app/savings/savings.service.ts index 21898149e..e3d5e952e 100644 --- a/src/app/savings/savings.service.ts +++ b/src/app/savings/savings.service.ts @@ -63,7 +63,18 @@ export class SavingsService { * @returns {Observable} Savings data. */ getSavingsAccountData(accountId: string): Observable { - const httpParams = new HttpParams().set('associations', 'all'); + const httpParams = new HttpParams().set('associations', 'all' ); + return this.http.get(`/savingsaccounts/${accountId}`, { params: httpParams }); + } + + /** + * @param accountId Savings Account Id of account to get data for. + * @returns {Observable} Savings account and template. + */ + getSavingsAccountAndTemplate(accountId: string, template: boolean): Observable { + const httpParams = new HttpParams() + .set('template', template.toString()) + .set('associations', 'charges' ); return this.http.get(`/savingsaccounts/${accountId}`, { params: httpParams }); } @@ -156,4 +167,12 @@ export class SavingsService { return this.http.post('/savingsaccounts', savingsAccount); } + /** + * @param {any} savingsAccount Savings Account + * @returns {Observable} + */ + updateSavingsAccount(accountId: string, savingsAccount: any): Observable { + return this.http.put(`/savingsaccounts/${accountId}`, savingsAccount); + } + } diff --git a/src/app/shares/shares-account-stepper/shares-account-charges-step/shares-account-charges-step.component.ts b/src/app/shares/shares-account-stepper/shares-account-charges-step/shares-account-charges-step.component.ts index 87a119ffc..445b6724c 100644 --- a/src/app/shares/shares-account-stepper/shares-account-charges-step/shares-account-charges-step.component.ts +++ b/src/app/shares/shares-account-stepper/shares-account-charges-step/shares-account-charges-step.component.ts @@ -81,8 +81,8 @@ export class SharesAccountChargesStepComponent implements OnInit, OnChanges { controlName: 'amount', label: 'Amount', value: charge.amount || charge.amountOrPercentage, - type: 'text', - required: true, + type: 'number', + required: false, }), ]; const data = { diff --git a/src/app/shares/shares-account-stepper/shares-account-terms-step/shares-account-terms-step.component.ts b/src/app/shares/shares-account-stepper/shares-account-terms-step/shares-account-terms-step.component.ts index 95e80f915..a382db0e1 100644 --- a/src/app/shares/shares-account-stepper/shares-account-terms-step/shares-account-terms-step.component.ts +++ b/src/app/shares/shares-account-stepper/shares-account-terms-step/shares-account-terms-step.component.ts @@ -63,9 +63,9 @@ export class SharesAccountTermsStepComponent implements OnChanges, OnInit { this.sharesAccountTermsForm.patchValue({ 'requestedShares': this.sharesAccountTemplate.summary.totalPendingForApprovalShares, 'minimumActivePeriod': this.sharesAccountTemplate.minimumActivePeriod, - 'minimumActivePeriodFrequencyType': this.sharesAccountTemplate.minimumActivePeriodTypeEnum.id, + 'minimumActivePeriodFrequencyType': this.sharesAccountTemplate.minimumActivePeriod && this.sharesAccountTemplate.minimumActivePeriodTypeEnum.id, 'lockinPeriodFrequency': this.sharesAccountTemplate.lockinPeriod, - 'lockinPeriodFrequencyType': this.sharesAccountTemplate.lockPeriodTypeEnum.id, + 'lockinPeriodFrequencyType': this.sharesAccountTemplate.lockinPeriod && this.sharesAccountTemplate.lockPeriodTypeEnum.id, 'applicationDate': this.sharesAccountTemplate.purchasedShares[0].purchasedDate && new Date(this.sharesAccountTemplate.purchasedShares[0].purchasedDate), 'allowDividendCalculationForInactiveClients': this.sharesAccountTemplate.allowDividendCalculationForInactiveClients });