diff --git a/src/app/organization/loan-provisioning-criteria/common-resolvers/loan-provisioning-criteria-template.resolver.ts b/src/app/organization/loan-provisioning-criteria/common-resolvers/loan-provisioning-criteria-template.resolver.ts new file mode 100644 index 000000000..da0967cfa --- /dev/null +++ b/src/app/organization/loan-provisioning-criteria/common-resolvers/loan-provisioning-criteria-template.resolver.ts @@ -0,0 +1,30 @@ +/** Angular Imports */ +import { Injectable } from '@angular/core'; +import { Resolve } from '@angular/router'; + +/** rxjs Imports */ +import { Observable } from 'rxjs'; + +/** Custom Services */ +import { OrganizationService } from '../../organization.service'; + +/** + * Provisioning criteria template resolver. + */ +@Injectable() +export class LoanProvisioningCriteriaTemplateResolver implements Resolve { + + /** + * @param {OrganizationService} organizationService Products service. + */ + constructor(private organizationService: OrganizationService) {} + + /** + * Returns the Pprovisioning criteria template + * @returns {Observable} + */ + resolve(): Observable { + return this.organizationService.getProvisioningCriteriaTemplate(); + } + +} diff --git a/src/app/organization/loan-provisioning-criteria/loan-provisioning-criteria.resolver.ts b/src/app/organization/loan-provisioning-criteria/common-resolvers/loan-provisioning-criteria.resolver.ts similarity index 92% rename from src/app/organization/loan-provisioning-criteria/loan-provisioning-criteria.resolver.ts rename to src/app/organization/loan-provisioning-criteria/common-resolvers/loan-provisioning-criteria.resolver.ts index 8a89b38a3..809a283db 100644 --- a/src/app/organization/loan-provisioning-criteria/loan-provisioning-criteria.resolver.ts +++ b/src/app/organization/loan-provisioning-criteria/common-resolvers/loan-provisioning-criteria.resolver.ts @@ -6,7 +6,7 @@ import { Resolve, ActivatedRouteSnapshot } from '@angular/router'; import { Observable } from 'rxjs'; /** Custom Services */ -import { OrganizationService } from '../organization.service'; +import { OrganizationService } from '../../organization.service'; /** * Loan Provisioning Criteria data resolver. diff --git a/src/app/organization/loan-provisioning-criteria/loan-provisioning-criterias.resolver.ts b/src/app/organization/loan-provisioning-criteria/common-resolvers/loan-provisioning-criterias.resolver.ts similarity index 90% rename from src/app/organization/loan-provisioning-criteria/loan-provisioning-criterias.resolver.ts rename to src/app/organization/loan-provisioning-criteria/common-resolvers/loan-provisioning-criterias.resolver.ts index 6f3a087a9..dc3139a94 100644 --- a/src/app/organization/loan-provisioning-criteria/loan-provisioning-criterias.resolver.ts +++ b/src/app/organization/loan-provisioning-criteria/common-resolvers/loan-provisioning-criterias.resolver.ts @@ -6,7 +6,7 @@ import { Resolve } from '@angular/router'; import { Observable } from 'rxjs'; /** Custom Services */ -import { OrganizationService } from '../organization.service'; +import { OrganizationService } from '../../organization.service'; /** * Charges data resolver. diff --git a/src/app/organization/loan-provisioning-criteria/create-loan-provisioning-criteria/create-loan-provisioning-criteria.component.html b/src/app/organization/loan-provisioning-criteria/create-loan-provisioning-criteria/create-loan-provisioning-criteria.component.html new file mode 100644 index 000000000..9d14efd42 --- /dev/null +++ b/src/app/organization/loan-provisioning-criteria/create-loan-provisioning-criteria/create-loan-provisioning-criteria.component.html @@ -0,0 +1,94 @@ +
+ + + +
+ +
+ +
+ + + Provisioning Criteria + + + Provisioning Criteria is required + + + + + Selected Products + + + {{ product.name }} + + + + +
+ +
+ +
+ +
+ + Please fill all provisioning criteria definitions. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Category {{ definition.categoryName }} Min Age {{ definition.minAge || '-' }} Max Age {{ definition.maxAge || '-' }} Percentage (%) {{ definition.provisioningPercentage || '-' }} Liability Account {{ (definition.liabilityAccount | find:loanProvisioningCriteriaTemplate.glAccounts:'id':'name') || '-' }} Expense Account {{ (definition.expenseAccount | find:loanProvisioningCriteriaTemplate.glAccounts:'id':'name') || '-' }} Actions + +
+ +
+ +
+ + +
+ +
+ +
diff --git a/src/app/organization/loan-provisioning-criteria/create-loan-provisioning-criteria/create-loan-provisioning-criteria.component.scss b/src/app/organization/loan-provisioning-criteria/create-loan-provisioning-criteria/create-loan-provisioning-criteria.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/organization/loan-provisioning-criteria/create-loan-provisioning-criteria/create-loan-provisioning-criteria.component.spec.ts b/src/app/organization/loan-provisioning-criteria/create-loan-provisioning-criteria/create-loan-provisioning-criteria.component.spec.ts new file mode 100644 index 000000000..7d1e26630 --- /dev/null +++ b/src/app/organization/loan-provisioning-criteria/create-loan-provisioning-criteria/create-loan-provisioning-criteria.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateLoanProvisioningCriteriaComponent } from './create-loan-provisioning-criteria.component'; + +describe('CreateLoanProvisioningCriteriaComponent', () => { + let component: CreateLoanProvisioningCriteriaComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ CreateLoanProvisioningCriteriaComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateLoanProvisioningCriteriaComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/organization/loan-provisioning-criteria/create-loan-provisioning-criteria/create-loan-provisioning-criteria.component.ts b/src/app/organization/loan-provisioning-criteria/create-loan-provisioning-criteria/create-loan-provisioning-criteria.component.ts new file mode 100644 index 000000000..65cdcf79f --- /dev/null +++ b/src/app/organization/loan-provisioning-criteria/create-loan-provisioning-criteria/create-loan-provisioning-criteria.component.ts @@ -0,0 +1,189 @@ +/** Angular Imports */ +import { Component, OnInit } from '@angular/core'; +import { FormGroup, FormBuilder, Validators } from '@angular/forms'; +import { MatTableDataSource, MatDialog } from '@angular/material'; +import { Router, ActivatedRoute } from '@angular/router'; + +/** Custom Models */ +import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield-base'; +import { InputBase } from 'app/shared/form-dialog/formfield/model/input-base'; +import { SelectBase } from 'app/shared/form-dialog/formfield/model/select-base'; + +/** Custom Dialogs */ +import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component'; + +/** Custom Services */ +import { OrganizationService } from '../../organization.service'; + +/** + * Create Loan Provisioning Criteria Component. + */ +@Component({ + selector: 'mifosx-create-loan-provisioning-criteria', + templateUrl: './create-loan-provisioning-criteria.component.html', + styleUrls: ['./create-loan-provisioning-criteria.component.scss'] +}) +export class CreateLoanProvisioningCriteriaComponent implements OnInit { + + /** Loan Provisioning Criteria form. */ + provisioningCriteriaForm: FormGroup; + /** Loan Provisioning Criteria Template */ + loanProvisioningCriteriaTemplate: any; + /** Liability Accounts */ + liabilityAccounts: any; + /** Expense Accounts */ + expenseAccounts: any; + + /** Columns to be displayed in definitions table. */ + displayedColumns: string[] = ['category', 'minAge', 'maxAge', 'percentage', 'liabilityAccount', 'expenseAccount', 'edit']; + /** Criteria Definitions Array */ + definitions: { + categoryId: number, + categoryName: string, + maxAge?: number, + minAge?: number, + liabilityAccount?: string, + expenseAccount?: string, + provisioningPercentage?: number + }[] = []; + /** Checks Definitons Table Validity */ + isDefinitionValid: any = {}; + + /** + * Retrieves the offices data from `resolve`. + * @param {FormBuilder} formBuilder Form Builder. + * @param {OrganizationService} organizationService Organization Service. + * @param {ActivatedRoute} route Activated Route. + * @param {Router} router Router for navigation. + */ + constructor(private formBuilder: FormBuilder, + private organizationService: OrganizationService, + private router: Router, + public dialog: MatDialog, + private route: ActivatedRoute) { + this.route.data.subscribe((data: { loanProvisioningCriteriaTemplate: any }) => { + this.loanProvisioningCriteriaTemplate = data.loanProvisioningCriteriaTemplate; + this.definitions = this.loanProvisioningCriteriaTemplate.definitions; + this.liabilityAccounts = this.loanProvisioningCriteriaTemplate.glAccounts.filter((account: any) => account.type.value === 'LIABILITY'); + this.expenseAccounts = this.loanProvisioningCriteriaTemplate.glAccounts.filter((account: any) => account.type.value === 'EXPENSE'); + }); + } + + ngOnInit() { + this.createProvisioningCriteriaForm(); + } + + /** + * Creates the provisioning criteria form + */ + createProvisioningCriteriaForm() { + this.provisioningCriteriaForm = this.formBuilder.group({ + 'criteriaName': ['', Validators.required], + 'loanProducts': [''] + }); + } + + /** + * Edit Definition + * @param {any} definition Definition + * @param {number} index Definition index + */ + editDefinition(definition: any) { + const data = { + title: 'Edit Criteria Definition', + formfields: this.getDefinitionFormFields(definition), + layout: { addButtonText: 'Confirm' } + }; + const editDefinitionDialogRef = this.dialog.open(FormDialogComponent, { data }); + editDefinitionDialogRef.afterClosed().subscribe((response: any) => { + if (response.data) { + const definitionData = { + ...response.data.value, + categoryName: definition.categoryName, + categoryId: definition.categoryId + }; + this.definitions.splice(this.definitions.indexOf(definition), 1, definitionData); + this.definitions = this.definitions.concat([]); + this.isDefinitionValid[definition.categoryName] = true; + } + }); + } + + /** + * Gets formfields for form dialog. + * @param {any} definition Definition + */ + getDefinitionFormFields(definition: any) { + const formfields: FormfieldBase[] = []; + formfields.push(new InputBase({ + controlName: 'minAge', + label: 'Min Age', + value: definition ? definition.minAge : '', + type: 'number', + required: true, + order: 1 + })); + formfields.push(new InputBase({ + controlName: 'maxAge', + label: 'Max Age', + value: definition ? definition.maxAge : '', + type: 'number', + required: true, + order: 2 + })); + formfields.push(new InputBase({ + controlName: 'provisioningPercentage', + label: 'Percentage (%)', + value: definition ? definition.provisioningPercentage : '', + type: 'number', + required: true, + order: 3 + })); + formfields.push(new SelectBase({ + controlName: 'liabilityAccount', + label: 'Liability Account', + value: definition ? definition.liabilityAccount : '', + options: { label: 'name', value: 'id', data: this.liabilityAccounts }, + required: true, + order: 4 + })); + formfields.push(new SelectBase({ + controlName: 'expenseAccount', + label: 'Expense Account', + value: definition ? definition.expenseAccount : '', + options: { label: 'name', value: 'id', data: this.expenseAccounts }, + required: true, + order: 5 + })); + return formfields; + } + + /** + * Returns validity of form and table. + */ + get provisioningCriteriaFormValid() { + const definitionsValid: boolean = Object.entries(this.isDefinitionValid).length === this.definitions.length ? true : false; + return this.provisioningCriteriaForm.valid && definitionsValid; + } + + /** + * Creates a loan provisioning criteria. + */ + submit() { + const locale = 'en'; + const loanProvisioningCriteria = { + ...this.provisioningCriteriaForm.value, + loanProducts: this.provisioningCriteriaForm.get('loanProducts').value.map((product: any) => ({ + id: product.id, + name: product.name, + includeInBorrowerCycle: product.includeInBorrowerCycle + })), + definitions: this.definitions, + locale + }; + this.organizationService.createProvisioningCriteria(loanProvisioningCriteria).subscribe((response: any) => { + this.router.navigate(['../', response.resourceId], { relativeTo: this.route }); + }); + } + +} diff --git a/src/app/organization/loan-provisioning-criteria/loan-provisioning-criteria.component.html b/src/app/organization/loan-provisioning-criteria/loan-provisioning-criteria.component.html index 4bdb23072..3200a51c1 100644 --- a/src/app/organization/loan-provisioning-criteria/loan-provisioning-criteria.component.html +++ b/src/app/organization/loan-provisioning-criteria/loan-provisioning-criteria.component.html @@ -1,5 +1,5 @@
- diff --git a/src/app/organization/loan-provisioning-criteria/view-loan-provisioning-criteria/view-loan-provisioning-criteria.component.html b/src/app/organization/loan-provisioning-criteria/view-loan-provisioning-criteria/view-loan-provisioning-criteria.component.html index 36e1eb7c9..46dc0fbec 100644 --- a/src/app/organization/loan-provisioning-criteria/view-loan-provisioning-criteria/view-loan-provisioning-criteria.component.html +++ b/src/app/organization/loan-provisioning-criteria/view-loan-provisioning-criteria/view-loan-provisioning-criteria.component.html @@ -29,7 +29,7 @@
- +
@@ -65,8 +65,6 @@
Category
- -
diff --git a/src/app/organization/loan-provisioning-criteria/view-loan-provisioning-criteria/view-loan-provisioning-criteria.component.ts b/src/app/organization/loan-provisioning-criteria/view-loan-provisioning-criteria/view-loan-provisioning-criteria.component.ts index dfc84c210..b9b53929a 100644 --- a/src/app/organization/loan-provisioning-criteria/view-loan-provisioning-criteria/view-loan-provisioning-criteria.component.ts +++ b/src/app/organization/loan-provisioning-criteria/view-loan-provisioning-criteria/view-loan-provisioning-criteria.component.ts @@ -1,8 +1,7 @@ /** Angular Imports */ -import { Component, OnInit, ViewChild } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { MatDialog } from '@angular/material'; import { Router, ActivatedRoute } from '@angular/router'; -import { MatPaginator } from '@angular/material/paginator'; import { MatTableDataSource } from '@angular/material/table'; /** Custom Services */ @@ -30,9 +29,6 @@ export class ViewLoanProvisioningCriteriaComponent implements OnInit { /** Data source for loan provisioning criteria table. */ dataSource: MatTableDataSource; - /** Paginator for loan provisioning criteria table. */ - @ViewChild(MatPaginator) paginator: MatPaginator; - /** * Retrieves the Provisioning data from `resolve`. * @param {OrganizationService} organizationService Organization Service. @@ -58,7 +54,6 @@ export class ViewLoanProvisioningCriteriaComponent implements OnInit { */ setLoanProvisioningSelectedCriteria() { this.dataSource = new MatTableDataSource(this.provisioningData.definitions); - this.dataSource.paginator = this.paginator; /** Get load products as a string. */ for (let _id = 0; _id < this.provisioningData.loanProducts.length; _id++) { diff --git a/src/app/organization/organization-routing.module.ts b/src/app/organization/organization-routing.module.ts index ee69afbe9..04c78553f 100644 --- a/src/app/organization/organization-routing.module.ts +++ b/src/app/organization/organization-routing.module.ts @@ -56,9 +56,11 @@ import { ViewLoanProvisioningCriteriaComponent } from './loan-provisioning-crite import { CreateCampaignComponent } from './sms-campaigns/create-campaign/create-campaign.component'; import { EditCampaignComponent } from './sms-campaigns/edit-campaign/edit-campaign.component'; import { CreateEnityDataTableChecksComponent } from './entity-data-table-checks/create-enity-data-table-checks/create-enity-data-table-checks.component'; +import { CreateLoanProvisioningCriteriaComponent } from './loan-provisioning-criteria/create-loan-provisioning-criteria/create-loan-provisioning-criteria.component'; +import { BulkLoanReassignmnetComponent } from './bulk-loan-reassignmnet/bulk-loan-reassignmnet.component'; /** Custom Resolvers */ -import { LoanProvisioningCriteriaResolver } from './loan-provisioning-criteria/loan-provisioning-criteria.resolver'; +import { LoanProvisioningCriteriaResolver } from './loan-provisioning-criteria/common-resolvers/loan-provisioning-criteria.resolver'; import { OfficesResolver } from './offices/common-resolvers/offices.resolver'; import { EmployeesResolver } from './employees/employees.resolver'; import { EmployeeResolver } from './employees/employee.resolver'; @@ -76,7 +78,7 @@ import { EntityDataTableChecksResolver } from './entity-data-table-checks/entity import { WorkingDaysResolver } from './working-days/working-days.resolver'; import { EditOfficeResolver } from './offices/common-resolvers/edit-office.resolver'; import { AdhocQueryTemplateResolver } from './adhoc-query/adhoc-query-template.resolver'; -import { LoanProvisioningCriteriasResolver } from './loan-provisioning-criteria/loan-provisioning-criterias.resolver'; +import { LoanProvisioningCriteriasResolver } from './loan-provisioning-criteria/common-resolvers/loan-provisioning-criterias.resolver'; import { CashierResolver } from './tellers/common-resolvers/cashier.resolver'; import { CashiersResolver } from './tellers/common-resolvers/cashiers.resolver'; import { HolidayResolver } from './holidays/holiday.resolver'; @@ -92,7 +94,7 @@ import { AdhocQueryAndTemplateResolver } from './adhoc-query/common-resolvers/ad import { BulkImportResolver } from './bulk-import/bulk-import.resolver'; import { SmsCampaignTemplateResolver } from './sms-campaigns/common-resolvers/sms-campaign-template.resolver'; import { EntityDataTableChecksTemplateResolver } from './entity-data-table-checks/enitity-data-table-checks-template.resolver'; -import { BulkLoanReassignmnetComponent } from './bulk-loan-reassignmnet/bulk-loan-reassignmnet.component'; +import { LoanProvisioningCriteriaTemplateResolver } from './loan-provisioning-criteria/common-resolvers/loan-provisioning-criteria-template.resolver'; /** Organization Routes */ const routes: Routes = [ @@ -116,6 +118,14 @@ const routes: Routes = [ loanProvisioningCriterias: LoanProvisioningCriteriasResolver } }, + { + path: 'create', + data: { title: extract('Create Provisioning Criteria'), breadcrumb: 'Create Provisioning Criteria' }, + component: CreateLoanProvisioningCriteriaComponent, + resolve: { + loanProvisioningCriteriaTemplate: LoanProvisioningCriteriaTemplateResolver, + } + }, { path: ':id', data: { title: extract('View Provisioning Criteria'), routeParamBreadcrumb: 'id' }, @@ -641,7 +651,8 @@ const routes: Routes = [ BulkImportResolver, HolidayResolver, EntityDataTableChecksTemplateResolver, - LoanProvisioningCriteriasResolver + LoanProvisioningCriteriasResolver, + LoanProvisioningCriteriaTemplateResolver ] }) export class OrganizationRoutingModule { } diff --git a/src/app/organization/organization.module.ts b/src/app/organization/organization.module.ts index ac67adb27..9a13bcb4d 100644 --- a/src/app/organization/organization.module.ts +++ b/src/app/organization/organization.module.ts @@ -64,6 +64,7 @@ import { EditSmsCampaignStepComponent } from './sms-campaigns/sms-campaign-stepp import { EditBusinessRuleParametersComponent } from './sms-campaigns/sms-campaign-stepper/edit-sms-campaign-step/edit-business-rule-parameters/edit-business-rule-parameters.component'; import { CreateEnityDataTableChecksComponent } from './entity-data-table-checks/create-enity-data-table-checks/create-enity-data-table-checks.component'; import { BulkLoanReassignmnetComponent } from './bulk-loan-reassignmnet/bulk-loan-reassignmnet.component'; +import { CreateLoanProvisioningCriteriaComponent } from './loan-provisioning-criteria/create-loan-provisioning-criteria/create-loan-provisioning-criteria.component'; /** * Organization Module @@ -134,6 +135,7 @@ import { BulkLoanReassignmnetComponent } from './bulk-loan-reassignmnet/bulk-loa EditBusinessRuleParametersComponent, CreateEnityDataTableChecksComponent, BulkLoanReassignmnetComponent, + CreateLoanProvisioningCriteriaComponent, ] }) export class OrganizationModule { } diff --git a/src/app/organization/organization.service.ts b/src/app/organization/organization.service.ts index 5684baec9..e4f103e0d 100644 --- a/src/app/organization/organization.service.ts +++ b/src/app/organization/organization.service.ts @@ -41,6 +41,14 @@ export class OrganizationService { return this.http.get(`/provisioningcriteria/${provisioningId}`, { params: httpParams }); } + /** + * @param {any} Criteria Provisioning Criteria to be created. + * @returns {Observable} + */ + createProvisioningCriteria(criteriaData: any): Observable { + return this.http.post('/provisioningcriteria', criteriaData); + } + /** * @param {string} provisioningId Provisioning ID of provisioning criteria to be deleted. * @returns {Observable}