Enhancement/inverstor search data (#1838)
* Investor Search data * Investor module --------- Co-authored-by: Jose Alberto Hernandez <alberto@blue-daemon.local>
This commit is contained in:
co-authored by
Jose Alberto Hernandez
parent
861cf7a000
commit
ed47d769e3
+4
-54
@@ -37,33 +37,8 @@
|
|||||||
"src/main.scss",
|
"src/main.scss",
|
||||||
{
|
{
|
||||||
"inject": false,
|
"inject": false,
|
||||||
"input": "src/theme/deeppurple-amber.scss",
|
"input": "src/theme/mifosx-theme.scss",
|
||||||
"bundleName": "deeppurple-amber"
|
"bundleName": "mifosx-theme"
|
||||||
},
|
|
||||||
{
|
|
||||||
"inject": false,
|
|
||||||
"input": "src/theme/indigo-pink.scss",
|
|
||||||
"bundleName": "indigo-pink"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"inject": false,
|
|
||||||
"input": "src/theme/pink-bluegrey.scss",
|
|
||||||
"bundleName": "pink-bluegrey"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"inject": false,
|
|
||||||
"input": "src/theme/purple-green.scss",
|
|
||||||
"bundleName": "purple-green"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"inject": false,
|
|
||||||
"input": "src/theme/custom/denim-yellowgreen.scss",
|
|
||||||
"bundleName": "denim-yellowgreen"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"inject": false,
|
|
||||||
"input": "src/theme/custom/pictonblue-yellowgreen.scss",
|
|
||||||
"bundleName": "pictonblue-yellowgreen"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"scripts": [],
|
"scripts": [],
|
||||||
@@ -147,33 +122,8 @@
|
|||||||
"src/main.scss",
|
"src/main.scss",
|
||||||
{
|
{
|
||||||
"inject": false,
|
"inject": false,
|
||||||
"input": "src/theme/deeppurple-amber.scss",
|
"input": "src/theme/mifosx-theme.scss",
|
||||||
"bundleName": "deeppurple-amber"
|
"bundleName": "mifosx-theme"
|
||||||
},
|
|
||||||
{
|
|
||||||
"inject": false,
|
|
||||||
"input": "src/theme/indigo-pink.scss",
|
|
||||||
"bundleName": "indigo-pink"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"inject": false,
|
|
||||||
"input": "src/theme/pink-bluegrey.scss",
|
|
||||||
"bundleName": "pink-bluegrey"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"inject": false,
|
|
||||||
"input": "src/theme/purple-green.scss",
|
|
||||||
"bundleName": "purple-green"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"inject": false,
|
|
||||||
"input": "src/theme/custom/denim-yellowgreen.scss",
|
|
||||||
"bundleName": "denim-yellowgreen"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"inject": false,
|
|
||||||
"input": "src/theme/custom/pictonblue-yellowgreen.scss",
|
|
||||||
"bundleName": "pictonblue-yellowgreen"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"assets": [
|
"assets": [
|
||||||
|
|||||||
Generated
+916
-86
File diff suppressed because it is too large
Load Diff
@@ -50,6 +50,7 @@
|
|||||||
"@ngx-translate/core": "13.0.0",
|
"@ngx-translate/core": "13.0.0",
|
||||||
"@ngx-translate/http-loader": "^6.0.0",
|
"@ngx-translate/http-loader": "^6.0.0",
|
||||||
"@swimlane/ngx-graph": "^8.0.2",
|
"@swimlane/ngx-graph": "^8.0.2",
|
||||||
|
"@tailwindcss/forms": "^0.5.4",
|
||||||
"chart.js": "3.0.0-alpha",
|
"chart.js": "3.0.0-alpha",
|
||||||
"d3": "^7.6.1",
|
"d3": "^7.6.1",
|
||||||
"install": "^0.13.0",
|
"install": "^0.13.0",
|
||||||
@@ -91,12 +92,14 @@
|
|||||||
"karma-jasmine": "^5.1.0",
|
"karma-jasmine": "^5.1.0",
|
||||||
"karma-jasmine-html-reporter": "^2.0.0",
|
"karma-jasmine-html-reporter": "^2.0.0",
|
||||||
"karma-junit-reporter": "1.2.0",
|
"karma-junit-reporter": "1.2.0",
|
||||||
|
"prettier": "^3.0.1",
|
||||||
"protractor": "~7.0.0",
|
"protractor": "~7.0.0",
|
||||||
"puppeteer": "^15.3.2",
|
"puppeteer": "^15.3.2",
|
||||||
"stylelint": "10.0.1",
|
"stylelint": "10.0.1",
|
||||||
"stylelint-config-recommended-scss": "3.3.0",
|
"stylelint-config-recommended-scss": "3.3.0",
|
||||||
"stylelint-config-standard": "18.3.0",
|
"stylelint-config-standard": "18.3.0",
|
||||||
"stylelint-scss": "3.6.1",
|
"stylelint-scss": "3.6.1",
|
||||||
|
"tailwindcss": "^3.3.3",
|
||||||
"ts-node": "8.2.0",
|
"ts-node": "8.2.0",
|
||||||
"tslint": "~6.1.0",
|
"tslint": "~6.1.0",
|
||||||
"typescript": "4.6.4"
|
"typescript": "4.6.4"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
|
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { ExternalAssetOwnerService } from '../external-asset-owner.service';
|
import { ExternalAssetOwnerService } from '../services/external-asset-owner.service';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
|
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
|
||||||
import { Observable, of } from 'rxjs';
|
import { Observable, of } from 'rxjs';
|
||||||
import { ExternalAssetOwnerService } from '../external-asset-owner.service';
|
import { ExternalAssetOwnerService } from '../services/external-asset-owner.service';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
|
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { ExternalAssetOwnerService } from '../external-asset-owner.service';
|
import { ExternalAssetOwnerService } from '../services/external-asset-owner.service';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import {
|
||||||
|
Resolve,
|
||||||
|
ActivatedRouteSnapshot
|
||||||
|
} from '@angular/router';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { LoansService } from '../loans.service';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class LoanCollateralsResolver implements Resolve<boolean> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {LoansService} LoansService Loans service.
|
||||||
|
*/
|
||||||
|
constructor(private loansService: LoansService) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Loans data.
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
resolve(route: ActivatedRouteSnapshot): Observable<any> {
|
||||||
|
const loanId = route.paramMap.get('loanId') || route.parent.paramMap.get('loanId');
|
||||||
|
return this.loansService.getLoanCollaterals(loanId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -61,6 +61,7 @@ import { ExternalAssetOwnerTabComponent } from './loans-view/external-asset-owne
|
|||||||
import { ExternalAssetOwnerResolver } from './common-resolvers/external-asset-owner.resolver';
|
import { ExternalAssetOwnerResolver } from './common-resolvers/external-asset-owner.resolver';
|
||||||
import { ExternalAssetOwnerActiveTransferResolver } from './common-resolvers/external-asset-owner-active-transfer.resolver';
|
import { ExternalAssetOwnerActiveTransferResolver } from './common-resolvers/external-asset-owner-active-transfer.resolver';
|
||||||
import { ExternalAssetOwnerJournalEntryResolver } from './common-resolvers/external-asset-owner-journal-entry.resolver';
|
import { ExternalAssetOwnerJournalEntryResolver } from './common-resolvers/external-asset-owner-journal-entry.resolver';
|
||||||
|
import { LoanCollateralsResolver } from './common-resolvers/loan-collaterals.resolver';
|
||||||
|
|
||||||
/** Loans Route. */
|
/** Loans Route. */
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
@@ -160,6 +161,9 @@ const routes: Routes = [
|
|||||||
path: 'loan-collateral',
|
path: 'loan-collateral',
|
||||||
component: LoanCollateralTabComponent,
|
component: LoanCollateralTabComponent,
|
||||||
data: { title: extract('Loan Collateral Details'), breadcrumb: 'Loan Collateral Details', routeParamBreadcrumb: false },
|
data: { title: extract('Loan Collateral Details'), breadcrumb: 'Loan Collateral Details', routeParamBreadcrumb: false },
|
||||||
|
resolve: {
|
||||||
|
loanCollaterals: LoanCollateralsResolver
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'loan-tranche-details',
|
path: 'loan-tranche-details',
|
||||||
|
|||||||
+4
-75
@@ -1,93 +1,22 @@
|
|||||||
<div class="tab-container mat-typography">
|
<div class="tab-container mat-typography">
|
||||||
<div fxFlexFill *ngIf="existActiveTransfer">
|
<div fxFlexFill *ngIf="existActiveTransfer">
|
||||||
<h3>Active Asset Transfer</h3>
|
<h3>Active Asset Transfer</h3>
|
||||||
<div fxLayout="row" fxLayoutGap="32px" class="asset-transfer-container">
|
<mifosx-external-asset-transfer [transferData]="activeTransferData"></mifosx-external-asset-transfer>
|
||||||
<table>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td fxFlex="25%">
|
|
||||||
<b>Status :</b>
|
|
||||||
</td>
|
|
||||||
<td fxFlex="25%" class="left">
|
|
||||||
<div [ngClass]="itemStatus(activeTransferData.status)">
|
|
||||||
<fa-icon icon="stop"></fa-icon>
|
|
||||||
<span class="m-l-10 status">{{activeTransferData.status}}</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td fxFlex="25%">
|
|
||||||
<b>Owner External Id :</b>
|
|
||||||
</td>
|
|
||||||
<td fxFlex="25%" class="left">
|
|
||||||
<mifosx-external-identifier externalId="{{activeTransferData.owner.externalId}}" completed="true"></mifosx-external-identifier>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td fxFlex="25%">
|
|
||||||
<b>Settlement Date :</b>
|
|
||||||
</td>
|
|
||||||
<td fxFlex="25%" class="left">
|
|
||||||
{{activeTransferData.settlementDate | dateFormat}}
|
|
||||||
</td>
|
|
||||||
<td fxFlex="25%">
|
|
||||||
<b>Effective Date :</b>
|
|
||||||
</td>
|
|
||||||
<td fxFlex="25%" class="left">
|
|
||||||
{{activeTransferData.effectiveFrom | dateFormat}}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td fxFlex="25%">
|
|
||||||
<b>Details :</b>
|
|
||||||
</td>
|
|
||||||
<td fxFlex="75%" class="left">
|
|
||||||
<table>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td fxFlex="50%"><b>Principal Outstanding :</b></td>
|
|
||||||
<td fxFlex="50%" class="r-amount">{{activeTransferData.details.totalPrincipalOutstanding | formatNumber}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td fxFlex="50%"><b>Interest Outstanding :</b></td>
|
|
||||||
<td fxFlex="50%" class="r-amount">{{activeTransferData.details.totalInterestOutstanding | formatNumber}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td fxFlex="50%"><b>Fees Outstanding :</b></td>
|
|
||||||
<td fxFlex="50%" class="r-amount">{{activeTransferData.details.totalFeeChargesOutstanding | formatNumber}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td fxFlex="50%"><b>Penalties Outstanding :</b></td>
|
|
||||||
<td fxFlex="50%" class="r-amount">{{activeTransferData.details.totalPenaltyChargesOutstanding | formatNumber}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td fxFlex="50%"><b>Outstanding :</b></td>
|
|
||||||
<td fxFlex="50%" class="r-amount">{{activeTransferData.details.totalOutstanding | formatNumber}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td fxFlex="50%"><b>Overpaid :</b></td>
|
|
||||||
<td fxFlex="50%" class="r-amount">{{activeTransferData.details.totalOverpaid | formatNumber}}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div fxLayout="row" fxLayoutAlign="start center">
|
<div fxLayout="row" fxLayoutAlign="start center">
|
||||||
|
|
||||||
<h3 fxFlex="90%">External Asset Owner</h3>
|
<h3 fxFlex="90%">External Asset Owner</h3>
|
||||||
|
|
||||||
<div fxFlex="10%" *ngIf="canBeSaled()" >
|
<div fxFlex="10%" *ngIf="canBeSold()" >
|
||||||
<button mat-raised-button class="f-right" color="primary" (click)="saleLoan()" *mifosxHasPermission="'SALE_LOAN'">
|
<button mat-raised-button class="f-right" color="primary" (click)="saleLoan()" *mifosxHasPermission="'SALE_LOAN'">
|
||||||
<fa-icon icon="dollar-sign" class="m-r-10"></fa-icon>Sale Loan
|
<fa-icon icon="dollar-sign" class="m-r-10"></fa-icon>Sell Loan
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div fxFlex="10%" *ngIf="canBeCancelled()" >
|
<div fxFlex="10%" *ngIf="canBeCancelled()" >
|
||||||
<button mat-raised-button class="f-right" color="warn" (click)="cancelSaleLoan()" *mifosxHasPermission="'SALE_LOAN'">
|
<button mat-raised-button class="f-right" color="warn" (click)="cancelSaleLoan()" *mifosxHasPermission="'SALE_LOAN'">
|
||||||
<fa-icon icon="trash" class="m-r-10"></fa-icon>Cancel Sale Loan
|
<fa-icon icon="trash" class="m-r-10"></fa-icon>Cancel Sell Loan
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
+13
-24
@@ -1,7 +1,8 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { ExternalAssetOwnerService } from 'app/loans/external-asset-owner.service';
|
import { ExternalAssetOwner } from 'app/loans/services/external-asset-owner';
|
||||||
|
import { ExternalAssetOwnerService } from 'app/loans/services/external-asset-owner.service';
|
||||||
import { CancelDialogComponent } from 'app/shared/cancel-dialog/cancel-dialog.component';
|
import { CancelDialogComponent } from 'app/shared/cancel-dialog/cancel-dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -22,6 +23,7 @@ export class ExternalAssetOwnerTabComponent implements OnInit {
|
|||||||
constructor(private route: ActivatedRoute,
|
constructor(private route: ActivatedRoute,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
|
private externalAssetOwner: ExternalAssetOwner,
|
||||||
private externalAssetOwnerService: ExternalAssetOwnerService
|
private externalAssetOwnerService: ExternalAssetOwnerService
|
||||||
) {
|
) {
|
||||||
this.route.data.subscribe((data: { loanTransfersData: any, activeTransferData: any }) => {
|
this.route.data.subscribe((data: { loanTransfersData: any, activeTransferData: any }) => {
|
||||||
@@ -39,52 +41,39 @@ export class ExternalAssetOwnerTabComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
itemCurrentStatus(item: any): string {
|
itemCurrentStatus(item: any): string {
|
||||||
if (this.isBuyBackPending(item)) {
|
return this.externalAssetOwner.itemCurrentStatus(item);
|
||||||
return item.status + ' PENDING';
|
|
||||||
}
|
|
||||||
return item.status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
itemStatus(status: string): string {
|
itemStatus(status: string): string {
|
||||||
return 'status-' + status.toLowerCase();
|
return this.externalAssetOwner.itemStatus(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
isPending(item: any): boolean {
|
isPending(item: any): boolean {
|
||||||
return (item.status === 'PENDING');
|
return this.externalAssetOwner.isPending(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
isPendingOrCanceled(item: any): boolean {
|
isPendingOrCanceled(item: any): boolean {
|
||||||
return ((item.status === 'PENDING') || (item.status === 'CANCELLED') || this.isBuyBackPending(item));
|
return this.externalAssetOwner.isPendingOrCanceled(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
isBuyBackPending(item: any): boolean {
|
isBuyBackPending(item: any): boolean {
|
||||||
return (item.status === 'BUYBACK' && item.effectiveTo === this.defaultDate);
|
return this.externalAssetOwner.isBuyBackPending(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
canBeCancelled(): boolean {
|
canBeCancelled(): boolean {
|
||||||
return this.validateStatus('PENDING');
|
return this.externalAssetOwner.validateStatus(this.currentItem, 'PENDING');
|
||||||
}
|
}
|
||||||
|
|
||||||
canBeSaled(): boolean {
|
canBeSold(): boolean {
|
||||||
if (this.currentItem == null) {
|
return this.externalAssetOwner.canBeSold(this.currentItem);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return ['', 'CANCELLED'].includes(this.currentItem.status) || (this.currentItem.status === 'BUYBACK' && this.currentItem.effectiveTo !== this.defaultDate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
canBeBuyed(): boolean {
|
canBeBuyed(): boolean {
|
||||||
return this.validateStatus('ACTIVE');
|
return this.externalAssetOwner.validateStatus(this.currentItem, 'ACTIVE');
|
||||||
}
|
|
||||||
|
|
||||||
private validateStatus(status: string): boolean {
|
|
||||||
if (this.currentItem != null) {
|
|
||||||
return (this.currentItem.status === status);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
saleLoan(): void {
|
saleLoan(): void {
|
||||||
this.router.navigate(['../actions/Sale Loan'], { relativeTo: this.route });
|
this.router.navigate(['../actions/Sell Loan'], { relativeTo: this.route });
|
||||||
}
|
}
|
||||||
|
|
||||||
cancelSaleLoan(): void {
|
cancelSaleLoan(): void {
|
||||||
|
|||||||
+72
@@ -0,0 +1,72 @@
|
|||||||
|
<div fxLayout="row" fxLayoutGap="32px" class="asset-transfer-container">
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td fxFlex="25%" class="m-l-5">
|
||||||
|
<b>Status :</b>
|
||||||
|
</td>
|
||||||
|
<td fxFlex="25%" class="m-l-5 left">
|
||||||
|
<div [ngClass]="itemStatus(transferData.status)">
|
||||||
|
<fa-icon icon="stop"></fa-icon>
|
||||||
|
<span class="m-l-5 status">{{transferData.status}}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td fxFlex="25%" class="m-l-5">
|
||||||
|
<b>Owner External Id :</b>
|
||||||
|
</td>
|
||||||
|
<td fxFlex="25%" class="m-l-5 left">
|
||||||
|
<mifosx-external-identifier externalId="{{transferData.owner.externalId}}" completed="true"></mifosx-external-identifier>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td fxFlex="25%" class="m-l-5">
|
||||||
|
<b>Settlement Date :</b>
|
||||||
|
</td>
|
||||||
|
<td fxFlex="25%" class="m-l-5">
|
||||||
|
{{transferData.settlementDate | dateFormat}}
|
||||||
|
</td>
|
||||||
|
<td fxFlex="25%" class="m-l-5">
|
||||||
|
<b>Effective Date :</b>
|
||||||
|
</td>
|
||||||
|
<td fxFlex="25%" class="m-l-5">
|
||||||
|
{{transferData.effectiveFrom | dateFormat}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td fxFlex="25%" class="m-l-5">
|
||||||
|
<b>Details :</b>
|
||||||
|
</td>
|
||||||
|
<td fxFlex="75%" class="left">
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td fxFlex="50%" class="m-l-5"><b>Principal Outstanding :</b></td>
|
||||||
|
<td fxFlex="50%" class="r-amount">{{transferData.details.totalPrincipalOutstanding | formatNumber}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td fxFlex="50%" class="m-l-5"><b>Interest Outstanding :</b></td>
|
||||||
|
<td fxFlex="50%" class="r-amount">{{transferData.details.totalInterestOutstanding | formatNumber}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td fxFlex="50%" class="m-l-5"><b>Fees Outstanding :</b></td>
|
||||||
|
<td fxFlex="50%" class="r-amount">{{transferData.details.totalFeeChargesOutstanding | formatNumber}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td fxFlex="50%" class="m-l-5"><b>Penalties Outstanding :</b></td>
|
||||||
|
<td fxFlex="50%" class="r-amount">{{transferData.details.totalPenaltyChargesOutstanding | formatNumber}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td fxFlex="50%" class="m-l-5"><b>Outstanding :</b></td>
|
||||||
|
<td fxFlex="50%" class="r-amount">{{transferData.details.totalOutstanding | formatNumber}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td fxFlex="50%" class="m-l-5"><b>Overpaid :</b></td>
|
||||||
|
<td fxFlex="50%" class="r-amount">{{transferData.details.totalOverpaid | formatNumber}}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
.asset-transfer-container {
|
||||||
|
|
||||||
|
height: 150px;
|
||||||
|
|
||||||
|
.status {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ExternalAssetTransferComponent } from './external-asset-transfer.component';
|
||||||
|
|
||||||
|
describe('ExternalAssetTransferComponent', () => {
|
||||||
|
let component: ExternalAssetTransferComponent;
|
||||||
|
let fixture: ComponentFixture<ExternalAssetTransferComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ ExternalAssetTransferComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ExternalAssetTransferComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
|
import { ExternalAssetOwner } from 'app/loans/services/external-asset-owner';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-external-asset-transfer',
|
||||||
|
templateUrl: './external-asset-transfer.component.html',
|
||||||
|
styleUrls: ['./external-asset-transfer.component.scss']
|
||||||
|
})
|
||||||
|
export class ExternalAssetTransferComponent implements OnInit {
|
||||||
|
/** Input Fields Data */
|
||||||
|
@Input() transferData: any;
|
||||||
|
|
||||||
|
constructor(private externalAssetOwner: ExternalAssetOwner) { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
console.log(this.transferData);
|
||||||
|
}
|
||||||
|
|
||||||
|
itemStatus(status: string): string {
|
||||||
|
return this.externalAssetOwner.itemStatus(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+1
-1
@@ -36,7 +36,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
|
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
|
||||||
<button type="button" mat-raised-button [routerLink]="['../../general']">Cancel</button>
|
<button type="button" mat-raised-button [routerLink]="['../../loan-collateral']">Cancel</button>
|
||||||
<button mat-raised-button color="primary" [disabled]="!collateralForm.valid"
|
<button mat-raised-button color="primary" [disabled]="!collateralForm.valid"
|
||||||
*mifosxHasPermission="'CREATE_COLLATERAL'">Submit</button>
|
*mifosxHasPermission="'CREATE_COLLATERAL'">Submit</button>
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
|
|||||||
+1
-1
@@ -62,7 +62,7 @@ export class AddCollateralComponent implements OnInit {
|
|||||||
const collateralForm = this.collateralForm.value;
|
const collateralForm = this.collateralForm.value;
|
||||||
collateralForm.locale = 'en';
|
collateralForm.locale = 'en';
|
||||||
this.loanService.createLoanCollateral(loanId, collateralForm).subscribe((response: any) => {
|
this.loanService.createLoanCollateral(loanId, collateralForm).subscribe((response: any) => {
|
||||||
this.router.navigate(['../../general'], { relativeTo: this.route });
|
this.router.navigate(['../../loan-collateral'], { relativeTo: this.route });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -2,7 +2,7 @@ import { Component, Input, OnInit } from '@angular/core';
|
|||||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { Dates } from 'app/core/utils/dates';
|
import { Dates } from 'app/core/utils/dates';
|
||||||
import { ExternalAssetOwnerService } from 'app/loans/external-asset-owner.service';
|
import { ExternalAssetOwnerService } from 'app/loans/services/external-asset-owner.service';
|
||||||
import { SettingsService } from 'app/settings/settings.service';
|
import { SettingsService } from 'app/settings/settings.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -22,7 +22,7 @@ export class AssetTransferLoanComponent implements OnInit {
|
|||||||
minDate = new Date(2000, 0, 1);
|
minDate = new Date(2000, 0, 1);
|
||||||
/** Maximum Date allowed. */
|
/** Maximum Date allowed. */
|
||||||
maxDate = new Date();
|
maxDate = new Date();
|
||||||
/** Sale Loan Form */
|
/** Sell Loan Form */
|
||||||
saleLoanForm: FormGroup;
|
saleLoanForm: FormGroup;
|
||||||
|
|
||||||
constructor(private formBuilder: FormBuilder,
|
constructor(private formBuilder: FormBuilder,
|
||||||
@@ -33,11 +33,11 @@ export class AssetTransferLoanComponent implements OnInit {
|
|||||||
private settingsService: SettingsService) {
|
private settingsService: SettingsService) {
|
||||||
this.loanId = this.route.snapshot.params['loanId'];
|
this.loanId = this.route.snapshot.params['loanId'];
|
||||||
const actionName = this.route.snapshot.params['action'];
|
const actionName = this.route.snapshot.params['action'];
|
||||||
this.command = (actionName === 'Sale Loan') ? this.SALE_COMMAND : this.BUYBACK_COMMAND;
|
this.command = (actionName === 'Sell Loan') ? this.SALE_COMMAND : this.BUYBACK_COMMAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the sale loan form
|
* Creates the Sell Loan form
|
||||||
* and initialize with the required values
|
* and initialize with the required values
|
||||||
*/
|
*/
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
|||||||
@@ -1,25 +1,52 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
<table mat-table [dataSource]="loanDetails.collateral">
|
<div fxLayout="row" fxLayoutAlign="end" fxLayoutGap="20px" class="action-buttons">
|
||||||
|
<button mat-raised-button color="primary" [routerLink]="['../actions/Add Collateral']">
|
||||||
|
Add Collateral
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div fxLayout="row" fxLayoutGap="32px" *ngIf="loanCollaterals?.length > 0" class="performance-history-container">
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td fxFlex="25%">
|
||||||
|
<b>Number of Collaterals :</b>
|
||||||
|
</td>
|
||||||
|
<td fxFlex="25%" class="left">
|
||||||
|
{{loanCollaterals?.length | formatNumber}}
|
||||||
|
</td>
|
||||||
|
<td fxFlex="25%">
|
||||||
|
<b>Total Amount :</b>
|
||||||
|
</td>
|
||||||
|
<td fxFlex="25%" class="left">
|
||||||
|
{{totalAmount | formatNumber}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table mat-table *ngIf="loanCollaterals?.length > 0" [dataSource]="loanCollaterals">
|
||||||
|
|
||||||
<ng-container matColumnDef="id">
|
<ng-container matColumnDef="id">
|
||||||
<th mat-header-cell *matHeaderCellDef> ID </th>
|
<th mat-header-cell *matHeaderCellDef> ID </th>
|
||||||
<td mat-cell *matCellDef="let ele"> {{ ele.clientCollateralId }} </td>
|
<td mat-cell *matCellDef="let ele"> {{ ele.id }} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="quantity">
|
<ng-container matColumnDef="currency">
|
||||||
<th mat-header-cell *matHeaderCellDef> Quantity </th>
|
<th mat-header-cell *matHeaderCellDef> Currency </th>
|
||||||
<td mat-cell *matCellDef="let ele"> {{ ele.quantity }} </td>
|
<td mat-cell *matCellDef="let ele"> {{ ele.currency.code }} </td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="description">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> Description </th>
|
||||||
|
<td mat-cell *matCellDef="let ele"> {{ ele.description }} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="total">
|
<ng-container matColumnDef="total">
|
||||||
<th mat-header-cell *matHeaderCellDef> Total Value </th>
|
<th mat-header-cell *matHeaderCellDef> Total Value </th>
|
||||||
<td mat-cell *matCellDef="let ele"> {{ ele.total }} </td>
|
<td mat-cell *matCellDef="let ele"> {{ ele.value | currency:currencyCode:'symbol-narrow':'1.2-2' }} </td>
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="totalCollateral">
|
|
||||||
<th mat-header-cell *matHeaderCellDef> Total Collateral Value </th>
|
|
||||||
<td mat-cell *matCellDef="let ele"> {{ ele.totalCollateral }} </td>
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||||
|
|||||||
@@ -8,22 +8,28 @@ import { ActivatedRoute } from '@angular/router';
|
|||||||
})
|
})
|
||||||
export class LoanCollateralTabComponent implements OnInit {
|
export class LoanCollateralTabComponent implements OnInit {
|
||||||
|
|
||||||
/** Loan Details */
|
/** Loan Collateral Details */
|
||||||
loanDetails: any;
|
loanCollaterals: any[] = [];
|
||||||
/** Columns to be displayed in collateral table. */
|
/** Columns to be displayed in collateral table. */
|
||||||
displayedColumns: string[] = ['id', 'quantity', 'total', 'totalCollateral'];
|
displayedColumns: string[] = ['id', 'currency', 'description', 'total'];
|
||||||
|
|
||||||
|
totalAmount: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the loans data from `resolve`.
|
* Retrieves the loans data from `resolve`.
|
||||||
* @param {ActivatedRoute} route Activated Route.
|
* @param {ActivatedRoute} route Activated Route.
|
||||||
*/
|
*/
|
||||||
constructor(private route: ActivatedRoute) {
|
constructor(private route: ActivatedRoute) {
|
||||||
this.route.parent.data.subscribe((data: { loanDetailsData: any }) => {
|
this.route.data.subscribe((data: { loanCollaterals: any }) => {
|
||||||
this.loanDetails = data.loanDetailsData;
|
this.loanCollaterals = data.loanCollaterals;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
this.totalAmount = 0;
|
||||||
|
this.loanCollaterals.forEach((collateral: any) => {
|
||||||
|
this.totalAmount = this.totalAmount + collateral.value;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,13 +162,15 @@ export class TransactionsTabComponent implements OnInit {
|
|||||||
if (this.isChargeOff(transaction.type)) {
|
if (this.isChargeOff(transaction.type)) {
|
||||||
command = 'undo-charge-off';
|
command = 'undo-charge-off';
|
||||||
operationDate = this.settingsService.businessDate;
|
operationDate = this.settingsService.businessDate;
|
||||||
|
payload = {};
|
||||||
|
} else {
|
||||||
|
payload = {
|
||||||
|
transactionDate: this.dateUtils.formatDate(operationDate && new Date(operationDate), dateFormat),
|
||||||
|
transactionAmount: 0,
|
||||||
|
dateFormat,
|
||||||
|
locale
|
||||||
|
};
|
||||||
}
|
}
|
||||||
payload = {
|
|
||||||
transactionDate: this.dateUtils.formatDate(operationDate && new Date(operationDate), dateFormat),
|
|
||||||
transactionAmount: 0,
|
|
||||||
dateFormat,
|
|
||||||
locale
|
|
||||||
};
|
|
||||||
|
|
||||||
const undoTransactionAccountDialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
const undoTransactionAccountDialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
||||||
data: { heading: 'Undo Transaction', dialogContext: `Are you sure you want undo the transaction type ${transaction.type.value} with id ${transaction.id}` }
|
data: { heading: 'Undo Transaction', dialogContext: `Are you sure you want undo the transaction type ${transaction.type.value} with id ${transaction.id}` }
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ import { AdjustLoanChargeComponent } from './loans-view/loan-account-actions/adj
|
|||||||
import { ChargeOffComponent } from './loans-view/loan-account-actions/charge-off/charge-off.component';
|
import { ChargeOffComponent } from './loans-view/loan-account-actions/charge-off/charge-off.component';
|
||||||
import { AssetTransferLoanComponent } from './loans-view/loan-account-actions/asset-transfer-loan/asset-transfer-loan.component';
|
import { AssetTransferLoanComponent } from './loans-view/loan-account-actions/asset-transfer-loan/asset-transfer-loan.component';
|
||||||
import { ExternalAssetOwnerTabComponent } from './loans-view/external-asset-owner-tab/external-asset-owner-tab.component';
|
import { ExternalAssetOwnerTabComponent } from './loans-view/external-asset-owner-tab/external-asset-owner-tab.component';
|
||||||
|
import { ExternalAssetTransferComponent } from './loans-view/external-asset-owner-tab/external-asset-transfer/external-asset-transfer.component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loans Module
|
* Loans Module
|
||||||
@@ -152,7 +153,8 @@ import { ExternalAssetOwnerTabComponent } from './loans-view/external-asset-owne
|
|||||||
AdjustLoanChargeComponent,
|
AdjustLoanChargeComponent,
|
||||||
ChargeOffComponent,
|
ChargeOffComponent,
|
||||||
AssetTransferLoanComponent,
|
AssetTransferLoanComponent,
|
||||||
ExternalAssetOwnerTabComponent
|
ExternalAssetOwnerTabComponent,
|
||||||
|
ExternalAssetTransferComponent
|
||||||
],
|
],
|
||||||
providers: [ ],
|
providers: [ ],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -112,6 +112,15 @@ export class LoansService {
|
|||||||
return this.http.get(`/loans/${loanId}/collaterals/template`);
|
return this.http.get(`/loans/${loanId}/collaterals/template`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get collaterals.
|
||||||
|
* @param {string} loanId Loan Id.
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
getLoanCollaterals(loanId: string): Observable<any> {
|
||||||
|
return this.http.get(`/loans/${loanId}/collaterals`);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create Loan Collateral.
|
* Create Loan Collateral.
|
||||||
* @param {string} loanId Loan Id.
|
* @param {string} loanId Loan Id.
|
||||||
|
|||||||
+15
-5
@@ -7,6 +7,8 @@ import { Observable } from 'rxjs';
|
|||||||
})
|
})
|
||||||
export class ExternalAssetOwnerService {
|
export class ExternalAssetOwnerService {
|
||||||
|
|
||||||
|
basePath = '/external-asset-owners';
|
||||||
|
|
||||||
constructor(private http: HttpClient) { }
|
constructor(private http: HttpClient) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -17,7 +19,7 @@ export class ExternalAssetOwnerService {
|
|||||||
*/
|
*/
|
||||||
executeExternalAssetOwnerLoanCommand(loanId: string, data: any, command: string): Observable<any> {
|
executeExternalAssetOwnerLoanCommand(loanId: string, data: any, command: string): Observable<any> {
|
||||||
const httpParams = new HttpParams().set('command', command);
|
const httpParams = new HttpParams().set('command', command);
|
||||||
return this.http.post(`/external-asset-owners/transfers/loans/${loanId}`, data, { params: httpParams });
|
return this.http.post(`${this.basePath}/transfers/loans/${loanId}`, data, { params: httpParams });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,7 +30,7 @@ export class ExternalAssetOwnerService {
|
|||||||
*/
|
*/
|
||||||
executeExternalAssetOwnerTransferCommand(transferId: string, data: any, command: string): Observable<any> {
|
executeExternalAssetOwnerTransferCommand(transferId: string, data: any, command: string): Observable<any> {
|
||||||
const httpParams = new HttpParams().set('command', command);
|
const httpParams = new HttpParams().set('command', command);
|
||||||
return this.http.post(`/external-asset-owners/transfers/${transferId}`, data, { params: httpParams });
|
return this.http.post(`${this.basePath}/transfers/${transferId}`, data, { params: httpParams });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,7 +39,7 @@ export class ExternalAssetOwnerService {
|
|||||||
*/
|
*/
|
||||||
retrieveExternalAssetOwnerTransfers(loanId: string): Observable<any> {
|
retrieveExternalAssetOwnerTransfers(loanId: string): Observable<any> {
|
||||||
const httpParams = new HttpParams().set('loanId', loanId);
|
const httpParams = new HttpParams().set('loanId', loanId);
|
||||||
return this.http.get(`/external-asset-owners/transfers`, { params: httpParams });
|
return this.http.get(`${this.basePath}/transfers`, { params: httpParams });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,7 +48,7 @@ export class ExternalAssetOwnerService {
|
|||||||
*/
|
*/
|
||||||
retrieveExternalAssetOwnerActiveTransfer(loanId: string): Observable<any> {
|
retrieveExternalAssetOwnerActiveTransfer(loanId: string): Observable<any> {
|
||||||
const httpParams = new HttpParams().set('loanId', loanId);
|
const httpParams = new HttpParams().set('loanId', loanId);
|
||||||
return this.http.get(`/external-asset-owners/transfers/active-transfer`, { params: httpParams });
|
return this.http.get(`${this.basePath}/transfers/active-transfer`, { params: httpParams });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,7 +56,15 @@ export class ExternalAssetOwnerService {
|
|||||||
* @returns {Observable<any>}
|
* @returns {Observable<any>}
|
||||||
*/
|
*/
|
||||||
retrieveExternalAssetOwnerTransferJournalEntries(transferId: string): Observable<any> {
|
retrieveExternalAssetOwnerTransferJournalEntries(transferId: string): Observable<any> {
|
||||||
return this.http.get(`/external-asset-owners/transfers/${transferId}/journal-entries`);
|
return this.http.get(`${this.basePath}/transfers/${transferId}/journal-entries`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {any} request Transfer Id
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
searchExternalAssetOwnerTransfer(request: any): Observable<any> {
|
||||||
|
return this.http.post(`${this.basePath}/search`, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class ExternalAssetOwner {
|
||||||
|
defaultDate = '9999-12-31';
|
||||||
|
|
||||||
|
validateStatus(item: any, status: string): boolean {
|
||||||
|
if (item != null) {
|
||||||
|
return (item.status === status);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
itemCurrentStatus(item: any): string {
|
||||||
|
if (this.isBuyBackPending(item)) {
|
||||||
|
return item.status + ' PENDING';
|
||||||
|
}
|
||||||
|
return item.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
itemStatus(status: string): string {
|
||||||
|
return 'status-' + status.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
isPending(item: any): boolean {
|
||||||
|
return (item.status === 'PENDING');
|
||||||
|
}
|
||||||
|
|
||||||
|
isPendingOrCanceled(item: any): boolean {
|
||||||
|
return ((item.status === 'PENDING') || (item.status === 'CANCELLED') || this.isBuyBackPending(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
isBuyBackPending(item: any): boolean {
|
||||||
|
return (item.status === 'BUYBACK' && item.effectiveTo === this.defaultDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
canBeCancelled(item: any): boolean {
|
||||||
|
return this.validateStatus(item, 'PENDING');
|
||||||
|
}
|
||||||
|
|
||||||
|
canBeSold(item: any): boolean {
|
||||||
|
if (item == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return ['', 'CANCELLED'].includes(item.status)
|
||||||
|
|| (item.status === 'BUYBACK' && item.effectiveTo !== this.defaultDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
canBeBuyed(item: any): boolean {
|
||||||
|
return this.validateStatus(item, 'ACTIVE');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,84 +1,145 @@
|
|||||||
<div class="container" fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
<mat-card class="container">
|
||||||
|
|
||||||
<mat-form-field fxFlex="31%">
|
<div fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||||
<mat-label>{{ 'labels.inputs.Filter' | translate }}</mat-label>
|
|
||||||
<mat-select [formControl]="entryTypeFilter">
|
|
||||||
<mat-option *ngFor="let filter of entryTypeFilterData" [value]="filter.value">
|
|
||||||
{{ filter.option }}
|
|
||||||
</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<mat-form-field fxFlex="31%" (click)="transferDateFromPicker.open()">
|
<mat-form-field fxFlex="22%" (click)="effectiveFromDatePicker.open()">
|
||||||
<mat-label>Transfer Date From</mat-label>
|
<mat-label>Effective Date From</mat-label>
|
||||||
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="transferDateFromPicker" [formControl]="transferDateFrom">
|
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="effectiveFromDatePicker"
|
||||||
<mat-datepicker-toggle matSuffix [for]="transferDateFromPicker"></mat-datepicker-toggle>
|
[formControl]="effectiveFromDate">
|
||||||
<mat-datepicker #transferDateFromPicker></mat-datepicker>
|
<mat-datepicker-toggle matSuffix [for]="effectiveFromDatePicker"></mat-datepicker-toggle>
|
||||||
</mat-form-field>
|
<mat-datepicker #effectiveFromDatePicker></mat-datepicker>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field fxFlex="31%" (click)="transferDateToPicker.open()">
|
<mat-form-field fxFlex="22%" (click)="effectiveToDatePicker.open()">
|
||||||
<mat-label>Transfer Date To</mat-label>
|
<mat-label>Effective Date To</mat-label>
|
||||||
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="transferDateToPicker" [formControl]="transferDateTo">
|
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="effectiveToDatePicker"
|
||||||
<mat-datepicker-toggle matSuffix [for]="transferDateToPicker"></mat-datepicker-toggle>
|
[formControl]="effectiveToDate">
|
||||||
<mat-datepicker #transferDateToPicker></mat-datepicker>
|
<mat-datepicker-toggle matSuffix [for]="effectiveToDatePicker"></mat-datepicker-toggle>
|
||||||
</mat-form-field>
|
<mat-datepicker #effectiveToDatePicker></mat-datepicker>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field fxFlex="31%">
|
<mat-form-field fxFlex="22%" (click)="settlementFromDatePicker.open()">
|
||||||
<mat-label>Transfer External Id</mat-label>
|
<mat-label>Settlement Date From</mat-label>
|
||||||
<input matInput [formControl]="transferExternalId">
|
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="settlementFromDatePicker"
|
||||||
</mat-form-field>
|
[formControl]="settlementFromDate">
|
||||||
|
<mat-datepicker-toggle matSuffix [for]="settlementFromDatePicker"></mat-datepicker-toggle>
|
||||||
|
<mat-datepicker #settlementFromDatePicker></mat-datepicker>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
</div>
|
<mat-form-field fxFlex="22%" (click)="settlementToDatePicker.open()">
|
||||||
|
<mat-label>Settlement Date To</mat-label>
|
||||||
|
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="settlementToDatePicker"
|
||||||
|
[formControl]="settlementToDate">
|
||||||
|
<mat-datepicker-toggle matSuffix [for]="settlementToDatePicker"></mat-datepicker-toggle>
|
||||||
|
<mat-datepicker #settlementToDatePicker></mat-datepicker>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
<div class="mat-elevation-z8 container">
|
<mat-form-field fxFlex="60%">
|
||||||
|
<mat-label>Transaction ID</mat-label>
|
||||||
|
<input matInput [formControl]="searchText">
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
<table mat-table [dataSource]="dataSource" matSort>
|
<ng-container fxFlex="40%" class="right">
|
||||||
|
<button mat-raised-button color="primary" (click)="searchEAO()">
|
||||||
<ng-container matColumnDef="investor">
|
<fa-icon icon="search" class="m-r-10"></fa-icon> Search
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Investor </th>
|
</button>
|
||||||
<td mat-cell *matCellDef="let item"> </td>
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
<ng-container matColumnDef="loanAccount">
|
<div class="mat-elevation-z8 container">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Loan </th>
|
<mat-progress-bar mode="indeterminate" *ngIf="isLoading"></mat-progress-bar>
|
||||||
<td mat-cell *matCellDef="let item"> </td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="totalAmount">
|
<table mat-table [dataSource]="dataSource" matSort *ngIf="existsDataToFilter" multiTemplateDataRows>
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Total Amount </th>
|
|
||||||
<td mat-cell *matCellDef="let item"> </td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="principal">
|
<ng-container matColumnDef="status">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Principal </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> Status </th>
|
||||||
<td mat-cell *matCellDef="let item"> </td>
|
<td mat-cell *matCellDef="let item">
|
||||||
</ng-container>
|
<div [ngClass]="itemStatus(item.status)">
|
||||||
|
<fa-icon icon="stop"></fa-icon>
|
||||||
|
<span class="m-l-10 status">{{item.status}}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="interest">
|
<ng-container matColumnDef="effectiveFrom">
|
||||||
<th mat-header-cell *matHeaderCellDef> Interest </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> Effective From Date </th>
|
||||||
<td mat-cell *matCellDef="let item"> </td>
|
<td mat-cell *matCellDef="let item"> {{ item.effectiveFrom | dateFormat }} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="fees">
|
<ng-container matColumnDef="ownerExternalId">
|
||||||
<th mat-header-cell *matHeaderCellDef> Fees </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> Owner </th>
|
||||||
<td mat-cell *matCellDef="let item"> </td>
|
<td mat-cell *matCellDef="let item">
|
||||||
</ng-container>
|
<mifosx-external-identifier externalId="{{item.owner.externalId}}"></mifosx-external-identifier>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="penalties">
|
<ng-container matColumnDef="loanAccount">
|
||||||
<th mat-header-cell *matHeaderCellDef> Penalties </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> Loan </th>
|
||||||
<td mat-cell *matCellDef="let item"> </td>
|
<td mat-cell *matCellDef="let item"> {{ item.loan.loanId }} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="actions">
|
<ng-container matColumnDef="transferExternalId">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Actions </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> Transfer </th>
|
||||||
<td mat-cell *matCellDef="let item"> </td>
|
<td mat-cell *matCellDef="let item">
|
||||||
</ng-container>
|
<mifosx-external-identifier externalId="{{item.transferExternalId}}"></mifosx-external-identifier>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
<ng-container matColumnDef="settlementDate">
|
||||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [routerLink]="['transactions/view', row.transactionId]" class="select-row"></tr>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> Settlement Date </th>
|
||||||
|
<td mat-cell *matCellDef="let item"> {{ item.settlementDate | dateFormat }} </td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
</table>
|
<ng-container matColumnDef="purchasePriceRatio">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> Purchase Price Ratio </th>
|
||||||
|
<td mat-cell *matCellDef="let item"> {{ item.purchasePriceRatio | number }} </td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<mat-paginator [pageSize]="50" [pageSizeOptions]="[50, 100, 200, 500]" showFirstLastButtons></mat-paginator>
|
<ng-container matColumnDef="totalAmount">
|
||||||
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> Total Amount </th>
|
||||||
|
<td mat-cell *matCellDef="let item">
|
||||||
|
<span *ngIf="item.details">
|
||||||
|
{{ item.details.totalOutstanding | number }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
</div>
|
<ng-container matColumnDef="actions">
|
||||||
|
<th mat-header-cell class="center" *matHeaderCellDef> Actions </th>
|
||||||
|
<td mat-cell *matCellDef="let item" class="center td-min-space">
|
||||||
|
<button class="account-action-button" *ngIf="!isPendingOrCanceled(item)" mat-raised-button color="primary" matTooltip="View Journal Entries"
|
||||||
|
matTooltipPosition="left" (click)="routeJournalEntry($event)" [routerLink]="['/', 'journal-entry', 'view-transfer', item.transferId]">
|
||||||
|
<i class="fa fa-arrow-circle-right"></i>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="expandedDetail">
|
||||||
|
<td mat-cell *matCellDef="let item" [attr.colspan]="displayedColumns.length">
|
||||||
|
<div class="element-detail"
|
||||||
|
[@detailExpand]="item.transferId == expandedRowId ? 'expanded' : 'collapsed'">
|
||||||
|
<mifosx-external-asset-transfer [transferData]="item"></mifosx-external-asset-transfer>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let item; columns: displayedColumns;"
|
||||||
|
class="element-row"
|
||||||
|
[class.expanded-row]="expandedRowId === item.transferId"
|
||||||
|
(click)="expandedRowId = expandedRowId === item.transferId ? null : item.transferId"></tr>
|
||||||
|
<tr mat-row *matRowDef="let item; columns: ['expandedDetail']" class="detail-row"></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="[50, 100, 200]" [length]="totalRows" (page)="pageChanged($event)"
|
||||||
|
showFirstLastButtons *ngIf="existsDataToFilter"></mat-paginator>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="alert" *ngIf="!existsDataToFilter">
|
||||||
|
<div class="message">
|
||||||
|
<i class="fa fa-exclamation-circle alert-check"></i>
|
||||||
|
No data was found
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</mat-card>
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
.status {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-action-button{
|
||||||
|
min-width: 26px;
|
||||||
|
padding: 0 0 3px 0;
|
||||||
|
margin: 0 2%;
|
||||||
|
line-height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-detail {
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.detail-row {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.element-row:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.element-row:not(.expanded-row):hover {
|
||||||
|
background: whitesmoke;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.element-row:not(.expanded-row):active {
|
||||||
|
background: #efefef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.element-row td {
|
||||||
|
border-bottom-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.element-detail {
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +1,25 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||||
|
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||||
import { FormControl } from '@angular/forms';
|
import { FormControl } from '@angular/forms';
|
||||||
|
import { MatPaginator, PageEvent } from '@angular/material/paginator';
|
||||||
|
import { MatSort } from '@angular/material/sort';
|
||||||
import { MatTableDataSource } from '@angular/material/table';
|
import { MatTableDataSource } from '@angular/material/table';
|
||||||
|
import { Dates } from 'app/core/utils/dates';
|
||||||
|
import { ExternalAssetOwner } from 'app/loans/services/external-asset-owner';
|
||||||
|
import { ExternalAssetOwnerService } from 'app/loans/services/external-asset-owner.service';
|
||||||
|
import { SettingsService } from 'app/settings/settings.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'mifosx-investors',
|
selector: 'mifosx-investors',
|
||||||
templateUrl: './investors.component.html',
|
templateUrl: './investors.component.html',
|
||||||
styleUrls: ['./investors.component.scss']
|
styleUrls: ['./investors.component.scss'],
|
||||||
|
animations: [
|
||||||
|
trigger('detailExpand', [
|
||||||
|
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 InvestorsComponent implements OnInit {
|
export class InvestorsComponent implements OnInit {
|
||||||
|
|
||||||
@@ -14,9 +28,28 @@ export class InvestorsComponent implements OnInit {
|
|||||||
/** Maximum transaction date allowed. */
|
/** Maximum transaction date allowed. */
|
||||||
maxDate = new Date();
|
maxDate = new Date();
|
||||||
|
|
||||||
transferDateFrom = new FormControl('');
|
searchText = new FormControl('');
|
||||||
transferDateTo = new FormControl('');
|
effectiveFromDate = new FormControl('');
|
||||||
transferExternalId = new FormControl('');
|
effectiveToDate = new FormControl('');
|
||||||
|
settlementFromDate = new FormControl('');
|
||||||
|
settlementToDate = new FormControl('');
|
||||||
|
|
||||||
|
dataSource: MatTableDataSource<any> = new MatTableDataSource();
|
||||||
|
existsDataToFilter = false;
|
||||||
|
expandedRowId: number | null;
|
||||||
|
|
||||||
|
totalRows: number;
|
||||||
|
isLoading = false;
|
||||||
|
|
||||||
|
pageSize = 50;
|
||||||
|
currentPage = 0;
|
||||||
|
filterText = '';
|
||||||
|
|
||||||
|
sortAttribute = '';
|
||||||
|
sortDirection = '';
|
||||||
|
|
||||||
|
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||||
|
@ViewChild(MatSort) sort: MatSort;
|
||||||
|
|
||||||
/** Entry type filter form control. */
|
/** Entry type filter form control. */
|
||||||
entryTypeFilter = new FormControl('');
|
entryTypeFilter = new FormControl('');
|
||||||
@@ -27,7 +60,7 @@ export class InvestorsComponent implements OnInit {
|
|||||||
value: ''
|
value: ''
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
option: 'Sale',
|
option: 'Sell',
|
||||||
value: true
|
value: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -37,13 +70,87 @@ export class InvestorsComponent implements OnInit {
|
|||||||
];
|
];
|
||||||
|
|
||||||
/** Columns to be displayed in investors table. */
|
/** Columns to be displayed in investors table. */
|
||||||
displayedColumns: string[] = ['investor', 'loanAccount', 'totalAmount', 'principal', 'interest', 'fees', 'penalties', 'actions'];
|
displayedColumns: string[] = ['status', 'effectiveFrom', 'ownerExternalId', 'loanAccount', 'transferExternalId', 'settlementDate', 'purchasePriceRatio', 'totalAmount', 'actions'];
|
||||||
/** Data source for investors table. */
|
constructor(private settingsService: SettingsService,
|
||||||
dataSource: MatTableDataSource<any> = new MatTableDataSource();
|
private externalAssetOwner: ExternalAssetOwner,
|
||||||
|
private externalAssetOwnerService: ExternalAssetOwnerService,
|
||||||
constructor() { }
|
private dateUtils: Dates) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
this.maxDate = this.settingsService.maxAllowedDate;
|
||||||
|
this.searchEAO();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
itemStatus(status: string): string {
|
||||||
|
return this.externalAssetOwner.itemStatus(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
isPending(item: any): boolean {
|
||||||
|
return this.externalAssetOwner.isPending(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
isPendingOrCanceled(item: any): boolean {
|
||||||
|
return this.externalAssetOwner.isPendingOrCanceled(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
isBuyBackPending(item: any): boolean {
|
||||||
|
return this.externalAssetOwner.isBuyBackPending(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
canBeCancelled(item: any): boolean {
|
||||||
|
return this.externalAssetOwner.validateStatus(item, 'PENDING');
|
||||||
|
}
|
||||||
|
|
||||||
|
canBeSold(item: any): boolean {
|
||||||
|
return this.externalAssetOwner.canBeSold(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
canBeBuyed(item: any): boolean {
|
||||||
|
return this.externalAssetOwner.validateStatus(item, 'ACTIVE');
|
||||||
|
}
|
||||||
|
|
||||||
|
searchEAO(): void {
|
||||||
|
this.isLoading = true;
|
||||||
|
const payload: any = {
|
||||||
|
'request': {},
|
||||||
|
'page': this.currentPage,
|
||||||
|
'size': this.pageSize
|
||||||
|
};
|
||||||
|
const dateFormat = 'yyyy-MM-dd';
|
||||||
|
const request: any = {};
|
||||||
|
if (this.searchText.value) {
|
||||||
|
request['text'] = this.searchText.value;
|
||||||
|
}
|
||||||
|
if (this.effectiveFromDate.value) {
|
||||||
|
request['effectiveFromDate'] = this.dateUtils.formatDate(this.effectiveFromDate.value, dateFormat);
|
||||||
|
}
|
||||||
|
if (this.effectiveToDate.value) {
|
||||||
|
request['effectiveToDate'] = this.dateUtils.formatDate(this.effectiveToDate.value, dateFormat);
|
||||||
|
}
|
||||||
|
if (this.settlementFromDate.value) {
|
||||||
|
request['settlementFromDate'] = this.dateUtils.formatDate(this.settlementFromDate.value, dateFormat);
|
||||||
|
}
|
||||||
|
if (this.settlementToDate.value) {
|
||||||
|
request['settlementToDate'] = this.dateUtils.formatDate(this.settlementToDate.value, dateFormat);
|
||||||
|
}
|
||||||
|
payload['request'] = request;
|
||||||
|
this.externalAssetOwnerService.searchExternalAssetOwnerTransfer(payload).subscribe((response: any) => {
|
||||||
|
this.totalRows = response.totalElements;
|
||||||
|
this.existsDataToFilter = (response.totalElements > 0);
|
||||||
|
this.dataSource.data = response.content;
|
||||||
|
this.isLoading = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pageChanged(event: PageEvent) {
|
||||||
|
this.pageSize = event.pageSize;
|
||||||
|
this.currentPage = event.pageIndex;
|
||||||
|
this.searchEAO();
|
||||||
|
}
|
||||||
|
|
||||||
|
private resetPaginator() {
|
||||||
|
this.currentPage = 0;
|
||||||
|
this.paginator.firstPage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ import { CreateFundComponent } from './manage-funds/create-fund/create-fund.comp
|
|||||||
import { EditFundComponent } from './manage-funds/edit-fund/edit-fund.component';
|
import { EditFundComponent } from './manage-funds/edit-fund/edit-fund.component';
|
||||||
import { ViewFundComponent } from './manage-funds/view-fund/view-fund.component';
|
import { ViewFundComponent } from './manage-funds/view-fund/view-fund.component';
|
||||||
import { InvestorsComponent } from './investors/investors.component';
|
import { InvestorsComponent } from './investors/investors.component';
|
||||||
|
import { ExternalAssetTransferComponent } from 'app/loans/loans-view/external-asset-owner-tab/external-asset-transfer/external-asset-transfer.component';
|
||||||
|
import { LoansModule } from 'app/loans/loans.module';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,7 +92,8 @@ import { InvestorsComponent } from './investors/investors.component';
|
|||||||
SharedModule,
|
SharedModule,
|
||||||
PipesModule,
|
PipesModule,
|
||||||
DirectivesModule,
|
DirectivesModule,
|
||||||
OrganizationRoutingModule
|
OrganizationRoutingModule,
|
||||||
|
LoansModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
OrganizationComponent,
|
OrganizationComponent,
|
||||||
@@ -155,7 +158,7 @@ import { InvestorsComponent } from './investors/investors.component';
|
|||||||
CreateFundComponent,
|
CreateFundComponent,
|
||||||
EditFundComponent,
|
EditFundComponent,
|
||||||
ViewFundComponent,
|
ViewFundComponent,
|
||||||
InvestorsComponent,
|
InvestorsComponent
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
CreateHoliday,
|
CreateHoliday,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
<mat-card>
|
<mat-card>
|
||||||
|
|
||||||
<form [formGroup]="collateralForm" (ngSubmit)="submit()">
|
<form [formGroup]="collateralForm" (ngSubmit)="submit()">
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
|
|
||||||
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
|
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
|
||||||
@@ -68,4 +68,4 @@
|
|||||||
|
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+2
-2
@@ -96,13 +96,13 @@ export class LoanProductSettingsStepComponent implements OnInit {
|
|||||||
|
|
||||||
if (this.loanProductsTemplate.delinquencyBucket) {
|
if (this.loanProductsTemplate.delinquencyBucket) {
|
||||||
this.loanProductSettingsForm.patchValue({
|
this.loanProductSettingsForm.patchValue({
|
||||||
'disbursedAmountPercentageForDownPayment': this.loanProductsTemplate.disbursedAmountPercentageForDownPayment || 0
|
'delinquencyBucketId': this.loanProductsTemplate.delinquencyBucket.id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.loanProductsTemplate.enableDownPayment) {
|
if (this.loanProductsTemplate.enableDownPayment) {
|
||||||
this.loanProductSettingsForm.patchValue({
|
this.loanProductSettingsForm.patchValue({
|
||||||
'delinquencyBucketId': this.loanProductsTemplate.delinquencyBucket.id
|
'disbursedAmountPercentageForDownPayment': this.loanProductsTemplate.disbursedAmountPercentageForDownPayment || 0
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,9 @@
|
|||||||
|
|
||||||
<ng-container matColumnDef="entityAccount">
|
<ng-container matColumnDef="entityAccount">
|
||||||
<th mat-header-cell *matHeaderCellDef> Account No </th>
|
<th mat-header-cell *matHeaderCellDef> Account No </th>
|
||||||
<td mat-cell *matCellDef="let entity" class="view-details"> {{entity.entityAccountNo}} </td>
|
<td mat-cell *matCellDef="let entity" class="view-details">
|
||||||
|
<mifosx-account-number display="left" accountNo="{{entity.entityAccountNo}}"></mifosx-account-number>
|
||||||
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="externalId">
|
<ng-container matColumnDef="externalId">
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<span (mouseenter)="mouseEnter()" (mouseleave)="mouseLeave()">
|
<span (mouseenter)="mouseEnter()" (mouseleave)="mouseLeave()" *ngIf="!emptyValue">
|
||||||
<span (click)="copyValue()" *ngIf="displayL && iconVisible"><fa-icon icon="copy" size="sm" title="Copy External Id"></fa-icon></span>
|
<span (click)="copyValue()" *ngIf="displayL && iconVisible"><fa-icon icon="copy" size="sm" title="Copy External Id"></fa-icon></span>
|
||||||
<span class="m-l-3" *ngIf="displayL && !completed && iconVisible && isLongValue()"><fa-icon icon="eye" size="sm" [title]="externalId"></fa-icon></span>
|
<span class="m-l-3" *ngIf="displayL && !completed && iconVisible && isLongValue()"><fa-icon icon="eye" size="sm" [title]="externalId"></fa-icon></span>
|
||||||
<span class="m-l-5" *ngIf="!completed">{{ externalId | externalIdentifier }}</span>
|
<span class="m-l-5" *ngIf="!completed">{{ externalId | externalIdentifier }}</span>
|
||||||
|
|||||||
@@ -15,11 +15,13 @@ export class ExternalIdentifierComponent implements OnInit {
|
|||||||
iconVisible = false;
|
iconVisible = false;
|
||||||
displayL = false;
|
displayL = false;
|
||||||
displayR = true;
|
displayR = true;
|
||||||
|
emptyValue = false;
|
||||||
|
|
||||||
constructor(private clipboard: Clipboard,
|
constructor(private clipboard: Clipboard,
|
||||||
private alertService: AlertService) { }
|
private alertService: AlertService) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
this.emptyValue = (!this.externalId || this.externalId === '');
|
||||||
this.displayL = (this.display === 'left');
|
this.displayL = (this.display === 'left');
|
||||||
this.displayR = (this.display === 'right');
|
this.displayR = (this.display === 'right');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import { SettingsService } from './settings/settings.service';
|
|||||||
import { Alert } from './core/alert/alert.model';
|
import { Alert } from './core/alert/alert.model';
|
||||||
import { KeyboardShortcutsConfiguration } from './keyboards-shortcut-config';
|
import { KeyboardShortcutsConfiguration } from './keyboards-shortcut-config';
|
||||||
import { Dates } from './core/utils/dates';
|
import { Dates } from './core/utils/dates';
|
||||||
|
import { animate, style, transition, trigger } from '@angular/animations';
|
||||||
|
|
||||||
/** Initialize Logger */
|
/** Initialize Logger */
|
||||||
const log = new Logger('MifosX');
|
const log = new Logger('MifosX');
|
||||||
@@ -35,7 +36,19 @@ const log = new Logger('MifosX');
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'mifosx-web-app',
|
selector: 'mifosx-web-app',
|
||||||
templateUrl: './web-app.component.html',
|
templateUrl: './web-app.component.html',
|
||||||
styleUrls: ['./web-app.component.scss']
|
styleUrls: ['./web-app.component.scss'],
|
||||||
|
animations: [
|
||||||
|
trigger('opacityScale', [
|
||||||
|
transition(':enter', [
|
||||||
|
style({ opacity: 0, transform: 'scale(.95)' }),
|
||||||
|
animate('100ms ease-out', style({ opacity: 1, transform: 'scale(1)' }))
|
||||||
|
]),
|
||||||
|
transition(':leave', [
|
||||||
|
style({ opacity: 1, transform: 'scale(1)' }),
|
||||||
|
animate('75ms ease-in', style({ opacity: 0, transform: 'scale(.95)' }))
|
||||||
|
])
|
||||||
|
])
|
||||||
|
]
|
||||||
})
|
})
|
||||||
export class WebAppComponent implements OnInit {
|
export class WebAppComponent implements OnInit {
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en" class="h-full bg-gray-100">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<title>{{ 'APP_NAME' | translate }}</title>
|
<title>{{ 'APP_NAME' | translate }}</title>
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
<!-- Load environment variables -->
|
<!-- Load environment variables -->
|
||||||
<script src="assets/env.js"></script>
|
<script src="assets/env.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body class="h-full">
|
||||||
<!--[if lt IE 10]>
|
<!--[if lt IE 10]>
|
||||||
<p>
|
<p>
|
||||||
You are using an <strong>outdated</strong> browser.
|
You are using an <strong>outdated</strong> browser.
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Import Default Theme for MifosX
|
// Import Default Theme for MifosX
|
||||||
@import "theme/custom/denim-yellowgreen";
|
@import "theme/mifosx-theme";
|
||||||
|
|
||||||
// Global Imports
|
// Global Imports
|
||||||
/* You can add global styles to this file, and also import other style files */
|
/* You can add global styles to this file, and also import other style files */
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
$primary-palette: (
|
||||||
|
100: #5ba2ec,
|
||||||
|
500: #1074b9,
|
||||||
|
700: #004989,
|
||||||
|
contrast: (
|
||||||
|
100: rgba(black, 0.87),
|
||||||
|
500: white,
|
||||||
|
700: white
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$accent-palette: (
|
||||||
|
100: #e7ffa5,
|
||||||
|
500: #b4d575,
|
||||||
|
700: #83a447,
|
||||||
|
contrast: (
|
||||||
|
100: rgba(black, 0.87),
|
||||||
|
500: rgba(black, 0.87),
|
||||||
|
700: rgba(black, 0.87)
|
||||||
|
)
|
||||||
|
);
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
@use '@angular/material' as mat;
|
|
||||||
// Plus imports for other components in your app.
|
|
||||||
@import '../../app/clients/clients-view/clients-view.component-theme.scss';
|
|
||||||
@import '../../app/groups/groups-view/groups-view.component-theme.scss';
|
|
||||||
@import '../../app/centers/centers-view/centers-view.component-theme.scss';
|
|
||||||
@import '../../app/home/dashboard/dashboard.component-theme.scss';
|
|
||||||
@import '../../app/loans/loans-view/loans-view.component-theme.scss';
|
|
||||||
@import '../../app/savings/savings-account-view/savings-account-view.component-theme.scss';
|
|
||||||
@import '../../app/shares/shares-account-view/shares-account-view.component-theme.scss';
|
|
||||||
@import '../../app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component-theme.scss';
|
|
||||||
@import '../../app/deposits/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component-theme.scss';
|
|
||||||
|
|
||||||
// Custom material palette
|
|
||||||
$mat-picton-blue: (
|
|
||||||
100: #6ce0ff,
|
|
||||||
500: #1daeec,
|
|
||||||
700: #007fb9,
|
|
||||||
contrast: (
|
|
||||||
100: rgba(black, 0.87),
|
|
||||||
500: rgba(black, 0.87),
|
|
||||||
700: rgba(black, 0.87)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$mat-yellow-green: (
|
|
||||||
100: #e7ffa5,
|
|
||||||
500: #b4d575,
|
|
||||||
700: #83a447,
|
|
||||||
contrast: (
|
|
||||||
100: rgba(black, 0.87),
|
|
||||||
500: rgba(black, 0.87),
|
|
||||||
700: rgba(black, 0.87)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Include the common styles for Angular Material. We include this here so that you only
|
|
||||||
// have to load a single css file for Angular Material in your app.
|
|
||||||
// Be sure that you only ever include this mixin once!
|
|
||||||
@include mat.core();
|
|
||||||
|
|
||||||
// Define the palettes for your theme using the Material Design palettes available in palette.scss
|
|
||||||
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
|
|
||||||
// hue. Available color palettes: https://material.io/design/color/
|
|
||||||
$mifosx-app-primary: mat.define-palette($mat-picton-blue);
|
|
||||||
$mifosx-app-accent: mat.define-palette($mat-yellow-green);
|
|
||||||
|
|
||||||
// The warn palette is optional (defaults to red).
|
|
||||||
$mifosx-app-warn: mat.define-palette(mat.$red-palette);
|
|
||||||
|
|
||||||
// Create the theme object (a Sass map containing all of the palettes).
|
|
||||||
$mifosx-app-theme: mat.define-light-theme($mifosx-app-primary, $mifosx-app-accent, $mifosx-app-warn);
|
|
||||||
|
|
||||||
// Include theme styles for core and each component used in your app.
|
|
||||||
// Alternatively, you can import and @include the theme mixins for each component
|
|
||||||
// that you are using.
|
|
||||||
@include mat.all-component-themes($mifosx-app-theme);
|
|
||||||
@include clients-view-component-theme($mifosx-app-theme);
|
|
||||||
@include groups-view-component-theme($mifosx-app-theme);
|
|
||||||
@include centers-view-component-theme($mifosx-app-theme);
|
|
||||||
@include dashboard-component-theme($mifosx-app-theme);
|
|
||||||
@include loans-view-component-theme($mifosx-app-theme);
|
|
||||||
@include savings-account-view-component-theme($mifosx-app-theme);
|
|
||||||
@include shares-account-view-component-theme($mifosx-app-theme);
|
|
||||||
@include fixed-deposits-account-view-component-theme($mifosx-app-theme);
|
|
||||||
@include recurring-deposits-account-view-component-theme($mifosx-app-theme);
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
@import "~@angular/material/prebuilt-themes/deeppurple-amber.css";
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
@import "~@angular/material/prebuilt-themes/indigo-pink.css";
|
|
||||||
@@ -1,37 +1,18 @@
|
|||||||
@use '@angular/material' as mat;
|
@use '@angular/material' as mat;
|
||||||
// Plus imports for other components in your app.
|
|
||||||
@import '../../app/clients/clients-view/clients-view.component-theme.scss';
|
|
||||||
@import '../../app/groups/groups-view/groups-view.component-theme.scss';
|
|
||||||
@import '../../app/centers/centers-view/centers-view.component-theme.scss';
|
|
||||||
@import '../../app/home/dashboard/dashboard.component-theme.scss';
|
|
||||||
@import '../../app/loans/loans-view/loans-view.component-theme.scss';
|
|
||||||
@import '../../app/savings/savings-account-view/savings-account-view.component-theme.scss';
|
|
||||||
@import '../../app/shares/shares-account-view/shares-account-view.component-theme.scss';
|
|
||||||
@import '../../app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component-theme.scss';
|
|
||||||
@import '../../app/deposits/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component-theme.scss';
|
|
||||||
|
|
||||||
// Custom material palette
|
// Custom material palette
|
||||||
$mat-denim: (
|
@import 'material-palette';
|
||||||
100: #5ba2ec,
|
|
||||||
500: #1074b9,
|
|
||||||
700: #004989,
|
|
||||||
contrast: (
|
|
||||||
100: rgba(black, 0.87),
|
|
||||||
500: white,
|
|
||||||
700: white
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$mat-yellow-green: (
|
// Plus imports for other components in your app.
|
||||||
100: #e7ffa5,
|
@import '../app/clients/clients-view/clients-view.component-theme.scss';
|
||||||
500: #b4d575,
|
@import '../app/groups/groups-view/groups-view.component-theme.scss';
|
||||||
700: #83a447,
|
@import '../app/centers/centers-view/centers-view.component-theme.scss';
|
||||||
contrast: (
|
@import '../app/home/dashboard/dashboard.component-theme.scss';
|
||||||
100: rgba(black, 0.87),
|
@import '../app/loans/loans-view/loans-view.component-theme.scss';
|
||||||
500: rgba(black, 0.87),
|
@import '../app/savings/savings-account-view/savings-account-view.component-theme.scss';
|
||||||
700: rgba(black, 0.87)
|
@import '../app/shares/shares-account-view/shares-account-view.component-theme.scss';
|
||||||
)
|
@import '../app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component-theme.scss';
|
||||||
);
|
@import '../app/deposits/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component-theme.scss';
|
||||||
|
|
||||||
// Include the common styles for Angular Material. We include this here so that you only
|
// Include the common styles for Angular Material. We include this here so that you only
|
||||||
// have to load a single css file for Angular Material in your app.
|
// have to load a single css file for Angular Material in your app.
|
||||||
@@ -41,8 +22,8 @@ $mat-yellow-green: (
|
|||||||
// Define the palettes for your theme using the Material Design palettes available in palette.scss
|
// Define the palettes for your theme using the Material Design palettes available in palette.scss
|
||||||
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
|
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
|
||||||
// hue. Available color palettes: https://material.io/design/color/
|
// hue. Available color palettes: https://material.io/design/color/
|
||||||
$mifosx-app-primary: mat.define-palette($mat-denim);
|
$mifosx-app-primary: mat.define-palette($primary-palette);
|
||||||
$mifosx-app-accent: mat.define-palette($mat-yellow-green);
|
$mifosx-app-accent: mat.define-palette($accent-palette);
|
||||||
|
|
||||||
// The warn palette is optional (defaults to red).
|
// The warn palette is optional (defaults to red).
|
||||||
$mifosx-app-warn: mat.define-palette(mat.$red-palette);
|
$mifosx-app-warn: mat.define-palette(mat.$red-palette);
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
@import "~@angular/material/prebuilt-themes/pink-bluegrey.css";
|
|
||||||
|
|
||||||
div.alert {
|
|
||||||
background-color: dimgray !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.mat-table tbody tr:nth-child(even) {
|
|
||||||
background-color: dimgray !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
@import "~@angular/material/prebuilt-themes/purple-green.css";
|
|
||||||
|
|
||||||
div.alert {
|
|
||||||
background-color: dimgray !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.mat-table tbody tr:nth-child(even) {
|
|
||||||
background-color: dimgray !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
/*
|
|
||||||
* Global application theme.
|
|
||||||
* Framework overrides and customization goes here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
mode: process.env.TAILWIND_MODE ? 'jit' : '',
|
||||||
|
content: [
|
||||||
|
"./src/app/**/*.{html,js}",
|
||||||
|
'./index.html',
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extends: {
|
||||||
|
animation: {
|
||||||
|
wiggle: 'wiggle 1s ease-in-out infinite',
|
||||||
|
'fade-in-down': 'fade-in-down 0.3s ease-out',
|
||||||
|
'fade-out-down': 'fade-out-down 0.3s ease-out',
|
||||||
|
'fade-in-up': 'fade-in-up 0.3s ease-out',
|
||||||
|
'fade-out-up': 'fade-out-up 0.3s ease-out',
|
||||||
|
},
|
||||||
|
boxShadow: {
|
||||||
|
custom: '0px 0px 50px 0px rgb(82 63 105 / 15%)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
require("@tailwindcss/forms")
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user