From 4c060ba32e22daaf3ad099114ba4d55376425e46 Mon Sep 17 00:00:00 2001 From: Muskan Khedia <36980003+muskankhedia@users.noreply.github.com> Date: Wed, 5 Aug 2020 12:49:04 +0530 Subject: [PATCH] feat: add product mix component functionality (#1174) - add create product mix component - add edit product mix component - add delete product mix component Fixes: #196 Co-authored-by: OussEmaDevCode --- .../create-tax-group.component.ts | 16 +--- .../create-product-mix.component.html | 47 ++++++++++ .../create-product-mix.component.scss | 3 + .../create-product-mix.component.spec.ts | 25 +++++ .../create-product-mix.component.ts | 92 +++++++++++++++++++ .../edit-product-mix.component.html | 40 ++++++++ .../edit-product-mix.component.scss | 3 + .../edit-product-mix.component.spec.ts | 25 +++++ .../edit-product-mix.component.ts | 84 +++++++++++++++++ .../products-mix-template.resolver.ts | 30 ++++++ .../products-mix/products-mix.component.html | 2 +- .../view-product-mix.component.html | 4 +- .../view-product-mix.component.ts | 30 +++++- src/app/products/products-routing.module.ts | 44 +++++++-- src/app/products/products.module.ts | 6 +- src/app/products/products.service.ts | 45 +++++++++ 16 files changed, 467 insertions(+), 29 deletions(-) create mode 100644 src/app/products/products-mix/create-product-mix/create-product-mix.component.html create mode 100644 src/app/products/products-mix/create-product-mix/create-product-mix.component.scss create mode 100644 src/app/products/products-mix/create-product-mix/create-product-mix.component.spec.ts create mode 100644 src/app/products/products-mix/create-product-mix/create-product-mix.component.ts create mode 100644 src/app/products/products-mix/edit-product-mix/edit-product-mix.component.html create mode 100644 src/app/products/products-mix/edit-product-mix/edit-product-mix.component.scss create mode 100644 src/app/products/products-mix/edit-product-mix/edit-product-mix.component.spec.ts create mode 100644 src/app/products/products-mix/edit-product-mix/edit-product-mix.component.ts create mode 100644 src/app/products/products-mix/products-mix-template.resolver.ts diff --git a/src/app/products/manage-tax-groups/create-tax-group/create-tax-group.component.ts b/src/app/products/manage-tax-groups/create-tax-group/create-tax-group.component.ts index b93ae6b9c..7028b3f27 100644 --- a/src/app/products/manage-tax-groups/create-tax-group/create-tax-group.component.ts +++ b/src/app/products/manage-tax-groups/create-tax-group/create-tax-group.component.ts @@ -99,13 +99,10 @@ export class CreateTaxGroupComponent implements OnInit { layout: { addButtonText: 'Add' }, formfields: formfields }; - const memberAttendanceDialogRef = this.dialog.open(FormDialogComponent, { data }); - memberAttendanceDialogRef.afterClosed().subscribe((response: any) => { + const taxComponentDialogRef = this.dialog.open(FormDialogComponent, { data }); + taxComponentDialogRef.afterClosed().subscribe((response: any) => { if (response.data) { - // this.taxComponents.push(response.data.value); this.taxComponentsDataSource = this.taxComponentsDataSource.concat(response.data.value); - - console.log('tjos.taxComponents: ', this.taxComponentsDataSource); } }); } @@ -136,15 +133,12 @@ export class CreateTaxGroupComponent implements OnInit { layout: { addButtonText: 'Submit' }, formfields: formfields }; - const memberAttendanceDialogRef = this.dialog.open(FormDialogComponent, { data }); - memberAttendanceDialogRef.afterClosed().subscribe((response: any) => { + const taxComponentDialogRef = this.dialog.open(FormDialogComponent, { data }); + taxComponentDialogRef.afterClosed().subscribe((response: any) => { if (response.data) { - // this.taxComponents.push(response.data.value); - // this.taxComponentsDataSource = this.taxComponentsDataSource.concat(response.data.value); const updatedMemeber = { ...taxComponent, ...response.data.value }; this.taxComponentsDataSource.splice(this.taxComponentsDataSource.indexOf(taxComponent), 1, updatedMemeber); this.taxComponentsDataSource = this.taxComponentsDataSource.concat([]); - console.log('tjos.taxComponents: ', this.taxComponentsDataSource); } }); } @@ -177,8 +171,6 @@ export class CreateTaxGroupComponent implements OnInit { dateFormat, locale }; - console.log(taxGroup); - for (const taxComponent of taxGroup.taxComponents) { taxComponent.startDate = this.datePipe.transform(taxComponent.startDate, dateFormat) || ''; } diff --git a/src/app/products/products-mix/create-product-mix/create-product-mix.component.html b/src/app/products/products-mix/create-product-mix/create-product-mix.component.html new file mode 100644 index 000000000..74db66535 --- /dev/null +++ b/src/app/products/products-mix/create-product-mix/create-product-mix.component.html @@ -0,0 +1,47 @@ +
+ + + +
+ + + +
+ + + Product + + + {{ productOption.name }} + + + + Product is required + + + + + Restricted products + + + {{ product.name }} + + + + At least one restricted product must be selected + + +
+ +
+ + + + + + +
+ +
+ +
diff --git a/src/app/products/products-mix/create-product-mix/create-product-mix.component.scss b/src/app/products/products-mix/create-product-mix/create-product-mix.component.scss new file mode 100644 index 000000000..d774f68da --- /dev/null +++ b/src/app/products/products-mix/create-product-mix/create-product-mix.component.scss @@ -0,0 +1,3 @@ +.container { + max-width: 37rem; +} diff --git a/src/app/products/products-mix/create-product-mix/create-product-mix.component.spec.ts b/src/app/products/products-mix/create-product-mix/create-product-mix.component.spec.ts new file mode 100644 index 000000000..ab855a62a --- /dev/null +++ b/src/app/products/products-mix/create-product-mix/create-product-mix.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateProductMixComponent } from './create-product-mix.component'; + +describe('CreateProductMixComponent', () => { + let component: CreateProductMixComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ CreateProductMixComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateProductMixComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/products/products-mix/create-product-mix/create-product-mix.component.ts b/src/app/products/products-mix/create-product-mix/create-product-mix.component.ts new file mode 100644 index 000000000..8528f59e4 --- /dev/null +++ b/src/app/products/products-mix/create-product-mix/create-product-mix.component.ts @@ -0,0 +1,92 @@ +/** Angular Imports */ +import { Component, OnInit } from '@angular/core'; +import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms'; +import { Router, ActivatedRoute } from '@angular/router'; + +/** Custom Services */ +import { ProductsService } from '../../products.service'; + +/** + * Create Product mix component. + */ +@Component({ + selector: 'mifosx-create-product-mix', + templateUrl: './create-product-mix.component.html', + styleUrls: ['./create-product-mix.component.scss'] +}) +export class CreateProductMixComponent implements OnInit { + + /** Product mix form. */ + productMixForm: FormGroup; + /** Products mix template data. */ + productsMixTemplateData: any; + /** Product option data. */ + productOptionData: any; + /** Product data. */ + productData: any; + + /** + * Retrieves the Products mix template data from `resolve`. + * @param {FormBuilder} formBuilder Form Builder. + * @param {ProductsService} productsService Products Service. + * @param {ActivatedRoute} route Activated Route. + * @param {Router} router Router for navigation. + */ + constructor(private formBuilder: FormBuilder, + private productsService: ProductsService, + private route: ActivatedRoute, + private router: Router) { + this.route.data.subscribe(( data: { productsMixTemplate: any }) => { + this.productsMixTemplateData = data.productsMixTemplate; + }); + } + + /** + * Creates the product mix form and conditional controls of the product mix form. + */ + ngOnInit() { + this.createProductMixForm(); + this.setConditionalControls(); + } + + /** + * Creates the product mix form + */ + createProductMixForm() { + this.productOptionData = this.productsMixTemplateData.productOptions; + this.productMixForm = this.formBuilder.group({ + 'productId': ['', Validators.required], + 'restrictedProducts': ['', Validators.required] + }); + } + + /** + * Sets the conditional controls of the product mix form. + */ + setConditionalControls() { + this.productMixForm.get('productId').valueChanges.subscribe(productId => { + this.productData = undefined; + this.productMixForm.get('restrictedProducts').reset(); + this.productsService.getProductMixTemplate(productId).subscribe((productMixTemplateData: any) => { + const restrictedProductsData = productMixTemplateData.restrictedProducts; + this.productData = [...restrictedProductsData, ...productMixTemplateData.allowedProducts]; + this.productMixForm.get('restrictedProducts').setValue([...restrictedProductsData.map((restrictedProduct: any) => restrictedProduct.id)]); + } + ); + }); + } + + /** + * Submits the product mix form and creates product mix, + * if successful redirects to products mix. + */ + submit() { + const productMix = { + restrictedProducts: this.productMixForm.value.restrictedProducts + }; + const productMixId = this.productMixForm.value.productId; + this.productsService.createProductMix(productMix, productMixId).subscribe((response: any) => { + this.router.navigate(['../', response.resourceId], { relativeTo: this.route }); + }); + } +} diff --git a/src/app/products/products-mix/edit-product-mix/edit-product-mix.component.html b/src/app/products/products-mix/edit-product-mix/edit-product-mix.component.html new file mode 100644 index 000000000..171aff0f5 --- /dev/null +++ b/src/app/products/products-mix/edit-product-mix/edit-product-mix.component.html @@ -0,0 +1,40 @@ +
+ + + +
+ + + +
+ + + Product + + + + + Restricted products + + + {{ product.name }} + + + + At least one restricted product must be selected + + +
+ +
+ + + + + + +
+ +
+ +
diff --git a/src/app/products/products-mix/edit-product-mix/edit-product-mix.component.scss b/src/app/products/products-mix/edit-product-mix/edit-product-mix.component.scss new file mode 100644 index 000000000..d774f68da --- /dev/null +++ b/src/app/products/products-mix/edit-product-mix/edit-product-mix.component.scss @@ -0,0 +1,3 @@ +.container { + max-width: 37rem; +} diff --git a/src/app/products/products-mix/edit-product-mix/edit-product-mix.component.spec.ts b/src/app/products/products-mix/edit-product-mix/edit-product-mix.component.spec.ts new file mode 100644 index 000000000..8339ac61e --- /dev/null +++ b/src/app/products/products-mix/edit-product-mix/edit-product-mix.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EditProductMixComponent } from './edit-product-mix.component'; + +describe('EditProductMixComponent', () => { + let component: EditProductMixComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ EditProductMixComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(EditProductMixComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/products/products-mix/edit-product-mix/edit-product-mix.component.ts b/src/app/products/products-mix/edit-product-mix/edit-product-mix.component.ts new file mode 100644 index 000000000..8cc77ff27 --- /dev/null +++ b/src/app/products/products-mix/edit-product-mix/edit-product-mix.component.ts @@ -0,0 +1,84 @@ +/** Angular Imports */ +import { Component, OnInit } from '@angular/core'; +import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms'; +import { Router, ActivatedRoute } from '@angular/router'; + +/** Custom Services */ +import { ProductsService } from '../../products.service'; + +/** + * Edit Product mix component. + */ +@Component({ + selector: 'mifosx-edit-product-mix', + templateUrl: './edit-product-mix.component.html', + styleUrls: ['./edit-product-mix.component.scss'] +}) +export class EditProductMixComponent implements OnInit { + + /** Product mix form. */ + productMixForm: FormGroup; + /** Products mix template data. */ + productMixData: any; + /** Product option data. */ + productOptionData: any; + /** Product data. */ + productData: any; + + /** + * Retrieves the Products mix template data from `resolve`. + * @param {FormBuilder} formBuilder Form Builder. + * @param {ProductsService} productsService Products Service. + * @param {ActivatedRoute} route Activated Route. + * @param {Router} router Router for navigation. + */ + constructor(private formBuilder: FormBuilder, + private productsService: ProductsService, + private route: ActivatedRoute, + private router: Router) { + this.route.data.subscribe((data: { productMix: any }) => { + this.productMixData = data.productMix; + }); + } + + /** + * Creates the product mix form and sets data of the product mix form. + */ + ngOnInit() { + this.createProductMixForm(); + this.setFormData(); + } + + /** + * Creates the product mix form + */ + createProductMixForm() { + this.productMixForm = this.formBuilder.group({ + 'productId': [{ value: this.productMixData.productName, disabled: true}], + 'restrictedProducts': ['', Validators.required] + }); + } + + /** + * Sets the conditional controls of the product mix form. + */ + setFormData() { + const restrictedProductsData: {}[] = this.productMixData.restrictedProducts; + this.productData = [...restrictedProductsData, ...this.productMixData.allowedProducts]; + this.productMixForm.get('restrictedProducts').setValue([...restrictedProductsData.map((restrictedProduct: any) => restrictedProduct.id)]); + } + + /** + * Submits the product mix form and edits product mix, + * if successful redirects to products mix. + */ + submit() { + const productMix = { + restrictedProducts: this.productMixForm.value.restrictedProducts + }; + const productMixId = this.productMixData.productId; + this.productsService.updateProductMix(productMix, productMixId).subscribe((response: any) => { + this.router.navigate(['../'], { relativeTo: this.route }); + }); + } +} diff --git a/src/app/products/products-mix/products-mix-template.resolver.ts b/src/app/products/products-mix/products-mix-template.resolver.ts new file mode 100644 index 000000000..614de5bd2 --- /dev/null +++ b/src/app/products/products-mix/products-mix-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 { ProductsService } from '../products.service'; + +/** + * Products mix template data resolver. + */ +@Injectable() +export class ProductsMixTemplateResolver implements Resolve { + + /** + * @param {ProductsService} productsService Products service. + */ + constructor(private productsService: ProductsService) {} + + /** + * Returns the products mix template data. + * @returns {Observable} + */ + resolve(): Observable { + return this.productsService.getProductsMixTemplate(); + } + +} diff --git a/src/app/products/products-mix/products-mix.component.html b/src/app/products/products-mix/products-mix.component.html index 5ccfb9e36..71819e44d 100644 --- a/src/app/products/products-mix/products-mix.component.html +++ b/src/app/products/products-mix/products-mix.component.html @@ -1,5 +1,5 @@
-
diff --git a/src/app/products/products-mix/view-product-mix/view-product-mix.component.html b/src/app/products/products-mix/view-product-mix/view-product-mix.component.html index d69f9c0a6..f9e3a56bb 100644 --- a/src/app/products/products-mix/view-product-mix/view-product-mix.component.html +++ b/src/app/products/products-mix/view-product-mix/view-product-mix.component.html @@ -1,9 +1,9 @@
- - diff --git a/src/app/products/products-mix/view-product-mix/view-product-mix.component.ts b/src/app/products/products-mix/view-product-mix/view-product-mix.component.ts index 06d9c9f9b..c91d1219f 100644 --- a/src/app/products/products-mix/view-product-mix/view-product-mix.component.ts +++ b/src/app/products/products-mix/view-product-mix/view-product-mix.component.ts @@ -1,7 +1,11 @@ /** Angular Imports */ import { Component, OnInit, ViewChild } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; -import { MatPaginator, MatSort, MatTableDataSource } from '@angular/material'; +import { ActivatedRoute, Router } from '@angular/router'; +import { MatPaginator, MatSort, MatTableDataSource, MatDialog } from '@angular/material'; +import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component'; + +/** Custom Services */ +import { ProductsService } from 'app/products/products.service'; /** * View product mix component. @@ -37,7 +41,10 @@ export class ViewProductMixComponent implements OnInit { * Retrieves the product mix data from `resolve`. * @param {ActivatedRoute} route Activated Route. */ - constructor(private route: ActivatedRoute) { + constructor(private route: ActivatedRoute, + private dialog: MatDialog, + private productsService: ProductsService, + private router: Router ) { this.route.data.subscribe((data: { productMix: any }) => { this.productMixData = data.productMix; }); @@ -68,4 +75,21 @@ export class ViewProductMixComponent implements OnInit { this.restrictedProductsDatasource.paginator = this.restrictedPaginator; this.restrictedProductsDatasource.sort = this.restrictedSort; } + + /** + * Deletes the product mix + */ + delete() { + const deleteProductMixDialogRef = this.dialog.open(DeleteDialogComponent, { + data: { deleteContext: `the productmix component with id ${this.productMixData.productId}` } + }); + deleteProductMixDialogRef.afterClosed().subscribe((response: any) => { + if (response.delete) { + this.productsService.deleteProductMix(this.productMixData.productId) + .subscribe(() => { + this.router.navigate(['../'], { relativeTo: this.route }); + }); + } + }); + } } diff --git a/src/app/products/products-routing.module.ts b/src/app/products/products-routing.module.ts index fbaa65ee9..2618a56ad 100644 --- a/src/app/products/products-routing.module.ts +++ b/src/app/products/products-routing.module.ts @@ -48,6 +48,7 @@ import { ViewFixedDepositProductComponent } from './fixed-deposit-products/view- import { ViewDividendComponent } from './share-products/view-dividend/view-dividend.component'; import { CreateTaxGroupComponent } from './manage-tax-groups/create-tax-group/create-tax-group.component'; import { EditTaxGroupComponent } from './manage-tax-groups/edit-tax-group/edit-tax-group.component'; +import { CreateProductMixComponent } from './products-mix/create-product-mix/create-product-mix.component'; /** Custom Resolvers */ import { LoanProductsResolver } from './loan-products/loan-products.resolver'; @@ -87,6 +88,8 @@ import { ViewDividendDataResolver } from './share-products/view-dividend/view-di import { FixedDepositProductResolver } from './fixed-deposit-products/fixed-deposit-product.resolver'; import { ManageTaxGroupTemplateResolver } from './manage-tax-groups/create-tax-group/manage-tax-group-template.resolver'; import { EditTaxGroupResolver } from './manage-tax-groups/edit-tax-group/edit-tax-group.resolver'; +import { ProductsMixTemplateResolver } from './products-mix/products-mix-template.resolver'; +import { EditProductMixComponent } from './products-mix/edit-product-mix/edit-product-mix.component'; /** Products Routes */ const routes: Routes = [ @@ -431,20 +434,41 @@ const routes: Routes = [ data: { title: extract('Products Mix'), breadcrumb: 'Products Mix' }, children: [ { - path: '', - component: ProductsMixComponent, + path: 'create', + component: CreateProductMixComponent, + data: { title: extract('Create Product Mix'), breadcrumb: 'Create' }, resolve: { - products: ProductsMixResolver + productsMixTemplate: ProductsMixTemplateResolver } }, { - path: ':id', - component: ViewProductMixComponent, - data: { title: extract('View Product Mix'), routeParamBreadcrumb: 'id'}, + path: '', + component: ProductsMixComponent, resolve: { - productMix: ViewProductMixResolver + products: ProductsMixResolver }, - } + }, + { + path: ':id', + data: { title: extract('View Product Mix'), routeParamBreadcrumb: 'id'}, + children: [ + { + path: '', + component: ViewProductMixComponent, + resolve: { + productMix: ViewProductMixResolver + } + }, + { + path: 'edit', + data: { title: extract('Edit Product Mix'), breadcrumb: 'Edit', routeParamBreadcrumb: false }, + component: EditProductMixComponent, + resolve: { + productMix: ViewProductMixResolver + } + }, + ] + }, ] }, { @@ -497,7 +521,6 @@ const routes: Routes = [ charges: ChargesResolver } }, - { path: ':id', data: { title: extract('View Charges'), routeParamBreadcrumb: 'id' }, @@ -570,7 +593,8 @@ const routes: Routes = [ ViewDividendDataResolver, FixedDepositProductResolver, ManageTaxGroupTemplateResolver, - EditTaxGroupResolver + EditTaxGroupResolver, + ProductsMixTemplateResolver ] }) export class ProductsRoutingModule { } diff --git a/src/app/products/products.module.ts b/src/app/products/products.module.ts index 8c2fd19ae..639fa77ae 100644 --- a/src/app/products/products.module.ts +++ b/src/app/products/products.module.ts @@ -92,6 +92,8 @@ import { ViewDividendComponent } from './share-products/view-dividend/view-divid import { ViewFixedDepositProductComponent } from './fixed-deposit-products/view-fixed-deposit-product/view-fixed-deposit-product.component'; import { CreateTaxGroupComponent } from './manage-tax-groups/create-tax-group/create-tax-group.component'; import { EditTaxGroupComponent } from './manage-tax-groups/edit-tax-group/edit-tax-group.component'; +import { CreateProductMixComponent } from './products-mix/create-product-mix/create-product-mix.component'; +import { EditProductMixComponent } from './products-mix/edit-product-mix/edit-product-mix.component'; /** * Products Module @@ -187,7 +189,9 @@ import { EditTaxGroupComponent } from './manage-tax-groups/edit-tax-group/edit-t ViewDividendComponent, ViewFixedDepositProductComponent, CreateTaxGroupComponent, - EditTaxGroupComponent + EditTaxGroupComponent, + CreateProductMixComponent, + EditProductMixComponent ], entryComponents: [ DepositProductIncentiveFormDialogComponent, diff --git a/src/app/products/products.service.ts b/src/app/products/products.service.ts index afb6027dd..1ec70c00f 100644 --- a/src/app/products/products.service.ts +++ b/src/app/products/products.service.ts @@ -326,6 +326,51 @@ export class ProductsService { return this.http.get(`/loanproducts/${productId}/productmix`); } + /* + * @returns {Observable} Products mix Template data + */ + getProductsMixTemplate(): Observable { + let httpParams = new HttpParams(); + httpParams = httpParams.set('isProductMixTemplate', 'true'); + return this.http.get('/loanproducts/template', { params: httpParams }); + } + + /** + * @param {string} productMixId product mix ID of product mix. + * @returns {Observable} Product mix Template data + */ + getProductMixTemplate(productMixId: string): Observable { + let httpParams = new HttpParams(); + httpParams = httpParams.set('template', 'true'); + return this.http.get(`/loanproducts/${productMixId}/productmix`, { params: httpParams }); + } + + /** + * @param {string} productMixId product mix ID of product mix. + * @param {any} productMix Product mix to be created. + * @returns {Observable} + */ + createProductMix(productMix: any, productMixId: string): Observable { + return this.http.post(`/loanproducts/${productMixId}/productmix`, productMix); + } + + /** + * @param {string} productMixId product mix ID of product mix. + * @param {any} productMix Product mix to be updaated. + * @returns {Observable} + */ + updateProductMix(productMix: any, productMixId: string): Observable { + return this.http.put(`/loanproducts/${productMixId}/productmix`, productMix); + } + + /** + * @param {string} productMixId product mix ID of product mix. + * @returns {Observable} + */ + deleteProductMix(productMixId: string): Observable { + return this.http.delete(`/loanproducts/${productMixId}/productmix`); + } + /* * @param {string} productId Product ID * @returns {Observable}