feat: add create recurring deposit product component (#934)
Fixes: #193
This commit is contained in:
@@ -42,6 +42,7 @@ import { CreateTaxComponentComponent } from './manage-tax-components/create-tax-
|
|||||||
import { EditTaxComponentComponent } from './manage-tax-components/edit-tax-component/edit-tax-component.component';
|
import { EditTaxComponentComponent } from './manage-tax-components/edit-tax-component/edit-tax-component.component';
|
||||||
import { ViewTaxGroupComponent } from './manage-tax-groups/view-tax-group/view-tax-group.component';
|
import { ViewTaxGroupComponent } from './manage-tax-groups/view-tax-group/view-tax-group.component';
|
||||||
import { ShareProductsDividendsComponent } from './share-products/dividends-share-product/dividends.components';
|
import { ShareProductsDividendsComponent } from './share-products/dividends-share-product/dividends.components';
|
||||||
|
import { CreateRecurringDepositProductComponent } from './recurring-deposit-products/create-recurring-deposit-product/create-recurring-deposit-product.component';
|
||||||
|
|
||||||
/** Custom Resolvers */
|
/** Custom Resolvers */
|
||||||
import { LoanProductsResolver } from './loan-products/loan-products.resolver';
|
import { LoanProductsResolver } from './loan-products/loan-products.resolver';
|
||||||
@@ -301,7 +302,7 @@ const routes: Routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'recurring-deposit-products',
|
path: 'recurring-deposit-products',
|
||||||
data: { title: extract('Recurring Deposit Products'), breadcrumb: 'Recurring Deposit Products' },
|
data: { title: extract('Recurring Deposit Products'), breadcrumb: 'Recurring Deposit Products' },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
@@ -324,6 +325,14 @@ const routes: Routes = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'create',
|
||||||
|
component: CreateRecurringDepositProductComponent,
|
||||||
|
data: { title: extract('Create Recurring Deposit Product'), breadcrumb: 'Create' },
|
||||||
|
resolve: {
|
||||||
|
recurringDepositProductsTemplate: RecurringDepositProductsTemplateResolver
|
||||||
|
}
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
/** Angular Imports */
|
/** Angular Imports */
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { DatePipe, CommonModule } from '@angular/common';
|
import { DatePipe, CommonModule } from '@angular/common';
|
||||||
|
import { MatFormFieldModule, MatSelectModule, MatOptionModule } from '@angular/material';
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
|
||||||
/** Custom Modules */
|
/** Custom Modules */
|
||||||
import { SharedModule } from '../shared/shared.module';
|
import { SharedModule } from '../shared/shared.module';
|
||||||
import { ProductsRoutingModule } from './products-routing.module';
|
import { ProductsRoutingModule } from './products-routing.module';
|
||||||
import { PipesModule } from 'app/pipes/pipes.module';
|
import { PipesModule } from 'app/pipes/pipes.module';
|
||||||
|
import { DirectivesModule } from '../directives/directives.module';
|
||||||
|
|
||||||
/** Custom Components */
|
/** Custom Components */
|
||||||
import { ProductsComponent } from './products.component';
|
import { ProductsComponent } from './products.component';
|
||||||
@@ -71,11 +74,18 @@ import { FloatingRatePeriodDialogComponent } from './floating-rates/floating-rat
|
|||||||
import { CreateTaxComponentComponent } from './manage-tax-components/create-tax-component/create-tax-component.component';
|
import { CreateTaxComponentComponent } from './manage-tax-components/create-tax-component/create-tax-component.component';
|
||||||
import { EditTaxComponentComponent } from './manage-tax-components/edit-tax-component/edit-tax-component.component';
|
import { EditTaxComponentComponent } from './manage-tax-components/edit-tax-component/edit-tax-component.component';
|
||||||
import { EditChargeComponent } from './charges/edit-charge/edit-charge.component';
|
import { EditChargeComponent } from './charges/edit-charge/edit-charge.component';
|
||||||
import { MatFormFieldModule, MatSelectModule, MatOptionModule } from '@angular/material';
|
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
||||||
import { ViewTaxGroupComponent } from './manage-tax-groups/view-tax-group/view-tax-group.component';
|
import { ViewTaxGroupComponent } from './manage-tax-groups/view-tax-group/view-tax-group.component';
|
||||||
import { ShareProductsDividendsComponent } from './share-products/dividends-share-product/dividends.components';
|
import { ShareProductsDividendsComponent } from './share-products/dividends-share-product/dividends.components';
|
||||||
import { ViewRecurringDepositProductComponent } from './recurring-deposit-products/view-recurring-deposit-product/view-recurring-deposit-product.component';
|
import { ViewRecurringDepositProductComponent } from './recurring-deposit-products/view-recurring-deposit-product/view-recurring-deposit-product.component';
|
||||||
|
import { CreateRecurringDepositProductComponent } from './recurring-deposit-products/create-recurring-deposit-product/create-recurring-deposit-product.component';
|
||||||
|
import { RecurringDepositProductAccountingStepComponent } from './recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-accounting-step/recurring-deposit-product-accounting-step.component';
|
||||||
|
import { RecurringDepositProductChargesStepComponent } from './recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-charges-step/recurring-deposit-product-charges-step.component';
|
||||||
|
import { RecurringDepositProductCurrencyStepComponent } from './recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-currency-step/recurring-deposit-product-currency-step.component';
|
||||||
|
import { RecurringDepositProductDetailsStepComponent } from './recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-details-step/recurring-deposit-product-details-step.component';
|
||||||
|
import { RecurringDepositProductInterestRateChartStepComponent } from './recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-interest-rate-chart-step/recurring-deposit-product-interest-rate-chart-step.component';
|
||||||
|
import { RecurringDepositProductPreviewStepComponent } from './recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-preview-step/recurring-deposit-product-preview-step.component';
|
||||||
|
import { RecurringDepositProductSettingsStepComponent } from './recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-settings-step/recurring-deposit-product-settings-step.component';
|
||||||
|
import { RecurringDepositProductTermsStepComponent } from './recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-terms-step/recurring-deposit-product-terms-step.component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Products Module
|
* Products Module
|
||||||
@@ -86,7 +96,8 @@ import { ViewRecurringDepositProductComponent } from './recurring-deposit-produc
|
|||||||
imports: [
|
imports: [
|
||||||
SharedModule,
|
SharedModule,
|
||||||
ProductsRoutingModule,
|
ProductsRoutingModule,
|
||||||
PipesModule
|
PipesModule,
|
||||||
|
DirectivesModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
ProductsComponent,
|
ProductsComponent,
|
||||||
@@ -155,7 +166,16 @@ import { ViewRecurringDepositProductComponent } from './recurring-deposit-produc
|
|||||||
ViewTaxGroupComponent,
|
ViewTaxGroupComponent,
|
||||||
ShareProductsDividendsComponent,
|
ShareProductsDividendsComponent,
|
||||||
DepositProductIncentiveFormDialogComponent,
|
DepositProductIncentiveFormDialogComponent,
|
||||||
ViewRecurringDepositProductComponent
|
ViewRecurringDepositProductComponent,
|
||||||
|
CreateRecurringDepositProductComponent,
|
||||||
|
RecurringDepositProductAccountingStepComponent,
|
||||||
|
RecurringDepositProductChargesStepComponent,
|
||||||
|
RecurringDepositProductCurrencyStepComponent,
|
||||||
|
RecurringDepositProductDetailsStepComponent,
|
||||||
|
RecurringDepositProductInterestRateChartStepComponent,
|
||||||
|
RecurringDepositProductPreviewStepComponent,
|
||||||
|
RecurringDepositProductSettingsStepComponent,
|
||||||
|
RecurringDepositProductTermsStepComponent
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
DepositProductIncentiveFormDialogComponent,
|
DepositProductIncentiveFormDialogComponent,
|
||||||
|
|||||||
@@ -276,4 +276,9 @@ export class ProductsService {
|
|||||||
const httpParams = new HttpParams().set('productId', productId);
|
const httpParams = new HttpParams().set('productId', productId);
|
||||||
return this.http.get(`/interestratecharts`, {params: httpParams});
|
return this.http.get(`/interestratecharts`, {params: httpParams});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createRecurringDepositProduct(recurringDepositProduct: string): Observable<any> {
|
||||||
|
return this.http.post('/recurringdepositproducts', recurringDepositProduct);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+110
@@ -0,0 +1,110 @@
|
|||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<mat-horizontal-stepper class="mat-elevation-z8" labelPosition="bottom" #recurringDepositProductStepper>
|
||||||
|
|
||||||
|
<ng-template matStepperIcon="number">
|
||||||
|
<fa-icon icon="pencil-alt" size="sm"></fa-icon>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template matStepperIcon="edit">
|
||||||
|
<fa-icon icon="pencil-alt" size="sm"></fa-icon>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template matStepperIcon="done">
|
||||||
|
<fa-icon icon="check" size="sm"></fa-icon>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template matStepperIcon="error">
|
||||||
|
<fa-icon icon="exclamation-triangle" size="lg"></fa-icon>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template matStepperIcon="preview">
|
||||||
|
<fa-icon icon="eye" size="sm"></fa-icon>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<mat-step [stepControl]="recurringDepositProductDetailsForm">
|
||||||
|
|
||||||
|
<ng-template matStepLabel>DETAILS</ng-template>
|
||||||
|
|
||||||
|
<mifosx-recurring-deposit-product-details-step></mifosx-recurring-deposit-product-details-step>
|
||||||
|
|
||||||
|
</mat-step>
|
||||||
|
|
||||||
|
<mat-step [stepControl]="recurringDepositProductCurrencyForm">
|
||||||
|
|
||||||
|
<ng-template matStepLabel>CURRENCY</ng-template>
|
||||||
|
|
||||||
|
<mifosx-recurring-deposit-product-currency-step
|
||||||
|
[recurringDepositProductsTemplate]="recurringDepositProductsTemplate">
|
||||||
|
</mifosx-recurring-deposit-product-currency-step>
|
||||||
|
|
||||||
|
</mat-step>
|
||||||
|
|
||||||
|
<mat-step [stepControl]="recurringDepositProductTermsForm">
|
||||||
|
|
||||||
|
<ng-template matStepLabel>TERMS</ng-template>
|
||||||
|
|
||||||
|
<mifosx-recurring-deposit-product-terms-step
|
||||||
|
[recurringDepositProductsTemplate]="recurringDepositProductsTemplate">
|
||||||
|
</mifosx-recurring-deposit-product-terms-step>
|
||||||
|
|
||||||
|
</mat-step>
|
||||||
|
|
||||||
|
<mat-step [stepControl]="recurringDepositProductSettingsForm">
|
||||||
|
|
||||||
|
<ng-template matStepLabel>SETTINGS</ng-template>
|
||||||
|
|
||||||
|
<mifosx-recurring-deposit-product-settings-step
|
||||||
|
[recurringDepositProductsTemplate]="recurringDepositProductsTemplate">
|
||||||
|
</mifosx-recurring-deposit-product-settings-step>
|
||||||
|
|
||||||
|
</mat-step>
|
||||||
|
|
||||||
|
<mat-step [stepControl]="recurringDepositProductInterestRateChartForm">
|
||||||
|
|
||||||
|
<ng-template matStepLabel>INTEREST RATE CHART</ng-template>
|
||||||
|
|
||||||
|
<mifosx-recurring-deposit-product-interest-rate-chart-step
|
||||||
|
[recurringDepositProductsTemplate]="recurringDepositProductsTemplate">
|
||||||
|
</mifosx-recurring-deposit-product-interest-rate-chart-step>
|
||||||
|
|
||||||
|
</mat-step>
|
||||||
|
|
||||||
|
<mat-step>
|
||||||
|
|
||||||
|
<ng-template matStepLabel>CHARGES</ng-template>
|
||||||
|
|
||||||
|
<mifosx-recurring-deposit-product-charges-step
|
||||||
|
[recurringDepositProductsTemplate]="recurringDepositProductsTemplate"
|
||||||
|
[currencyCode]="recurringDepositProductCurrencyForm.get('currencyCode')">
|
||||||
|
</mifosx-recurring-deposit-product-charges-step>
|
||||||
|
|
||||||
|
</mat-step>
|
||||||
|
|
||||||
|
<mat-step [stepControl]="recurringDepositProductAccountingForm">
|
||||||
|
|
||||||
|
<ng-template matStepLabel>ACCOUNTING</ng-template>
|
||||||
|
|
||||||
|
<mifosx-recurring-deposit-product-accounting-step
|
||||||
|
[recurringDepositProductsTemplate]="recurringDepositProductsTemplate" [accountingRuleData]="accountingRuleData"
|
||||||
|
[recurringDepositProductFormValid]="recurringDepositProductFormValid">
|
||||||
|
</mifosx-recurring-deposit-product-accounting-step>
|
||||||
|
|
||||||
|
</mat-step>
|
||||||
|
|
||||||
|
<mat-step state="preview" *ngIf="recurringDepositProductFormValid" completed>
|
||||||
|
|
||||||
|
<ng-template matStepLabel>PREVIEW</ng-template>
|
||||||
|
|
||||||
|
<mifosx-recurring-deposit-product-preview-step
|
||||||
|
[recurringDepositProductsTemplate]="recurringDepositProductsTemplate"
|
||||||
|
[chartSlabsDisplayedColumns]="recurringDepositProductInterestRateChartStep.chartSlabsDisplayedColumns"
|
||||||
|
[accountingRuleData]="accountingRuleData" [recurringDepositProduct]="recurringDepositProduct"
|
||||||
|
(submit)="submit()">
|
||||||
|
</mifosx-recurring-deposit-product-preview-step>
|
||||||
|
|
||||||
|
</mat-step>
|
||||||
|
|
||||||
|
</mat-horizontal-stepper>
|
||||||
|
|
||||||
|
</div>
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { CreateRecurringDepositProductComponent } from './create-recurring-deposit-product.component';
|
||||||
|
|
||||||
|
describe('CreateRecurringDepositProductComponent', () => {
|
||||||
|
let component: CreateRecurringDepositProductComponent;
|
||||||
|
let fixture: ComponentFixture<CreateRecurringDepositProductComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ CreateRecurringDepositProductComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(CreateRecurringDepositProductComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
+107
@@ -0,0 +1,107 @@
|
|||||||
|
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||||
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
|
||||||
|
import { RecurringDepositProductDetailsStepComponent } from '../recurring-deposit-product-stepper/recurring-deposit-product-details-step/recurring-deposit-product-details-step.component';
|
||||||
|
import { RecurringDepositProductCurrencyStepComponent } from '../recurring-deposit-product-stepper/recurring-deposit-product-currency-step/recurring-deposit-product-currency-step.component';
|
||||||
|
import { RecurringDepositProductTermsStepComponent } from '../recurring-deposit-product-stepper/recurring-deposit-product-terms-step/recurring-deposit-product-terms-step.component';
|
||||||
|
import { RecurringDepositProductSettingsStepComponent } from '../recurring-deposit-product-stepper/recurring-deposit-product-settings-step/recurring-deposit-product-settings-step.component';
|
||||||
|
import { RecurringDepositProductInterestRateChartStepComponent } from '../recurring-deposit-product-stepper/recurring-deposit-product-interest-rate-chart-step/recurring-deposit-product-interest-rate-chart-step.component';
|
||||||
|
import { RecurringDepositProductChargesStepComponent } from '../recurring-deposit-product-stepper/recurring-deposit-product-charges-step/recurring-deposit-product-charges-step.component';
|
||||||
|
import { RecurringDepositProductAccountingStepComponent } from '../recurring-deposit-product-stepper/recurring-deposit-product-accounting-step/recurring-deposit-product-accounting-step.component';
|
||||||
|
|
||||||
|
import { ProductsService } from 'app/products/products.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-create-recurring-deposit-product',
|
||||||
|
templateUrl: './create-recurring-deposit-product.component.html',
|
||||||
|
styleUrls: ['./create-recurring-deposit-product.component.scss']
|
||||||
|
})
|
||||||
|
export class CreateRecurringDepositProductComponent implements OnInit {
|
||||||
|
|
||||||
|
@ViewChild(RecurringDepositProductDetailsStepComponent) recurringDepositProductDetailsStep: RecurringDepositProductDetailsStepComponent;
|
||||||
|
@ViewChild(RecurringDepositProductCurrencyStepComponent) recurringDepositProductCurrencyStep: RecurringDepositProductCurrencyStepComponent;
|
||||||
|
@ViewChild(RecurringDepositProductTermsStepComponent) recurringDepositProductTermsStep: RecurringDepositProductTermsStepComponent;
|
||||||
|
@ViewChild(RecurringDepositProductSettingsStepComponent) recurringDepositProductSettingsStep: RecurringDepositProductSettingsStepComponent;
|
||||||
|
@ViewChild(RecurringDepositProductInterestRateChartStepComponent) recurringDepositProductInterestRateChartStep: RecurringDepositProductInterestRateChartStepComponent;
|
||||||
|
@ViewChild(RecurringDepositProductChargesStepComponent) recurringDepositProductChargesStep: RecurringDepositProductChargesStepComponent;
|
||||||
|
@ViewChild(RecurringDepositProductAccountingStepComponent) recurringDepositProductAccountingStep: RecurringDepositProductAccountingStepComponent;
|
||||||
|
|
||||||
|
recurringDepositProductsTemplate: any;
|
||||||
|
accountingRuleData = ['None', 'Cash'];
|
||||||
|
|
||||||
|
constructor(private route: ActivatedRoute,
|
||||||
|
private productsService: ProductsService,
|
||||||
|
private router: Router) {
|
||||||
|
this.route.data.subscribe((data: { recurringDepositProductsTemplate: any }) => {
|
||||||
|
this.recurringDepositProductsTemplate = data.recurringDepositProductsTemplate;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
get recurringDepositProductDetailsForm() {
|
||||||
|
return this.recurringDepositProductDetailsStep.recurringDepositProductDetailsForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
get recurringDepositProductCurrencyForm() {
|
||||||
|
return this.recurringDepositProductCurrencyStep.recurringDepositProductCurrencyForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
get recurringDepositProductTermsForm() {
|
||||||
|
return this.recurringDepositProductTermsStep.recurringDepositProductTermsForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
get recurringDepositProductSettingsForm() {
|
||||||
|
return this.recurringDepositProductSettingsStep.recurringDepositProductSettingsForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
get recurringDepositProductInterestRateChartForm() {
|
||||||
|
return this.recurringDepositProductInterestRateChartStep.recurringDepositProductInterestRateChartForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
get recurringDepositProductAccountingForm() {
|
||||||
|
return this.recurringDepositProductAccountingStep.recurringDepositProductAccountingForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
get recurringDepositProductFormValid() {
|
||||||
|
return (
|
||||||
|
this.recurringDepositProductDetailsForm.valid &&
|
||||||
|
this.recurringDepositProductCurrencyForm.valid &&
|
||||||
|
this.recurringDepositProductTermsForm.valid &&
|
||||||
|
this.recurringDepositProductSettingsForm.valid &&
|
||||||
|
this.recurringDepositProductInterestRateChartForm.valid &&
|
||||||
|
this.recurringDepositProductAccountingForm.valid
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get recurringDepositProduct() {
|
||||||
|
return {
|
||||||
|
...this.recurringDepositProductDetailsStep.recurringDepositProductDetails,
|
||||||
|
...this.recurringDepositProductCurrencyStep.recurringDepositProductCurrency,
|
||||||
|
...this.recurringDepositProductTermsStep.recurringDepositProductTerms,
|
||||||
|
...this.recurringDepositProductSettingsStep.recurringDepositProductSettings,
|
||||||
|
...this.recurringDepositProductInterestRateChartStep.recurringDepositProductInterestRateChart,
|
||||||
|
...this.recurringDepositProductChargesStep.recurringDepositProductCharges,
|
||||||
|
...this.recurringDepositProductAccountingStep.recurringDepositProductAccounting
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
submit() {
|
||||||
|
// TODO: Update once language and date settings are setup
|
||||||
|
let recurringDepositProduct = {
|
||||||
|
...this.recurringDepositProduct,
|
||||||
|
charges: this.recurringDepositProduct.charges.map((charge: any) => ({ id: charge.id })),
|
||||||
|
locale: 'en' // locale required for depositAmount
|
||||||
|
};
|
||||||
|
if (!recurringDepositProduct.description) {
|
||||||
|
recurringDepositProduct.description = '';
|
||||||
|
}
|
||||||
|
delete recurringDepositProduct.advancedAccountingRules;
|
||||||
|
this.productsService.createRecurringDepositProduct(recurringDepositProduct)
|
||||||
|
.subscribe((response: any) => {
|
||||||
|
this.router.navigate(['../', response.resourceId], { relativeTo: this.route });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+264
@@ -0,0 +1,264 @@
|
|||||||
|
<form [formGroup]="recurringDepositProductAccountingForm">
|
||||||
|
|
||||||
|
<div fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||||
|
|
||||||
|
<mat-radio-group fxFlex="98%" fxLayout="row" fxLayoutGap="5%" fxLayout.lt-md="column"
|
||||||
|
formControlName="accountingRule">
|
||||||
|
<mat-radio-button *ngFor="let accountingRule of accountingRuleData; let i = index" [value]="i+1">
|
||||||
|
{{ accountingRule }}
|
||||||
|
</mat-radio-button>
|
||||||
|
</mat-radio-group>
|
||||||
|
|
||||||
|
<mat-divider fxFlex="98%"></mat-divider>
|
||||||
|
|
||||||
|
<div *ngIf="recurringDepositProductAccountingForm.value.accountingRule === 2" fxFlexFill fxLayout="row wrap"
|
||||||
|
fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||||
|
|
||||||
|
<h4 fxFlex="98%" class="mat-h4">Assets</h4>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Saving reference</mat-label>
|
||||||
|
<mat-select formControlName="savingsReferenceAccountId" required>
|
||||||
|
<mat-option *ngFor="let assetAccount of assetAccountData" [value]="assetAccount.id">
|
||||||
|
{{ assetAccount.name }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error>
|
||||||
|
Saving reference is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-divider fxFlex="98%"></mat-divider>
|
||||||
|
|
||||||
|
<h4 fxFlex="98%" class="mat-h4">Liabilities</h4>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Saving control</mat-label>
|
||||||
|
<mat-select formControlName="savingsControlAccountId" required>
|
||||||
|
<mat-option *ngFor="let liabilityAccount of liabilityAccountData" [value]="liabilityAccount.id">
|
||||||
|
{{ liabilityAccount.name }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error>
|
||||||
|
Saving control is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Savings transfers in suspense</mat-label>
|
||||||
|
<mat-select formControlName="transfersInSuspenseAccountId" required>
|
||||||
|
<mat-option *ngFor="let liabilityAccount of liabilityAccountData" [value]="liabilityAccount.id">
|
||||||
|
{{ liabilityAccount.name }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error>
|
||||||
|
Savings transfers in suspense is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-divider fxFlex="98%"></mat-divider>
|
||||||
|
|
||||||
|
<h4 fxFlex="98%" class="mat-h4">Expenses</h4>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Interest on savings</mat-label>
|
||||||
|
<mat-select formControlName="interestOnSavingsAccountId" required>
|
||||||
|
<mat-option *ngFor="let expenseAccount of expenseAccountData" [value]="expenseAccount.id">
|
||||||
|
{{ expenseAccount.name }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error>
|
||||||
|
Interest on savings is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-divider fxFlex="98%"></mat-divider>
|
||||||
|
|
||||||
|
<h4 fxFlex="98%" class="mat-h4">Income</h4>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Income from fees</mat-label>
|
||||||
|
<mat-select formControlName="incomeFromFeeAccountId" required>
|
||||||
|
<mat-option *ngFor="let incomeAccount of incomeAccountData" [value]="incomeAccount.id">
|
||||||
|
{{ incomeAccount.name }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error>
|
||||||
|
Income from fees Repayments is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Income from penalties</mat-label>
|
||||||
|
<mat-select formControlName="incomeFromPenaltyAccountId" required>
|
||||||
|
<mat-option *ngFor="let incomeAccount of incomeAccountData" [value]="incomeAccount.id">
|
||||||
|
{{ incomeAccount.name }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error>
|
||||||
|
Income from penalties is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-divider fxFlex="98%"></mat-divider>
|
||||||
|
|
||||||
|
<h3 fxFlex="23%" class="mat-h3">Advanced Accounting Rules</h3>
|
||||||
|
|
||||||
|
<mat-checkbox fxFlex="73%" formControlName="advancedAccountingRules"></mat-checkbox>
|
||||||
|
|
||||||
|
<div *ngIf="recurringDepositProductAccountingForm.value.advancedAccountingRules" fxFlexFill fxLayout="row wrap"
|
||||||
|
fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||||
|
|
||||||
|
<h4 fxFlex="33%" class="mat-h4">Configure Fund Sources for Payment Channels</h4>
|
||||||
|
|
||||||
|
<div fxFlex="63%">
|
||||||
|
<button type="button" mat-raised-button color="primary"
|
||||||
|
(click)="add('PaymentFundSource', paymentChannelToFundSourceMappings)">
|
||||||
|
<fa-icon icon="plus"></fa-icon>
|
||||||
|
Add
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table fxFlex="98%" class="mat-elevation-z1" mat-table [dataSource]="paymentChannelToFundSourceMappings.value"
|
||||||
|
*ngIf="paymentChannelToFundSourceMappings.value.length !== 0">
|
||||||
|
|
||||||
|
<ng-container matColumnDef="paymentTypeId">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Payment Type </th>
|
||||||
|
<td mat-cell *matCellDef="let paymentFundSource">
|
||||||
|
{{ paymentFundSource.paymentTypeId | find:paymentTypeData:'id':'name' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="fundSourceAccountId">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Fund Source </th>
|
||||||
|
<td mat-cell *matCellDef="let paymentFundSource">
|
||||||
|
{{ paymentFundSource.fundSourceAccountId | find:assetAccountData:'id':'name' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="actions">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Actions </th>
|
||||||
|
<td mat-cell *matCellDef="let paymentFundSource; let i = index">
|
||||||
|
<button mat-icon-button color="primary"
|
||||||
|
(click)="edit('PaymentFundSource', paymentChannelToFundSourceMappings, i)">
|
||||||
|
<fa-icon icon="edit"></fa-icon>
|
||||||
|
</button>
|
||||||
|
<button mat-icon-button color="warn" (click)="delete(paymentChannelToFundSourceMappings, i)">
|
||||||
|
<fa-icon icon="trash"></fa-icon>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="paymentFundSourceDisplayedColumns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: paymentFundSourceDisplayedColumns;"></tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h4 fxFlex="33%" class="mat-h4">Map Fees to Specific Income Accounts</h4>
|
||||||
|
|
||||||
|
<div fxFlex="63%">
|
||||||
|
<button type="button" mat-raised-button color="primary"
|
||||||
|
(click)="add('FeesIncome', feeToIncomeAccountMappings)">
|
||||||
|
<fa-icon icon="plus"></fa-icon>
|
||||||
|
Add
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table fxFlex="98%" class="mat-elevation-z1" mat-table [dataSource]="feeToIncomeAccountMappings.value"
|
||||||
|
*ngIf="feeToIncomeAccountMappings.value.length !== 0">
|
||||||
|
|
||||||
|
<ng-container matColumnDef="chargeId">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Fees </th>
|
||||||
|
<td mat-cell *matCellDef="let feesIncome">
|
||||||
|
{{ feesIncome.chargeId | find:chargeData:'id':'name' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="incomeAccountId">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Income Account </th>
|
||||||
|
<td mat-cell *matCellDef="let feesIncome">
|
||||||
|
{{ feesIncome.incomeAccountId | find:incomeAccountData:'id':'name' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="actions">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Actions </th>
|
||||||
|
<td mat-cell *matCellDef="let feesIncome; let i = index">
|
||||||
|
<button mat-icon-button color="primary" (click)="edit('FeesIncome', feeToIncomeAccountMappings, i)">
|
||||||
|
<fa-icon icon="edit"></fa-icon>
|
||||||
|
</button>
|
||||||
|
<button mat-icon-button color="warn" (click)="delete(feeToIncomeAccountMappings, i)">
|
||||||
|
<fa-icon icon="trash"></fa-icon>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns;"></tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h4 fxFlex="33%" class="mat-h4">Map Penalties to Specific Income Accounts</h4>
|
||||||
|
|
||||||
|
<div fxFlex="63%">
|
||||||
|
<button type="button" mat-raised-button color="primary"
|
||||||
|
(click)="add('PenaltyIncome', penaltyToIncomeAccountMappings)">
|
||||||
|
<fa-icon icon="plus"></fa-icon>
|
||||||
|
Add
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<table fxFlex="98%" class="mat-elevation-z1" mat-table [dataSource]="penaltyToIncomeAccountMappings.value"
|
||||||
|
*ngIf="penaltyToIncomeAccountMappings.value.length !== 0">
|
||||||
|
|
||||||
|
<ng-container matColumnDef="chargeId">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Penalty </th>
|
||||||
|
<td mat-cell *matCellDef="let penaltyIncome">
|
||||||
|
{{ penaltyIncome.chargeId | find:penaltyData:'id':'name' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="incomeAccountId">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Income Account </th>
|
||||||
|
<td mat-cell *matCellDef="let penaltyIncome">
|
||||||
|
{{ penaltyIncome.incomeAccountId | find:incomeAccountData:'id':'name' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="actions">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Actions </th>
|
||||||
|
<td mat-cell *matCellDef="let penaltyIncome; let i = index">
|
||||||
|
<button mat-icon-button color="primary"
|
||||||
|
(click)="edit('PenaltyIncome', penaltyToIncomeAccountMappings, i)">
|
||||||
|
<fa-icon icon="edit"></fa-icon>
|
||||||
|
</button>
|
||||||
|
<button mat-icon-button color="warn" (click)="delete(penaltyToIncomeAccountMappings, i)">
|
||||||
|
<fa-icon icon="trash"></fa-icon>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns;"></tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxLayout="row" class="margin-t" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="2%">
|
||||||
|
<button mat-raised-button matStepperPrevious>
|
||||||
|
<fa-icon icon="arrow-left"></fa-icon>
|
||||||
|
Previous
|
||||||
|
</button>
|
||||||
|
<button mat-raised-button matStepperNext [disabled]="!recurringDepositProductFormValid">
|
||||||
|
Next
|
||||||
|
<fa-icon icon="arrow-right"></fa-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-elevation-z1 {
|
||||||
|
margin: 1em 0 1.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3, h4 {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-radio-group, h4 {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-divider {
|
||||||
|
margin: 1em 0 2em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-t {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { RecurringDepositProductAccountingStepComponent } from './recurring-deposit-product-accounting-step.component';
|
||||||
|
|
||||||
|
describe('RecurringDepositProductAccountingStepComponent', () => {
|
||||||
|
let component: RecurringDepositProductAccountingStepComponent;
|
||||||
|
let fixture: ComponentFixture<RecurringDepositProductAccountingStepComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ RecurringDepositProductAccountingStepComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(RecurringDepositProductAccountingStepComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
+218
@@ -0,0 +1,218 @@
|
|||||||
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
|
import { FormGroup, FormBuilder, FormArray, Validators, FormControl } 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 { SelectBase } from 'app/shared/form-dialog/formfield/model/select-base';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-recurring-deposit-product-accounting-step',
|
||||||
|
templateUrl: './recurring-deposit-product-accounting-step.component.html',
|
||||||
|
styleUrls: ['./recurring-deposit-product-accounting-step.component.scss']
|
||||||
|
})
|
||||||
|
export class RecurringDepositProductAccountingStepComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input() recurringDepositProductsTemplate: any;
|
||||||
|
@Input() accountingRuleData: any;
|
||||||
|
@Input() recurringDepositProductFormValid: boolean;
|
||||||
|
|
||||||
|
recurringDepositProductAccountingForm: FormGroup;
|
||||||
|
|
||||||
|
chargeData: any;
|
||||||
|
penaltyData: any;
|
||||||
|
paymentTypeData: any;
|
||||||
|
assetAccountData: any;
|
||||||
|
incomeAccountData: any;
|
||||||
|
expenseAccountData: any;
|
||||||
|
liabilityAccountData: any;
|
||||||
|
|
||||||
|
paymentFundSourceDisplayedColumns: string[] = ['paymentTypeId', 'fundSourceAccountId', 'actions'];
|
||||||
|
feesPenaltyIncomeDisplayedColumns: string[] = ['chargeId', 'incomeAccountId', 'actions'];
|
||||||
|
|
||||||
|
constructor(private formBuilder: FormBuilder,
|
||||||
|
public dialog: MatDialog) {
|
||||||
|
this.createrecurringDepositProductAccountingForm();
|
||||||
|
this.setConditionalControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.chargeData = this.recurringDepositProductsTemplate.chargeOptions || [];
|
||||||
|
this.penaltyData = this.recurringDepositProductsTemplate.penaltyOptions || [];
|
||||||
|
this.paymentTypeData = this.recurringDepositProductsTemplate.paymentTypeOptions || [];
|
||||||
|
this.assetAccountData = this.recurringDepositProductsTemplate.accountingMappingOptions.assetAccountOptions || [];
|
||||||
|
this.incomeAccountData = this.recurringDepositProductsTemplate.accountingMappingOptions.incomeAccountOptions || [];
|
||||||
|
this.expenseAccountData = this.recurringDepositProductsTemplate.accountingMappingOptions.expenseAccountOptions || [];
|
||||||
|
this.liabilityAccountData = this.recurringDepositProductsTemplate.accountingMappingOptions.liabilityAccountOptions || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
createrecurringDepositProductAccountingForm() {
|
||||||
|
this.recurringDepositProductAccountingForm = this.formBuilder.group({
|
||||||
|
'accountingRule': [1]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setConditionalControls() {
|
||||||
|
this.recurringDepositProductAccountingForm.get('accountingRule').valueChanges
|
||||||
|
.subscribe((accountingRule: any) => {
|
||||||
|
if (accountingRule === 2) {
|
||||||
|
this.recurringDepositProductAccountingForm.addControl('savingsReferenceAccountId', new FormControl('', Validators.required));
|
||||||
|
this.recurringDepositProductAccountingForm.addControl('savingsControlAccountId', new FormControl('', Validators.required));
|
||||||
|
this.recurringDepositProductAccountingForm.addControl('transfersInSuspenseAccountId', new FormControl('', Validators.required));
|
||||||
|
this.recurringDepositProductAccountingForm.addControl('interestOnSavingsAccountId', new FormControl('', Validators.required));
|
||||||
|
this.recurringDepositProductAccountingForm.addControl('incomeFromFeeAccountId', new FormControl('', Validators.required));
|
||||||
|
this.recurringDepositProductAccountingForm.addControl('incomeFromPenaltyAccountId', new FormControl('', Validators.required));
|
||||||
|
this.recurringDepositProductAccountingForm.addControl('advancedAccountingRules', new FormControl(false));
|
||||||
|
|
||||||
|
this.recurringDepositProductAccountingForm.get('advancedAccountingRules').valueChanges
|
||||||
|
.subscribe((advancedAccountingRules: boolean) => {
|
||||||
|
if (advancedAccountingRules) {
|
||||||
|
this.recurringDepositProductAccountingForm.addControl('paymentChannelToFundSourceMappings', this.formBuilder.array([]));
|
||||||
|
this.recurringDepositProductAccountingForm.addControl('feeToIncomeAccountMappings', this.formBuilder.array([]));
|
||||||
|
this.recurringDepositProductAccountingForm.addControl('penaltyToIncomeAccountMappings', this.formBuilder.array([]));
|
||||||
|
} else {
|
||||||
|
this.recurringDepositProductAccountingForm.removeControl('paymentChannelToFundSourceMappings');
|
||||||
|
this.recurringDepositProductAccountingForm.removeControl('feeToIncomeAccountMappings');
|
||||||
|
this.recurringDepositProductAccountingForm.removeControl('penaltyToIncomeAccountMappings');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.recurringDepositProductAccountingForm.removeControl('savingsReferenceAccountId');
|
||||||
|
this.recurringDepositProductAccountingForm.removeControl('overdraftPortfolioControlId');
|
||||||
|
this.recurringDepositProductAccountingForm.removeControl('savingsControlAccountId');
|
||||||
|
this.recurringDepositProductAccountingForm.removeControl('transfersInSuspenseAccountId');
|
||||||
|
this.recurringDepositProductAccountingForm.removeControl('interestOnSavingsAccountId');
|
||||||
|
this.recurringDepositProductAccountingForm.removeControl('writeOffAccountId');
|
||||||
|
this.recurringDepositProductAccountingForm.removeControl('incomeFromFeeAccountId');
|
||||||
|
this.recurringDepositProductAccountingForm.removeControl('incomeFromPenaltyAccountId');
|
||||||
|
this.recurringDepositProductAccountingForm.removeControl('incomeFromInterestId');
|
||||||
|
this.recurringDepositProductAccountingForm.removeControl('advancedAccountingRules');
|
||||||
|
this.recurringDepositProductAccountingForm.removeControl('escheatLiabilityId');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get paymentChannelToFundSourceMappings(): FormArray {
|
||||||
|
return this.recurringDepositProductAccountingForm.get('paymentChannelToFundSourceMappings') as FormArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
get feeToIncomeAccountMappings(): FormArray {
|
||||||
|
return this.recurringDepositProductAccountingForm.get('feeToIncomeAccountMappings') as FormArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
get penaltyToIncomeAccountMappings(): FormArray {
|
||||||
|
return this.recurringDepositProductAccountingForm.get('penaltyToIncomeAccountMappings') as FormArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
add(formType: string, formArray: FormArray) {
|
||||||
|
const data = { ...this.getData(formType), pristine: false };
|
||||||
|
const dialogRef = this.dialog.open(FormDialogComponent, { data });
|
||||||
|
dialogRef.afterClosed().subscribe((response: any) => {
|
||||||
|
if (response.data) {
|
||||||
|
formArray.push(response.data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
edit(formType: string, formArray: FormArray, index: number) {
|
||||||
|
const data = { ...this.getData(formType, formArray.at(index).value), layout: { addButtonText: 'Edit' } };
|
||||||
|
const dialogRef = this.dialog.open(FormDialogComponent, { data });
|
||||||
|
dialogRef.afterClosed().subscribe((response: any) => {
|
||||||
|
if (response.data) {
|
||||||
|
formArray.at(index).patchValue(response.data.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(formArray: FormArray, index: number) {
|
||||||
|
const dialogRef = this.dialog.open(DeleteDialogComponent, {
|
||||||
|
data: { deleteContext: `this` }
|
||||||
|
});
|
||||||
|
dialogRef.afterClosed().subscribe((response: any) => {
|
||||||
|
if (response.delete) {
|
||||||
|
formArray.removeAt(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getData(formType: string, values?: any) {
|
||||||
|
switch (formType) {
|
||||||
|
case 'PaymentFundSource': return { title: 'Configure Fund Sources for Payment Channels', formfields: this.getPaymentFundSourceFormfields(values) };
|
||||||
|
case 'FeesIncome': return { title: 'Map Fees to Income Accounts', formfields: this.getFeesIncomeFormfields(values) };
|
||||||
|
case 'PenaltyIncome': return { title: 'Map Penalties to Specific Income Accounts', formfields: this.getPenaltyIncomeFormfields(values) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getPaymentFundSourceFormfields(values?: any) {
|
||||||
|
const formfields: FormfieldBase[] = [
|
||||||
|
new SelectBase({
|
||||||
|
controlName: 'paymentTypeId',
|
||||||
|
label: 'Payment Type',
|
||||||
|
value: values ? values.paymentTypeId : this.paymentTypeData[0].id,
|
||||||
|
options: { label: 'name', value: 'id', data: this.paymentTypeData },
|
||||||
|
required: true,
|
||||||
|
order: 1
|
||||||
|
}),
|
||||||
|
new SelectBase({
|
||||||
|
controlName: 'fundSourceAccountId',
|
||||||
|
label: 'Fund Source',
|
||||||
|
value: values ? values.fundSourceAccountId : this.assetAccountData[0].id,
|
||||||
|
options: { label: 'name', value: 'id', data: this.assetAccountData },
|
||||||
|
required: true,
|
||||||
|
order: 2
|
||||||
|
})
|
||||||
|
];
|
||||||
|
return formfields;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFeesIncomeFormfields(values?: any) {
|
||||||
|
const formfields: FormfieldBase[] = [
|
||||||
|
new SelectBase({
|
||||||
|
controlName: 'chargeId',
|
||||||
|
label: 'Fees',
|
||||||
|
value: values ? values.chargeId : this.chargeData[0].id,
|
||||||
|
options: { label: 'name', value: 'id', data: this.chargeData },
|
||||||
|
required: true,
|
||||||
|
order: 1
|
||||||
|
}),
|
||||||
|
new SelectBase({
|
||||||
|
controlName: 'incomeAccountId',
|
||||||
|
label: 'Income Account',
|
||||||
|
value: values ? values.incomeAccountId : this.incomeAccountData[0].id,
|
||||||
|
options: { label: 'name', value: 'id', data: this.incomeAccountData },
|
||||||
|
required: true,
|
||||||
|
order: 2
|
||||||
|
})
|
||||||
|
];
|
||||||
|
return formfields;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPenaltyIncomeFormfields(values?: any) {
|
||||||
|
const formfields: FormfieldBase[] = [
|
||||||
|
new SelectBase({
|
||||||
|
controlName: 'chargeId',
|
||||||
|
label: 'Penalty',
|
||||||
|
value: values ? values.chargeId : this.penaltyData[0].id,
|
||||||
|
options: { label: 'name', value: 'id', data: this.penaltyData },
|
||||||
|
required: true,
|
||||||
|
order: 1
|
||||||
|
}),
|
||||||
|
new SelectBase({
|
||||||
|
controlName: 'incomeAccountId',
|
||||||
|
label: 'Income Account',
|
||||||
|
value: values ? values.incomeAccountId : this.incomeAccountData[0].id,
|
||||||
|
options: { label: 'name', value: 'id', data: this.incomeAccountData },
|
||||||
|
required: true,
|
||||||
|
order: 2
|
||||||
|
})
|
||||||
|
];
|
||||||
|
return formfields;
|
||||||
|
}
|
||||||
|
|
||||||
|
get recurringDepositProductAccounting() {
|
||||||
|
return this.recurringDepositProductAccountingForm.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+76
@@ -0,0 +1,76 @@
|
|||||||
|
<div fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Charge</mat-label>
|
||||||
|
<mat-select #charge>
|
||||||
|
<mat-option *ngFor="let charge of chargeData | chargesFilter:chargesDataSource:currencyCode.value"
|
||||||
|
[value]="charge">
|
||||||
|
{{ charge.name }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<div fxFlex="48%" fxFlexAlign="center">
|
||||||
|
<button type="button" mat-raised-button color="primary" (click)="addCharge(charge)" [disabled]="!charge.value">
|
||||||
|
<fa-icon icon="plus"></fa-icon>
|
||||||
|
Add
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table fxFlex="98%" class="mat-elevation-z1" mat-table [dataSource]="chargesDataSource"
|
||||||
|
[hidden]="chargesDataSource.length === 0">
|
||||||
|
|
||||||
|
<ng-container matColumnDef="name">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Name </th>
|
||||||
|
<td mat-cell *matCellDef="let charge">
|
||||||
|
{{ charge.name + ', ' + charge.currency.displaySymbol }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="chargeCalculationType">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Type </th>
|
||||||
|
<td mat-cell *matCellDef="let charge">
|
||||||
|
{{ charge.chargeCalculationType.value }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="amount">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Amount </th>
|
||||||
|
<td mat-cell *matCellDef="let charge">
|
||||||
|
{{ charge.amount }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="chargeTimeType">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Collected On </th>
|
||||||
|
<td mat-cell *matCellDef="let charge">
|
||||||
|
{{ charge.chargeTimeType.value }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="action">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Actions </th>
|
||||||
|
<td mat-cell *matCellDef="let charge">
|
||||||
|
<button mat-icon-button color="warn" (click)="deleteCharge(charge)">
|
||||||
|
<fa-icon icon="trash"></fa-icon>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxLayout="row" class="margin-t" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="2%">
|
||||||
|
<button mat-raised-button matStepperPrevious>
|
||||||
|
<fa-icon icon="arrow-left"></fa-icon>
|
||||||
|
Previous
|
||||||
|
</button>
|
||||||
|
<button mat-raised-button matStepperNext>
|
||||||
|
Next
|
||||||
|
<fa-icon icon="arrow-right"></fa-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-elevation-z1 {
|
||||||
|
margin: 1em 0 1.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-t {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { RecurringDepositProductChargesStepComponent } from './recurring-deposit-product-charges-step.component';
|
||||||
|
|
||||||
|
describe('RecurringDepositProductChargesStepComponent', () => {
|
||||||
|
let component: RecurringDepositProductChargesStepComponent;
|
||||||
|
let fixture: ComponentFixture<RecurringDepositProductChargesStepComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ RecurringDepositProductChargesStepComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(RecurringDepositProductChargesStepComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
+56
@@ -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-recurring-deposit-product-charges-step',
|
||||||
|
templateUrl: './recurring-deposit-product-charges-step.component.html',
|
||||||
|
styleUrls: ['./recurring-deposit-product-charges-step.component.scss']
|
||||||
|
})
|
||||||
|
export class RecurringDepositProductChargesStepComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input() recurringDepositProductsTemplate: any;
|
||||||
|
@Input() currencyCode: FormControl;
|
||||||
|
|
||||||
|
chargeData: any;
|
||||||
|
|
||||||
|
chargesDataSource: {}[];
|
||||||
|
displayedColumns: string[] = ['name', 'chargeCalculationType', 'amount', 'chargeTimeType', 'action'];
|
||||||
|
|
||||||
|
constructor(public dialog: MatDialog) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.chargeData = this.recurringDepositProductsTemplate.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 recurringDepositProductCharges() {
|
||||||
|
return {
|
||||||
|
charges: this.chargesDataSource
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
<form [formGroup]="recurringDepositProductCurrencyForm">
|
||||||
|
|
||||||
|
<div fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Currency</mat-label>
|
||||||
|
<mat-select formControlName="currencyCode" required>
|
||||||
|
<mat-option *ngFor="let currency of currencyData" [value]="currency.code">
|
||||||
|
{{ currency.name }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error>
|
||||||
|
Currency is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Decimal Places</mat-label>
|
||||||
|
<input type="number" matInput formControlName="digitsAfterDecimal" required>
|
||||||
|
<mat-error>
|
||||||
|
Decimal Places is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Currency in multiples of</mat-label>
|
||||||
|
<input type="number" matInput formControlName="inMultiplesOf" required>
|
||||||
|
<mat-error>
|
||||||
|
Currency in multiples of is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxLayout="row" class="margin-t" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="2%">
|
||||||
|
<button mat-raised-button matStepperPrevious>
|
||||||
|
<fa-icon icon="arrow-left"></fa-icon>
|
||||||
|
Previous
|
||||||
|
</button>
|
||||||
|
<button mat-raised-button matStepperNext>
|
||||||
|
Next
|
||||||
|
<fa-icon icon="arrow-right"></fa-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
.margin-t {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { RecurringDepositProductCurrencyStepComponent } from './recurring-deposit-product-currency-step.component';
|
||||||
|
|
||||||
|
describe('RecurringDepositProductCurrencyStepComponent', () => {
|
||||||
|
let component: RecurringDepositProductCurrencyStepComponent;
|
||||||
|
let fixture: ComponentFixture<RecurringDepositProductCurrencyStepComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ RecurringDepositProductCurrencyStepComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(RecurringDepositProductCurrencyStepComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
|
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-recurring-deposit-product-currency-step',
|
||||||
|
templateUrl: './recurring-deposit-product-currency-step.component.html',
|
||||||
|
styleUrls: ['./recurring-deposit-product-currency-step.component.scss']
|
||||||
|
})
|
||||||
|
export class RecurringDepositProductCurrencyStepComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input() recurringDepositProductsTemplate: any;
|
||||||
|
|
||||||
|
recurringDepositProductCurrencyForm: FormGroup;
|
||||||
|
|
||||||
|
currencyData: any;
|
||||||
|
|
||||||
|
constructor(private formBuilder: FormBuilder) {
|
||||||
|
this.createrecurringDepositProductCurrencyForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.currencyData = this.recurringDepositProductsTemplate.currencyOptions;
|
||||||
|
|
||||||
|
this.recurringDepositProductCurrencyForm.patchValue({
|
||||||
|
'currencyCode': this.currencyData[0].code,
|
||||||
|
'digitsAfterDecimal': 2
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createrecurringDepositProductCurrencyForm() {
|
||||||
|
this.recurringDepositProductCurrencyForm = this.formBuilder.group({
|
||||||
|
'currencyCode': ['', Validators.required],
|
||||||
|
'digitsAfterDecimal': ['', Validators.required],
|
||||||
|
'inMultiplesOf': ['', Validators.required]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get recurringDepositProductCurrency() {
|
||||||
|
return this.recurringDepositProductCurrencyForm.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
<form [formGroup]="recurringDepositProductDetailsForm">
|
||||||
|
|
||||||
|
<div fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Product Name</mat-label>
|
||||||
|
<input matInput formControlName="name" required>
|
||||||
|
<mat-error>
|
||||||
|
Product Name is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Short Name</mat-label>
|
||||||
|
<input matInput formControlName="shortName" maxlength="4" required>
|
||||||
|
<mat-error>
|
||||||
|
Short Name is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="98%">
|
||||||
|
<mat-label>Description</mat-label>
|
||||||
|
<textarea matInput formControlName="description"></textarea>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxLayout="row" class="margin-t" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="2%">
|
||||||
|
<button mat-raised-button matStepperPrevious disabled>
|
||||||
|
<fa-icon icon="arrow-left"></fa-icon>
|
||||||
|
Previous
|
||||||
|
</button>
|
||||||
|
<button mat-raised-button matStepperNext>
|
||||||
|
Next
|
||||||
|
<fa-icon icon="arrow-right"></fa-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
.margin-t {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { RecurringDepositProductDetailsStepComponent } from './recurring-deposit-product-details-step.component';
|
||||||
|
|
||||||
|
describe('RecurringDepositProductDetailsStepComponent', () => {
|
||||||
|
let component: RecurringDepositProductDetailsStepComponent;
|
||||||
|
let fixture: ComponentFixture<RecurringDepositProductDetailsStepComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ RecurringDepositProductDetailsStepComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(RecurringDepositProductDetailsStepComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-recurring-deposit-product-details-step',
|
||||||
|
templateUrl: './recurring-deposit-product-details-step.component.html',
|
||||||
|
styleUrls: ['./recurring-deposit-product-details-step.component.scss']
|
||||||
|
})
|
||||||
|
export class RecurringDepositProductDetailsStepComponent implements OnInit {
|
||||||
|
|
||||||
|
recurringDepositProductDetailsForm: FormGroup;
|
||||||
|
|
||||||
|
constructor(private formBuilder: FormBuilder) {
|
||||||
|
this.createrecurringDepositProductDetailsForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
createrecurringDepositProductDetailsForm() {
|
||||||
|
this.recurringDepositProductDetailsForm = this.formBuilder.group({
|
||||||
|
'name': ['', Validators.required],
|
||||||
|
'shortName': ['', Validators.required],
|
||||||
|
'description': ['']
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get recurringDepositProductDetails() {
|
||||||
|
return this.recurringDepositProductDetailsForm.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+225
@@ -0,0 +1,225 @@
|
|||||||
|
<form [formGroup]="recurringDepositProductInterestRateChartForm">
|
||||||
|
|
||||||
|
<div fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||||
|
|
||||||
|
<h3 fxFlex="13%" class="mat-h3">Interest Rate Charts</h3>
|
||||||
|
|
||||||
|
<div fxFlex="83%" fxLayout="row" fxLayoutAlign="start center">
|
||||||
|
<button type="button" mat-raised-button color="primary" (click)="addChart()">
|
||||||
|
<fa-icon icon="plus"></fa-icon>
|
||||||
|
Add
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column" formArrayName="charts" *ngFor="let chart of charts.controls; let chartIndex = index">
|
||||||
|
|
||||||
|
<mat-divider fxFlex="98%"></mat-divider>
|
||||||
|
|
||||||
|
<div fxFlexFill fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column" [formGroupName]="chartIndex">
|
||||||
|
|
||||||
|
<div fxFlex="98%" fxLayout="row" fxLayoutAlign="end center">
|
||||||
|
<button type="button" mat-icon-button color="warn" (click)="delete(charts, chartIndex)" matTooltip="Delete Interest Rate Chart" matTooltipPosition="left">
|
||||||
|
<fa-icon icon="trash"></fa-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="32%">
|
||||||
|
<mat-label>Name</mat-label>
|
||||||
|
<input matInput formControlName="name">
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="31%">
|
||||||
|
<mat-label>Valid from Date</mat-label>
|
||||||
|
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="validFromDatePicker" formControlName="fromDate" required>
|
||||||
|
<mat-datepicker-toggle matSuffix [for]="validFromDatePicker"></mat-datepicker-toggle>
|
||||||
|
<mat-datepicker #validFromDatePicker></mat-datepicker>
|
||||||
|
<mat-error>
|
||||||
|
Valid from Date is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="31%">
|
||||||
|
<mat-label>End Date</mat-label>
|
||||||
|
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="endDatePicker" formControlName="endDate">
|
||||||
|
<mat-datepicker-toggle matSuffix [for]="endDatePicker"></mat-datepicker-toggle>
|
||||||
|
<mat-datepicker #endDatePicker></mat-datepicker>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="65%">
|
||||||
|
<mat-label>Description</mat-label>
|
||||||
|
<textarea matInput formControlName="description"></textarea>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<div fxFlex="31%" fxLayout="row" fxLayoutAlign="space-between center">
|
||||||
|
<mat-checkbox labelPosition="before" formControlName="isPrimaryGroupingByAmount">
|
||||||
|
Is primary grouping by amount?
|
||||||
|
</mat-checkbox>
|
||||||
|
<button type="button" mat-raised-button color="primary" (click)="addChartSlab(chart.controls.chartSlabs)">
|
||||||
|
<fa-icon icon="plus"></fa-icon>
|
||||||
|
Add Slab
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table fxFlex="98%" class="mat-elevation-z1" mat-table [dataSource]="chart.value.chartSlabs" *ngIf="chart.value.chartSlabs.length !== 0" multiTemplateDataRows>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="period">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Period </th>
|
||||||
|
<td mat-cell *matCellDef="let chartSlab">
|
||||||
|
{{ chartSlab.fromPeriod + ' - ' + chartSlab.toPeriod + ' ' + (chartSlab.periodType | find:periodTypeData:'id':'value') }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="amountRange">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Amount Range </th>
|
||||||
|
<td mat-cell *matCellDef="let chartSlab">
|
||||||
|
{{ chartSlab.amountRangeFrom + ' - ' + chartSlab.amountRangeTo }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="annualInterestRate">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Interest </th>
|
||||||
|
<td mat-cell *matCellDef="let chartSlab">
|
||||||
|
{{ chartSlab.annualInterestRate }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="description">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Description </th>
|
||||||
|
<td mat-cell *matCellDef="let chartSlab">
|
||||||
|
{{ chartSlab.description }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="actions">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Actions </th>
|
||||||
|
<td mat-cell *matCellDef="let chartSlab; let chartSlabIndex = dataIndex">
|
||||||
|
<button mat-icon-button color="primary" (click)="editChartSlab(chart.controls.chartSlabs, chartSlabIndex)">
|
||||||
|
<fa-icon icon="edit"></fa-icon>
|
||||||
|
</button>
|
||||||
|
<button mat-icon-button color="warn" (click)="delete(chart.controls.chartSlabs, chartSlabIndex)">
|
||||||
|
<fa-icon icon="trash"></fa-icon>
|
||||||
|
</button>
|
||||||
|
<button mat-button color="primary" (click)="expandChartSlabIndex[chartIndex] = expandChartSlabIndex[chartIndex] === chartSlabIndex ? null : chartSlabIndex">
|
||||||
|
<span *ngIf="expandChartSlabIndex[chartIndex] !== chartSlabIndex">
|
||||||
|
<fa-icon icon="eye"></fa-icon>
|
||||||
|
View Incentives
|
||||||
|
</span>
|
||||||
|
<span *ngIf="expandChartSlabIndex[chartIndex] === chartSlabIndex">
|
||||||
|
<fa-icon icon="eye-slash"></fa-icon>
|
||||||
|
Hide Incentives
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="incentives">
|
||||||
|
<td mat-cell *matCellDef="let chartSlab; let chartSlabIndex = dataIndex" [attr.colspan]="chartSlabsDisplayedColumns[chartIndex].length">
|
||||||
|
|
||||||
|
<div fxLayout="row wrap" fxFlexFill class="incentives" [@expandChartSlab]="chartSlabIndex === expandChartSlabIndex[chartIndex] ? 'expanded' : 'collapsed'">
|
||||||
|
|
||||||
|
<mat-card fxLayout="row wrap" fxFlexFill>
|
||||||
|
|
||||||
|
<h4 class="mat-h4" fxFlex="13%">
|
||||||
|
Incentives
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<div fxFlex="83%">
|
||||||
|
<button mat-raised-button color="primary" (click)="addIncentive(getIncentives(chart.controls.chartSlabs, chartSlabIndex))">
|
||||||
|
<fa-icon icon="plus"></fa-icon>
|
||||||
|
Add
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="chartSlab.incentives" *ngIf="chartSlab.incentives.length">
|
||||||
|
|
||||||
|
<ng-container matColumnDef="entityType">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Entity Type </th>
|
||||||
|
<td mat-cell *matCellDef="let incentive">
|
||||||
|
{{ incentive.entityType | find:entityTypeData:'id':'value' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="attributeName">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Attribute Name </th>
|
||||||
|
<td mat-cell *matCellDef="let incentive">
|
||||||
|
{{ incentive.attributeName | find:attributeNameData:'id':'value' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="conditionType">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Condition Type </th>
|
||||||
|
<td mat-cell *matCellDef="let incentive">
|
||||||
|
{{ incentive.conditionType | find:conditionTypeData:'id':'value' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="attributeValue">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Attribute Value </th>
|
||||||
|
<td mat-cell *matCellDef="let incentive" [ngSwitch]="incentive.attributeName">
|
||||||
|
<span *ngSwitchCase="2">{{ incentive.attributeValue | find:genderData:'id':'name' }}</span>
|
||||||
|
<span *ngSwitchCase="3">{{ incentive.attributeValue }}</span>
|
||||||
|
<span *ngSwitchCase="4">{{ incentive.attributeValue | find:clientTypeData:'id':'name' }}</span>
|
||||||
|
<span *ngSwitchCase="5">{{ incentive.attributeValue | find:clientClassificationData:'id':'name' }}</span>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="incentiveType">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Incentive Type </th>
|
||||||
|
<td mat-cell *matCellDef="let incentive">
|
||||||
|
{{ incentive.incentiveType | find:incentiveTypeData:'id':'value'}}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="amount">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Interest </th>
|
||||||
|
<td mat-cell *matCellDef="let incentive">
|
||||||
|
{{ incentive.amount }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="actions">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Actions </th>
|
||||||
|
<td mat-cell *matCellDef="let incentive; let incentiveIndex = index">
|
||||||
|
<button mat-icon-button color="primary" (click)="editIncentive(getIncentives(chart.controls.chartSlabs, chartSlabIndex), incentiveIndex)">
|
||||||
|
<fa-icon icon="edit"></fa-icon>
|
||||||
|
</button>
|
||||||
|
<button mat-icon-button color="warn" (click)="delete(getIncentives(chart.controls.chartSlabs, chartSlabIndex), incentiveIndex)">
|
||||||
|
<fa-icon icon="trash"></fa-icon>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="incentivesDisplayedColumns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: incentivesDisplayedColumns;"></tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="chartSlabsDisplayedColumns[chartIndex]"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: chartSlabsDisplayedColumns[chartIndex];"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: chartSlabsIncentivesDisplayedColumns;" class="incentives-row"></tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxLayout="row" class="margin-t" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="2%">
|
||||||
|
<button mat-raised-button matStepperPrevious disabled>
|
||||||
|
<fa-icon icon="arrow-left"></fa-icon>
|
||||||
|
Previous
|
||||||
|
</button>
|
||||||
|
<button mat-raised-button matStepperNext>
|
||||||
|
Next
|
||||||
|
<fa-icon icon="arrow-right"></fa-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
tr.incentives-row {
|
||||||
|
height: 0;
|
||||||
|
|
||||||
|
> td {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.incentives {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-card {
|
||||||
|
border-radius: 0;
|
||||||
|
|
||||||
|
> h4 {
|
||||||
|
margin: 0.5em 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-divider {
|
||||||
|
margin: 1em 0 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-elevation-z1 {
|
||||||
|
margin: 1em 0 1.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3, h4 {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3, h4 {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-t {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-v {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { RecurringDepositProductInterestRateChartStepComponent } from './recurring-deposit-product-interest-rate-chart-step.component';
|
||||||
|
|
||||||
|
describe('RecurringDepositProductInterestRateChartStepComponent', () => {
|
||||||
|
let component: RecurringDepositProductInterestRateChartStepComponent;
|
||||||
|
let fixture: ComponentFixture<RecurringDepositProductInterestRateChartStepComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ RecurringDepositProductInterestRateChartStepComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(RecurringDepositProductInterestRateChartStepComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
+244
@@ -0,0 +1,244 @@
|
|||||||
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
|
import { FormGroup, FormBuilder, Validators, FormArray } from '@angular/forms';
|
||||||
|
import { DatePipe } from '@angular/common';
|
||||||
|
import { MatDialog } from '@angular/material';
|
||||||
|
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||||
|
|
||||||
|
import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component';
|
||||||
|
import { DepositProductIncentiveFormDialogComponent } from 'app/products/deposit-product-incentive-form-dialog/deposit-product-incentive-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 { SelectBase } from 'app/shared/form-dialog/formfield/model/select-base';
|
||||||
|
import { InputBase } from 'app/shared/form-dialog/formfield/model/input-base';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-recurring-deposit-product-interest-rate-chart-step',
|
||||||
|
templateUrl: './recurring-deposit-product-interest-rate-chart-step.component.html',
|
||||||
|
styleUrls: ['./recurring-deposit-product-interest-rate-chart-step.component.scss'],
|
||||||
|
animations: [
|
||||||
|
trigger('expandChartSlab', [
|
||||||
|
state('collapsed', style({ height: '0px', minHeight: '0' })),
|
||||||
|
state('expanded', style({ height: '*' })),
|
||||||
|
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)'))
|
||||||
|
])
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class RecurringDepositProductInterestRateChartStepComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input() recurringDepositProductsTemplate: any;
|
||||||
|
|
||||||
|
recurringDepositProductInterestRateChartForm: FormGroup;
|
||||||
|
|
||||||
|
periodTypeData: any;
|
||||||
|
entityTypeData: any;
|
||||||
|
attributeNameData: any;
|
||||||
|
conditionTypeData: any;
|
||||||
|
genderData: any;
|
||||||
|
clientTypeData: any;
|
||||||
|
clientClassificationData: any;
|
||||||
|
incentiveTypeData: any;
|
||||||
|
|
||||||
|
chartSlabsDisplayedColumns: any[] = [];
|
||||||
|
chartSlabsIncentivesDisplayedColumns: string[] = ['incentives'];
|
||||||
|
incentivesDisplayedColumns: string[] = ['entityType', 'attributeName', 'conditionType', 'attributeValue', 'incentiveType', 'amount', 'actions'];
|
||||||
|
|
||||||
|
minDate = new Date(2000, 0, 1);
|
||||||
|
maxDate = new Date(new Date().setFullYear(new Date().getFullYear() + 10));
|
||||||
|
|
||||||
|
expandChartSlabIndex: number[] = [];
|
||||||
|
|
||||||
|
constructor(private formBuilder: FormBuilder,
|
||||||
|
public dialog: MatDialog,
|
||||||
|
private datePipe: DatePipe) {
|
||||||
|
this.createrecurringDepositProductInterestRateChartForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.periodTypeData = this.recurringDepositProductsTemplate.chartTemplate.periodTypes;
|
||||||
|
this.entityTypeData = this.recurringDepositProductsTemplate.chartTemplate.entityTypeOptions;
|
||||||
|
this.attributeNameData = this.recurringDepositProductsTemplate.chartTemplate.attributeNameOptions;
|
||||||
|
this.conditionTypeData = this.recurringDepositProductsTemplate.chartTemplate.conditionTypeOptions;
|
||||||
|
this.genderData = this.recurringDepositProductsTemplate.chartTemplate.genderOptions;
|
||||||
|
this.clientTypeData = this.recurringDepositProductsTemplate.chartTemplate.clientTypeOptions;
|
||||||
|
this.clientClassificationData = this.recurringDepositProductsTemplate.chartTemplate.clientClassificationOptions;
|
||||||
|
this.incentiveTypeData = this.recurringDepositProductsTemplate.chartTemplate.incentiveTypeOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
createrecurringDepositProductInterestRateChartForm() {
|
||||||
|
this.recurringDepositProductInterestRateChartForm = this.formBuilder.group({
|
||||||
|
'charts': this.formBuilder.array([])
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get charts(): FormArray {
|
||||||
|
return this.recurringDepositProductInterestRateChartForm.get('charts') as FormArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
createChartForm(): FormGroup {
|
||||||
|
return this.formBuilder.group({
|
||||||
|
'name': [''],
|
||||||
|
'description': [''],
|
||||||
|
'fromDate': ['', Validators.required],
|
||||||
|
'endDate': [''],
|
||||||
|
'isPrimaryGroupingByAmount': [false],
|
||||||
|
'chartSlabs': this.formBuilder.array([])
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addChart() {
|
||||||
|
this.charts.push(this.createChartForm());
|
||||||
|
this.setConditionalControls(this.charts.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
setConditionalControls(chartIndex: number) {
|
||||||
|
this.chartSlabsDisplayedColumns[chartIndex] = ['period', 'amountRange', 'annualInterestRate', 'description', 'actions'];
|
||||||
|
this.charts.at(chartIndex).get('isPrimaryGroupingByAmount').valueChanges
|
||||||
|
.subscribe((isPrimaryGroupingByAmount: boolean) => {
|
||||||
|
this.chartSlabsDisplayedColumns[chartIndex] = isPrimaryGroupingByAmount ? ['amountRange', 'period'] : ['period', 'amountRange'];
|
||||||
|
this.chartSlabsDisplayedColumns[chartIndex].push('annualInterestRate', 'description', 'actions');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getIncentives(chartSlabs: FormArray, chartSlabIndex: number): FormArray {
|
||||||
|
return chartSlabs.at(chartSlabIndex).get('incentives') as FormArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
addChartSlab(chartSlabs: FormArray) {
|
||||||
|
const data = { ...this.getData('Slab') };
|
||||||
|
const dialogRef = this.dialog.open(FormDialogComponent, { data });
|
||||||
|
dialogRef.afterClosed().subscribe((response: any) => {
|
||||||
|
if (response.data) {
|
||||||
|
response.data.addControl('incentives', this.formBuilder.array([]));
|
||||||
|
chartSlabs.push(response.data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addIncentive(incentives: FormArray) {
|
||||||
|
const data = { ...this.getData('Incentive'), entityType: this.entityTypeData[0].id };
|
||||||
|
const dialogRef = this.dialog.open(DepositProductIncentiveFormDialogComponent, { data });
|
||||||
|
dialogRef.afterClosed().subscribe((response: any) => {
|
||||||
|
if (response.data) {
|
||||||
|
incentives.push(response.data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
editChartSlab(chartSlabs: FormArray, chartSlabIndex: number) {
|
||||||
|
const data = { ...this.getData('Slab', chartSlabs.at(chartSlabIndex).value), layout: { addButtonText: 'Edit' } };
|
||||||
|
const dialogRef = this.dialog.open(FormDialogComponent, { data });
|
||||||
|
dialogRef.afterClosed().subscribe((response: any) => {
|
||||||
|
if (response.data) {
|
||||||
|
chartSlabs.at(chartSlabIndex).patchValue(response.data.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
editIncentive(incentives: FormArray, incentiveIndex: number) {
|
||||||
|
const data = { ...this.getData('Incentive', incentives.at(incentiveIndex).value), layout: { addButtonText: 'Edit' } };
|
||||||
|
const dialogRef = this.dialog.open(DepositProductIncentiveFormDialogComponent, { data });
|
||||||
|
dialogRef.afterClosed().subscribe((response: any) => {
|
||||||
|
if (response.data) {
|
||||||
|
incentives.at(incentiveIndex).patchValue(response.data.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(formArray: FormArray, index: number) {
|
||||||
|
const dialogRef = this.dialog.open(DeleteDialogComponent, {
|
||||||
|
data: { deleteContext: `this` }
|
||||||
|
});
|
||||||
|
dialogRef.afterClosed().subscribe((response: any) => {
|
||||||
|
if (response.delete) {
|
||||||
|
formArray.removeAt(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getData(formType: string, values?: any) {
|
||||||
|
switch (formType) {
|
||||||
|
case 'Slab': return { title: 'Slab', formfields: this.getSlabFormfields(values) };
|
||||||
|
case 'Incentive': return { values, chartTemplate: this.recurringDepositProductsTemplate.chartTemplate };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getSlabFormfields(values?: any) {
|
||||||
|
const formfields: FormfieldBase[] = [
|
||||||
|
new SelectBase({
|
||||||
|
controlName: 'periodType',
|
||||||
|
label: 'Period Type',
|
||||||
|
value: values ? values.periodType : this.periodTypeData[0].id,
|
||||||
|
options: { label: 'value', value: 'id', data: this.periodTypeData },
|
||||||
|
required: true,
|
||||||
|
order: 1
|
||||||
|
}),
|
||||||
|
new InputBase({
|
||||||
|
controlName: 'fromPeriod',
|
||||||
|
label: 'Period From',
|
||||||
|
value: values ? values.fromPeriod : undefined,
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
order: 2
|
||||||
|
}),
|
||||||
|
new InputBase({
|
||||||
|
controlName: 'toPeriod',
|
||||||
|
label: 'Period To',
|
||||||
|
value: values ? values.toPeriod : undefined,
|
||||||
|
type: 'number',
|
||||||
|
order: 3
|
||||||
|
}),
|
||||||
|
new InputBase({
|
||||||
|
controlName: 'amountRangeFrom',
|
||||||
|
label: 'Amount Range From',
|
||||||
|
value: values ? values.amountRangeFrom : undefined,
|
||||||
|
type: 'number',
|
||||||
|
order: 4
|
||||||
|
}),
|
||||||
|
new InputBase({
|
||||||
|
controlName: 'amountRangeTo',
|
||||||
|
label: 'Amount Range To',
|
||||||
|
value: values ? values.amountRangeTo : undefined,
|
||||||
|
type: 'number',
|
||||||
|
order: 5
|
||||||
|
}),
|
||||||
|
new InputBase({
|
||||||
|
controlName: 'annualInterestRate',
|
||||||
|
label: 'Interest',
|
||||||
|
value: values ? values.annualInterestRate : undefined,
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
order: 6
|
||||||
|
}),
|
||||||
|
new InputBase({
|
||||||
|
controlName: 'description',
|
||||||
|
label: 'Description',
|
||||||
|
value: values ? values.description : undefined,
|
||||||
|
required: true,
|
||||||
|
order: 7
|
||||||
|
})
|
||||||
|
];
|
||||||
|
return formfields;
|
||||||
|
}
|
||||||
|
|
||||||
|
get recurringDepositProductInterestRateChart() {
|
||||||
|
// TODO: Update once language and date settings are setup
|
||||||
|
const dateFormat = 'yyyy-MM-dd';
|
||||||
|
const locale = 'en';
|
||||||
|
const recurringDepositProductInterestRateChart = this.recurringDepositProductInterestRateChartForm.value;
|
||||||
|
for (const chart of recurringDepositProductInterestRateChart.charts) {
|
||||||
|
chart.dateFormat = dateFormat;
|
||||||
|
chart.locale = locale;
|
||||||
|
chart.fromDate = this.datePipe.transform(chart.fromDate, dateFormat) || '';
|
||||||
|
chart.endDate = this.datePipe.transform(chart.endDate, dateFormat) || '';
|
||||||
|
if (chart.endDate === '') {
|
||||||
|
delete chart.endDate;
|
||||||
|
}
|
||||||
|
if (chart.description === '') {
|
||||||
|
delete chart.description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return recurringDepositProductInterestRateChart;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+466
@@ -0,0 +1,466 @@
|
|||||||
|
<div fxLayout="row wrap" fxLayout.lt-md="column">
|
||||||
|
|
||||||
|
<h2 class="mat-h2" fxFlexFill>{{ recurringDepositProduct.name }}</h2>
|
||||||
|
|
||||||
|
<mat-divider fxFlexFill></mat-divider>
|
||||||
|
|
||||||
|
<h3 class="mat-h3" fxFlexFill>Details</h3>
|
||||||
|
|
||||||
|
<mat-divider fxFlexFill></mat-divider>
|
||||||
|
|
||||||
|
<div fxFlexFill>
|
||||||
|
<span fxFlex="40%">Short Name:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.shortName }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill *ngIf="recurringDepositProduct.description">
|
||||||
|
<span fxFlex="40%">Description:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.description }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="mat-h3" fxFlexFill>Currency</h3>
|
||||||
|
|
||||||
|
<mat-divider fxFlexFill></mat-divider>
|
||||||
|
|
||||||
|
<div fxFlexFill>
|
||||||
|
<span fxFlex="40%">Currency:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.currencyCode | find:recurringDepositProductsTemplate.currencyOptions:'code':'name' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill>
|
||||||
|
<span fxFlex="40%">Decimal Places:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.digitsAfterDecimal }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill>
|
||||||
|
<span fxFlex="40%">Currency in multiples of:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.inMultiplesOf }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="mat-h3" fxFlexFill>Terms</h3>
|
||||||
|
|
||||||
|
<mat-divider fxFlexFill></mat-divider>
|
||||||
|
|
||||||
|
<div fxFlexFill>
|
||||||
|
<span fxFlex="40%">Deposit Amount:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.depositAmount + ' (Min: ' + (recurringDepositProduct.minDepositAmount ? recurringDepositProduct.minDepositAmount : recurringDepositProduct.depositAmount) + ', Max: ' + (recurringDepositProduct.maxDepositAmount ? recurringDepositProduct.maxDepositAmount : recurringDepositProduct.depositAmount) + ')' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill>
|
||||||
|
<span fxFlex="40%">Interest Compounding Period:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.interestCompoundingPeriodType | find:recurringDepositProductsTemplate.interestCompoundingPeriodTypeOptions:'id':'value' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill>
|
||||||
|
<span fxFlex="40%">Interest Posting Period:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.interestPostingPeriodType | find:recurringDepositProductsTemplate.interestPostingPeriodTypeOptions:'id':'value' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill>
|
||||||
|
<span fxFlex="40%">Interest Calculated using:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.interestCalculationType | find:recurringDepositProductsTemplate.interestCalculationTypeOptions:'id':'value' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill>
|
||||||
|
<span fxFlex="40%">Days in Year:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.interestCalculationDaysInYearType | find:recurringDepositProductsTemplate.interestCalculationDaysInYearTypeOptions:'id':'value' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="mat-h3" fxFlexFill>Settings</h3>
|
||||||
|
|
||||||
|
<mat-divider fxFlexFill></mat-divider>
|
||||||
|
|
||||||
|
<div fxFlexFill *ngIf="recurringDepositProduct.lockinPeriodFrequency">
|
||||||
|
<span fxFlex="40%">Lock-in Period:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.lockinPeriodFrequency + ' ' + (recurringDepositProduct.lockinPeriodFrequencyType | find:recurringDepositProductsTemplate.lockinPeriodFrequencyTypeOptions:'id':'value') }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill>
|
||||||
|
<span fxFlex="40%">Minimum Deposit Term:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.minDepositTerm + ' ' + (recurringDepositProduct.minDepositTermTypeId | find:recurringDepositProductsTemplate.periodFrequencyTypeOptions:'id':'value') }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill *ngIf="recurringDepositProduct.inMultiplesOfDepositTerm">
|
||||||
|
<span fxFlex="40%">And thereafter, in Multiples of:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.inMultiplesOfDepositTerm + ' ' + (recurringDepositProduct.inMultiplesOfDepositTermTypeId | find:recurringDepositProductsTemplate.periodFrequencyTypeOptions:'id':'value') }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill *ngIf="recurringDepositProduct.maxDepositTerm">
|
||||||
|
<span fxFlex="40%">Minimum Deposit Term:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.maxDepositTerm + ' ' + (recurringDepositProduct.maxDepositTermTypeId | find:recurringDepositProductsTemplate.periodFrequencyTypeOptions:'id':'value') }}</span>
|
||||||
|
</div>
|
||||||
|
<!-- For Pre-mature closure -->
|
||||||
|
<div fxFlexFill>
|
||||||
|
<span fxFlex="40%">Apply Penal Interest (less):</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.preClosurePenalApplicable ? 'Yes' : 'No' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill *ngIf="recurringDepositProduct.preClosurePenalApplicable">
|
||||||
|
<span fxFlex="40%">Penal Interest (%):</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.preClosurePenalInterest + '% (' + (recurringDepositProduct.preClosurePenalInterestOnTypeId | find:recurringDepositProductsTemplate.preClosurePenalInterestOnTypeOptions:'id':'value') + ')' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill *ngIf="recurringDepositProduct.isMandatoryDeposit !== undefined">
|
||||||
|
<span fxFlex="40%">Recurring Deposit Type:</span>
|
||||||
|
<span fxFlex="60%" *ngIf="recurringDepositProduct.isMandatoryDeposit"> Mandatory </span>
|
||||||
|
<span fxFlex="60%" *ngIf="!recurringDepositProduct.isMandatoryDeposit"> Voluntary </span>
|
||||||
|
</div>
|
||||||
|
<!-- -->
|
||||||
|
<div fxFlexFill>
|
||||||
|
<span fxFlex="40%">Withhold Tax is Applicable:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.withHoldTax ? 'Yes' : 'No' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill *ngIf="recurringDepositProduct.withHoldTax">
|
||||||
|
<span fxFlex="40%">Tax Group:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.taxGroupId | find:recurringDepositProductsTemplate.taxGroupOptions:'id':'name' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column" *ngIf="recurringDepositProduct.charts.length !== 0">
|
||||||
|
|
||||||
|
<h3 class="mat-h3" fxFlexFill>Interest Rate Charts</h3>
|
||||||
|
|
||||||
|
<mat-divider fxFlexFill></mat-divider>
|
||||||
|
|
||||||
|
<div fxFlexFill *ngFor="let chart of recurringDepositProduct.charts; let chartIndex = index" fxLayout="row wrap" fxLayout.lt-md="column">
|
||||||
|
|
||||||
|
<div fxFlexFill *ngIf="chart.name">
|
||||||
|
<span fxFlex="40%">Name:</span>
|
||||||
|
<span fxFlex="60%">{{ chart.name }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill>
|
||||||
|
<span fxFlex="40%">Valid from Date:</span>
|
||||||
|
<span fxFlex="60%">{{ chart.fromDate | date }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill *ngIf="chart.endDate">
|
||||||
|
<span fxFlex="40%">End Date:</span>
|
||||||
|
<span fxFlex="60%">{{ chart.endDate | date }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill *ngIf="chart.description">
|
||||||
|
<span fxFlex="40%">Description:</span>
|
||||||
|
<span fxFlex="60%">{{ chart.description }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill>
|
||||||
|
<span fxFlex="40%">Primary Grouping by Amount:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.isPrimaryGroupingByAmount ? 'Yes' : 'No' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="chart.chartSlabs" *ngIf="chart.chartSlabs.length !== 0" multiTemplateDataRows>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="period">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Period </th>
|
||||||
|
<td mat-cell *matCellDef="let chartSlab">
|
||||||
|
{{ chartSlab.fromPeriod + ' - ' + chartSlab.toPeriod + ' ' + (chartSlab.periodType | find:recurringDepositProductsTemplate.chartTemplate.periodTypes:'id':'value') }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="amountRange">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Amount Range </th>
|
||||||
|
<td mat-cell *matCellDef="let chartSlab">
|
||||||
|
{{ chartSlab.amountRangeFrom + ' - ' + chartSlab.amountRangeTo }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="annualInterestRate">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Interest </th>
|
||||||
|
<td mat-cell *matCellDef="let chartSlab">
|
||||||
|
{{ chartSlab.annualInterestRate }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="description">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Description </th>
|
||||||
|
<td mat-cell *matCellDef="let chartSlab">
|
||||||
|
{{ chartSlab.description }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="actions">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Actions </th>
|
||||||
|
<td mat-cell *matCellDef="let chartSlab; let chartSlabIndex = dataIndex">
|
||||||
|
<button mat-button color="primary" (click)="expandChartSlabIndex[chartIndex] = expandChartSlabIndex[chartIndex] === chartSlabIndex ? null : chartSlabIndex" [disabled]="chartSlab.incentives.length === 0">
|
||||||
|
<span *ngIf="expandChartSlabIndex[chartIndex] !== chartSlabIndex">
|
||||||
|
<fa-icon icon="eye"></fa-icon>
|
||||||
|
View Incentives
|
||||||
|
</span>
|
||||||
|
<span *ngIf="expandChartSlabIndex[chartIndex] === chartSlabIndex">
|
||||||
|
<fa-icon icon="eye-slash"></fa-icon>
|
||||||
|
Hide Incentives
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="incentives">
|
||||||
|
<td mat-cell *matCellDef="let chartSlab; let chartSlabIndex = dataIndex" [attr.colspan]="chartSlabsDisplayedColumns[chartIndex].length">
|
||||||
|
<div fxLayout="row wrap" fxFlexFill class="incentives" [@expandChartSlab]="chartSlabIndex === expandChartSlabIndex[chartIndex] ? 'expanded' : 'collapsed'">
|
||||||
|
<mat-card fxLayout="row wrap" fxFlexFill>
|
||||||
|
|
||||||
|
<h4 class="mat-h4" fxFlex="23%">
|
||||||
|
Incentives
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="chartSlab.incentives">
|
||||||
|
|
||||||
|
<ng-container matColumnDef="entityType">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Entity Type </th>
|
||||||
|
<td mat-cell *matCellDef="let incentive">
|
||||||
|
{{ incentive.entityType | find:recurringDepositProductsTemplate.chartTemplate.entityTypeOptions:'id':'value' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="attributeName">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Attribute Name </th>
|
||||||
|
<td mat-cell *matCellDef="let incentive">
|
||||||
|
{{ incentive.attributeName | find:recurringDepositProductsTemplate.chartTemplate.attributeNameOptions:'id':'value' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="conditionType">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Condition Type </th>
|
||||||
|
<td mat-cell *matCellDef="let incentive">
|
||||||
|
{{ incentive.conditionType | find:recurringDepositProductsTemplate.chartTemplate.conditionTypeOptions:'id':'value' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="attributeValue">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Attribute Value </th>
|
||||||
|
<td mat-cell *matCellDef="let incentive" [ngSwitch]="incentive.attributeName">
|
||||||
|
<span *ngSwitchCase="2">{{ incentive.attributeValue | find:recurringDepositProductsTemplate.chartTemplate.genderOptions:'id':'name' }}</span>
|
||||||
|
<span *ngSwitchCase="3">{{ incentive.attributeValue }}</span>
|
||||||
|
<span *ngSwitchCase="4">{{ incentive.attributeValue | find:recurringDepositProductsTemplate.chartTemplate.clientTypeOptions:'id':'name' }}</span>
|
||||||
|
<span *ngSwitchCase="5">{{ incentive.attributeValue | find:recurringDepositProductsTemplate.chartTemplate.clientClassificationOptions:'id':'name' }}</span>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="incentiveType">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Incentive Type </th>
|
||||||
|
<td mat-cell *matCellDef="let incentive">
|
||||||
|
{{ incentive.incentiveType | find:recurringDepositProductsTemplate.chartTemplate.incentiveTypeOptions:'id':'value'}}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="amount">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Amount </th>
|
||||||
|
<td mat-cell *matCellDef="let incentive">
|
||||||
|
{{ incentive.amount }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="incentivesDisplayedColumns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: incentivesDisplayedColumns;"></tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="chartSlabsDisplayedColumns[chartIndex]"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: chartSlabsDisplayedColumns[chartIndex];"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: chartSlabsIncentivesDisplayedColumns;" class="incentives-row"></tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<mat-divider fxFlexFill></mat-divider>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill *ngIf="recurringDepositProduct.charges.length" fxLayout="row wrap" fxLayout.lt-md="column">
|
||||||
|
|
||||||
|
<h3 class="mat-h3" fxFlexFill>Charges</h3>
|
||||||
|
|
||||||
|
<mat-divider fxFlexFill></mat-divider>
|
||||||
|
|
||||||
|
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="recurringDepositProduct.charges">
|
||||||
|
|
||||||
|
<ng-container matColumnDef="name">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Name </th>
|
||||||
|
<td mat-cell *matCellDef="let charge">
|
||||||
|
{{ charge.name + ', ' + charge.currency.displaySymbol }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="chargeCalculationType">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Type </th>
|
||||||
|
<td mat-cell *matCellDef="let charge">
|
||||||
|
{{ charge.chargeCalculationType.value }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="amount">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Amount </th>
|
||||||
|
<td mat-cell *matCellDef="let charge">
|
||||||
|
{{ charge.amount }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="chargeTimeType">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Collected On </th>
|
||||||
|
<td mat-cell *matCellDef="let charge">
|
||||||
|
{{ charge.chargeTimeType.value }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="chargesDisplayedColumns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: chargesDisplayedColumns;"></tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="mat-h3" fxFlexFill>Accounting</h3>
|
||||||
|
|
||||||
|
<mat-divider fxFlexFill></mat-divider>
|
||||||
|
|
||||||
|
<div fxFlexFill>
|
||||||
|
<span fxFlex="40%">Type:</span>
|
||||||
|
<span fxFlex="60%">{{ accountingRuleData[recurringDepositProduct.accountingRule-1] }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxFlexFill *ngIf="recurringDepositProduct.accountingRule === 2" fxLayout="row wrap" fxLayout.lt-md="column">
|
||||||
|
|
||||||
|
<h4 fxFlexFill class="mat-h4">Assets</h4>
|
||||||
|
|
||||||
|
<div fxFlexFill>
|
||||||
|
<span fxFlex="40%">Saving reference:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.savingsReferenceAccountId | find:recurringDepositProductsTemplate.accountingMappingOptions.assetAccountOptions:'id':'name' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h4 fxFlexFill class="mat-h4">Liabilities</h4>
|
||||||
|
|
||||||
|
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
|
||||||
|
<span fxFlex="40%">Saving control:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.savingsControlAccountId | find:recurringDepositProductsTemplate.accountingMappingOptions.liabilityAccountOptions:'id':'name' }}</span>
|
||||||
|
<span fxFlex="40%">Savings transfers in suspense:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.transfersInSuspenseAccountId | find:recurringDepositProductsTemplate.accountingMappingOptions.liabilityAccountOptions:'id':'name' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h4 fxFlexFill class="mat-h4">Expenses</h4>
|
||||||
|
|
||||||
|
<div fxFlexFill>
|
||||||
|
<span fxFlex="40%">Interest on savings:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.interestOnSavingsAccountId | find:recurringDepositProductsTemplate.accountingMappingOptions.expenseAccountOptions:'id':'name' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h4 fxFlexFill class="mat-h4">Income</h4>
|
||||||
|
|
||||||
|
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
|
||||||
|
<span fxFlex="40%">Income from fees:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.incomeFromFeeAccountId | find:recurringDepositProductsTemplate.accountingMappingOptions.incomeAccountOptions:'id':'name' }}</span>
|
||||||
|
<span fxFlex="40%">Income from penalties:</span>
|
||||||
|
<span fxFlex="60%">{{ recurringDepositProduct.incomeFromPenaltyAccountId | find:recurringDepositProductsTemplate.accountingMappingOptions.incomeAccountOptions:'id':'name' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="recurringDepositProduct.advancedAccountingRules && (recurringDepositProduct.paymentChannelToFundSourceMappings?.length || recurringDepositProduct.feeToIncomeAccountMappings?.length || recurringDepositProduct.penaltyToIncomeAccountMappings?.length)" fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
|
||||||
|
|
||||||
|
<h3 class="mat-h3" fxFlexFill>Advanced Accounting Rules</h3>
|
||||||
|
|
||||||
|
<mat-divider fxFlexFill></mat-divider>
|
||||||
|
|
||||||
|
<div *ngIf="recurringDepositProduct.paymentChannelToFundSourceMappings?.length" fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
|
||||||
|
|
||||||
|
<h4 class="mat-h4" fxFlexFill>Fund Sources for Payment Channels</h4>
|
||||||
|
|
||||||
|
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="recurringDepositProduct.paymentChannelToFundSourceMappings">
|
||||||
|
|
||||||
|
<ng-container matColumnDef="paymentTypeId">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Payment Type </th>
|
||||||
|
<td mat-cell *matCellDef="let paymentFundSource">
|
||||||
|
{{ paymentFundSource.paymentTypeId | find:recurringDepositProductsTemplate.paymentTypeOptions:'id':'name' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="fundSourceAccountId">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Fund Source </th>
|
||||||
|
<td mat-cell *matCellDef="let paymentFundSource">
|
||||||
|
{{ paymentFundSource.fundSourceAccountId | find:recurringDepositProductsTemplate.accountingMappingOptions.assetAccountOptions:'id':'name' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="paymentFundSourceDisplayedColumns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: paymentFundSourceDisplayedColumns;"></tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="recurringDepositProduct.feeToIncomeAccountMappings?.length" fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
|
||||||
|
|
||||||
|
<h4 class="mat-h4" fxFlexFill>Fees to Specific Income Accounts</h4>
|
||||||
|
|
||||||
|
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="recurringDepositProduct.feeToIncomeAccountMappings">
|
||||||
|
|
||||||
|
<ng-container matColumnDef="chargeId">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Fees </th>
|
||||||
|
<td mat-cell *matCellDef="let feesIncome">
|
||||||
|
{{ feesIncome.chargeId | find:recurringDepositProductsTemplate.chargeOptions:'id':'name' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="incomeAccountId">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Income Account </th>
|
||||||
|
<td mat-cell *matCellDef="let feesIncome">
|
||||||
|
{{ feesIncome.incomeAccountId | find:recurringDepositProductsTemplate.accountingMappingOptions.incomeAccountOptions:'id':'name' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns;"></tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="recurringDepositProduct.penaltyToIncomeAccountMappings?.length" fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
|
||||||
|
|
||||||
|
<h4 class="mat-h4" fxFlexFill>Penalties to Specific Income Accounts</h4>
|
||||||
|
|
||||||
|
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="recurringDepositProduct.penaltyToIncomeAccountMappings">
|
||||||
|
|
||||||
|
<ng-container matColumnDef="chargeId">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Penalty </th>
|
||||||
|
<td mat-cell *matCellDef="let penaltyIncome">
|
||||||
|
{{ penaltyIncome.chargeId | find:recurringDepositProductsTemplate.penaltyOptions:'id':'name' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="incomeAccountId">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Income Account </th>
|
||||||
|
<td mat-cell *matCellDef="let penaltyIncome">
|
||||||
|
{{ penaltyIncome.incomeAccountId | find:recurringDepositProductsTemplate.accountingMappingOptions.incomeAccountOptions:'id':'name' }}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns;"></tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxLayout="row" class="margin-t" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="2%">
|
||||||
|
<button mat-raised-button matStepperPrevious>
|
||||||
|
<fa-icon icon="arrow-left"></fa-icon>
|
||||||
|
Previous
|
||||||
|
</button>
|
||||||
|
<button mat-raised-button [routerLink]="['../']">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button mat-raised-button color="primary" (click)="submit.emit()">
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
tr.incentives-row {
|
||||||
|
height: 0;
|
||||||
|
|
||||||
|
> td {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.incentives {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-card {
|
||||||
|
border-radius: 0;
|
||||||
|
|
||||||
|
> h4 {
|
||||||
|
font-weight: 500;
|
||||||
|
margin: 0.5em 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { RecurringDepositProductPreviewStepComponent } from './recurring-deposit-product-preview-step.component';
|
||||||
|
|
||||||
|
describe('RecurringDepositProductPreviewStepComponent', () => {
|
||||||
|
let component: RecurringDepositProductPreviewStepComponent;
|
||||||
|
let fixture: ComponentFixture<RecurringDepositProductPreviewStepComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ RecurringDepositProductPreviewStepComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(RecurringDepositProductPreviewStepComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { trigger, state, transition, animate, style } from '@angular/animations';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-recurring-deposit-product-preview-step',
|
||||||
|
templateUrl: './recurring-deposit-product-preview-step.component.html',
|
||||||
|
styleUrls: ['./recurring-deposit-product-preview-step.component.scss'],
|
||||||
|
animations: [
|
||||||
|
trigger('expandChartSlab', [
|
||||||
|
state('collapsed', style({ height: '0px', minHeight: '0' })),
|
||||||
|
state('expanded', style({ height: '*' })),
|
||||||
|
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)'))
|
||||||
|
])
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class RecurringDepositProductPreviewStepComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input() recurringDepositProductsTemplate: any;
|
||||||
|
@Input() chartSlabsDisplayedColumns: any[];
|
||||||
|
@Input() accountingRuleData: any;
|
||||||
|
@Input() recurringDepositProduct: any;
|
||||||
|
@Output() submit = new EventEmitter();
|
||||||
|
|
||||||
|
chartSlabsIncentivesDisplayedColumns: string[] = ['incentives'];
|
||||||
|
incentivesDisplayedColumns: string[] = ['entityType', 'attributeName', 'conditionType', 'attributeValue', 'incentiveType', 'amount'];
|
||||||
|
chargesDisplayedColumns: string[] = ['name', 'chargeCalculationType', 'amount', 'chargeTimeType'];
|
||||||
|
paymentFundSourceDisplayedColumns: string[] = ['paymentTypeId', 'fundSourceAccountId'];
|
||||||
|
feesPenaltyIncomeDisplayedColumns: string[] = ['chargeId', 'incomeAccountId'];
|
||||||
|
|
||||||
|
expandChartSlabIndex: number[] = [];
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+142
@@ -0,0 +1,142 @@
|
|||||||
|
<form [formGroup]="recurringDepositProductSettingsForm">
|
||||||
|
|
||||||
|
<div fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||||
|
|
||||||
|
<mat-checkbox fxFlex="48%" labelPosition="before" formControlName="isMandatoryDeposit" class="margin-v">
|
||||||
|
Is Mandatory Deposit?
|
||||||
|
</mat-checkbox>
|
||||||
|
|
||||||
|
<mat-checkbox fxFlex="48%" labelPosition="before" formControlName="adjustAdvanceTowardsFuturePayments" class="margin-v">
|
||||||
|
Adjust advance payments toward future installments?
|
||||||
|
</mat-checkbox>
|
||||||
|
|
||||||
|
<mat-checkbox fxFlex="48%" labelPosition="before" formControlName="allowWithdrawal" class="margin-v">
|
||||||
|
Allow Withdrawals?
|
||||||
|
</mat-checkbox>
|
||||||
|
|
||||||
|
<h4 fxFlex="98%" class="mat-h4">Lock-in Period</h4>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Frequency</mat-label>
|
||||||
|
<input type="number" matInput formControlName="lockinPeriodFrequency">
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Type</mat-label>
|
||||||
|
<mat-select formControlName="lockinPeriodFrequencyType">
|
||||||
|
<mat-option *ngFor="let lockinPeriodFrequencyType of lockinPeriodFrequencyTypeData"
|
||||||
|
[value]="lockinPeriodFrequencyType.id">
|
||||||
|
{{ lockinPeriodFrequencyType.value }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<h4 fxFlex="98%" class="mat-h4">Minimum Deposit Term</h4>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Frequency</mat-label>
|
||||||
|
<input type="number" matInput formControlName="minDepositTerm" required>
|
||||||
|
<mat-error>
|
||||||
|
Minimum Deposit Term Frequency is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Frequency Type</mat-label>
|
||||||
|
<mat-select formControlName="minDepositTermTypeId" required>
|
||||||
|
<mat-option *ngFor="let periodFrequencyType of periodFrequencyTypeData" [value]="periodFrequencyType.id">
|
||||||
|
{{ periodFrequencyType.value }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error>
|
||||||
|
Minimum Deposit Term Frequency Type is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<h4 fxFlex="98%" class="mat-h4">And thereafter, in Multiples of</h4>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Frequency</mat-label>
|
||||||
|
<input type="number" matInput formControlName="inMultiplesOfDepositTerm">
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Type</mat-label>
|
||||||
|
<mat-select formControlName="inMultiplesOfDepositTermTypeId">
|
||||||
|
<mat-option *ngFor="let periodFrequencyType of periodFrequencyTypeData" [value]="periodFrequencyType.id">
|
||||||
|
{{ periodFrequencyType.value }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<h4 fxFlex="98%" class="mat-h4">Maximum Deposit Term</h4>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Frequency</mat-label>
|
||||||
|
<input type="number" matInput formControlName="maxDepositTerm">
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Type</mat-label>
|
||||||
|
<mat-select formControlName="maxDepositTermTypeId">
|
||||||
|
<mat-option *ngFor="let periodFrequencyType of periodFrequencyTypeData" [value]="periodFrequencyType.id">
|
||||||
|
{{ periodFrequencyType.value }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-divider fxFlex="98%"></mat-divider>
|
||||||
|
|
||||||
|
<h4 fxFlex="23%" class="mat-h4">For Pre-mature closure</h4>
|
||||||
|
|
||||||
|
<mat-checkbox fxFlex="73%" labelPosition="before" formControlName="preClosurePenalApplicable" class="margin-v">
|
||||||
|
Apply Penal Interest (less)
|
||||||
|
</mat-checkbox>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Penal Interest (%)</mat-label>
|
||||||
|
<input type="number" matInput formControlName="preClosurePenalInterest">
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Period</mat-label>
|
||||||
|
<mat-select formControlName="preClosurePenalInterestOnTypeId">
|
||||||
|
<mat-option *ngFor="let preClosurePenalInterestOnType of preClosurePenalInterestOnTypeData"
|
||||||
|
[value]="preClosurePenalInterestOnType.id">
|
||||||
|
{{ preClosurePenalInterestOnType.value }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-divider fxFlex="98%"></mat-divider>
|
||||||
|
|
||||||
|
<mat-checkbox fxFlex="48%" labelPosition="before" formControlName="withHoldTax" class="margin-v">
|
||||||
|
Is Withhold Tax Applicable?
|
||||||
|
</mat-checkbox>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%" *ngIf="recurringDepositProductSettingsForm.value.withHoldTax">
|
||||||
|
<mat-label>Tax Group</mat-label>
|
||||||
|
<mat-select formControlName="taxGroupId" required>
|
||||||
|
<mat-option *ngFor="let taxGroup of taxGroupData" [value]="taxGroup.id">
|
||||||
|
{{ taxGroup.name }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error>
|
||||||
|
Tax Group is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxLayout="row" class="margin-t" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="2%">
|
||||||
|
<button mat-raised-button matStepperPrevious>
|
||||||
|
<fa-icon icon="arrow-left"></fa-icon>
|
||||||
|
Previous
|
||||||
|
</button>
|
||||||
|
<button mat-raised-button matStepperNext>
|
||||||
|
Next
|
||||||
|
<fa-icon icon="arrow-right"></fa-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
h4 {
|
||||||
|
font-weight: 500;
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-divider {
|
||||||
|
margin: 1em 0 2em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-v {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-b {
|
||||||
|
margin: 0 0 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-t {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { RecurringDepositProductSettingsStepComponent } from './recurring-deposit-product-settings-step.component';
|
||||||
|
|
||||||
|
describe('RecurringDepositProductSettingsStepComponent', () => {
|
||||||
|
let component: RecurringDepositProductSettingsStepComponent;
|
||||||
|
let fixture: ComponentFixture<RecurringDepositProductSettingsStepComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ RecurringDepositProductSettingsStepComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(RecurringDepositProductSettingsStepComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
+73
@@ -0,0 +1,73 @@
|
|||||||
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
|
import { FormGroup, FormBuilder, FormControl, Validators } from '@angular/forms';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-recurring-deposit-product-settings-step',
|
||||||
|
templateUrl: './recurring-deposit-product-settings-step.component.html',
|
||||||
|
styleUrls: ['./recurring-deposit-product-settings-step.component.scss']
|
||||||
|
})
|
||||||
|
export class RecurringDepositProductSettingsStepComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input() recurringDepositProductsTemplate: any;
|
||||||
|
|
||||||
|
recurringDepositProductSettingsForm: FormGroup;
|
||||||
|
|
||||||
|
lockinPeriodFrequencyTypeData: any;
|
||||||
|
periodFrequencyTypeData: any;
|
||||||
|
preClosurePenalInterestOnTypeData: any;
|
||||||
|
taxGroupData: any;
|
||||||
|
|
||||||
|
constructor(private formBuilder: FormBuilder) {
|
||||||
|
this.createrecurringDepositProductSettingsForm();
|
||||||
|
this.setConditionalControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.lockinPeriodFrequencyTypeData = this.recurringDepositProductsTemplate.lockinPeriodFrequencyTypeOptions;
|
||||||
|
this.periodFrequencyTypeData = this.recurringDepositProductsTemplate.periodFrequencyTypeOptions.slice(0, -1);
|
||||||
|
this.preClosurePenalInterestOnTypeData = this.recurringDepositProductsTemplate.preClosurePenalInterestOnTypeOptions;
|
||||||
|
this.taxGroupData = this.recurringDepositProductsTemplate.taxGroupOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
createrecurringDepositProductSettingsForm() {
|
||||||
|
this.recurringDepositProductSettingsForm = this.formBuilder.group({
|
||||||
|
'isMandatoryDeposit': [false],
|
||||||
|
'adjustAdvanceTowardsFuturePayments': [false],
|
||||||
|
'allowWithdrawal': [false],
|
||||||
|
'lockinPeriodFrequency': [''],
|
||||||
|
'lockinPeriodFrequencyType': [''],
|
||||||
|
'minDepositTerm': ['', Validators.required],
|
||||||
|
'minDepositTermTypeId': ['', Validators.required],
|
||||||
|
'inMultiplesOfDepositTerm': [''],
|
||||||
|
'inMultiplesOfDepositTermTypeId': [''],
|
||||||
|
'maxDepositTerm': [''],
|
||||||
|
'maxDepositTermTypeId': [''],
|
||||||
|
'preClosurePenalApplicable': [false],
|
||||||
|
'preClosurePenalInterest': [''],
|
||||||
|
'preClosurePenalInterestOnTypeId': [''],
|
||||||
|
'withHoldTax': [false]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setConditionalControls() {
|
||||||
|
this.recurringDepositProductSettingsForm.get('withHoldTax').valueChanges
|
||||||
|
.subscribe((withHoldTax: any) => {
|
||||||
|
if (withHoldTax) {
|
||||||
|
this.recurringDepositProductSettingsForm.addControl('taxGroupId', new FormControl('', Validators.required));
|
||||||
|
} else {
|
||||||
|
this.recurringDepositProductSettingsForm.removeControl('taxGroupId');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get recurringDepositProductSettings() {
|
||||||
|
const recurringDepositProductSettings = this.recurringDepositProductSettingsForm.value;
|
||||||
|
for (const key in recurringDepositProductSettings) {
|
||||||
|
if (recurringDepositProductSettings[key] === '') {
|
||||||
|
delete recurringDepositProductSettings[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return recurringDepositProductSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
<form [formGroup]="recurringDepositProductTermsForm">
|
||||||
|
|
||||||
|
<div fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||||
|
|
||||||
|
<h4 fxFlex="98%" class="mat-h4">Deposit Amount</h4>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="31%">
|
||||||
|
<mat-label>Minimum</mat-label>
|
||||||
|
<input type="number" matInput formControlName="minDepositAmount">
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="31%">
|
||||||
|
<mat-label>Default</mat-label>
|
||||||
|
<input type="number" matInput formControlName="depositAmount" required>
|
||||||
|
<mat-error>
|
||||||
|
Default Deposit Amount is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="31%">
|
||||||
|
<mat-label>Maximum</mat-label>
|
||||||
|
<input type="number" matInput formControlName="maxDepositAmount">
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-divider fxFlex="98%"></mat-divider>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Interest Compounding Period</mat-label>
|
||||||
|
<mat-select formControlName="interestCompoundingPeriodType" required>
|
||||||
|
<mat-option *ngFor="let interestCompoundingPeriodType of interestCompoundingPeriodTypeData" [value]="interestCompoundingPeriodType.id">
|
||||||
|
{{ interestCompoundingPeriodType.value }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error>
|
||||||
|
Interest Compounding Period is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Interest Posting Period</mat-label>
|
||||||
|
<mat-select formControlName="interestPostingPeriodType" required>
|
||||||
|
<mat-option *ngFor="let interestPostingPeriodType of interestPostingPeriodTypeData" [value]="interestPostingPeriodType.id">
|
||||||
|
{{ interestPostingPeriodType.value }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error>
|
||||||
|
Interest Posting Period is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Interest Calculated using</mat-label>
|
||||||
|
<mat-select formControlName="interestCalculationType" required>
|
||||||
|
<mat-option *ngFor="let interestCalculationType of interestCalculationTypeData" [value]="interestCalculationType.id">
|
||||||
|
{{ interestCalculationType.value }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error>
|
||||||
|
Interest Calculated using is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="48%">
|
||||||
|
<mat-label>Days in Year</mat-label>
|
||||||
|
<mat-select formControlName="interestCalculationDaysInYearType" required>
|
||||||
|
<mat-option *ngFor="let interestCalculationDaysInYearType of interestCalculationDaysInYearTypeData" [value]="interestCalculationDaysInYearType.id">
|
||||||
|
{{ interestCalculationDaysInYearType.value }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error>
|
||||||
|
Days in Year is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxLayout="row" class="margin-t" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="2%">
|
||||||
|
<button mat-raised-button matStepperPrevious>
|
||||||
|
<fa-icon icon="arrow-left"></fa-icon>
|
||||||
|
Previous
|
||||||
|
</button>
|
||||||
|
<button mat-raised-button matStepperNext>
|
||||||
|
Next
|
||||||
|
<fa-icon icon="arrow-right"></fa-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
h4 {
|
||||||
|
font-weight: 500;
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-divider {
|
||||||
|
margin: 1em 0 2em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-t {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { RecurringDepositProductTermsStepComponent } from './recurring-deposit-product-terms-step.component';
|
||||||
|
|
||||||
|
describe('RecurringDepositProductTermsStepComponent', () => {
|
||||||
|
let component: RecurringDepositProductTermsStepComponent;
|
||||||
|
let fixture: ComponentFixture<RecurringDepositProductTermsStepComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ RecurringDepositProductTermsStepComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(RecurringDepositProductTermsStepComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
|
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-recurring-deposit-product-terms-step',
|
||||||
|
templateUrl: './recurring-deposit-product-terms-step.component.html',
|
||||||
|
styleUrls: ['./recurring-deposit-product-terms-step.component.scss']
|
||||||
|
})
|
||||||
|
export class RecurringDepositProductTermsStepComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input() recurringDepositProductsTemplate: any;
|
||||||
|
|
||||||
|
recurringDepositProductTermsForm: FormGroup;
|
||||||
|
|
||||||
|
interestCompoundingPeriodTypeData: any;
|
||||||
|
interestPostingPeriodTypeData: any;
|
||||||
|
interestCalculationTypeData: any;
|
||||||
|
interestCalculationDaysInYearTypeData: any;
|
||||||
|
|
||||||
|
constructor(private formBuilder: FormBuilder) {
|
||||||
|
this.createrecurringDepositProductTermsForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.interestCompoundingPeriodTypeData = this.recurringDepositProductsTemplate.interestCompoundingPeriodTypeOptions;
|
||||||
|
this.interestPostingPeriodTypeData = this.recurringDepositProductsTemplate.interestPostingPeriodTypeOptions;
|
||||||
|
this.interestCalculationTypeData = this.recurringDepositProductsTemplate.interestCalculationTypeOptions;
|
||||||
|
this.interestCalculationDaysInYearTypeData = this.recurringDepositProductsTemplate.interestCalculationDaysInYearTypeOptions;
|
||||||
|
|
||||||
|
this.recurringDepositProductTermsForm.patchValue({
|
||||||
|
'interestCompoundingPeriodType': this.recurringDepositProductsTemplate.interestCompoundingPeriodType.id,
|
||||||
|
'interestPostingPeriodType': this.recurringDepositProductsTemplate.interestPostingPeriodType.id,
|
||||||
|
'interestCalculationType': this.recurringDepositProductsTemplate.interestCalculationType.id,
|
||||||
|
'interestCalculationDaysInYearType': this.recurringDepositProductsTemplate.interestCalculationDaysInYearType.id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createrecurringDepositProductTermsForm() {
|
||||||
|
this.recurringDepositProductTermsForm = this.formBuilder.group({
|
||||||
|
'minDepositAmount': [''],
|
||||||
|
'depositAmount': ['', Validators.required],
|
||||||
|
'maxDepositAmount': [''],
|
||||||
|
'interestCompoundingPeriodType': ['', Validators.required],
|
||||||
|
'interestPostingPeriodType': ['', Validators.required],
|
||||||
|
'interestCalculationType': ['', Validators.required],
|
||||||
|
'interestCalculationDaysInYearType': ['', Validators.required]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get recurringDepositProductTerms() {
|
||||||
|
const recurringDepositProductTerms = this.recurringDepositProductTermsForm.value;
|
||||||
|
for (const key in recurringDepositProductTerms) {
|
||||||
|
if (recurringDepositProductTerms[key] === '') {
|
||||||
|
delete recurringDepositProductTerms[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return recurringDepositProductTerms;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+1
-1
@@ -11,7 +11,7 @@ import { ProductsService } from '../products.service';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class RecurringDepositProductsTemplateResolver implements Resolve<Object> {
|
export class RecurringDepositProductsTemplateResolver implements Resolve<Object> {
|
||||||
|
|
||||||
constructor(private productsService: ProductsService) {}
|
constructor(private productsService: ProductsService) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the recurring deposit products template data.
|
* Returns the recurring deposit products template data.
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
<div class="container m-b-20" fxLayout="row" fxLayoutAlign="end" fxLayoutGap="20px">
|
<div class="container m-b-20" fxLayout="row" fxLayoutAlign="end" fxLayoutGap="20px">
|
||||||
<button mat-raised-button color="primary">
|
<button mat-raised-button color="primary" [routerLink]="['create']" mifosxHasPermission='"CREATE_RECURRINGDEPOSITPRODUCT"'>
|
||||||
<fa-icon icon="plus"></fa-icon>
|
<fa-icon icon="plus"></fa-icon>
|
||||||
Create Recurring Deposit Product
|
Create Recurring Deposit Product
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user