This commit is contained in:
Jose Alberto Hernandez 2026-02-05 20:06:37 -05:00 committed by GitHub
commit 48a08bd419
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 99 additions and 28 deletions

View File

@ -142,7 +142,7 @@
</table>
</div>
<div class="layout-row responsive-column align-center gap-2px margin-t">
<div class="layout-row responsive-column align-center gap-2px margin-t stepper-buttons">
<button mat-raised-button matStepperPrevious>
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Previous' | translate }}

View File

@ -27,7 +27,6 @@ import {
/** Dialog Components */
import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component';
import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component';
// import { LoansAccountAddCollateralDialogComponent } from 'app/loans/custom-dialog/loans-account-add-collateral-dialog/loans-account-add-collateral-dialog.component';
/** Custom Services */
import { DatepickerBase } from 'app/shared/form-dialog/formfield/model/datepicker-base';
@ -35,14 +34,16 @@ import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield-
import { InputBase } from 'app/shared/form-dialog/formfield/model/input-base';
import { SettingsService } from 'app/settings/settings.service';
import { Dates } from 'app/core/utils/dates';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { MatButton, MatIconButton } from '@angular/material/button';
import { ActivatedRoute } from '@angular/router';
import { MatIconButton } from '@angular/material/button';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { MatDivider } from '@angular/material/divider';
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
import { DateFormatPipe } from '../../../pipes/date-format.pipe';
import { FormatNumberPipe } from '../../../pipes/format-number.pipe';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
import { TranslateService } from '@ngx-translate/core';
import { LoanCharge } from 'app/loans/models/loan-charge.model';
/**
* Recurring Deposit Account Charges Step
@ -77,6 +78,7 @@ export class LoansAccountChargesStepComponent implements OnInit, OnChanges {
private dateUtils = inject(Dates);
private route = inject(ActivatedRoute);
private settingsService = inject(SettingsService);
private translateService = inject(TranslateService);
// @Input loansAccountProductTemplate: LoansAccountProductTemplate
@Input() loansAccountProductTemplate: any;
@ -148,11 +150,13 @@ export class LoansAccountChargesStepComponent implements OnInit, OnChanges {
ngOnInit() {
if (this.loansAccountTemplate && this.loansAccountTemplate.charges) {
this.chargesDataSource =
this.loansAccountTemplate.charges.map((charge: any) => {
this.loansAccountTemplate.charges.map((loanCharge: LoanCharge) => {
const amount = this.isPercentageCharge(loanCharge) ? loanCharge.percentage : loanCharge.amount;
return {
...charge,
id: charge.id,
chargeId: charge.chargeId
...loanCharge,
amount,
id: loanCharge.id,
chargeId: loanCharge.chargeId
};
}) || [];
}
@ -189,11 +193,13 @@ export class LoansAccountChargesStepComponent implements OnInit, OnChanges {
})) || [];
} else if (isModification && this.loansAccountTemplate && this.loansAccountTemplate.charges) {
this.chargesDataSource =
this.loansAccountTemplate.charges.map((charge: any) => {
this.loansAccountTemplate.charges.map((loanCharge: LoanCharge) => {
const amount = this.isPercentageCharge(loanCharge) ? loanCharge.percentage : loanCharge.amount;
return {
...charge,
id: charge.id,
chargeId: charge.chargeId
...loanCharge,
amount,
id: loanCharge.id,
chargeId: loanCharge.chargeId
};
}) || [];
}
@ -222,13 +228,16 @@ export class LoansAccountChargesStepComponent implements OnInit, OnChanges {
new InputBase({
controlName: 'amount',
label: 'Amount',
value: charge.amount,
value: this.isPercentageCharge(charge) ? charge.amountOrPercentage : charge.amount,
type: 'number',
required: false
})
];
const data = {
title: 'Edit Charge Amount',
title:
this.translateService.instant('labels.buttons.Edit') +
' ' +
this.translateService.instant('labels.inputs.Charge Amount'),
layout: { addButtonText: 'Confirm' },
formfields: formfields
};
@ -254,11 +263,15 @@ export class LoansAccountChargesStepComponent implements OnInit, OnChanges {
label: 'Date',
value: charge.dueDate || charge.feeOnMonthDay || '',
type: 'datetime-local',
maxDate: this.settingsService.maxFutureDate,
required: false
})
];
const data = {
title: 'Edit Charge Date',
title:
this.translateService.instant('labels.buttons.Edit') +
' ' +
this.translateService.instant('labels.inputs.Charge Date'),
layout: { addButtonText: 'Confirm' },
formfields: formfields
};
@ -380,4 +393,8 @@ export class LoansAccountChargesStepComponent implements OnInit, OnChanges {
this.selectAllItems =
len === 0 ? false : this.activeClientMembers.filter((item: any) => item.selected).length === len;
}
private isPercentageCharge(loanCharge: LoanCharge): boolean {
return loanCharge.chargeCalculationType.code.includes('.percent.');
}
}

View File

@ -54,7 +54,7 @@
}
</div>
<div class="layout-row align-center gap-2percent margin-t responsive-column">
<div class="layout-row align-center gap-2percent margin-t responsive-column stepper-buttons">
<button mat-raised-button matStepperPrevious disabled>
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Previous' | translate }}

View File

@ -138,7 +138,7 @@
</div>
}
<div class="layout-row align-center gap-2percent margin-t responsive-column">
<div class="layout-row align-center gap-2percent margin-t responsive-column stepper-buttons">
<button mat-raised-button matStepperPrevious disabled>
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Previous' | translate }}

View File

@ -390,7 +390,7 @@
}
</div>
<div class="layout-row responsive-column align-center gap-2px margin-t">
<div class="layout-row responsive-column align-center gap-2px margin-t stepper-buttons">
<button mat-raised-button matStepperPrevious>
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Previous' | translate }}

View File

@ -19,7 +19,7 @@
</mifosx-repayment-schedule-tab>
</div>
<div class="layout-row responsive-column align-center gap-2px margin-t">
<div class="layout-row responsive-column align-center gap-2px margin-t stepper-buttons">
<button mat-raised-button matStepperPrevious>
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Previous' | translate }}

View File

@ -726,7 +726,7 @@
</table>
</div>
<div class="layout-row align-center gap-2percent margin-t responsive-column">
<div class="layout-row align-center gap-2percent margin-t responsive-column stepper-buttons">
<button mat-raised-button matStepperPrevious>
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Previous' | translate }}

View File

@ -59,7 +59,7 @@
</div>
}
<div class="layout-row responsive-column align-center gap-2px margin-t">
<div class="layout-row responsive-column align-center gap-2px margin-t stepper-buttons">
<button mat-raised-button matStepperPrevious>
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Previous' | translate }}

View File

@ -56,7 +56,12 @@
<ng-container matColumnDef="calculationtype">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'labels.inputs.Calculation Type' | translate }}</th>
<td mat-cell *matCellDef="let charge">{{ charge.chargeCalculationType.value }}</td>
<td mat-cell *matCellDef="let charge">
{{ charge.chargeCalculationType.value }}
@if (isPercentageCharge(charge)) {
({{ charge.percentage | formatNumber: 2 }}%)
}
</td>
</ng-container>
<ng-container matColumnDef="due">

View File

@ -8,7 +8,7 @@
/** Angular Imports */
import { Component, OnInit, ViewChild, inject } from '@angular/core';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
import { ActivatedRoute, Router } from '@angular/router';
import { MatDialog } from '@angular/material/dialog';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort, MatSortHeader } from '@angular/material/sort';
@ -47,6 +47,8 @@ import { CurrencyPipe } from '@angular/common';
import { MatTooltip } from '@angular/material/tooltip';
import { DateFormatPipe } from '../../../pipes/date-format.pipe';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
import { LoanCharge } from 'app/loans/models/loan-charge.model';
import { FormatNumberPipe } from '@pipes/format-number.pipe';
@Component({
selector: 'mifosx-charges-tab',
@ -69,7 +71,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
MatRow,
MatPaginator,
CurrencyPipe,
DateFormatPipe
DateFormatPipe,
FormatNumberPipe
]
})
export class ChargesTabComponent implements OnInit {
@ -78,14 +81,14 @@ export class ChargesTabComponent implements OnInit {
private dateUtils = inject(Dates);
private router = inject(Router);
private translateService = inject(TranslateService);
dialog = inject(MatDialog);
private dialog = inject(MatDialog);
private settingsService = inject(SettingsService);
private systemService = inject(SystemService);
/** Loan Details Data */
loanDetails: any;
/** Charges Data */
chargesData: any;
chargesData: LoanCharge[] = [];
/** Status */
status: any;
/** Columns to be displayed in charges table. */
@ -232,7 +235,7 @@ export class ChargesTabComponent implements OnInit {
new InputBase({
controlName: 'amount',
label: 'Amount',
value: charge.amount || charge.amountOrPercentage,
value: this.isPercentageCharge(charge) ? charge.amountOrPercentage : charge.amount,
type: 'number',
required: true
})
@ -295,4 +298,8 @@ export class ChargesTabComponent implements OnInit {
.navigateByUrl(`/clients/${clientId}/loans-accounts`, { skipLocationChange: true })
.then(() => this.router.navigate([url]));
}
isPercentageCharge(loanCharge: LoanCharge): boolean {
return loanCharge.chargeCalculationType.code.includes('.percent.');
}
}

View File

@ -32,7 +32,7 @@
matTooltip="{{ 'labels.status.' + loanDetailsData.status.value | translate }}"
[ngClass]="iconLoanStatusColor() | statusLookup"
></i>
<span class="m-r-5">{{ 'labels.heading.Loan Product' | translate }} :</span>
<span class="m-l-5 m-r-5">{{ 'labels.heading.Loan Product' | translate }} :</span>
<span class="m-r-5"
><mifosx-long-text textValue="{{ loanDetailsData.loanProductName }}"></mifosx-long-text
></span>

View File

@ -0,0 +1,38 @@
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
import { Charge, Currency } from 'app/shared/models/general.model';
import { OptionData } from 'app/shared/models/option-data.model';
export interface LoanCharge {
id: number;
chargeId: number;
name: string;
chargeTimeType: Charge;
submittedOnDate: number[];
dueDate: number[];
chargeCalculationType: OptionData;
percentage: number;
amountPercentageAppliedTo: number;
currency: Currency;
amount: number;
amountPaid: number;
amountWaived: number;
amountWrittenOff: number;
amountOutstanding: number;
amountOrPercentage: number;
penalty: boolean;
chargePaymentMode: OptionData;
chargeTime: OptionData;
paid: boolean;
waived: boolean;
chargePayable: boolean;
loanId: number;
externalId: string;
externalLoanId: string;
}

View File

@ -44,3 +44,7 @@ textarea.noresize {
margin-top: 5px;
margin-bottom: 5px;
}
.stepper-buttons {
height: 38px;
}