feat: add loans view page (#661)

- Add loan account page
- Add general tab
- Add account details tab

Fixes: #219
This commit is contained in:
Muskan Khedia
2020-05-31 22:49:21 +05:30
committed by GitHub
parent 1539180a3a
commit 11cbe7a155
24 changed files with 1178 additions and 11 deletions
@@ -0,0 +1,200 @@
<div class="tab-container mat-typography">
<ng-container *ngIf="loanDetails.summary">
<h3>Performance History</h3>
<div fxLayout="row" fxLayoutGap="32px" class="performance-history-container">
<p>
# of Repayments :{{loanDetails?.numberOfRepayments}}
<p>
Maturity Date :{{loanDetails?.timeline.expectedMaturityDate | date}}
</p>
</div>
</ng-container>
<div *ngIf="loanDetails.summary">
<h3> Loan Summary </h3>
<table mat-table [dataSource]="dataSource">
<ng-container matColumnDef="Empty">
<th mat-header-cell *matHeaderCellDef> </th>
<td mat-cell *matCellDef="let ele"> {{ ele.property }} </td>
</ng-container>
<ng-container matColumnDef="Original">
<th mat-header-cell *matHeaderCellDef> Original </th>
<td mat-cell *matCellDef="let ele"> {{ ele.original | number }} </td>
</ng-container>
<ng-container matColumnDef="Paid">
<th mat-header-cell *matHeaderCellDef> Paid </th>
<td mat-cell *matCellDef="let ele"> {{ ele.paid | number }} </td>
</ng-container>
<ng-container matColumnDef="Waived">
<th mat-header-cell *matHeaderCellDef> Waived </th>
<td mat-cell *matCellDef="let ele"> {{ ele.waived | number }} </td>
</ng-container>
<ng-container matColumnDef="Written Off">
<th mat-header-cell *matHeaderCellDef> Written Off </th>
<td mat-cell *matCellDef="let ele"> {{ ele.writtenOff | number }} </td>
</ng-container>
<ng-container matColumnDef="Outstanding">
<th mat-header-cell *matHeaderCellDef> Outstanding </th>
<td mat-cell *matCellDef="let ele"> {{ ele.outstanding | number }} </td>
</ng-container>
<ng-container matColumnDef="Over Due">
<th mat-header-cell *matHeaderCellDef> Over Due </th>
<td mat-cell *matCellDef="let ele"> {{ ele.overdue | number }} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="loanSummaryColumns"></tr>
<tr mat-row *matRowDef="let row; columns: loanSummaryColumns;"></tr>
</table>
</div>
<div *ngIf="loanDetails.summary">
<h3> Loan Details</h3>
<table mat-table [dataSource]="detailsDataSource">
<ng-container matColumnDef="Key">
<th mat-header-cell *matHeaderCellDef> Key </th>
<td mat-cell *matCellDef="let ele"> {{ ele.key }} </td>
</ng-container>
<ng-container matColumnDef="Value">
<th mat-header-cell *matHeaderCellDef> Value </th>
<td mat-cell *matCellDef="let ele">
<ng-container *ngIf="ele.key === 'Disbursement Date'" >
<span *ngIf="loanDetails.timeline.actualDisbursementDate"> {{loanDetails.timeline.actualDisbursementDate | date}} </span>
<span *ngIf="!loanDetails.timeline.actualDisbursementDate"> Not Available </span>
</ng-container>
<ng-container *ngIf="ele.key === 'Loan Purpose'">
<span *ngIf="loanDetails.loanPurchaseName"> {{loanDetails.loanPurchaseName}} </span>
<span *ngIf="!loanDetails.loanPurchaseName"> Not Available </span>
</ng-container>
<ng-container *ngIf="ele.key === 'Loan Officer'">
<span *ngIf="!loanDetails.loanOfficerName"> Unassigned </span>
<span *ngIf="loanDetails.loanOfficerName"> {{loanDetails.loanOfficerName}} &nbsp;
<span *ngIf="loanDetails.loanOfficerName">
<!-- <a ng-click="clickEvent('unassignloanofficer', loanDetails.id)" *mifosxHasPermission = "'REMOVELOANOFFICER_LOAN'"><i
class="fa fa-times"></i></a> -->
</span>
</span>
</ng-container>
<ng-container *ngIf="ele.key === 'Currency'">
<span> {{loanDetails.currency.name }} {{loanDetails.currency.code}} </span>
</ng-container>
<ng-container *ngIf="ele.key === 'External Id'">
<span *ngIf="loanDetails.externalId"> {{loanDetails.externalId}} </span>
<span *ngIf="!loanDetails.externalId"> Not Available </span>
</ng-container>
<ng-container *ngIf="ele.key === 'Proposed Amount' || ele.key === 'Approved Amount' || ele.key === 'Disburse Amount'">
{{ ele.value }}
</ng-container>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="loanDetailsColumns"></tr>
<tr mat-row *matRowDef="let row; columns: loanDetailsColumns;"></tr>
</table>
</div>
<div *ngIf="!loanDetails.summary">
<h3> Loan Details </h3>
<table mat-table [dataSource]="detailsDataSource">
<ng-container matColumnDef="Key">
<th mat-header-cell *matHeaderCellDef> Key </th>
<td mat-cell *matCellDef="let ele"> {{ ele.key }} </td>
</ng-container>
<ng-container matColumnDef="Value">
<th mat-header-cell *matHeaderCellDef> Value </th>
<td mat-cell *matCellDef="let ele">
<ng-container *ngIf="ele.key === 'Disbursement Date'" >
<span *ngIf="loanDetails.timeline.actualDisbursementDate"> {{loanDetails.timeline.actualDisbursementDate | date}} </span>
<span *ngIf="!loanDetails.timeline.actualDisbursementDate"> Not Available </span>
</ng-container>
<ng-container *ngIf="ele.key === 'Loan Officer'">
<span *ngIf="!loanDetails.loanOfficerName"> Unassigned </span>
<span *ngIf="loanDetails.loanOfficerName"> {{loanDetails.loanOfficerName}} &nbsp;
<span *ngIf="loanDetails.loanOfficerName">
<!-- <a ng-click="clickEvent('unassignloanofficer', loanDetails.id)" *mifosxHasPermission = "'REMOVELOANOFFICER_LOAN'"><i
class="fa fa-times"></i></a> -->
</span>
</span>
</ng-container>
<ng-container *ngIf="ele.key === 'Currency'">
<span> {{loanDetails.currency.name }} </span>
</ng-container>
<ng-container *ngIf="ele.key === 'External Id'">
<span *ngIf="loanDetails.externalId"> {{loanDetails.externalId}} </span>
<span *ngIf="!loanDetails.externalId"> Not Available </span>
</ng-container>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="loanDetailsColumns"></tr>
<tr mat-row *matRowDef="let row; columns: loanDetailsColumns;"></tr>
</table>
</div>
<div *ngIf="!loanDetails.summary">
<h3> Loan Purpose </h3>
<div class="container">
<div fxLayout="row wrap" fxLayout.lt-md="column">
<div fxFlexFill>
<span fxFlex="50%">Loan Purpose:</span>
<span fxFlex="50%" *ngIf="loanDetails.loanPurposeName">
{{ loanDetails.loanPurposeName }}
</span>
<span fxFlex="50%" *ngIf="!loanDetails.loanPurposeName">
Not Provided
</span>
</div>
<div fxFlexFill>
<span fxFlex="50%">Proposed Amount:</span>
<span fxFlex="50%">{{ loanDetails.proposedPrincipal | number}}</span>
</div>
<div fxFlexFill *ngIf="showApprovedAmountBasedOnStatus()">
<span fxFlex="50%">Approved Amount:</span>
<span fxFlex="50%">{{ loanDetails.approvedPrincipal | number }}</span>
</div>
<div fxFlexFill *ngIf="showDisbursedAmountBasedOnStatus()">
<span fxFlex="50%">Disburse Amount:</span>
<span fxFlex="50%">{{ loanDetails.principal | number }}</span>
</div>
<div fxFlexFill>
<span fxFlex="50%">Arrears By:</span>
<span fxFlex="50%"> Not Provided</span>
</div>
</div>
</div>
</div>
</div>
@@ -0,0 +1,22 @@
.tab-container {
padding: 1%;
margin: 1%;
h3{
margin:1% auto;
}
.performance-history-container {
border: 1px solid;
padding: 1%;
margin-bottom: 20px ;
}
table {
width: 100%;
margin-bottom: 20px;
}
}
span {
margin: 0.5em 0;
}
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { GeneralTabComponent } from './general-tab.component';
describe('GeneralTabComponent', () => {
let component: GeneralTabComponent;
let fixture: ComponentFixture<GeneralTabComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ GeneralTabComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(GeneralTabComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,169 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { MatTableDataSource } from '@angular/material';
@Component({
selector: 'mifosx-general-tab',
templateUrl: './general-tab.component.html',
styleUrls: ['./general-tab.component.scss']
})
export class GeneralTabComponent implements OnInit {
loanDetails: any;
status: any;
loanSummaryColumns: string[] = ['Empty', 'Original', 'Paid', 'Waived', 'Written Off', 'Outstanding', 'Over Due'];
loanDetailsColumns: string[] = ['Key', 'Value'];
loanSummaryTableData: {
'property': string,
'original': string,
'paid': string,
'waived': string,
'writtenOff': string,
'outstanding': string,
'overdue': string
}[];
loanDetailsTableData: {
'key': string,
'value'?: string
}[];
/** Data source for loans summary table. */
dataSource: MatTableDataSource<any>;
detailsDataSource: MatTableDataSource<any>;
constructor(private route: ActivatedRoute) {
this.route.data.subscribe((data: { loanDetailsData: any, }) => {
this.loanDetails = data.loanDetailsData;
});
}
ngOnInit() {
this.status = this.loanDetails.value;
if (this.loanDetails.summary) {
this.setloanSummaryTableData();
this.setloanDetailsTableData();
} else {
this.setloanNonDetailsTableData();
}
}
setloanSummaryTableData() {
this.loanSummaryTableData = [
{
'property': 'Principal',
'original': this.loanDetails.summary.principalDisbursed,
'paid': this.loanDetails.summary.principalPaid,
'waived': this.loanDetails.summary.principalWrittenOff,
'writtenOff': this.loanDetails.summary.principalOutstanding,
'outstanding': this.loanDetails.summary.principalOutstanding,
'overdue': this.loanDetails.summary.principalOverdue,
},
{
'property': 'Interest',
'original': this.loanDetails.summary.interestCharged,
'paid': this.loanDetails.summary.interestPaid,
'waived': this.loanDetails.summary.interestWaived,
'writtenOff': this.loanDetails.summary.interestWrittenOff,
'outstanding': this.loanDetails.summary.interestOutstanding,
'overdue': this.loanDetails.summary.interestOverdue,
},
{
'property': 'Fees',
'original': this.loanDetails.summary.feeChargesCharged,
'paid': this.loanDetails.summary.feeChargesPaid,
'waived': this.loanDetails.summary.feeChargesWaived,
'writtenOff': this.loanDetails.summary.feeChargesWrittenOff,
'outstanding': this.loanDetails.summary.feeChargesOutstanding,
'overdue': this.loanDetails.summary.feeChargesOverdue,
},
{
'property': 'Penalties',
'original': this.loanDetails.summary.penaltyChargesCharged,
'paid': this.loanDetails.summary.penaltyChargesPaid,
'waived': this.loanDetails.summary.penaltyChargesWaived,
'writtenOff': this.loanDetails.summary.penaltyChargesWrittenOff,
'outstanding': this.loanDetails.summary.penaltyChargesOutstanding,
'overdue': this.loanDetails.summary.penaltyChargesOverdue,
},
{
'property': 'Total',
'original': this.loanDetails.summary.totalExpectedRepayment,
'paid': this.loanDetails.summary.totalRepayment,
'waived': this.loanDetails.summary.totalWaived,
'writtenOff': this.loanDetails.summary.totalWrittenOff,
'outstanding': this.loanDetails.summary.totalOutstanding,
'overdue': this.loanDetails.summary.totalOverdue,
}
];
this.dataSource = new MatTableDataSource(this.loanSummaryTableData);
}
setloanDetailsTableData() {
this.loanDetailsTableData = [
{
'key': 'Disbursement Date'
},
{
'key': 'Loan Purpose'
},
{
'key': 'Loan Officer'
},
{
'key': 'Currency'
},
{
'key': 'External Id'
},
{
'key': 'Proposed Amount',
'value': this.loanDetails.proposedPrincipal,
},
{
'key': 'Approved Amount',
'value': this.loanDetails.approvedPrincipal,
},
{
'key': 'Disburse Amount',
'value': this.loanDetails.principal,
},
];
this.detailsDataSource = new MatTableDataSource(this.loanDetailsTableData);
}
setloanNonDetailsTableData() {
this.loanDetailsTableData = [
{
'key': 'Disbursement Date'
},
{
'key': 'Currency'
},
{
'key': 'Loan Officer'
},
{
'key': 'External Id'
}
];
this.detailsDataSource = new MatTableDataSource(this.loanDetailsTableData);
}
showApprovedAmountBasedOnStatus() {
if (this.status === 'Submitted and pending approval' || this.status === 'Withdrawn by applicant' || this.status === 'Rejected') {
return false;
}
return true;
}
showDisbursedAmountBasedOnStatus = function() {
if (this.status === 'Submitted and pending approval' || this.status === 'Withdrawn by applicant' || this.status === 'Rejected' ||
this.status === 'Approved') {
return false;
}
return true;
};
}