diff --git a/src/app/clients/clients-routing.module.ts b/src/app/clients/clients-routing.module.ts index 5da1a44a3..3e800ebc2 100644 --- a/src/app/clients/clients-routing.module.ts +++ b/src/app/clients/clients-routing.module.ts @@ -173,6 +173,10 @@ const routes: Routes = [ data: { title: extract('Loans'), breadcrumb: 'loans', routeParamBreadcrumb: false }, loadChildren: '../loans/loans.module#LoansModule' }, + { + path: 'fixed-deposits-accounts', + loadChildren: '../deposits/fixed-deposits/fixed-deposits.module#FixedDepositsModule' + }, { path: 'savingsaccounts', loadChildren: '../savings/savings.module#SavingsModule' diff --git a/src/app/clients/clients-view/general-tab/general-tab.component.html b/src/app/clients/clients-view/general-tab/general-tab.component.html index f1f11d4bc..98ce7e5c5 100644 --- a/src/app/clients/clients-view/general-tab/general-tab.component.html +++ b/src/app/clients/clients-view/general-tab/general-tab.component.html @@ -374,7 +374,7 @@ + [routerLink]="['../', 'fixed-deposits-accounts', row.id, 'interest-rate-chart']"> @@ -399,7 +399,8 @@ - + diff --git a/src/app/deposits/fixed-deposits/common-resolvers/fixed-deposit-account-view.resolver.ts b/src/app/deposits/fixed-deposits/common-resolvers/fixed-deposit-account-view.resolver.ts new file mode 100644 index 000000000..09f5d82c8 --- /dev/null +++ b/src/app/deposits/fixed-deposits/common-resolvers/fixed-deposit-account-view.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 { FixedDepositsService } from 'app/deposits/fixed-deposits/fixed-deposits.service'; + +/** + * Fixed Deposits Account data resolver. + */ +@Injectable() +export class FixedDepositsAccountViewResolver implements Resolve { + + /** + * @param {FixedDepositsService} fixedDepositsService Fixed Deposits service. + */ + constructor(private fixedDepositsService: FixedDepositsService) { } + + /** + * Returns the Fixed Deposits Account data. + * @param {ActivatedRouteSnapshot} route Route Snapshot + * @returns {Observable} + */ + resolve(route: ActivatedRouteSnapshot): Observable { + const fixedDepositAccountId = route.paramMap.get('fixedDepositAccountId'); + return this.fixedDepositsService.getFixedDepositsAccountData(fixedDepositAccountId); + } + +} diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/charges-tab/charges-tab.component.html b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/charges-tab/charges-tab.component.html new file mode 100644 index 000000000..c4f98d03f --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/charges-tab/charges-tab.component.html @@ -0,0 +1,101 @@ +
+ +
+
+

All Charges

+
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name {{ charge.name }} Fee/Penalty {{ charge.penalty === true ? 'Penalty' : 'Fee' }} Payment Due At {{ charge.chargeTimeType.value }} Due As Of {{ charge.dueDate | date }} Repeats On (M/d) {{ charge.feeOnMonthDay ? charge.feeOnMonthDay.join('/') : '' }} Calculation Type {{charge.chargeCalculationType.value}} Due {{charge.currency.displaySymbol}} {{charge.amount}} Paid {{charge.currency.displaySymbol}} {{charge.amountPaid}} Waived {{charge.currency.displaySymbol}} {{charge.amountWaived}} Outstanding {{charge.currency.displaySymbol}} {{charge.amountOutstanding}} Actions + + + + + + + + + + + +
+ +
+ +
diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/charges-tab/charges-tab.component.scss b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/charges-tab/charges-tab.component.scss new file mode 100644 index 000000000..aaafd7b18 --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/charges-tab/charges-tab.component.scss @@ -0,0 +1,19 @@ +.tab-container { + padding: 1%; + margin: 1%; + h3 { + margin:1% auto; + } + .action-button { + margin-left: auto; + } + table { + width: 100%; + .account-action-button{ + min-width: 26px; + padding: 0 6px; + margin: 4px; + line-height: 25px; + } + } +} diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/charges-tab/charges-tab.component.spec.ts b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/charges-tab/charges-tab.component.spec.ts new file mode 100644 index 000000000..1ef118215 --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/charges-tab/charges-tab.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ChargesTabComponent } from './charges-tab.component'; + +describe('ChargesTabComponent', () => { + let component: ChargesTabComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ChargesTabComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ChargesTabComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/charges-tab/charges-tab.component.ts b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/charges-tab/charges-tab.component.ts new file mode 100644 index 000000000..8bc3f2e0f --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/charges-tab/charges-tab.component.ts @@ -0,0 +1,81 @@ +/** Angular Imports */ +import { Component, OnInit, ViewChild } from '@angular/core'; +import { MatTableDataSource, MatTable } from '@angular/material'; +import { ActivatedRoute } from '@angular/router'; + +/** + * Charges Tab Component + */ +@Component({ + selector: 'mifosx-charges-tab', + templateUrl: './charges-tab.component.html', + styleUrls: ['./charges-tab.component.scss'] +}) +export class ChargesTabComponent implements OnInit { + + /** Fixed Deposits Account Data */ + fixedDepositsAccountData: any; + /** Charges Data */ + chargesData: any[]; + /** Data source for charges table. */ + dataSource: MatTableDataSource; + /** Toggles Charges Table */ + showInactiveCharges = false; + /** Columns to be displayed in charges table. */ + displayedColumns: string[] = [ + 'name', + 'feeOrPenalty', + 'paymentDueAt', + 'dueAsOf', + 'repeatsOn', + 'calculationType', + 'due', + 'paid', + 'waived', + 'outstanding', + 'actions' + ]; + + /** Charges Table Reference */ + @ViewChild('chargesTable') chargesTableRef: MatTable; + + /** + * Retrieves Fixed Deposits Account Data from `resolve`. + * @param {ActivatedRoute} route Activated Route. + */ + constructor(private route: ActivatedRoute) { + this.route.parent.data.subscribe((data: { fixedDepositsAccountData: any }) => { + this.fixedDepositsAccountData = data.fixedDepositsAccountData; + this.chargesData = this.fixedDepositsAccountData.charges; + }); + } + + ngOnInit() { + const activeCharges = this.chargesData ? this.chargesData.filter(charge => charge.isActive) : []; + this.dataSource = new MatTableDataSource(activeCharges); + } + + /** + * Toggles datasource for active/inactive charges. + */ + toggleCharges() { + this.showInactiveCharges = !this.showInactiveCharges; + if (!this.showInactiveCharges) { + const activeCharges = this.chargesData.filter(charge => charge.isActive); + this.dataSource.data = activeCharges; + } else { + const inActiveCharges = this.chargesData.filter(charge => !charge.isActive); + this.dataSource.data = inActiveCharges; + } + this.chargesTableRef.renderRows(); + } + + /** + * Checks if charge is recurring. + * @param {any} charge Charge + */ + isRecurringCharge(charge: any) { + return charge.chargeTimeType.value === 'Monthly Fee' || charge.chargeTimeType.value === 'Annual Fee' || charge.chargeTimeType.value === 'Weekly Fee'; + } + +} diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component-theme.scss b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component-theme.scss new file mode 100644 index 000000000..dd8f6d0bb --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component-theme.scss @@ -0,0 +1,16 @@ +@import "~@angular/material/theming"; + +@mixin fixed-deposits-account-view-component-theme($theme) { + $primary: map-get($theme, primary); + mifosx-fixed-deposit-account-view { + .fixed-deposits-account-card { + .header { + background-color: mat-color($primary, 500); + } + .table-headers { + background-color: mat-color($primary, 500); + color: mat-contrast($primary, 500); + } + } + } +} diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component.html b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component.html new file mode 100644 index 000000000..fc1d41963 --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component.html @@ -0,0 +1,200 @@ + diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component.scss b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component.scss new file mode 100644 index 000000000..53af5797a --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component.scss @@ -0,0 +1,53 @@ +.fixed-deposits-account-card { + margin: 0 auto; + max-width: 80rem; + width: 90%; + padding: 0; + .header { + padding: 1%; + .header-title-group { + .account-card-title { + color: white; + width: 90%; + p { + color: white; + } + } + } + .profile-image-container { + margin: 1%; + .profile-image { + object-fit: cover; + border-radius: 20px; + } + } + .account-actions { + align-self: flex-end; + margin: 0 1%; + i { + margin-bottom: 2px; + margin-right: 4px; + } + } + } + .navigation-tabs { + background-color: #f2f2f2; + overflow: auto; + } + .content { + .fixed-deposits-account-tables { + padding: 1%; + margin: 1%; + .table-headers { + margin: 0; + padding: 6px; + } + td { + padding: 3px; + } + } + } + i, img:hover { + cursor: pointer; + } +} diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component.spec.ts b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component.spec.ts new file mode 100644 index 000000000..699b6b14c --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FixedDepositAccountViewComponent } from './fixed-deposit-account-view.component'; + +describe('FixedDepositAccountViewComponent', () => { + let component: FixedDepositAccountViewComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ FixedDepositAccountViewComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(FixedDepositAccountViewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component.ts b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component.ts new file mode 100644 index 000000000..4fa30aac1 --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component.ts @@ -0,0 +1,54 @@ +/** Angular Imports */ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { FixedDepositsButtonsConfiguration } from './fixed-deposits-buttons.config'; + +/** + * Fixed Deposits Account View Component + */ +@Component({ + selector: 'mifosx-fixed-deposit-account-view', + templateUrl: './fixed-deposit-account-view.component.html', + styleUrls: ['./fixed-deposit-account-view.component.scss'] +}) +export class FixedDepositAccountViewComponent implements OnInit { + + /** Fixed Deposits Account Data */ + fixedDepositsAccountData: any; + /** Button Configurations */ + buttonConfig: FixedDepositsButtonsConfiguration; + + /** + * Fetches fixed deposits account data from `resolve` + * @param {ActivatedRoute} route Activated Route + */ + constructor(private route: ActivatedRoute) { + this.route.data.subscribe((data: { fixedDepositsAccountData: any }) => { + this.fixedDepositsAccountData = data.fixedDepositsAccountData; + }); + } + + ngOnInit() { + this.setConditionalButtons(); + } + + /** + * Adds options to button config. conditionaly. + */ + setConditionalButtons() { + const status = this.fixedDepositsAccountData.status.value; + this.buttonConfig = new FixedDepositsButtonsConfiguration(status); + if (this.fixedDepositsAccountData.taxGroup && status === 'Active') { + if (this.fixedDepositsAccountData.withHoldTax) { + this.buttonConfig.addOption({ + name: 'Disable Withhold Tax' + }); + } else { + this.buttonConfig.addOption({ + name: 'Enable Withhold Tax' + }); + } + } + } + +} diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposits-buttons.config.ts b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposits-buttons.config.ts new file mode 100644 index 000000000..a0688ae0c --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposits-buttons.config.ts @@ -0,0 +1,120 @@ +/** Fixed Deposits Account Buttons Configuration */ +export class FixedDepositsButtonsConfiguration { + + optionArray: { + name: string + }[]; + + buttonsArray: { + name: string, + icon: string, + }[]; + + constructor(status: string) { + this.setOptions(status); + this.setButtons(status); + } + + get singleButtons() { + return this.buttonsArray; + } + + get options() { + return this.optionArray; + } + + setButtons(status: string) { + switch (status) { + case 'Active': + this.buttonsArray = [ + { + name: 'Premature Close', + icon: 'fa fa-arrow-left' + }, + { + name: 'Calculate Interest', + icon: 'fa fa-table' + } + ]; + break; + case 'Matured': + this.buttonsArray = [ + { + name: 'Close', + icon: 'fa fa-arrow-right' + }, + { + name: 'Calculate Interest', + icon: 'fa fa-table' + } + ]; + break; + case 'Submitted and pending approval': + this.buttonsArray = [ + { + name: 'Modify Application', + icon: 'fa fa-pencil ' + }, + { + name: 'Approve', + icon: 'fa fa-check' + } + ]; + break; + case 'Approved': + this.buttonsArray = [ + { + name: 'Undo Approval', + icon: 'fa fa-undo' + }, + { + name: 'Activate', + icon: 'fa fa-check' + } + ]; + break; + default: + this.buttonsArray = []; + } + } + + setOptions(status: string) { + switch (status) { + case 'Active': + case 'Matured': + this.optionArray = [ + { + name: 'Post Interest' + }, + { + name: 'Add Charge' + } + ]; + break; + case 'Submitted and pending approval': + this.optionArray = [ + { + name: 'Reject' + }, + { + name: 'Withdraw By Client' + }, + { + name: 'Add Charge' + }, + { + name: 'Delete' + } + ]; + break; + case 'Approved': + default: + this.optionArray = []; + } + } + + addOption(option: {name: string}) { + this.optionArray.push(option); + } + +} diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/interest-rate-chart-tab/interest-rate-chart-tab.component.html b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/interest-rate-chart-tab/interest-rate-chart-tab.component.html new file mode 100644 index 000000000..05ee03c80 --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/interest-rate-chart-tab/interest-rate-chart-tab.component.html @@ -0,0 +1,44 @@ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Period {{rateChart.fromPeriod}}-{{rateChart.toPeriod}} {{rateChart.periodType.value}} Amount Range {{rateChart.amountRangeFrom}}-{{rateChart.amountRangeTo}} Interest {{ rateChart.annualInterestRate }} Description {{ rateChart.description }} Incentives + +
+ +
+ +
diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/interest-rate-chart-tab/interest-rate-chart-tab.component.scss b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/interest-rate-chart-tab/interest-rate-chart-tab.component.scss new file mode 100644 index 000000000..be9328c80 --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/interest-rate-chart-tab/interest-rate-chart-tab.component.scss @@ -0,0 +1,10 @@ +.tab-container { + padding: 1%; + margin: 1%; + h3 { + margin:1% auto; + } + table { + width: 100%; + } +} diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/interest-rate-chart-tab/interest-rate-chart-tab.component.spec.ts b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/interest-rate-chart-tab/interest-rate-chart-tab.component.spec.ts new file mode 100644 index 000000000..26675582a --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/interest-rate-chart-tab/interest-rate-chart-tab.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InterestRateChartTabComponent } from './interest-rate-chart-tab.component'; + +describe('InterestRateChartTabComponent', () => { + let component: InterestRateChartTabComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ InterestRateChartTabComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(InterestRateChartTabComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/interest-rate-chart-tab/interest-rate-chart-tab.component.ts b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/interest-rate-chart-tab/interest-rate-chart-tab.component.ts new file mode 100644 index 000000000..29156ca00 --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/interest-rate-chart-tab/interest-rate-chart-tab.component.ts @@ -0,0 +1,39 @@ +/** Angular Imports */ +import { Component, OnInit } from '@angular/core'; +import { MatTableDataSource } from '@angular/material'; +import { ActivatedRoute } from '@angular/router'; + +/** + * Interest Rate Chart Tab Component. + */ +@Component({ + selector: 'mifosx-interest-rate-chart-tab', + templateUrl: './interest-rate-chart-tab.component.html', + styleUrls: ['./interest-rate-chart-tab.component.scss'] +}) +export class InterestRateChartTabComponent implements OnInit { + + /** Fixed Deposits Account Status */ + status: any; + /** Interest Rate Chart Data */ + interestRateChartData: any; + /** Columns to be displayed in interest rate chart table. */ + displayedColumns: string[] = ['period', 'amountRange', 'interest', 'description', 'incentives']; + /** Data source for interest rate chart table. */ + dataSource: MatTableDataSource; + + /** + * Retrieves fixed deposits account data from `resolve`. + * @param {ActivatedRoute} route Activated Route. + */ + constructor(private route: ActivatedRoute) { + this.route.parent.data.subscribe((data: { fixedDepositsAccountData: any }) => { + this.interestRateChartData = data.fixedDepositsAccountData.accountChart.chartSlabs; + }); + } + + ngOnInit() { + this.dataSource = new MatTableDataSource(this.interestRateChartData); + } + +} diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/standing-instructions-tab/standing-instructions-tab.component.html b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/standing-instructions-tab/standing-instructions-tab.component.html new file mode 100644 index 000000000..709466062 --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/standing-instructions-tab/standing-instructions-tab.component.html @@ -0,0 +1,70 @@ +
+ +
+

All Standing Instructions

+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Client {{instruction.fromClient.displayName}}-{{instruction.fromClient.id}} From Account {{instruction.fromAccount.accountNo}} ({{instruction.fromAccountType.value}}) Beneficiary {{instruction.toClient.displayName}} To Account {{instruction.toAccount.accountNo}} ({{instruction.toAccountType.value}}) Amount {{instruction.instructionType.value}}/{{instruction.amount}} Validity {{instruction.validFrom | date}} to {{instruction.validTill | date}} Actions + + + + + + + +
+ +
+ +
diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/standing-instructions-tab/standing-instructions-tab.component.scss b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/standing-instructions-tab/standing-instructions-tab.component.scss new file mode 100644 index 000000000..aaafd7b18 --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/standing-instructions-tab/standing-instructions-tab.component.scss @@ -0,0 +1,19 @@ +.tab-container { + padding: 1%; + margin: 1%; + h3 { + margin:1% auto; + } + .action-button { + margin-left: auto; + } + table { + width: 100%; + .account-action-button{ + min-width: 26px; + padding: 0 6px; + margin: 4px; + line-height: 25px; + } + } +} diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/standing-instructions-tab/standing-instructions-tab.component.spec.ts b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/standing-instructions-tab/standing-instructions-tab.component.spec.ts new file mode 100644 index 000000000..f3997e094 --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/standing-instructions-tab/standing-instructions-tab.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { StandingInstructionsTabComponent } from './standing-instructions-tab.component'; + +describe('StandingInstructionsTabComponent', () => { + let component: StandingInstructionsTabComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ StandingInstructionsTabComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(StandingInstructionsTabComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/standing-instructions-tab/standing-instructions-tab.component.ts b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/standing-instructions-tab/standing-instructions-tab.component.ts new file mode 100644 index 000000000..c9250bd45 --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/standing-instructions-tab/standing-instructions-tab.component.ts @@ -0,0 +1,70 @@ +/** Angular Imports */ +import { Component, OnInit, ViewChild } from '@angular/core'; +import { MatTableDataSource, MatTable } from '@angular/material'; +import { ActivatedRoute } from '@angular/router'; + +/** Custom Services */ +import { FixedDepositsService } from 'app/deposits/fixed-deposits/fixed-deposits.service'; + +/** + * Fixed Deposits Standing Instructions Tab + */ +@Component({ + selector: 'mifosx-standing-instructions-tab', + templateUrl: './standing-instructions-tab.component.html', + styleUrls: ['./standing-instructions-tab.component.scss'] +}) +export class StandingInstructionsTabComponent implements OnInit { + + /** Fixed Deposits Data */ + fixedDepositsData: any; + /** Instructions Data */ + instructionsData: any[]; + /** Data source for instructions table. */ + dataSource = new MatTableDataSource(); + /** Columns to be displayed in instructions table. */ + displayedColumns: string[] = [ + 'client', + 'fromAccount', + 'beneficiary', + 'toAccount', + 'amount', + 'validity', + 'actions' + ]; + + /** Instruction Table Reference */ + @ViewChild('instructionsTable') instructionTableRef: MatTable; + + /** + * Retrieves Fixed Deposits Account Data from `resolve`. + * @param {ActivatedRoute} route Activated Route. + */ + constructor(private route: ActivatedRoute, + private fixedDepositsService: FixedDepositsService) { + this.route.parent.data.subscribe((data: { fixedDepositsAccountData: any }) => { + this.fixedDepositsData = data.fixedDepositsAccountData; + }); + } + + ngOnInit() { + this.getStandingInstructions(); + } + + /** + * Retrieves standing instructions and initializes instructions table. + */ + getStandingInstructions() { + const clientId = this.fixedDepositsData.clientId; + const clientName = this.fixedDepositsData.clientName; + const accountId = this.fixedDepositsData.id; + const locale = 'en'; + const dateFormat = 'dd MMMM yyyy'; + this.fixedDepositsService.getStandingInstructions(clientId, clientName, accountId, locale, dateFormat).subscribe((response: any) => { + this.instructionsData = response.pageItems; + this.dataSource.data = this.instructionsData; + this.instructionTableRef.renderRows(); + }); + } + +} diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/transactions-tab/transactions-tab.component.html b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/transactions-tab/transactions-tab.component.html new file mode 100644 index 000000000..f9307818a --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/transactions-tab/transactions-tab.component.html @@ -0,0 +1,44 @@ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ID {{ transaction.id }} Transaction Date {{ transaction.date | date }} Transaction Type {{ transaction.transactionType.value }} Debit {{ isDebit(transaction.transactionType) ? transaction.amount : 'N/A'}} Credit {{ !isDebit(transaction.transactionType) ? transaction.amount : 'N/A' }} Balance {{ transaction.runningBalance }}
+ +
+ +
diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/transactions-tab/transactions-tab.component.scss b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/transactions-tab/transactions-tab.component.scss new file mode 100644 index 000000000..be9328c80 --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/transactions-tab/transactions-tab.component.scss @@ -0,0 +1,10 @@ +.tab-container { + padding: 1%; + margin: 1%; + h3 { + margin:1% auto; + } + table { + width: 100%; + } +} diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/transactions-tab/transactions-tab.component.spec.ts b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/transactions-tab/transactions-tab.component.spec.ts new file mode 100644 index 000000000..a67fc2279 --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/transactions-tab/transactions-tab.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TransactionsTabComponent } from './transactions-tab.component'; + +describe('TransactionsTabComponent', () => { + let component: TransactionsTabComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ TransactionsTabComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TransactionsTabComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/transactions-tab/transactions-tab.component.ts b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/transactions-tab/transactions-tab.component.ts new file mode 100644 index 000000000..772723b43 --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/transactions-tab/transactions-tab.component.ts @@ -0,0 +1,49 @@ +/** Angular Imports */ +import { Component, OnInit } from '@angular/core'; +import { MatTableDataSource } from '@angular/material'; +import { ActivatedRoute } from '@angular/router'; + +/** + * Transactions Tab Component. + */ +@Component({ + selector: 'mifosx-transactions-tab', + templateUrl: './transactions-tab.component.html', + styleUrls: ['./transactions-tab.component.scss'] +}) +export class TransactionsTabComponent implements OnInit { + + /** Fixed Deposits Account Status */ + status: any; + /** Transactions Data */ + transactionsData: any; + /** Columns to be displayed in transactions table. */ + displayedColumns: string[] = ['id', 'transactionDate', 'transactionType', 'debit', 'credit', 'balance']; + /** Data source for transactions table. */ + dataSource: MatTableDataSource; + + /** + * Retrieves fixed deposits account data from `resolve`. + * @param {ActivatedRoute} route Activated Route. + */ + constructor(private route: ActivatedRoute) { + this.route.parent.data.subscribe((data: { fixedDepositsAccountData: any }) => { + this.transactionsData = data.fixedDepositsAccountData.transactions; + this.status = data.fixedDepositsAccountData.status.value; + }); + } + + ngOnInit() { + this.dataSource = new MatTableDataSource(this.transactionsData); + } + + /** + * Checks if transaction is debit. + * @param {any} transactionType Transaction Type + */ + isDebit(transactionType: any) { + return transactionType.withdrawal === true || transactionType.feeDeduction === true + || transactionType.overdraftInterest === true || transactionType.withholdTax === true; + } + +} diff --git a/src/app/deposits/fixed-deposits/fixed-deposits-routing.module.ts b/src/app/deposits/fixed-deposits/fixed-deposits-routing.module.ts new file mode 100644 index 000000000..0dd3d2fb1 --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposits-routing.module.ts @@ -0,0 +1,72 @@ +/** Angular Imports */ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; + +/** Translation Imports */ +import { extract } from 'app/core/i18n/i18n.service'; + +/** Custom Components */ +import { FixedDepositAccountViewComponent } from './fixed-deposit-account-view/fixed-deposit-account-view.component'; +import { InterestRateChartTabComponent } from './fixed-deposit-account-view/interest-rate-chart-tab/interest-rate-chart-tab.component'; +import { TransactionsTabComponent } from './fixed-deposit-account-view/transactions-tab/transactions-tab.component'; +import { ChargesTabComponent } from './fixed-deposit-account-view/charges-tab/charges-tab.component'; +import { StandingInstructionsTabComponent } from './fixed-deposit-account-view/standing-instructions-tab/standing-instructions-tab.component'; + +/** Custom Resolvers */ +import { FixedDepositsAccountViewResolver } from '../fixed-deposits/common-resolvers/fixed-deposit-account-view.resolver'; + +const routes: Routes = [ + { + path: '', + data: { title: extract('All Fixed Deposits'), breadcrumb: 'Fixed Deposits', routeParamBreadcrumb: false }, + children: [ + { + path: ':fixedDepositAccountId', + data: { title: extract('Fixed Deposit Account View'), routeParamBreadcrumb: 'fixedDepositAccountId' }, + resolve: { + + }, + children: [ + { + path: '', + component: FixedDepositAccountViewComponent, + resolve: { + fixedDepositsAccountData: FixedDepositsAccountViewResolver + }, + children: [ + { + path: 'interest-rate-chart', + component: InterestRateChartTabComponent, + data: { title: extract('Fixed Deposit Account Interest Rate Chart'), breadcrumb: 'Interest Rate Chart', routeParamBreadcrumb: false }, + }, + { + path: 'transactions', + component: TransactionsTabComponent, + data: { title: extract('Fixed Deposit Account Transactions'), breadcrumb: 'Transactions', routeParamBreadcrumb: false }, + }, + { + path: 'charges', + component: ChargesTabComponent, + data: { title: extract('Fixed Deposit Account Charges'), breadcrumb: 'Charges', routeParamBreadcrumb: false } + }, + { + path: 'standing-instructions', + component: StandingInstructionsTabComponent, + data: { title: extract('Fixed Deposit Account Standing Instructions'), breadcrumb: 'Standing Instructions', routeParamBreadcrumb: false } + } + ] + } + ] + } + ] + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], + providers: [ + FixedDepositsAccountViewResolver + ] +}) +export class FixedDepositsRoutingModule { } diff --git a/src/app/deposits/fixed-deposits/fixed-deposits.module.ts b/src/app/deposits/fixed-deposits/fixed-deposits.module.ts new file mode 100644 index 000000000..b8f5ef163 --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposits.module.ts @@ -0,0 +1,34 @@ +/** Angular Imports */ +import { NgModule } from '@angular/core'; +import { DatePipe } from '@angular/common'; + +/** Custom Modules */ +import { SharedModule } from 'app/shared/shared.module'; +import { PipesModule } from 'app/pipes/pipes.module'; +import { DirectivesModule } from 'app/directives/directives.module'; +import { FixedDepositsRoutingModule } from './fixed-deposits-routing.module'; + +/** Custom Components */ +import { FixedDepositAccountViewComponent } from './fixed-deposit-account-view/fixed-deposit-account-view.component'; +import { TransactionsTabComponent } from './fixed-deposit-account-view/transactions-tab/transactions-tab.component'; +import { ChargesTabComponent } from './fixed-deposit-account-view/charges-tab/charges-tab.component'; +import { StandingInstructionsTabComponent } from './fixed-deposit-account-view/standing-instructions-tab/standing-instructions-tab.component'; +import { InterestRateChartTabComponent } from './fixed-deposit-account-view/interest-rate-chart-tab/interest-rate-chart-tab.component'; + +@NgModule({ + declarations: [ + FixedDepositAccountViewComponent, + TransactionsTabComponent, + ChargesTabComponent, + StandingInstructionsTabComponent, + InterestRateChartTabComponent + ], + imports: [ + SharedModule, + PipesModule, + DirectivesModule, + FixedDepositsRoutingModule + ], + providers: [DatePipe] +}) +export class FixedDepositsModule { } diff --git a/src/app/deposits/fixed-deposits/fixed-deposits.service.spec.ts b/src/app/deposits/fixed-deposits/fixed-deposits.service.spec.ts new file mode 100644 index 000000000..757430e9f --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposits.service.spec.ts @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { FixedDepositsService } from './fixed-deposits.service'; + +describe('FixedDepositsService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: FixedDepositsService = TestBed.get(FixedDepositsService); + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/deposits/fixed-deposits/fixed-deposits.service.ts b/src/app/deposits/fixed-deposits/fixed-deposits.service.ts new file mode 100644 index 000000000..dd3eead71 --- /dev/null +++ b/src/app/deposits/fixed-deposits/fixed-deposits.service.ts @@ -0,0 +1,48 @@ +/** Angular Imports */ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpParams } from '@angular/common/http'; + +/** rxjs Imports */ +import { Observable } from 'rxjs'; + +/** + * Fixed Deposits Service. + */ +@Injectable({ + providedIn: 'root' +}) +export class FixedDepositsService { + + constructor(private http: HttpClient) {} + + /** + * @param accountId Account Id of group to get data for. + * @returns {Observable} Fixed Deposits data. + */ + getFixedDepositsAccountData(accountId: string): Observable { + const httpParams = new HttpParams().set('associations', 'all'); + return this.http.get(`/fixeddepositaccounts/${accountId}`, { params: httpParams }); + } + + /** + * @param clientId Client Id + * @param clientName Client Name + * @param fromAccountId Account Id + * @param locale Locale + * @param dateFormat Date Format + * @returns {Observable} Standing Instructions + */ + getStandingInstructions( + clientId: string, clientName: string, fromAccountId: string, + locale: string, dateFormat: string): Observable { + const httpParams = new HttpParams() + .set('clientId', clientId) + .set('clientName', clientName) + .set('fromAccountId', fromAccountId) + .set('fromAccountType', '2') + .set('locale', locale) + .set('dateFormat', dateFormat); + return this.http.get(`/standinginstructions`, { params: httpParams }); + } + +} diff --git a/src/assets/images/fd_account_placeholder.png b/src/assets/images/fd_account_placeholder.png new file mode 100644 index 000000000..e63ed3e3b Binary files /dev/null and b/src/assets/images/fd_account_placeholder.png differ diff --git a/src/theme/custom/denim-yellowgreen.scss b/src/theme/custom/denim-yellowgreen.scss index c85fd0ed9..63a3739d9 100644 --- a/src/theme/custom/denim-yellowgreen.scss +++ b/src/theme/custom/denim-yellowgreen.scss @@ -7,6 +7,7 @@ @import '../../app/loans/loans-view/loans-view.component-theme.scss'; @import '../../app/savings/savings-account-view/savings-account-view.component-theme.scss'; @import '../../app/shares/shares-account-view/shares-account-view.component-theme.scss'; +@import '../../app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component-theme.scss'; // Custom material palette $mat-denim: ( @@ -59,3 +60,4 @@ $mifosx-app-theme: mat-light-theme($mifosx-app-primary, $mifosx-app-accent, $mif @include loans-view-component-theme($mifosx-app-theme); @include savings-account-view-component-theme($mifosx-app-theme); @include shares-account-view-component-theme($mifosx-app-theme); +@include fixed-deposits-account-view-component-theme($mifosx-app-theme); diff --git a/src/theme/custom/pictonblue-yellowgreen.scss b/src/theme/custom/pictonblue-yellowgreen.scss index 1934afb8a..5ebba0b37 100644 --- a/src/theme/custom/pictonblue-yellowgreen.scss +++ b/src/theme/custom/pictonblue-yellowgreen.scss @@ -7,6 +7,7 @@ @import '../../app/loans/loans-view/loans-view.component-theme.scss'; @import '../../app/savings/savings-account-view/savings-account-view.component-theme.scss'; @import '../../app/shares/shares-account-view/shares-account-view.component-theme.scss'; +@import '../../app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component-theme.scss'; // Custom material palette $mat-picton-blue: ( @@ -59,3 +60,4 @@ $mifosx-app-theme: mat-light-theme($mifosx-app-primary, $mifosx-app-accent, $mif @include loans-view-component-theme($mifosx-app-theme); @include savings-account-view-component-theme($mifosx-app-theme); @include shares-account-view-component-theme($mifosx-app-theme); +@include fixed-deposits-account-view-component-theme($mifosx-app-theme);