diff --git a/src/app/groups/common-resolvers/glim-account-resolver.ts b/src/app/groups/common-resolvers/glim-account-resolver.ts new file mode 100644 index 000000000..d287cadfc --- /dev/null +++ b/src/app/groups/common-resolvers/glim-account-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 { GroupsService } from '../groups.service'; + +/** + * GLIM Loans Accounts data resolver. + */ +@Injectable() +export class GLIMAccountsResolver implements Resolve { + + /** + * @param {GroupsService} groupsService Groups service. + */ + constructor(private groupsService: GroupsService) { } + + /** + * Returns the Group's GLIM Loans Acccounts data. + * @param {ActivatedRouteSnapshot} route Route Snapshot. + * @returns {Observable} + */ + resolve(route: ActivatedRouteSnapshot): Observable { + const groupId = route.parent.paramMap.get('groupId'); + return this.groupsService.getGLIMAccountsData(groupId); + } + +} diff --git a/src/app/groups/common-resolvers/gsim-account-resolver.ts b/src/app/groups/common-resolvers/gsim-account-resolver.ts new file mode 100644 index 000000000..055736b19 --- /dev/null +++ b/src/app/groups/common-resolvers/gsim-account-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 { GroupsService } from '../groups.service'; + +/** + * GSIM Accounts data resolver. + */ +@Injectable() +export class GSIMAccountsResolver implements Resolve { + + /** + * @param {GroupsService} groupsService Groups service. + */ + constructor(private groupsService: GroupsService) { } + + /** + * Returns the Group's GSIM Acccounts data. + * @param {ActivatedRouteSnapshot} route Route Snapshot. + * @returns {Observable} + */ + resolve(route: ActivatedRouteSnapshot): Observable { + const groupId = route.parent.paramMap.get('groupId'); + return this.groupsService.getGSIMAccountsData(groupId); + } + +} diff --git a/src/app/groups/groups-routing.module.ts b/src/app/groups/groups-routing.module.ts index ef3410078..249f5df78 100644 --- a/src/app/groups/groups-routing.module.ts +++ b/src/app/groups/groups-routing.module.ts @@ -30,6 +30,8 @@ import { GroupDatatablesResolver } from './common-resolvers/group-datatables.res import { GroupDatatableResolver } from './common-resolvers/group-datatable.resolver'; import { GroupDataAndTemplateResolver } from './common-resolvers/group-data-and-template.resolver'; import { GroupActionsResolver } from './common-resolvers/group-actions.resolver'; +import { GLIMAccountsResolver } from './common-resolvers/glim-account-resolver'; +import { GSIMAccountsResolver } from './common-resolvers/gsim-account-resolver'; /** Groups Routes */ const routes: Routes = [ @@ -71,7 +73,9 @@ const routes: Routes = [ data: { title: extract('General'), breadcrumb: 'General', routeParamBreadcrumb: false }, resolve: { groupAccountsData: GroupAccountsResolver, - groupSummary: GroupSummaryResolver + groupSummary: GroupSummaryResolver, + gsimData: GSIMAccountsResolver, + glimData: GLIMAccountsResolver } }, { @@ -166,6 +170,8 @@ const routes: Routes = [ GroupDatatablesResolver, GroupDatatableResolver, GroupDataAndTemplateResolver, - GroupActionsResolver] + GroupActionsResolver, + GSIMAccountsResolver, + GLIMAccountsResolver] }) export class GroupsRoutingModule { } diff --git a/src/app/groups/groups-view/general-tab/general-tab.component.html b/src/app/groups/groups-view/general-tab/general-tab.component.html index 9a1c9a1b7..2089dc781 100644 --- a/src/app/groups/groups-view/general-tab/general-tab.component.html +++ b/src/app/groups/groups-view/general-tab/general-tab.component.html @@ -193,6 +193,96 @@ +
+ +
+
+

GSIM Account Overview

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
GSIM Id + {{element.gsimId}} Account Number {{element.accountNumber}} Product {{element.childGSIMAccounts[0].productName}} Balance {{element.parentBalance}} Status {{element.savingsStatus}}
+ +
+ +
+ +
+
+

