Support datatable for share products (#1707)

Co-authored-by: Jose Alberto Hernandez <alberto@MacBook-Pro.local>
This commit is contained in:
José Alberto Hernández
2023-03-14 10:37:40 -06:00
committed by GitHub
co-authored by Jose Alberto Hernandez
parent 1e9444cd20
commit c27c50a6fb
21 changed files with 527 additions and 273 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ import { Dates } from './dates';
export class Datatables {
systemFields: string[] = ['id', 'created_at', 'updated_at', 'client_id', 'savings_account_id',
'loan_id', 'group_id', 'center_id', 'office_id', 'product_loan_id', 'savings_product_id'];
'loan_id', 'group_id', 'center_id', 'office_id', 'product_loan_id', 'savings_product_id', 'share_product_id'];
constructor(private dateUtils: Dates,
private settingsService: SettingsService) { }
+33 -7
View File
@@ -124,6 +124,10 @@ import { FixedDepositGeneralTabComponent } from './fixed-deposit-products/view-f
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';
import { ShareProductGeneralTabComponent } from './share-products/view-share-product/share-product-general-tab/share-product-general-tab.component';
import { ShareProductDatatableTabComponent } from './share-products/view-share-product/share-product-datatable-tab/share-product-datatable-tab.component';
import { ShareProductDatatablesResolver } from './share-products/share-product-datatables.resolver';
import { ShareProductDatatableResolver } from './share-products/share-product-datatable.resolver';
/** Products Routes */
const routes: Routes = [
@@ -228,7 +232,6 @@ const routes: Routes = [
{
path: '',
component: ViewSavingProductComponent,
children: [
{
path: '',
@@ -288,18 +291,41 @@ const routes: Routes = [
}
},
{
path: ':id',
data: { title: extract('View Share Product'), routeParamBreadcrumb: 'id' },
path: ':productId',
data: { title: extract('View Share Product'), breadcrumb: 'productId', routeParamBreadcrumb: 'productId' },
resolve: {
shareProduct: ShareProductResolver
shareProductDatatables: ShareProductDatatablesResolver
},
children: [
{
path: '',
component: ViewShareProductComponent,
resolve: {
shareProduct: ShareProductResolver
},
children: [
{
path: '',
redirectTo: 'general',
pathMatch: 'full'
},
{
path: 'general',
data: { title: extract('General'), breadcrumb: 'General', routeParamBreadcrumb: false },
component: ShareProductGeneralTabComponent,
resolve: {
shareProduct: ShareProductResolver
},
},
{
path: 'datatables',
children: [{
path: ':datatableName',
component: ShareProductDatatableTabComponent,
data: { title: extract('Data Table View'), routeParamBreadcrumb: 'datatableName' },
resolve: {
shareProductDatatable: ShareProductDatatableResolver
}
}]
}
]
},
{
path: 'edit',
+5 -1
View File
@@ -114,6 +114,8 @@ import { FixedDepositGeneralTabComponent } from './fixed-deposit-products/view-f
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';
import { ShareProductGeneralTabComponent } from './share-products/view-share-product/share-product-general-tab/share-product-general-tab.component';
import { ShareProductDatatableTabComponent } from './share-products/view-share-product/share-product-datatable-tab/share-product-datatable-tab.component';
/**
* Products Module
@@ -235,7 +237,9 @@ import { RecurringDepositGeneralTabComponent } from './recurring-deposit-product
FixedDepositGeneralTabComponent,
FixedDepositDatatableTabComponent,
RecurringDepositDatatableTabComponent,
RecurringDepositGeneralTabComponent
RecurringDepositGeneralTabComponent,
ShareProductGeneralTabComponent,
ShareProductDatatableTabComponent
],
entryComponents: [
DepositProductIncentiveFormDialogComponent,
@@ -215,21 +215,21 @@
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Saving reference:</span>
<span fxFlex="60%">{{ savingProduct.accountingMappings.savingsReferenceAccount.name }}</span>
<span fxFlex="60%">({{ savingProduct.accountingMappings.savingsReferenceAccount.glCode }}) {{ savingProduct.accountingMappings.savingsReferenceAccount.name }}</span>
<span fxFlex="40%">Overdraft portfolio:</span>
<span fxFlex="60%">{{ savingProduct.accountingMappings.overdraftPortfolioControl.name }}</span>
<span fxFlex="60%">({{ savingProduct.accountingMappings.overdraftPortfolioControl.glCode }}) {{ savingProduct.accountingMappings.overdraftPortfolioControl.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%">{{ savingProduct.accountingMappings.savingsControlAccount.name }}</span>
<span fxFlex="60%">({{ savingProduct.accountingMappings.savingsControlAccount.glCode }}) {{ savingProduct.accountingMappings.savingsControlAccount.name }}</span>
<span fxFlex="40%">Savings transfers in suspense:</span>
<span fxFlex="60%">{{ savingProduct.accountingMappings.transfersInSuspenseAccount.name }}</span>
<span fxFlex="60%">({{ savingProduct.accountingMappings.transfersInSuspenseAccount.glCode }}) {{ savingProduct.accountingMappings.transfersInSuspenseAccount.name }}</span>
<div fxFlexFill *ngIf="savingProduct.isDormancyTrackingActive">
<span fxFlex="40%">Escheat liability:</span>
<span fxFlex="60%">{{ savingProduct.accountingMappings.escheatLiabilityAccount.name }}</span>
<span fxFlex="60%">({{ savingProduct.accountingMappings.escheatLiabilityAccount.glCode }}) {{ savingProduct.accountingMappings.escheatLiabilityAccount.name }}</span>
</div>
</div>
@@ -237,20 +237,20 @@
<div fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
<span fxFlex="40%">Interest on savings:</span>
<span fxFlex="60%">{{ savingProduct.accountingMappings.interestOnSavingsAccount.name }}</span>
<span fxFlex="60%">({{ savingProduct.accountingMappings.interestOnSavingsAccount.glCode }}) {{ savingProduct.accountingMappings.interestOnSavingsAccount.name }}</span>
<span fxFlex="40%">Write-off:</span>
<span fxFlex="60%">{{ savingProduct.accountingMappings.writeOffAccount.name }}</span>
<span fxFlex="60%">({{ savingProduct.accountingMappings.writeOffAccount.glCode }}) {{ savingProduct.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%">{{ savingProduct.accountingMappings.incomeFromFeeAccount.name }}</span>
<span fxFlex="60%">({{ savingProduct.accountingMappings.incomeFromFeeAccount.glCode }}) {{ savingProduct.accountingMappings.incomeFromFeeAccount.name }}</span>
<span fxFlex="40%">Income from penalties:</span>
<span fxFlex="60%">{{ savingProduct.accountingMappings.incomeFromPenaltyAccount.name }}</span>
<span fxFlex="60%">({{ savingProduct.accountingMappings.incomeFromPenaltyAccount.glCode }}) {{ savingProduct.accountingMappings.incomeFromPenaltyAccount.name }}</span>
<span fxFlex="40%">Overdraft Interest Income:</span>
<span fxFlex="60%">{{ savingProduct.accountingMappings.incomeFromInterest.name }}</span>
<span fxFlex="60%">({{ savingProduct.accountingMappings.incomeFromInterest.glCode }}) {{ savingProduct.accountingMappings.incomeFromInterest.name }}</span>
</div>
<div *ngIf="savingProduct.paymentChannelToFundSourceMappings?.length || savingProduct.feeToIncomeAccountMappings?.length || savingProduct.penaltyToIncomeAccountMappings?.length" fxFlexFill fxLayout="row wrap" fxLayout.lt-md="column">
@@ -275,7 +275,7 @@
<ng-container matColumnDef="fundSourceAccountId">
<th mat-header-cell *matHeaderCellDef> Fund Source </th>
<td mat-cell *matCellDef="let paymentFundSource">
{{ paymentFundSource.fundSourceAccount.name }}
({{ paymentFundSource.fundSourceAccount.glCode }}) {{ paymentFundSource.fundSourceAccount.name }}
</td>
</ng-container>
@@ -302,7 +302,7 @@
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef> Income Account </th>
<td mat-cell *matCellDef="let feesIncome">
{{ feesIncome.incomeAccount.name }}
({{ feesIncome.incomeAccount.glCode }}) {{ feesIncome.incomeAccount.name }}
</td>
</ng-container>
@@ -329,7 +329,7 @@
<ng-container matColumnDef="incomeAccountId">
<th mat-header-cell *matHeaderCellDef> Income Account </th>
<td mat-cell *matCellDef="let penaltyIncome">
{{ penaltyIncome.incomeAccount.name }}
({{ penaltyIncome.incomeAccount.glCode }}) {{ penaltyIncome.incomeAccount.name }}
</td>
</ng-container>
@@ -24,8 +24,8 @@ export class ShareProductAndTemplateResolver implements Resolve<Object> {
* @returns {Observable<any>}
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const shareProductId = route.paramMap.get('id');
return this.productsService.getShareProduct(shareProductId, true);
const productId = route.parent.paramMap.get('productId');
return this.productsService.getShareProduct(productId, true);
}
}
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { ShareProductDatatableResolver } from './share-product-datatable.resolver';
describe('ShareProductDatatableResolver', () => {
let resolver: ShareProductDatatableResolver;
beforeEach(() => {
TestBed.configureTestingModule({});
resolver = TestBed.inject(ShareProductDatatableResolver);
});
it('should be created', () => {
expect(resolver).toBeTruthy();
});
});
@@ -0,0 +1,30 @@
import { Injectable } from '@angular/core';
import {
Router, Resolve,
RouterStateSnapshot,
ActivatedRouteSnapshot
} from '@angular/router';
import { SystemService } from 'app/system/system.service';
import { Observable, of } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ShareProductDatatableResolver implements Resolve<boolean> {
/**
* @param {SystemService} systemService Products service.
*/
constructor(private systemService: SystemService) { }
/**
* Returns the loan product data.
* @returns {Observable<any>}
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const productId = route.parent.parent.paramMap.get('productId');
const datatableName = route.paramMap.get('datatableName');
return this.systemService.getEntityDatatable(productId, datatableName);
}
}
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { ShareProductDatatablesResolver } from './share-product-datatables.resolver';
describe('ShareProductDatatablesResolver', () => {
let resolver: ShareProductDatatablesResolver;
beforeEach(() => {
TestBed.configureTestingModule({});
resolver = TestBed.inject(ShareProductDatatablesResolver);
});
it('should be created', () => {
expect(resolver).toBeTruthy();
});
});
@@ -0,0 +1,27 @@
import { Injectable } from '@angular/core';
import {
Router, Resolve,
RouterStateSnapshot,
ActivatedRouteSnapshot
} from '@angular/router';
import { SystemService } from 'app/system/system.service';
import { Observable, of } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ShareProductDatatablesResolver implements Resolve<boolean> {
/**
* @param {SystemService} systemService Products service.
*/
constructor(private systemService: SystemService) { }
/**
* Returns the loan product data.
* @returns {Observable<any>}
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
return this.systemService.getEntityDatatables('m_share_product');
}
}
@@ -24,8 +24,8 @@ export class ShareProductResolver implements Resolve<Object> {
* @returns {Observable<any>}
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const id = route.paramMap.get('id');
return this.productsService.getShareProduct(id);
const productId = route.parent.paramMap.get('productId');
return this.productsService.getShareProduct(productId);
}
}
@@ -0,0 +1,9 @@
<div class="tab-container mat-typography">
<mifosx-entity-datatable-tab
entityType="Share Product"
[entityId]="entityId"
[multiRowDatatableFlag]="multiRowDatatableFlag"
[entityDatatable]="entityDatatable"
>
</mifosx-entity-datatable-tab>
</div>
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ShareProductDatatableTabComponent } from './share-product-datatable-tab.component';
describe('ShareProductDatatableTabComponent', () => {
let component: ShareProductDatatableTabComponent;
let fixture: ComponentFixture<ShareProductDatatableTabComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ShareProductDatatableTabComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ShareProductDatatableTabComponent);
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-share-product-datatable-tab',
templateUrl: './share-product-datatable-tab.component.html',
styleUrls: ['./share-product-datatable-tab.component.scss']
})
export class ShareProductDatatableTabComponent 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: { shareProductDatatable: any }) => {
this.entityDatatable = data.shareProductDatatable;
this.multiRowDatatableFlag = this.entityDatatable.columnHeaders[0].columnName === 'id' ? true : false;
});
}
ngOnInit(): void {
}
}
@@ -0,0 +1,224 @@
<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_SHAREPRODUCT'">
<fa-icon icon="edit" class="m-r-10"></fa-icon>
Edit
</button>
<button mat-raised-button color="primary" [routerLink]="['../dividends']" *mifosxHasPermission="'UPDATE_SHAREPRODUCT'">
<fa-icon icon="hand-holding-usd" class="m-r-10"></fa-icon>
Dividends
</button>
</div>
<div class="container">
<mat-card>
<mat-card-content>
<div fxLayout="row wrap" fxLayout.lt-md="column">
<h2 class="mat-h2" fxFlexFill>{{ shareProduct.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%">{{ shareProduct.shortName }}</span>
</div>
<div fxFlexFill *ngIf="shareProduct.description">
<span fxFlex="40%">Description:</span>
<span fxFlex="60%">{{ shareProduct.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%">{{ shareProduct.currency.name }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Decimal Places:</span>
<span fxFlex="60%">{{ shareProduct.currency.decimalPlaces }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Currency in multiples of:</span>
<span fxFlex="60%">{{ shareProduct.currency.inMultiplesOf }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Terms</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Total Number of Shares:</span>
<span fxFlex="60%">{{ shareProduct.totalShares }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Shares to be Issued:</span>
<span fxFlex="60%">{{ shareProduct.totalSharesIssued }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Nominal/Unit Price:</span>
<span fxFlex="60%">{{ shareProduct.unitPrice }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Capital Value:</span>
<span fxFlex="60%">{{ shareProduct.shareCapital }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Settings</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Shares per Client:</span>
<span fxFlex="60%">{{ shareProduct.nominalShares + ' (Min: ' + (shareProduct.minimumShares ? shareProduct.minimumShares : shareProduct.nominalShares) + ', Max: ' + (shareProduct.maximumShares ? shareProduct.maximumShares : shareProduct.nominalShares) + ')' }}</span>
</div>
<div fxFlexFill *ngIf="shareProduct.minimumActivePeriod">
<span fxFlex="40%">Minimum Active Period:</span>
<span fxFlex="60%">{{ shareProduct.minimumActivePeriod + ' ' + shareProduct.minimumActivePeriodForDividendsTypeEnum.value }}</span>
</div>
<div fxFlexFill *ngIf="shareProduct.lockinPeriod">
<span fxFlex="40%">Lock-in Period:</span>
<span fxFlex="60%">{{ shareProduct.lockinPeriod + ' ' + shareProduct.lockPeriodTypeEnum.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Allow dividends for inactive clients:</span>
<span fxFlex="60%">{{ shareProduct.allowDividendCalculationForInactiveClients ? 'Yes' : 'No' }}</span>
</div>
<div fxFlexFill *ngIf="shareProduct.marketPrice?.length" fxLayout="row wrap" fxLayout.lt-md="column">
<h3 class="mat-h3" fxFlexFill>Market Price Periods</h3>
<mat-divider [inset]="true"></mat-divider>
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="shareProduct.marketPrice">
<ng-container matColumnDef="fromDate">
<th mat-header-cell *matHeaderCellDef> From Date </th>
<td mat-cell *matCellDef="let marketPrice">
{{ marketPrice.fromDate | dateFormat }}
</td>
</ng-container>
<ng-container matColumnDef="shareValue">
<th mat-header-cell *matHeaderCellDef> Nominal/Unit Price </th>
<td mat-cell *matCellDef="let marketPrice">
{{ marketPrice.shareValue }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="marketPriceDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: marketPriceDisplayedColumns;"></tr>
</table>
</div>
<div fxFlexFill *ngIf="shareProduct.charges.length" 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]="shareProduct.charges">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let charge">
{{ charge.name + ', ' + charge.currency.displaySymbol }}
</td>
</ng-container>
<ng-container matColumnDef="chargeCalculationType">
<th mat-header-cell *matHeaderCellDef> Type </th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeCalculationType.value }}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef> Amount </th>
<td mat-cell *matCellDef="let charge">
{{ charge.amount | numberFormat }}
</td>
</ng-container>
<ng-container matColumnDef="chargeTimeType">
<th mat-header-cell *matHeaderCellDef> Collected On </th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeTimeType.value }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chargesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chargesDisplayedColumns;"></tr>
</table>
</div>
<h3 class="mat-h3" fxFlexFill>Accounting</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Type:</span>
<span fxFlex="60%">{{ shareProduct.accountingRule.value }}</span>
</div>
<div fxFlexFill *ngIf="shareProduct.accountingRule.id === 2" fxLayout="row wrap" fxLayout.lt-md="column">
<h4 fxFlexFill class="mat-h4">Assets</h4>
<div fxFlexFill>
<span fxFlex="40%">Share reference:</span>
<span fxFlex="60%">({{ shareProduct.accountingMappings.shareReferenceId.glCode }}) {{ shareProduct.accountingMappings.shareReferenceId.name }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Liabilities</h4>
<div fxFlexFill>
<span fxFlex="40%">Share suspense control:</span>
<span fxFlex="60%">({{ shareProduct.accountingMappings.shareSuspenseId.glCode }}) {{ shareProduct.accountingMappings.shareSuspenseId.name }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Share Equity</h4>
<div fxFlexFill>
<span fxFlex="40%">Equity:</span>
<span fxFlex="60%">({{ shareProduct.accountingMappings.shareEquityId.glCode }}) {{ shareProduct.accountingMappings.shareEquityId.name }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Income</h4>
<div fxFlexFill>
<span fxFlex="40%">Income from fees:</span>
<span fxFlex="60%">({{ shareProduct.accountingMappings.incomeFromFeeAccountId.glCode }}) {{ shareProduct.accountingMappings.incomeFromFeeAccountId.name }}</span>
</div>
</div>
</div>
</mat-card-content>
</mat-card>
</div>
@@ -0,0 +1,12 @@
@import "assets/styles/helper";
.tab-container {
padding: 1%;
margin: 1%;
}
.mat-h3 {
margin-top: 10px !important;
font-weight: 300;
color: $status-approved;
}
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ShareProductGeneralTabComponent } from './share-product-general-tab.component';
describe('ShareProductGeneralTabComponent', () => {
let component: ShareProductGeneralTabComponent;
let fixture: ComponentFixture<ShareProductGeneralTabComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ShareProductGeneralTabComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ShareProductGeneralTabComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,25 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'mifosx-share-product-general-tab',
templateUrl: './share-product-general-tab.component.html',
styleUrls: ['./share-product-general-tab.component.scss']
})
export class ShareProductGeneralTabComponent implements OnInit {
shareProduct: any;
marketPriceDisplayedColumns: string[] = ['fromDate', 'shareValue'];
chargesDisplayedColumns: string[] = ['name', 'chargeCalculationType', 'amount', 'chargeTimeType'];
constructor(private route: ActivatedRoute) {
this.route.data.subscribe((data: { shareProduct: any }) => {
this.shareProduct = data.shareProduct;
});
}
ngOnInit(): void {
}
}
@@ -1,224 +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']" *mifosxHasPermission="'UPDATE_SHAREPRODUCT'">
<fa-icon icon="edit" class="m-r-10"></fa-icon>
Edit
</button>
<button mat-raised-button color="primary" [routerLink]="['dividends']" *mifosxHasPermission="'UPDATE_SHAREPRODUCT'">
<fa-icon icon="hand-holding-usd" class="m-r-10"></fa-icon>
Dividends
</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 shareProductDatatable of shareProductDatatables">
<a mat-tab-link [routerLink]="['./datatables',shareProductDatatable.registeredTableName]" routerLinkActive
#datatable="routerLinkActive" [active]="datatable.isActive"
*mifosxHasPermission="'READ_' + shareProductDatatable.registeredTableName">
{{shareProductDatatable.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>{{ shareProduct.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%">{{ shareProduct.shortName }}</span>
</div>
<div fxFlexFill *ngIf="shareProduct.description">
<span fxFlex="40%">Description:</span>
<span fxFlex="60%">{{ shareProduct.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%">{{ shareProduct.currency.name }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Decimal Places:</span>
<span fxFlex="60%">{{ shareProduct.currency.decimalPlaces }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Currency in multiples of:</span>
<span fxFlex="60%">{{ shareProduct.currency.inMultiplesOf }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Terms</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Total Number of Shares:</span>
<span fxFlex="60%">{{ shareProduct.totalShares }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Shares to be Issued:</span>
<span fxFlex="60%">{{ shareProduct.totalSharesIssued }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Nominal/Unit Price:</span>
<span fxFlex="60%">{{ shareProduct.unitPrice }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Capital Value:</span>
<span fxFlex="60%">{{ shareProduct.shareCapital }}</span>
</div>
<h3 class="mat-h3" fxFlexFill>Settings</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Shares per Client:</span>
<span fxFlex="60%">{{ shareProduct.nominalShares + ' (Min: ' + (shareProduct.minimumShares ? shareProduct.minimumShares : shareProduct.nominalShares) + ', Max: ' + (shareProduct.maximumShares ? shareProduct.maximumShares : shareProduct.nominalShares) + ')' }}</span>
</div>
<div fxFlexFill *ngIf="shareProduct.minimumActivePeriod">
<span fxFlex="40%">Minimum Active Period:</span>
<span fxFlex="60%">{{ shareProduct.minimumActivePeriod + ' ' + shareProduct.minimumActivePeriodForDividendsTypeEnum.value }}</span>
</div>
<div fxFlexFill *ngIf="shareProduct.lockinPeriod">
<span fxFlex="40%">Lock-in Period:</span>
<span fxFlex="60%">{{ shareProduct.lockinPeriod + ' ' + shareProduct.lockPeriodTypeEnum.value }}</span>
</div>
<div fxFlexFill>
<span fxFlex="40%">Allow dividends for inactive clients:</span>
<span fxFlex="60%">{{ shareProduct.allowDividendCalculationForInactiveClients ? 'Yes' : 'No' }}</span>
</div>
<div fxFlexFill *ngIf="shareProduct.marketPrice?.length" fxLayout="row wrap" fxLayout.lt-md="column">
<h3 class="mat-h3" fxFlexFill>Market Price Periods</h3>
<mat-divider [inset]="true"></mat-divider>
<table fxFlexFill class="mat-elevation-z1" mat-table [dataSource]="shareProduct.marketPrice">
<ng-container matColumnDef="fromDate">
<th mat-header-cell *matHeaderCellDef> From Date </th>
<td mat-cell *matCellDef="let marketPrice">
{{ marketPrice.fromDate | dateFormat }}
</td>
</ng-container>
<ng-container matColumnDef="shareValue">
<th mat-header-cell *matHeaderCellDef> Nominal/Unit Price </th>
<td mat-cell *matCellDef="let marketPrice">
{{ marketPrice.shareValue }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="marketPriceDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: marketPriceDisplayedColumns;"></tr>
</table>
</div>
<div fxFlexFill *ngIf="shareProduct.charges.length" 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]="shareProduct.charges">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let charge">
{{ charge.name + ', ' + charge.currency.displaySymbol }}
</td>
</ng-container>
<ng-container matColumnDef="chargeCalculationType">
<th mat-header-cell *matHeaderCellDef> Type </th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeCalculationType.value }}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef> Amount </th>
<td mat-cell *matCellDef="let charge">
{{ charge.amount }}
</td>
</ng-container>
<ng-container matColumnDef="chargeTimeType">
<th mat-header-cell *matHeaderCellDef> Collected On </th>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeTimeType.value }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="chargesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: chargesDisplayedColumns;"></tr>
</table>
</div>
<h3 class="mat-h3" fxFlexFill>Accounting</h3>
<mat-divider [inset]="true"></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Type:</span>
<span fxFlex="60%">{{ shareProduct.accountingRule.value }}</span>
</div>
<div fxFlexFill *ngIf="shareProduct.accountingRule.id === 2" fxLayout="row wrap" fxLayout.lt-md="column">
<h4 fxFlexFill class="mat-h4">Assets</h4>
<div fxFlexFill>
<span fxFlex="40%">Share reference:</span>
<span fxFlex="60%">{{ shareProduct.accountingMappings.shareReferenceId.name }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Liabilities</h4>
<div fxFlexFill>
<span fxFlex="40%">Share suspense control:</span>
<span fxFlex="60%">{{ shareProduct.accountingMappings.shareSuspenseId.name }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Share Equity</h4>
<div fxFlexFill>
<span fxFlex="40%">Equity:</span>
<span fxFlex="60%">{{ shareProduct.accountingMappings.shareEquityId.name }}</span>
</div>
<h4 fxFlexFill class="mat-h4">Income</h4>
<div fxFlexFill>
<span fxFlex="40%">Income from fees:</span>
<span fxFlex="60%">{{ shareProduct.accountingMappings.incomeFromFeeAccountId.name }}</span>
</div>
</div>
</div>
</mat-card-content>
</mat-card>
</div>
</mat-card>
@@ -1,24 +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;
.navigation-tabs {
overflow: auto;
}
i:hover {
cursor: pointer;
}
}
@@ -8,14 +8,14 @@ import { ActivatedRoute } from '@angular/router';
})
export class ViewShareProductComponent implements OnInit {
shareProduct: any;
marketPriceDisplayedColumns: string[] = ['fromDate', 'shareValue'];
chargesDisplayedColumns: string[] = ['name', 'chargeCalculationType', 'amount', 'chargeTimeType'];
shareProductDatatables: any = [];
constructor(private route: ActivatedRoute) {
this.route.data.subscribe((data: { shareProduct: any }) => {
this.shareProduct = data.shareProduct;
this.route.data.subscribe((data: { shareProductDatatables: any }) => {
this.shareProductDatatables = [];
data.shareProductDatatables.forEach((datatable: any) => {
this.shareProductDatatables.push(datatable);
});
});
}