Fixed Deposit and Recurring Deposit products with datatables (#1647)

Co-authored-by: Jose Alberto Hernandez <alberto@MacBook-Pro.local>
This commit is contained in:
José Alberto Hernández
2023-01-18 18:53:56 -06:00
committed by GitHub
co-authored by Jose Alberto Hernandez
parent 00ceeed3f2
commit e61f4f92e3
51 changed files with 1625 additions and 1237 deletions
@@ -14,19 +14,19 @@ import { ProductsService } from '../../products.service';
@Injectable()
export class FixedDepositProductAndTemplateResolver implements Resolve<Object> {
/**
* @param {ProductsService} productsService Products service.
*/
constructor(private productsService: ProductsService) { }
/**
* @param {ProductsService} productsService Products service.
*/
constructor(private productsService: ProductsService) { }
/**
* Returns the Fixed Deposits Product and Template.
* @param {ActivatedRouteSnapshot} route Route Snapshot
* @returns {Observable<any>}
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const fixedDepositProductId = route.paramMap.get('id');
return this.productsService.getFixedDepositProductAndTemplate(fixedDepositProductId);
}
/**
* Returns the Fixed Deposits Product and Template.
* @param {ActivatedRouteSnapshot} route Route Snapshot
* @returns {Observable<any>}
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const productId = route.parent.paramMap.get('productId');
return this.productsService.getFixedDepositProductAndTemplate(productId);
}
}
@@ -24,8 +24,8 @@ export class FixedDepositProductResolver implements Resolve<Object> {
* @returns {Observable<any>}
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const fixedDepositProductId = route.paramMap.get('id');
return this.productsService.getFixedDepositProduct(fixedDepositProductId);
const productId = route.parent.paramMap.get('productId');
return this.productsService.getFixedDepositProduct(productId);
}
}
@@ -0,0 +1,9 @@
<div class="tab-container mat-typography">
<mifosx-entity-datatable-tab
entityType="Fixed Deposit Product"
[entityId]="entityId"
[multiRowDatatableFlag]="multiRowDatatableFlag"
[entityDatatable]="entityDatatable"
>
</mifosx-entity-datatable-tab>
</div>
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FixedDepositDatatableTabComponent } from './fixed-deposit-datatable-tab.component';
describe('FixedDepositDatatableTabComponent', () => {
let component: FixedDepositDatatableTabComponent;
let fixture: ComponentFixture<FixedDepositDatatableTabComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ FixedDepositDatatableTabComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(FixedDepositDatatableTabComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,26 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'mifosx-fixed-deposit-datatable-tab',
templateUrl: './fixed-deposit-datatable-tab.component.html',
styleUrls: ['./fixed-deposit-datatable-tab.component.scss']
})
export class FixedDepositDatatableTabComponent implements OnInit {
entityId: string;
entityDatatable: any;
multiRowDatatableFlag: boolean;
constructor(private route: ActivatedRoute) {
this.entityId = this.route.parent.parent.snapshot.paramMap.get('productId');
this.route.data.subscribe((data: { fixedDepositDatatable: any }) => {
this.entityDatatable = data.fixedDepositDatatable;
this.multiRowDatatableFlag = this.entityDatatable.columnHeaders[0].columnName === 'id' ? true : false;
});
}
ngOnInit(): void {
}
}
@@ -0,0 +1,494 @@
<div fxLayout="row" fxLayoutAlign="end" fxLayoutGap="2%" fxLayout.lt-md="column" class="container m-b-20">
<button mat-raised-button color="primary" [routerLink]="['../edit']" *mifosxHasPermission="'UPDATE_SAVINGSPRODUCT'">
<fa-icon icon="edit" class="m-r-10"></fa-icon>Edit
</button>
</div>
<div class="container">
<mat-card>
<mat-card-content>
<div fxLayout="row wrap" fxLayout.lt-md="column">
<h2 class="mat-h2" fxFlexFill>{{ fixedDepositProductData.name }}</h2>
<mat-divider [inset]="true"></mat-divider>
<h3 class="mat-h3" fxFlexFill>Details</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Short Name:</span>
<span fxFlex="60%">{{ fixedDepositProductData.shortName }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.description">
<span fxFlex="40%">Description:</span>
<span fxFlex="60%">{{ fixedDepositProductData.description }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Currency</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Currency:</span>
<span fxFlex="60%">{{ fixedDepositProductData.currency.name }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Decimal Places:</span>
<span fxFlex="60%">{{ fixedDepositProductData.currency.decimalPlaces }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Currency in Multiples Of:</span>
<span fxFlex="60%">{{ fixedDepositProductData.currency.inMultiplesOf | number}}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Terms</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Deposit Amount:</span>
<span fxFlex="60%">{{ fixedDepositProductData.depositAmount + ' (Min: ' + (fixedDepositProductData.minDepositAmount ? fixedDepositProductData.minDepositAmount : fixedDepositProductData.depositAmount) + ', Max: ' + (fixedDepositProductData.maxDepositAmount ? fixedDepositProductData.maxDepositAmount : fixedDepositProductData.depositAmount) + ')' }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Interest Compounding Period:</span>
<span fxFlex="60%">{{ fixedDepositProductData.interestCompoundingPeriodType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Interest Posting Period:</span>
<span fxFlex="60%">{{ fixedDepositProductData.interestPostingPeriodType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Interest Calculated Using:</span>
<span fxFlex="60%">{{ fixedDepositProductData.interestCalculationType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Days in Years:</span>
<span fxFlex="60%">{{ fixedDepositProductData.interestCalculationDaysInYearType.value }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Settings</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill *ngIf="fixedDepositProductData.lockinPeriodFrequency">
<span fxFlex="40%">Lock-in Period:</span>
<span fxFlex="60%">
{{ fixedDepositProductData.lockinPeriodFrequency }} {{ fixedDepositProductData.lockinPeriodFrequencyType.value }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.minDepositTerm">
<span fxFlex="40%">Minimum Deposit Term:</span>
<span fxFlex="60%"
*ngIf="fixedDepositProductData.minDepositTerm !== undefined">{{ fixedDepositProductData.minDepositTerm }}
&nbsp;
{{ fixedDepositProductData.minDepositTermType.value }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.maxDepositTerm">
<span fxFlex="40%">Maximum Deposit Term:</span>
<span fxFlex="60%"
*ngIf="fixedDepositProductData.maxDepositTerm !== undefined">{{ fixedDepositProductData.maxDepositTerm }}
&nbsp;
{{ fixedDepositProductData.maxDepositTermType.value }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.inMultiplesOfDepositTerm">
<span fxFlex="40%">Deposit Term In multiple of:</span>
<span fxFlex="60%">{{ fixedDepositProductData.inMultiplesOfDepositTerm }}
-
{{ fixedDepositProductData.inMultiplesOfDepositTermType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Apply Penal Interest (less):</span>
<span fxFlex="60%">{{ fixedDepositProductData.preClosurePenalApplicable ? 'Yes' : 'No' }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.preClosurePenalApplicable">
<span fxFlex="40%">Penal Interest (%):</span>
<span fxFlex="60%">{{fixedDepositProductData.preClosurePenalInterest}} &nbsp; &nbsp; % &nbsp; &nbsp; On
&nbsp;&nbsp;
{{fixedDepositProductData.preClosurePenalInterestOnType.value}}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.minBalanceForInterestCalculation">
<span fxFlex="40%">Balance Required For Interest Calculation:</span>
<span fxFlex="60%">{{ fixedDepositProductData.minBalanceForInterestCalculation | number }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Is withhold tax Applicable:</span>
<span fxFlex="60%">{{ fixedDepositProductData.withHoldTax ? 'Yes' : 'No' }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.withHoldTax">
<span fxFlex="40%">Withhold Tax group:</span>
<span fxFlex="60%">{{ fixedDepositProductData.taxGroup.name }}</span>
</div>
<div *ngIf="fixedDepositProductData.activeChart" fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column" >
<h3 class="mat-h3" fxFlexFill>Interest Rate Chart</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<div fxFlexFill *ngIf="fixedDepositProductData.activeChart.name">
<span fxFlex="40%">Name:</span>
<span fxFlex="60%">{{ fixedDepositProductData.activeChart.name }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Valid from Date:</span>
<span fxFlex="60%">{{ fixedDepositProductData.activeChart.fromDate | dateFormat }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.activeChart.endDate">
<span fxFlex="40%">End Date:</span>
<span fxFlex="60%">{{ fixedDepositProductData.activeChart.endDate | dateFormat }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.activeChart.description">
<span fxFlex="40%">Description:</span>
<span fxFlex="60%">{{ fixedDepositProductData.activeChart.description }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Primary Grouping by Amount:</span>
<span fxFlex="60%">{{ fixedDepositProductData.activeChart.isPrimaryGroupingByAmount ? 'Yes' : 'No' }}</span>
</div>
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="fixedDepositProductData.activeChart.chartSlabs" multiTemplateDataRows>
<ng-container matColumnDef="period">
<th mat-header-cell *matHeaderCellDef> Period </th>
<td mat-cell *matCellDef="let chartSlab">
<div *ngIf="chartSlab.fromPeriod !== undefined">
{{ chartSlab.fromPeriod }} - {{ chartSlab.toPeriod }} {{ chartSlab.periodType.value }}
</div>
<div *ngIf="chartSlab.fromPeriod == undefined">
&nbsp;
</div>
</td>
</ng-container>
<ng-container matColumnDef="amountRange">
<th mat-header-cell *matHeaderCellDef> Amount Range </th>
<td mat-cell *matCellDef="let chartSlab">
<div *ngIf="chartSlab.amountRangeFrom !== undefined">
{{ chartSlab.amountRangeFrom }} - {{ chartSlab.amountRangeTo }}
</div>
<div *ngIf="chartSlab.amountRangeFrom == undefined">
&nbsp;
</div>
</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 = expandChartSlabIndex === chartSlabIndex ? null : chartSlabIndex">
<span *ngIf="expandChartSlabIndex !== chartSlabIndex">
<fa-icon icon="eye" class="m-r-10"></fa-icon>
View Incentives
</span>
<span *ngIf="expandChartSlabIndex === chartSlabIndex">
<fa-icon icon="eye-slash" class="m-r-10"></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.length">
<div fxLayout="row wrap" fxFlexFill class="incentives" [@expandChartSlab]="chartSlabIndex === expandChartSlabIndex? '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:fixedDepositProductsTemplate.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:fixedDepositProductsTemplate.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:fixedDepositProductsTemplate.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:fixedDepositProductsTemplate.chartTemplate.genderOptions:'id':'name' }}</span>
<span *ngSwitchCase="3">{{ incentive.attributeValue }}</span>
<span *ngSwitchCase="4">{{ incentive.attributeValue | find:fixedDepositProductsTemplate.chartTemplate.clientTypeOptions:'id':'name' }}</span>
<span *ngSwitchCase="5">{{ incentive.attributeValue | find:fixedDepositProductsTemplate.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:fixedDepositProductsTemplate.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"></tr>
<tr mat-row *matRowDef="let row; columns: chartSlabsDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chartSlabsIncentivesDisplayedColumns;" class="incentives-row"></tr>
</table>
</div>
</div>
<div *ngIf="fixedDepositProductData.charges.length" fxFlexFill 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]="fixedDepositProductData.charges">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let charge">
{{ charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="type">
<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 | number }}
</td>
</ng-container>
<ng-container matColumnDef="collectedon">
<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 [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Type:</span>
<span fxFlex="60%">{{ fixedDepositProductData.accountingRule.value }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.accountingRule.id === 2" fxLayout="row wrap" fxLayout.lt-md="column">
<h4 fxFlexFill class="mat-h4">Assets</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Saving reference:</span>
<span fxFlex="60%">{{ fixedDepositProductData.accountingMappings.savingsReferenceAccount.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%">{{ fixedDepositProductData.accountingMappings.savingsControlAccount.name }}</span>
<span fxFlex="40%">Savings transfers in suspense:</span>
<span fxFlex="60%">{{ fixedDepositProductData.accountingMappings.transfersInSuspenseAccount.name }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Expenses</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Interest on savings:</span>
<span fxFlex="60%">{{ fixedDepositProductData.accountingMappings.interestOnSavingsAccount.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%">{{ fixedDepositProductData.accountingMappings.incomeFromFeeAccount.name }}</span>
<span fxFlex="40%">Income from penalties:</span>
<span fxFlex="60%">{{ fixedDepositProductData.accountingMappings.incomeFromPenaltyAccount.name }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.advancedAccountingRules && (fixedDepositProductData.paymentChannelToFundSourceMappings?.length || fixedDepositProductData.feeToIncomeAccountMappings?.length || fixedDepositProductData.penaltyToIncomeAccountMappings?.length)" fxLayout="row wrap" fxLayout.lt-md="column">
<h3 class="mat-h3" fxFlexFill>Advanced Accounting Rules</h3>
<mat-divider [inset]="true"></mat-divider>
<hr>
<div *ngIf="fixedDepositProductData.paymentChannelToFundSourceMappings?.length" fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<h4 class="mat-h4" fxFlexFill>Configure Fund Sources for Payment Channels</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table
[dataSource]="fixedDepositProductData.paymentChannelToFundSourceMappings">
<ng-container matColumnDef="paymentTypeId">
<th mat-header-cell *matHeaderCellDef> Payment Type </th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.paymentType.name }}
</td>
</ng-container>
<ng-container matColumnDef="fundSourceAccountId">
<th mat-header-cell *matHeaderCellDef> Fund Source </th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.fundSourceAccount.name }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="paymentFundSourceDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: paymentFundSourceDisplayedColumns;"></tr>
</table>
</div>
<div *ngIf="fixedDepositProductData.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]="fixedDepositProductData.feeToIncomeAccountMappings">
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef> Fees </th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef> Income Account </th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.incomeAccount.name }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns;"></tr>
</table>
</div>
<div *ngIf="fixedDepositProductData.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]="fixedDepositProductData.penaltyToIncomeAccountMappings">
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef> Penalty </th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef> Income Account </th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.incomeAccount.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>
</mat-card-content>
</mat-card>
</div>
@@ -0,0 +1,62 @@
@import "assets/styles/helper";
.tab-container {
padding: 1%;
margin: 1%;
}
.mat-h3 {
margin-top: 10px !important;
font-weight: 300;
color: $status-approved;
}
table {
width: 100%;
}
.mat-elevation-z1 {
margin: 1em 0 1.5em 0;
}
h2, h3, h4 {
margin: 0;
font-weight: 500;
}
span {
margin: 0.5em 0;
}
.mat-card .mat-divider-horizontal.mat-divider-inset {
margin: 0 0 0.5em 0;
}
.margin-t {
margin-top: 1em;
}
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;
}
}
}
}
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FixedDepositGeneralTabComponent } from './fixed-deposit-general-tab.component';
describe('FixedDepositGeneralTabComponent', () => {
let component: FixedDepositGeneralTabComponent;
let fixture: ComponentFixture<FixedDepositGeneralTabComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ FixedDepositGeneralTabComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(FixedDepositGeneralTabComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,43 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { trigger, state, transition, animate, style } from '@angular/animations';
@Component({
selector: 'mifosx-fixed-deposit-general-tab',
templateUrl: './fixed-deposit-general-tab.component.html',
styleUrls: ['./fixed-deposit-general-tab.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 FixedDepositGeneralTabComponent implements OnInit {
/** Fixed Deposit Product data. */
fixedDepositProductData: any;
fixedDepositProductsTemplate: any;
chartSlabsIncentivesDisplayedColumns: string[] = ['incentives'];
chartSlabsDisplayedColumns: string[] = ['period', 'amountRange', 'annualInterestRate', 'description', 'actions'];
incentivesDisplayedColumns: string[] = ['entityType', 'attributeName', 'conditionType', 'attributeValue', 'incentiveType', 'amount'];
chargesDisplayedColumns: string[] = ['name', 'type', 'amount', 'collectedon'];
paymentFundSourceDisplayedColumns: string[] = ['paymentTypeId', 'fundSourceAccountId'];
feesPenaltyIncomeDisplayedColumns: string[] = ['chargeId', 'incomeAccountId'];
/**
* Retrieves the fixed deposit product data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
*/
constructor(private route: ActivatedRoute) {
this.route.data.subscribe((data: { fixedDepositProduct: any, fixedDepositProductsTemplate: any }) => {
this.fixedDepositProductData = data.fixedDepositProduct;
this.fixedDepositProductsTemplate = data.fixedDepositProductsTemplate;
});
}
ngOnInit(): void {
}
}
@@ -1,495 +1,23 @@
<div fxLayout="row" fxLayoutAlign="end" fxLayoutGap="2%" fxLayout.lt-md="column" class="container m-b-20">
<button mat-raised-button color="primary" [routerLink]="['edit']">
<fa-icon icon="edit" class="m-r-10"></fa-icon>
Edit
</button>
</div>
<mat-card class="product-card">
<div class="container">
<mat-card-content>
<mat-card>
<nav mat-tab-nav-bar class="navigation-tabs">
<a mat-tab-link [routerLink]="['./general']" routerLinkActive #general="routerLinkActive"
[active]="general.isActive">
General
</a>
<ng-container *ngFor="let fixedDepositDatatable of fixedDepositDatatables">
<a mat-tab-link [routerLink]="['./datatables',fixedDepositDatatable.registeredTableName]" routerLinkActive
#datatable="routerLinkActive" [active]="datatable.isActive"
*mifosxHasPermission="'READ_' + fixedDepositDatatable.registeredTableName">
{{fixedDepositDatatable.registeredTableName}}
</a>
</ng-container>
</nav>
<mat-card-content>
<router-outlet></router-outlet>
<div fxLayout="row wrap" fxLayout.lt-md="column">
</mat-card-content>
<h2 class="mat-h2" fxFlexFill>{{ fixedDepositProductData.name }}</h2>
<mat-divider [inset]="true"></mat-divider>
<h3 class="mat-h3" fxFlexFill>Details</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Short Name:</span>
<span fxFlex="60%">{{ fixedDepositProductData.shortName }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.description">
<span fxFlex="40%">Description:</span>
<span fxFlex="60%">{{ fixedDepositProductData.description }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Currency</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Currency:</span>
<span fxFlex="60%">{{ fixedDepositProductData.currency.name }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Decimal Places:</span>
<span fxFlex="60%">{{ fixedDepositProductData.currency.decimalPlaces }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Currency in Multiples Of:</span>
<span fxFlex="60%">{{ fixedDepositProductData.currency.inMultiplesOf | number}}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Terms</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Deposit Amount:</span>
<span fxFlex="60%">{{ fixedDepositProductData.depositAmount + ' (Min: ' + (fixedDepositProductData.minDepositAmount ? fixedDepositProductData.minDepositAmount : fixedDepositProductData.depositAmount) + ', Max: ' + (fixedDepositProductData.maxDepositAmount ? fixedDepositProductData.maxDepositAmount : fixedDepositProductData.depositAmount) + ')' }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Interest Compounding Period:</span>
<span fxFlex="60%">{{ fixedDepositProductData.interestCompoundingPeriodType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Interest Posting Period:</span>
<span fxFlex="60%">{{ fixedDepositProductData.interestPostingPeriodType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Interest Calculated Using:</span>
<span fxFlex="60%">{{ fixedDepositProductData.interestCalculationType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Days in Years:</span>
<span fxFlex="60%">{{ fixedDepositProductData.interestCalculationDaysInYearType.value }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Settings</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill *ngIf="fixedDepositProductData.lockinPeriodFrequency">
<span fxFlex="40%">Lock-in Period:</span>
<span fxFlex="60%">
{{ fixedDepositProductData.lockinPeriodFrequency }} {{ fixedDepositProductData.lockinPeriodFrequencyType.value }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.minDepositTerm">
<span fxFlex="40%">Minimum Deposit Term:</span>
<span fxFlex="60%"
*ngIf="fixedDepositProductData.minDepositTerm !== undefined">{{ fixedDepositProductData.minDepositTerm }}
&nbsp;
{{ fixedDepositProductData.minDepositTermType.value }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.maxDepositTerm">
<span fxFlex="40%">Maximum Deposit Term:</span>
<span fxFlex="60%"
*ngIf="fixedDepositProductData.maxDepositTerm !== undefined">{{ fixedDepositProductData.maxDepositTerm }}
&nbsp;
{{ fixedDepositProductData.maxDepositTermType.value }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.inMultiplesOfDepositTerm">
<span fxFlex="40%">Deposit Term In multiple of:</span>
<span fxFlex="60%">{{ fixedDepositProductData.inMultiplesOfDepositTerm }}
-
{{ fixedDepositProductData.inMultiplesOfDepositTermType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Apply Penal Interest (less):</span>
<span fxFlex="60%">{{ fixedDepositProductData.preClosurePenalApplicable ? 'Yes' : 'No' }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.preClosurePenalApplicable">
<span fxFlex="40%">Penal Interest (%):</span>
<span fxFlex="60%">{{fixedDepositProductData.preClosurePenalInterest}} &nbsp; &nbsp; % &nbsp; &nbsp; On
&nbsp;&nbsp;
{{fixedDepositProductData.preClosurePenalInterestOnType.value}}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.minBalanceForInterestCalculation">
<span fxFlex="40%">Balance Required For Interest Calculation:</span>
<span fxFlex="60%">{{ fixedDepositProductData.minBalanceForInterestCalculation | number }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Is withhold tax Applicable:</span>
<span fxFlex="60%">{{ fixedDepositProductData.withHoldTax ? 'Yes' : 'No' }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.withHoldTax">
<span fxFlex="40%">Withhold Tax group:</span>
<span fxFlex="60%">{{ fixedDepositProductData.taxGroup.name }}</span>
</div>
<div *ngIf="fixedDepositProductData.activeChart" fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column" >
<h3 class="mat-h3" fxFlexFill>Interest Rate Chart</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<div fxFlexFill *ngIf="fixedDepositProductData.activeChart.name">
<span fxFlex="40%">Name:</span>
<span fxFlex="60%">{{ fixedDepositProductData.activeChart.name }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Valid from Date:</span>
<span fxFlex="60%">{{ fixedDepositProductData.activeChart.fromDate | dateFormat }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.activeChart.endDate">
<span fxFlex="40%">End Date:</span>
<span fxFlex="60%">{{ fixedDepositProductData.activeChart.endDate | dateFormat }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.activeChart.description">
<span fxFlex="40%">Description:</span>
<span fxFlex="60%">{{ fixedDepositProductData.activeChart.description }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Primary Grouping by Amount:</span>
<span fxFlex="60%">{{ fixedDepositProductData.activeChart.isPrimaryGroupingByAmount ? 'Yes' : 'No' }}</span>
</div>
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="fixedDepositProductData.activeChart.chartSlabs" multiTemplateDataRows>
<ng-container matColumnDef="period">
<th mat-header-cell *matHeaderCellDef> Period </th>
<td mat-cell *matCellDef="let chartSlab">
<div *ngIf="chartSlab.fromPeriod !== undefined">
{{ chartSlab.fromPeriod }} - {{ chartSlab.toPeriod }} {{ chartSlab.periodType.value }}
</div>
<div *ngIf="chartSlab.fromPeriod == undefined">
&nbsp;
</div>
</td>
</ng-container>
<ng-container matColumnDef="amountRange">
<th mat-header-cell *matHeaderCellDef> Amount Range </th>
<td mat-cell *matCellDef="let chartSlab">
<div *ngIf="chartSlab.amountRangeFrom !== undefined">
{{ chartSlab.amountRangeFrom }} - {{ chartSlab.amountRangeTo }}
</div>
<div *ngIf="chartSlab.amountRangeFrom == undefined">
&nbsp;
</div>
</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 = expandChartSlabIndex === chartSlabIndex ? null : chartSlabIndex">
<span *ngIf="expandChartSlabIndex !== chartSlabIndex">
<fa-icon icon="eye" class="m-r-10"></fa-icon>
View Incentives
</span>
<span *ngIf="expandChartSlabIndex === chartSlabIndex">
<fa-icon icon="eye-slash" class="m-r-10"></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.length">
<div fxLayout="row wrap" fxFlexFill class="incentives" [@expandChartSlab]="chartSlabIndex === expandChartSlabIndex? '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:fixedDepositProductsTemplate.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:fixedDepositProductsTemplate.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:fixedDepositProductsTemplate.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:fixedDepositProductsTemplate.chartTemplate.genderOptions:'id':'name' }}</span>
<span *ngSwitchCase="3">{{ incentive.attributeValue }}</span>
<span *ngSwitchCase="4">{{ incentive.attributeValue | find:fixedDepositProductsTemplate.chartTemplate.clientTypeOptions:'id':'name' }}</span>
<span *ngSwitchCase="5">{{ incentive.attributeValue | find:fixedDepositProductsTemplate.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:fixedDepositProductsTemplate.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"></tr>
<tr mat-row *matRowDef="let row; columns: chartSlabsDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chartSlabsIncentivesDisplayedColumns;" class="incentives-row"></tr>
</table>
</div>
</div>
<div *ngIf="fixedDepositProductData.charges.length" fxFlexFill 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]="fixedDepositProductData.charges">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let charge">
{{ charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="type">
<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 | number }}
</td>
</ng-container>
<ng-container matColumnDef="collectedon">
<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 [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Type:</span>
<span fxFlex="60%">{{ fixedDepositProductData.accountingRule.value }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.accountingRule.id === 2" fxLayout="row wrap" fxLayout.lt-md="column">
<h4 fxFlexFill class="mat-h4">Assets</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Saving reference:</span>
<span fxFlex="60%">{{ fixedDepositProductData.accountingMappings.savingsReferenceAccount.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%">{{ fixedDepositProductData.accountingMappings.savingsControlAccount.name }}</span>
<span fxFlex="40%">Savings transfers in suspense:</span>
<span fxFlex="60%">{{ fixedDepositProductData.accountingMappings.transfersInSuspenseAccount.name }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Expenses</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Interest on savings:</span>
<span fxFlex="60%">{{ fixedDepositProductData.accountingMappings.interestOnSavingsAccount.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%">{{ fixedDepositProductData.accountingMappings.incomeFromFeeAccount.name }}</span>
<span fxFlex="40%">Income from penalties:</span>
<span fxFlex="60%">{{ fixedDepositProductData.accountingMappings.incomeFromPenaltyAccount.name }}</span>
</div>
<div fxFlexFill *ngIf="fixedDepositProductData.advancedAccountingRules && (fixedDepositProductData.paymentChannelToFundSourceMappings?.length || fixedDepositProductData.feeToIncomeAccountMappings?.length || fixedDepositProductData.penaltyToIncomeAccountMappings?.length)" fxLayout="row wrap" fxLayout.lt-md="column">
<h3 class="mat-h3" fxFlexFill>Advanced Accounting Rules</h3>
<mat-divider [inset]="true"></mat-divider>
<hr>
<div *ngIf="fixedDepositProductData.paymentChannelToFundSourceMappings?.length" fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<h4 class="mat-h4" fxFlexFill>Configure Fund Sources for Payment Channels</h4>
<table fxFlexFill class="mat-elevation-z1" mat-table
[dataSource]="fixedDepositProductData.paymentChannelToFundSourceMappings">
<ng-container matColumnDef="paymentTypeId">
<th mat-header-cell *matHeaderCellDef> Payment Type </th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.paymentType.name }}
</td>
</ng-container>
<ng-container matColumnDef="fundSourceAccountId">
<th mat-header-cell *matHeaderCellDef> Fund Source </th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.fundSourceAccount.name }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="paymentFundSourceDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: paymentFundSourceDisplayedColumns;"></tr>
</table>
</div>
<div *ngIf="fixedDepositProductData.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]="fixedDepositProductData.feeToIncomeAccountMappings">
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef> Fees </th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef> Income Account </th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.incomeAccount.name }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns;"></tr>
</table>
</div>
<div *ngIf="fixedDepositProductData.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]="fixedDepositProductData.penaltyToIncomeAccountMappings">
<ng-container matColumnDef="chargeId">
<th mat-header-cell *matHeaderCellDef> Penalty </th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef> Income Account </th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.incomeAccount.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>
</mat-card-content>
</mat-card>
</div>
</mat-card>
@@ -1,49 +1,13 @@
table {
width: 100%;
}
.product-card {
margin: 0 auto;
max-width: 80rem;
width: 90%;
padding: 0;
.mat-elevation-z1 {
margin: 1em 0 1.5em 0;
}
h2, h3, h4 {
margin: 0;
font-weight: 500;
}
span {
margin: 0.5em 0;
}
.mat-card .mat-divider-horizontal.mat-divider-inset {
margin: 0 0 0.5em 0;
}
.margin-t {
margin-top: 1em;
}
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;
}
}
.navigation-tabs {
overflow: auto;
}
i:hover {
cursor: pointer;
}
}
@@ -1,9 +1,6 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { MatTable } from '@angular/material/table';
import { MatDialog } from '@angular/material/dialog';
import { trigger, state, transition, animate, style } from '@angular/animations';
/**
* Fixed Deposit Product component.
@@ -11,37 +8,21 @@ import { trigger, state, transition, animate, style } from '@angular/animations'
@Component({
selector: 'mifosx-view-fixed-deposit-product',
templateUrl: './view-fixed-deposit-product.component.html',
styleUrls: ['./view-fixed-deposit-product.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)'))
])
]
styleUrls: ['./view-fixed-deposit-product.component.scss']
})
export class ViewFixedDepositProductComponent implements OnInit {
/** Fixed Deposit Product data. */
fixedDepositProductData: any;
fixedDepositProductsTemplate: any;
fixedDepositDatatables: any = [];
chartSlabsIncentivesDisplayedColumns: string[] = ['incentives'];
chartSlabsDisplayedColumns: string[] = ['period', 'amountRange', 'annualInterestRate', 'description', 'actions'];
incentivesDisplayedColumns: string[] = ['entityType', 'attributeName', 'conditionType', 'attributeValue', 'incentiveType', 'amount'];
chargesDisplayedColumns: string[] = ['name', 'type', 'amount', 'collectedon'];
paymentFundSourceDisplayedColumns: string[] = ['paymentTypeId', 'fundSourceAccountId'];
feesPenaltyIncomeDisplayedColumns: string[] = ['chargeId', 'incomeAccountId'];
/**
* Retrieves the fixed deposit product data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
*/
constructor(private route: ActivatedRoute) {
this.route.data.subscribe((data: { fixedDepositProduct: any, fixedDepositProductsTemplate: any }) => {
this.fixedDepositProductData = data.fixedDepositProduct;
this.fixedDepositProductsTemplate = data.fixedDepositProductsTemplate;
this.route.data.subscribe((data: { fixedDepositDatatables: any }) => {
this.fixedDepositDatatables = [];
data.fixedDepositDatatables.forEach((datatable: any) => {
if (datatable.entitySubType === 'Fixed Deposit') {
this.fixedDepositDatatables.push(datatable);
}
});
});
}
@@ -47,12 +47,12 @@
<ng-container matColumnDef="fromDate">
<th mat-header-cell *matHeaderCellDef mat-sort-header> From Date </th>
<td mat-cell *matCellDef="let floatingRatePeriod"> {{ floatingRatePeriod.fromDate | dateFormat : 'dd MMMM yyyy' }} </td>
<td mat-cell *matCellDef="let floatingRatePeriod"> {{ floatingRatePeriod.fromDate | dateFormat }} </td>
</ng-container>
<ng-container matColumnDef="interestRate">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Interest Rate </th>
<td mat-cell *matCellDef="let floatingRatePeriod"> {{ floatingRatePeriod.interestRate }} </td>
<td mat-cell *matCellDef="let floatingRatePeriod"> {{ floatingRatePeriod.interestRate | number }} </td>
</ng-container>
<ng-container matColumnDef="isDifferential">
@@ -68,11 +68,11 @@
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> Actions </th>
<td mat-cell *matCellDef="let floatingRatePeriod" fxLayoutGap="15%">
<button type="button" fxFlex="8%" color="primary" mat-icon-button
<button type="button" fxFlex="8%" color="primary" mat-icon-button matTooltip="Edit Period" matTooltipPosition="left"
(click)="editFloatingRatePeriod(floatingRatePeriod)">
<fa-icon icon="edit" size="lg"></fa-icon>
</button>
<button type="button" fxFlex="8%" color="warn" mat-icon-button
<button type="button" fxFlex="8%" color="warn" mat-icon-button matTooltip="Remove Period" matTooltipPosition="right"
(click)="deleteFloatingRatePeriod(floatingRatePeriod)">
<fa-icon icon="trash" size="lg"></fa-icon>
</button>
@@ -106,7 +106,9 @@ export class CreateFloatingRateComponent implements OnInit {
*/
addFloatingRatePeriod() {
const floatingRatePeriodDialogRef = this.dialog.open(FloatingRatePeriodDialogComponent, {
data: {}
data: {
fromDate: this.settingsService.businessDate
}
});
floatingRatePeriodDialogRef.afterClosed().subscribe((response: any) => {
if (response) {
@@ -131,7 +133,8 @@ export class CreateFloatingRateComponent implements OnInit {
data: {
fromDate: ratePeriod.fromDate,
interestRate: ratePeriod.interestRate,
isDifferentialToBaseLendingRate: ratePeriod.isDifferentialToBaseLendingRate
isDifferentialToBaseLendingRate: ratePeriod.isDifferentialToBaseLendingRate,
isNew: true
}
});
editFloatingRatePeriodDialogRef.afterClosed().subscribe((response: any) => {
@@ -24,7 +24,7 @@
</mat-error>
</mat-form-field>
<mat-checkbox class="is-differential" formControlName="isDifferentialToBaseLendingRate" labelPosition="before">
<mat-checkbox class="is-differential" formControlName="isDifferentialToBaseLendingRate" labelPosition="after">
Is Differential?
</mat-checkbox>
@@ -38,4 +38,4 @@
<button mat-button mat-dialog-close>Cancel</button>
<button mat-raised-button color="primary"
[disabled]="!floatingRatePeriodForm.valid || floatingRatePeriodForm.pristine" (click)="submit()">Submit</button>
</mat-dialog-actions>
</mat-dialog-actions>
@@ -2,6 +2,7 @@
import { Component, OnInit, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { SettingsService } from 'app/settings/settings.service';
/**
* Floating Rate Period Dialog Component.
@@ -25,6 +26,7 @@ export class FloatingRatePeriodDialogComponent implements OnInit {
*/
constructor(public dialogRef: MatDialogRef<FloatingRatePeriodDialogComponent>,
public formBuilder: FormBuilder,
private settingsService: SettingsService,
@Inject(MAT_DIALOG_DATA) public data: any) {
}
@@ -32,7 +34,14 @@ export class FloatingRatePeriodDialogComponent implements OnInit {
* Creates the floating rate period form.
*/
ngOnInit() {
const rowDisabled: Boolean = this.data ? (new Date(this.data.fromDate) < new Date() ? true : false) : false;
this.minDate = this.settingsService.businessDate;
let rowDisabled = false;
if (this.data && (new Date(this.data.fromDate) < this.minDate)) {
rowDisabled = true;
}
if (this.data.isNew) {
rowDisabled = false;
}
this.floatingRatePeriodForm = this.formBuilder.group({
'fromDate': [{ value: this.data ? new Date(this.data.fromDate) : '', disabled: rowDisabled }, Validators.required],
'interestRate': [{ value: this.data ? this.data.interestRate : '', disabled: rowDisabled }, Validators.required],
+48 -12
View File
@@ -120,6 +120,10 @@ import { SavingProductDatatableResolver } from './saving-products/saving-product
import { SavingProductDatatablesResolver } from './saving-products/saving-product-datatables.resolver';
import { SavingProductGeneralTabComponent } from './saving-products/view-saving-product/saving-product-general-tab/saving-product-general-tab.component';
import { SavingProductDatatableTabComponent } from './saving-products/view-saving-product/saving-product-datatable-tab/saving-product-datatable-tab.component';
import { FixedDepositGeneralTabComponent } from './fixed-deposit-products/view-fixed-deposit-product/fixed-deposit-general-tab/fixed-deposit-general-tab.component';
import { FixedDepositDatatableTabComponent } from './fixed-deposit-products/view-fixed-deposit-product/fixed-deposit-datatable-tab/fixed-deposit-datatable-tab.component';
import { RecurringDepositGeneralTabComponent } from './recurring-deposit-products/view-recurring-deposit-product/recurring-deposit-general-tab/recurring-deposit-general-tab.component';
import { RecurringDepositDatatableTabComponent } from './recurring-deposit-products/view-recurring-deposit-product/recurring-deposit-datatable-tab/recurring-deposit-datatable-tab.component';
/** Products Routes */
const routes: Routes = [
@@ -556,20 +560,36 @@ const routes: Routes = [
}
},
{
path: ':id',
data: { title: extract('View Recurring Deposit Product'), routeParamBreadcrumb: 'id' },
path: ':productId',
data: { title: extract('View Recurring Deposit Product'), breadcrumb: 'productId', routeParamBreadcrumb: 'productId' },
component: ViewRecurringDepositProductComponent,
resolve: {
recurringDepositProduct: RecurringDepositProductResolver
recurringDepositDatatables: SavingProductDatatablesResolver
},
children: [
{
path: '',
component: ViewRecurringDepositProductComponent,
redirectTo: 'general',
pathMatch: 'full'
},
{
path: 'general',
component: RecurringDepositGeneralTabComponent,
resolve: {
recurringDepositProduct: RecurringDepositProductResolver,
recurringDepositProductsTemplate: RecurringDepositProductsTemplateResolver
recurringDepositProduct: RecurringDepositProductResolver
}
},
{
path: 'datatables',
children: [{
path: ':datatableName',
component: RecurringDepositDatatableTabComponent,
data: { title: extract('Data Table View'), routeParamBreadcrumb: 'datatableName' },
resolve: {
recurringDepositDatatable: SavingProductDatatableResolver
}
}]
},
{
path: 'edit',
data: { title: extract('Edit Recurring Deposit Product'), breadcrumb: 'edit', routeParamBreadcrumb: false },
@@ -602,20 +622,36 @@ const routes: Routes = [
},
},
{
path: ':id',
data: { title: extract('View Fixed Deposit Product'), routeParamBreadcrumb: 'id' },
path: ':productId',
data: { title: extract('View Fixed Deposit Product'), breadcrumb: 'productId', routeParamBreadcrumb: 'productId' },
component: ViewFixedDepositProductComponent,
resolve: {
fixedDepositProduct: FixedDepositProductResolver,
fixedDepositDatatables: SavingProductDatatablesResolver
},
children: [
{
path: '',
component: ViewFixedDepositProductComponent,
redirectTo: 'general',
pathMatch: 'full'
},
{
path: 'general',
component: FixedDepositGeneralTabComponent,
resolve: {
fixedDepositProduct: FixedDepositProductResolver,
fixedDepositProductsTemplate: FixedDepositProductsTemplateResolver
fixedDepositProduct: FixedDepositProductResolver
}
},
{
path: 'datatables',
children: [{
path: ':datatableName',
component: FixedDepositDatatableTabComponent,
data: { title: extract('Data Table View'), routeParamBreadcrumb: 'datatableName' },
resolve: {
fixedDepositDatatable: SavingProductDatatableResolver
}
}]
},
{
path: 'edit',
data: { title: extract('Edit Fixed Deposit Product'), breadcrumb: 'edit', routeParamBreadcrumb: false },
+9 -1
View File
@@ -110,6 +110,10 @@ import { DatatableTabComponent } from './loan-products/view-loan-product/datatab
import { GeneralTabComponent } from './loan-products/view-loan-product/general-tab/general-tab.component';
import { SavingProductGeneralTabComponent } from './saving-products/view-saving-product/saving-product-general-tab/saving-product-general-tab.component';
import { SavingProductDatatableTabComponent } from './saving-products/view-saving-product/saving-product-datatable-tab/saving-product-datatable-tab.component';
import { FixedDepositGeneralTabComponent } from './fixed-deposit-products/view-fixed-deposit-product/fixed-deposit-general-tab/fixed-deposit-general-tab.component';
import { FixedDepositDatatableTabComponent } from './fixed-deposit-products/view-fixed-deposit-product/fixed-deposit-datatable-tab/fixed-deposit-datatable-tab.component';
import { RecurringDepositDatatableTabComponent } from './recurring-deposit-products/view-recurring-deposit-product/recurring-deposit-datatable-tab/recurring-deposit-datatable-tab.component';
import { RecurringDepositGeneralTabComponent } from './recurring-deposit-products/view-recurring-deposit-product/recurring-deposit-general-tab/recurring-deposit-general-tab.component';
/**
* Products Module
@@ -227,7 +231,11 @@ import { SavingProductDatatableTabComponent } from './saving-products/view-savin
DatatableTabComponent,
GeneralTabComponent,
SavingProductGeneralTabComponent,
SavingProductDatatableTabComponent
SavingProductDatatableTabComponent,
FixedDepositGeneralTabComponent,
FixedDepositDatatableTabComponent,
RecurringDepositDatatableTabComponent,
RecurringDepositGeneralTabComponent
],
entryComponents: [
DepositProductIncentiveFormDialogComponent,
@@ -25,8 +25,8 @@ export class RecurringDepositProductAndTemplateResolver implements Resolve<Objec
* @returns {Observable<any>}
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const recurringDepositProductId = route.paramMap.get('id');
return this.productsService.getRecurringDepositProductAndTemplate(recurringDepositProductId);
const productId = route.parent.paramMap.get('productId');
return this.productsService.getRecurringDepositProductAndTemplate(productId);
}
}
@@ -24,8 +24,8 @@ export class RecurringDepositProductResolver implements Resolve<Object> {
* @returns {Observable<any>}
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const id = route.paramMap.get('id');
return this.productsService.getRecurringDepositProduct(id);
const productId = route.parent.paramMap.get('productId');
return this.productsService.getRecurringDepositProduct(productId);
}
}
@@ -0,0 +1,9 @@
<div class="tab-container mat-typography">
<mifosx-entity-datatable-tab
entityType="Recurring Deposit Product"
[entityId]="entityId"
[multiRowDatatableFlag]="multiRowDatatableFlag"
[entityDatatable]="entityDatatable"
>
</mifosx-entity-datatable-tab>
</div>
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RecurringDepositDatatableTabComponent } from './recurring-deposit-datatable-tab.component';
describe('RecurringDepositDatatableTabComponent', () => {
let component: RecurringDepositDatatableTabComponent;
let fixture: ComponentFixture<RecurringDepositDatatableTabComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ RecurringDepositDatatableTabComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(RecurringDepositDatatableTabComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,27 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'mifosx-recurring-deposit-datatable-tab',
templateUrl: './recurring-deposit-datatable-tab.component.html',
styleUrls: ['./recurring-deposit-datatable-tab.component.scss']
})
export class RecurringDepositDatatableTabComponent implements OnInit {
entityId: string;
entityDatatable: any;
multiRowDatatableFlag: boolean;
constructor(private route: ActivatedRoute) {
this.entityId = this.route.parent.parent.snapshot.paramMap.get('productId');
this.route.data.subscribe((data: { recurringDepositDatatable: any }) => {
this.entityDatatable = data.recurringDepositDatatable;
this.multiRowDatatableFlag = this.entityDatatable.columnHeaders[0].columnName === 'id' ? true : false;
});
}
ngOnInit(): void {
}
}
@@ -0,0 +1,499 @@
<div fxLayout="row" fxLayoutAlign="end" fxLayoutGap="2%" fxLayout.lt-md="column" class="container m-b-20">
<button mat-raised-button color="primary" [routerLink]="['../edit']">
<fa-icon icon="edit" class="m-r-10"></fa-icon>
Edit
</button>
</div>
<div class="container">
<mat-card>
<mat-card-content>
<div fxLayout="row wrap" fxLayout.lt-md="column">
<h2 class="mat-h2" fxFlexFill>{{ recurringDepositProduct.name }}</h2>
<mat-divider [inset]="true"></mat-divider>
<h3 class="mat-h3" fxFlexFill>Details</h3>
<mat-divider [inset]="true"></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 Details</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Currency:</span>
<span fxFlex="60%">{{ recurringDepositProduct.currency.name }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Decimal Places:</span>
<span fxFlex="60%">{{ recurringDepositProduct.currency.decimalPlaces }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Currency in Multiples Of:</span>
<span fxFlex="60%">{{ recurringDepositProduct.currency.inMultiplesOf | number}}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Terms</h3>
<mat-divider [inset]="true"></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.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Interest Posting Period:</span>
<span fxFlex="60%">{{ recurringDepositProduct.interestPostingPeriodType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Interested Calculated Using:</span>
<span fxFlex="60%">{{ recurringDepositProduct.interestCalculationType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Days in Years:</span>
<span fxFlex="60%">{{ recurringDepositProduct.interestCalculationDaysInYearType.value }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Settings</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill *ngIf="recurringDepositProduct.lockinPeriodFrequency">
<span fxFlex="40%">Lock-in Period:</span>
<span fxFlex="60%" *ngIf="recurringDepositProduct.lockinPeriodFrequency !== undefined">
{{ recurringDepositProduct.lockinPeriodFrequency }}
{{ recurringDepositProduct.lockinPeriodFrequencyType.value }}</span>
</div>
<div fxFlexFill *ngIf="recurringDepositProduct.minDepositTerm">
<span fxFlex="40%">Minimum Deposit Term:</span>
<span fxFlex="60%"
*ngIf="recurringDepositProduct.minDepositTerm !== undefined">{{ recurringDepositProduct.minDepositTerm }}
&nbsp;
{{ recurringDepositProduct.minDepositTermType.value }}</span>
</div>
<div fxFlexFill *ngIf="recurringDepositProduct.maxDepositTerm">
<span fxFlex="40%">Maximum Deposit Term:</span>
<span fxFlex="60%"
*ngIf="recurringDepositProduct.maxDepositTerm !== undefined">{{ recurringDepositProduct.maxDepositTerm }}
&nbsp;
{{ recurringDepositProduct.maxDepositTermType.value }}</span>
</div>
<div fxFlexFill *ngIf="recurringDepositProduct.inMultipleOfDepositTerm">
<span fxFlex="40%">Deposit Term In multiple of:</span>
<span fxFlex="60%"
*ngIf="recurringDepositProduct.inMultipleOfDepositTerm !== undefined">{{ recurringDepositProduct.inMultipleOfDepositTerm }}
-
{{ recurringDepositProduct.inMultipleOfDepositTermType.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 *ngIf="recurringDepositProduct.preClosurePenalInterest">
<span fxFlex="40%">Apply penal interest (less):</span>
<span fxFlex="60%">{{recurringDepositProduct.preClosurePenalInterest}} &nbsp; &nbsp; % &nbsp; &nbsp; On
&nbsp;&nbsp;
{{recurringDepositProduct.preClosurePenalInterestOnType.value}}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Is withhold tax Applicable:</span>
<span fxFlex="60%">{{ recurringDepositProduct.withHoldTax }}</span>
</div>
<div fxFlexFill *ngIf="recurringDepositProduct.withHoldTax">
<span fxFlex="40%">Withhold Tax group:</span>
<span fxFlex="60%">{{ recurringDepositProduct.taxGroup.name }}</span>
</div>
<div *ngIf="recurringDepositProduct.activeChart" fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column" >
<h3 class="mat-h3" fxFlexFill>Interest Rate Charts</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<div fxFlexFill *ngIf="recurringDepositProduct.activeChart.name">
<span fxFlex="40%">Name:</span>
<span fxFlex="60%">{{ recurringDepositProduct.activeChart.name }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Valid from Date:</span>
<span fxFlex="60%">{{ recurringDepositProduct.activeChart.fromDate | dateFormat }}</span>
</div>
<div fxFlexFill *ngIf="recurringDepositProduct.activeChart.endDate">
<span fxFlex="40%">End Date:</span>
<span fxFlex="60%">{{ recurringDepositProduct.activeChart.endDate | dateFormat }}</span>
</div>
<div fxFlexFill *ngIf="recurringDepositProduct.activeChart.description">
<span fxFlex="40%">Description:</span>
<span fxFlex="60%">{{ recurringDepositProduct.activeChart.description }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Primary Grouping by Amount:</span>
<span fxFlex="60%">{{ recurringDepositProduct.activeChart.isPrimaryGroupingByAmount ? 'Yes' : 'No' }}</span>
</div>
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="recurringDepositProduct.activeChart.chartSlabs" multiTemplateDataRows>
<ng-container matColumnDef="period">
<th mat-header-cell *matHeaderCellDef> Period </th>
<td mat-cell *matCellDef="let chartSlab">
<div *ngIf="chartSlab.fromPeriod !== undefined">
{{ chartSlab.fromPeriod }} - {{ chartSlab.toPeriod }} {{ chartSlab.periodType.value }}
</div>
<div *ngIf="chartSlab.fromPeriod == undefined">
&nbsp;
</div>
</td>
</ng-container>
<ng-container matColumnDef="amountRange">
<th mat-header-cell *matHeaderCellDef> Amount Range </th>
<td mat-cell *matCellDef="let chartSlab">
<div *ngIf="chartSlab.amountRangeFrom !== undefined">
{{ chartSlab.amountRangeFrom }} - {{ chartSlab.amountRangeTo }}
</div>
<div *ngIf="chartSlab.amountRangeFrom == undefined">
&nbsp;
</div>
</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 = expandChartSlabIndex === chartSlabIndex ? null : chartSlabIndex">
<span *ngIf="expandChartSlabIndex !== chartSlabIndex">
<fa-icon icon="eye" class="m-r-10"></fa-icon>
View Incentives
</span>
<span *ngIf="expandChartSlabIndex === chartSlabIndex">
<fa-icon icon="eye-slash" class="m-r-10"></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.length">
<div fxLayout="row wrap" fxFlexFill class="incentives" [@expandChartSlab]="chartSlabIndex === expandChartSlabIndex? '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:recurringDepositProductTemplate.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:recurringDepositProductTemplate.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:recurringDepositProductTemplate.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:recurringDepositProductTemplate.chartTemplate.genderOptions:'id':'name' }}</span>
<span *ngSwitchCase="3">{{ incentive.attributeValue }}</span>
<span *ngSwitchCase="4">{{ incentive.attributeValue | find:recurringDepositProductTemplate.chartTemplate.clientTypeOptions:'id':'name' }}</span>
<span *ngSwitchCase="5">{{ incentive.attributeValue | find:recurringDepositProductTemplate.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:recurringDepositProductTemplate.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"></tr>
<tr mat-row *matRowDef="let row; columns: chartSlabsDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chartSlabsIncentivesDisplayedColumns;" class="incentives-row"></tr>
</table>
<mat-divider [inset]="true"></mat-divider>
</div>
</div>
<div *ngIf="recurringDepositProduct.charges.length" fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<h3 class="mat-h3" fxFlexFill>Charges</h3>
<mat-divider [inset]="true"></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 }}
</td>
</ng-container>
<ng-container matColumnDef="type">
<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 | number }}
</td>
</ng-container>
<ng-container matColumnDef="collectedon">
<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 [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Type:</span>
<span fxFlex="60%">{{ recurringDepositProduct.accountingRule.value }}</span>
</div>
<div fxFlexFill *ngIf="recurringDepositProduct.accountingRule.id === 2" fxLayout="row wrap" fxLayout.lt-md="column">
<h4 fxFlexFill class="mat-h4">Assets</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Saving reference:</span>
<span fxFlex="60%">{{ recurringDepositProduct.accountingMappings.savingsReferenceAccount.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.accountingMappings.savingsControlAccount.name }}</span>
<span fxFlex="40%">Savings transfers in suspense:</span>
<span fxFlex="60%">{{ recurringDepositProduct.accountingMappings.transfersInSuspenseAccount.name }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Expenses</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Interest on savings:</span>
<span fxFlex="60%">{{ recurringDepositProduct.accountingMappings.interestOnSavingsAccount.name }}</span>
<span fxFlex="40%">Write-off:</span>
<span fxFlex="60%">{{ recurringDepositProduct.accountingMappings.writeOffAccount.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.accountingMappings.incomeFromFeeAccount.name }}</span>
<span fxFlex="40%">Income from penalties:</span>
<span fxFlex="60%">{{ recurringDepositProduct.accountingMappings.incomeFromPenaltyAccount.name }}</span>
</div>
<div fxFlexFill *ngIf="recurringDepositProduct.paymentChannelToFundSourceMappings?.length || recurringDepositProduct.feeToIncomeAccountMappings?.length || recurringDepositProduct.penaltyToIncomeAccountMappings?.length " fxLayout="row wrap" fxLayout.lt-md="column">
<h3 class="mat-h3" fxFlexFill>Advanced Accounting Rules</h3>
<mat-divider [inset]="true"></mat-divider>
<div *ngIf="recurringDepositProduct.paymentChannelToFundSourceMappings?.length" fxFlexFill fxLayout="row wrap"
fxLayout.lt-md="column">
<h4 class="mat-h4" fxFlexFill>Configure 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.paymentType.name }}
</td>
</ng-container>
<ng-container matColumnDef="fundSourceAccountId">
<th mat-header-cell *matHeaderCellDef> Fund Source </th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.fundSourceAccount.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.charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef> Income Account </th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.incomeAccount.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.charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef> Income Account </th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.incomeAccount.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>
</mat-card-content>
</mat-card>
</div>
@@ -0,0 +1,83 @@
@import "assets/styles/helper";
.tab-container {
padding: 1%;
margin: 1%;
}
.mat-h3 {
margin-top: 10px !important;
font-weight: 300;
color: $status-approved;
}
table {
width: 100%;
}
.mat-elevation-z1 {
margin: 1em 0 1.5em 0;
}
h2, h3, h4 {
margin: 0;
font-weight: 500;
}
span {
margin: 0.5em 0;
}
.margin-t {
margin-top: 1em;
}
.interestCarts {
float:right;
}
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;
}
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RecurringDepositGeneralTabComponent } from './recurring-deposit-general-tab.component';
describe('RecurringDepositGeneralTabComponent', () => {
let component: RecurringDepositGeneralTabComponent;
let fixture: ComponentFixture<RecurringDepositGeneralTabComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ RecurringDepositGeneralTabComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(RecurringDepositGeneralTabComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,39 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { trigger, state, transition, animate, style } from '@angular/animations';
@Component({
selector: 'mifosx-recurring-deposit-general-tab',
templateUrl: './recurring-deposit-general-tab.component.html',
styleUrls: ['./recurring-deposit-general-tab.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 RecurringDepositGeneralTabComponent implements OnInit {
recurringDepositProduct: any;
recurringDepositProductTemplate: any;
chartSlabsIncentivesDisplayedColumns: string[] = ['incentives'];
chartSlabsDisplayedColumns: string[] = ['period', 'amountRange', 'annualInterestRate', 'description', 'actions'];
incentivesDisplayedColumns: string[] = ['entityType', 'attributeName', 'conditionType', 'attributeValue', 'incentiveType', 'amount'];
chargesDisplayedColumns: string[] = ['name', 'type', 'amount', 'collectedon'];
paymentFundSourceDisplayedColumns: string[] = ['paymentTypeId', 'fundSourceAccountId'];
feesPenaltyIncomeDisplayedColumns: string[] = ['chargeId', 'incomeAccountId'];
constructor(private route: ActivatedRoute) {
this.route.data.subscribe((data: { recurringDepositProduct: any, recurringDepositProductsTemplate: any}) => {
this.recurringDepositProduct = data.recurringDepositProduct;
this.recurringDepositProductTemplate = data.recurringDepositProductsTemplate;
});
}
ngOnInit(): void {
}
}
@@ -1,499 +1,23 @@
<div fxLayout="row" fxLayoutAlign="end" fxLayoutGap="2%" fxLayout.lt-md="column" class="container m-b-20">
<button mat-raised-button color="primary" [routerLink]="['edit']">
<fa-icon icon="edit" class="m-r-10"></fa-icon>
Edit
</button>
</div>
<mat-card class="product-card">
<div class="container">
<mat-card-content>
<mat-card>
<nav mat-tab-nav-bar class="navigation-tabs">
<a mat-tab-link [routerLink]="['./general']" routerLinkActive #general="routerLinkActive"
[active]="general.isActive">
General
</a>
<ng-container *ngFor="let recurringDepositDatatable of recurringDepositDatatables">
<a mat-tab-link [routerLink]="['./datatables',recurringDepositDatatable.registeredTableName]" routerLinkActive
#datatable="routerLinkActive" [active]="datatable.isActive"
*mifosxHasPermission="'READ_' + recurringDepositDatatable.registeredTableName">
{{recurringDepositDatatable.registeredTableName}}
</a>
</ng-container>
</nav>
<mat-card-content>
<router-outlet></router-outlet>
<div fxLayout="row wrap" fxLayout.lt-md="column">
</mat-card-content>
<h2 class="mat-h2" fxFlexFill>{{ recurringDepositProduct.name }}</h2>
<mat-divider [inset]="true"></mat-divider>
<h3 class="mat-h3" fxFlexFill>Details</h3>
<mat-divider [inset]="true"></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 Details</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Currency:</span>
<span fxFlex="60%">{{ recurringDepositProduct.currency.name }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Decimal Places:</span>
<span fxFlex="60%">{{ recurringDepositProduct.currency.decimalPlaces }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Currency in Multiples Of:</span>
<span fxFlex="60%">{{ recurringDepositProduct.currency.inMultiplesOf | number}}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Terms</h3>
<mat-divider [inset]="true"></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.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Interest Posting Period:</span>
<span fxFlex="60%">{{ recurringDepositProduct.interestPostingPeriodType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Interested Calculated Using:</span>
<span fxFlex="60%">{{ recurringDepositProduct.interestCalculationType.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Days in Years:</span>
<span fxFlex="60%">{{ recurringDepositProduct.interestCalculationDaysInYearType.value }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Settings</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill *ngIf="recurringDepositProduct.lockinPeriodFrequency">
<span fxFlex="40%">Lock-in Period:</span>
<span fxFlex="60%" *ngIf="recurringDepositProduct.lockinPeriodFrequency !== undefined">
{{ recurringDepositProduct.lockinPeriodFrequency }}
{{ recurringDepositProduct.lockinPeriodFrequencyType.value }}</span>
</div>
<div fxFlexFill *ngIf="recurringDepositProduct.minDepositTerm">
<span fxFlex="40%">Minimum Deposit Term:</span>
<span fxFlex="60%"
*ngIf="recurringDepositProduct.minDepositTerm !== undefined">{{ recurringDepositProduct.minDepositTerm }}
&nbsp;
{{ recurringDepositProduct.minDepositTermType.value }}</span>
</div>
<div fxFlexFill *ngIf="recurringDepositProduct.maxDepositTerm">
<span fxFlex="40%">Maximum Deposit Term:</span>
<span fxFlex="60%"
*ngIf="recurringDepositProduct.maxDepositTerm !== undefined">{{ recurringDepositProduct.maxDepositTerm }}
&nbsp;
{{ recurringDepositProduct.maxDepositTermType.value }}</span>
</div>
<div fxFlexFill *ngIf="recurringDepositProduct.inMultipleOfDepositTerm">
<span fxFlex="40%">Deposit Term In multiple of:</span>
<span fxFlex="60%"
*ngIf="recurringDepositProduct.inMultipleOfDepositTerm !== undefined">{{ recurringDepositProduct.inMultipleOfDepositTerm }}
-
{{ recurringDepositProduct.inMultipleOfDepositTermType.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 *ngIf="recurringDepositProduct.preClosurePenalInterest">
<span fxFlex="40%">Apply penal interest (less):</span>
<span fxFlex="60%">{{recurringDepositProduct.preClosurePenalInterest}} &nbsp; &nbsp; % &nbsp; &nbsp; On
&nbsp;&nbsp;
{{recurringDepositProduct.preClosurePenalInterestOnType.value}}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Is withhold tax Applicable:</span>
<span fxFlex="60%">{{ recurringDepositProduct.withHoldTax }}</span>
</div>
<div fxFlexFill *ngIf="recurringDepositProduct.withHoldTax">
<span fxFlex="40%">Withhold Tax group:</span>
<span fxFlex="60%">{{ recurringDepositProduct.taxGroup.name }}</span>
</div>
<div *ngIf="recurringDepositProduct.activeChart" fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column" >
<h3 class="mat-h3" fxFlexFill>Interest Rate Charts</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<div fxFlexFill *ngIf="recurringDepositProduct.activeChart.name">
<span fxFlex="40%">Name:</span>
<span fxFlex="60%">{{ recurringDepositProduct.activeChart.name }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Valid from Date:</span>
<span fxFlex="60%">{{ recurringDepositProduct.activeChart.fromDate | dateFormat }}</span>
</div>
<div fxFlexFill *ngIf="recurringDepositProduct.activeChart.endDate">
<span fxFlex="40%">End Date:</span>
<span fxFlex="60%">{{ recurringDepositProduct.activeChart.endDate | dateFormat }}</span>
</div>
<div fxFlexFill *ngIf="recurringDepositProduct.activeChart.description">
<span fxFlex="40%">Description:</span>
<span fxFlex="60%">{{ recurringDepositProduct.activeChart.description }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Primary Grouping by Amount:</span>
<span fxFlex="60%">{{ recurringDepositProduct.activeChart.isPrimaryGroupingByAmount ? 'Yes' : 'No' }}</span>
</div>
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="recurringDepositProduct.activeChart.chartSlabs" multiTemplateDataRows>
<ng-container matColumnDef="period">
<th mat-header-cell *matHeaderCellDef> Period </th>
<td mat-cell *matCellDef="let chartSlab">
<div *ngIf="chartSlab.fromPeriod !== undefined">
{{ chartSlab.fromPeriod }} - {{ chartSlab.toPeriod }} {{ chartSlab.periodType.value }}
</div>
<div *ngIf="chartSlab.fromPeriod == undefined">
&nbsp;
</div>
</td>
</ng-container>
<ng-container matColumnDef="amountRange">
<th mat-header-cell *matHeaderCellDef> Amount Range </th>
<td mat-cell *matCellDef="let chartSlab">
<div *ngIf="chartSlab.amountRangeFrom !== undefined">
{{ chartSlab.amountRangeFrom }} - {{ chartSlab.amountRangeTo }}
</div>
<div *ngIf="chartSlab.amountRangeFrom == undefined">
&nbsp;
</div>
</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 = expandChartSlabIndex === chartSlabIndex ? null : chartSlabIndex">
<span *ngIf="expandChartSlabIndex !== chartSlabIndex">
<fa-icon icon="eye" class="m-r-10"></fa-icon>
View Incentives
</span>
<span *ngIf="expandChartSlabIndex === chartSlabIndex">
<fa-icon icon="eye-slash" class="m-r-10"></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.length">
<div fxLayout="row wrap" fxFlexFill class="incentives" [@expandChartSlab]="chartSlabIndex === expandChartSlabIndex? '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:recurringDepositProductTemplate.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:recurringDepositProductTemplate.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:recurringDepositProductTemplate.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:recurringDepositProductTemplate.chartTemplate.genderOptions:'id':'name' }}</span>
<span *ngSwitchCase="3">{{ incentive.attributeValue }}</span>
<span *ngSwitchCase="4">{{ incentive.attributeValue | find:recurringDepositProductTemplate.chartTemplate.clientTypeOptions:'id':'name' }}</span>
<span *ngSwitchCase="5">{{ incentive.attributeValue | find:recurringDepositProductTemplate.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:recurringDepositProductTemplate.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"></tr>
<tr mat-row *matRowDef="let row; columns: chartSlabsDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chartSlabsIncentivesDisplayedColumns;" class="incentives-row"></tr>
</table>
<mat-divider [inset]="true"></mat-divider>
</div>
</div>
<div *ngIf="recurringDepositProduct.charges.length" fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<h3 class="mat-h3" fxFlexFill>Charges</h3>
<mat-divider [inset]="true"></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 }}
</td>
</ng-container>
<ng-container matColumnDef="type">
<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 | number }}
</td>
</ng-container>
<ng-container matColumnDef="collectedon">
<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 [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Type:</span>
<span fxFlex="60%">{{ recurringDepositProduct.accountingRule.value }}</span>
</div>
<div fxFlexFill *ngIf="recurringDepositProduct.accountingRule.id === 2" fxLayout="row wrap" fxLayout.lt-md="column">
<h4 fxFlexFill class="mat-h4">Assets</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Saving reference:</span>
<span fxFlex="60%">{{ recurringDepositProduct.accountingMappings.savingsReferenceAccount.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.accountingMappings.savingsControlAccount.name }}</span>
<span fxFlex="40%">Savings transfers in suspense:</span>
<span fxFlex="60%">{{ recurringDepositProduct.accountingMappings.transfersInSuspenseAccount.name }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Expenses</h4>
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Interest on savings:</span>
<span fxFlex="60%">{{ recurringDepositProduct.accountingMappings.interestOnSavingsAccount.name }}</span>
<span fxFlex="40%">Write-off:</span>
<span fxFlex="60%">{{ recurringDepositProduct.accountingMappings.writeOffAccount.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.accountingMappings.incomeFromFeeAccount.name }}</span>
<span fxFlex="40%">Income from penalties:</span>
<span fxFlex="60%">{{ recurringDepositProduct.accountingMappings.incomeFromPenaltyAccount.name }}</span>
</div>
<div fxFlexFill *ngIf="recurringDepositProduct.paymentChannelToFundSourceMappings?.length || recurringDepositProduct.feeToIncomeAccountMappings?.length || recurringDepositProduct.penaltyToIncomeAccountMappings?.length " fxLayout="row wrap" fxLayout.lt-md="column">
<h3 class="mat-h3" fxFlexFill>Advanced Accounting Rules</h3>
<mat-divider [inset]="true"></mat-divider>
<div *ngIf="recurringDepositProduct.paymentChannelToFundSourceMappings?.length" fxFlexFill fxLayout="row wrap"
fxLayout.lt-md="column">
<h4 class="mat-h4" fxFlexFill>Configure 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.paymentType.name }}
</td>
</ng-container>
<ng-container matColumnDef="fundSourceAccountId">
<th mat-header-cell *matHeaderCellDef> Fund Source </th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.fundSourceAccount.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.charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef> Income Account </th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.incomeAccount.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.charge.name }}
</td>
</ng-container>
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef> Income Account </th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.incomeAccount.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>
</mat-card-content>
</mat-card>
</div>
</mat-card>
@@ -1,70 +1,13 @@
table {
width: 100%;
}
.product-card {
margin: 0 auto;
max-width: 80rem;
width: 90%;
padding: 0;
.mat-elevation-z1 {
margin: 1em 0 1.5em 0;
}
h2, h3, h4 {
margin: 0;
font-weight: 500;
}
span {
margin: 0.5em 0;
}
.margin-t {
margin-top: 1em;
}
.interestCarts {
float:right;
}
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;
}
}
}
.navigation-tabs {
overflow: auto;
}
.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;
i:hover {
cursor: pointer;
}
}
@@ -1,35 +1,23 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { trigger, state, transition, animate, style } from '@angular/animations';
@Component({
selector: 'mifosx-view-recurring-deposit-product',
templateUrl: './view-recurring-deposit-product.component.html',
styleUrls: ['./view-recurring-deposit-product.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)'))
])
]
styleUrls: ['./view-recurring-deposit-product.component.scss']
})
export class ViewRecurringDepositProductComponent implements OnInit {
recurringDepositProduct: any;
recurringDepositProductTemplate: any;
chartSlabsIncentivesDisplayedColumns: string[] = ['incentives'];
chartSlabsDisplayedColumns: string[] = ['period', 'amountRange', 'annualInterestRate', 'description', 'actions'];
incentivesDisplayedColumns: string[] = ['entityType', 'attributeName', 'conditionType', 'attributeValue', 'incentiveType', 'amount'];
chargesDisplayedColumns: string[] = ['name', 'type', 'amount', 'collectedon'];
paymentFundSourceDisplayedColumns: string[] = ['paymentTypeId', 'fundSourceAccountId'];
feesPenaltyIncomeDisplayedColumns: string[] = ['chargeId', 'incomeAccountId'];
recurringDepositDatatables: any = [];
constructor(private route: ActivatedRoute) {
this.route.data.subscribe((data: { recurringDepositProduct: any, recurringDepositProductsTemplate: any}) => {
this.recurringDepositProduct = data.recurringDepositProduct;
this.recurringDepositProductTemplate = data.recurringDepositProductsTemplate;
this.route.data.subscribe((data: { recurringDepositDatatables: any }) => {
this.recurringDepositDatatables = [];
data.recurringDepositDatatables.forEach((datatable: any) => {
if (datatable.entitySubType === 'Recurring Deposit') {
this.recurringDepositDatatables.push(datatable);
}
});
});
}
@@ -18,8 +18,8 @@ export class SavingProductDatatableTabComponent implements OnInit {
this.entityDatatable = data.savingProductDatatable;
this.multiRowDatatableFlag = this.entityDatatable.columnHeaders[0].columnName === 'id' ? true : false;
});
}
ngOnInit(): void {
}