WEB-263: Add Buy Down Fees tabs

This commit is contained in:
Oleksii Novikov
2025-07-28 17:32:25 +03:00
parent e55aaf90be
commit c1128f424d
21 changed files with 397 additions and 27 deletions
@@ -0,0 +1,60 @@
<div class="container">
<h3>{{ 'labels.heading.Buy Down Fees' | translate }}</h3>
<div *ngIf="isLoading" class="loading-indicator">
<mat-spinner diameter="30"></mat-spinner>
</div>
<div *ngIf="!isLoading">
<div *ngIf="buyDownFeeData.length === 0" class="no-data">
{{ 'labels.messages.No Data Found' | translate }}
</div>
<table mat-table [dataSource]="buyDownFeeData" *ngIf="buyDownFeeData.length > 0">
<ng-container matColumnDef="date">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.heading.Date' | translate }}</th>
<td mat-cell *matCellDef="let item">
{{ item.date | date: 'mediumDate' }}
</td>
</ng-container>
<ng-container matColumnDef="buyDownFeeAmount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.heading.Fee Amount' | translate }}</th>
<td mat-cell *matCellDef="let item">
{{ item.buyDownFeeAmount | formatNumber: '0.00' }}
</td>
</ng-container>
<ng-container matColumnDef="amortizedAmount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.heading.Amortized Amount' | translate }}</th>
<td mat-cell *matCellDef="let item">
{{ item.amortizedAmount | formatNumber: '0.00' }}
</td>
</ng-container>
<ng-container matColumnDef="notYetAmortizedAmount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.heading.Not Yet Amortized Amount' | translate }}</th>
<td mat-cell *matCellDef="let item">
{{ item.notYetAmortizedAmount | formatNumber: '0.00' }}
</td>
</ng-container>
<ng-container matColumnDef="adjustedAmount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.heading.Adjusted Amount' | translate }}</th>
<td mat-cell *matCellDef="let item">
{{ item.adjustedAmount | formatNumber: '0.00' }}
</td>
</ng-container>
<ng-container matColumnDef="chargedOffAmount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.heading.Charged Off Amount' | translate }}</th>
<td mat-cell *matCellDef="let item">
{{ item.chargedOffAmount | formatNumber: '0.00' }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="buyDownFeeColumns"></tr>
<tr mat-row *matRowDef="let row; columns: buyDownFeeColumns"></tr>
</table>
</div>
</div>
@@ -0,0 +1,106 @@
import { Component, OnInit } from '@angular/core';
import {
MatCell,
MatCellDef,
MatColumnDef,
MatHeaderCell,
MatHeaderCellDef,
MatHeaderRow,
MatHeaderRowDef,
MatRow,
MatRowDef,
MatTable
} from '@angular/material/table';
import { ActivatedRoute } from '@angular/router';
import { FormatNumberPipe } from '@pipes/format-number.pipe';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
import { LoansService } from '../../loans.service';
import { BuyDownFeeAmortizationDetails } from '../../models/loan-account.model';
import { DatePipe } from '@angular/common';
@Component({
selector: 'mifosx-loan-buy-down-fees-tab',
templateUrl: './loan-buy-down-fees-tab.component.html',
styleUrl: './loan-buy-down-fees-tab.component.scss',
imports: [
...STANDALONE_SHARED_IMPORTS,
MatTable,
MatColumnDef,
MatHeaderCellDef,
MatHeaderCell,
MatCellDef,
MatCell,
MatHeaderRowDef,
MatHeaderRow,
MatRowDef,
MatRow,
FormatNumberPipe,
DatePipe
]
})
export class LoanBuyDownFeesTabComponent implements OnInit {
buyDownFeeData: BuyDownFeeAmortizationDetails[] = [];
loanId: string;
isLoading = true;
buyDownFeeColumns: string[] = [
'date',
'buyDownFeeAmount',
'amortizedAmount',
'notYetAmortizedAmount',
'adjustedAmount',
'chargedOffAmount'
];
constructor(
private route: ActivatedRoute,
private loansService: LoansService
) {}
ngOnInit(): void {
this.getLoanId();
this.loadBuyDownFees();
}
private getLoanId(): void {
if (this.route.snapshot.data && this.route.snapshot.data['loanId']) {
this.loanId = this.route.snapshot.data['loanId'];
return;
}
let currentRoute = this.route;
while (currentRoute) {
if (currentRoute.snapshot.paramMap.has('loanId')) {
this.loanId = currentRoute.snapshot.paramMap.get('loanId');
return;
}
if (currentRoute.parent) {
currentRoute = currentRoute.parent;
} else {
break;
}
}
console.error('Could not find loanId in route parameters');
}
private loadBuyDownFees(): void {
if (!this.loanId) {
console.error('Cannot load buy down fees: loanId is undefined');
this.isLoading = false;
return;
}
this.isLoading = true;
this.loansService.getBuyDownFeeData(this.loanId).subscribe({
next: (data: BuyDownFeeAmortizationDetails[]) => {
this.buyDownFeeData = data || [];
this.isLoading = false;
},
error: (error) => {
console.error('Error loading buy down fees:', error);
this.isLoading = false;
}
});
}
}
@@ -219,6 +219,17 @@
{{ 'labels.inputs.Deferred income' | translate }}
</a>
</ng-container>
<ng-container *ngIf="loanDetailsData.enableBuyDownFee">
<a
mat-tab-link
[routerLink]="['./buy-down-fees']"
routerLinkActive
#buyDownFees="routerLinkActive"
[active]="buyDownFees.isActive"
>
{{ 'labels.heading.Buy Down Fees' | translate }}
</a>
</ng-container>
<ng-container *ngIf="loanDetailsData.status.active">
<a
mat-tab-link