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 <oussamahassini6@gmail.com>
This commit is contained in:
Muskan Khedia
2020-08-05 12:49:04 +05:30
committed by GitHub
co-authored by OussEmaDevCode
parent b94857c39c
commit 4c060ba32e
16 changed files with 467 additions and 29 deletions
@@ -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) || '';
}
@@ -0,0 +1,47 @@
<div class="container">
<mat-card>
<form [formGroup]="productMixForm" (ngSubmit)="submit()">
<mat-card-content>
<div fxLayout="column">
<mat-form-field>
<mat-label>Product</mat-label>
<mat-select required formControlName="productId">
<mat-option *ngFor="let productOption of productOptionData" [value]="productOption.id">
{{ productOption.name }}
</mat-option>
</mat-select>
<mat-error *ngIf="productMixForm.controls.productId.hasError('required')">
Product is <strong>required</strong>
</mat-error>
</mat-form-field>
<mat-form-field *ngIf="productData">
<mat-label>Restricted products</mat-label>
<mat-select required formControlName="restrictedProducts" multiple>
<mat-option *ngFor="let product of productData" [value]="product.id">
{{ product.name }}
</mat-option>
</mat-select>
<mat-error *ngIf="productMixForm.controls.restrictedProducts.hasError('required')" >
At least one restricted product <strong>must be selected</strong>
</mat-error>
</mat-form-field>
</div>
</mat-card-content>
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
<button type="button" mat-raised-button [routerLink]="['../']">Cancel</button>
<button mat-raised-button color="primary" [disabled]="!productMixForm.valid">Submit</button>
</mat-card-actions>
</form>
</mat-card>
</div>
@@ -0,0 +1,3 @@
.container {
max-width: 37rem;
}
@@ -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<CreateProductMixComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CreateProductMixComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CreateProductMixComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -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 });
});
}
}
@@ -0,0 +1,40 @@
<div class="container">
<mat-card>
<form [formGroup]="productMixForm" (ngSubmit)="submit()">
<mat-card-content>
<div fxLayout="column">
<mat-form-field>
<mat-label>Product</mat-label>
<input matInput formControlName="productId">
</mat-form-field>
<mat-form-field *ngIf="productData">
<mat-label>Restricted products</mat-label>
<mat-select required formControlName="restrictedProducts" multiple>
<mat-option *ngFor="let product of productData" [value]="product.id">
{{ product.name }}
</mat-option>
</mat-select>
<mat-error *ngIf="productMixForm.controls.restrictedProducts.hasError('required')">
At least one restricted product <strong>must be selected</strong>
</mat-error>
</mat-form-field>
</div>
</mat-card-content>
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
<button type="button" mat-raised-button [routerLink]="['../']">Cancel</button>
<button mat-raised-button color="primary" [disabled]="!productMixForm.valid">Submit</button>
</mat-card-actions>
</form>
</mat-card>
</div>
@@ -0,0 +1,3 @@
.container {
max-width: 37rem;
}
@@ -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<EditProductMixComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ EditProductMixComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(EditProductMixComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -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 });
});
}
}
@@ -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<Object> {
/**
* @param {ProductsService} productsService Products service.
*/
constructor(private productsService: ProductsService) {}
/**
* Returns the products mix template data.
* @returns {Observable<any>}
*/
resolve(): Observable<any> {
return this.productsService.getProductsMixTemplate();
}
}
@@ -1,5 +1,5 @@
<div fxLayout="row" fxLayoutAlign="end" class="container m-b-20">
<button mat-raised-button color="primary">
<button mat-raised-button color="primary" [routerLink]="['create']">
<fa-icon icon="plus"></fa-icon>&nbsp;&nbsp;Add
</button>
</div>
@@ -1,9 +1,9 @@
<div class="container m-b-20" fxLayout="row" fxLayout.lt-md="column" fxLayoutAlign="end" fxLayoutGap="20px">
<button mat-raised-button color="primary">
<button mat-raised-button color="primary" [routerLink]="['edit']">
<fa-icon icon="edit"></fa-icon>&nbsp;&nbsp;
Edit
</button>
<button mat-raised-button color="warn">
<button mat-raised-button color="warn" (click)="delete()">
<fa-icon icon="trash"></fa-icon>&nbsp;&nbsp;
Delete
</button>
@@ -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 });
});
}
});
}
}
+34 -10
View File
@@ -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 { }
+5 -1
View File
@@ -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,
+45
View File
@@ -326,6 +326,51 @@ export class ProductsService {
return this.http.get(`/loanproducts/${productId}/productmix`);
}
/*
* @returns {Observable<any>} Products mix Template data
*/
getProductsMixTemplate(): Observable<any> {
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<any>} Product mix Template data
*/
getProductMixTemplate(productMixId: string): Observable<any> {
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<any>}
*/
createProductMix(productMix: any, productMixId: string): Observable<any> {
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<any>}
*/
updateProductMix(productMix: any, productMixId: string): Observable<any> {
return this.http.put(`/loanproducts/${productMixId}/productmix`, productMix);
}
/**
* @param {string} productMixId product mix ID of product mix.
* @returns {Observable<any>}
*/
deleteProductMix(productMixId: string): Observable<any> {
return this.http.delete(`/loanproducts/${productMixId}/productmix`);
}
/*
* @param {string} productId Product ID
* @returns {Observable<any>}