Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Dates } from 'app/core/utils/dates';
import { Currency, PaymentType } from 'app/shared/models/general.model';
import { PenaltyManagementService } from 'app/loans/services/penalty-management.service';
import { AlertService } from 'app/core/alert/alert.service';
import { TranslateService } from '@ngx-translate/core';
import { InputAmountComponent } from '../../../../shared/input-amount/input-amount.component';
import { MatSlideToggle } from '@angular/material/slide-toggle';
import { FormatNumberPipe } from '../../../../pipes/format-number.pipe';
Expand Down Expand Up @@ -44,6 +45,7 @@ export class MakeRepaymentComponent extends LoanAccountActionsBaseComponent impl
private cdr = inject(ChangeDetectorRef);
private destroyRef = inject(DestroyRef);
private alertService = inject(AlertService);
private translate = inject(TranslateService);

/** Payment Type Options */
paymentTypes: PaymentType[] = [];
Expand Down Expand Up @@ -225,9 +227,11 @@ export class MakeRepaymentComponent extends LoanAccountActionsBaseComponent impl
.subscribe({
next: (penalties: any[]) => {
this.penalties = penalties;
this.cdr.markForCheck();
},
error: () => {
this.penalties = [];
this.cdr.markForCheck();
}
});
}
Expand Down Expand Up @@ -316,7 +320,9 @@ export class MakeRepaymentComponent extends LoanAccountActionsBaseComponent impl
});

// Calculate new transaction amount
const newAmount = Math.max(0, baseAmount - totalWaived);
const decimalPlaces = this.currency?.decimalPlaces ?? 2;
const multiplier = Math.pow(10, decimalPlaces);
const newAmount = Math.max(0, Math.round((baseAmount - totalWaived) * multiplier) / multiplier);

// Allow zero when fully waived
this.updateTransactionAmountValidators(this.waivePenalties && newAmount === 0);
Expand Down Expand Up @@ -410,8 +416,10 @@ export class MakeRepaymentComponent extends LoanAccountActionsBaseComponent impl
error: () => {
this.alertService.alert({
type: 'Warning',
message: 'Some penalties could not be waived. Proceeding with repayment.'
message: this.translate.instant('Failed to waive penalties. Please try again.')
});
this.isSubmitting = false;
this.cdr.markForCheck();
}
});
} else {
Expand Down
23 changes: 10 additions & 13 deletions src/app/loans/services/penalty-management.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
*/

import { Injectable, inject } from '@angular/core';
import { Observable, forkJoin, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { Observable, of, from } from 'rxjs';
import { map, concatMap, toArray } from 'rxjs/operators';
import { LoansService, LoanAccountPath } from '../loans.service';
import { Dates } from 'app/core/utils/dates';

Expand Down Expand Up @@ -208,17 +208,14 @@ export class PenaltyManagementService {
return of([]);
}

// Create waive requests for each penalty
const waiveRequests = penaltyIds.map((chargeId: number) =>
this.loanService.executeLoansAccountChargesCommand(loanAccountPath, loanId, 'waive', {}, chargeId).pipe(
catchError((error: any) => {
console.error(`Error waiving penalty ${chargeId}:`, error);
// Return null for failed waive operations so we can continue with others
return of(null);
})
)
// Process waive requests sequentially to avoid race conditions.
// Each waive modifies the loan state on the backend, so the next
// request must wait for the previous one to complete.
return from(penaltyIds).pipe(
concatMap((chargeId: number) =>
this.loanService.executeLoansAccountChargesCommand(loanAccountPath, loanId, 'waive', {}, chargeId)
),
toArray()
);

return forkJoin(waiveRequests);
}
}
Loading