Loan Repayment Schedule with Export to PDF option

This commit is contained in:
Jose Alberto Hernandez
2024-07-21 17:32:40 -06:00
committed by Jose Alberto Hernandez
parent 44aa8cdc77
commit e810ce1e5e
24 changed files with 455 additions and 88 deletions
@@ -2,64 +2,70 @@
<table mat-table [dataSource]="originalScheduleDetails.periods" matSort>
<ng-container matColumnDef="number">
<th mat-header-cell *matHeaderCellDef> # </th>
<td mat-cell *matCellDef="let ele; let idx = index;">{{(idx + 1)}}</td>
<td mat-footer-cell *matFooterCellDef> &nbsp; </td>
</ng-container>
<ng-container matColumnDef="date">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{"labels.inputs.Date" | translate}} </th>
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Date" | translate}} </th>
<td mat-cell *matCellDef="let ele"> {{ ele.dueDate | dateFormat}} </td>
<td mat-footer-cell *matFooterCellDef> <b> {{"labels.inputs.Total" | translate}}</b> </td>
</ng-container>
<ng-container matColumnDef="principalDue">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{"labels.inputs.Principal Due" | translate}} </th>
<td mat-cell *matCellDef="let ele"> {{ ele.principalDue | formatNumber }} </td>
<td mat-footer-cell *matFooterCellDef> <b> {{ originalScheduleDetails.totalPrincipalExpected | formatNumber }} </b> </td>
</ng-container>
<ng-container matColumnDef="balanceOfLoan">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{"labels.inputs.Balance Of Loan" | translate}} </th>
<td mat-cell *matCellDef="let ele"> {{ ele.principalLoanBalanceOutstanding | formatNumber }} </td>
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Balance Of Loan" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele"> {{ ele.principalLoanBalanceOutstanding | formatNumber }} </td>
<td mat-footer-cell *matFooterCellDef> &nbsp; </td>
</ng-container>
<ng-container matColumnDef="principalDue">
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Principal Due" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele"> {{ ele.principalDue | formatNumber }} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ originalScheduleDetails.totalPrincipalExpected | currency:currency.code:'symbol-narrow':'1.2-2' }} </b> </td>
</ng-container>
<ng-container matColumnDef="interest">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{"labels.inputs.Interest" | translate}} </th>
<td mat-cell *matCellDef="let ele"> {{ ele.interestOriginalDue | formatNumber}} </td>
<td mat-footer-cell *matFooterCellDef> <b> {{ originalScheduleDetails.totalInterestCharged | formatNumber }} </b> </td>
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Interest" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele"> {{ ele.interestOriginalDue | formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ originalScheduleDetails.totalInterestCharged | currency:currency.code:'symbol-narrow':'1.2-2' }} </b> </td>
</ng-container>
<ng-container matColumnDef="fees">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{"labels.inputs.Fees" | translate}} </th>
<td mat-cell *matCellDef="let ele"> {{ ele.feeChargesDue | formatNumber}} </td>
<td mat-footer-cell *matFooterCellDef> <b> {{ originalScheduleDetails.totalFeeChargesCharged | formatNumber }} </b> </td>
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Fees" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele"> {{ ele.feeChargesDue | formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ originalScheduleDetails.totalFeeChargesCharged | currency:currency.code:'symbol-narrow':'1.2-2' }} </b> </td>
</ng-container>
<ng-container matColumnDef="penalties">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{"labels.inputs.Penalties" | translate}} </th>
<td mat-cell *matCellDef="let ele"> {{ ele.penaltyChargesDue | formatNumber}} </td>
<td mat-footer-cell *matFooterCellDef> <b> {{ originalScheduleDetails.totalPenaltyChargesCharged | formatNumber }} </b> </td>
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Penalties" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele"> {{ ele.penaltyChargesDue | formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ originalScheduleDetails.totalPenaltyChargesCharged | currency:currency.code:'symbol-narrow':'1.2-2' }} </b> </td>
</ng-container>
<ng-container matColumnDef="outstanding">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{"labels.inputs.Outstanding" | translate}} </th>
<td mat-cell *matCellDef="let ele"> {{ ele.totalOutstandingForPeriod | formatNumber}} </td>
<td mat-footer-cell *matFooterCellDef> <b> {{ originalScheduleDetails.totalRepaymentExpected | formatNumber }} </b> </td>
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Outstanding" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele"> {{ ele.totalOutstandingForPeriod | formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ originalScheduleDetails.totalRepaymentExpected | currency:currency.code:'symbol-narrow':'1.2-2' }} </b> </td>
</ng-container>
<!-- Header row first group -->
<ng-container matColumnDef="header">
<th mat-header-cell *matHeaderCellDef [attr.colspan]="1"> </th>
<th mat-header-cell class="center" *matHeaderCellDef [attr.colspan]="2"> </th>
</ng-container>
<!-- Header row second group -->
<ng-container matColumnDef="header-amount">
<th mat-header-cell *matHeaderCellDef [attr.colspan]="2"> {{"labels.inputs.Loan Amount and Balance" | translate}} </th>
<th mat-header-cell class="center" *matHeaderCellDef [attr.colspan]="2"> {{"labels.inputs.Loan Amount and Balance" | translate}} </th>
</ng-container>
<ng-container matColumnDef="header-total-cost">
<th mat-header-cell *matHeaderCellDef [attr.colspan]="3"> {{"labels.inputs.Total Cost of Loan" | translate}} </th>
<th mat-header-cell class="center" *matHeaderCellDef [attr.colspan]="3"> {{"labels.inputs.Total Cost of Loan" | translate}} </th>
</ng-container>
<ng-container matColumnDef="header-installment-totals">
<th mat-header-cell *matHeaderCellDef [attr.colspan]="1"> {{"labels.inputs.Installment Totals" | translate}} </th>
<th mat-header-cell class="center" *matHeaderCellDef [attr.colspan]="1"> {{"labels.inputs.Installment Totals" | translate}} </th>
</ng-container>
<tr mat-header-row *matHeaderRowDef="['header', 'header-amount', 'header-total-cost', 'header-installment-totals']"></tr>
@@ -1,17 +1,20 @@
import { Component, OnInit } from '@angular/core';
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Currency } from 'app/shared/models/general.model';
@Component({
selector: 'mifosx-original-schedule-tab',
templateUrl: './original-schedule-tab.component.html',
styleUrls: ['./original-schedule-tab.component.scss']
})
export class OriginalScheduleTabComponent implements OnInit {
export class OriginalScheduleTabComponent {
/** Loan Details Data */
originalScheduleDetails: any;
/** Columns to be displayed in original schedule table. */
displayedColumns: string[] = ['date', 'principalDue', 'balanceOfLoan', 'interest', 'fees', 'penalties', 'outstanding'];
displayedColumns: string[] = ['number', 'date', 'balanceOfLoan', 'principalDue', 'interest', 'fees', 'penalties', 'outstanding'];
currency: Currency | null = null;
/**
* Retrieves the loans with associations data from `resolve`.
@@ -19,11 +22,9 @@ export class OriginalScheduleTabComponent implements OnInit {
*/
constructor(private route: ActivatedRoute) {
this.route.parent.data.subscribe((data: { loanDetailsData: any }) => {
this.currency = data.loanDetailsData.currency;
this.originalScheduleDetails = data.loanDetailsData.originalSchedule;
});
}
ngOnInit() {
}
}
@@ -1,6 +1,11 @@
<div class="container">
<div fxLayout="row" class="m-t-20" fxLayoutAlign="end center">
<button mat-raised-button color="primary" (click)="exportToPDF()">
<fa-icon icon="download" class="m-r-10"></fa-icon>Export to PDF
</button>
</div>
<table mat-table [dataSource]="repaymentScheduleDetails.periods" *ngIf="!forEditing">
<table mat-table [dataSource]="repaymentScheduleDetails.periods" *ngIf="!forEditing" id="repaymentSchedule">
<ng-container matColumnDef="number">
<th mat-header-cell class="center" *matHeaderCellDef> # </th>
@@ -16,14 +21,16 @@
<ng-container matColumnDef="date">
<th mat-header-cell class="center" *matHeaderCellDef> {{"labels.inputs.Date" | translate}} </th>
<td mat-cell class="m-r-5" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.dueDate | dateFormat}} </td>
<td mat-footer-cell *matFooterCellDef> </td>
<td mat-cell class="m-r-5" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.dueDate | dateFormat}}
</td>
<td mat-footer-cell *matFooterCellDef> </td>
</ng-container>
<ng-container matColumnDef="paiddate">
<th mat-header-cell class="center" *matHeaderCellDef> {{"labels.inputs.Paid Date" | translate}} </th>
<td mat-cell class="center" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.obligationsMetOnDate | dateFormat}} </td>
<td mat-footer-cell *matFooterCellDef> </td>
<td mat-cell class="center" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.obligationsMetOnDate |
dateFormat}} </td>
<td mat-footer-cell *matFooterCellDef> </td>
</ng-container>
<ng-container matColumnDef="check">
@@ -36,63 +43,82 @@
<ng-container matColumnDef="balanceOfLoan">
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Balance Of Loan" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.principalLoanBalanceOutstanding | formatNumber }} </td>
<td mat-cell class="r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{
ele.principalLoanBalanceOutstanding | formatNumber }} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> &nbsp; </td>
</ng-container>
<ng-container matColumnDef="principalDue">
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Principal Due" | translate}} </th>
<td mat-cell class="check r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.principalDue | formatNumber }} </td>
<td mat-footer-cell class="check r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalPrincipalExpected | currency:currencyCode:'symbol-narrow':'1.2-2' }}</b> </td>
<td mat-cell class="check r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.principalDue |
formatNumber }} </td>
<td mat-footer-cell class="check r-amount" *matFooterCellDef> <b> {{
repaymentScheduleDetails.totalPrincipalExpected | currency:currencyCode:'symbol-narrow':'1.2-2' }}</b> </td>
</ng-container>
<ng-container matColumnDef="interest">
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Interest" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.interestOriginalDue | formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalInterestCharged | currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
<td mat-cell class="r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.interestOriginalDue
| formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalInterestCharged |
currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
</ng-container>
<ng-container matColumnDef="fees">
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Fees" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.feeChargesDue | formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalFeeChargesCharged | currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
<td mat-cell class="r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.feeChargesDue |
formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalFeeChargesCharged |
currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
</ng-container>
<ng-container matColumnDef="penalties">
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Penalties" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.penaltyChargesDue | formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalPenaltyChargesCharged | currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
<td mat-cell class="r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.penaltyChargesDue |
formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalPenaltyChargesCharged
| currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
</ng-container>
<ng-container matColumnDef="due">
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Due" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.totalDueForPeriod | formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalRepaymentExpected | currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
<td mat-cell class="r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.totalDueForPeriod |
formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalRepaymentExpected |
currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
</ng-container>
<ng-container matColumnDef="paid">
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Paid" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.totalPaidForPeriod | formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalRepayment | currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
<td mat-cell class="r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.totalPaidForPeriod |
formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalRepayment |
currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
</ng-container>
<ng-container matColumnDef="inadvance">
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.In advance" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.totalPaidInAdvanceForPeriod | formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalPaidInAdvance | currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
<td mat-cell class="r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{
ele.totalPaidInAdvanceForPeriod | formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalPaidInAdvance |
currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
</ng-container>
<ng-container matColumnDef="late">
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Late" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.totalPaidLateForPeriod | formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalPaidLate | currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
<td mat-cell class="r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{
ele.totalPaidLateForPeriod | formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalPaidLate |
currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
</ng-container>
<ng-container *ngIf="isWaived">
<ng-container matColumnDef="waived">
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Waived" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{ ele.totalWaivedForPeriod | formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalWaived | currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
<td mat-cell class="r-amount" *matCellDef="let ele" [ngClass]="installmentStyle(ele)"> {{
ele.totalWaivedForPeriod | formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalWaived |
currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
</ng-container>
</ng-container>
@@ -107,7 +133,8 @@
<ng-container matColumnDef="outstanding">
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Outstanding" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele"> {{ ele.totalOutstandingForPeriod | formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalOutstanding | currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalOutstanding |
currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
</ng-container>
<ng-container matColumnDef="header">
@@ -115,18 +142,22 @@
</ng-container>
<ng-container matColumnDef="header-amount">
<th mat-header-cell class="center" *matHeaderCellDef [attr.colspan]="2"> {{"labels.inputs.Loan Amount and Balance" | translate}} </th>
<th mat-header-cell class="center" *matHeaderCellDef [attr.colspan]="2"> {{"labels.inputs.Loan Amount and Balance"
| translate}} </th>
</ng-container>
<ng-container matColumnDef="header-total-cost">
<th mat-header-cell class="center" *matHeaderCellDef [attr.colspan]="3"> {{"labels.inputs.Total Cost of Loan" | translate}} </th>
<th mat-header-cell class="center" *matHeaderCellDef [attr.colspan]="3"> {{"labels.inputs.Total Cost of Loan" |
translate}} </th>
</ng-container>
<ng-container matColumnDef="header-installment-totals">
<th mat-header-cell class="center" *matHeaderCellDef [attr.colspan]="6"> {{"labels.inputs.Installment Totals" | translate}} </th>
<th mat-header-cell class="center" *matHeaderCellDef [attr.colspan]="6"> {{"labels.inputs.Installment Totals" |
translate}} </th>
</ng-container>
<tr mat-header-row *matHeaderRowDef="['header', 'header-amount', 'header-total-cost', 'header-installment-totals']"></tr>
<tr mat-header-row *matHeaderRowDef="['header', 'header-amount', 'header-total-cost', 'header-installment-totals']">
</tr>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<tr mat-footer-row *matFooterRowDef="displayedColumns"></tr>
@@ -134,7 +165,7 @@
</table>
<!-- Repayment Schedule to be Edited -->
<div *ngIf="forEditing" fxLayout="column" fxFlex="100%" >
<div *ngIf="forEditing" fxLayout="column" fxFlex="100%">
<table mat-table [dataSource]="repaymentScheduleDetails.periods">
@@ -147,31 +178,35 @@
<ng-container matColumnDef="date">
<th mat-header-cell class="center" *matHeaderCellDef> {{"labels.inputs.Date" | translate}} </th>
<td mat-cell class="m-r-10" *matCellDef="let ele"> {{ ele.dueDate | dateFormat}} </td>
<td mat-footer-cell *matFooterCellDef> </td>
<td mat-footer-cell *matFooterCellDef> </td>
</ng-container>
<ng-container matColumnDef="balanceOfLoan">
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Balance Of Loan" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele"> {{ ele.principalLoanBalanceOutstanding | formatNumber }} </td>
<td mat-cell class="r-amount" *matCellDef="let ele"> {{ ele.principalLoanBalanceOutstanding | formatNumber }}
</td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> &nbsp; </td>
</ng-container>
<ng-container matColumnDef="principalDue">
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Principal Due" | translate}} </th>
<td mat-cell class="check r-amount" *matCellDef="let ele"> {{ ele.principalDue | formatNumber }} </td>
<td mat-footer-cell class="check r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalPrincipalExpected | currency:currencyCode:'symbol-narrow':'1.2-2' }}</b> </td>
<td mat-footer-cell class="check r-amount" *matFooterCellDef> <b> {{
repaymentScheduleDetails.totalPrincipalExpected | currency:currencyCode:'symbol-narrow':'1.2-2' }}</b> </td>
</ng-container>
<ng-container matColumnDef="interest">
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Interest" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele"> {{ ele.interestOriginalDue | formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalInterestCharged | currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalInterestCharged |
currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
</ng-container>
<ng-container matColumnDef="fees">
<th mat-header-cell class="r-amount" *matHeaderCellDef> {{"labels.inputs.Fees" | translate}} </th>
<td mat-cell class="r-amount" *matCellDef="let ele"> {{ ele.feeChargesDue | formatNumber}} </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalFeeChargesCharged | currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalFeeChargesCharged |
currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
</ng-container>
<ng-container matColumnDef="due">
@@ -184,17 +219,19 @@
<b>{{ ele.totalDueForPeriod | formatNumber}}</b>
</span>
</td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalRepaymentExpected | currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
<td mat-footer-cell class="r-amount" *matFooterCellDef> <b> {{ repaymentScheduleDetails.totalRepaymentExpected |
currency:currencyCode:'symbol-narrow':'1.2-2' }} </b> </td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Actions" | translate}} </th>
<td mat-cell class="center" *matCellDef="let ele">
<button *ngIf="ele.period" type="button" color="primary" mat-icon-button matTooltip="{{ 'tooltips.Edit' | translate}}" matTooltipPosition="above" (click)="editPeriod(ele)">
<button *ngIf="ele.period" type="button" color="primary" mat-icon-button
matTooltip="{{ 'tooltips.Edit' | translate}}" matTooltipPosition="above" (click)="editPeriod(ele)">
<fa-icon icon="edit" size="lg"></fa-icon>
</button>
</td>
<td mat-footer-cell *matFooterCellDef> </td>
<td mat-footer-cell *matFooterCellDef> </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumnsEdit"></tr>
@@ -205,4 +242,4 @@
</div>
</div>
</div>
@@ -2,7 +2,7 @@
table {
width: 100%;
margin: 3% 0%;
margin: 2% 0%;
}
.container {
@@ -23,4 +23,16 @@ table {
.downpayment {
color: $status-downpayment;
}
}
.paid {
color: $state-done;
}
.current {
color: $status-active;
}
.overdued {
color: $status-matured;
}
@@ -1,5 +1,11 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Dates } from 'app/core/utils/dates';
import { RepaymentSchedulePeriod } from 'app/loans/models/loan-account.model';
import { SettingsService } from 'app/settings/settings.service';
import {jsPDF, jsPDFOptions} from 'jspdf';
import autoTable from 'jspdf-autotable';
@Component({
selector: 'mifosx-repayment-schedule-tab',
@@ -26,17 +32,23 @@ export class RepaymentScheduleTabComponent implements OnInit {
/** Form functions event */
@Output() editPeriod = new EventEmitter();
businessDate: Date = new Date();
/**
* Retrieves the loans with associations data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
*/
constructor(private route: ActivatedRoute) {
constructor(private route: ActivatedRoute,
private settingsService: SettingsService,
private dates: Dates
) {
this.route.parent.data.subscribe((data: { loanDetailsData: any }) => {
if (data.loanDetailsData) {
this.currencyCode = data.loanDetailsData.currency.code;
}
this.loanDetailsDataRepaymentSchedule = data.loanDetailsData ? data.loanDetailsData.repaymentSchedule : [];
});
this.businessDate = this.settingsService.businessDate;
}
ngOnInit() {
@@ -46,7 +58,14 @@ export class RepaymentScheduleTabComponent implements OnInit {
this.isWaived = this.repaymentScheduleDetails.totalWaived > 0;
}
installmentStyle(installment: any): string {
installmentStyle(installment: RepaymentSchedulePeriod): string {
if (installment.complete) {
return 'paid';
}
const isCurrent: string = this.isCurrent(installment);
if (isCurrent !== '') {
return isCurrent;
}
if (installment.isAdditional) {
return 'additional';
} else if (installment.downPaymentPeriod) {
@@ -55,4 +74,45 @@ export class RepaymentScheduleTabComponent implements OnInit {
return '';
}
isCurrent(installment: RepaymentSchedulePeriod): string {
if (!installment.fromDate) {
return '';
} else {
const fromDate = this.dates.parseDate(installment.fromDate);
const dueDate = this.dates.parseDate(installment.dueDate);
if (fromDate <= this.businessDate && this.businessDate < dueDate) {
return 'current';
}
if (this.businessDate > dueDate) {
return 'overdued';
}
}
return '';
}
exportToPDF() {
const businessDate = this.dates.formatDate(this.settingsService.businessDate, Dates.DEFAULT_DATEFORMAT);
const fileName = `repaymentschedule-${businessDate}.pdf`;
const options: jsPDFOptions = {
orientation: 'l',
unit: 'in',
format: 'letter',
precision: 2,
compress: true,
putOnlyUsedFonts: true
};
const pdf = new jsPDF(options);
autoTable(pdf, {
html: '#repaymentSchedule',
bodyStyles: {lineColor: [0, 0, 0]},
styles: {
fontSize: 8,
cellWidth: 'auto',
halign: 'center'
}});
pdf.save(fileName);
}
}
@@ -1,3 +1,4 @@
import { Currency } from 'app/shared/models/general.model';
export interface DelinquencyRange {
id: number;
@@ -49,3 +50,69 @@ export interface DelinquencyPausePeriod {
pausePeriodStart: number[];
pausePeriodEnd: number[];
}
export interface RepaymentSchedule {
currency: Currency;
loanTermInDays: number;
totalPrincipalDisbursed: number;
totalPrincipalExpected: number;
totalPrincipalPaid: number;
totalInterestCharged: number;
totalFeeChargesCharged: number;
totalPenaltyChargesCharged: number;
totalWaived: number;
totalWrittenOff: number;
totalRepaymentExpected: number;
totalRepayment: number;
totalPaidInAdvance: number;
totalPaidLate: number;
totalOutstanding: number;
totalCredits: number;
periods: RepaymentSchedulePeriod[];
}
export interface RepaymentSchedulePeriod {
dueDate: number[];
principalDisbursed?: number;
principalLoanBalanceOutstanding: number;
feeChargesDue: number;
feeChargesPaid: number;
feeChargesOutstanding: number;
totalOriginalDueForPeriod: number;
totalDueForPeriod: number;
totalPaidForPeriod: number;
totalOutstandingForPeriod: number;
totalOverdue?: number;
totalActualCostOfLoanForPeriod: number;
totalCredits: number;
period?: number;
fromDate?: number[];
complete?: boolean;
isAdditional?: boolean;
downPaymentPeriod?: boolean;
daysInPeriod?: number;
principalOriginalDue?: number;
principalDue?: number;
principalPaid?: number;
principalWrittenOff?: number;
principalOutstanding?: number;
interestOriginalDue?: number;
interestDue?: number;
interestPaid?: number;
interestWaived?: number;
interestWrittenOff?: number;
interestOutstanding?: number;
feeChargesWaived?: number;
feeChargesWrittenOff?: number;
penaltyChargesDue?: number;
penaltyChargesPaid?: number;
penaltyChargesWaived?: number;
penaltyChargesWrittenOff?: number;
penaltyChargesOutstanding?: number;
totalPaidInAdvanceForPeriod?: number;
totalPaidLateForPeriod?: number;
totalWaivedForPeriod?: number;
totalWrittenOffForPeriod?: number;
totalInstallmentAmountForPeriod?: number;
}
@@ -48,6 +48,12 @@ export class FixedDepositProductSettingsStepComponent implements OnInit {
'withHoldTax': this.fixedDepositProductsTemplate.withHoldTax
});
}
if (this.fixedDepositProductsTemplate.withHoldTax) {
this.fixedDepositProductSettingsForm.patchValue({
'taxGroupId': this.fixedDepositProductsTemplate.taxGroup ? this.fixedDepositProductsTemplate.taxGroup.id : ''
});
}
}
createFixedDepositProductSettingsForm() {
@@ -47,6 +47,12 @@ export class RecurringDepositProductSettingsStepComponent implements OnInit {
'withHoldTax': this.recurringDepositProductsTemplate.withHoldTax
});
}
if (this.recurringDepositProductsTemplate.withHoldTax) {
this.recurringDepositProductSettingsForm.patchValue({
'taxGroupId': this.recurringDepositProductsTemplate.taxGroup ? this.recurringDepositProductsTemplate.taxGroup.id : ''
});
}
}
createrecurringDepositProductSettingsForm() {
+1 -1
View File
@@ -63,7 +63,7 @@ $highlight: $belize-hole;
$accent: $peter-river;
//Status Colors Defined Here
$status-active: #00ce00;
$status-active: #5cb85c;
$status-inactive: #666f73;
$status-deleted: #000000;
$status-pending: #ffa500;
+1
View File
@@ -576,6 +576,7 @@
"Specified due date": "Specified due date",
"Installment Fee": "Installment Fee",
"Overdue Fees": "Overdue Fees",
"Overdraft Fee": "Poplatek za přečerpání",
"Tranche Disbursement": "Tranche Disbursement",
"Savings Activation": "Savings Activation",
"Saving No Activity Fee": "Ušetříte žádný poplatek za aktivitu",
+1
View File
@@ -576,6 +576,7 @@
"Specified due date": "Angegebenes Fälligkeitsdatum",
"Installment Fee": "Ratenzahlungsgebühr",
"Overdue Fees": "Überfällige Gebühren",
"Overdraft Fee": "Überziehungsgebühr",
"Tranche Disbursement": "Tranchenauszahlung",
"Savings Activation": "Sparaktivierung",
"Saving No Activity Fee": "Sparen Sie keine Aktivitätsgebühr",
+1
View File
@@ -576,6 +576,7 @@
"Specified due date": "Specified due date",
"Installment Fee": "Installment Fee",
"Overdue Fees": "Overdue Fees",
"Overdraft Fee": "Overdraft Fee",
"Tranche Disbursement": "Tranche Disbursement",
"Savings Activation": "Savings Activation",
"Saving No Activity Fee": "Saving No Activity Fee",
+1
View File
@@ -576,6 +576,7 @@
"Specified due date": "Fecha de Vencimiento",
"Installment Fee": "Cuota de pago",
"Overdue Fees": "Cuotas vencidas",
"Overdraft Fee": "Cargo por sobregiro",
"Tranche Disbursement": "Multiple Desembolso",
"Savings Activation": "Activación de Cuenta",
"Saving No Activity Fee": "Ahorro sin Actividad",
+1
View File
@@ -576,6 +576,7 @@
"Specified due date": "Date d'échéance spécifiée",
"Installment Fee": "Frais de versement",
"Overdue Fees": "Frais de retard",
"Overdraft Fee": "Frais de découvert",
"Tranche Disbursement": "Décaissement des tranches",
"Savings Activation": "Activation de l'épargne",
"Saving No Activity Fee": "Économiser sans frais d'activité",
+1
View File
@@ -576,6 +576,7 @@
"Specified due date": "Data di scadenza specificata",
"Installment Fee": "Commissione di rata",
"Overdue Fees": "Commissioni scadute",
"Overdraft Fee": "Commissione di scoperto",
"Tranche Disbursement": "Erogazione della tranche",
"Savings Activation": "Attivazione del risparmio",
"Saving No Activity Fee": "Risparmio senza costi di attività",
+1
View File
@@ -576,6 +576,7 @@
"Specified due date": "지정된 마감일",
"Installment Fee": "할부 수수료",
"Overdue Fees": "연체 수수료",
"Overdraft Fee": "초과인월 수수료",
"Tranche Disbursement": "트랜치 지급",
"Savings Activation": "저축 활성화",
"Saving No Activity Fee": "활동비 절약",
+1
View File
@@ -576,6 +576,7 @@
"Specified due date": "Nurodytas terminas",
"Installment Fee": "Įmokos mokestis",
"Overdue Fees": "Pradelsti mokesčiai",
"Overdraft Fee": "Overdrafto mokestis",
"Tranche Disbursement": "Dalies išmokėjimas",
"Savings Activation": "Taupymo aktyvinimas",
"Saving No Activity Fee": "Sutaupykite jokios veiklos mokesčio",
+1
View File
@@ -576,6 +576,7 @@
"Specified due date": "Norādīts izpildes datums",
"Installment Fee": "Nomaksas maksa",
"Overdue Fees": "Nokavējuma maksas",
"Overdraft Fee": "Overdrafta maksa",
"Tranche Disbursement": "Daļas izmaksa",
"Savings Activation": "Uzkrājumu aktivizēšana",
"Saving No Activity Fee": "Ietaupot bezdarbības maksu",
+1
View File
@@ -576,6 +576,7 @@
"Specified due date": "तोकिएको म्याद मिति",
"Installment Fee": "किस्ता शुल्क",
"Overdue Fees": "अतिदेय शुल्क",
"Overdraft Fee": "ओभरड्राफ्ट शुल्क",
"Tranche Disbursement": "किस्ता वितरण",
"Savings Activation": "बचत सक्रियता",
"Saving No Activity Fee": "कुनै गतिविधि शुल्क बचत गर्दै",
+1
View File
@@ -576,6 +576,7 @@
"Specified due date": "Data de vencimento especificada",
"Installment Fee": "Taxa de parcelamento",
"Overdue Fees": "Taxas vencidas",
"Overdraft Fee": "Taxa de cheque especial",
"Tranche Disbursement": "Desembolso da Tranche",
"Savings Activation": "Ativação de poupança",
"Saving No Activity Fee": "Economizando sem taxa de atividade",
+1
View File
@@ -576,6 +576,7 @@
"Specified due date": "Tarehe ya mwisho iliyoainishwa",
"Installment Fee": "Ada ya Ufungaji",
"Overdue Fees": "Ada Zilizochelewa",
"Overdraft Fee": "Ada ya Overdraft",
"Tranche Disbursement": "Utoaji wa Tranche",
"Savings Activation": "Uanzishaji wa Akiba",
"Saving No Activity Fee": "Haihifadhi Ada ya Shughuli",
+2 -2
View File
@@ -2,8 +2,8 @@
/* tslint:disable */
export default {
'mifos_x': {
'version': '240706',
'hash': '71b9b7d7'
'version': '240721',
'hash': 'd39a6d8a'
},
'allow_switching_backend_instance': true
};