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
@@ -184,7 +184,7 @@
<mat-form-field *ngIf="createClientForm.contains('activationDate')" fxFlex="48%" (click)="activatedOnDatePicker.open()">
<mat-label>Activation Date</mat-label>
<input matInput [min]="minDate" [max]="createClientForm.value.submittedOnDate" [matDatepicker]="activatedOnDatePicker" required
<input matInput [min]="createClientForm.value.submittedOnDate" [max]="createClientForm.value.submittedOnDate" [matDatepicker]="activatedOnDatePicker" required
formControlName="activationDate">
<mat-datepicker-toggle matSuffix [for]="activatedOnDatePicker"></mat-datepicker-toggle>
<mat-datepicker #activatedOnDatePicker></mat-datepicker>
@@ -25,7 +25,7 @@
<mat-card-content>
<div class="share-account-tables" fxLayout="row wrap" fxFlex="50%" class="p-t-20">
<div class="share-account-tables p-t-20" fxLayout="row wrap" fxFlex="50%">
<table>
@@ -55,7 +55,7 @@ export class ErrorHandlerInterceptor implements HttpInterceptor {
} else if (status === 403 && errorMessage === 'The provided one time token is invalid') {
this.alertService.alert({ type: 'Invalid Token', message: 'Invalid Token. Please try again!' });
} else if (status === 400) {
this.alertService.alert({ type: 'Bad Request', message: 'Invalid parameters were passed in the request!' });
this.alertService.alert({ type: 'Bad Request', message: errorMessage || 'Invalid parameters were passed in the request!' });
} else if (status === 403) {
this.alertService.alert({ type: 'Unauthorized Request', message: errorMessage || 'You are not authorized for this request!' });
} else if (status === 404) {
@@ -25,7 +25,7 @@ export class GroupActionsResolver implements Resolve<Object> {
* @returns {Observable<any>}
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const actionName = route.paramMap.get('name');
const actionName = route.paramMap.get('action');
const groupId = route.paramMap.get('groupId') || route.parent.parent.paramMap.get('groupId');
switch (actionName) {
case 'Attendance':
@@ -40,13 +40,23 @@
</mat-select>
</mat-form-field>
<mat-form-field (click)="submittedOnDatePicker.open()">
<mat-label>Submitted on</mat-label>
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="submittedOnDatePicker" required formControlName="submittedOnDate">
<mat-datepicker-toggle matSuffix [for]="submittedOnDatePicker"></mat-datepicker-toggle>
<mat-datepicker #submittedOnDatePicker></mat-datepicker>
<mat-error *ngIf="groupForm.controls.submittedOnDate.hasError('required')">
Submission Date is <strong>required</strong>
</mat-error>
</mat-form-field>
<mat-checkbox labelPosition="before" formControlName="active">
Active
</mat-checkbox>
<mat-form-field *ngIf="this.groupForm.controls.active.value" (click)="activationDatePicker.open()">
<mat-form-field *ngIf="groupForm.controls.active.value" (click)="activationDatePicker.open()">
<mat-label>Activation Date</mat-label>
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="activationDatePicker" required formControlName="activationDate">
<input matInput [min]="groupForm.value.submittedOnDate" [max]="maxDate" [matDatepicker]="activationDatePicker" required formControlName="activationDate">
<mat-datepicker-toggle matSuffix [for]="activationDatePicker"></mat-datepicker-toggle>
<mat-datepicker #activationDatePicker></mat-datepicker>
<mat-error *ngIf="groupForm.controls.activationDate.hasError('required')">
@@ -59,21 +69,11 @@
<input matInput formControlName="externalId">
</mat-form-field>
<mat-form-field (click)="submittedOnDatePicker.open()">
<mat-label>Submitted on</mat-label>
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="submittedOnDatePicker" required formControlName="submittedOnDate">
<mat-datepicker-toggle matSuffix [for]="submittedOnDatePicker"></mat-datepicker-toggle>
<mat-datepicker #submittedOnDatePicker></mat-datepicker>
<mat-error *ngIf="groupForm.controls.submittedOnDate.hasError('required')">
Submission Date is <strong>required</strong>
</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Add Clients</mat-label>
<input matInput [formControl]="clientChoice" [matAutocomplete]="clientsAutocomplete">
</mat-form-field>
</div>
<mat-autocomplete autoActiveFirstOption #clientsAutocomplete="matAutocomplete" [displayWith]="displayClient">
@@ -108,10 +108,10 @@
<mat-nav-list *ngIf="clientMembers.length">
<h3 matSubheader>Selected Clients</h3>
<div mat-list-item *ngFor="let client of clientMembers index as i">
<button mat-icon-button (click)="removeClient(i)">
<span matLine>{{client.displayName}}</span>
<button mat-icon-button color="warn" (click)="removeClient(i)">
<fa-icon icon="trash"></fa-icon>
</button>
<span matLine>{{client.displayName}}</span>
</div>
</mat-nav-list>
@@ -1,5 +1,5 @@
.container {
max-width: 37rem;
max-width: 50rem;
}
.mat-table {
@@ -87,7 +87,7 @@ export class CreateGroupComponent implements OnInit, AfterViewInit {
this.groupForm = this.formBuilder.group({
'name': ['', [Validators.required, Validators.pattern('(^[A-z]).*')]],
'officeId': ['', Validators.required],
'submittedOnDate': ['', Validators.required],
'submittedOnDate': [this.settingsService.businessDate, Validators.required],
'staffId': [''],
'externalId': [''],
'active': [false],
@@ -169,7 +169,7 @@ export class CreateGroupComponent implements OnInit, AfterViewInit {
data.clientMembers = [];
this.clientMembers.forEach((client: any) => data.clientMembers.push(client.id));
this.groupService.createGroup(data).subscribe((response: any) => {
this.router.navigate(['../groups']);
this.router.navigate(['../groups', response.resourceId, 'general']);
});
}
@@ -28,9 +28,19 @@
</mat-select>
</mat-form-field>
<mat-form-field (click)="submittedOnDatePicker.open()">
<mat-label>Submitted on</mat-label>
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="submittedOnDatePicker" required formControlName="submittedOnDate">
<mat-datepicker-toggle matSuffix [for]="submittedOnDatePicker"></mat-datepicker-toggle>
<mat-datepicker #submittedOnDatePicker></mat-datepicker>
<mat-error *ngIf="editGroupForm.controls.submittedOnDate.hasError('required')">
Submission Date is <strong>required</strong>
</mat-error>
</mat-form-field>
<mat-form-field *ngIf="this.editGroupForm.contains('activationDate')" (click)="activationDatePicker.open()">
<mat-label>Activation Date</mat-label>
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="activationDatePicker" required formControlName="activationDate">
<input matInput [min]="editGroupForm.value.submittedOnDate" [max]="maxDate" [matDatepicker]="activationDatePicker" required formControlName="activationDate">
<mat-datepicker-toggle matSuffix [for]="activationDatePicker"></mat-datepicker-toggle>
<mat-datepicker #activationDatePicker></mat-datepicker>
<mat-error *ngIf="editGroupForm.controls.activationDate.hasError('required')">
@@ -43,16 +53,6 @@
<input matInput formControlName="externalId">
</mat-form-field>
<mat-form-field (click)="submittedOnDatePicker.open()">
<mat-label>Submitted on</mat-label>
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="submittedOnDatePicker" required formControlName="submittedOnDate">
<mat-datepicker-toggle matSuffix [for]="submittedOnDatePicker"></mat-datepicker-toggle>
<mat-datepicker #submittedOnDatePicker></mat-datepicker>
<mat-error *ngIf="editGroupForm.controls.submittedOnDate.hasError('required')">
Submission Date is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
</mat-card-content>
@@ -1,3 +1,3 @@
.container {
max-width: 37rem;
max-width: 50rem;
}
+7 -2
View File
@@ -67,6 +67,11 @@ const routes: Routes = [
groupDatatables: GroupDatatablesResolver
},
children: [
{
path: '',
redirectTo: 'general',
pathMatch: 'full'
},
{
path: 'general',
component: GeneralTabComponent,
@@ -133,8 +138,8 @@ const routes: Routes = [
]
},
{
path: 'actions/:name',
data: { title: extract('Group Actions'), routeParamBreadcrumb: 'name' },
path: 'actions/:action',
data: { title: extract('Group Actions'), breadcrumb: 'action', routeParamBreadcrumb: 'action' },
component: GroupActionsComponent,
resolve: {
groupActionData: GroupActionsResolver
@@ -59,7 +59,7 @@ export class AttachGroupMeetingComponent implements OnInit {
}
ngOnInit() {
this.maxDate = this.settingsService.businessDate;
this.maxDate = this.settingsService.maxFutureDate;
this.createGroupMeetingForm();
this.buildDependencies();
}
@@ -119,7 +119,7 @@ export class AttachGroupMeetingComponent implements OnInit {
const locale = this.settingsService.language.code;
const dateFormat = this.settingsService.dateFormat;
const title = `groups_${this.groupId}_CollectionMeeting`;
const typeId = '1';
const typeId = groupMeetingFormData.repeating ? '1' : '4' ;
const prevStartDate: Date = this.groupMeetingForm.value.startDate;
if (groupMeetingFormData.startDate instanceof Date) {
groupMeetingFormData.startDate = this.dateUtils.formatDate(prevStartDate, dateFormat);
@@ -42,8 +42,8 @@ export class GroupActionsComponent {
constructor(private route: ActivatedRoute,
private router: Router) {
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
const name = this.route.snapshot.params['name'];
this.actions[name] = true;
const action = this.route.snapshot.params['action'];
this.actions[action] = true;
}
}
@@ -36,7 +36,7 @@
</mat-card>
<mat-card fxFlex="40%">
<mat-card fxFlex="50%">
<h3 matSubheader>Client Members</h3>
@@ -44,7 +44,7 @@
<div mat-list-item *ngFor="let client of clientMembers index as i">
<span matLine class="p-t-10">{{client.displayName}}</span>
<div fxFlex></div>
<button mat-icon-button color="warn" (click)="removeClient(i, client)">
<button mat-icon-button color="warn" (click)="removeClient(i, client)" matTooltip="Remove Client from Group" matTooltipPosition="left">
<fa-icon icon="trash"></fa-icon>
</button>
</div>
@@ -52,4 +52,8 @@
</mat-card>
<div fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
<button type="button" mat-raised-button [routerLink]="['../']">Back</button>
</div>
</div>
@@ -1,12 +1,12 @@
.container {
max-width: 50rem;
max-width: 70rem;
.mat-table {
display: block;
font-family: Tahoma, Verdana;
width: 100%;
}
.mat-row,
.mat-header-row {
display: flex;
@@ -16,14 +16,14 @@
min-height: 48px;
padding: 0 24px;
}
.mat-cell,
.mat-header-cell {
flex: 1;
overflow: hidden;
word-wrap: break-word;
}
h3 {
padding-left: 0;
margin-bottom: 0;
@@ -43,7 +43,7 @@ export class ManageGroupMembersComponent implements AfterViewInit {
public dialog: MatDialog) {
this.route.data.subscribe((data: { groupActionData: any }) => {
this.groupData = data.groupActionData;
this.clientMembers = data.groupActionData.clientMembers;
this.clientMembers = data.groupActionData.clientMembers || [];
});
}
@@ -74,7 +74,7 @@
</mat-icon>
<span>Edit</span>
</button>
<button mat-menu-item *mifosxHasPermission="'CREATE_CLIENT'">
<button mat-menu-item *mifosxHasPermission="'CREATE_CLIENT'" (click)="doAction('Manage Members')">
<mat-icon matListIcon>
<fa-icon icon="plus" size="sm"></fa-icon>
</mat-icon>
@@ -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 {
}
@@ -30,6 +30,10 @@
<td mat-cell *matCellDef="let dataTable"> {{ dataTable.applicationTableName }} </td>
</ng-container>
<ng-container matColumnDef="entitySubType">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Sub Type </th>
<td mat-cell *matCellDef="let dataTable"> {{ dataTable.entitySubType }} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [routerLink]="[row.registeredTableName]" class="select-row"></tr>
@@ -25,7 +25,7 @@ export class ManageDataTablesComponent implements OnInit, AfterViewInit {
/** Data table data. */
dataTableData: any;
/** Columns to be displayed in manage data tables table. */
displayedColumns: string[] = ['registeredTableName', 'applicationTableName'];
displayedColumns: string[] = ['registeredTableName', 'applicationTableName', 'entitySubType'];
/** Data source for manage data tables table. */
dataSource: MatTableDataSource<any>;