diff --git a/src/app/clients/clients-routing.module.ts b/src/app/clients/clients-routing.module.ts index 3e800ebc2..3a98e5198 100644 --- a/src/app/clients/clients-routing.module.ts +++ b/src/app/clients/clients-routing.module.ts @@ -181,6 +181,10 @@ const routes: Routes = [ path: 'savingsaccounts', loadChildren: '../savings/savings.module#SavingsModule' }, + { + path: 'recurringdeposits', + loadChildren: '../recurring-deposits/recurring-deposits.module#RecurringDepositsModule' + }, { path: 'sharesaccounts', loadChildren: '../shares/shares.module#SharesModule' 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 98ce7e5c5..8b62ab1aa 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 @@ -469,7 +469,7 @@ + [routerLink]="['../', 'recurringdeposits', row.id]"> @@ -494,8 +494,10 @@ - + +
diff --git a/src/app/recurring-deposits/common-resolvers/recurring-deposits-account-view.resolver.ts b/src/app/recurring-deposits/common-resolvers/recurring-deposits-account-view.resolver.ts new file mode 100644 index 000000000..b564eb244 --- /dev/null +++ b/src/app/recurring-deposits/common-resolvers/recurring-deposits-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 { RecurringDepositsService } from '../recurring-deposits.service'; + +/** + * RecurringDeposits Account data resolver. + */ +@Injectable() +export class RecurringDepositsAccountViewResolver implements Resolve { + + /** + * @param {RecurringDepositsService} RecurringDepositsService RecurringDeposits service. + */ + constructor(private recurringDepositsService: RecurringDepositsService) { } + + /** + * Returns the RecurringDeposits Account data. + * @param {ActivatedRouteSnapshot} route Route Snapshot + * @returns {Observable} + */ + resolve(route: ActivatedRouteSnapshot): Observable { + const recurringDepositAccountId = route.paramMap.get('recurringDepositAccountId'); + return this.recurringDepositsService.getRecurringDepositsAccountData(recurringDepositAccountId); + } + +} diff --git a/src/app/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component-theme.scss b/src/app/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component-theme.scss new file mode 100644 index 000000000..ec65550b6 --- /dev/null +++ b/src/app/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component-theme.scss @@ -0,0 +1,16 @@ +@import "~@angular/material/theming"; + +@mixin recurring-deposits-account-view-component-theme($theme) { + $primary: map-get($theme, primary); + mifosx-recurring-deposits-account-view { + .recurringDeposits-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/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component.html b/src/app/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component.html new file mode 100644 index 000000000..e32d72f1a --- /dev/null +++ b/src/app/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component.html @@ -0,0 +1,202 @@ + diff --git a/src/app/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component.scss b/src/app/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component.scss new file mode 100644 index 000000000..4c783d851 --- /dev/null +++ b/src/app/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component.scss @@ -0,0 +1,53 @@ +.recurringDeposits-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 { + .recurringDeposits-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/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component.spec.ts b/src/app/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component.spec.ts new file mode 100644 index 000000000..eaa6cacfe --- /dev/null +++ b/src/app/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RecurringDepositsAccountViewComponent } from './recurring-deposits-account-view.component'; + +describe('RecurringDepositsAccountViewComponent', () => { + let component: RecurringDepositsAccountViewComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ RecurringDepositsAccountViewComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(RecurringDepositsAccountViewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component.ts b/src/app/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component.ts new file mode 100644 index 000000000..17f7d3e16 --- /dev/null +++ b/src/app/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component.ts @@ -0,0 +1,72 @@ +/** Angular Imports */ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { MatDialog } from '@angular/material'; +import { DatePipe } from '@angular/common'; + +/** Custom Services */ +import { RecurringDepositsService } from '../recurring-deposits.service'; + +/** Custom Buttons Configuration */ +import { RecurringDepositsButtonsConfiguration } from './recurring-deposits-buttons.config'; + +/** + * RecurringDeposits Account View Component + */ +@Component({ + selector: 'mifosx-recurring-deposits-account-view', + templateUrl: './recurring-deposits-account-view.component.html', + styleUrls: ['./recurring-deposits-account-view.component.scss'] +}) +export class RecurringDepositsAccountViewComponent implements OnInit { + + /** RecurringDeposits Account Data */ + recurringDepositsAccountData: any; + buttonConfig: RecurringDepositsButtonsConfiguration; + charges: any; + + /** + * Fetches recurringDeposits account data from `resolve` + * @param {ActivatedRoute} route Activated Route + * @param {Router} router Router + * @param {RecurringDepositsService} recurringDepositsService RecurringDeposits Service + */ + constructor(private route: ActivatedRoute, + private router: Router, + private datePipe: DatePipe, + private recurringDepositsService: RecurringDepositsService, + public dialog: MatDialog) { + this.route.data.subscribe((data: { recurringDepositsAccountData: any }) => { + this.recurringDepositsAccountData = data.recurringDepositsAccountData; + this.charges = this.recurringDepositsAccountData.charges; + }); + } + + ngOnInit() { + this.setConditionalButtons(); + } + + /** + * Adds options to button config. conditionaly. + */ + setConditionalButtons() { + const status = this.recurringDepositsAccountData.status.value; + this.buttonConfig = new RecurringDepositsButtonsConfiguration(status); + if (this.recurringDepositsAccountData.clientId && this.recurringDepositsAccountData.status.value === 'Matured') { + this.buttonConfig.addOption({ + name: 'Transfer Funds', + }); + } + + if (this.recurringDepositsAccountData.charges && this.recurringDepositsAccountData.status.value === 'Matured') { + this.charges.forEach((element: any) => { + if (element.name === 'Annual fee - INR') { + this.buttonConfig.addOption({ + name: 'Apply Annual Fees', + }); + } + }); + } + } + +} diff --git a/src/app/recurring-deposits/recurring-deposits-account-view/recurring-deposits-buttons.config.ts b/src/app/recurring-deposits/recurring-deposits-account-view/recurring-deposits-buttons.config.ts new file mode 100644 index 000000000..423d412b6 --- /dev/null +++ b/src/app/recurring-deposits/recurring-deposits-account-view/recurring-deposits-buttons.config.ts @@ -0,0 +1,136 @@ +/** Recurring Deposits Account Buttons Configuration */ +export class RecurringDepositsButtonsConfiguration { + + optionArray: { + name: string, + taskPermissionName?: string, + }[]; + + buttonsArray: { + name: string, + icon: string, + taskPermissionName?: 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: 'Deposit', + icon: 'fa fa-arrow-up' + }, + { + name: 'Premature Close', + icon: 'fa fa-arrow-left' + }, + { + 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; + case 'Matured': + this.buttonsArray = [ + { + name: 'Close', + icon: 'fa fa-arrow-right' + }, + { + name: 'Calculate Interest', + icon: 'fa fa-table' + }, + { + name: 'Post Interest', + icon: 'fa fa-table' + } + ]; + break; + default: + this.buttonsArray = []; + } + } + + setOptions(status: string) { + switch (status) { + case 'Active': + 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 'Matured': + this.optionArray = [ + { + name: 'Add Charge' + } + ]; + break; + case 'Approved': + default: + this.optionArray = []; + } + } + + addOption(option: {name: string, taskPermissionName?: string}) { + this.optionArray.push(option); + } + +} diff --git a/src/app/recurring-deposits/recurring-deposits-routing.module.ts b/src/app/recurring-deposits/recurring-deposits-routing.module.ts new file mode 100644 index 000000000..c4b657beb --- /dev/null +++ b/src/app/recurring-deposits/recurring-deposits-routing.module.ts @@ -0,0 +1,38 @@ +/** Angular Imports */ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; + +/** Translation Imports */ +import { extract } from '../core/i18n/i18n.service'; + +/** Custom Components */ +import { RecurringDepositsAccountViewComponent } from './recurring-deposits-account-view/recurring-deposits-account-view.component'; + +/** Custom Resolvers */ +import { RecurringDepositsAccountViewResolver } from './common-resolvers/recurring-deposits-account-view.resolver'; + +const routes: Routes = [ + { + path: '', + data: { title: extract('All RecurringDeposits'), breadcrumb: 'RecurringDeposits', routeParamBreadcrumb: false }, + children: [ + { + path: ':recurringDepositAccountId', + data: { title: extract('RecurringDeposit Account View'), routeParamBreadcrumb: 'recurringDepositAccountId' }, + resolve: { + recurringDepositsAccountData: RecurringDepositsAccountViewResolver + }, + component: RecurringDepositsAccountViewComponent + } + ] + } +]; +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], + declarations: [], + providers: [ + RecurringDepositsAccountViewResolver, + ] +}) +export class RecurringDepositsRoutingModule {} diff --git a/src/app/recurring-deposits/recurring-deposits.module.spec.ts b/src/app/recurring-deposits/recurring-deposits.module.spec.ts new file mode 100644 index 000000000..5e980bf94 --- /dev/null +++ b/src/app/recurring-deposits/recurring-deposits.module.spec.ts @@ -0,0 +1,13 @@ +import { RecurringDepositsModule } from './recurring-deposits.module'; + +describe('RecurringDepositsModule', () => { + let recurringDepositsModule: RecurringDepositsModule; + + beforeEach(() => { + recurringDepositsModule = new RecurringDepositsModule(); + }); + + it('should create an instance', () => { + expect(recurringDepositsModule).toBeTruthy(); + }); +}); diff --git a/src/app/recurring-deposits/recurring-deposits.module.ts b/src/app/recurring-deposits/recurring-deposits.module.ts new file mode 100644 index 000000000..d572beadf --- /dev/null +++ b/src/app/recurring-deposits/recurring-deposits.module.ts @@ -0,0 +1,31 @@ +/** Angular Imports */ +import { NgModule } from '@angular/core'; +import { DatePipe } from '@angular/common'; + +/** Custom Modules */ +import { RecurringDepositsRoutingModule } from './recurring-deposits-routing.module'; +import { SharedModule } from 'app/shared/shared.module'; +import { PipesModule } from '../pipes/pipes.module'; +import { DirectivesModule } from '../directives/directives.module'; + +/** Custom Components */ +import { RecurringDepositsAccountViewComponent } from './recurring-deposits-account-view/recurring-deposits-account-view.component'; + +/** + * RecurringDeposits Module + * + * All components related to RecurringDeposits functions should be declared here. + */ +@NgModule({ + imports: [ + SharedModule, + PipesModule, + DirectivesModule, + RecurringDepositsRoutingModule + ], + declarations: [ + RecurringDepositsAccountViewComponent + ], + providers: [DatePipe] +}) +export class RecurringDepositsModule {} diff --git a/src/app/recurring-deposits/recurring-deposits.service.spec.ts b/src/app/recurring-deposits/recurring-deposits.service.spec.ts new file mode 100644 index 000000000..4746bf4a2 --- /dev/null +++ b/src/app/recurring-deposits/recurring-deposits.service.spec.ts @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { RecurringDepositsService } from './recurring-deposits.service'; + +describe('RecurringDepositsService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: RecurringDepositsService = TestBed.get(RecurringDepositsService); + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/recurring-deposits/recurring-deposits.service.ts b/src/app/recurring-deposits/recurring-deposits.service.ts new file mode 100644 index 000000000..8abe9e8d5 --- /dev/null +++ b/src/app/recurring-deposits/recurring-deposits.service.ts @@ -0,0 +1,32 @@ +/** Angular Imports */ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpParams } from '@angular/common/http'; + +/** rxjs Imports */ +import { Observable } from 'rxjs'; + +/** + * RecurringDeposits Service. + */ +@Injectable({ + providedIn: 'root' +}) +export class RecurringDepositsService { + + constructor(private http: HttpClient) {} + + /** + * @param {string} recurringDepositAccountId is recurringDeposit account's Id. + * @returns {Observable} + */ + // getRecurringDepositsTransactionTemplateResource(recurringDepositAccountId: string): Observable { + // return this.http.get(`/recurringDepositsaccounts/${recurringDepositAccountId}/transactions/template`); + // } + + getRecurringDepositsAccountData(recurringDepositAccountId: any) { + const httpParams = new HttpParams() + .set('associations', 'all'); + return this.http.get(`/recurringdepositaccounts/${recurringDepositAccountId}`, { params: httpParams }); + } + +} diff --git a/src/assets/images/recurring-deposits_account_placeholder.png b/src/assets/images/recurring-deposits_account_placeholder.png new file mode 100644 index 000000000..5bff577f9 Binary files /dev/null and b/src/assets/images/recurring-deposits_account_placeholder.png differ diff --git a/src/theme/custom/denim-yellowgreen.scss b/src/theme/custom/denim-yellowgreen.scss index 63a3739d9..d969d3fd3 100644 --- a/src/theme/custom/denim-yellowgreen.scss +++ b/src/theme/custom/denim-yellowgreen.scss @@ -8,6 +8,7 @@ @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'; +@import '../../app/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component-theme.scss'; // Custom material palette $mat-denim: ( @@ -61,3 +62,4 @@ $mifosx-app-theme: mat-light-theme($mifosx-app-primary, $mifosx-app-accent, $mif @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); +@include recurring-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 5ebba0b37..478e08001 100644 --- a/src/theme/custom/pictonblue-yellowgreen.scss +++ b/src/theme/custom/pictonblue-yellowgreen.scss @@ -8,6 +8,7 @@ @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'; +@import '../../app/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component-theme.scss'; // Custom material palette $mat-picton-blue: ( @@ -61,3 +62,4 @@ $mifosx-app-theme: mat-light-theme($mifosx-app-primary, $mifosx-app-accent, $mif @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); +@include recurring-deposits-account-view-component-theme($mifosx-app-theme);