From c3dcd4852aa9b66bc20416a7b1506f4921048c10 Mon Sep 17 00:00:00 2001 From: Abhay Chawla Date: Sat, 3 Aug 2019 11:51:23 +0530 Subject: [PATCH] feat: add create share product component (#462) - Add share product stepper components - Add create share product component - Add datepicker-base.ts Fixes: #190 --- src/app/products/products-routing.module.ts | 11 + src/app/products/products.module.ts | 20 +- src/app/products/products.service.ts | 8 + .../create-share-product.component.html | 106 +++++++++ .../create-share-product.component.scss | 0 .../create-share-product.component.spec.ts | 25 ++ .../create-share-product.component.ts | 103 +++++++++ ...are-product-accounting-step.component.html | 92 ++++++++ ...are-product-accounting-step.component.scss | 15 ++ ...-product-accounting-step.component.spec.ts | 25 ++ ...share-product-accounting-step.component.ts | 61 +++++ .../share-product-charges-step.component.html | 74 ++++++ .../share-product-charges-step.component.scss | 11 + ...are-product-charges-step.component.spec.ts | 25 ++ .../share-product-charges-step.component.ts | 56 +++++ ...share-product-currency-step.component.html | 46 ++++ ...share-product-currency-step.component.scss | 3 + ...re-product-currency-step.component.spec.ts | 25 ++ .../share-product-currency-step.component.ts | 42 ++++ .../share-product-details-step.component.html | 39 ++++ .../share-product-details-step.component.scss | 3 + ...are-product-details-step.component.spec.ts | 25 ++ .../share-product-details-step.component.ts | 32 +++ ...e-product-market-price-step.component.html | 56 +++++ ...e-product-market-price-step.component.scss | 16 ++ ...roduct-market-price-step.component.spec.ts | 25 ++ ...are-product-market-price-step.component.ts | 115 ++++++++++ .../share-product-preview-step.component.html | 214 ++++++++++++++++++ .../share-product-preview-step.component.scss | 24 ++ ...are-product-preview-step.component.spec.ts | 25 ++ .../share-product-preview-step.component.ts | 23 ++ ...share-product-settings-step.component.html | 74 ++++++ ...share-product-settings-step.component.scss | 12 + ...re-product-settings-step.component.spec.ts | 25 ++ .../share-product-settings-step.component.ts | 44 ++++ .../share-product-terms-step.component.html | 50 ++++ .../share-product-terms-step.component.scss | 3 + ...share-product-terms-step.component.spec.ts | 25 ++ .../share-product-terms-step.component.ts | 40 ++++ .../share-products-template.resolver.ts | 24 ++ .../share-products.component.html | 2 +- .../formfield/formfield.component.html | 58 +++-- .../formfield/model/datepicker-base.ts | 15 ++ .../form-dialog/formfield/model/input-base.ts | 2 +- 44 files changed, 1691 insertions(+), 28 deletions(-) create mode 100644 src/app/products/share-products/create-share-product/create-share-product.component.html create mode 100644 src/app/products/share-products/create-share-product/create-share-product.component.scss create mode 100644 src/app/products/share-products/create-share-product/create-share-product.component.spec.ts create mode 100644 src/app/products/share-products/create-share-product/create-share-product.component.ts create mode 100644 src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.html create mode 100644 src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.scss create mode 100644 src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.spec.ts create mode 100644 src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.ts create mode 100644 src/app/products/share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component.html create mode 100644 src/app/products/share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component.scss create mode 100644 src/app/products/share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component.spec.ts create mode 100644 src/app/products/share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component.ts create mode 100644 src/app/products/share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component.html create mode 100644 src/app/products/share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component.scss create mode 100644 src/app/products/share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component.spec.ts create mode 100644 src/app/products/share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component.ts create mode 100644 src/app/products/share-products/share-product-stepper/share-product-details-step/share-product-details-step.component.html create mode 100644 src/app/products/share-products/share-product-stepper/share-product-details-step/share-product-details-step.component.scss create mode 100644 src/app/products/share-products/share-product-stepper/share-product-details-step/share-product-details-step.component.spec.ts create mode 100644 src/app/products/share-products/share-product-stepper/share-product-details-step/share-product-details-step.component.ts create mode 100644 src/app/products/share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component.html create mode 100644 src/app/products/share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component.scss create mode 100644 src/app/products/share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component.spec.ts create mode 100644 src/app/products/share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component.ts create mode 100644 src/app/products/share-products/share-product-stepper/share-product-preview-step/share-product-preview-step.component.html create mode 100644 src/app/products/share-products/share-product-stepper/share-product-preview-step/share-product-preview-step.component.scss create mode 100644 src/app/products/share-products/share-product-stepper/share-product-preview-step/share-product-preview-step.component.spec.ts create mode 100644 src/app/products/share-products/share-product-stepper/share-product-preview-step/share-product-preview-step.component.ts create mode 100644 src/app/products/share-products/share-product-stepper/share-product-settings-step/share-product-settings-step.component.html create mode 100644 src/app/products/share-products/share-product-stepper/share-product-settings-step/share-product-settings-step.component.scss create mode 100644 src/app/products/share-products/share-product-stepper/share-product-settings-step/share-product-settings-step.component.spec.ts create mode 100644 src/app/products/share-products/share-product-stepper/share-product-settings-step/share-product-settings-step.component.ts create mode 100644 src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.html create mode 100644 src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.scss create mode 100644 src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.spec.ts create mode 100644 src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.ts create mode 100644 src/app/products/share-products/share-products-template.resolver.ts create mode 100644 src/app/shared/form-dialog/formfield/model/datepicker-base.ts diff --git a/src/app/products/products-routing.module.ts b/src/app/products/products-routing.module.ts index a7f121c39..3ce2315f1 100644 --- a/src/app/products/products-routing.module.ts +++ b/src/app/products/products-routing.module.ts @@ -19,6 +19,7 @@ import { CreateSavingProductComponent } from './saving-products/create-saving-pr import { ViewSavingProductComponent } from './saving-products/view-saving-product/view-saving-product.component'; import { EditSavingProductComponent } from './saving-products/edit-saving-product/edit-saving-product.component'; import { ShareProductsComponent } from './share-products/share-products.component'; +import { CreateShareProductComponent } from './share-products/create-share-product/create-share-product.component'; import { ManageTaxConfigurationsComponent } from './manage-tax-configurations/manage-tax-configurations.component'; import { RecurringDepositProductsComponent } from './recurring-deposit-products/recurring-deposit-products.component'; import { ChargesComponent } from './charges/charges.component'; @@ -36,6 +37,7 @@ import { SavingProductsTemplateResolver } from './saving-products/saving-product import { SavingProductResolver } from './saving-products/saving-product.resolver'; import { SavingProductAndTemplateResolver } from './saving-products/edit-saving-product/saving-product-and-template.resolver'; import { ShareProductsResolver } from './share-products/share-products.resolver'; +import { ShareProductsTemplateResolver } from './share-products/share-products-template.resolver'; import { RecurringDepositProductsResolver } from './recurring-deposit-products/recurring-deposit-products.resolver'; import { ChargesResolver } from './charges/charges.resolver'; import { FixedDepositProductsResolver } from './fixed-deposit-products/fixed-deposit-products.resolver'; @@ -147,6 +149,14 @@ const routes: Routes = [ resolve: { shareProducts: ShareProductsResolver } + }, + { + path: 'create', + component: CreateShareProductComponent, + data: { title: extract('Create Share Product'), breadcrumb: 'Create' }, + resolve: { + shareProductsTemplate: ShareProductsTemplateResolver + } } ] }, @@ -223,6 +233,7 @@ const routes: Routes = [ SavingProductResolver, SavingProductAndTemplateResolver, ShareProductsResolver, + ShareProductsTemplateResolver, RecurringDepositProductsResolver, ChargesResolver, FixedDepositProductsResolver, diff --git a/src/app/products/products.module.ts b/src/app/products/products.module.ts index 4e3aa54a2..789fbe5df 100644 --- a/src/app/products/products.module.ts +++ b/src/app/products/products.module.ts @@ -38,6 +38,15 @@ import { CreateSavingProductComponent } from './saving-products/create-saving-pr import { ViewSavingProductComponent } from './saving-products/view-saving-product/view-saving-product.component'; import { EditSavingProductComponent } from './saving-products/edit-saving-product/edit-saving-product.component'; import { ShareProductsComponent } from './share-products/share-products.component'; +import { ShareProductDetailsStepComponent } from './share-products/share-product-stepper/share-product-details-step/share-product-details-step.component'; +import { ShareProductCurrencyStepComponent } from './share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component'; +import { ShareProductTermsStepComponent } from './share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component'; +import { ShareProductSettingsStepComponent } from './share-products/share-product-stepper/share-product-settings-step/share-product-settings-step.component'; +import { ShareProductMarketPriceStepComponent } from './share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component'; +import { ShareProductChargesStepComponent } from './share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component'; +import { ShareProductAccountingStepComponent } from './share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component'; +import { ShareProductPreviewStepComponent } from './share-products/share-product-stepper/share-product-preview-step/share-product-preview-step.component'; +import { CreateShareProductComponent } from './share-products/create-share-product/create-share-product.component'; /** * Products Module @@ -80,7 +89,16 @@ import { ShareProductsComponent } from './share-products/share-products.componen CreateSavingProductComponent, ViewSavingProductComponent, EditSavingProductComponent, - ShareProductsComponent + ShareProductsComponent, + ShareProductDetailsStepComponent, + ShareProductCurrencyStepComponent, + ShareProductTermsStepComponent, + ShareProductSettingsStepComponent, + ShareProductMarketPriceStepComponent, + ShareProductChargesStepComponent, + ShareProductAccountingStepComponent, + ShareProductPreviewStepComponent, + CreateShareProductComponent ], entryComponents: [ ], diff --git a/src/app/products/products.service.ts b/src/app/products/products.service.ts index 226ad60e1..c26c95a29 100644 --- a/src/app/products/products.service.ts +++ b/src/app/products/products.service.ts @@ -73,6 +73,14 @@ export class ProductsService { return this.http.get('/products/share'); } + createShareProduct(shareProduct: string): Observable { + return this.http.post('/products/share', shareProduct); + } + + getShareProductsTemplate(): Observable { + return this.http.get('/products/share/template'); + } + /** * @returns {Observable} Recurring deposit products data */ diff --git a/src/app/products/share-products/create-share-product/create-share-product.component.html b/src/app/products/share-products/create-share-product/create-share-product.component.html new file mode 100644 index 000000000..2428faafc --- /dev/null +++ b/src/app/products/share-products/create-share-product/create-share-product.component.html @@ -0,0 +1,106 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + DETAILS + + + + + + + + CURRENCY + + + + + + + + TERMS + + + + + + + + SETTINGS + + + + + + + + MARKET PRICE + + + + + + + + CHARGES + + + + + + + + + ACCOUNTING + + + + + + + + + PREVIEW + + + + + + + + +
diff --git a/src/app/products/share-products/create-share-product/create-share-product.component.scss b/src/app/products/share-products/create-share-product/create-share-product.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/products/share-products/create-share-product/create-share-product.component.spec.ts b/src/app/products/share-products/create-share-product/create-share-product.component.spec.ts new file mode 100644 index 000000000..9b46b75af --- /dev/null +++ b/src/app/products/share-products/create-share-product/create-share-product.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateShareProductComponent } from './create-share-product.component'; + +describe('CreateShareProductComponent', () => { + let component: CreateShareProductComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ CreateShareProductComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateShareProductComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/products/share-products/create-share-product/create-share-product.component.ts b/src/app/products/share-products/create-share-product/create-share-product.component.ts new file mode 100644 index 000000000..30bfc62ca --- /dev/null +++ b/src/app/products/share-products/create-share-product/create-share-product.component.ts @@ -0,0 +1,103 @@ +import { Component, OnInit, ViewChild } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; + +import { ShareProductDetailsStepComponent } from '../share-product-stepper/share-product-details-step/share-product-details-step.component'; +import { ShareProductCurrencyStepComponent } from '../share-product-stepper/share-product-currency-step/share-product-currency-step.component'; +import { ShareProductTermsStepComponent } from '../share-product-stepper/share-product-terms-step/share-product-terms-step.component'; +import { ShareProductSettingsStepComponent } from '../share-product-stepper/share-product-settings-step/share-product-settings-step.component'; +import { ShareProductMarketPriceStepComponent } from '../share-product-stepper/share-product-market-price-step/share-product-market-price-step.component'; +import { ShareProductChargesStepComponent } from '../share-product-stepper/share-product-charges-step/share-product-charges-step.component'; +import { ShareProductAccountingStepComponent } from '../share-product-stepper/share-product-accounting-step/share-product-accounting-step.component'; + +import { ProductsService } from 'app/products/products.service'; + +@Component({ + selector: 'mifosx-create-share-product', + templateUrl: './create-share-product.component.html', + styleUrls: ['./create-share-product.component.scss'] +}) +export class CreateShareProductComponent implements OnInit { + + @ViewChild(ShareProductDetailsStepComponent) shareProductDetailsStep: ShareProductDetailsStepComponent; + @ViewChild(ShareProductCurrencyStepComponent) shareProductCurrencyStep: ShareProductCurrencyStepComponent; + @ViewChild(ShareProductTermsStepComponent) shareProductTermsStep: ShareProductTermsStepComponent; + @ViewChild(ShareProductSettingsStepComponent) shareProductSettingsStep: ShareProductSettingsStepComponent; + @ViewChild(ShareProductMarketPriceStepComponent) shareProductMarketPriceStep: ShareProductMarketPriceStepComponent; + @ViewChild(ShareProductChargesStepComponent) shareProductChargesStep: ShareProductChargesStepComponent; + @ViewChild(ShareProductAccountingStepComponent) shareProductAccountingStep: ShareProductAccountingStepComponent; + + shareProductsTemplate: any; + accountingRuleData = ['None', 'Cash']; + + constructor(private route: ActivatedRoute, + private productsService: ProductsService, + private router: Router) { + this.route.data.subscribe((data: { shareProductsTemplate: any }) => { + this.shareProductsTemplate = data.shareProductsTemplate; + }); + } + + ngOnInit() { + } + + get shareProductDetailsForm() { + return this.shareProductDetailsStep.shareProductDetailsForm; + } + + get shareProductCurrencyForm() { + return this.shareProductCurrencyStep.shareProductCurrencyForm; + } + + get shareProductTermsForm() { + return this.shareProductTermsStep.shareProductTermsForm; + } + + get shareProductSettingsForm() { + return this.shareProductSettingsStep.shareProductSettingsForm; + } + + get shareProductMarketPriceForm() { + return this.shareProductMarketPriceStep.shareProductMarketPriceForm; + } + + get shareProductAccountingForm() { + return this.shareProductAccountingStep.shareProductAccountingForm; + } + + get shareProductFormValid() { + return ( + this.shareProductDetailsForm.valid && + this.shareProductCurrencyForm.valid && + this.shareProductTermsForm.valid && + this.shareProductSettingsForm.valid && + this.shareProductMarketPriceForm.valid && + this.shareProductAccountingForm.valid + ); + } + + get shareProduct() { + return { + ...this.shareProductDetailsStep.shareProductDetails, + ...this.shareProductCurrencyStep.shareProductCurrency, + ...this.shareProductTermsStep.shareProductTerms, + ...this.shareProductSettingsStep.shareProductSettings, + ...this.shareProductMarketPriceStep.shareProductMarketPrice, + ...this.shareProductChargesStep.shareProductCharges, + ...this.shareProductAccountingStep.shareProductAccounting + }; + } + + submit() { + // TODO: Update once language and date settings are setup + const shareProduct = { + ...this.shareProduct, + chargesSelected: this.shareProduct.chargesSelected.map((charge: any) => ({ id: charge.id })), + locale: 'en' // locale required for digitsAfterDecimal + }; + this.productsService.createShareProduct(shareProduct) + .subscribe((response: any) => { + this.router.navigate(['../', response.resourceId], { relativeTo: this.route }); + }); + } + +} diff --git a/src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.html b/src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.html new file mode 100644 index 000000000..9828f4aed --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.html @@ -0,0 +1,92 @@ +
+ +
+ + + + {{ accountingRule }} + + + + + +
+ +

Assets

+ + + Share reference + + + {{ assetAccount.name }} + + + + Share reference is required + + + + + +

Liabilities

+ + + Share suspense control + + + {{ liabilityAccount.name }} + + + + Share suspense control is required + + + + + +

Share Equity

+ + + Equity + + + {{ equityAccount.name }} + + + + Equity is required + + + + + +

Income

+ + + Income from fees + + + {{ incomeAccount.name }} + + + + Income from fees is required + + + +
+ +
+ +
+ + +
+ +
diff --git a/src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.scss b/src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.scss new file mode 100644 index 000000000..8272d1779 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.scss @@ -0,0 +1,15 @@ +h4 { + font-weight: 500; +} + +mat-radio-group, h4 { + margin: 1em 0; +} + +mat-divider { + margin: 1em 0 2em 0; +} + +.margin-t { + margin-top: 1em; +} diff --git a/src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.spec.ts b/src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.spec.ts new file mode 100644 index 000000000..be929b5a4 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ShareProductAccountingStepComponent } from './share-product-accounting-step.component'; + +describe('ShareProductAccountingStepComponent', () => { + let component: ShareProductAccountingStepComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ShareProductAccountingStepComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ShareProductAccountingStepComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.ts b/src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.ts new file mode 100644 index 000000000..1badca8d8 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.ts @@ -0,0 +1,61 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms'; + +@Component({ + selector: 'mifosx-share-product-accounting-step', + templateUrl: './share-product-accounting-step.component.html', + styleUrls: ['./share-product-accounting-step.component.scss'] +}) +export class ShareProductAccountingStepComponent implements OnInit { + + @Input() shareProductsTemplate: any; + @Input() accountingRuleData: any; + @Input() shareProductFormValid: boolean; + + shareProductAccountingForm: FormGroup; + + assetAccountData: any; + incomeAccountData: any; + equityAccountData: any; + liabilityAccountData: any; + + constructor(private formBuilder: FormBuilder) { + this.createShareProductAccountingForm(); + this.setConditionalControls(); + } + + ngOnInit() { + this.assetAccountData = this.shareProductsTemplate.accountingMappingOptions.assetAccountOptions || []; + this.incomeAccountData = this.shareProductsTemplate.accountingMappingOptions.incomeAccountOptions || []; + this.equityAccountData = this.shareProductsTemplate.accountingMappingOptions.equityAccountOptions || []; + this.liabilityAccountData = this.shareProductsTemplate.accountingMappingOptions.liabilityAccountOptions || []; + } + + createShareProductAccountingForm() { + this.shareProductAccountingForm = this.formBuilder.group({ + 'accountingRule': [1] + }); + } + + setConditionalControls() { + this.shareProductAccountingForm.get('accountingRule').valueChanges + .subscribe((accountingRule: any) => { + if (accountingRule === 2) { + this.shareProductAccountingForm.addControl('shareReferenceId', new FormControl('', Validators.required)); + this.shareProductAccountingForm.addControl('shareSuspenseId', new FormControl('', Validators.required)); + this.shareProductAccountingForm.addControl('shareEquityId', new FormControl('', Validators.required)); + this.shareProductAccountingForm.addControl('incomeFromFeeAccountId', new FormControl('', Validators.required)); + } else { + this.shareProductAccountingForm.removeControl('shareReferenceId'); + this.shareProductAccountingForm.removeControl('shareSuspenseId'); + this.shareProductAccountingForm.removeControl('shareEquityId'); + this.shareProductAccountingForm.removeControl('incomeFromFeeAccountId'); + } + }); + } + + get shareProductAccounting() { + return this.shareProductAccountingForm.value; + } + +} diff --git a/src/app/products/share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component.html b/src/app/products/share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component.html new file mode 100644 index 000000000..4a0d5881e --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component.html @@ -0,0 +1,74 @@ +
+ + + Charge + + + {{ charge.name }} + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name + {{ charge.name + ', ' + charge.currency.displaySymbol }} + Type + {{ charge.chargeCalculationType.value }} + Amount + {{ charge.amount }} + Collected On + {{ charge.chargeTimeType.value }} + Actions + +
+ +
+ +
+ + +
diff --git a/src/app/products/share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component.scss b/src/app/products/share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component.scss new file mode 100644 index 000000000..dd420676a --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component.scss @@ -0,0 +1,11 @@ +table { + width: 100%; +} + +.mat-elevation-z1 { + margin: 1em 0 1.5em 0; +} + +.margin-t { + margin-top: 1em; +} diff --git a/src/app/products/share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component.spec.ts b/src/app/products/share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component.spec.ts new file mode 100644 index 000000000..65f7cfde0 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ShareProductChargesStepComponent } from './share-product-charges-step.component'; + +describe('ShareProductChargesStepComponent', () => { + let component: ShareProductChargesStepComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ShareProductChargesStepComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ShareProductChargesStepComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/products/share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component.ts b/src/app/products/share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component.ts new file mode 100644 index 000000000..aebaf5def --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component.ts @@ -0,0 +1,56 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { MatDialog } from '@angular/material'; +import { FormControl } from '@angular/forms'; + +import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component'; + +@Component({ + selector: 'mifosx-share-product-charges-step', + templateUrl: './share-product-charges-step.component.html', + styleUrls: ['./share-product-charges-step.component.scss'] +}) +export class ShareProductChargesStepComponent implements OnInit { + + @Input() shareProductsTemplate: any; + @Input() currencyCode: FormControl; + + chargeData: any; + + chargesDataSource: {}[]; + displayedColumns: string[] = ['name', 'chargeCalculationType', 'amount', 'chargeTimeType', 'action']; + + constructor(public dialog: MatDialog) { + } + + ngOnInit() { + this.chargeData = this.shareProductsTemplate.chargeOptions; + + this.chargesDataSource = []; + + this.currencyCode.valueChanges.subscribe(() => this.chargesDataSource = []); + } + + addCharge(charge: any) { + this.chargesDataSource = this.chargesDataSource.concat([charge.value]); + charge.value = ''; + } + + deleteCharge(charge: any) { + const deleteChargeDialogRef = this.dialog.open(DeleteDialogComponent, { + data: { deleteContext: `charge ${charge.name}` } + }); + deleteChargeDialogRef.afterClosed().subscribe((response: any) => { + if (response.delete) { + this.chargesDataSource.splice(this.chargesDataSource.indexOf(charge), 1); + this.chargesDataSource = this.chargesDataSource.concat([]); + } + }); + } + + get shareProductCharges() { + return { + chargesSelected: this.chargesDataSource + }; + } + +} diff --git a/src/app/products/share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component.html b/src/app/products/share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component.html new file mode 100644 index 000000000..ddaebd8a8 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component.html @@ -0,0 +1,46 @@ +
+ +
+ + + Currency + + + {{ currency.name }} + + + + Currency is required + + + + + Decimal Places + + + Decimal Places is required + + + + + Currency in multiples of + + + Currency in multiples of is required + + + +
+ +
+ + +
+ +
diff --git a/src/app/products/share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component.scss b/src/app/products/share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component.scss new file mode 100644 index 000000000..aa8d23226 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component.scss @@ -0,0 +1,3 @@ +.margin-t { + margin-top: 1em; +} diff --git a/src/app/products/share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component.spec.ts b/src/app/products/share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component.spec.ts new file mode 100644 index 000000000..b5a4edd45 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ShareProductCurrencyStepComponent } from './share-product-currency-step.component'; + +describe('ShareProductCurrencyStepComponent', () => { + let component: ShareProductCurrencyStepComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ShareProductCurrencyStepComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ShareProductCurrencyStepComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/products/share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component.ts b/src/app/products/share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component.ts new file mode 100644 index 000000000..dbdc98115 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component.ts @@ -0,0 +1,42 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { FormGroup, FormBuilder, Validators } from '@angular/forms'; + +@Component({ + selector: 'mifosx-share-product-currency-step', + templateUrl: './share-product-currency-step.component.html', + styleUrls: ['./share-product-currency-step.component.scss'] +}) +export class ShareProductCurrencyStepComponent implements OnInit { + + @Input() shareProductsTemplate: any; + + shareProductCurrencyForm: FormGroup; + + currencyData: any; + + constructor(private formBuilder: FormBuilder) { + this.createShareProductCurrencyForm(); + } + + ngOnInit() { + this.currencyData = this.shareProductsTemplate.currencyOptions; + + this.shareProductCurrencyForm.patchValue({ + 'currencyCode': this.currencyData[0].code, + 'digitsAfterDecimal': 2 + }); + } + + createShareProductCurrencyForm() { + this.shareProductCurrencyForm = this.formBuilder.group({ + 'currencyCode': ['', Validators.required], + 'digitsAfterDecimal': ['', Validators.required], + 'inMultiplesOf': ['', Validators.required] + }); + } + + get shareProductCurrency() { + return this.shareProductCurrencyForm.value; + } + +} diff --git a/src/app/products/share-products/share-product-stepper/share-product-details-step/share-product-details-step.component.html b/src/app/products/share-products/share-product-stepper/share-product-details-step/share-product-details-step.component.html new file mode 100644 index 000000000..fcaeb3363 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-details-step/share-product-details-step.component.html @@ -0,0 +1,39 @@ +
+ +
+ + + Product Name + + + Product Name is required + + + + + Short Name + + + Short Name is required + + + + + Description + + + +
+ +
+ + +
+ +
diff --git a/src/app/products/share-products/share-product-stepper/share-product-details-step/share-product-details-step.component.scss b/src/app/products/share-products/share-product-stepper/share-product-details-step/share-product-details-step.component.scss new file mode 100644 index 000000000..aa8d23226 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-details-step/share-product-details-step.component.scss @@ -0,0 +1,3 @@ +.margin-t { + margin-top: 1em; +} diff --git a/src/app/products/share-products/share-product-stepper/share-product-details-step/share-product-details-step.component.spec.ts b/src/app/products/share-products/share-product-stepper/share-product-details-step/share-product-details-step.component.spec.ts new file mode 100644 index 000000000..ea2f6d96b --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-details-step/share-product-details-step.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ShareProductDetailsStepComponent } from './share-product-details-step.component'; + +describe('ShareProductDetailsStepComponent', () => { + let component: ShareProductDetailsStepComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ShareProductDetailsStepComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ShareProductDetailsStepComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/products/share-products/share-product-stepper/share-product-details-step/share-product-details-step.component.ts b/src/app/products/share-products/share-product-stepper/share-product-details-step/share-product-details-step.component.ts new file mode 100644 index 000000000..f0f364284 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-details-step/share-product-details-step.component.ts @@ -0,0 +1,32 @@ +import { Component, OnInit } from '@angular/core'; +import { FormGroup, FormBuilder, Validators } from '@angular/forms'; + +@Component({ + selector: 'mifosx-share-product-details-step', + templateUrl: './share-product-details-step.component.html', + styleUrls: ['./share-product-details-step.component.scss'] +}) +export class ShareProductDetailsStepComponent implements OnInit { + + shareProductDetailsForm: FormGroup; + + constructor(private formBuilder: FormBuilder) { + this.createShareProductDetailsForm(); + } + + ngOnInit() { + } + + createShareProductDetailsForm() { + this.shareProductDetailsForm = this.formBuilder.group({ + 'name': ['', Validators.required], + 'shortName': ['', Validators.required], + 'description': [''] + }); + } + + get shareProductDetails() { + return this.shareProductDetailsForm.value; + } + +} diff --git a/src/app/products/share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component.html b/src/app/products/share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component.html new file mode 100644 index 000000000..1f4d6dc05 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component.html @@ -0,0 +1,56 @@ +
+ +

Market Price Periods

+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + +
From Date + {{ marketPricePeriod.fromDate | date }} + Nominal/Unit Price + {{ marketPricePeriod.shareValue }} + Actions + + +
+ +
+ +
+ + +
diff --git a/src/app/products/share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component.scss b/src/app/products/share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component.scss new file mode 100644 index 000000000..38b9ccfb6 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component.scss @@ -0,0 +1,16 @@ +table { + width: 100%; +} + +.mat-elevation-z1 { + margin: 1em 0 1.5em 0; +} + +h4 { + font-weight: 500; + margin: 1em 0; +} + +.margin-t { + margin-top: 1em; +} diff --git a/src/app/products/share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component.spec.ts b/src/app/products/share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component.spec.ts new file mode 100644 index 000000000..bf58fea17 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ShareProductMarketPriceStepComponent } from './share-product-market-price-step.component'; + +describe('ShareProductMarketPriceStepComponent', () => { + let component: ShareProductMarketPriceStepComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ShareProductMarketPriceStepComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ShareProductMarketPriceStepComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/products/share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component.ts b/src/app/products/share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component.ts new file mode 100644 index 000000000..d061c1c90 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component.ts @@ -0,0 +1,115 @@ +import { Component, OnInit } from '@angular/core'; +import { DatePipe } from '@angular/common'; +import { FormGroup, FormBuilder, FormArray } from '@angular/forms'; +import { MatDialog } from '@angular/material'; + +import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component'; +import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component'; + +import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield-base'; +import { DatepickerBase } from 'app/shared/form-dialog/formfield/model/datepicker-base'; +import { InputBase } from 'app/shared/form-dialog/formfield/model/input-base'; + +@Component({ + selector: 'mifosx-share-product-market-price-step', + templateUrl: './share-product-market-price-step.component.html', + styleUrls: ['./share-product-market-price-step.component.scss'] +}) +export class ShareProductMarketPriceStepComponent implements OnInit { + + shareProductMarketPriceForm: FormGroup; + + displayedColumns: string[] = ['fromDate', 'shareValue', 'actions']; + + constructor(private formBuilder: FormBuilder, + public dialog: MatDialog, + private datePipe: DatePipe) { + this.createShareProductMarketPriceForm(); + } + + ngOnInit() { + } + + createShareProductMarketPriceForm() { + this.shareProductMarketPriceForm = this.formBuilder.group({ + 'marketPricePeriods': this.formBuilder.array([]) + }); + } + + get marketPricePeriods(): FormArray { + return this.shareProductMarketPriceForm.get('marketPricePeriods') as FormArray; + } + + addMarketPricePeriod() { + const data = this.getData(); + const addVariationsForBorrowerCycleDialogRef = this.dialog.open(FormDialogComponent, { data }); + addVariationsForBorrowerCycleDialogRef.afterClosed().subscribe((response: any) => { + if (response.data) { + this.marketPricePeriods.push(response.data); + } + }); + } + + editMarketPricePeriod(index: number) { + const data = { ...this.getData(this.marketPricePeriods.at(index).value), layout: { addButtonText: 'Edit' } }; + const addVariationsForBorrowerCycleDialogRef = this.dialog.open(FormDialogComponent, { data }); + addVariationsForBorrowerCycleDialogRef.afterClosed().subscribe((response: any) => { + if (response.data) { + this.marketPricePeriods.at(index).patchValue(response.data.value); + } + }); + } + + deleteMarketPricePeriod(index: number) { + const deleteVariationsForBorrowerCycleDialogRef = this.dialog.open(DeleteDialogComponent, { + data: { deleteContext: `this` } + }); + deleteVariationsForBorrowerCycleDialogRef.afterClosed().subscribe((response: any) => { + if (response.delete) { + this.marketPricePeriods.removeAt(index); + } + }); + } + + getData(values?: any) { + return { title: 'Market Price Period', formfields: this.getFormfields(values) }; + } + + getFormfields(values?: any) { + const formfields: FormfieldBase[] = [ + new DatepickerBase({ + controlName: 'fromDate', + label: 'From Date', + value: values ? values.fromDate : undefined, + maxDate: new Date(new Date().setFullYear(new Date().getFullYear() + 10)), + required: true, + order: 1 + }), + new InputBase({ + controlName: 'shareValue', + label: 'Nominal/Unit Price', + value: values ? values.shareValue : undefined, + type: 'number', + required: true, + order: 2 + }) + ]; + return formfields; + } + + get shareProductMarketPrice() { + // TODO: Update once language and date settings are setup + const dateFormat = 'yyyy-MM-dd'; + const marketPricePeriods = []; + for (const marketPricePeriod of this.marketPricePeriods.value) { + marketPricePeriods.push({ + ...marketPricePeriod, + fromDate: this.datePipe.transform(marketPricePeriod.fromDate, dateFormat), + dateFormat, + locale: 'en' + }); + } + return { marketPricePeriods }; + } + +} diff --git a/src/app/products/share-products/share-product-stepper/share-product-preview-step/share-product-preview-step.component.html b/src/app/products/share-products/share-product-stepper/share-product-preview-step/share-product-preview-step.component.html new file mode 100644 index 000000000..ec8bf95e2 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-preview-step/share-product-preview-step.component.html @@ -0,0 +1,214 @@ +
+ +

{{ shareProduct.name }}

+ + + +

Details

+ + + +
+ Short Name: + {{ shareProduct.shortName }} +
+ +
+ Description: + {{ shareProduct.description }} +
+ +

Currency

+ + + +
+ Currency: + {{ shareProduct.currencyCode | find:shareProductsTemplate.currencyOptions:'code':'name' }} +
+ +
+ Decimal Places: + {{ shareProduct.digitsAfterDecimal }} +
+ +
+ Currency in multiples of: + {{ shareProduct.inMultiplesOf }} +
+ +

Terms

+ + + +
+ Total Number of Shares: + {{ shareProduct.totalShares }} +
+ +
+ Shares to be Issued: + {{ shareProduct.sharesIssued }} +
+ +
+ Nominal/Unit Price: + {{ shareProduct.unitPrice }} +
+ +
+ Capital Value: + {{ shareProduct.shareCapital }} +
+ +

Settings

+ + + +
+ Shares per Client: + {{ shareProduct.nominalShares + ' (Min: ' + (shareProduct.minimumShares ? shareProduct.minimumShares : shareProduct.nominalShares) + ', Max: ' + (shareProduct.maximumShares ? shareProduct.maximumShares : shareProduct.nominalShares) + ')' }} +
+ +
+ Minimum Active Period: + {{ shareProduct.minimumActivePeriodForDividends + ' ' + (shareProduct.minimumactiveperiodFrequencyType | find:shareProductsTemplate.minimumActivePeriodFrequencyTypeOptions:'id':'value') }} +
+ +
+ Lock-in Period: + {{ shareProduct.lockinPeriodFrequency + ' ' + (shareProduct.lockinPeriodFrequencyType | find:shareProductsTemplate.lockinPeriodFrequencyTypeOptions:'id':'value') }} +
+ +
+ Allow dividends for inactive clients: + {{ shareProduct.allowDividendCalculationForInactiveClients ? 'Yes' : 'No' }} +
+ +
+ +

Market Price Periods

+ + + + + + + + + + + + + + + + + + +
From Date + {{ marketPricePeriod.fromDate | date }} + Nominal/Unit Price + {{ marketPricePeriod.shareValue }} +
+ +
+ +
+ +

Charges

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name + {{ charge.name + ', ' + charge.currency.displaySymbol }} + Type + {{ charge.chargeCalculationType.value }} + Amount + {{ charge.amount }} + Collected On + {{ charge.chargeTimeType.value }} +
+ +
+ +

Accounting

+ + + +
+ Type: + {{ accountingRuleData[shareProduct.accountingRule-1] }} +
+ +
+ +

Assets

+ +
+ Share reference: + {{ shareProduct.shareReferenceId | find:shareProductsTemplate.accountingMappingOptions.assetAccountOptions:'id':'name' }} +
+ +

Liabilities

+ +
+ Share suspense control: + {{ shareProduct.shareSuspenseId | find:shareProductsTemplate.accountingMappingOptions.liabilityAccountOptions:'id':'name' }} +
+ +

Expenses

+ +
+ Share Equity: + {{ shareProduct.shareEquityId | find:shareProductsTemplate.accountingMappingOptions.equityAccountOptions:'id':'name' }} +
+ +

Income

+ +
+ Income from fees: + {{ shareProduct.incomeFromFeeAccountId | find:shareProductsTemplate.accountingMappingOptions.incomeAccountOptions:'id':'name' }} +
+ +
+ +
+ +
+ + + +
diff --git a/src/app/products/share-products/share-product-stepper/share-product-preview-step/share-product-preview-step.component.scss b/src/app/products/share-products/share-product-stepper/share-product-preview-step/share-product-preview-step.component.scss new file mode 100644 index 000000000..87258dacb --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-preview-step/share-product-preview-step.component.scss @@ -0,0 +1,24 @@ +table { + width: 100%; +} + +.mat-elevation-z1 { + margin: 1em 0 1.5em 0; +} + +h2, h3, h4 { + margin: 0; + font-weight: 500; +} + +span { + margin: 0.5em 0; +} + +mat-divider { + margin: 0 0 0.5em 0; +} + +.margin-t { + margin-top: 1em; +} diff --git a/src/app/products/share-products/share-product-stepper/share-product-preview-step/share-product-preview-step.component.spec.ts b/src/app/products/share-products/share-product-stepper/share-product-preview-step/share-product-preview-step.component.spec.ts new file mode 100644 index 000000000..c2c56bb98 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-preview-step/share-product-preview-step.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ShareProductPreviewStepComponent } from './share-product-preview-step.component'; + +describe('ShareProductPreviewStepComponent', () => { + let component: ShareProductPreviewStepComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ShareProductPreviewStepComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ShareProductPreviewStepComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/products/share-products/share-product-stepper/share-product-preview-step/share-product-preview-step.component.ts b/src/app/products/share-products/share-product-stepper/share-product-preview-step/share-product-preview-step.component.ts new file mode 100644 index 000000000..715d5d32f --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-preview-step/share-product-preview-step.component.ts @@ -0,0 +1,23 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; + +@Component({ + selector: 'mifosx-share-product-preview-step', + templateUrl: './share-product-preview-step.component.html', + styleUrls: ['./share-product-preview-step.component.scss'] +}) +export class ShareProductPreviewStepComponent implements OnInit { + + @Input() shareProductsTemplate: any; + @Input() accountingRuleData: any; + @Input() shareProduct: any; + @Output() submit = new EventEmitter(); + + marketPriceDisplayedColumns: string[] = ['fromDate', 'shareValue']; + chargesDisplayedColumns: string[] = ['name', 'chargeCalculationType', 'amount', 'chargeTimeType']; + + constructor() { } + + ngOnInit() { + } + +} diff --git a/src/app/products/share-products/share-product-stepper/share-product-settings-step/share-product-settings-step.component.html b/src/app/products/share-products/share-product-stepper/share-product-settings-step/share-product-settings-step.component.html new file mode 100644 index 000000000..683d3d5a9 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-settings-step/share-product-settings-step.component.html @@ -0,0 +1,74 @@ +
+ +
+ +

Shares per Client

+ + + Minimum + + + + + Default + + + Default Shares per Client is required + + + + + Maximum + + + +

Minimum Active Period

+ + + Frequency + + + + + Type + + + {{ minimumActivePeriodFrequencyType.value }} + + + + +

Lock-in Period

+ + + Frequency + + + + + Type + + + {{ lockinPeriodFrequencyType.value }} + + + + + + Allow dividends for inactive clients + + +
+ +
+ + +
+ +
diff --git a/src/app/products/share-products/share-product-stepper/share-product-settings-step/share-product-settings-step.component.scss b/src/app/products/share-products/share-product-stepper/share-product-settings-step/share-product-settings-step.component.scss new file mode 100644 index 000000000..1a76350e8 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-settings-step/share-product-settings-step.component.scss @@ -0,0 +1,12 @@ +h4 { + font-weight: 500; + margin: 1em 0; +} + +.margin-t { + margin-top: 1em; +} + +.margin-v { + margin: 1em 0; +} diff --git a/src/app/products/share-products/share-product-stepper/share-product-settings-step/share-product-settings-step.component.spec.ts b/src/app/products/share-products/share-product-stepper/share-product-settings-step/share-product-settings-step.component.spec.ts new file mode 100644 index 000000000..27116348e --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-settings-step/share-product-settings-step.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ShareProductSettingsStepComponent } from './share-product-settings-step.component'; + +describe('ShareProductSettingsStepComponent', () => { + let component: ShareProductSettingsStepComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ShareProductSettingsStepComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ShareProductSettingsStepComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/products/share-products/share-product-stepper/share-product-settings-step/share-product-settings-step.component.ts b/src/app/products/share-products/share-product-stepper/share-product-settings-step/share-product-settings-step.component.ts new file mode 100644 index 000000000..45e235b5f --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-settings-step/share-product-settings-step.component.ts @@ -0,0 +1,44 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { FormGroup, FormBuilder, FormControl, Validators } from '@angular/forms'; + +@Component({ + selector: 'mifosx-share-product-settings-step', + templateUrl: './share-product-settings-step.component.html', + styleUrls: ['./share-product-settings-step.component.scss'] +}) +export class ShareProductSettingsStepComponent implements OnInit { + + @Input() shareProductsTemplate: any; + + shareProductSettingsForm: FormGroup; + + minimumActivePeriodFrequencyTypeData: any; + lockinPeriodFrequencyTypeData: any; + + constructor(private formBuilder: FormBuilder) { + this.createShareProductSettingsForm(); + } + + ngOnInit() { + this.minimumActivePeriodFrequencyTypeData = this.shareProductsTemplate.minimumActivePeriodFrequencyTypeOptions; + this.lockinPeriodFrequencyTypeData = this.shareProductsTemplate.lockinPeriodFrequencyTypeOptions; + } + + createShareProductSettingsForm() { + this.shareProductSettingsForm = this.formBuilder.group({ + 'minimumShares': [''], + 'nominalShares': ['', Validators.required], + 'maximumShares': [''], + 'minimumActivePeriodForDividends': [''], + 'minimumactiveperiodFrequencyType': [''], + 'lockinPeriodFrequency': [''], + 'lockinPeriodFrequencyType': [''], + 'allowDividendCalculationForInactiveClients': [false] + }); + } + + get shareProductSettings() { + return this.shareProductSettingsForm.value; + } + +} diff --git a/src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.html b/src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.html new file mode 100644 index 000000000..be7c17463 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.html @@ -0,0 +1,50 @@ +
+ +
+ + + Total Number of Shares + + + Total Number of Shares is required + + + + + Shares to be Issued + + + Shares to be Issued is required + + + + + Nominal/Unit Price + + + Nominal Price is required + + + + + Capital Value + + + Shares to be Issued * Nominal Price (Auto calculated) + + + +
+ +
+ + +
+ +
diff --git a/src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.scss b/src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.scss new file mode 100644 index 000000000..aa8d23226 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.scss @@ -0,0 +1,3 @@ +.margin-t { + margin-top: 1em; +} diff --git a/src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.spec.ts b/src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.spec.ts new file mode 100644 index 000000000..4720695fd --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ShareProductTermsStepComponent } from './share-product-terms-step.component'; + +describe('ShareProductTermsStepComponent', () => { + let component: ShareProductTermsStepComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ShareProductTermsStepComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ShareProductTermsStepComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.ts b/src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.ts new file mode 100644 index 000000000..bd90b3372 --- /dev/null +++ b/src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.ts @@ -0,0 +1,40 @@ +import { Component, OnInit } from '@angular/core'; +import { FormGroup, FormBuilder, Validators } from '@angular/forms'; +import { combineLatest } from 'rxjs'; + +@Component({ + selector: 'mifosx-share-product-terms-step', + templateUrl: './share-product-terms-step.component.html', + styleUrls: ['./share-product-terms-step.component.scss'] +}) +export class ShareProductTermsStepComponent implements OnInit { + + shareProductTermsForm: FormGroup; + + constructor(private formBuilder: FormBuilder) { + this.createShareProductTermsForm(); + } + + ngOnInit() { + combineLatest([ + this.shareProductTermsForm.get('sharesIssued').valueChanges, + this.shareProductTermsForm.get('unitPrice').valueChanges + ]).subscribe(([sharesIssued, unitPrice]: number[]) => { + this.shareProductTermsForm.get('shareCapital').setValue(sharesIssued * unitPrice); + }); + } + + createShareProductTermsForm() { + this.shareProductTermsForm = this.formBuilder.group({ + 'totalShares': ['', Validators.required], + 'sharesIssued': ['', Validators.required], + 'unitPrice': ['', Validators.required], + 'shareCapital': [''] + }); + } + + get shareProductTerms() { + return this.shareProductTermsForm.value; + } + +} diff --git a/src/app/products/share-products/share-products-template.resolver.ts b/src/app/products/share-products/share-products-template.resolver.ts new file mode 100644 index 000000000..3da6a495a --- /dev/null +++ b/src/app/products/share-products/share-products-template.resolver.ts @@ -0,0 +1,24 @@ +/** 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'; + +@Injectable() +export class ShareProductsTemplateResolver implements Resolve { + + constructor(private productsService: ProductsService) {} + + /** + * Returns the share products template data. + * @returns {Observable} + */ + resolve(): Observable { + return this.productsService.getShareProductsTemplate(); + } + +} diff --git a/src/app/products/share-products/share-products.component.html b/src/app/products/share-products/share-products.component.html index 2bd1af9cf..2cf8d7b57 100644 --- a/src/app/products/share-products/share-products.component.html +++ b/src/app/products/share-products/share-products.component.html @@ -1,5 +1,5 @@
- diff --git a/src/app/shared/form-dialog/formfield/formfield.component.html b/src/app/shared/form-dialog/formfield/formfield.component.html index 10b733e1a..10012f4a4 100644 --- a/src/app/shared/form-dialog/formfield/formfield.component.html +++ b/src/app/shared/form-dialog/formfield/formfield.component.html @@ -1,35 +1,43 @@
-
+
+ + -
- - + {{ formfield.label }} - {{ formfield.label }} + - + + + {{ option[formfield.options.label] }} + + - - - {{ option[formfield.options.label] }} - - + + {{ formfield.label }} is required + - - {{ formfield.label }} is required - - - -
- - - {{ formfield.label }} - +
-
\ No newline at end of file + + {{ formfield.label }} + + + + + {{ formfield.label }} is required + + + + + {{ formfield.label }} + + +
diff --git a/src/app/shared/form-dialog/formfield/model/datepicker-base.ts b/src/app/shared/form-dialog/formfield/model/datepicker-base.ts new file mode 100644 index 000000000..2c2404010 --- /dev/null +++ b/src/app/shared/form-dialog/formfield/model/datepicker-base.ts @@ -0,0 +1,15 @@ +import { FormfieldBase } from './formfield-base'; + +export class DatepickerBase extends FormfieldBase { + + controlType = 'datepicker'; + minDate: Date; + maxDate: Date; + + constructor(options: {} = {}) { + super(options); + this.minDate = options['minDate'] || new Date(2000, 0, 1); + this.maxDate = options['maxDate'] || new Date(); + } + +} diff --git a/src/app/shared/form-dialog/formfield/model/input-base.ts b/src/app/shared/form-dialog/formfield/model/input-base.ts index bd73ae318..5c728b875 100644 --- a/src/app/shared/form-dialog/formfield/model/input-base.ts +++ b/src/app/shared/form-dialog/formfield/model/input-base.ts @@ -5,7 +5,7 @@ export class InputBase extends FormfieldBase { controlType = 'input'; type: string; - constructor(options: any) { + constructor(options: {} = {}) { super(options); this.type = options['type'] || 'text'; }