From 9dfe33c68e8640289dc3d611f1800c0423f9fe87 Mon Sep 17 00:00:00 2001 From: Jose Alberto Hernandez Date: Wed, 27 May 2026 15:24:48 -0500 Subject: [PATCH] WEB-954: Migrate Subscription management : loans --- .../loan-action-button.resolver.ts | 4 +- .../create-loans-account.component.ts | 11 +- ...account-add-collateral-dialog.component.ts | 26 +-- .../edit-loans-account.component.ts | 12 +- .../create-glim-account.component.ts | 22 ++- .../glim-account/glim-account.component.ts | 6 +- .../loans-account-details-step.component.ts | 18 +- .../loans-account-terms-step.component.ts | 76 +++++---- .../account-details.component.ts | 6 +- .../charges-tab/charges-tab.component.ts | 6 +- .../datatable-tab/datatable-tab.component.ts | 8 +- .../external-asset-owner-tab.component.ts | 16 +- .../floating-interest-rates.component.ts | 6 +- .../general-tab/general-tab.component.ts | 6 +- .../add-loan-charge.component.ts | 36 ++-- .../adjust-loan-charge.component.ts | 14 +- .../approve-loan/approve-loan.component.ts | 6 +- .../create-guarantor.component.ts | 84 ++++----- .../foreclosure/foreclosure.component.ts | 13 +- .../loan-account-actions.component.ts | 8 +- .../make-repayment.component.html | 44 ----- .../make-repayment.component.ts | 160 +++--------------- .../prepay-loan/prepay-loan.component.ts | 21 ++- .../loan-account-dashboard.component.ts | 20 +-- .../loan-collateral-tab.component.ts | 6 +- .../loan-deferred-income-tab.component.ts | 22 ++- .../loan-delinquency-tags-tab.component.ts | 48 +++--- .../loan-documents-tab.component.ts | 8 +- .../loan-originators-tab.component.ts | 14 +- .../loan-term-variations-tab.component.ts | 6 +- .../loan-tranche-details.component.ts | 6 +- .../loans/loans-view/loans-view.component.ts | 14 +- .../notes-tab/notes-tab.component.ts | 8 +- .../original-schedule-tab.component.ts | 6 +- .../overdue-charges-tab.component.ts | 6 +- .../reschedule-loan-tab.component.ts | 6 +- .../standing-instructions-tab.component.ts | 6 +- .../transactions-tab.component.ts | 14 +- .../edit-transaction.component.ts | 20 ++- .../export-transactions.component.ts | 12 +- .../view-reciept/view-reciept.component.ts | 6 +- .../view-transaction.component.ts | 6 +- .../view-charge/view-charge.component.ts | 18 +- .../loan-balances-tab.component.ts | 6 +- .../loan-period-payment-rates.component.ts | 12 +- src/app/loans/models/loan-form.model.ts | 24 +++ 46 files changed, 454 insertions(+), 449 deletions(-) create mode 100644 src/app/loans/models/loan-form.model.ts diff --git a/src/app/loans/common-resolvers/loan-action-button.resolver.ts b/src/app/loans/common-resolvers/loan-action-button.resolver.ts index 6d33d085da..521daf5818 100644 --- a/src/app/loans/common-resolvers/loan-action-button.resolver.ts +++ b/src/app/loans/common-resolvers/loan-action-button.resolver.ts @@ -38,7 +38,9 @@ export class LoanActionButtonResolver { if (loanActionButton === 'Assign Loan Officer' || loanActionButton === 'Change Loan Officer') { return this.loansService.getLoanTemplate(loanId); } else if (loanActionButton === 'Make Repayment') { - return this.loansService.getLoanActionTemplate(loanId, 'repayment'); + return this.loanProductService.isLoanProduct + ? this.loansService.getLoanActionTemplate(loanId, 'repayment') + : this.loansService.getWorkingCapitalLoanActionTemplate(loanId, 'repayment'); } else if (loanActionButton === 'Goodwill Credit') { return this.loansService.getLoanActionTemplate(loanId, 'goodwillCredit'); } else if (loanActionButton === 'Interest Payment Waiver') { diff --git a/src/app/loans/create-loans-account/create-loans-account.component.ts b/src/app/loans/create-loans-account/create-loans-account.component.ts index c9b4b39372..b53d78c4e9 100644 --- a/src/app/loans/create-loans-account/create-loans-account.component.ts +++ b/src/app/loans/create-loans-account/create-loans-account.component.ts @@ -12,11 +12,13 @@ import { AfterViewInit, ChangeDetectorRef, Component, + DestroyRef, QueryList, ViewChild, ViewChildren, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute } from '@angular/router'; /** Custom Services */ @@ -62,6 +64,7 @@ import { Dates } from 'app/core/utils/dates'; changeDetection: ChangeDetectionStrategy.OnPush }) export class CreateLoansAccountComponent extends LoanProductBaseComponent implements AfterViewInit { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); private loansService = inject(LoansService); private settingsService = inject(SettingsService); @@ -110,12 +113,12 @@ export class CreateLoansAccountComponent extends LoanProductBaseComponent implem constructor() { super(); this.loanProductsBasicDetails = []; - this.route.data.subscribe( - (data: { loansAccountTemplate: any; loanProductsBasicDetails: LoanProductBasicDetails[] }) => { + this.route.data + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((data: { loansAccountTemplate: any; loanProductsBasicDetails: LoanProductBasicDetails[] }) => { this.loanProductsBasicDetails = data.loanProductsBasicDetails; this.loansAccountTemplate = data.loansAccountTemplate; - } - ); + }); } ngAfterViewInit() { diff --git a/src/app/loans/custom-dialog/loans-account-add-collateral-dialog/loans-account-add-collateral-dialog.component.ts b/src/app/loans/custom-dialog/loans-account-add-collateral-dialog/loans-account-add-collateral-dialog.component.ts index 03c3317319..ce40b14462 100644 --- a/src/app/loans/custom-dialog/loans-account-add-collateral-dialog/loans-account-add-collateral-dialog.component.ts +++ b/src/app/loans/custom-dialog/loans-account-add-collateral-dialog/loans-account-add-collateral-dialog.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatDialogRef, MAT_DIALOG_DATA, @@ -34,6 +35,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; changeDetection: ChangeDetectionStrategy.OnPush }) export class LoansAccountAddCollateralDialogComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); dialogRef = inject>(MatDialogRef); data = inject(MAT_DIALOG_DATA); private formBuilder = inject(UntypedFormBuilder); @@ -81,16 +83,20 @@ export class LoansAccountAddCollateralDialogComponent implements OnInit { * Subscribe to Form controls value changes */ buildDependencies() { - this.addCollateralForm.controls.collateral.valueChanges.subscribe((collateral: any) => { - this.collateralData = collateral; - this.maxQuantity = collateral.quantity; - }); + this.addCollateralForm.controls.collateral.valueChanges + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((collateral: any) => { + this.collateralData = collateral; + this.maxQuantity = collateral.quantity; + }); - this.addCollateralForm.controls.quantity.valueChanges.subscribe((quantity: any) => { - this.addCollateralForm.patchValue({ - totalValue: this.collateralData.basePrice * quantity, - totalCollateralValue: (this.collateralData.basePrice * this.collateralData.pctToBase * quantity) / 100 + this.addCollateralForm.controls.quantity.valueChanges + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((quantity: any) => { + this.addCollateralForm.patchValue({ + totalValue: this.collateralData.basePrice * quantity, + totalCollateralValue: (this.collateralData.basePrice * this.collateralData.pctToBase * quantity) / 100 + }); }); - }); } } diff --git a/src/app/loans/edit-loans-account/edit-loans-account.component.ts b/src/app/loans/edit-loans-account/edit-loans-account.component.ts index 4486f855a5..b416830dcd 100644 --- a/src/app/loans/edit-loans-account/edit-loans-account.component.ts +++ b/src/app/loans/edit-loans-account/edit-loans-account.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, ViewChild, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, ViewChild, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute } from '@angular/router'; import { LoansService } from '../loans.service'; import { LoansAccountDetailsStepComponent } from '../loans-account-stepper/loans-account-details-step/loans-account-details-step.component'; @@ -47,6 +48,7 @@ import { LoanProductBaseComponent } from 'app/products/loan-products/common/loan changeDetection: ChangeDetectionStrategy.OnPush }) export class EditLoansAccountComponent extends LoanProductBaseComponent { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); private dateUtils = inject(Dates); private loansService = inject(LoansService); @@ -79,8 +81,9 @@ export class EditLoansAccountComponent extends LoanProductBaseComponent { this.loanProductService.initialize(LoanProductBaseComponent.resolveProductTypeDefault(this.route, 'loan')); this.loanId = this.route.snapshot.params['loanId']; - this.route.data.subscribe( - (data: { loansAccountAndTemplate: any; loanProductsBasicDetails: LoanProductBasicDetails[] }) => { + this.route.data + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((data: { loansAccountAndTemplate: any; loanProductsBasicDetails: LoanProductBasicDetails[] }) => { this.loansAccountAndTemplate = data.loansAccountAndTemplate; if (this.loanProductService.isLoanProduct) { this.loansAccountProductTemplate = data.loansAccountAndTemplate; @@ -92,8 +95,7 @@ export class EditLoansAccountComponent extends LoanProductBaseComponent { ); } this.loanProductsBasicDetails = data.loanProductsBasicDetails; - } - ); + }); } /** diff --git a/src/app/loans/glim-account/create-glim-account/create-glim-account.component.ts b/src/app/loans/glim-account/create-glim-account/create-glim-account.component.ts index 588fa08260..517e8f115b 100644 --- a/src/app/loans/glim-account/create-glim-account/create-glim-account.component.ts +++ b/src/app/loans/glim-account/create-glim-account/create-glim-account.component.ts @@ -7,7 +7,16 @@ */ /** Angular Imports */ -import { ChangeDetectionStrategy, Component, QueryList, ViewChild, ViewChildren, inject } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + DestroyRef, + QueryList, + ViewChild, + ViewChildren, + inject +} from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { I18nService } from 'app/core/i18n/i18n.service'; import { ActivatedRoute, Router } from '@angular/router'; @@ -51,6 +60,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; changeDetection: ChangeDetectionStrategy.OnPush }) export class CreateGlimAccountComponent { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); private router = inject(Router); private loansService = inject(LoansService); @@ -97,10 +107,12 @@ export class CreateGlimAccountComponent { * @param {ClientsService} clientService Client Service */ constructor() { - this.route.data.subscribe((data: { loansAccountTemplate: any; groupsData: any }) => { - this.loansAccountTemplate = data.loansAccountTemplate; - this.dataSource = data.groupsData.activeClientMembers; - }); + this.route.data + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((data: { loansAccountTemplate: any; groupsData: any }) => { + this.loansAccountTemplate = data.loansAccountTemplate; + this.dataSource = data.groupsData.activeClientMembers; + }); } /** diff --git a/src/app/loans/glim-account/glim-account.component.ts b/src/app/loans/glim-account/glim-account.component.ts index 19cba9276d..de7d706c48 100644 --- a/src/app/loans/glim-account/glim-account.component.ts +++ b/src/app/loans/glim-account/glim-account.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, OnInit, ViewChild, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, ViewChild, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatDialog } from '@angular/material/dialog'; import { MatPaginator } from '@angular/material/paginator'; import { @@ -53,6 +54,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; changeDetection: ChangeDetectionStrategy.OnPush }) export class GlimAccountComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); dialog = inject(MatDialog); @@ -81,7 +83,7 @@ export class GlimAccountComponent implements OnInit { * @param {MatDialog} dialog Dialog reference. */ constructor() { - this.route.data.subscribe((data: { glimData: any }) => { + this.route.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { glimData: any }) => { this.glimOverviewData = data.glimData; }); } diff --git a/src/app/loans/loans-account-stepper/loans-account-details-step/loans-account-details-step.component.ts b/src/app/loans/loans-account-stepper/loans-account-details-step/loans-account-details-step.component.ts index 406667acdc..69ac2f9617 100644 --- a/src/app/loans/loans-account-stepper/loans-account-details-step/loans-account-details-step.component.ts +++ b/src/app/loans/loans-account-stepper/loans-account-details-step/loans-account-details-step.component.ts @@ -11,13 +11,14 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + DestroyRef, OnInit, Input, Output, EventEmitter, - OnDestroy, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { UntypedFormGroup, UntypedFormBuilder, Validators, UntypedFormControl } from '@angular/forms'; import { ActivatedRoute } from '@angular/router'; import { SettingsService } from 'app/settings/settings.service'; @@ -26,8 +27,7 @@ import { TranslateService } from '@ngx-translate/core'; /** Custom Services */ import { LoansService } from '../../loans.service'; import { Commons } from 'app/core/utils/commons'; -import { takeUntil } from 'rxjs/operators'; -import { ReplaySubject, Subject } from 'rxjs'; +import { ReplaySubject } from 'rxjs'; import { MatTooltip } from '@angular/material/tooltip'; import { NgxMatSelectSearchModule } from 'ngx-mat-select-search'; import { AsyncPipe } from '@angular/common'; @@ -62,7 +62,8 @@ import { LoanProductBaseComponent } from 'app/products/loan-products/common/loan ], changeDetection: ChangeDetectionStrategy.OnPush }) -export class LoansAccountDetailsStepComponent extends LoanProductBaseComponent implements OnInit, OnDestroy { +export class LoansAccountDetailsStepComponent extends LoanProductBaseComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private formBuilder = inject(UntypedFormBuilder); private loansService = inject(LoansService); private route = inject(ActivatedRoute); @@ -106,8 +107,6 @@ export class LoansAccountDetailsStepComponent extends LoanProductBaseComponent i protected productData: ReplaySubject = new ReplaySubject(1); /** control for the filter select */ protected filterFormCtrl: UntypedFormControl = new UntypedFormControl(''); - /** Subject that emits when the component has been destroyed. */ - protected _onDestroy = new Subject(); productSelected: LoanProductBasicDetails | null = null; @@ -167,17 +166,12 @@ export class LoansAccountDetailsStepComponent extends LoanProductBaseComponent i this.getProductTemplate(false); } } - this.filterFormCtrl.valueChanges.pipe(takeUntil(this._onDestroy)).subscribe(() => { + this.filterFormCtrl.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => { this.searchItem(); }); this.productData.next(this.productList.slice()); } - ngOnDestroy(): void { - this._onDestroy.next(); - this._onDestroy.complete(); - } - searchItem(): void { if (this.productList) { const search: string = this.filterFormCtrl.value.toLowerCase(); diff --git a/src/app/loans/loans-account-stepper/loans-account-terms-step/loans-account-terms-step.component.ts b/src/app/loans/loans-account-stepper/loans-account-terms-step/loans-account-terms-step.component.ts index ac26af174d..08525b5b3e 100644 --- a/src/app/loans/loans-account-stepper/loans-account-terms-step/loans-account-terms-step.component.ts +++ b/src/app/loans/loans-account-stepper/loans-account-terms-step/loans-account-terms-step.component.ts @@ -11,12 +11,14 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + DestroyRef, OnInit, Input, OnChanges, SimpleChanges, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { UntypedFormGroup, UntypedFormBuilder, Validators, UntypedFormControl } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute } from '@angular/router'; @@ -99,6 +101,7 @@ interface DisbursementData { changeDetection: ChangeDetectionStrategy.OnPush }) export class LoansAccountTermsStepComponent extends LoanProductBaseComponent implements OnInit, OnChanges { + private readonly destroyRef = inject(DestroyRef); private formBuilder = inject(UntypedFormBuilder); private settingsService = inject(SettingsService); private route = inject(ActivatedRoute); @@ -515,42 +518,57 @@ export class LoansAccountTermsStepComponent extends LoanProductBaseComponent imp const repaymentFrequencyNthDayType = this.loansAccountTermsForm.get('repaymentFrequencyNthDayType'); const repaymentFrequencyDayOfWeekType = this.loansAccountTermsForm.get('repaymentFrequencyDayOfWeekType'); - this.loansAccountTermsForm.get('repaymentFrequencyType')?.valueChanges.subscribe((repaymentFrequencyType) => { - repaymentFrequencyNthDayType?.setValidators(null); - repaymentFrequencyDayOfWeekType?.setValidators(null); + this.loansAccountTermsForm + .get('repaymentFrequencyType') + ?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((repaymentFrequencyType) => { + repaymentFrequencyNthDayType?.setValidators(null); + repaymentFrequencyDayOfWeekType?.setValidators(null); - setTimeout(() => { - repaymentFrequencyNthDayType?.updateValueAndValidity(); - repaymentFrequencyDayOfWeekType?.updateValueAndValidity(); + setTimeout(() => { + repaymentFrequencyNthDayType?.updateValueAndValidity(); + repaymentFrequencyDayOfWeekType?.updateValueAndValidity(); + }); }); - }); } /** Custom Listeners for the form to calculate Loan Term */ setLoanTermListener() { - this.loansAccountTermsForm.get('numberOfRepayments')?.valueChanges.subscribe((numberOfRepayments) => { - const repaymentEvery: number = this.loansAccountTermsForm.value.repaymentEvery; - this.calculateLoanTerm(numberOfRepayments, repaymentEvery); - }); + this.loansAccountTermsForm + .get('numberOfRepayments') + ?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((numberOfRepayments) => { + const repaymentEvery: number = this.loansAccountTermsForm.value.repaymentEvery; + this.calculateLoanTerm(numberOfRepayments, repaymentEvery); + }); - this.loansAccountTermsForm.get('repaymentEvery')?.valueChanges.subscribe((repaymentEvery) => { - const numberOfRepayments: number = this.loansAccountTermsForm.value.numberOfRepayments; - this.calculateLoanTerm(numberOfRepayments, repaymentEvery); - }); + this.loansAccountTermsForm + .get('repaymentEvery') + ?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((repaymentEvery) => { + const numberOfRepayments: number = this.loansAccountTermsForm.value.numberOfRepayments; + this.calculateLoanTerm(numberOfRepayments, repaymentEvery); + }); - this.loansAccountTermsForm.get('loanTermFrequencyType')?.valueChanges.subscribe((loanTermFrequencyType) => { - this.loansAccountTermsForm.patchValue({ repaymentFrequencyType: loanTermFrequencyType }); - }); + this.loansAccountTermsForm + .get('loanTermFrequencyType') + ?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((loanTermFrequencyType) => { + this.loansAccountTermsForm.patchValue({ repaymentFrequencyType: loanTermFrequencyType }); + }); - this.loansAccountTermsForm.get('amortizationType')?.valueChanges.subscribe((amortizationType) => { - if (amortizationType === 0) { - // Equal Principal Payments - this.loansAccountTermsForm.addControl('fixedPrincipalPercentagePerInstallment', new UntypedFormControl('')); - } else { - // Equal Installments - this.loansAccountTermsForm.removeControl('fixedPrincipalPercentagePerInstallment'); - } - }); + this.loansAccountTermsForm + .get('amortizationType') + ?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((amortizationType) => { + if (amortizationType === 0) { + // Equal Principal Payments + this.loansAccountTermsForm.addControl('fixedPrincipalPercentagePerInstallment', new UntypedFormControl('')); + } else { + // Equal Installments + this.loansAccountTermsForm.removeControl('fixedPrincipalPercentagePerInstallment'); + } + }); } /** Prevent negative values in numeric fields */ @@ -568,7 +586,7 @@ export class LoansAccountTermsStepComponent extends LoanProductBaseComponent imp numericFieldsWithMinZero.forEach((fieldName) => { const control = this.loansAccountTermsForm.get(fieldName); if (control) { - control.valueChanges.subscribe((value) => { + control.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((value) => { if (typeof value === 'number' && value < 0) { control.setValue(0, { emitEvent: false }); } @@ -577,7 +595,7 @@ export class LoansAccountTermsStepComponent extends LoanProductBaseComponent imp }); const interestRateControl = this.loansAccountTermsForm.get('interestRatePerPeriod'); if (interestRateControl) { - interestRateControl.valueChanges.subscribe((value) => { + interestRateControl.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((value) => { if (typeof value === 'number' && value < 0.01) { interestRateControl.setValue(0.01, { emitEvent: false }); } diff --git a/src/app/loans/loans-view/account-details/account-details.component.ts b/src/app/loans/loans-view/account-details/account-details.component.ts index a53b58cbd0..be05057167 100644 --- a/src/app/loans/loans-view/account-details/account-details.component.ts +++ b/src/app/loans/loans-view/account-details/account-details.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute } from '@angular/router'; import { DateFormatPipe } from '../../../pipes/date-format.pipe'; import { FormatNumberPipe } from '../../../pipes/format-number.pipe'; @@ -29,6 +30,7 @@ import { BreachDisplayComponent } from 'app/shared/loan/breach-display/breach-di changeDetection: ChangeDetectionStrategy.OnPush }) export class AccountDetailsComponent extends LoanProductBaseComponent { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); loanDetails: any; @@ -40,7 +42,7 @@ export class AccountDetailsComponent extends LoanProductBaseComponent { constructor() { super(); this.loanProductService.initialize(LoanProductBaseComponent.resolveProductTypeDefault(this.route, 'loan')); - this.route.parent.data.subscribe((data: { loanDetailsData: any }) => { + this.route.parent.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loanDetailsData: any }) => { this.loanDetails = data.loanDetailsData; }); } diff --git a/src/app/loans/loans-view/charges-tab/charges-tab.component.ts b/src/app/loans/loans-view/charges-tab/charges-tab.component.ts index 387930029d..d3bf227966 100644 --- a/src/app/loans/loans-view/charges-tab/charges-tab.component.ts +++ b/src/app/loans/loans-view/charges-tab/charges-tab.component.ts @@ -7,7 +7,8 @@ */ /** Angular Imports */ -import { ChangeDetectionStrategy, Component, OnInit, ViewChild, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, ViewChild, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute } from '@angular/router'; import { MatDialog } from '@angular/material/dialog'; import { MatPaginator } from '@angular/material/paginator'; @@ -78,6 +79,7 @@ import { LoanAccountTabBaseComponent } from '../loan-account-tab-base.component' changeDetection: ChangeDetectionStrategy.OnPush }) export class ChargesTabComponent extends LoanAccountTabBaseComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private loansService = inject(LoansService); private route = inject(ActivatedRoute); private dateUtils = inject(Dates); @@ -122,7 +124,7 @@ export class ChargesTabComponent extends LoanAccountTabBaseComponent implements */ constructor() { super(); - this.route.parent.data.subscribe((data: { loanDetailsData: any }) => { + this.route.parent.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loanDetailsData: any }) => { this.loanDetails = data.loanDetailsData; }); } diff --git a/src/app/loans/loans-view/datatable-tab/datatable-tab.component.ts b/src/app/loans/loans-view/datatable-tab/datatable-tab.component.ts index a644466bca..c30c9284ba 100644 --- a/src/app/loans/loans-view/datatable-tab/datatable-tab.component.ts +++ b/src/app/loans/loans-view/datatable-tab/datatable-tab.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute } from '@angular/router'; import { EntityDatatableTabComponent } from '../../../shared/tabs/entity-datatable-tab/entity-datatable-tab.component'; import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; @@ -22,6 +23,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; changeDetection: ChangeDetectionStrategy.OnPush }) export class DatatableTabComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); entityId: string; @@ -37,14 +39,14 @@ export class DatatableTabComponent implements OnInit { constructor() { this.entityId = this.route.parent.parent.snapshot.paramMap.get('loanId'); this.entityDatatable = null; - this.route.data.subscribe((data: { loanDatatable: any }) => { + this.route.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loanDatatable: any }) => { this.entityDatatable = data.loanDatatable; this.multiRowDatatableFlag = this.entityDatatable.columnHeaders[0].columnName === 'id' ? true : false; }); } ngOnInit() { - this.route.parent.parent.params.subscribe((params) => { + this.route.parent.parent.params.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((params) => { this.entityId = params['loanId']; }); } diff --git a/src/app/loans/loans-view/external-asset-owner-tab/external-asset-owner-tab.component.ts b/src/app/loans/loans-view/external-asset-owner-tab/external-asset-owner-tab.component.ts index 0152315adf..d0ff36dc5b 100644 --- a/src/app/loans/loans-view/external-asset-owner-tab/external-asset-owner-tab.component.ts +++ b/src/app/loans/loans-view/external-asset-owner-tab/external-asset-owner-tab.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute } from '@angular/router'; import { ExternalAssetOwner } from 'app/loans/services/external-asset-owner'; @@ -60,6 +61,7 @@ import { LoanAccountTabBaseComponent } from '../loan-account-tab-base.component' changeDetection: ChangeDetectionStrategy.OnPush }) export class ExternalAssetOwnerTabComponent extends LoanAccountTabBaseComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); private dialog = inject(MatDialog); private externalAssetOwner = inject(ExternalAssetOwner); @@ -83,11 +85,13 @@ export class ExternalAssetOwnerTabComponent extends LoanAccountTabBaseComponent constructor() { super(); - this.route.data.subscribe((data: { loanTransfersData: any; activeTransferData: any }) => { - this.loanTransfersData = data.loanTransfersData.empty ? [] : data.loanTransfersData.content; - this.activeTransferData = data.activeTransferData || null; - this.existActiveTransfer = data.activeTransferData && data.activeTransferData.transferId != null; - }); + this.route.data + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((data: { loanTransfersData: any; activeTransferData: any }) => { + this.loanTransfersData = data.loanTransfersData.empty ? [] : data.loanTransfersData.content; + this.activeTransferData = data.activeTransferData || null; + this.existActiveTransfer = data.activeTransferData && data.activeTransferData.transferId != null; + }); } ngOnInit(): void { diff --git a/src/app/loans/loans-view/floating-interest-rates/floating-interest-rates.component.ts b/src/app/loans/loans-view/floating-interest-rates/floating-interest-rates.component.ts index 0c761d89f7..6fdeb1797f 100644 --- a/src/app/loans/loans-view/floating-interest-rates/floating-interest-rates.component.ts +++ b/src/app/loans/loans-view/floating-interest-rates/floating-interest-rates.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute } from '@angular/router'; import { MatTable, @@ -44,6 +45,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; changeDetection: ChangeDetectionStrategy.OnPush }) export class FloatingInterestRatesComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); /** Loan Details */ @@ -61,7 +63,7 @@ export class FloatingInterestRatesComponent implements OnInit { * @param {ActivatedRoute} route Activated Route. */ constructor() { - this.route.parent.data.subscribe((data: { loanDetailsData: any }) => { + this.route.parent.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loanDetailsData: any }) => { this.loanDetails = data.loanDetailsData; }); } diff --git a/src/app/loans/loans-view/general-tab/general-tab.component.ts b/src/app/loans/loans-view/general-tab/general-tab.component.ts index b9e0e9a442..46342679f3 100644 --- a/src/app/loans/loans-view/general-tab/general-tab.component.ts +++ b/src/app/loans/loans-view/general-tab/general-tab.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute } from '@angular/router'; import { MatTableDataSource, @@ -53,6 +54,7 @@ import { LoanProductBaseComponent } from 'app/products/loan-products/common/loan changeDetection: ChangeDetectionStrategy.OnPush }) export class GeneralTabComponent extends LoanProductBaseComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); /** Currency Code */ @@ -97,7 +99,7 @@ export class GeneralTabComponent extends LoanProductBaseComponent implements OnI if (productType) { this.loanProductService.initialize(productType); } - this.route.parent.data.subscribe((data: { loanDetailsData: any }) => { + this.route.parent.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loanDetailsData: any }) => { this.loanDetails = data.loanDetailsData; this.currencyCode = this.loanDetails.currency.code; if (this.loanDetails.transactions) { diff --git a/src/app/loans/loans-view/loan-account-actions/add-loan-charge/add-loan-charge.component.ts b/src/app/loans/loans-view/loan-account-actions/add-loan-charge/add-loan-charge.component.ts index a388e52f6e..855c953bc5 100644 --- a/src/app/loans/loans-view/loan-account-actions/add-loan-charge/add-loan-charge.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/add-loan-charge/add-loan-charge.component.ts @@ -7,7 +7,8 @@ */ /** Angular Imports */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { UntypedFormGroup, UntypedFormBuilder, Validators, UntypedFormControl } from '@angular/forms'; /** Custom Services */ @@ -28,6 +29,7 @@ import { LoanAccountActionsBaseComponent } from '../loan-account-actions-base.co changeDetection: ChangeDetectionStrategy.OnPush }) export class AddLoanChargeComponent extends LoanAccountActionsBaseComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private formBuilder = inject(UntypedFormBuilder); private dateUtils = inject(Dates); @@ -61,7 +63,7 @@ export class AddLoanChargeComponent extends LoanAccountActionsBaseComponent impl */ constructor() { super(); - this.route.data.subscribe((data: { actionButtonData: any }) => { + this.route.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { actionButtonData: any }) => { this.loanChargeOptions = data.actionButtonData.chargeOptions; }); this.loanId = this.route.snapshot.params['loanId']; @@ -73,21 +75,23 @@ export class AddLoanChargeComponent extends LoanAccountActionsBaseComponent impl ngOnInit() { this.maxDate = this.settingsService.maxFutureDate; this.createLoanChargeForm(); - this.loanChargeForm.controls.chargeId.valueChanges.subscribe((chargeId) => { - const chargeDetails = this.loanChargeOptions.find((option) => { - return option.id === chargeId; + this.loanChargeForm.controls.chargeId.valueChanges + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((chargeId) => { + const chargeDetails = this.loanChargeOptions.find((option) => { + return option.id === chargeId; + }); + if (chargeDetails.chargeTimeType.id === 2) { + this.loanChargeForm.addControl('dueDate', new UntypedFormControl('', Validators.required)); + } else { + this.loanChargeForm.removeControl('dueDate'); + } + this.loanChargeForm.patchValue({ + amount: chargeDetails.amount, + chargeCalculation: chargeDetails.chargeCalculationType.value, + chargeTime: chargeDetails.chargeTimeType.value + }); }); - if (chargeDetails.chargeTimeType.id === 2) { - this.loanChargeForm.addControl('dueDate', new UntypedFormControl('', Validators.required)); - } else { - this.loanChargeForm.removeControl('dueDate'); - } - this.loanChargeForm.patchValue({ - amount: chargeDetails.amount, - chargeCalculation: chargeDetails.chargeCalculationType.value, - chargeTime: chargeDetails.chargeTimeType.value - }); - }); } /** diff --git a/src/app/loans/loans-view/loan-account-actions/adjust-loan-charge/adjust-loan-charge.component.ts b/src/app/loans/loans-view/loan-account-actions/adjust-loan-charge/adjust-loan-charge.component.ts index 78acce9771..6c30bbac86 100644 --- a/src/app/loans/loans-view/loan-account-actions/adjust-loan-charge/adjust-loan-charge.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/adjust-loan-charge/adjust-loan-charge.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms'; import { OrganizationService } from 'app/organization/organization.service'; import { MatSlideToggle } from '@angular/material/slide-toggle'; @@ -28,6 +29,7 @@ import { InputAmountComponent } from 'app/shared/input-amount/input-amount.compo changeDetection: ChangeDetectionStrategy.OnPush }) export class AdjustLoanChargeComponent extends LoanAccountActionsBaseComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private formBuilder = inject(UntypedFormBuilder); private organizationService = inject(OrganizationService); @@ -55,10 +57,12 @@ export class AdjustLoanChargeComponent extends LoanAccountActionsBaseComponent i constructor() { super(); this.chargeId = this.route.snapshot.params['id']; - this.route.data.subscribe((data: { loansAccountCharge: any; loanDetailsData: any }) => { - this.chargeData = data.loansAccountCharge; - this.loanDetailsData = data.loanDetailsData; - }); + this.route.data + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((data: { loansAccountCharge: any; loanDetailsData: any }) => { + this.chargeData = data.loansAccountCharge; + this.loanDetailsData = data.loanDetailsData; + }); } /** diff --git a/src/app/loans/loans-view/loan-account-actions/approve-loan/approve-loan.component.ts b/src/app/loans/loans-view/loan-account-actions/approve-loan/approve-loan.component.ts index fac05a8049..fac43762c2 100644 --- a/src/app/loans/loans-view/loan-account-actions/approve-loan/approve-loan.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/approve-loan/approve-loan.component.ts @@ -7,7 +7,8 @@ */ /** Angular Imports. */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { UntypedFormGroup, UntypedFormBuilder, Validators, UntypedFormControl } from '@angular/forms'; import { Dates } from 'app/core/utils/dates'; @@ -35,6 +36,7 @@ import { LoanAccountActionsBaseComponent } from '../loan-account-actions-base.co changeDetection: ChangeDetectionStrategy.OnPush }) export class ApproveLoanComponent extends LoanAccountActionsBaseComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private formBuilder = inject(UntypedFormBuilder); private dateUtils = inject(Dates); @@ -54,7 +56,7 @@ export class ApproveLoanComponent extends LoanAccountActionsBaseComponent implem constructor() { super(); this.maxDate = this.settingsService.maxFutureDate; - this.route.data.subscribe((data: { actionButtonData: any }) => { + this.route.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { actionButtonData: any }) => { this.loanData = data.actionButtonData; this.currency = data.actionButtonData.currency; }); diff --git a/src/app/loans/loans-view/loan-account-actions/create-guarantor/create-guarantor.component.ts b/src/app/loans/loans-view/loan-account-actions/create-guarantor/create-guarantor.component.ts index 49c25d5d65..b241375516 100644 --- a/src/app/loans/loans-view/loan-account-actions/create-guarantor/create-guarantor.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/create-guarantor/create-guarantor.component.ts @@ -7,7 +7,8 @@ */ /** Angular Imports */ -import { ChangeDetectionStrategy, Component, OnInit, AfterViewInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, AfterViewInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { UntypedFormGroup, UntypedFormBuilder, Validators, UntypedFormControl } from '@angular/forms'; /** Custom Services */ @@ -34,6 +35,7 @@ import { LoanAccountActionsBaseComponent } from '../loan-account-actions-base.co changeDetection: ChangeDetectionStrategy.OnPush }) export class CreateGuarantorComponent extends LoanAccountActionsBaseComponent implements OnInit, AfterViewInit { + private readonly destroyRef = inject(DestroyRef); private formBuilder = inject(UntypedFormBuilder); private dateUtils = inject(Dates); private clientsService = inject(ClientsService); @@ -97,36 +99,39 @@ export class CreateGuarantorComponent extends LoanAccountActionsBaseComponent im * Add guarantor detail fields to the UI. */ buildDependencies() { - this.newGuarantorForm.get('existingClient').valueChanges.subscribe(() => { - this.showClientDetailsForm = !this.showClientDetailsForm; - if (this.showClientDetailsForm) { - this.newGuarantorForm.addControl('firstname', new UntypedFormControl('')); - this.newGuarantorForm.addControl('lastname', new UntypedFormControl('')); - this.newGuarantorForm.addControl('dob', new UntypedFormControl('')); - this.newGuarantorForm.addControl('addressLine1', new UntypedFormControl('')); - this.newGuarantorForm.addControl('addressLine2', new UntypedFormControl('')); - this.newGuarantorForm.addControl('city', new UntypedFormControl('')); - this.newGuarantorForm.addControl('zip', new UntypedFormControl('')); - this.newGuarantorForm.addControl('mobileNumber', new UntypedFormControl('')); - this.newGuarantorForm.addControl('housePhoneNumber', new UntypedFormControl('')); - this.newGuarantorForm.removeControl('name'); - this.newGuarantorForm.removeControl('savingsId'); - this.newGuarantorForm.removeControl('amount'); - } else { - this.newGuarantorForm.addControl('name', new UntypedFormControl('')); - this.newGuarantorForm.addControl('savingsId', new UntypedFormControl('')); - this.newGuarantorForm.addControl('amount', new UntypedFormControl('')); - this.newGuarantorForm.removeControl('firstname'); - this.newGuarantorForm.removeControl('lastname'); - this.newGuarantorForm.removeControl('dob'); - this.newGuarantorForm.removeControl('addressLine1'); - this.newGuarantorForm.removeControl('addressLine2'); - this.newGuarantorForm.removeControl('city'); - this.newGuarantorForm.removeControl('zip'); - this.newGuarantorForm.removeControl('mobileNumber'); - this.newGuarantorForm.removeControl('housePhoneNumber'); - } - }); + this.newGuarantorForm + .get('existingClient') + .valueChanges.pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe(() => { + this.showClientDetailsForm = !this.showClientDetailsForm; + if (this.showClientDetailsForm) { + this.newGuarantorForm.addControl('firstname', new UntypedFormControl('')); + this.newGuarantorForm.addControl('lastname', new UntypedFormControl('')); + this.newGuarantorForm.addControl('dob', new UntypedFormControl('')); + this.newGuarantorForm.addControl('addressLine1', new UntypedFormControl('')); + this.newGuarantorForm.addControl('addressLine2', new UntypedFormControl('')); + this.newGuarantorForm.addControl('city', new UntypedFormControl('')); + this.newGuarantorForm.addControl('zip', new UntypedFormControl('')); + this.newGuarantorForm.addControl('mobileNumber', new UntypedFormControl('')); + this.newGuarantorForm.addControl('housePhoneNumber', new UntypedFormControl('')); + this.newGuarantorForm.removeControl('name'); + this.newGuarantorForm.removeControl('savingsId'); + this.newGuarantorForm.removeControl('amount'); + } else { + this.newGuarantorForm.addControl('name', new UntypedFormControl('')); + this.newGuarantorForm.addControl('savingsId', new UntypedFormControl('')); + this.newGuarantorForm.addControl('amount', new UntypedFormControl('')); + this.newGuarantorForm.removeControl('firstname'); + this.newGuarantorForm.removeControl('lastname'); + this.newGuarantorForm.removeControl('dob'); + this.newGuarantorForm.removeControl('addressLine1'); + this.newGuarantorForm.removeControl('addressLine2'); + this.newGuarantorForm.removeControl('city'); + this.newGuarantorForm.removeControl('zip'); + this.newGuarantorForm.removeControl('mobileNumber'); + this.newGuarantorForm.removeControl('housePhoneNumber'); + } + }); } /** @@ -134,13 +139,16 @@ export class CreateGuarantorComponent extends LoanAccountActionsBaseComponent im */ ngAfterViewInit() { if (this.newGuarantorForm.value.existingClient) { - this.newGuarantorForm.get('name').valueChanges.subscribe((value: string) => { - if (value.length >= 2) { - this.clientsService.getFilteredClients('displayName', 'ASC', true, value).subscribe((data: any) => { - this.clientsData = data.pageItems; - }); - } - }); + this.newGuarantorForm + .get('name') + .valueChanges.pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((value: string) => { + if (value.length >= 2) { + this.clientsService.getFilteredClients('displayName', 'ASC', true, value).subscribe((data: any) => { + this.clientsData = data.pageItems; + }); + } + }); } } diff --git a/src/app/loans/loans-view/loan-account-actions/foreclosure/foreclosure.component.ts b/src/app/loans/loans-view/loan-account-actions/foreclosure/foreclosure.component.ts index 6b55ffb4de..1218f57e8f 100644 --- a/src/app/loans/loans-view/loan-account-actions/foreclosure/foreclosure.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/foreclosure/foreclosure.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; /** Custom Services */ @@ -26,6 +27,7 @@ import { LoanAccountActionsBaseComponent } from '../loan-account-actions-base.co changeDetection: ChangeDetectionStrategy.OnPush }) export class ForeclosureComponent extends LoanAccountActionsBaseComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private formBuilder = inject(UntypedFormBuilder); private dateUtils = inject(Dates); @@ -65,9 +67,12 @@ export class ForeclosureComponent extends LoanAccountActionsBaseComponent implem } onChanges(): void { - this.foreclosureForm.get('transactionDate').valueChanges.subscribe((val) => { - this.retrieveLoanForeclosureTemplate(val); - }); + this.foreclosureForm + .get('transactionDate') + .valueChanges.pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((val) => { + this.retrieveLoanForeclosureTemplate(val); + }); } retrieveLoanForeclosureTemplate(val: any) { diff --git a/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.ts b/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.ts index 2ecf36bb4e..23cf066caf 100644 --- a/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.ts @@ -7,7 +7,8 @@ */ /** Angular Imports. */ -import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute, Router } from '@angular/router'; import { LoansAccountCloseComponent } from './loans-account-close/loans-account-close.component'; import { UndoApprovalComponent } from './undo-approval/undo-approval.component'; @@ -89,6 +90,7 @@ import { UpdateDiscountComponent } from './update-discount/update-discount.compo changeDetection: ChangeDetectionStrategy.OnPush }) export class LoanAccountActionsComponent { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); private router = inject(Router); @@ -193,11 +195,11 @@ export class LoanAccountActionsComponent { // Safely access data with optional chaining this.navigationData = currentNavigation?.extras?.state?.data; - this.route.data.subscribe((data: { actionButtonData: any }) => { + this.route.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { actionButtonData: any }) => { this.actionButtonData = data.actionButtonData ? data.actionButtonData : {}; }); - this.route.params.subscribe((params) => { + this.route.params.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((params) => { this.actionName = params['action']; if (this.actionName === 'Change Loan Officer') { this.actionName = 'Assign Loan Officer'; diff --git a/src/app/loans/loans-view/loan-account-actions/make-repayment/make-repayment.component.html b/src/app/loans/loans-view/loan-account-actions/make-repayment/make-repayment.component.html index e9d127623b..06018405ef 100644 --- a/src/app/loans/loans-view/loan-account-actions/make-repayment/make-repayment.component.html +++ b/src/app/loans/loans-view/loan-account-actions/make-repayment/make-repayment.component.html @@ -103,44 +103,6 @@ -
- - {{ 'labels.inputs.Waive Penalties' | translate }} - -
- - @if (waivePenalties) { - @if (penalties.length > 0) { -
-
- - {{ 'labels.inputs.All' | translate }} - -
-
- @for (penalty of penalties; track penalty.id) { -
- - {{ 'labels.inputs.Penalty' | translate }} - {{ getPenaltyDisplayKey(penalty) | translate }} - {{ penalty.dueDate | dateFormat }} - {{ - penalty.amountOutstanding || penalty.amount || 0 | formatNumber - }} -
- } -
-
- } @else { -
- {{ 'labels.text.No penalties found' | translate }} -
- } - } - @if (showPaymentDetails) { {{ 'labels.inputs.Account' | translate }} # @@ -168,12 +130,6 @@ {{ 'labels.inputs.Note' | translate }} - - @if (showInterestRefundCheckbox()) { - - {{ 'labels.inputs.Skip Interest Refund Transaction Posting' | translate }} - - } diff --git a/src/app/loans/loans-view/loan-account-actions/make-repayment/make-repayment.component.ts b/src/app/loans/loans-view/loan-account-actions/make-repayment/make-repayment.component.ts index f9a556ccd9..b290362305 100644 --- a/src/app/loans/loans-view/loan-account-actions/make-repayment/make-repayment.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/make-repayment/make-repayment.component.ts @@ -8,7 +8,7 @@ /** Angular Imports */ import { ChangeDetectionStrategy, Component, OnInit, inject, ChangeDetectorRef } from '@angular/core'; -import { UntypedFormGroup, UntypedFormBuilder, Validators, UntypedFormControl } from '@angular/forms'; +import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; /** Custom Services */ import { Dates } from 'app/core/utils/dates'; @@ -16,11 +16,11 @@ import { Currency } from 'app/shared/models/general.model'; import { PenaltyManagementService } from 'app/loans/services/penalty-management.service'; import { InputAmountComponent } from '../../../../shared/input-amount/input-amount.component'; import { MatSlideToggle } from '@angular/material/slide-toggle'; -import { MatCheckbox } from '@angular/material/checkbox'; import { CdkTextareaAutosize } from '@angular/cdk/text-field'; import { FormatNumberPipe } from '../../../../pipes/format-number.pipe'; import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; import { LoanAccountActionsBaseComponent } from '../loan-account-actions-base.component'; +import { RepaymentForm } from 'app/loans/models/loan-form.model'; /** * Loan Make Repayment Component @@ -33,14 +33,13 @@ import { LoanAccountActionsBaseComponent } from '../loan-account-actions-base.co ...STANDALONE_SHARED_IMPORTS, InputAmountComponent, MatSlideToggle, - MatCheckbox, CdkTextareaAutosize, FormatNumberPipe ], changeDetection: ChangeDetectionStrategy.OnPush }) export class MakeRepaymentComponent extends LoanAccountActionsBaseComponent implements OnInit { - private formBuilder = inject(UntypedFormBuilder); + private formBuilder = inject(FormBuilder); private dateUtils = inject(Dates); private penaltyManagementService = inject(PenaltyManagementService); private cdr = inject(ChangeDetectorRef); @@ -64,7 +63,7 @@ export class MakeRepaymentComponent extends LoanAccountActionsBaseComponent impl /** Maximum Date allowed. */ maxDate = new Date(); /** Repayment Loan Form */ - repaymentLoanForm: UntypedFormGroup; + repaymentLoanForm: FormGroup | null = null; currency: Currency | null = null; command: string | null = null; @@ -101,26 +100,18 @@ export class MakeRepaymentComponent extends LoanAccountActionsBaseComponent impl * Creates the create close form. */ createRepaymentLoanForm() { - this.repaymentLoanForm = this.formBuilder.group({ - transactionDate: [ - this.settingsService.businessDate, - Validators.required - ], - externalId: '', - paymentTypeId: '', - note: '', - skipInterestRefund: [false] + this.repaymentLoanForm = this.formBuilder.group({ + transactionDate: new FormControl(this.settingsService.businessDate, Validators.required), + externalId: new FormControl(''), + paymentTypeId: new FormControl(''), + note: new FormControl(''), + skipInterestRefund: new FormControl(false), + transactionAmount: new FormControl(null) }); + this.updateTransactionAmountValidators(false); - if (this.isCapitalizedIncome()) { - this.repaymentLoanForm.addControl('transactionAmount', new UntypedFormControl('', [])); - this.updateTransactionAmountValidators(false); - } else { - this.repaymentLoanForm.addControl('transactionAmount', new UntypedFormControl('', [])); - this.updateTransactionAmountValidators(false); - } if (this.isCapitalizedIncome() || this.isBuyDownFee()) { - this.repaymentLoanForm.addControl('classificationId', new UntypedFormControl('')); + this.repaymentLoanForm.addControl('classificationId', new FormControl('')); } } @@ -138,11 +129,11 @@ export class MakeRepaymentComponent extends LoanAccountActionsBaseComponent impl addPaymentDetails() { this.showPaymentDetails = !this.showPaymentDetails; if (this.showPaymentDetails) { - this.repaymentLoanForm.addControl('accountNumber', new UntypedFormControl('')); - this.repaymentLoanForm.addControl('checkNumber', new UntypedFormControl('')); - this.repaymentLoanForm.addControl('routingCode', new UntypedFormControl('')); - this.repaymentLoanForm.addControl('receiptNumber', new UntypedFormControl('')); - this.repaymentLoanForm.addControl('bankNumber', new UntypedFormControl('')); + this.repaymentLoanForm.addControl('accountNumber', new FormControl('')); + this.repaymentLoanForm.addControl('checkNumber', new FormControl('')); + this.repaymentLoanForm.addControl('routingCode', new FormControl('')); + this.repaymentLoanForm.addControl('receiptNumber', new FormControl('')); + this.repaymentLoanForm.addControl('bankNumber', new FormControl('')); } else { this.repaymentLoanForm.removeControl('accountNumber'); this.repaymentLoanForm.removeControl('checkNumber'); @@ -190,113 +181,13 @@ export class MakeRepaymentComponent extends LoanAccountActionsBaseComponent impl }); } - /** - * Toggle waive penalties - * Following the addPaymentDetails() pattern - */ - toggleWaivePenalties() { - this.waivePenalties = !this.waivePenalties; - if (!this.waivePenalties) { - // Reset selections when toggling off - this.selectedPenalties = []; - this.selectAllPenalties = false; - this.updateTransactionAmountValidators(false); - this.recalculateTransactionAmount(); - } else { - this.recalculateTransactionAmount(); - } - } - - /** - * Toggle select all penalties - * Following the toggleSelects() pattern from loans-active-client-members - */ - toggleSelectAllPenalties() { - const result = this.penaltyManagementService.toggleSelectAllPenalties(this.selectAllPenalties, this.penalties); - this.selectAllPenalties = result.selectAllPenalties; - this.selectedPenalties = result.selectedPenalties; - this.recalculateTransactionAmount(); - } - - /** - * Toggle individual penalty selection - * Following the toggleSelect() pattern from loans-active-client-members - */ - togglePenaltySelection(penaltyId: number) { - const result = this.penaltyManagementService.togglePenaltySelection( - penaltyId, - this.selectedPenalties, - this.penalties - ); - this.selectedPenalties = result.selectedPenalties; - this.selectAllPenalties = result.selectAllPenalties; - this.recalculateTransactionAmount(); - } - - /** - * Check if penalty is selected - */ - isPenaltySelected(penaltyId: number): boolean { - return this.penaltyManagementService.isPenaltySelected(penaltyId, this.selectedPenalties); - } - - /** - * Get penalty display key or plain text for translation/output - * Normalizes common backend values (like MORA / labels.inputs.*) to translation keys - */ - getPenaltyDisplayKey(penalty: any): string { - return this.penaltyManagementService.getPenaltyDisplayKey(penalty); - } - - /** - * Recalculate transaction amount when penalties are waived - */ - recalculateTransactionAmount() { - const currentAmountValue = this.repaymentLoanForm.value.transactionAmount; - const currentAmount = - currentAmountValue !== undefined && currentAmountValue !== null - ? Number(currentAmountValue) - : Number(this.dataObject.amount ?? 0); - const baseAmount = isNaN(currentAmount) ? Number(this.dataObject.amount ?? 0) : currentAmount; - - if (!this.waivePenalties || this.selectedPenalties.length === 0) { - // Reset to original amount if no penalties selected - this.repaymentLoanForm.patchValue( - { - transactionAmount: baseAmount - }, - { emitEvent: false } - ); - return; - } - - // Calculate total waived amount - let totalWaived = 0; - this.selectedPenalties.forEach((penaltyId: number) => { - const penalty = this.penalties.find((p: any) => p.id === penaltyId); - if (penalty) { - totalWaived += penalty.amountOutstanding || penalty.amount || 0; - } - }); - - // Calculate new transaction amount - const newAmount = Math.max(0, baseAmount - totalWaived); - - // Allow zero when fully waived - this.updateTransactionAmountValidators(this.waivePenalties && newAmount === 0); - - this.repaymentLoanForm.patchValue( - { - transactionAmount: newAmount - }, - { emitEvent: false } - ); - } - /** * Update transaction amount validators to allow or disallow zero */ private updateTransactionAmountValidators(allowZero: boolean) { + if (!this.repaymentLoanForm) { + return; + } const validators = [ Validators.required, Validators.min(allowZero ? 0 : 0.001) @@ -310,7 +201,7 @@ export class MakeRepaymentComponent extends LoanAccountActionsBaseComponent impl /** Submits the repayment form */ submit() { - if (this.repaymentLoanForm.invalid || this.isSubmitting) { + if (!this.repaymentLoanForm || this.repaymentLoanForm.invalid || this.isSubmitting) { return; } this.isSubmitting = true; @@ -319,15 +210,14 @@ export class MakeRepaymentComponent extends LoanAccountActionsBaseComponent impl const repaymentLoanFormData = this.repaymentLoanForm.value; const locale = this.settingsService.language.code; const dateFormat = this.settingsService.dateFormat; - const prevTransactionDate: Date = this.repaymentLoanForm.value.transactionDate; - if (repaymentLoanFormData.transactionDate instanceof Date) { - repaymentLoanFormData.transactionDate = this.dateUtils.formatDate(prevTransactionDate, dateFormat); - } const data: any = { ...repaymentLoanFormData, dateFormat, locale }; + if (repaymentLoanFormData.transactionDate instanceof Date) { + data.transactionDate = this.dateUtils.formatDate(repaymentLoanFormData.transactionDate, dateFormat); + } data['transactionAmount'] = data['transactionAmount'] * 1; if (repaymentLoanFormData.skipInterestRefund) { data.interestRefundCalculation = false; diff --git a/src/app/loans/loans-view/loan-account-actions/prepay-loan/prepay-loan.component.ts b/src/app/loans/loans-view/loan-account-actions/prepay-loan/prepay-loan.component.ts index 39506ed541..201a17681f 100644 --- a/src/app/loans/loans-view/loan-account-actions/prepay-loan/prepay-loan.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/prepay-loan/prepay-loan.component.ts @@ -7,7 +7,8 @@ */ /** Angular Imports */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { UntypedFormGroup, UntypedFormBuilder, Validators, UntypedFormControl } from '@angular/forms'; /** Custom Services */ @@ -37,6 +38,7 @@ import { LoanAccountActionsBaseComponent } from '../loan-account-actions-base.co changeDetection: ChangeDetectionStrategy.OnPush }) export class PrepayLoanComponent extends LoanAccountActionsBaseComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private formBuilder = inject(UntypedFormBuilder); private dateUtils = inject(Dates); @@ -121,16 +123,19 @@ export class PrepayLoanComponent extends LoanAccountActionsBaseComponent impleme this.prepayLoanForm.patchValue({ transactionAmount: this.dataObject.amount }); - this.prepayLoanForm.get('transactionDate').valueChanges.subscribe((transactionDate: string) => { - const prepayDate = this.dateUtils.formatDate(transactionDate, this.settingsService.dateFormat); + this.prepayLoanForm + .get('transactionDate') + .valueChanges.pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((transactionDate: string) => { + const prepayDate = this.dateUtils.formatDate(transactionDate, this.settingsService.dateFormat); - this.loanService.getLoanPrepayLoanActionTemplate(this.loanId, prepayDate).subscribe((response: any) => { - this.prepayData = response; - this.prepayLoanForm.patchValue({ - transactionAmount: this.prepayData.amount + this.loanService.getLoanPrepayLoanActionTemplate(this.loanId, prepayDate).subscribe((response: any) => { + this.prepayData = response; + this.prepayLoanForm.patchValue({ + transactionAmount: this.prepayData.amount + }); }); }); - }); } /** diff --git a/src/app/loans/loans-view/loan-account-dashboard/loan-account-dashboard.component.ts b/src/app/loans/loans-view/loan-account-dashboard/loan-account-dashboard.component.ts index 55c0a8c68e..951be0e362 100644 --- a/src/app/loans/loans-view/loan-account-dashboard/loan-account-dashboard.component.ts +++ b/src/app/loans/loans-view/loan-account-dashboard/loan-account-dashboard.component.ts @@ -9,16 +9,17 @@ import { ChangeDetectionStrategy, Component, + DestroyRef, OnInit, AfterViewInit, + OnDestroy, ViewChild, ElementRef, - inject, - OnDestroy + inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; -import { Subscription } from 'rxjs'; import { MatCard, MatCardHeader, MatCardContent, MatCardTitle } from '@angular/material/card'; import { Chart, registerables } from 'chart.js'; import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; @@ -44,10 +45,9 @@ Chart.register(...registerables); changeDetection: ChangeDetectionStrategy.OnPush }) export class LoanAccountDashboardComponent implements OnInit, AfterViewInit, OnDestroy { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); private translate = inject(TranslateService); - private langChangeSubscription?: Subscription; - private routeDataSubscription?: Subscription; @ViewChild('statusChart', { static: false }) statusChartCanvas!: ElementRef; @ViewChild('paymentsChart', { static: false }) paymentsChartCanvas!: ElementRef; @@ -71,7 +71,7 @@ export class LoanAccountDashboardComponent implements OnInit, AfterViewInit, OnD ngOnInit(): void { this.loanId = this.route.parent?.snapshot.paramMap.get('loanId') || ''; - this.routeDataSubscription = this.route.parent!.data.subscribe((data: { loanDetailsData: any }) => { + this.route.parent!.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loanDetailsData: any }) => { if (data.loanDetailsData) { this.loanData = data.loanDetailsData; this.calculateMetrics(); @@ -82,7 +82,7 @@ export class LoanAccountDashboardComponent implements OnInit, AfterViewInit, OnD } }); - this.langChangeSubscription = this.translate.onLangChange.subscribe(() => { + this.translate.onLangChange.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => { if (this.statusChart) { this.createStatusChart(); } @@ -332,12 +332,6 @@ export class LoanAccountDashboardComponent implements OnInit, AfterViewInit, OnD clearTimeout(this.initTimeout); this.initTimeout = null; } - if (this.routeDataSubscription) { - this.routeDataSubscription.unsubscribe(); - } - if (this.langChangeSubscription) { - this.langChangeSubscription.unsubscribe(); - } if (this.statusChart) { this.statusChart.destroy(); } diff --git a/src/app/loans/loans-view/loan-collateral-tab/loan-collateral-tab.component.ts b/src/app/loans/loans-view/loan-collateral-tab/loan-collateral-tab.component.ts index bf1285d049..2409e108a8 100644 --- a/src/app/loans/loans-view/loan-collateral-tab/loan-collateral-tab.component.ts +++ b/src/app/loans/loans-view/loan-collateral-tab/loan-collateral-tab.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute, RouterLink } from '@angular/router'; import { MatTable, @@ -44,6 +45,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; changeDetection: ChangeDetectionStrategy.OnPush }) export class LoanCollateralTabComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); /** Loan Collateral Details */ @@ -63,7 +65,7 @@ export class LoanCollateralTabComponent implements OnInit { * @param {ActivatedRoute} route Activated Route. */ constructor() { - this.route.data.subscribe((data: { loanCollaterals: any }) => { + this.route.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loanCollaterals: any }) => { this.loanCollaterals = data.loanCollaterals; }); } diff --git a/src/app/loans/loans-view/loan-deferred-income-tab/loan-deferred-income-tab.component.ts b/src/app/loans/loans-view/loan-deferred-income-tab/loan-deferred-income-tab.component.ts index d27d8eb5c0..8b9d9a4bb6 100644 --- a/src/app/loans/loans-view/loan-deferred-income-tab/loan-deferred-income-tab.component.ts +++ b/src/app/loans/loans-view/loan-deferred-income-tab/loan-deferred-income-tab.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatCell, MatCellDef, @@ -45,6 +46,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; changeDetection: ChangeDetectionStrategy.OnPush }) export class LoanDeferredIncomeTabComponent { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); capitalizedIncomeData: LoanCapitalizedIncomeData[] = []; @@ -62,15 +64,17 @@ export class LoanDeferredIncomeTabComponent { this.loanId = this.route.parent.parent.snapshot.params['loanId']; this.capitalizedIncomeData = []; - this.route.parent.data.subscribe((data: { loanDeferredIncomeData: LoanDeferredIncomeData }) => { - data.loanDeferredIncomeData.capitalizedIncomeData.forEach((item: LoanCapitalizedIncomeData) => { - this.capitalizedIncomeData.push({ - amount: item.amount, - amortizedAmount: item.amortizedAmount ?? 0, - unrecognizedAmount: item.unrecognizedAmount ?? 0, - amountAdjustment: item.amountAdjustment ?? 0 + this.route.parent.data + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((data: { loanDeferredIncomeData: LoanDeferredIncomeData }) => { + data.loanDeferredIncomeData.capitalizedIncomeData.forEach((item: LoanCapitalizedIncomeData) => { + this.capitalizedIncomeData.push({ + amount: item.amount, + amortizedAmount: item.amortizedAmount ?? 0, + unrecognizedAmount: item.unrecognizedAmount ?? 0, + amountAdjustment: item.amountAdjustment ?? 0 + }); }); }); - }); } } diff --git a/src/app/loans/loans-view/loan-delinquency-tags-tab/loan-delinquency-tags-tab.component.ts b/src/app/loans/loans-view/loan-delinquency-tags-tab/loan-delinquency-tags-tab.component.ts index 742d2a6c1b..2c0bbb2a1f 100644 --- a/src/app/loans/loans-view/loan-delinquency-tags-tab/loan-delinquency-tags-tab.component.ts +++ b/src/app/loans/loans-view/loan-delinquency-tags-tab/loan-delinquency-tags-tab.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; @@ -74,6 +75,7 @@ import { ProductsService } from 'app/products/products.service'; changeDetection: ChangeDetectionStrategy.OnPush }) export class LoanDelinquencyTagsTabComponent extends LoanProductBaseComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); private loansServices = inject(LoansService); private productsServices = inject(ProductsService); @@ -128,28 +130,30 @@ export class LoanDelinquencyTagsTabComponent extends LoanProductBaseComponent im this.loanId = this.route.parent.parent.snapshot.params['loanId']; this.businessDate = this.settingsService.businessDate; - this.route.parent.data.subscribe( - (data: { - loanDelinquencyTagsData: LoanDelinquencyTags[]; - loanDelinquencyData: any; - loanDelinquencyActions: LoanDelinquencyAction[]; - wcLoanDelinquencyRangeSchedule: DelinquencyRangeSchedule[]; - }) => { - this.loanDelinquencyTags = data.loanDelinquencyTagsData; - this.setLoanDelinquencyAction(data.loanDelinquencyActions || []); - const loanDelinquencyDataResponse = data.loanDelinquencyData ?? null; - const loanDelinquencyData: DelinquentData | null = loanDelinquencyDataResponse?.delinquent || null; - this.currency = loanDelinquencyDataResponse?.currency; - this.installmentLevelDelinquency = []; - if (loanDelinquencyData != null) { - this.installmentLevelDelinquency = loanDelinquencyData.installmentLevelDelinquency || []; - } - if (loanDelinquencyDataResponse?.product) { - this.loanProductId = loanDelinquencyDataResponse.product.id; + this.route.parent.data + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe( + (data: { + loanDelinquencyTagsData: LoanDelinquencyTags[]; + loanDelinquencyData: any; + loanDelinquencyActions: LoanDelinquencyAction[]; + wcLoanDelinquencyRangeSchedule: DelinquencyRangeSchedule[]; + }) => { + this.loanDelinquencyTags = data.loanDelinquencyTagsData; + this.setLoanDelinquencyAction(data.loanDelinquencyActions || []); + const loanDelinquencyDataResponse = data.loanDelinquencyData ?? null; + const loanDelinquencyData: DelinquentData | null = loanDelinquencyDataResponse?.delinquent || null; + this.currency = loanDelinquencyDataResponse?.currency; + this.installmentLevelDelinquency = []; + if (loanDelinquencyData != null) { + this.installmentLevelDelinquency = loanDelinquencyData.installmentLevelDelinquency || []; + } + if (loanDelinquencyDataResponse?.product) { + this.loanProductId = loanDelinquencyDataResponse.product.id; + } + this.wcLoanDelinquencyRangeSchedule = data.wcLoanDelinquencyRangeSchedule; } - this.wcLoanDelinquencyRangeSchedule = data.wcLoanDelinquencyRangeSchedule; - } - ); + ); } ngOnInit(): void { diff --git a/src/app/loans/loans-view/loan-documents-tab/loan-documents-tab.component.ts b/src/app/loans/loans-view/loan-documents-tab/loan-documents-tab.component.ts index 963aea442b..c788d4f127 100644 --- a/src/app/loans/loans-view/loan-documents-tab/loan-documents-tab.component.ts +++ b/src/app/loans/loans-view/loan-documents-tab/loan-documents-tab.component.ts @@ -7,7 +7,8 @@ */ /** Angular Imports */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute } from '@angular/router'; /** Custom Services */ @@ -31,6 +32,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; changeDetection: ChangeDetectionStrategy.OnPush }) export class LoanDocumentsTabComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); private loansService = inject(LoansService); private settingsService = inject(SettingsService); @@ -48,13 +50,13 @@ export class LoanDocumentsTabComponent implements OnInit { constructor() { this.entityId = this.route.parent.snapshot.params['loanId']; - this.route.data.subscribe((data: { loanDocuments: any }) => { + this.route.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loanDocuments: any }) => { this.getLoanDocumentsData(data.loanDocuments); }); } ngOnInit(): void { - this.route.parent.params.subscribe((params) => { + this.route.parent.params.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((params) => { this.entityId = params['loanId']; }); } diff --git a/src/app/loans/loans-view/loan-originators-tab/loan-originators-tab.component.ts b/src/app/loans/loans-view/loan-originators-tab/loan-originators-tab.component.ts index 94f891e9c6..5d88d3b7ac 100644 --- a/src/app/loans/loans-view/loan-originators-tab/loan-originators-tab.component.ts +++ b/src/app/loans/loans-view/loan-originators-tab/loan-originators-tab.component.ts @@ -5,7 +5,8 @@ * 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 { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatIconButton } from '@angular/material/button'; import { MatDialog } from '@angular/material/dialog'; import { @@ -52,6 +53,7 @@ import { LoanAccountTabBaseComponent } from '../loan-account-tab-base.component' changeDetection: ChangeDetectionStrategy.OnPush }) export class LoanOriginatorsTabComponent extends LoanAccountTabBaseComponent { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); private loansService = inject(LoansService); private translateService = inject(TranslateService); @@ -77,10 +79,12 @@ export class LoanOriginatorsTabComponent extends LoanAccountTabBaseComponent { super(); this.clientId = this.route.parent.parent.snapshot.paramMap.get('clientId'); this.loanId = this.route.parent?.parent?.snapshot.paramMap.get('loanId'); - this.route.parent.parent.data.subscribe((data: { loanDetailsData: any }) => { - this.loanStatus = data.loanDetailsData.status; - }); - this.route.parent.data.subscribe((data: { loanOriginatorsData: any }) => { + this.route.parent.parent.data + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((data: { loanDetailsData: any }) => { + this.loanStatus = data.loanDetailsData.status; + }); + this.route.parent.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loanOriginatorsData: any }) => { this.loanOriginatorsData = data.loanOriginatorsData.originators; }); } diff --git a/src/app/loans/loans-view/loan-term-variations-tab/loan-term-variations-tab.component.ts b/src/app/loans/loans-view/loan-term-variations-tab/loan-term-variations-tab.component.ts index 88a818c5ee..e79bb17d51 100644 --- a/src/app/loans/loans-view/loan-term-variations-tab/loan-term-variations-tab.component.ts +++ b/src/app/loans/loans-view/loan-term-variations-tab/loan-term-variations-tab.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute } from '@angular/router'; import { Dates } from 'app/core/utils/dates'; @@ -61,6 +62,7 @@ import { LoanAccountTabBaseComponent } from '../loan-account-tab-base.component' changeDetection: ChangeDetectionStrategy.OnPush }) export class LoanTermVariationsTabComponent extends LoanAccountTabBaseComponent { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); private dates = inject(Dates); private settingsService = inject(SettingsService); @@ -98,7 +100,7 @@ export class LoanTermVariationsTabComponent extends LoanAccountTabBaseComponent this.interestPausesData = []; this.clientId = this.route.parent.parent.snapshot.paramMap.get('clientId'); - this.route.parent.data.subscribe((data: { loanDetailsData: any }) => { + this.route.parent.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loanDetailsData: any }) => { this.loanId = data.loanDetailsData.id; this.loanTermVariationsData = []; data.loanDetailsData.loanTermVariations?.forEach((item: any) => { diff --git a/src/app/loans/loans-view/loan-tranche-details/loan-tranche-details.component.ts b/src/app/loans/loans-view/loan-tranche-details/loan-tranche-details.component.ts index ed3fff3033..4990a706cf 100644 --- a/src/app/loans/loans-view/loan-tranche-details/loan-tranche-details.component.ts +++ b/src/app/loans/loans-view/loan-tranche-details/loan-tranche-details.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute } from '@angular/router'; import { Dates } from 'app/core/utils/dates'; @@ -65,6 +66,7 @@ import { LoanAccountTabBaseComponent } from '../loan-account-tab-base.component' changeDetection: ChangeDetectionStrategy.OnPush }) export class LoanTrancheDetailsComponent extends LoanAccountTabBaseComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); private dialog = inject(MatDialog); private loanServices = inject(LoansService); @@ -101,7 +103,7 @@ export class LoanTrancheDetailsComponent extends LoanAccountTabBaseComponent imp */ constructor() { super(); - this.route.parent.data.subscribe((data: { loanDetailsData: any }) => { + this.route.parent.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loanDetailsData: any }) => { this.loanId = data.loanDetailsData.id; this.loanDetails = data.loanDetailsData; this.disallowExpectedDisbursements = this.loanDetails.disallowExpectedDisbursements || false; diff --git a/src/app/loans/loans-view/loans-view.component.ts b/src/app/loans/loans-view/loans-view.component.ts index 2f520c35c1..16507e5991 100644 --- a/src/app/loans/loans-view/loans-view.component.ts +++ b/src/app/loans/loans-view/loans-view.component.ts @@ -7,7 +7,8 @@ */ /** Angular Imports */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute, NavigationExtras, RouterLinkActive, RouterOutlet } from '@angular/router'; import { MatDialog } from '@angular/material/dialog'; @@ -79,6 +80,7 @@ import { LoanProductBaseComponent } from 'app/products/loan-products/common/loan changeDetection: ChangeDetectionStrategy.OnPush }) export class LoansViewComponent extends LoanProductBaseComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); loansService = inject(LoansService); private translateService = inject(TranslateService); @@ -118,8 +120,9 @@ export class LoansViewComponent extends LoanProductBaseComponent implements OnIn const loansService = this.loansService; this.loanProductService.initialize(LoanProductBaseComponent.resolveProductTypeDefault(this.route, 'loan')); - this.route.data.subscribe( - (data: { loanDetailsData: any; loanDatatables: any; loanArrearsDelinquencyConfig: any }) => { + this.route.data + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((data: { loanDetailsData: any; loanDatatables: any; loanArrearsDelinquencyConfig: any }) => { this.loanDetailsData = data.loanDetailsData; if (!this.loanDetailsData.loanProductName) { this.loanDetailsData.loanProductName = this.loanDetailsData.product.name; @@ -146,13 +149,12 @@ export class LoansViewComponent extends LoanProductBaseComponent implements OnIn this.filterDatatablesByProduct(); } this.setConditionalButtons(); - } - ); + }); this.loanId = this.route.snapshot.params['loanId']; } ngOnInit() { - this.route.params.subscribe((params) => { + this.route.params.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((params) => { if (this.loanId != params['loanId']) { this.loanId = params['loanId']; this.reload(); diff --git a/src/app/loans/loans-view/notes-tab/notes-tab.component.ts b/src/app/loans/loans-view/notes-tab/notes-tab.component.ts index 0216885641..284c689dad 100644 --- a/src/app/loans/loans-view/notes-tab/notes-tab.component.ts +++ b/src/app/loans/loans-view/notes-tab/notes-tab.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute } from '@angular/router'; /** Custom Components */ @@ -28,6 +29,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; changeDetection: ChangeDetectionStrategy.OnPush }) export class NotesTabComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); private loansService = inject(LoansService); private authenticationService = inject(AuthenticationService); @@ -40,13 +42,13 @@ export class NotesTabComponent implements OnInit { const savedCredentials = this.authenticationService.getCredentials(); this.username = savedCredentials.username; this.entityId = this.route.parent.snapshot.params['loanId']; - this.route.data.subscribe((data: { loanNotes: any }) => { + this.route.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loanNotes: any }) => { this.entityNotes = data.loanNotes; }); } ngOnInit(): void { - this.route.parent.params.subscribe((params) => { + this.route.parent.params.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((params) => { this.entityId = params['loanId']; }); } diff --git a/src/app/loans/loans-view/original-schedule-tab/original-schedule-tab.component.ts b/src/app/loans/loans-view/original-schedule-tab/original-schedule-tab.component.ts index ed2c1fa926..070ad33482 100644 --- a/src/app/loans/loans-view/original-schedule-tab/original-schedule-tab.component.ts +++ b/src/app/loans/loans-view/original-schedule-tab/original-schedule-tab.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute } from '@angular/router'; import { Currency } from 'app/shared/models/general.model'; import { @@ -59,6 +60,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; changeDetection: ChangeDetectionStrategy.OnPush }) export class OriginalScheduleTabComponent { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); /** Loan Details Data */ @@ -82,7 +84,7 @@ export class OriginalScheduleTabComponent { * @param {ActivatedRoute} route Activated Route. */ constructor() { - this.route.parent.data.subscribe((data: { loanDetailsData: any }) => { + this.route.parent.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loanDetailsData: any }) => { this.currency = data.loanDetailsData.currency; this.originalScheduleDetails = data.loanDetailsData.originalSchedule; }); diff --git a/src/app/loans/loans-view/overdue-charges-tab/overdue-charges-tab.component.ts b/src/app/loans/loans-view/overdue-charges-tab/overdue-charges-tab.component.ts index 66961ce584..622cfa2dc9 100644 --- a/src/app/loans/loans-view/overdue-charges-tab/overdue-charges-tab.component.ts +++ b/src/app/loans/loans-view/overdue-charges-tab/overdue-charges-tab.component.ts @@ -7,7 +7,8 @@ */ /** Angular Imports */ -import { ChangeDetectionStrategy, Component, OnInit, ViewChild, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, ViewChild, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort, MatSortHeader } from '@angular/material/sort'; import { @@ -54,6 +55,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; changeDetection: ChangeDetectionStrategy.OnPush }) export class OverdueChargesTabComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); /** Stores the resolved loan data */ @@ -81,7 +83,7 @@ export class OverdueChargesTabComponent implements OnInit { * @param {ActivatedRoute} route Activated Route. */ constructor() { - this.route.parent.data.subscribe((data: { loanDetailsData: any }) => { + this.route.parent.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loanDetailsData: any }) => { this.loanDetails = data.loanDetailsData; }); } diff --git a/src/app/loans/loans-view/reschedule-loan-tab/reschedule-loan-tab.component.ts b/src/app/loans/loans-view/reschedule-loan-tab/reschedule-loan-tab.component.ts index ad13f6dd75..97ef7e0763 100644 --- a/src/app/loans/loans-view/reschedule-loan-tab/reschedule-loan-tab.component.ts +++ b/src/app/loans/loans-view/reschedule-loan-tab/reschedule-loan-tab.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, Input, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, Input, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; @@ -60,6 +61,7 @@ import { LoanAccountTabBaseComponent } from '../loan-account-tab-base.component' changeDetection: ChangeDetectionStrategy.OnPush }) export class RescheduleLoanTabComponent extends LoanAccountTabBaseComponent { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); private loansServices = inject(LoansService); private settingsService = inject(SettingsService); @@ -82,7 +84,7 @@ export class RescheduleLoanTabComponent extends LoanAccountTabBaseComponent { constructor() { super(); this.clientId = this.route.parent.parent.snapshot.paramMap.get('clientId'); - this.route.parent.data.subscribe((data: { loanRescheduleData: any }) => { + this.route.parent.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loanRescheduleData: any }) => { this.loanRescheduleData = data.loanRescheduleData; }); } diff --git a/src/app/loans/loans-view/standing-instructions-tab/standing-instructions-tab.component.ts b/src/app/loans/loans-view/standing-instructions-tab/standing-instructions-tab.component.ts index 8cc274b508..23962f4651 100644 --- a/src/app/loans/loans-view/standing-instructions-tab/standing-instructions-tab.component.ts +++ b/src/app/loans/loans-view/standing-instructions-tab/standing-instructions-tab.component.ts @@ -7,7 +7,8 @@ */ /** Angular Imports */ -import { ChangeDetectionStrategy, Component, OnInit, ViewChild, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, ViewChild, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatDialog } from '@angular/material/dialog'; import { MatTableDataSource, @@ -60,6 +61,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; changeDetection: ChangeDetectionStrategy.OnPush }) export class StandingInstructionsTabComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); private loansService = inject(LoansService); private dialog = inject(MatDialog); @@ -92,7 +94,7 @@ export class StandingInstructionsTabComponent implements OnInit { * @param {SettingsService} settingsService Settings Service */ constructor() { - this.route.parent.data.subscribe((data: { loanDetailsData: any }) => { + this.route.parent.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loanDetailsData: any }) => { this.loanDetailsData = data.loanDetailsData; }); } diff --git a/src/app/loans/loans-view/transactions-tab/transactions-tab.component.ts b/src/app/loans/loans-view/transactions-tab/transactions-tab.component.ts index 6393e25178..bc5f741850 100644 --- a/src/app/loans/loans-view/transactions-tab/transactions-tab.component.ts +++ b/src/app/loans/loans-view/transactions-tab/transactions-tab.component.ts @@ -6,7 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ChangeDetectionStrategy, Component, OnInit, ViewChild, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, ViewChild, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute } from '@angular/router'; import { UntypedFormControl, Validators } from '@angular/forms'; import { MatPaginator } from '@angular/material/paginator'; @@ -82,6 +83,7 @@ import { LoanProductBaseComponent } from 'app/products/loan-products/common/loan changeDetection: ChangeDetectionStrategy.OnPush }) export class TransactionsTabComponent extends LoanProductBaseComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); private dateUtils = inject(Dates); private dialog = inject(MatDialog); @@ -147,10 +149,12 @@ export class TransactionsTabComponent extends LoanProductBaseComponent implement */ constructor() { super(); - this.route.parent.parent.data.subscribe((data: { loanDetailsData: any }) => { - this.loanDetailsData = data.loanDetailsData; - this.status = data.loanDetailsData.status.value; - }); + this.route.parent.parent.data + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((data: { loanDetailsData: any }) => { + this.loanDetailsData = data.loanDetailsData; + this.status = data.loanDetailsData.status.value; + }); this.loanId = this.route.parent.parent.snapshot.params['loanId']; } diff --git a/src/app/loans/loans-view/transactions/edit-transaction/edit-transaction.component.ts b/src/app/loans/loans-view/transactions/edit-transaction/edit-transaction.component.ts index bd53e8beeb..25ebaf0d34 100644 --- a/src/app/loans/loans-view/transactions/edit-transaction/edit-transaction.component.ts +++ b/src/app/loans/loans-view/transactions/edit-transaction/edit-transaction.component.ts @@ -7,7 +7,8 @@ */ /** Angular Imports */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { UntypedFormGroup, UntypedFormBuilder, Validators, UntypedFormControl } from '@angular/forms'; import { Dates } from 'app/core/utils/dates'; @@ -34,6 +35,7 @@ import { LoanAccountActionsBaseComponent } from '../../loan-account-actions/loan changeDetection: ChangeDetectionStrategy.OnPush }) export class EditTransactionComponent extends LoanAccountActionsBaseComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private formBuilder = inject(UntypedFormBuilder); private dateUtils = inject(Dates); private loansService = inject(LoansService); @@ -71,13 +73,15 @@ export class EditTransactionComponent extends LoanAccountActionsBaseComponent im */ constructor() { super(); - this.route.data.subscribe((data: { loansAccountTransactionTemplate: any }) => { - this.transactionTemplateData = data.loansAccountTransactionTemplate; - if (data.loansAccountTransactionTemplate.currency) { - this.currency = data.loansAccountTransactionTemplate.currency; - } - this.paymentTypeOptions = this.transactionTemplateData.paymentTypeOptions; - }); + this.route.data + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((data: { loansAccountTransactionTemplate: any }) => { + this.transactionTemplateData = data.loansAccountTransactionTemplate; + if (data.loansAccountTransactionTemplate.currency) { + this.currency = data.loansAccountTransactionTemplate.currency; + } + this.paymentTypeOptions = this.transactionTemplateData.paymentTypeOptions; + }); this.loanAccountId = this.route.snapshot.params['loanId']; } diff --git a/src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.ts b/src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.ts index 3d5acf7625..4f8d73797d 100644 --- a/src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.ts +++ b/src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.ts @@ -7,7 +7,8 @@ */ /** Angular Imports */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { DomSanitizer } from '@angular/platform-browser'; import { UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms'; import { ActivatedRoute, RouterLink } from '@angular/router'; @@ -33,6 +34,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; changeDetection: ChangeDetectionStrategy.OnPush }) export class ExportTransactionsComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private sanitizer = inject(DomSanitizer); private reportsService = inject(ReportsService); private formBuilder = inject(UntypedFormBuilder); @@ -63,9 +65,11 @@ export class ExportTransactionsComponent implements OnInit { * @param {SettingsService} settingsService Settings Service */ constructor() { - this.route.parent.parent.data.subscribe((data: { loanDetailsData: any }) => { - this.loansAccountId = data.loanDetailsData.accountNo; - }); + this.route.parent.parent.data + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((data: { loanDetailsData: any }) => { + this.loansAccountId = data.loanDetailsData.accountNo; + }); } ngOnInit() { diff --git a/src/app/loans/loans-view/transactions/view-reciept/view-reciept.component.ts b/src/app/loans/loans-view/transactions/view-reciept/view-reciept.component.ts index 98332789d4..828ac16d5b 100644 --- a/src/app/loans/loans-view/transactions/view-reciept/view-reciept.component.ts +++ b/src/app/loans/loans-view/transactions/view-reciept/view-reciept.component.ts @@ -7,7 +7,8 @@ */ /** Angular Imports */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { DomSanitizer } from '@angular/platform-browser'; import { ActivatedRoute, RouterLink } from '@angular/router'; import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @@ -27,6 +28,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; changeDetection: ChangeDetectionStrategy.OnPush }) export class ViewRecieptComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private sanitizer = inject(DomSanitizer); private route = inject(ActivatedRoute); @@ -41,7 +43,7 @@ export class ViewRecieptComponent implements OnInit { * @param {ActivatedRoute} route Activated Route */ constructor() { - this.route.data.subscribe((data: { loansTransactionReciept: any }) => { + this.route.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loansTransactionReciept: any }) => { this.transactionRecieptData = data.loansTransactionReciept; }); } diff --git a/src/app/loans/loans-view/transactions/view-transaction/view-transaction.component.ts b/src/app/loans/loans-view/transactions/view-transaction/view-transaction.component.ts index dc14397431..3334add663 100644 --- a/src/app/loans/loans-view/transactions/view-transaction/view-transaction.component.ts +++ b/src/app/loans/loans-view/transactions/view-transaction/view-transaction.component.ts @@ -7,7 +7,8 @@ */ /** Angular Imports */ -import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatDialog } from '@angular/material/dialog'; /** Custom Services */ @@ -79,6 +80,7 @@ import { LoanAccountActionsBaseComponent } from '../../loan-account-actions/loan changeDetection: ChangeDetectionStrategy.OnPush }) export class ViewTransactionComponent extends LoanAccountActionsBaseComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private loansService = inject(LoansService); private dateUtils = inject(Dates); dialog = inject(MatDialog); @@ -122,7 +124,7 @@ export class ViewTransactionComponent extends LoanAccountActionsBaseComponent im */ constructor() { super(); - this.route.data.subscribe((data: { loansAccountTransaction: any }) => { + this.route.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loansAccountTransaction: any }) => { this.transactionData = data.loansAccountTransaction; this.transactionType = this.transactionData.type; this.allowEdition = diff --git a/src/app/loans/loans-view/view-charge/view-charge.component.ts b/src/app/loans/loans-view/view-charge/view-charge.component.ts index bd6243b29d..d797fffe63 100644 --- a/src/app/loans/loans-view/view-charge/view-charge.component.ts +++ b/src/app/loans/loans-view/view-charge/view-charge.component.ts @@ -7,7 +7,8 @@ */ /** Angular Imports */ -import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute } from '@angular/router'; import { MatDialog } from '@angular/material/dialog'; @@ -50,6 +51,7 @@ import { LoanAccountTabBaseComponent } from '../loan-account-tab-base.component' changeDetection: ChangeDetectionStrategy.OnPush }) export class ViewChargeComponent extends LoanAccountTabBaseComponent { + private readonly destroyRef = inject(DestroyRef); private loansService = inject(LoansService); private route = inject(ActivatedRoute); private dateUtils = inject(Dates); @@ -75,12 +77,14 @@ export class ViewChargeComponent extends LoanAccountTabBaseComponent { */ constructor() { super(); - this.route.data.subscribe((data: { loansAccountCharge: any; loanDetailsData: any }) => { - this.chargeData = data.loansAccountCharge; - this.allowPayCharge = this.chargeData.chargePayable && !this.chargeData.paid; - this.allowWaive = !this.chargeData.chargeTimeType.waived; - this.loansAccountData = data.loanDetailsData; - }); + this.route.data + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((data: { loansAccountCharge: any; loanDetailsData: any }) => { + this.chargeData = data.loansAccountCharge; + this.allowPayCharge = this.chargeData.chargePayable && !this.chargeData.paid; + this.allowWaive = !this.chargeData.chargeTimeType.waived; + this.loansAccountData = data.loanDetailsData; + }); } /** diff --git a/src/app/loans/loans-view/working-capital/loan-balances-tab/loan-balances-tab.component.ts b/src/app/loans/loans-view/working-capital/loan-balances-tab/loan-balances-tab.component.ts index ec323f8f07..b05ea0c593 100644 --- a/src/app/loans/loans-view/working-capital/loan-balances-tab/loan-balances-tab.component.ts +++ b/src/app/loans/loans-view/working-capital/loan-balances-tab/loan-balances-tab.component.ts @@ -7,7 +7,8 @@ */ import { CurrencyPipe } from '@angular/common'; -import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DestroyRef, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute } from '@angular/router'; import { FormatNumberPipe } from '@pipes/format-number.pipe'; import { WorkingCapitalBalances } from 'app/loans/models/working-capital/working-capital-loan-account.model'; @@ -26,6 +27,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; changeDetection: ChangeDetectionStrategy.OnPush }) export class LoanBalancesTabComponent extends LoanProductBaseComponent { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); loanBalances: WorkingCapitalBalances | null = null; @@ -33,7 +35,7 @@ export class LoanBalancesTabComponent extends LoanProductBaseComponent { constructor() { super(); - this.route.parent.data.subscribe((data: { loanDetailsData: any }) => { + this.route.parent.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { loanDetailsData: any }) => { this.currencyCode = data.loanDetailsData.currency.code; this.loanBalances = data.loanDetailsData.balance; }); diff --git a/src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.ts b/src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.ts index a5ad247d69..4e1682fd4b 100644 --- a/src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.ts +++ b/src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.ts @@ -5,7 +5,8 @@ * 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 { Component, inject, OnInit } from '@angular/core'; +import { Component, DestroyRef, inject, OnInit } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; import { MatTable, @@ -50,6 +51,7 @@ import { InputBase } from 'app/shared/form-dialog/formfield/model/input-base'; ] }) export class LoanPeriodPaymentRatesComponent implements OnInit { + private readonly destroyRef = inject(DestroyRef); private route = inject(ActivatedRoute); private dialog = inject(MatDialog); private translateService = inject(TranslateService); @@ -73,9 +75,11 @@ export class LoanPeriodPaymentRatesComponent implements OnInit { ngOnInit(): void { this.loanId = this.route.parent.snapshot.params['loanId']; - this.route.data.subscribe((data: { loanPaymentRatesData: PeriodPaymentRateChange[] }) => { - this.loanPaymentRatesData = data.loanPaymentRatesData; - }); + this.route.data + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((data: { loanPaymentRatesData: PeriodPaymentRateChange[] }) => { + this.loanPaymentRatesData = data.loanPaymentRatesData; + }); } addPaymentRate(): void { diff --git a/src/app/loans/models/loan-form.model.ts b/src/app/loans/models/loan-form.model.ts new file mode 100644 index 0000000000..784c1ddb57 --- /dev/null +++ b/src/app/loans/models/loan-form.model.ts @@ -0,0 +1,24 @@ +/** + * 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 { FormControl } from '@angular/forms'; + +export interface RepaymentForm { + transactionDate: FormControl; + externalId: FormControl; + paymentTypeId: FormControl; + note: FormControl; + skipInterestRefund: FormControl; + transactionAmount: FormControl; + classificationId?: FormControl; + accountNumber?: FormControl; + checkNumber?: FormControl; + routingCode?: FormControl; + receiptNumber?: FormControl; + bankNumber?: FormControl; +}