216 lines
8.4 KiB
TypeScript
216 lines
8.4 KiB
TypeScript
/**
|
|
* 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 { Component, ViewChild, inject } from '@angular/core';
|
|
import { ActivatedRoute, Router } from '@angular/router';
|
|
import { LoansService } from '../loans.service';
|
|
import { LoansAccountDetailsStepComponent } from '../loans-account-stepper/loans-account-details-step/loans-account-details-step.component';
|
|
import { LoansAccountTermsStepComponent } from '../loans-account-stepper/loans-account-terms-step/loans-account-terms-step.component';
|
|
import { LoansAccountChargesStepComponent } from '../loans-account-stepper/loans-account-charges-step/loans-account-charges-step.component';
|
|
|
|
/** Custom Services */
|
|
import { SettingsService } from 'app/settings/settings.service';
|
|
import { Dates } from 'app/core/utils/dates';
|
|
import { MatStepper, MatStepperIcon, MatStep, MatStepLabel } from '@angular/material/stepper';
|
|
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
|
import { LoansAccountScheduleStepComponent } from '../loans-account-stepper/loans-account-schedule-step/loans-account-schedule-step.component';
|
|
import { LoansAccountPreviewStepComponent } from '../loans-account-stepper/loans-account-preview-step/loans-account-preview-step.component';
|
|
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
|
|
|
/**
|
|
* Edit Loans
|
|
*/
|
|
@Component({
|
|
selector: 'mifosx-edit-loans-account',
|
|
templateUrl: './edit-loans-account.component.html',
|
|
styleUrls: ['./edit-loans-account.component.scss'],
|
|
imports: [
|
|
...STANDALONE_SHARED_IMPORTS,
|
|
MatStepper,
|
|
MatStepperIcon,
|
|
FaIconComponent,
|
|
MatStep,
|
|
MatStepLabel,
|
|
LoansAccountDetailsStepComponent,
|
|
LoansAccountTermsStepComponent,
|
|
LoansAccountChargesStepComponent,
|
|
LoansAccountScheduleStepComponent,
|
|
LoansAccountPreviewStepComponent
|
|
]
|
|
})
|
|
export class EditLoansAccountComponent {
|
|
private route = inject(ActivatedRoute);
|
|
private router = inject(Router);
|
|
private dateUtils = inject(Dates);
|
|
private loansService = inject(LoansService);
|
|
private settingsService = inject(SettingsService);
|
|
|
|
@ViewChild(LoansAccountDetailsStepComponent, { static: true })
|
|
loansAccountDetailsStep: LoansAccountDetailsStepComponent;
|
|
@ViewChild(LoansAccountTermsStepComponent, { static: true }) loansAccountTermsStep: LoansAccountTermsStepComponent;
|
|
@ViewChild(LoansAccountChargesStepComponent, { static: true })
|
|
loansAccountChargesStep: LoansAccountChargesStepComponent;
|
|
|
|
loansAccountAndTemplate: any;
|
|
/** Loans Account Product Template */
|
|
loansAccountProductTemplate: any;
|
|
/** Collateral Options */
|
|
collateralOptions: any;
|
|
/** Loan Id */
|
|
loanId: any;
|
|
/** Currency Code */
|
|
currencyCode: string;
|
|
|
|
/**
|
|
* Sets loans account edit form.
|
|
* @param {route} ActivatedRoute Activated Route.
|
|
* @param {router} Router Router.
|
|
* @param {Dates} dateUtils Date Utils
|
|
* @param {loansService} LoansService Loans Service
|
|
* @param {SettingsService} settingsService Settings Service
|
|
*/
|
|
constructor() {
|
|
this.route.data.subscribe((data: { loansAccountAndTemplate: any }) => {
|
|
this.loansAccountAndTemplate = data.loansAccountAndTemplate;
|
|
});
|
|
this.loanId = this.route.snapshot.params['loanId'];
|
|
}
|
|
|
|
/**
|
|
* Sets loans account product template and collateral template
|
|
* @param {any} $event API response
|
|
*/
|
|
setTemplate($event: any) {
|
|
this.loansAccountProductTemplate = $event;
|
|
this.currencyCode = this.loansAccountProductTemplate.currency.code;
|
|
if (this.loansAccountProductTemplate.loanProductId) {
|
|
this.loansService
|
|
.getLoansCollateralTemplateResource(this.loansAccountProductTemplate.loanProductId)
|
|
.subscribe((response: any) => {
|
|
this.collateralOptions = response.loanCollateralOptions;
|
|
});
|
|
}
|
|
}
|
|
|
|
/** Get Loans Account Details Form Data */
|
|
get loansAccountDetailsForm() {
|
|
return this.loansAccountDetailsStep.loansAccountDetailsForm;
|
|
}
|
|
|
|
/** Get Loans Account Terms Form Data */
|
|
get loansAccountTermsForm() {
|
|
return this.loansAccountTermsStep.loansAccountTermsForm;
|
|
}
|
|
|
|
/** Checks wheter all the forms in different steps are valid and not pristine */
|
|
get loansAccountFormValidAndNotPristine() {
|
|
return (
|
|
this.loansAccountDetailsForm.valid &&
|
|
this.loansAccountTermsForm.valid &&
|
|
(!this.loansAccountDetailsForm.pristine ||
|
|
!this.loansAccountTermsForm.pristine ||
|
|
!this.loansAccountTermsStep.pristine ||
|
|
!this.loansAccountChargesStep.pristine)
|
|
);
|
|
}
|
|
|
|
/** Retrieves Data of all forms except Currency to submit the data */
|
|
get loansAccount() {
|
|
return {
|
|
...this.loansAccountDetailsStep.loansAccountDetails,
|
|
...this.loansAccountTermsStep.loansAccountTerms,
|
|
...this.loansAccountChargesStep.loansAccountCharges,
|
|
...this.loansAccountTermsStep.loanCollateral,
|
|
...this.loansAccountTermsStep.disbursementData
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Submits Data to create loan account
|
|
*/
|
|
submit() {
|
|
const locale = this.settingsService.language.code;
|
|
const dateFormat = this.settingsService.dateFormat;
|
|
const loanType = 'individual';
|
|
const uniqueCharges = new Map<number | string, any>();
|
|
(this.loansAccount.charges ?? []).forEach((charge: any) => {
|
|
const chargeId = charge.chargeId;
|
|
if (chargeId == null) {
|
|
return;
|
|
} // Skip malformed entries
|
|
uniqueCharges.set(chargeId, charge);
|
|
});
|
|
|
|
const loansAccountData = {
|
|
...this.loansAccount,
|
|
clientId: this.loansAccountAndTemplate.clientId,
|
|
charges: Array.from(uniqueCharges.values()).map((charge: any) => {
|
|
const result: any = {
|
|
chargeId: charge.chargeId,
|
|
amount: charge.amount,
|
|
dueDate: charge.dueDate && this.dateUtils.formatDate(charge.dueDate, dateFormat)
|
|
};
|
|
if (charge.id && charge.id !== charge.chargeId) {
|
|
result.id = charge.id;
|
|
}
|
|
return result;
|
|
}),
|
|
collateral: this.loansAccount.collateral.map((collateralEle: any) => ({
|
|
type: collateralEle.type,
|
|
value: collateralEle.value,
|
|
description: collateralEle.description
|
|
})),
|
|
disbursementData: this.loansAccount.disbursementData.map((item: any) => ({
|
|
expectedDisbursementDate: this.dateUtils.formatDate(item.expectedDisbursementDate, dateFormat),
|
|
principal: item.principal
|
|
})),
|
|
interestChargedFromDate: this.dateUtils.formatDate(this.loansAccount.interestChargedFromDate, dateFormat),
|
|
repaymentsStartingFromDate: this.dateUtils.formatDate(this.loansAccount.repaymentsStartingFromDate, dateFormat),
|
|
submittedOnDate: this.dateUtils.formatDate(this.loansAccount.submittedOnDate, dateFormat),
|
|
expectedDisbursementDate: this.dateUtils.formatDate(this.loansAccount.expectedDisbursementDate, dateFormat),
|
|
dateFormat,
|
|
locale,
|
|
loanType
|
|
};
|
|
delete loansAccountData.isValid;
|
|
if (loansAccountData.syncRepaymentsWithMeeting) {
|
|
loansAccountData.calendarId = this.loansAccountProductTemplate.calendarOptions[0].id;
|
|
delete loansAccountData.syncRepaymentsWithMeeting;
|
|
}
|
|
|
|
if (loansAccountData.recalculationRestFrequencyDate) {
|
|
loansAccountData.recalculationRestFrequencyDate = this.dateUtils.formatDate(
|
|
this.loansAccount.recalculationRestFrequencyDate,
|
|
dateFormat
|
|
);
|
|
}
|
|
|
|
if (loansAccountData.interestCalculationPeriodType === 0) {
|
|
loansAccountData.allowPartialPeriodInterestCalculation = false;
|
|
}
|
|
if (
|
|
!loansAccountData.isLoanProductLinkedToFloatingRate ||
|
|
loansAccountData.isLoanProductLinkedToFloatingRate === false
|
|
) {
|
|
delete loansAccountData.isFloatingInterestRate;
|
|
}
|
|
loansAccountData.principal = loansAccountData.principalAmount;
|
|
delete loansAccountData.principalAmount;
|
|
delete loansAccountData.multiDisburseLoan;
|
|
|
|
// In Fineract, the POST and PUT endpoints for /v1/loans have a typo in the field
|
|
// allowPartialPeriodInterestCalculation. Until that is fixed, we need to replace the field name in the payload.
|
|
loansAccountData.allowPartialPeriodInterestCalculation = loansAccountData.allowPartialPeriodInterestCalculation;
|
|
delete loansAccountData.allowPartialPeriodInterestCalculation;
|
|
|
|
this.loansService.updateLoansAccount(this.loanId, loansAccountData).subscribe((response: any) => {
|
|
this.router.navigate(['../'], { relativeTo: this.route });
|
|
});
|
|
}
|
|
}
|