GLIM Loans Account Overview

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
GLIM Id + {{element.glimId}} Account Number {{element.accountNumber}} Product {{element.childGLIMAccounts[0].productName}} Original Loan {{element.parentPrincipalAmount}} Status {{element.loanStatus}}
+ +
+
diff --git a/src/app/groups/groups-view/general-tab/general-tab.component.scss b/src/app/groups/groups-view/general-tab/general-tab.component.scss index 7624c1d93..0d3fc4c09 100644 --- a/src/app/groups/groups-view/general-tab/general-tab.component.scss +++ b/src/app/groups/groups-view/general-tab/general-tab.component.scss @@ -26,4 +26,7 @@ i:hover { cursor: pointer; } + tr:hover { + cursor: pointer; + } } diff --git a/src/app/groups/groups-view/general-tab/general-tab.component.ts b/src/app/groups/groups-view/general-tab/general-tab.component.ts index 0f23eb687..d4f5a38ac 100644 --- a/src/app/groups/groups-view/general-tab/general-tab.component.ts +++ b/src/app/groups/groups-view/general-tab/general-tab.component.ts @@ -18,6 +18,10 @@ export class GeneralTabComponent { loanAccounts: any; /** Group's savings accounts data */ savingAccounts: any; + /** GSIM Accounts */ + gsimAccounts: any; + /** GLIM Accounts */ + glimAccounts: any; /** Group Summary */ groupSummary: any; /** Group's Client Members */ @@ -32,6 +36,10 @@ export class GeneralTabComponent { openSavingsColumns: string[] = ['Account No', 'Saving Account', 'Last Active', 'Balance', 'Actions']; /** Columns to be displayed for closed accounts table */ closedSavingsColumns: string[] = ['Account No', 'Saving Account', 'Closed Date']; + /** Columns to be displayed for GSIM Accounts Table */ + gsimAccountsColumns: string[] = ['GSIM Id', 'Account Number', 'Product', 'Balance', 'Status']; + /** Columns to be displayed for GLIM Accounts Table */ + glimAccountsColumns: string[] = ['GLIM Id', 'Account Number', 'Product', 'Original Loan', 'Status']; /** Boolean for toggling loan accounts table */ showClosedLoanAccounts = false; /** Boolean for toggling savings accounts table */ @@ -42,7 +50,9 @@ export class GeneralTabComponent { * @param {ActivatedRoute} route Activated Route. */ constructor(private route: ActivatedRoute) { - this.route.data.subscribe((data: { groupAccountsData: any, groupClientMembers: any, groupSummary: any }) => { + this.route.data.subscribe((data: { groupAccountsData: any, groupClientMembers: any, groupSummary: any, glimData: any, gsimData: any }) => { + this.glimAccounts = data.glimData; + this.gsimAccounts = data.gsimData; this.groupAccountData = data.groupAccountsData; this.savingAccounts = data.groupAccountsData.savingsAccounts; this.loanAccounts = data.groupAccountsData.loanAccounts; diff --git a/src/app/groups/groups-view/groups-view.component.html b/src/app/groups/groups-view/groups-view.component.html index e99e04cc4..c03d6e45d 100644 --- a/src/app/groups/groups-view/groups-view.component.html +++ b/src/app/groups/groups-view/groups-view.component.html @@ -73,6 +73,8 @@ + + diff --git a/src/app/groups/groups.service.ts b/src/app/groups/groups.service.ts index 3ddf8c23c..67d6908f4 100644 --- a/src/app/groups/groups.service.ts +++ b/src/app/groups/groups.service.ts @@ -312,4 +312,20 @@ export class GroupsService { return this.http.get('/groups/template', { params: httpParams }); } + /** + * @param groupId Group Id of group to get data for. + * @returns {Observable} Group GLIM Accounts data. + */ + getGLIMAccountsData(groupId: string): Observable { + return this.http.get(`/groups/${groupId}/glimaccounts`); + } + + /** + * @param groupId Group Id of group to get data for. + * @returns {Observable} Group GSIM Accounts data. + */ + getGSIMAccountsData(groupId: string): Observable { + return this.http.get(`/groups/${groupId}/gsimaccounts`); + } + } diff --git a/src/app/loans/common-resolvers/glim-loan-template.resolver.ts b/src/app/loans/common-resolvers/glim-loan-template.resolver.ts new file mode 100644 index 000000000..e1855207a --- /dev/null +++ b/src/app/loans/common-resolvers/glim-loan-template.resolver.ts @@ -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'; + +/** + * GLIM Loan template data resolver. + */ +@Injectable() +export class GLIMLoanTemplateResolver implements Resolve { + /** + * @param {ProductsService} loansService Loan service. + */ + constructor(private loansService: LoansService) { } + + /** + * Returns the loan account template data. + * @returns {Observable} + */ + resolve(route: ActivatedRouteSnapshot): Observable { + const groupId = route.parent.parent.paramMap.get('groupId'); + return this.loansService.getGLIMLoanAccountTemplate(groupId); + } +} diff --git a/src/app/loans/glim-account/create-glim-account/create-glim-account.component.html b/src/app/loans/glim-account/create-glim-account/create-glim-account.component.html new file mode 100644 index 000000000..43c8b928d --- /dev/null +++ b/src/app/loans/glim-account/create-glim-account/create-glim-account.component.html @@ -0,0 +1,68 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + DETAILS + + + + + + + + + TERMS + + + + + + + + + CHARGES + + + + + + + + + PREVIEW + + + + + + + + +
diff --git a/src/app/loans/glim-account/create-glim-account/create-glim-account.component.scss b/src/app/loans/glim-account/create-glim-account/create-glim-account.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/loans/glim-account/create-glim-account/create-glim-account.component.spec.ts b/src/app/loans/glim-account/create-glim-account/create-glim-account.component.spec.ts new file mode 100644 index 000000000..e34f6e9df --- /dev/null +++ b/src/app/loans/glim-account/create-glim-account/create-glim-account.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateGlimAccountComponent } from './create-glim-account.component'; + +describe('CreateGlimAccountComponent', () => { + let component: CreateGlimAccountComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateGlimAccountComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateGlimAccountComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/loans/glim-account/create-glim-account/create-glim-account.component.ts b/src/app/loans/glim-account/create-glim-account/create-glim-account.component.ts new file mode 100644 index 000000000..f7c944ced --- /dev/null +++ b/src/app/loans/glim-account/create-glim-account/create-glim-account.component.ts @@ -0,0 +1,185 @@ +import { Component, OnInit, ViewChild } from '@angular/core'; +import { FormGroup, FormBuilder, Validators } from '@angular/forms'; +import { MatDialog } from '@angular/material/dialog'; +import { MatPaginator } from '@angular/material/paginator'; +import { MatTableDataSource } from '@angular/material/table'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Dates } from 'app/core/utils/dates'; +import { LoansService } from 'app/loans/loans.service'; +import { SettingsService } from 'app/settings/settings.service'; +import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component'; +import { DatepickerBase } from 'app/shared/form-dialog/formfield/model/datepicker-base'; +import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield-base'; +import { InputBase } from 'app/shared/form-dialog/formfield/model/input-base'; +import { GlimChargesStepComponent } from './glim-account-stepper/glim-charges-step/glim-charges-step.component'; +import { GlimDetailsStepComponent } from './glim-account-stepper/glim-details-step/glim-details-step.component'; +import { GlimTermsStepComponent } from './glim-account-stepper/glim-terms-step/glim-terms-step.component'; + +@Component({ + selector: 'mifosx-create-glim-account', + templateUrl: './create-glim-account.component.html', + styleUrls: ['./create-glim-account.component.scss'] +}) +export class CreateGlimAccountComponent implements OnInit { + + /** Imports all the step component */ + @ViewChild(GlimDetailsStepComponent, { static: true }) loansAccountDetailsStep: GlimDetailsStepComponent; + @ViewChild(GlimTermsStepComponent, { static: true }) loansAccountTermsStep: GlimTermsStepComponent; + @ViewChild(GlimChargesStepComponent, { static: true }) loansAccountChargesStep: GlimChargesStepComponent; + + /** Loans Account Template */ + loansAccountTemplate: any; + /** Loans Account Product Template */ + loansAccountProductTemplate: any; + /** Collateral Options */ + collateralOptions: any; + /** Multi Disburse Loan */ + multiDisburseLoan: any; + /** Principal Amount */ + principal: any; + + accountLinkingOptions: any; + + totalLoan: any; + + /** Table Data Source */ + dataSource: any; + /** Selected Members */ + selectedMembers: any; + /** Selected Members */ + activeClientMembers: any; + gsimData: any; + /** + * Sets loans account details form. + * @param {FormBuilder} formBuilder Form Builder. + * @param {LoansService} loansService Loans Service. + * @param {SettingsService} settingsService SettingsService + */ + constructor(private route: ActivatedRoute, + private router: Router, + private loansService: LoansService, + private settingsService: SettingsService, + public dialog: MatDialog, + private dateUtils: Dates) { + this.route.data.subscribe((data: {loansAccountTemplate: any, gsimData: any, groupsData: any}) => { + this.loansAccountTemplate = data.loansAccountTemplate; + this.activeClientMembers = data.groupsData.activeClientMembers; + this.gsimData = data.gsimData; + }); + } + + ngOnInit(): void { + } + + /** + * Sets loans account product template and collateral template + * @param {any} $event API response + */ + setTemplate($event: any) { + this.loansAccountProductTemplate = $event; + } + + /** 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 or not */ + get loansAccountFormValid() { + return ( + this.loansAccountDetailsForm.valid && + this.loansAccountTermsForm.valid + ); + } + + /** Gets principal Amount */ + get loanPrincipal() { + return this.loansAccountTermsStep.loansAccountTermsForm.value.principal; + } + + /** Retrieves Data of all forms except Currency to submit the data */ + get loansAccount() { + this.selectedMembers = this.loansAccountChargesStep.selectedClientMembers; + return { + ...this.loansAccountDetailsStep.loansAccountDetails, + ...this.loansAccountTermsStep.loansAccountTerms, + ...this.loansAccountChargesStep.loansAccountCharges, + }; + } + + + + setData(client: any): any { + const locale = this.settingsService.language.code; + const dateFormat = this.settingsService.dateFormat; + // const monthDayFormat = 'dd MMMM'; + const data = { + ...this.loansAccount, + charges: this.loansAccount.charges.map((charge: any) => ({ + chargeId: charge.id, + amount: charge.amount, + })), + clientId: client.id, + totalLoan: this.totalLoan, + loanType: 'glim', + amortizationType: 1, + isParentAccount: true, + principal: client.principal, + syncDisbursementWithMeeting: false, + expectedDisbursementDate: this.dateUtils.formatDate(this.loansAccount.expectedDisbursementDate, dateFormat), + submittedOnDate: this.dateUtils.formatDate(this.loansAccount.submittedOnDate, dateFormat), + dateFormat, + // monthDayFormat, + locale + }; + data.groupId = this.loansAccountTemplate.group.id; + + return JSON.stringify(data); + + } + + /** Request Body Data */ + buildRequestData(): any[] { + const requestData = []; + const memberSelected = this.selectedMembers.selectedMembers; + this.totalLoanAmount(); + for (let index = 0; index < memberSelected.length; index++) { + console.log(memberSelected); + requestData.push({ + requestId: index.toString(), + method : 'POST', + relativeUrl: 'loans', + body : this.setData( memberSelected[ index ] ) + } + ); + } + return requestData; + } + + totalLoanAmount(): any { + let total = 0; + const memberSelected = this.selectedMembers.selectedMembers; + for (let index = 0; index < memberSelected.length; index++) { + total += memberSelected[index].principal; + } + console.log(total); + this.totalLoan = total; + } + + /** + * Creates a new GSIM account. + */ + submit() { + const data = this.buildRequestData(); + console.log(data); + this.loansService.createGlimAccount(data).subscribe((response: any) => { + this.router.navigate(['../../../'], { relativeTo: this.route }); + }); + } + +} diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.html b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.html new file mode 100644 index 000000000..6b6b4015f --- /dev/null +++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.html @@ -0,0 +1,170 @@ +
+ + + Charge + + + {{ charge.name }} + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name + {{ charge.name + ', ' + charge.currency.displaySymbol }} + Type + {{ charge.chargeCalculationType.value }} + Amount + {{ charge.amount }} + + Collected On + {{ charge.chargeTimeType.value }} + Date + + {{(charge.dueDate | dateFormat) || 'Unassigned'}} + + + {{(charge.feeOnMonthDay | dateFormat) || 'Unassigned'}} + + + N/A + + + Repayments Every + {{ charge.feeInterval || 'Not Provided' }} + + Actions + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Client ID {{element.id}} Client Name {{element.displayName}} Loan Purpose + + Select Purpose + + + {{ purpose.name }} + + + + Original Loan + + + +
+
+ + +
+ +
+ + +
+ \ No newline at end of file diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.scss b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.spec.ts b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.spec.ts new file mode 100644 index 000000000..0cc2e5fad --- /dev/null +++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GlimChargesStepComponent } from './glim-charges-step.component'; + +describe('GlimChargesStepComponent', () => { + let component: GlimChargesStepComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ GlimChargesStepComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GlimChargesStepComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.ts b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.ts new file mode 100644 index 000000000..16a579927 --- /dev/null +++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component.ts @@ -0,0 +1,207 @@ +import { Component, Input, OnInit, OnChanges } from '@angular/core'; +import { FormControl } from '@angular/forms'; +import { MatDialog } from '@angular/material/dialog'; +import { MatTableDataSource } from '@angular/material/table'; +import { Dates } from 'app/core/utils/dates'; +import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component'; +import { DatepickerBase } from 'app/shared/form-dialog/formfield/model/datepicker-base'; +import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield-base'; +import { InputBase } from 'app/shared/form-dialog/formfield/model/input-base'; + +@Component({ + selector: 'mifosx-glim-charges-step', + templateUrl: './glim-charges-step.component.html', + styleUrls: ['./glim-charges-step.component.scss'] +}) +export class GlimChargesStepComponent implements OnInit, OnChanges { + + /** Savings Account Product Template */ + @Input() loansAccountProductTemplate: any; + /** Savings Account Template */ + @Input() loansAccountTemplate: any; + /** Currency Code */ + // @Input() currencyCode: FormControl; + // /** active Client Members in case of GLIM Account */ + @Input() activeClientMembers?: any; + + /** Charge Data */ + chargeData: any = []; + /** Charges Data Source */ + chargesDataSource: {}[] = []; + /** Component is pristine if there has been no changes by user interaction */ + pristine = true; + /** For Edit Savings Account Form */ + isChargesPatched = false; + /** Display columns for charges table */ + displayedColumns: string[] = ['name', 'chargeCalculationType', 'amount', 'chargeTimeType', 'date', 'repaymentsEvery', 'action']; + /** Table Data Source */ + dataSource: any; + /** Check for select all the Clients List */ + selectAllItems = false; + /** Loan Purpose Options */ + loanPurposeOptions: string[] = []; + /** Table Displayed Columns */ + displayedColumn: string[] = ['check', 'id', 'name', 'purpose', 'amount']; + + /** + * @param {MatDialog} dialog Mat Dialog + */ + constructor(public dialog: MatDialog, + private dateUtils: Dates) {} + + ngOnInit() { + this.dataSource = new MatTableDataSource(this.activeClientMembers); + } + + ngOnChanges() { + if (this.loansAccountProductTemplate) { + this.chargeData = this.loansAccountProductTemplate.chargeOptions; + } + } + + /** + * Adds the charge to charges table + * @param {any} charge Charge + */ + addCharge(charge: any) { + this.chargesDataSource = this.chargesDataSource.concat([charge.value]); + charge.value = ''; + this.pristine = false; + } + + /** + * Edits the Charge Amount + * @param {any} charge Charge + */ + editChargeAmount(charge: any) { + const formfields: FormfieldBase[] = [ + new InputBase({ + controlName: 'amount', + label: 'Amount', + value: charge.amount, + type: 'number', + required: false + }), + ]; + const data = { + title: 'Edit Charge Amount', + layout: { addButtonText: 'Confirm' }, + formfields: formfields + }; + const editNoteDialogRef = this.dialog.open(FormDialogComponent, { data }); + editNoteDialogRef.afterClosed().subscribe((response: any) => { + if (response.data) { + const newCharge = { ...charge, amount: response.data.value.amount }; + this.chargesDataSource.splice(this.chargesDataSource.indexOf(charge), 1, newCharge); + this.chargesDataSource = this.chargesDataSource.concat([]); + } + }); + this.pristine = false; + } + + /** + * Edits the Charge Date + * @param {any} charge Charge + */ + editChargeDate(charge: any) { + const formfields: FormfieldBase[] = [ + new DatepickerBase({ + controlName: 'date', + label: 'Date', + value: charge.dueDate || charge.feeOnMonthDay || '', + type: 'datetime-local', + required: false + }), + ]; + const data = { + title: 'Edit Charge Date', + layout: { addButtonText: 'Confirm' }, + formfields: formfields + }; + const editNoteDialogRef = this.dialog.open(FormDialogComponent, { data }); + editNoteDialogRef.afterClosed().subscribe((response: any) => { + if (response.data) { + let newCharge: any; + const dateFormat = 'dd MMMM yyyy'; + const date = this.dateUtils.formatDate(response.data.value.date, dateFormat); + switch (charge.chargeTimeType.value) { + case 'Specified due date': + case 'Weekly Fee': + newCharge = { ...charge, dueDate: date }; + break; + case 'Annual Fee': + newCharge = { ...charge, feeOnMonthDay: date }; + break; + } + this.chargesDataSource.splice(this.chargesDataSource.indexOf(charge), 1, newCharge); + this.chargesDataSource = this.chargesDataSource.concat([]); + } + }); + this.pristine = false; + } + + /** + * Edits the Charge Fee Interval + * @param {any} charge Charge + */ + editChargeFeeInterval(charge: any) { + const formfields: FormfieldBase[] = [ + new InputBase({ + controlName: 'feeInterval', + label: 'Fee Interval', + value: charge.feeInterval, + type: 'text', + required: false + }), + ]; + const data = { + title: 'Edit Charge Fee Interval', + layout: { addButtonText: 'Confirm' }, + formfields: formfields + }; + const editNoteDialogRef = this.dialog.open(FormDialogComponent, { data }); + editNoteDialogRef.afterClosed().subscribe((response: any) => { + if (response.data) { + const newCharge = { ...charge, feeInterval: response.data.value.feeInterval }; + this.chargesDataSource.splice(this.chargesDataSource.indexOf(charge), 1, newCharge); + this.chargesDataSource = this.chargesDataSource.concat([]); + } + }); + this.pristine = false; + } + + /** + * Removes the charge from charges table + * @param {any} charge Charge + */ + deleteCharge(charge: any) { + this.chargesDataSource.splice(this.chargesDataSource.indexOf(charge), 1); + this.chargesDataSource = this.chargesDataSource.concat([]); + this.pristine = false; + } + + /** + * Returns loan account charges + */ + get loansAccountCharges() { + return { charges: this.chargesDataSource }; + } + + get selectedClientMembers() { + return { selectedMembers: this.activeClientMembers.filter( (item: any) => item.selected ) }; + } + + /** Toggle all checks */ + toggleSelects() { + for (const member of this.activeClientMembers) { + member.selected = this.selectAllItems; + } + } + + /** Check if all the checks are selected */ + toggleSelect() { + const len = this.activeClientMembers.length; + this.selectAllItems = len === 0 ? false : this.activeClientMembers.filter( (item: any) => item.selected ).length === len; + } + +} diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.html b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.html new file mode 100644 index 000000000..f90328ba3 --- /dev/null +++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.html @@ -0,0 +1,89 @@ +
+ +
+ + + Product Name + + + {{ product.name }} + + + + Product Name is required + + + + + Loan officer + + + {{ loanOfficer.displayName }} + + + + + + + Fund + + + {{ fund.name }} + + + + + + Submitted on + + + + + Submitted on is required + + + + + Disbursement on + + + + + Disbursement on is required + + + + + + + +

Savings Linkage

+ + + Link savings + + + {{ savingaccount.accountNumber }} + + + + + + +
+ +
+ + +
+ +
+ \ No newline at end of file diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.scss b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.spec.ts b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.spec.ts new file mode 100644 index 000000000..c486517e4 --- /dev/null +++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GlimDetailsStepComponent } from './glim-details-step.component'; + +describe('GlimDetailsStepComponent', () => { + let component: GlimDetailsStepComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ GlimDetailsStepComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GlimDetailsStepComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.ts b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.ts new file mode 100644 index 000000000..420e26b82 --- /dev/null +++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component.ts @@ -0,0 +1,104 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { LoansService } from 'app/loans/loans.service'; +import { SettingsService } from 'app/settings/settings.service'; + +@Component({ + selector: 'mifosx-glim-details-step', + templateUrl: './glim-details-step.component.html', + styleUrls: ['./glim-details-step.component.scss'] +}) +export class GlimDetailsStepComponent implements OnInit { + /** Loans Account Template */ + @Input() loansAccountTemplate: any; + @Input() gsimData: any; + /** Minimum date allowed. */ + minDate = new Date(2000, 0, 1); + /** Maximum date allowed. */ + maxDate = new Date(2100, 0, 1); + /** Product Data */ + productData: any; + /** Loan Officer Data */ + loanOfficerOptions: any; + /** Loan Purpose Options */ + loanPurposeOptions: any; + /** Fund Options */ + fundOptions: any; + /** Account Linking Options */ + accountLinkingOptions: any; + /** For edit loan accounts form */ + isFieldOfficerPatched = false; + /** Loans Account Details Form */ + loansAccountDetailsForm: FormGroup; + + /** Loans Account Template with product data */ + @Output() loansAccountProductTemplate = new EventEmitter(); + /** + * Sets loans account details form. + * @param {FormBuilder} formBuilder Form Builder. + * @param {LoansService} loansService Loans Service. + * @param {SettingsService} settingsService SettingsService + */ + constructor(private formBuilder: FormBuilder, + private loansService: LoansService, + private settingsService: SettingsService) { + this.createLoansAccountDetailsForm(); + } + + ngOnInit(): void { + this.maxDate = this.settingsService.businessDate; + this.buildDependencies(); + if (this.loansAccountTemplate) { + this.productData = this.loansAccountTemplate.productOptions; + if (this.loansAccountTemplate.loanProductId) { + 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 + }); + } + } + } + + /** + * Creates glim account details form. + */ + createLoansAccountDetailsForm() { + this.loansAccountDetailsForm = this.formBuilder.group({ + 'productId': ['', Validators.required], + 'loanOfficerId': [''], + 'fundId': [''], + 'submittedOnDate': [new Date(), Validators.required], + 'expectedDisbursementDate': ['', Validators.required], + 'linkAccountId': [''], + }); + } + + /** + * Fetches loans account product template on productId value changes + */ + buildDependencies() { + const groupId = this.loansAccountTemplate.group.id; + this.loansAccountDetailsForm.get('productId').valueChanges.subscribe((productId: string) => { + this.loansService.getLoansAccountTemplateResource(groupId, true, productId).subscribe((response: any) => { + this.loansAccountProductTemplate.emit(response); + this.loanOfficerOptions = response.loanOfficerOptions; + this.loanPurposeOptions = response.loanPurposeOptions; + this.fundOptions = response.fundOptions; + this.accountLinkingOptions = response.accountLinkingOptions; + }); + }); + } + + /** + * Returns loans account details form value. + */ + get loansAccountDetails() { + return this.loansAccountDetailsForm.value; + } + +} diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.html b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.html new file mode 100644 index 000000000..7039f58ef --- /dev/null +++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.html @@ -0,0 +1,274 @@ +
+ +

Details

+ + + +
+ Product: + {{ loansAccount.productId | find:loansAccountTemplate.productOptions:'id':'name' }} +
+ +
+ Loan officer: + {{ loansAccount.loanOfficerId | find:loansAccountProductTemplate.loanOfficerOptions:'id':'displayName'}} +
+ +
+ Loan purpose: + {{ loansAccount.loanPurposeId | find:loansAccountProductTemplate.loanPurposeOptions:'id':'name'}} +
+ +
+ Fund: + {{ loansAccount.fundId | find:loansAccountProductTemplate.fundOptions:'id':'name'}} +
+ +
+ Submitted on: + {{ loansAccount.submittedOnDate | dateFormat }} +
+ +
+ Disbursement on: + {{ loansAccount.expectedDisbursementDate | dateFormat }} +
+ +
+ External id: + {{ loansAccount.externalId }} +
+ +

Terms

+ + + +
+ Principal: + {{ loansAccount.principal }} {{loansAccountProductTemplate.currency.DisplaySymbol}} +
+ +
+ Loan term: + {{ loansAccount.loanTermFrequency }} + {{loansAccount.loanTermFrequencyType | find: loansAccountProductTemplate.termFrequencyTypeOptions:'id':'name'}} +
+ +
+ Number of repayments: + {{ loansAccount.numberOfRepayments }} +
+ +
+ Repaid every: + {{loansAccount.repaymentEvery}} + {{loansAccount.repaymentFrequencyType | find: loansAccountProductTemplate.termFrequencyTypeOptions:'id':'name'}} + {{loansAccount.repaymentFrequencyNthDayType | find: loansAccountProductTemplate.repaymentFrequencyNthDayTypeOptions:'id': 'name'}} + {{loansAccount.repaymentFrequencyDayOfWeekType | find: loansAccountProductTemplate.repaymentFrequencyDaysOfWeekTypeOptions:'id': 'name'}} +
+ +
+ First repayment on: + {{ loansAccount.repaymentsStartingFromDate | dateFormat }} +
+ +
+ Interest charged from: + {{ loansAccount.interestChargedFromDate | dateFormat }} +
+ +
+ Nominal interest rate: + {{loansAccount.interestRatePerPeriod}}  {{loansAccountProductTemplate.interestRateFrequencyType.value}} +
+ +
+ Interest method: + {{loansAccount.interestType}} +
+ +
+ Is Equal Amortization: + {{loansAccount.isEqualAmortization}} +
+ +
+ Amortization + {{ loansAccount.amortizationType | find:loansAccountProductTemplate.amortizationTypeOptions:'id':'value' }} +
+ +
+ Interest calculation period: + {{ loansAccount.interestCalculationPeriodType | find:loansAccountProductTemplate.interestCalculationPeriodTypeOptions:'id':'value' }} +
+ +
+ Calculate interest for exact days in partial period: + {{ loansAccount.allowPartialPeriodInterestCalcualtion }} +
+ +
+ Arrears tolerance: + {{loansAccount.inArrearsTolerance}} {{loansAccountProductTemplate.currency.displaySymbol}} +
+ +
+ Interest free period: + {{ loansAccount.graceOnInterestCharged }} +
+ +
+ Repayment strategy: + {{ loansAccount.transactionProcessingStrategyId | find:loansAccountTemplate.transactionProcessingStrategyOptions:'id':'name' }} +
+ +

Moratorium

+ + + +
+ On principal payment: + {{ loansAccount.graceOnPrincipalPayment }} +
+ +
+ On interest payment: + {{ loansAccount.graceOnInterestPayment }} +
+ +
+ On Arrears Aging: + {{ loansAccount.graceOnArrearsAgeing }} +
+ +
+ Is Topup Loan? + {{ loansAccount.isTopup }} +
+ +
+ Recalculate Interest: + {{ loansAccountProductTemplate?.isInterestRecalculationEnabled? 'Yes' : 'No' }} +
+ +
+ Days in month: + {{ loansAccountProductTemplate?.daysInMonthType.value }} +
+ +
+ +

Charges

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name + {{ charge.name + ', ' + charge.currency.displaySymbol }} + Type + {{ charge.chargeCalculationType.value }} + Amount + {{ charge.amount }} + Collected On + {{ charge.chargeTimeType.value }} + Date + + {{(charge.dueDate | dateFormat) || 'Unassigned'}} + + + {{(charge.feeOnMonthDay | dateFormat) || 'Unassigned'}} + + + N/A + +
+ +
+ +
+ +

Overdue Charges

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name {{ charge.name }},{{ charge.currency.displaySymbol }} Type {{ charge.chargeCalculationType.value }} Amount {{ charge.amount| number }} Collected On {{ charge.chargeTimeType.value }}
+
+ +
+ +
+ + + +
+ \ No newline at end of file diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.scss b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.spec.ts b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.spec.ts new file mode 100644 index 000000000..c052ee2c0 --- /dev/null +++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GlimPreviewStepComponent } from './glim-preview-step.component'; + +describe('GlimPreviewStepComponent', () => { + let component: GlimPreviewStepComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ GlimPreviewStepComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GlimPreviewStepComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.ts b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.ts new file mode 100644 index 000000000..85634dc8c --- /dev/null +++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component.ts @@ -0,0 +1,30 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; + +@Component({ + selector: 'mifosx-glim-preview-step', + templateUrl: './glim-preview-step.component.html', + styleUrls: ['./glim-preview-step.component.scss'] +}) +export class GlimPreviewStepComponent implements OnInit { + + + /** Loans Account Template */ + @Input() loansAccountTemplate: any; + /** Loans Account Product Template */ + @Input() loansAccountProductTemplate: any; + /** Loans Account Data */ + @Input() loansAccount: any; + /** Submit Loans Account */ + @Output() submit = new EventEmitter(); + + /** Charges Displayed Columns */ + chargesDisplayedColumns: string[] = ['name', 'chargeCalculationType', 'amount', 'chargeTimeType', 'date']; + /** Overdue Charges Displayed Columns */ + overdueChargesDisplayedColumns: string[] = ['name', 'type', 'amount', 'collectedon']; + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.html b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.html new file mode 100644 index 000000000..6c6ce6bb9 --- /dev/null +++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.html @@ -0,0 +1,129 @@ +
+ +
+ +

Term Options

+ + + Loan Term + + + Loan Term is required + + + + + Frequency + + + {{ type.value }} + + + + Frequency is required + + + + + Number of repayments + + + Number of repayments is required + + + + + First repayment on + + + + + +

Repaid Every

+ + + Repaid every + + + Repaid every is required + + + + + Frequency + + + {{ repaymentFrequencyType.value }} + + + + + + Select On + + + {{ repaymentFrequencyNthDayType.value }} + + + + + + Select Day + + + {{ repaymentFrequencyDayOfWeekType.value }} + + + + + + Interest charged from + + + + + + + + + Nominal interest rate + + + + + Interest method + + + {{ interestType.value }} + + + + + + + + +
+
+ + +
+ +
diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.scss b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.spec.ts b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.spec.ts new file mode 100644 index 000000000..b9829eb90 --- /dev/null +++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GlimTermsStepComponent } from './glim-terms-step.component'; + +describe('GlimTermsStepComponent', () => { + let component: GlimTermsStepComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ GlimTermsStepComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GlimTermsStepComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.ts b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.ts new file mode 100644 index 000000000..6abc058d2 --- /dev/null +++ b/src/app/loans/glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component.ts @@ -0,0 +1,145 @@ +import { Component, Input, OnInit, OnChanges } from '@angular/core'; +import { FormGroup, FormBuilder, Validators, FormArray } from '@angular/forms'; +import { SettingsService } from 'app/settings/settings.service'; + +@Component({ + selector: 'mifosx-glim-terms-step', + templateUrl: './glim-terms-step.component.html', + styleUrls: ['./glim-terms-step.component.scss'] +}) +export class GlimTermsStepComponent implements OnInit, OnChanges { + + /** Loans Account Product Template */ + @Input() loansAccountProductTemplate: any; + /** Loans Account Template */ + @Input() loansAccountTemplate: any; + + /** Minimum date allowed. */ + minDate = new Date(2000, 0, 1); + /** Maximum date allowed. */ + maxDate = new Date(2100, 0, 1); + /** Loans Account Terms Form */ + loansAccountTermsForm: FormGroup; + /** Term Frequency Type Data */ + termFrequencyTypeData: any; + /** Repayment Frequency Nth Day Type Data */ + repaymentFrequencyNthDayTypeData: any; + /** Repayment Frequency Days of Week Type Data */ + repaymentFrequencyDaysOfWeekTypeData: any; + /** Interest Type Data */ + interestTypeData: any; + /** Amortization Type Data */ + amortizationTypeData: any; + /** Interest Calculation Period Type Data */ + interestCalculationPeriodTypeData: any; + /** Transaction Processing Strategy Data */ + transactionProcessingStrategyData: any; + /** Client Active Loan Data */ + clientActiveLoanData: any; + + /** + * Create Loans Account Terms Form + * @param formBuilder FormBuilder + * @param {SettingsService} settingsService SettingsService + */ + constructor(private formBuilder: FormBuilder, + private settingsService: SettingsService) { + this.createloansAccountTermsForm(); + } + /** + * Executes on change of input values + */ + ngOnChanges() { + if (this.loansAccountProductTemplate) { + this.loansAccountTermsForm.patchValue({ + 'principal': this.loansAccountProductTemplate.principal, + 'loanTermFrequency': this.loansAccountProductTemplate.termFrequency, + 'loanTermFrequencyType': this.loansAccountProductTemplate.termPeriodFrequencyType.id, + 'numberOfRepayments': this.loansAccountProductTemplate.numberOfRepayments, + 'repaymentEvery': this.loansAccountProductTemplate.repaymentEvery, + 'repaymentFrequencyType': this.loansAccountProductTemplate.repaymentFrequencyType.id, + 'interestRatePerPeriod': this.loansAccountProductTemplate.interestRatePerPeriod, + 'interestType': this.loansAccountProductTemplate.interestType.id, + 'interestCalculationPeriodType': this.loansAccountProductTemplate.interestCalculationPeriodType.id, + 'transactionProcessingStrategyId': this.loansAccountProductTemplate.transactionProcessingStrategyId, + }); + this.setOptions(); + } + } + + ngOnInit() { + this.maxDate = this.settingsService.businessDate; + if (this.loansAccountTemplate) { + if (this.loansAccountTemplate.loanProductId) { + this.loansAccountTermsForm.patchValue({ + 'repaymentsStartingFromDate': this.loansAccountTemplate.expectedFirstRepaymentOnDate && new Date(this.loansAccountTemplate.expectedFirstRepaymentOnDate) + }); + } + } + this.createloansAccountTermsForm(); + this.setCustomValidators(); + } + + /** Custom Validators for the form */ + setCustomValidators() { + const repaymentFrequencyNthDayType = this.loansAccountTermsForm.get('repaymentFrequencyNthDayType'); + const repaymentFrequencyDayOfWeekType = this.loansAccountTermsForm.get('repaymentFrequencyDayOfWeekType'); + + this.loansAccountTermsForm.get('repaymentFrequencyType').valueChanges + .subscribe(repaymentFrequencyType => { + + if (repaymentFrequencyType === 2) { + repaymentFrequencyNthDayType.setValidators([Validators.required]); + repaymentFrequencyDayOfWeekType.setValidators([Validators.required]); + } else { + repaymentFrequencyNthDayType.setValidators(null); + repaymentFrequencyDayOfWeekType.setValidators(null); + } + + repaymentFrequencyNthDayType.updateValueAndValidity(); + repaymentFrequencyDayOfWeekType.updateValueAndValidity(); + }); + } + + /** Create Loans Account Terms Form */ + createloansAccountTermsForm() { + this.loansAccountTermsForm = this.formBuilder.group({ + 'principal': ['', Validators.required], + 'loanTermFrequency': ['', Validators.required], + 'loanTermFrequencyType': ['', Validators.required], + 'numberOfRepayments': ['', Validators.required], + 'repaymentEvery': ['', Validators.required], + 'repaymentFrequencyType': ['', Validators.required], + 'repaymentFrequencyNthDayType': [''], + 'repaymentFrequencyDayOfWeekType': [''], + 'repaymentsStartingFromDate': [''], + 'interestChargedFromDate': [''], + 'interestRatePerPeriod': [''], + 'interestType': [''], + 'interestCalculationPeriodType': [''], + 'transactionProcessingStrategyId': [''] + }); + } + + /** + * Sets all select dropdown options. + */ + setOptions() { + this.termFrequencyTypeData = this.loansAccountProductTemplate.termFrequencyTypeOptions; + this.repaymentFrequencyNthDayTypeData = this.loansAccountProductTemplate.repaymentFrequencyNthDayTypeOptions; + this.repaymentFrequencyDaysOfWeekTypeData = this.loansAccountProductTemplate.repaymentFrequencyDaysOfWeekTypeOptions; + this.interestTypeData = this.loansAccountProductTemplate.interestTypeOptions; + this.amortizationTypeData = this.loansAccountProductTemplate.amortizationTypeOptions; + this.interestCalculationPeriodTypeData = this.loansAccountProductTemplate.interestCalculationPeriodTypeOptions; + this.transactionProcessingStrategyData = this.loansAccountProductTemplate.transactionProcessingStrategyOptions; + this.clientActiveLoanData = this.loansAccountProductTemplate.clientActiveLoanOptions; + } + + /** + * Returns loans account terms form value. + */ + get loansAccountTerms() { + return this.loansAccountTermsForm.value; + } + +} diff --git a/src/app/loans/glim-account/glim-account-view.resolver.ts b/src/app/loans/glim-account/glim-account-view.resolver.ts new file mode 100644 index 000000000..10268e56a --- /dev/null +++ b/src/app/loans/glim-account/glim-account-view.resolver.ts @@ -0,0 +1,33 @@ +/** 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'; + +/** + * GLIM Account data resolver. + */ +@Injectable() +export class GLIMViewResolver implements Resolve { + + /** + * @param {LoansService} loansService Loans service. + */ + constructor(private loansService: LoansService) { } + + /** + * Returns the Savings Account data. + * @param {ActivatedRouteSnapshot} route Route Snapshot + * @returns {Observable} + */ + resolve(route: ActivatedRouteSnapshot): Observable { + const groupId = route.paramMap.get('groupId'); + const glimId = route.paramMap.get('glimId'); + return this.loansService.getGLIMAccountData(glimId, groupId); + } + +} diff --git a/src/app/loans/glim-account/glim-account.component.html b/src/app/loans/glim-account/glim-account.component.html new file mode 100644 index 000000000..9a5ce69cb --- /dev/null +++ b/src/app/loans/glim-account/glim-account.component.html @@ -0,0 +1,46 @@ +
+ +
+ +

GLIM Account Overview

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Loan Id + {{element.childLoanId}} Client ID {{element.clientId}} Client Name{{element.clientName}} Loan Account Number {{element.childLoanAccountNo}} Client Principal Loan {{element.childPrincipalAmount}} Group Principal Loan {{element.parentPrincipalAmount}}
+ + +
diff --git a/src/app/loans/glim-account/glim-account.component.scss b/src/app/loans/glim-account/glim-account.component.scss new file mode 100644 index 000000000..8fd9a5c15 --- /dev/null +++ b/src/app/loans/glim-account/glim-account.component.scss @@ -0,0 +1,33 @@ +.tab-container { + padding: 1%; + margin: 1%; + h3 { + margin:1% auto; + } + .group-details-container { + border: 1px solid; + padding: 1%; + } + .action-button{ + margin-left: auto; + } + table { + width: 100%; + .account-action-button{ + min-width: 26px; + padding: 0 6px; + margin: 4px; + line-height: 25px; + } + tr.select-row:hover { + cursor: pointer; + } + } + i:hover { + cursor: pointer; + } + tr:hover { + cursor: pointer; + } + } + \ No newline at end of file diff --git a/src/app/loans/glim-account/glim-account.component.spec.ts b/src/app/loans/glim-account/glim-account.component.spec.ts new file mode 100644 index 000000000..584889228 --- /dev/null +++ b/src/app/loans/glim-account/glim-account.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GlimAccountComponent } from './glim-account.component'; + +describe('GlimAccountComponent', () => { + let component: GlimAccountComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ GlimAccountComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GlimAccountComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/loans/glim-account/glim-account.component.ts b/src/app/loans/glim-account/glim-account.component.ts new file mode 100644 index 000000000..b82af0583 --- /dev/null +++ b/src/app/loans/glim-account/glim-account.component.ts @@ -0,0 +1,49 @@ +import { Component, OnInit, ViewChild } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { MatPaginator } from '@angular/material/paginator'; +import { MatTableDataSource } from '@angular/material/table'; +import { ActivatedRoute } from '@angular/router'; + +/** + * GSIM Accounts Overview component. + */ +@Component({ + selector: 'mifosx-glim-account', + templateUrl: './glim-account.component.html', + styleUrls: ['./glim-account.component.scss'] +}) +export class GlimAccountComponent implements OnInit { + + /** Columns to be displayed in GLIM overview table. */ + displayedColumns: string[] = ['loanId', 'clientId', 'clientName', 'loanAccountNumber', 'clientPrincipalLoan', 'groupPrincipalLoan']; + /** Data source for charge overview table. */ + dataSource: MatTableDataSource; + /** Charge Overview data */ + glimOverviewData: any; + + /** Paginator for charge overview table. */ + @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator; + + /** + * Retrieves the charge overview data from `resolve`. + * @param {ActivatedRoute} route Activated Route. + * @param {MatDialog} dialog Dialog reference. + */ + constructor(private route: ActivatedRoute, + public dialog: MatDialog) { + this.route.data.subscribe((data: { glimData: any }) => { + this.glimOverviewData = data.glimData; + }); + } + + ngOnInit(): void { + this.setLoanClientChargeOverview(); + } + + /** + * Set GLIM Overview. + */ + setLoanClientChargeOverview() { + this.dataSource = new MatTableDataSource(this.glimOverviewData); + } +} diff --git a/src/app/loans/loans-routing.module.ts b/src/app/loans/loans-routing.module.ts index 097d0220b..9836db919 100644 --- a/src/app/loans/loans-routing.module.ts +++ b/src/app/loans/loans-routing.module.ts @@ -29,6 +29,8 @@ import { ViewTransactionComponent } from './loans-view/transactions/view-transac import { EditTransactionComponent } from './loans-view/transactions/edit-transaction/edit-transaction.component'; import { ViewRecieptComponent } from './loans-view/transactions/view-reciept/view-reciept.component'; import { ExportTransactionsComponent } from './loans-view/transactions/export-transactions/export-transactions.component'; +import { GlimAccountComponent } from './glim-account/glim-account.component'; +import { CreateGlimAccountComponent } from './glim-account/create-glim-account/create-glim-account.component'; /** Custom Resolvers */ import { LoanDetailsResolver } from './common-resolvers/loan-details.resolver'; @@ -43,6 +45,12 @@ import { LoansAccountChargeResolver } from './common-resolvers/loans-account-cha import { LoansAccountTransactionResolver } from './common-resolvers/loans-account-transaction.resolver'; import { LoansTransactionRecieptResolver } from './common-resolvers/loans-transaction-reciept.resolver'; import { LoansAccountTransactionTemplateResolver } from './common-resolvers/loans-account-transaction-template.resolver'; +import { SavingsAccountViewResolver } from 'app/savings/common-resolvers/savings-account-view.resolver'; +import { GroupAccountsResolver } from 'app/groups/common-resolvers/group-account.resolver'; +import { GLIMViewResolver } from './glim-account/glim-account-view.resolver'; +import { GSIMAccountsResolver } from 'app/groups/common-resolvers/gsim-account-resolver'; +import { GLIMLoanTemplateResolver } from './common-resolvers/glim-loan-template.resolver'; +import { GroupViewResolver } from 'app/groups/common-resolvers/group-view.resolver'; /** Loans Route. */ const routes: Routes = [ @@ -249,6 +257,30 @@ const routes: Routes = [ } }, ] + }, + { + path: 'glim-account', + children: [ + { + path: 'create', + data: { title: extract('Create GLIM Application'), breadcrumb: 'Create GLIM Application'}, + component: CreateGlimAccountComponent, + resolve: { + loansAccountTemplate: GLIMLoanTemplateResolver, + gsimData: GSIMAccountsResolver, + groupsData: GroupViewResolver, + }, + }, + { + path: ':glimId', + data: { title: extract('GSIM Account View'), routeParamBreadcrumb: 'savingAccountId'}, + component: GlimAccountComponent, + resolve: { + glimData: GLIMViewResolver, + groupsData: GroupAccountsResolver + }, + } + ] }] }, ]; @@ -268,7 +300,12 @@ const routes: Routes = [ LoansAccountChargeResolver, LoansAccountTransactionResolver, LoansAccountTransactionTemplateResolver, - LoansTransactionRecieptResolver + LoansTransactionRecieptResolver, + SavingsAccountViewResolver, + GroupAccountsResolver, + GLIMViewResolver, + GSIMAccountsResolver, + GLIMLoanTemplateResolver ] }) diff --git a/src/app/loans/loans.module.ts b/src/app/loans/loans.module.ts index 1aaf5616d..7d51d1f31 100644 --- a/src/app/loans/loans.module.ts +++ b/src/app/loans/loans.module.ts @@ -59,6 +59,12 @@ import { ViewRecieptComponent } from './loans-view/transactions/view-reciept/vie import { ExportTransactionsComponent } from './loans-view/transactions/export-transactions/export-transactions.component'; import { ViewTransactionComponent } from './loans-view/transactions/view-transaction/view-transaction.component'; import { EditTransactionComponent } from './loans-view/transactions/edit-transaction/edit-transaction.component'; +import { GlimAccountComponent } from './glim-account/glim-account.component'; +import { CreateGlimAccountComponent } from './glim-account/create-glim-account/create-glim-account.component'; +import { GlimDetailsStepComponent } from './glim-account/create-glim-account/glim-account-stepper/glim-details-step/glim-details-step.component'; +import { GlimChargesStepComponent } from './glim-account/create-glim-account/glim-account-stepper/glim-charges-step/glim-charges-step.component'; +import { GlimTermsStepComponent } from './glim-account/create-glim-account/glim-account-stepper/glim-terms-step/glim-terms-step.component'; +import { GlimPreviewStepComponent } from './glim-account/create-glim-account/glim-account-stepper/glim-preview-step/glim-preview-step.component'; /** Dialog Components */ import { LoansAccountViewGuarantorDetailsDialogComponent } from './custom-dialog/loans-account-view-guarantor-details-dialog/loans-account-view-guarantor-details-dialog.component'; @@ -128,7 +134,13 @@ import { LoanCreditBalanceRefundComponent } from './loans-view/loan-account-acti EditTransactionComponent, ViewRecieptComponent, ExportTransactionsComponent, - LoanCreditBalanceRefundComponent + LoanCreditBalanceRefundComponent, + GlimAccountComponent, + CreateGlimAccountComponent, + GlimDetailsStepComponent, + GlimChargesStepComponent, + GlimTermsStepComponent, + GlimPreviewStepComponent ], providers: [ ], }) diff --git a/src/app/loans/loans.service.ts b/src/app/loans/loans.service.ts index 1319031f5..ed81c3984 100644 --- a/src/app/loans/loans.service.ts +++ b/src/app/loans/loans.service.ts @@ -440,4 +440,22 @@ export class LoansService { return this.http.post(`/loans/${accountId}/transactions`, data, { params: httpParams }); } + /** + * @param glimId GLIM Id of account to get data for. + * @returns {Observable} GLIM Account data. + */ + getGLIMAccountData(glimId: string, groupId: string): Observable { + return this.http.get(`/loans/glimAccount/${glimId}`); + } + + getGLIMLoanAccountTemplate(groupId: any): Observable { + const httpParams = new HttpParams().set('groupId', groupId) + .set('lendingStrategy', '300') + .set('templateType', 'jlgbulk'); + return this.http.get('/loans/template', { params: httpParams }); + } + createGlimAccount(glimAccount: any): Observable { + return this.http.post('/batches?enclosingTransaction=true', glimAccount); + } + } diff --git a/src/app/savings/gsim-account/create-gsim-account/create-gsim-account.component.html b/src/app/savings/gsim-account/create-gsim-account/create-gsim-account.component.html new file mode 100644 index 000000000..1824f18b5 --- /dev/null +++ b/src/app/savings/gsim-account/create-gsim-account/create-gsim-account.component.html @@ -0,0 +1,79 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + DETAILS + + + + + + + + + TERMS + + + + + + + + CHARGES + + + + + + + + + PREVIEW + + + + + + + + +
+ \ No newline at end of file diff --git a/src/app/savings/gsim-account/create-gsim-account/create-gsim-account.component.scss b/src/app/savings/gsim-account/create-gsim-account/create-gsim-account.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/savings/gsim-account/create-gsim-account/create-gsim-account.component.spec.ts b/src/app/savings/gsim-account/create-gsim-account/create-gsim-account.component.spec.ts new file mode 100644 index 000000000..71729de01 --- /dev/null +++ b/src/app/savings/gsim-account/create-gsim-account/create-gsim-account.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateGsimAccountComponent } from './create-gsim-account.component'; + +describe('CreateGsimAccountComponent', () => { + let component: CreateGsimAccountComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateGsimAccountComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateGsimAccountComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/savings/gsim-account/create-gsim-account/create-gsim-account.component.ts b/src/app/savings/gsim-account/create-gsim-account/create-gsim-account.component.ts new file mode 100644 index 000000000..4bc5595e7 --- /dev/null +++ b/src/app/savings/gsim-account/create-gsim-account/create-gsim-account.component.ts @@ -0,0 +1,167 @@ +/** Angular Imports */ +import { Component, OnInit, ViewChild } from '@angular/core'; +import { Router, ActivatedRoute } from '@angular/router'; + +/** 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'; +import { SettingsService } from 'app/settings/settings.service'; +import { Dates } from 'app/core/utils/dates'; + +/** + * Create GSIM Account Component + */ +@Component({ + selector: 'mifosx-create-gsim-account', + templateUrl: './create-gsim-account.component.html', + styleUrls: ['./create-gsim-account.component.scss'] +}) + +export class CreateGsimAccountComponent implements OnInit { + + /** Savings Account Template */ + savingsAccountTemplate: any; + /** Savings Account Product Template */ + savingsAccountProductTemplate: any; + /** Table Data Source */ + dataSource: any; + /** Selected Members */ + selectedMembers: any; + + /** Savings Account Details Step */ + @ViewChild(SavingsAccountDetailsStepComponent, { static: true }) savingsAccountDetailsStep: SavingsAccountDetailsStepComponent; + /** Savings Account Terms Step */ + @ViewChild(SavingsAccountTermsStepComponent, { static: true }) savingsAccountTermsStep: SavingsAccountTermsStepComponent; + /** Savings Account Charges Step */ + @ViewChild(SavingsAccountChargesStepComponent, { static: true }) savingsAccountChargesStep: SavingsAccountChargesStepComponent; + + /** + * Fetches savings account template from `resolve` + * @param {ActivatedRoute} route Activated Route + * @param {Router} router Router + * @param {Dates} dateUtils Date Utils + * @param {SavingsService} savingsService Savings Service + * @param {SettingsService} settingsService Settings Service + */ + constructor(private route: ActivatedRoute, + private router: Router, + private dateUtils: Dates, + private savingsService: SavingsService, + private settingsService: SettingsService + ) { + this.route.data.subscribe((data: { savingsAccountTemplate: any, groupsData: any }) => { + this.savingsAccountTemplate = data.savingsAccountTemplate; + this.dataSource = data.groupsData.activeClientMembers; + }); + } + + ngOnInit(): void { + } + + /** + * 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; + } + + /** + * Retrieves savings account terms form. + */ + get activeClientMembers() { + return this.dataSource; + } + + /** + * Checks validity of overall savings account form. + */ + get savingsAccountFormValid() { + return ( + this.savingsAccountDetailsForm.valid && + this.savingsAccountTermsForm.valid + ); + } + + /** + * Retrieves savings account object. + */ + get savingsAccount() { + this.selectedMembers = this.savingsAccountChargesStep.selectedClientMembers; + return { + ...this.savingsAccountDetailsStep.savingsAccountDetails, + ...this.savingsAccountTermsStep.savingsAccountTerms, + ...this.savingsAccountChargesStep.savingsAccountCharges + }; + } + + /** Set Body for each client selected */ + setData(client: any): any { + const locale = this.settingsService.language.code; + const dateFormat = this.settingsService.dateFormat; + const monthDayFormat = 'dd MMMM'; + const data = { + ...this.savingsAccount, + charges: this.savingsAccount.charges.map((charge: any) => ({ + chargeId: charge.id, + amount: charge.amount, + })), + clientId: client.id, + isGSIM: true, + isParentAccount: true, + submittedOnDate: this.dateUtils.formatDate(this.savingsAccount.submittedOnDate, dateFormat), + dateFormat, + monthDayFormat, + locale + }; + data.groupId = this.savingsAccountTemplate.groupId; + + return data; + + } + + /** Request Body Data */ + buildRequestData(): any[] { + const requestData = []; + const memberSelected = this.selectedMembers.selectedMembers; + for (let index = 0; index < 1; index++) { + console.log(index); + requestData.push( + this.setData( memberSelected[ index ] ), + ); + } + return requestData; + } + + /** + * Creates a new GSIM account. + */ + submit() { + const data = this.buildRequestData(); + const gsimData = { + clientArray: data, + }; + this.savingsService.createGsimAcccount(gsimData).subscribe((response: any) => { + this.router.navigate(['../', response.resourceId], { relativeTo: this.route }); + }); + } + +} diff --git a/src/app/savings/gsim-account/gsim-account.component.html b/src/app/savings/gsim-account/gsim-account.component.html new file mode 100644 index 000000000..a5ee31805 --- /dev/null +++ b/src/app/savings/gsim-account/gsim-account.component.html @@ -0,0 +1,66 @@ +
+ +
+ +

GSIM Account Overview

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Client Details + {{element.displayName}} Saving Account {{element.accountNo}} Products {{element.productName}} Balance Actions + + + + + +
+ + + +
+ \ No newline at end of file diff --git a/src/app/savings/gsim-account/gsim-account.component.scss b/src/app/savings/gsim-account/gsim-account.component.scss new file mode 100644 index 000000000..5264088d8 --- /dev/null +++ b/src/app/savings/gsim-account/gsim-account.component.scss @@ -0,0 +1,33 @@ +.tab-container { + padding: 1%; + margin: 1%; + h3 { + margin:1% auto; + } + .group-details-container { + border: 1px solid; + padding: 1%; + } + .action-button{ + margin-left: auto; + } + table { + width: 100%; + .account-action-button{ + min-width: 26px; + padding: 0 6px; + margin: 4px; + line-height: 25px; + } + tr.select-row:hover { + cursor: pointer; + } + } + i:hover { + cursor: pointer; + } + tr:hover { + cursor: pointer; + } + } + \ No newline at end of file diff --git a/src/app/savings/gsim-account/gsim-account.component.spec.ts b/src/app/savings/gsim-account/gsim-account.component.spec.ts new file mode 100644 index 000000000..9f1b2a155 --- /dev/null +++ b/src/app/savings/gsim-account/gsim-account.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GsimAccountComponent } from './gsim-account.component'; + +describe('GsimAccountComponent', () => { + let component: GsimAccountComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ GsimAccountComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GsimAccountComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/savings/gsim-account/gsim-account.component.ts b/src/app/savings/gsim-account/gsim-account.component.ts new file mode 100644 index 000000000..784111e80 --- /dev/null +++ b/src/app/savings/gsim-account/gsim-account.component.ts @@ -0,0 +1,68 @@ +import { Component, OnInit, ViewChild } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { MatPaginator } from '@angular/material/paginator'; +import { MatTableDataSource } from '@angular/material/table'; +import { ActivatedRoute } from '@angular/router'; + +/** + * GSIM Accounts Overview component. + */ +@Component({ + selector: 'mifosx-gsim-account', + templateUrl: './gsim-account.component.html', + styleUrls: ['./gsim-account.component.scss'] +}) +export class GsimAccountComponent implements OnInit { + + /** Columns to be displayed in charge overview table. */ + displayedColumns: string[] = ['clientDetails', 'savingsAccount', 'products', 'balance', 'Actions']; + /** Data source for charge overview table. */ + dataSource: MatTableDataSource; + /** Charge Overview data */ + gsimOverviewData: any; + + savingAccountData: any; + + groupsData: any; + + /** Paginator for charge overview table. */ + @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator; + + /** + * Retrieves the charge overview data from `resolve`. + * @param {ActivatedRoute} route Activated Route. + * @param {MatDialog} dialog Dialog reference. + */ + constructor(private route: ActivatedRoute, + public dialog: MatDialog) { + this.route.data.subscribe((data: { gsimData: any, savingAccountData: any, groupsData: any }) => { + this.gsimOverviewData = data.gsimData[0].childGSIMAccounts; + this.savingAccountData = data.savingAccountData; + this.groupsData = data.groupsData; + console.log(data); + }); + } + + ngOnInit(): void { + this.setLoanClientChargeOverview(); + } + + /** + * Set Client Charge Overview. + */ + setLoanClientChargeOverview() { + this.dataSource = new MatTableDataSource(this.gsimOverviewData); + console.log(this.dataSource); + console.log(this.gsimOverviewData); + // this.dataSource.paginator = this.paginator; + } + + /** + * Stops the propagation to view pages. + * @param $event Mouse Event + */ + routeEdit($event: MouseEvent) { + $event.stopPropagation(); + } + +} diff --git a/src/app/savings/gsim-account/gsim-account.resolver.ts b/src/app/savings/gsim-account/gsim-account.resolver.ts new file mode 100644 index 000000000..2b87639c8 --- /dev/null +++ b/src/app/savings/gsim-account/gsim-account.resolver.ts @@ -0,0 +1,33 @@ +/** 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'; + +/** + * GSIM Account data resolver. + */ +@Injectable() +export class GSIMViewResolver implements Resolve { + + /** + * @param {SavingsService} savingsService Savings service. + */ + constructor(private savingsService: SavingsService) { } + + /** + * Returns the Savings Account data. + * @param {ActivatedRouteSnapshot} route Route Snapshot + * @returns {Observable} + */ + resolve(route: ActivatedRouteSnapshot): Observable { + const groupId = route.paramMap.get('groupId'); + const savingAccountId = route.paramMap.get('savingAccountId'); + return this.savingsService.getGSIMAccountData(savingAccountId, groupId); + } + +} 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 ac4ecc0a6..35a1b00f1 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 @@ -98,6 +98,38 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Client ID {{element.id}} Client Name {{element.displayName}}
+
+ +
diff --git a/src/app/savings/savings-account-stepper/savings-account-charges-step/savings-account-charges-step.component.ts b/src/app/savings/savings-account-stepper/savings-account-charges-step/savings-account-charges-step.component.ts index ce3b979c1..0b4666361 100644 --- a/src/app/savings/savings-account-stepper/savings-account-charges-step/savings-account-charges-step.component.ts +++ b/src/app/savings/savings-account-stepper/savings-account-charges-step/savings-account-charges-step.component.ts @@ -11,6 +11,7 @@ import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield- import { InputBase } from 'app/shared/form-dialog/formfield/model/input-base'; import { DatepickerBase } from 'app/shared/form-dialog/formfield/model/datepicker-base'; import { Dates } from 'app/core/utils/dates'; +import { MatTableDataSource } from '@angular/material/table'; /** * Savings Account Charges Step @@ -28,6 +29,8 @@ export class SavingsAccountChargesStepComponent implements OnInit, OnChanges { @Input() savingsAccountTemplate: any; /** Currency Code */ @Input() currencyCode: FormControl; + /** active Client Members in case of GSIM Account */ + @Input() activeClientMembers?: any; /** Charge Data */ chargeData: any = []; @@ -39,6 +42,15 @@ export class SavingsAccountChargesStepComponent implements OnInit, OnChanges { isChargesPatched = false; /** Display columns for charges table */ displayedColumns: string[] = ['name', 'chargeCalculationType', 'amount', 'chargeTimeType', 'date', 'repaymentsEvery', 'action']; + /** Table Data Source */ + dataSource: any; + /** Check for select all the Clients List */ + selectAllItems = false; + /** Loan Purpose Options */ + loanPurposeOptions: string[] = []; + /** Table Displayed Columns */ + displayedColumn: string[] = ['check', 'id', 'name']; + /** * @param {MatDialog} dialog Mat Dialog @@ -54,6 +66,7 @@ export class SavingsAccountChargesStepComponent implements OnInit, OnChanges { } else { this.chargesDataSource = []; } + this.dataSource = new MatTableDataSource(this.activeClientMembers); } } @@ -192,4 +205,21 @@ export class SavingsAccountChargesStepComponent implements OnInit, OnChanges { return { charges: this.chargesDataSource }; } + get selectedClientMembers() { + return { selectedMembers: this.activeClientMembers.filter( (item: any) => item.selected ) }; + } + + /** Toggle all checks */ + toggleSelects() { + for (const member of this.activeClientMembers) { + member.selected = this.selectAllItems; + } + } + + /** Check if all the checks are selected */ + toggleSelect() { + const len = this.activeClientMembers.length; + this.selectAllItems = len === 0 ? false : this.activeClientMembers.filter( (item: any) => item.selected ).length === len; + } + } diff --git a/src/app/savings/savings-routing.module.ts b/src/app/savings/savings-routing.module.ts index 6509b03ba..aa0f4b745 100644 --- a/src/app/savings/savings-routing.module.ts +++ b/src/app/savings/savings-routing.module.ts @@ -19,6 +19,8 @@ import { ViewChargeComponent } from './savings-account-view/view-charge/view-cha import { ViewRecieptComponent } from './savings-account-view/transactions/view-reciept/view-reciept.component'; import { ExportTransactionsComponent } from './savings-account-view/transactions-tab/export-transactions/export-transactions.component'; import { EditTransactionComponent } from './savings-account-view/transactions/edit-transaction/edit-transaction.component'; +import { CreateGsimAccountComponent } from './gsim-account/create-gsim-account/create-gsim-account.component'; +import { GsimAccountComponent } from './gsim-account/gsim-account.component'; /** Custom Resolvers */ import { SavingsAccountViewResolver } from './common-resolvers/savings-account-view.resolver'; @@ -31,7 +33,10 @@ import { SavingsAccountChargeResolver } from './common-resolvers/savings-account import { SavingsAccountActionsResolver } from './common-resolvers/savings-account-actions.resolver'; import { SavingsTransactionRecieptResolver } from './common-resolvers/savings-transaction-reciept.resolver'; import { SavingsAccountTransactionTemplateResolver } from './common-resolvers/savings-account-transaction-template.resolver'; - +import { GSIMAccountsResolver } from 'app/groups/common-resolvers/gsim-account-resolver'; +import { GroupAccountsResolver } from 'app/groups/common-resolvers/group-account.resolver'; +import { GSIMViewResolver } from './gsim-account/gsim-account.resolver'; +import { GroupViewResolver } from 'app/groups/common-resolvers/group-view.resolver'; /** Savings Routes */ const routes: Routes = [ { @@ -184,6 +189,35 @@ const routes: Routes = [ loadChildren: () => import('../account-transfers/account-transfers.module').then(m => m.AccountTransfersModule) } ] + }, + { + path: 'gsim-account', + children: [ + { + path: 'create', + data: { title: extract('Create GSIM Application'), breadcrumb: 'Create GSIM Application'}, + component: CreateGsimAccountComponent, + resolve: { + groupsData: GroupViewResolver, + savingsAccountTemplate: SavingsAccountTemplateResolver + }, + }, + { + path: ':savingAccountId', + data: { title: extract('GSIM Account View'), routeParamBreadcrumb: 'savingAccountId'}, + children: [ + { + path: '', + component: GsimAccountComponent, + resolve: { + gsimData: GSIMViewResolver, + savingAccountData: SavingsAccountViewResolver, + groupsData: GroupAccountsResolver + }, + }, + ] + }, + ] } ] }, @@ -201,6 +235,9 @@ const routes: Routes = [ SavingsAccountChargeResolver, SavingsAccountActionsResolver, SavingsTransactionRecieptResolver, - SavingsAccountTransactionTemplateResolver] + SavingsAccountTransactionTemplateResolver, + GSIMAccountsResolver, + GroupAccountsResolver, + GSIMViewResolver] }) export class SavingsRoutingModule {} diff --git a/src/app/savings/savings.module.ts b/src/app/savings/savings.module.ts index 469c0435d..5cfcea34c 100644 --- a/src/app/savings/savings.module.ts +++ b/src/app/savings/savings.module.ts @@ -45,6 +45,8 @@ import { ViewRecieptComponent } from './savings-account-view/transactions/view-r import { ExportTransactionsComponent } from './savings-account-view/transactions-tab/export-transactions/export-transactions.component'; import { EditTransactionComponent } from './savings-account-view/transactions/edit-transaction/edit-transaction.component'; import { ApplyAnnualFeesSavingsAccountComponent } from './saving-account-actions/apply-annual-fees-savings-account/apply-annual-fees-savings-account.component'; +import { GsimAccountComponent } from './gsim-account/gsim-account.component'; +import { CreateGsimAccountComponent } from './gsim-account/create-gsim-account/create-gsim-account.component'; /** @@ -96,7 +98,9 @@ import { ApplyAnnualFeesSavingsAccountComponent } from './saving-account-actions ViewRecieptComponent, ExportTransactionsComponent, EditTransactionComponent, - ApplyAnnualFeesSavingsAccountComponent + ApplyAnnualFeesSavingsAccountComponent, + GsimAccountComponent, + CreateGsimAccountComponent ], providers: [ ] }) diff --git a/src/app/savings/savings.service.ts b/src/app/savings/savings.service.ts index f9836d399..a523ea0ac 100644 --- a/src/app/savings/savings.service.ts +++ b/src/app/savings/savings.service.ts @@ -269,4 +269,21 @@ export class SavingsService { return this.http.delete(`/savingsaccounts/${accountId}/charges/${chargeId}`); } + /** + * @param savingAccountId GSIM Account Id of account to get data for. + * @returns {Observable} Savings data. + */ + getGSIMAccountData(savingAccountId: string, groupId: string): Observable { + const httpParams = new HttpParams().set('parentGSIMAccountNo', savingAccountId ); + return this.http.get(`/groups/${groupId}/gsimaccounts`, { params: httpParams }); + } + + /** + * @param {any} gsimData GSIM Account Data + * @returns {Observable} + */ + createGsimAcccount(gsimData: any): Observable { + return this.http.post(`/savingsaccounts/gsim`, gsimData); + } + }