WEB-331: Introduce loan reaging preview
This commit is contained in:
+8
-7
@@ -1,6 +1,7 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { ActivatedRoute, RouterLink } from '@angular/router';
|
||||
import { LoansService } from 'app/loans/loans.service';
|
||||
import { RepaymentSchedule } from 'app/loans/models/loan-account.model';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { RepaymentScheduleTabComponent } from '../../loans-view/repayment-schedule-tab/repayment-schedule-tab.component';
|
||||
@@ -23,15 +24,15 @@ export class LoansAccountScheduleStepComponent {
|
||||
/** Currency Code */
|
||||
@Input() currencyCode: string;
|
||||
/** Loans Account Template */
|
||||
@Input() loansAccountTemplate: any;
|
||||
@Input() loansAccountTemplate: Record<string, unknown>;
|
||||
/** Loans Account Product Template */
|
||||
@Input() loansAccountProductTemplate: any;
|
||||
@Input() loansAccountProductTemplate: { calendarOptions?: unknown };
|
||||
/** Loans Account Data */
|
||||
@Input() loansAccount: any;
|
||||
@Input() loansAccount: Record<string, unknown>;
|
||||
|
||||
repaymentScheduleDetails: any = { periods: [] };
|
||||
repaymentScheduleDetails: RepaymentSchedule | null = null;
|
||||
|
||||
loanId: any = null;
|
||||
loanId: string | null = null;
|
||||
|
||||
constructor(
|
||||
private loansService: LoansService,
|
||||
@@ -42,7 +43,7 @@ export class LoansAccountScheduleStepComponent {
|
||||
}
|
||||
|
||||
showRepaymentInfo(): void {
|
||||
this.repaymentScheduleDetails = { periods: [] };
|
||||
this.repaymentScheduleDetails = null;
|
||||
const locale = this.settingsService.language.code;
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
const payload = this.loansService.buildLoanRequestPayload(
|
||||
@@ -55,7 +56,7 @@ export class LoansAccountScheduleStepComponent {
|
||||
delete payload['enableInstallmentLevelDelinquency'];
|
||||
delete payload['externalId'];
|
||||
|
||||
this.loansService.calculateLoanSchedule(payload).subscribe((response: any) => {
|
||||
this.loansService.calculateLoanSchedule(payload).subscribe((response: RepaymentSchedule) => {
|
||||
this.repaymentScheduleDetails = response;
|
||||
});
|
||||
}
|
||||
|
||||
+77
-46
@@ -4,6 +4,7 @@ import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
import { LoansService } from 'app/loans/loans.service';
|
||||
import { EditableRepaymentSchedule, EditablePeriod, ScheduleChangeRecord } from 'app/loans/models/loan-account.model';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { ConfirmationDialogComponent } from 'app/shared/confirmation-dialog/confirmation-dialog.component';
|
||||
import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component';
|
||||
@@ -30,11 +31,9 @@ export class EditRepaymentScheduleComponent implements OnInit {
|
||||
/** Indicates If the Schedule has been validated */
|
||||
wasValidated = false;
|
||||
/** Stores the Repayment Schedule data */
|
||||
repaymentScheduleDetails: {
|
||||
periods: { period?: number; dueDate: string; totalDueForPeriod?: number; changed?: boolean }[];
|
||||
} | null = null;
|
||||
repaymentScheduleDetails: EditableRepaymentSchedule | null = null;
|
||||
/** Stores the Installments changed */
|
||||
repaymentScheduleChanges: any = {};
|
||||
repaymentScheduleChanges: Record<string, ScheduleChangeRecord> = {};
|
||||
|
||||
/**
|
||||
* @param {LoansService} systemService Loan Service.
|
||||
@@ -62,14 +61,23 @@ export class EditRepaymentScheduleComponent implements OnInit {
|
||||
}
|
||||
|
||||
getRepaymentSchedule(): void {
|
||||
this.loansService.getLoanAccountResource(this.loanId, 'repaymentSchedule').subscribe((response: any) => {
|
||||
this.repaymentScheduleDetails = response.repaymentSchedule;
|
||||
this.loansService.getLoanAccountResource(this.loanId, 'repaymentSchedule').subscribe({
|
||||
next: (response: { repaymentSchedule: EditableRepaymentSchedule }) => {
|
||||
this.repaymentScheduleDetails = response.repaymentSchedule;
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Failed to load repayment schedule:', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
applyPattern(): void {
|
||||
const periods: any = [];
|
||||
this.repaymentScheduleDetails['periods'].forEach((period: any) => {
|
||||
if (!this.repaymentScheduleDetails) {
|
||||
return;
|
||||
}
|
||||
|
||||
const periods: Array<{ idx: number; dueDate: string }> = [];
|
||||
this.repaymentScheduleDetails.periods.forEach((period: EditablePeriod) => {
|
||||
if (period.period) {
|
||||
periods.push({
|
||||
idx: period.period,
|
||||
@@ -106,27 +114,29 @@ export class EditRepaymentScheduleComponent implements OnInit {
|
||||
formfields: formfields
|
||||
};
|
||||
const addDialogRef = this.dialog.open(FormDialogComponent, { data });
|
||||
addDialogRef.afterClosed().subscribe((response: any) => {
|
||||
if (response.data) {
|
||||
const fromPeriod = response.data.value.fromPeriod;
|
||||
const toPeriod = response.data.value.toPeriod;
|
||||
const amount = response.data.value.amount;
|
||||
const periodsVariation: any = [];
|
||||
this.repaymentScheduleDetails['periods'].forEach((period: any) => {
|
||||
const dueDate = this.dateUtils.formatDate(period.dueDate, this.settingsService.dateFormat);
|
||||
if (period.period && fromPeriod <= period.period && toPeriod >= period.period) {
|
||||
if (period.totalDueForPeriod !== amount) {
|
||||
period.totalDueForPeriod = amount;
|
||||
this.repaymentScheduleChanges[dueDate] = { dueDate: dueDate, installmentAmount: amount };
|
||||
this.wasChanged = true;
|
||||
period['changed'] = true;
|
||||
addDialogRef
|
||||
.afterClosed()
|
||||
.subscribe((response: { data?: { value?: { fromPeriod: number; toPeriod: number; amount: number } } }) => {
|
||||
if (response.data?.value && this.repaymentScheduleDetails) {
|
||||
const fromPeriod = response.data.value.fromPeriod;
|
||||
const toPeriod = response.data.value.toPeriod;
|
||||
const amount = response.data.value.amount;
|
||||
const periodsVariation: EditablePeriod[] = [];
|
||||
this.repaymentScheduleDetails.periods.forEach((period: EditablePeriod) => {
|
||||
const dueDate = this.dateUtils.formatDate(period.dueDate, this.settingsService.dateFormat);
|
||||
if (period.period && fromPeriod <= period.period && toPeriod >= period.period) {
|
||||
if (period.totalDueForPeriod !== amount) {
|
||||
period.totalDueForPeriod = amount;
|
||||
this.repaymentScheduleChanges[dueDate] = { dueDate: dueDate, installmentAmount: amount };
|
||||
this.wasChanged = true;
|
||||
period.changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
periodsVariation.push(period);
|
||||
});
|
||||
this.repaymentScheduleDetails['periods'] = periodsVariation;
|
||||
}
|
||||
});
|
||||
periodsVariation.push(period);
|
||||
});
|
||||
this.repaymentScheduleDetails.periods = periodsVariation;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
@@ -138,42 +148,63 @@ export class EditRepaymentScheduleComponent implements OnInit {
|
||||
)
|
||||
}
|
||||
});
|
||||
recoverScheduleDialogRef.afterClosed().subscribe((responseConfirmation: any) => {
|
||||
recoverScheduleDialogRef.afterClosed().subscribe((responseConfirmation: { confirm?: boolean }) => {
|
||||
if (responseConfirmation.confirm) {
|
||||
this.loansService
|
||||
.applyCommandLoanScheduleVariations(this.loanId, 'deleteVariations', {})
|
||||
.subscribe((response: any) => {
|
||||
this.loansService.applyCommandLoanScheduleVariations(this.loanId, 'deleteVariations', {}).subscribe({
|
||||
next: () => {
|
||||
this.getRepaymentSchedule();
|
||||
this.wasChanged = false;
|
||||
this.wasValidated = false;
|
||||
});
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Failed to delete schedule variations:', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
validate(): void {
|
||||
if (!this.repaymentScheduleDetails) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loansService
|
||||
.applyCommandLoanScheduleVariations(this.loanId, 'calculateLoanSchedule', this.getPayload())
|
||||
.subscribe((response: any) => {
|
||||
this.repaymentScheduleDetails['periods'] = [];
|
||||
response['periods'].forEach((period: any) => {
|
||||
period['changed'] = true;
|
||||
this.repaymentScheduleDetails['periods'].push(period);
|
||||
this.wasValidated = true;
|
||||
});
|
||||
.subscribe({
|
||||
next: (response: EditableRepaymentSchedule) => {
|
||||
if (this.repaymentScheduleDetails) {
|
||||
this.repaymentScheduleDetails.periods = [];
|
||||
response.periods.forEach((period: EditablePeriod) => {
|
||||
period.changed = true;
|
||||
this.repaymentScheduleDetails!.periods.push(period);
|
||||
this.wasValidated = true;
|
||||
});
|
||||
}
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Failed to calculate loan schedule:', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
submit(): void {
|
||||
this.loansService
|
||||
.applyCommandLoanScheduleVariations(this.loanId, 'addVariations', this.getPayload())
|
||||
.subscribe((response: any) => {
|
||||
this.loansService.applyCommandLoanScheduleVariations(this.loanId, 'addVariations', this.getPayload()).subscribe({
|
||||
next: () => {
|
||||
this.router.navigate(['../../repayment-schedule'], { relativeTo: this.route });
|
||||
});
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Failed to add schedule variations:', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private getPayload(): any {
|
||||
const modifiedinstallments: any = [];
|
||||
private getPayload(): {
|
||||
exceptions: { modifiedinstallments: ScheduleChangeRecord[] };
|
||||
dateFormat: string;
|
||||
locale: string;
|
||||
} {
|
||||
const modifiedinstallments: ScheduleChangeRecord[] = [];
|
||||
Object.keys(this.repaymentScheduleChanges).forEach((key: string) => {
|
||||
modifiedinstallments.push(this.repaymentScheduleChanges[key]);
|
||||
});
|
||||
|
||||
+10
@@ -84,6 +84,16 @@
|
||||
>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
[disabled]="!reagingLoanForm.valid"
|
||||
*mifosxHasPermission="'REAGING_LOAN'"
|
||||
(click)="preview()"
|
||||
>
|
||||
{{ 'labels.buttons.Preview' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</mat-card-content>
|
||||
</form>
|
||||
|
||||
+63
-6
@@ -1,11 +1,14 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
import { LoansService } from 'app/loans/loans.service';
|
||||
import { RepaymentSchedule } from 'app/loans/models/loan-account.model';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { OptionData } from 'app/shared/models/option-data.model';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
import { ReAgePreviewDialogComponent } from './re-age-preview-dialog/re-age-preview-dialog.component';
|
||||
|
||||
@Component({
|
||||
selector: 'mifosx-loan-reaging',
|
||||
@@ -31,13 +34,16 @@ export class LoanReagingComponent implements OnInit {
|
||||
/** Maximum Date allowed. */
|
||||
maxDate = new Date();
|
||||
|
||||
currencyCode: string = '';
|
||||
|
||||
constructor(
|
||||
private formBuilder: UntypedFormBuilder,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private settingsService: SettingsService,
|
||||
private loanService: LoansService,
|
||||
private dateUtils: Dates
|
||||
private dateUtils: Dates,
|
||||
private dialog: MatDialog
|
||||
) {
|
||||
this.loanId = this.route.snapshot.params['loanId'];
|
||||
}
|
||||
@@ -49,6 +55,11 @@ export class LoanReagingComponent implements OnInit {
|
||||
this.reAgeInterestHandlingOptions = this.dataObject.reAgeInterestHandlingOptions;
|
||||
this.periodFrequencyOptions = this.dataObject.periodFrequencyOptions;
|
||||
|
||||
const loanDetailsData = this.route.parent?.parent?.snapshot.data['loanDetailsData'];
|
||||
if (loanDetailsData?.currency?.code) {
|
||||
this.currencyCode = loanDetailsData.currency.code;
|
||||
}
|
||||
|
||||
this.createReagingLoanForm();
|
||||
}
|
||||
|
||||
@@ -79,21 +90,67 @@ export class LoanReagingComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
submit(): void {
|
||||
const reagingLoanFormData = this.reagingLoanForm.value;
|
||||
private prepareReagingData() {
|
||||
const reagingLoanFormData = { ...this.reagingLoanForm.value };
|
||||
const locale = this.settingsService.language.code;
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
const startDate: Date = this.reagingLoanForm.value.startDate;
|
||||
if (reagingLoanFormData.startDate instanceof Date) {
|
||||
reagingLoanFormData.startDate = this.dateUtils.formatDate(startDate, dateFormat);
|
||||
}
|
||||
const data = {
|
||||
if (reagingLoanFormData.reAgeInterestHandling && typeof reagingLoanFormData.reAgeInterestHandling === 'object') {
|
||||
reagingLoanFormData.reAgeInterestHandling = reagingLoanFormData.reAgeInterestHandling.id;
|
||||
}
|
||||
return {
|
||||
...reagingLoanFormData,
|
||||
dateFormat,
|
||||
locale
|
||||
};
|
||||
this.loanService.submitLoanActionButton(this.loanId, data, 'reAge').subscribe((response: any) => {
|
||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||
}
|
||||
|
||||
preview(): void {
|
||||
if (this.reagingLoanForm.invalid) {
|
||||
return;
|
||||
}
|
||||
const data = this.prepareReagingData();
|
||||
|
||||
this.loanService.getReAgePreview(this.loanId, data).subscribe({
|
||||
next: (response: RepaymentSchedule) => {
|
||||
const currencyCode = response.currency?.code || this.currencyCode;
|
||||
|
||||
if (!currencyCode) {
|
||||
console.error('Currency code is not available in API response or loan details');
|
||||
return;
|
||||
}
|
||||
|
||||
this.dialog.open(ReAgePreviewDialogComponent, {
|
||||
data: {
|
||||
repaymentSchedule: response,
|
||||
currencyCode: currencyCode
|
||||
},
|
||||
width: '95%',
|
||||
maxWidth: '1400px',
|
||||
height: '90vh'
|
||||
});
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Error loading re-age preview:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
submit(): void {
|
||||
if (this.reagingLoanForm.invalid) {
|
||||
return;
|
||||
}
|
||||
const data = this.prepareReagingData();
|
||||
this.loanService.submitLoanActionButton(this.loanId, data, 'reAge').subscribe({
|
||||
next: (response: any) => {
|
||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Error submitting re-age:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
<h1 mat-dialog-title>{{ 'labels.heading.Repayment Schedule Preview' | translate }}</h1>
|
||||
|
||||
<mat-dialog-content class="mat-typography">
|
||||
<mifosx-repayment-schedule-tab
|
||||
[repaymentScheduleDetails]="repaymentSchedule"
|
||||
[currencyCode]="currencyCode"
|
||||
[forEditing]="false"
|
||||
>
|
||||
</mifosx-repayment-schedule-tab>
|
||||
</mat-dialog-content>
|
||||
|
||||
<mat-dialog-actions align="end">
|
||||
<button mat-raised-button type="button" (click)="close()">
|
||||
{{ 'labels.buttons.Go back' | translate }}
|
||||
</button>
|
||||
</mat-dialog-actions>
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import {
|
||||
MAT_DIALOG_DATA,
|
||||
MatDialogRef,
|
||||
MatDialogTitle,
|
||||
MatDialogContent,
|
||||
MatDialogActions
|
||||
} from '@angular/material/dialog';
|
||||
import { MatButton } from '@angular/material/button';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
import { RepaymentSchedule } from 'app/loans/models/loan-account.model';
|
||||
import { RepaymentScheduleTabComponent } from '../../../repayment-schedule-tab/repayment-schedule-tab.component';
|
||||
|
||||
export interface ReAgePreviewDialogData {
|
||||
repaymentSchedule: RepaymentSchedule;
|
||||
currencyCode: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'mifosx-re-age-preview-dialog',
|
||||
templateUrl: './re-age-preview-dialog.component.html',
|
||||
styleUrls: ['./re-age-preview-dialog.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatDialogTitle,
|
||||
MatDialogContent,
|
||||
MatDialogActions,
|
||||
MatButton,
|
||||
RepaymentScheduleTabComponent
|
||||
]
|
||||
})
|
||||
export class ReAgePreviewDialogComponent {
|
||||
repaymentSchedule: RepaymentSchedule;
|
||||
currencyCode: string;
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<ReAgePreviewDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: ReAgePreviewDialogData
|
||||
) {
|
||||
this.repaymentSchedule = data.repaymentSchedule;
|
||||
this.currencyCode = data.currencyCode;
|
||||
}
|
||||
|
||||
close(): void {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
}
|
||||
+16
-14
@@ -5,7 +5,7 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<table mat-table [dataSource]="repaymentScheduleDetails.periods" *ngIf="!forEditing" id="repaymentSchedule">
|
||||
<table mat-table [dataSource]="repaymentScheduleDetails?.periods" *ngIf="!forEditing" id="repaymentSchedule">
|
||||
<ng-container matColumnDef="number">
|
||||
<th mat-header-cell class="center mat-header-cell" *matHeaderCellDef>#</th>
|
||||
<td mat-cell class="right" *matCellDef="let item">{{ item.period }}</td>
|
||||
@@ -63,7 +63,7 @@
|
||||
</td>
|
||||
<td mat-footer-cell class="check r-amount" *matFooterCellDef>
|
||||
<b>
|
||||
{{ repaymentScheduleDetails.totalPrincipalExpected | currency: currencyCode : 'symbol-narrow' : '1.2-2' }}</b
|
||||
{{ repaymentScheduleDetails?.totalPrincipalExpected | currency: currencyCode : 'symbol-narrow' : '1.2-2' }}</b
|
||||
>
|
||||
</td>
|
||||
</ng-container>
|
||||
@@ -77,7 +77,7 @@
|
||||
</td>
|
||||
<td mat-footer-cell class="r-amount" *matFooterCellDef>
|
||||
<b>
|
||||
{{ repaymentScheduleDetails.totalInterestCharged | currency: currencyCode : 'symbol-narrow' : '1.2-2' }}
|
||||
{{ repaymentScheduleDetails?.totalInterestCharged | currency: currencyCode : 'symbol-narrow' : '1.2-2' }}
|
||||
</b>
|
||||
</td>
|
||||
</ng-container>
|
||||
@@ -89,7 +89,7 @@
|
||||
</td>
|
||||
<td mat-footer-cell class="r-amount" *matFooterCellDef>
|
||||
<b>
|
||||
{{ repaymentScheduleDetails.totalFeeChargesCharged | currency: currencyCode : 'symbol-narrow' : '1.2-2' }}
|
||||
{{ repaymentScheduleDetails?.totalFeeChargesCharged | currency: currencyCode : 'symbol-narrow' : '1.2-2' }}
|
||||
</b>
|
||||
</td>
|
||||
</ng-container>
|
||||
@@ -103,7 +103,9 @@
|
||||
</td>
|
||||
<td mat-footer-cell class="r-amount" *matFooterCellDef>
|
||||
<b>
|
||||
{{ repaymentScheduleDetails.totalPenaltyChargesCharged | currency: currencyCode : 'symbol-narrow' : '1.2-2' }}
|
||||
{{
|
||||
repaymentScheduleDetails?.totalPenaltyChargesCharged | currency: currencyCode : 'symbol-narrow' : '1.2-2'
|
||||
}}
|
||||
</b>
|
||||
</td>
|
||||
</ng-container>
|
||||
@@ -115,7 +117,7 @@
|
||||
</td>
|
||||
<td mat-footer-cell class="r-amount" *matFooterCellDef>
|
||||
<b>
|
||||
{{ repaymentScheduleDetails.totalRepaymentExpected | currency: currencyCode : 'symbol-narrow' : '1.2-2' }}
|
||||
{{ repaymentScheduleDetails?.totalRepaymentExpected | currency: currencyCode : 'symbol-narrow' : '1.2-2' }}
|
||||
</b>
|
||||
</td>
|
||||
</ng-container>
|
||||
@@ -126,7 +128,7 @@
|
||||
{{ item.totalPaidForPeriod | formatNumber }}
|
||||
</td>
|
||||
<td mat-footer-cell class="r-amount" *matFooterCellDef>
|
||||
<b> {{ repaymentScheduleDetails.totalRepayment | currency: currencyCode : 'symbol-narrow' : '1.2-2' }} </b>
|
||||
<b> {{ repaymentScheduleDetails?.totalRepayment | currency: currencyCode : 'symbol-narrow' : '1.2-2' }} </b>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
@@ -138,7 +140,7 @@
|
||||
{{ item.totalPaidInAdvanceForPeriod | formatNumber }}
|
||||
</td>
|
||||
<td mat-footer-cell class="r-amount" *matFooterCellDef>
|
||||
<b> {{ repaymentScheduleDetails.totalPaidInAdvance | currency: currencyCode : 'symbol-narrow' : '1.2-2' }} </b>
|
||||
<b> {{ repaymentScheduleDetails?.totalPaidInAdvance | currency: currencyCode : 'symbol-narrow' : '1.2-2' }} </b>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
@@ -148,7 +150,7 @@
|
||||
{{ item.totalPaidLateForPeriod | formatNumber }}
|
||||
</td>
|
||||
<td mat-footer-cell class="r-amount" *matFooterCellDef>
|
||||
<b> {{ repaymentScheduleDetails.totalPaidLate | currency: currencyCode : 'symbol-narrow' : '1.2-2' }} </b>
|
||||
<b> {{ repaymentScheduleDetails?.totalPaidLate | currency: currencyCode : 'symbol-narrow' : '1.2-2' }} </b>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
@@ -161,7 +163,7 @@
|
||||
{{ item.totalWaivedForPeriod | formatNumber }}
|
||||
</td>
|
||||
<td mat-footer-cell class="r-amount" *matFooterCellDef>
|
||||
<b> {{ repaymentScheduleDetails.totalWaived | currency: currencyCode : 'symbol-narrow' : '1.2-2' }} </b>
|
||||
<b> {{ repaymentScheduleDetails?.totalWaived | currency: currencyCode : 'symbol-narrow' : '1.2-2' }} </b>
|
||||
</td>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
@@ -180,7 +182,7 @@
|
||||
</th>
|
||||
<td mat-cell class="r-amount" *matCellDef="let item">{{ item.totalOutstandingForPeriod | formatNumber }}</td>
|
||||
<td mat-footer-cell class="r-amount" *matFooterCellDef>
|
||||
<b> {{ repaymentScheduleDetails.totalOutstanding | currency: currencyCode : 'symbol-narrow' : '1.2-2' }} </b>
|
||||
<b> {{ repaymentScheduleDetails?.totalOutstanding | currency: currencyCode : 'symbol-narrow' : '1.2-2' }} </b>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
@@ -218,8 +220,8 @@
|
||||
<!-- Repayment Schedule to be Edited -->
|
||||
<table
|
||||
mat-table
|
||||
[dataSource]="repaymentScheduleDetails.periods"
|
||||
*ngIf="forEditing && repaymentScheduleDetails.periods.length > 0"
|
||||
[dataSource]="repaymentScheduleDetails?.periods"
|
||||
*ngIf="forEditing && repaymentScheduleDetails?.periods?.length > 0"
|
||||
id="repaymentScheduleEdit"
|
||||
>
|
||||
<ng-container matColumnDef="number">
|
||||
@@ -285,7 +287,7 @@
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
|
||||
<td mat-cell class="center" *matCellDef="let item">
|
||||
<span *ngIf="item.period && item.period + 1 < repaymentScheduleDetails.periods.length">
|
||||
<span *ngIf="item.period && item.period + 1 < repaymentScheduleDetails?.periods?.length">
|
||||
<ng-container>
|
||||
<button
|
||||
type="button"
|
||||
|
||||
+91
-20
@@ -1,8 +1,23 @@
|
||||
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
DestroyRef,
|
||||
EventEmitter,
|
||||
inject,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnInit,
|
||||
Output,
|
||||
SimpleChanges
|
||||
} 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';
|
||||
import { RepaymentSchedulePeriod } from 'app/loans/models/loan-account.model';
|
||||
import {
|
||||
RepaymentSchedule,
|
||||
RepaymentSchedulePeriod,
|
||||
RepaymentScheduleEditCache
|
||||
} from 'app/loans/models/loan-account.model';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component';
|
||||
import { DatepickerBase } from 'app/shared/form-dialog/formfield/model/datepicker-base';
|
||||
@@ -70,11 +85,11 @@ export class RepaymentScheduleTabComponent implements OnInit, OnChanges {
|
||||
/** Loan Repayment Schedule to be Edited */
|
||||
@Input() forEditing = false;
|
||||
/** Loan Repayment Schedule Details Data */
|
||||
@Input() repaymentScheduleDetails: any = null;
|
||||
loanDetailsDataRepaymentSchedule: any = [];
|
||||
@Input() repaymentScheduleDetails: RepaymentSchedule | null = null;
|
||||
loanDetailsDataRepaymentSchedule: RepaymentSchedule | null = null;
|
||||
|
||||
editCache: { [key: string]: any } = {};
|
||||
listOfData: any[] = [];
|
||||
editCache: { [key: string]: RepaymentScheduleEditCache } = {};
|
||||
listOfData: RepaymentSchedulePeriod[] = [];
|
||||
|
||||
repaymentSchedulePeriods: RepaymentSchedulePeriod[] = [];
|
||||
|
||||
@@ -118,6 +133,8 @@ export class RepaymentScheduleTabComponent implements OnInit, OnChanges {
|
||||
|
||||
businessDate: Date = new Date();
|
||||
|
||||
private destroyRef = inject(DestroyRef);
|
||||
|
||||
/**
|
||||
* Retrieves the loans with associations data from `resolve`.
|
||||
* @param {ActivatedRoute} route Activated Route.
|
||||
@@ -128,24 +145,69 @@ export class RepaymentScheduleTabComponent implements OnInit, OnChanges {
|
||||
private dateUtils: Dates,
|
||||
private dialog: MatDialog
|
||||
) {
|
||||
this.route.parent.data.subscribe((data: { loanDetailsData: any }) => {
|
||||
if (data.loanDetailsData) {
|
||||
this.currencyCode = data.loanDetailsData.currency.code;
|
||||
}
|
||||
this.loanDetailsDataRepaymentSchedule = data.loanDetailsData ? data.loanDetailsData.repaymentSchedule : [];
|
||||
});
|
||||
this.businessDate = this.settingsService.businessDate;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.repaymentScheduleDetails == null) {
|
||||
this.repaymentScheduleDetails = this.loanDetailsDataRepaymentSchedule;
|
||||
if (this.route.parent) {
|
||||
this.route.parent.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
|
||||
next: (data: { loanDetailsData: { repaymentSchedule?: RepaymentSchedule; currency?: { code: string } } }) => {
|
||||
this.loanDetailsDataRepaymentSchedule =
|
||||
data.loanDetailsData?.repaymentSchedule ?? this.getDefaultRepaymentSchedule();
|
||||
if (data.loanDetailsData?.currency?.code) {
|
||||
this.currencyCode = data.loanDetailsData.currency.code;
|
||||
}
|
||||
this.initializeRepaymentSchedule();
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Failed to load loan repayment schedule data:', err);
|
||||
this.loanDetailsDataRepaymentSchedule = this.getDefaultRepaymentSchedule();
|
||||
this.initializeRepaymentSchedule();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.loanDetailsDataRepaymentSchedule = this.getDefaultRepaymentSchedule();
|
||||
this.initializeRepaymentSchedule();
|
||||
}
|
||||
this.isWaived = this.repaymentScheduleDetails.totalWaived > 0;
|
||||
}
|
||||
|
||||
private initializeRepaymentSchedule(): void {
|
||||
if (!this.repaymentScheduleDetails) {
|
||||
this.repaymentScheduleDetails = this.loanDetailsDataRepaymentSchedule ?? this.getDefaultRepaymentSchedule();
|
||||
} else {
|
||||
this.repaymentScheduleDetails.periods ??= [];
|
||||
this.repaymentScheduleDetails.totalWaived ??= 0;
|
||||
}
|
||||
this.isWaived = (this.repaymentScheduleDetails.totalWaived ?? 0) > 0;
|
||||
this.updateEditCache();
|
||||
}
|
||||
|
||||
private getDefaultRepaymentSchedule(): RepaymentSchedule {
|
||||
return {
|
||||
periods: [],
|
||||
totalWaived: 0,
|
||||
currency: {} as any,
|
||||
loanTermInDays: 0,
|
||||
totalPrincipalDisbursed: 0,
|
||||
totalPrincipalExpected: 0,
|
||||
totalPrincipalPaid: 0,
|
||||
totalInterestCharged: 0,
|
||||
totalFeeChargesCharged: 0,
|
||||
totalPenaltyChargesCharged: 0,
|
||||
totalWrittenOff: 0,
|
||||
totalRepaymentExpected: 0,
|
||||
totalRepayment: 0,
|
||||
totalPaidInAdvance: 0,
|
||||
totalPaidLate: 0,
|
||||
totalOutstanding: 0,
|
||||
totalCredits: 0
|
||||
};
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if (changes['repaymentScheduleDetails'] && !changes['repaymentScheduleDetails'].firstChange) {
|
||||
this.initializeRepaymentSchedule();
|
||||
}
|
||||
this.totalRepaymentExpected = 0;
|
||||
this.listOfData.forEach((item) => {
|
||||
this.totalRepaymentExpected = this.totalRepaymentExpected + item.totalDueForPeriod;
|
||||
@@ -216,6 +278,9 @@ export class RepaymentScheduleTabComponent implements OnInit, OnChanges {
|
||||
}
|
||||
|
||||
editInstallment(period: RepaymentSchedulePeriod): void {
|
||||
if (!period.period) {
|
||||
return;
|
||||
}
|
||||
this.editCache[period.period].edit = true;
|
||||
const formfields: FormfieldBase[] = [
|
||||
new DatepickerBase({
|
||||
@@ -240,14 +305,17 @@ export class RepaymentScheduleTabComponent implements OnInit, OnChanges {
|
||||
formfields: formfields
|
||||
};
|
||||
const addDialogRef = this.dialog.open(FormDialogComponent, { data, width: '50rem' });
|
||||
addDialogRef.afterClosed().subscribe((response: any) => {
|
||||
addDialogRef.afterClosed().subscribe((response: { data?: { value?: Record<string, unknown> } }) => {
|
||||
if (response.data) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
cancelEdit(id: string): void {
|
||||
const index = this.listOfData.findIndex((item) => item.id === id);
|
||||
const index = this.listOfData.findIndex((item) => item.period?.toString() === id);
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
this.editCache[id] = {
|
||||
data: { ...this.listOfData[index] },
|
||||
edit: false
|
||||
@@ -255,14 +323,17 @@ export class RepaymentScheduleTabComponent implements OnInit, OnChanges {
|
||||
}
|
||||
|
||||
saveEdit(period: string): void {
|
||||
const index = this.listOfData.findIndex((item) => item.period === period);
|
||||
const index = this.listOfData.findIndex((item) => item.period?.toString() === period);
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
Object.assign(this.listOfData[index], this.editCache[period].data);
|
||||
this.editCache[period].edit = false;
|
||||
this.editPeriod.emit(period);
|
||||
}
|
||||
|
||||
updateEditCache(): void {
|
||||
if (this.repaymentScheduleDetails != null) {
|
||||
if (this.repaymentScheduleDetails?.periods) {
|
||||
this.listOfData = this.repaymentScheduleDetails.periods;
|
||||
this.totalRepaymentExpected = 0;
|
||||
this.listOfData.forEach((item) => {
|
||||
@@ -275,7 +346,7 @@ export class RepaymentScheduleTabComponent implements OnInit, OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
numberOnly(inputFormControl: any, event: any): boolean {
|
||||
numberOnly(inputFormControl: { value: string }, event: KeyboardEvent): boolean {
|
||||
const charCode = event.which ? event.which : event.keyCode;
|
||||
if (charCode === 46) {
|
||||
if (!(inputFormControl.value.indexOf('.') > -1)) {
|
||||
|
||||
@@ -241,6 +241,24 @@ export class LoansService {
|
||||
return this.http.post(`/loans/${loanId}/transactions`, data, { params: httpParams });
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Re-Age preview with repayment schedule
|
||||
* @param loanId Loan Id
|
||||
* @param data Re-Age data
|
||||
* @returns Observable with repayment schedule preview
|
||||
*/
|
||||
getReAgePreview(loanId: string, data: any): Observable<any> {
|
||||
let httpParams = new HttpParams();
|
||||
|
||||
Object.keys(data).forEach((key) => {
|
||||
if (data[key] !== null && data[key] !== undefined && data[key] !== '') {
|
||||
httpParams = httpParams.set(key, data[key].toString());
|
||||
}
|
||||
});
|
||||
|
||||
return this.http.get(`/loans/${loanId}/transactions/reage-preview`, { params: httpParams });
|
||||
}
|
||||
|
||||
getLoanScreenReportsData(): Observable<any> {
|
||||
const httpParams = new HttpParams().set('entityId', '1').set('typeId', '0');
|
||||
return this.http.get(`/templates`, { params: httpParams });
|
||||
|
||||
@@ -146,3 +146,21 @@ export interface BuyDownFeeAmortizationDetails {
|
||||
adjustedAmount: number;
|
||||
chargedOffAmount: number;
|
||||
}
|
||||
|
||||
export interface EditablePeriod extends RepaymentSchedulePeriod {
|
||||
changed?: boolean;
|
||||
}
|
||||
|
||||
export interface EditableRepaymentSchedule extends RepaymentSchedule {
|
||||
periods: EditablePeriod[];
|
||||
}
|
||||
|
||||
export interface RepaymentScheduleEditCache {
|
||||
edit: boolean;
|
||||
data: RepaymentSchedulePeriod;
|
||||
}
|
||||
|
||||
export interface ScheduleChangeRecord {
|
||||
dueDate: string;
|
||||
installmentAmount: number;
|
||||
}
|
||||
|
||||
@@ -425,6 +425,7 @@
|
||||
"GSIM Application": "Aplikace GSIM",
|
||||
"Generate Report": "Vygenerovat zprávu",
|
||||
"Get Parameters": "Získat parametry",
|
||||
"Go back": "Vrátit se",
|
||||
"Go to next step": "Přejděte k dalšímu kroku",
|
||||
"Group Loan Application": "Žádost o skupinovou půjčku",
|
||||
"Group Saving Application": "Aplikace pro ukládání skupin",
|
||||
@@ -459,6 +460,7 @@
|
||||
"Pie Chart": "Koláčový graf",
|
||||
"Post Dividend": "Vyplácet dividendu",
|
||||
"Previous": "Předchozí",
|
||||
"Preview": "Náhled",
|
||||
"Print": "Tisk",
|
||||
"Proceed": "Pokračovat",
|
||||
"Productive Collection Sheet": "Produktivní kolekce list",
|
||||
@@ -1069,6 +1071,7 @@
|
||||
"Reject Checker": "Odmítnout kontrolu",
|
||||
"Release Amount": "Částka uvolnění",
|
||||
"Repaid Every": "Splaceno každý",
|
||||
"Repayment Schedule Preview": "Náhled splátkového kalendáře",
|
||||
"Report Parameter": "Parametr sestavy",
|
||||
"Reschedule Loan": "Přeplánovací půjčka",
|
||||
"Revert Transaction": "Vrátit transakci",
|
||||
|
||||
@@ -425,6 +425,7 @@
|
||||
"GSIM Application": "GSIM-Anwendung",
|
||||
"Generate Report": "Bericht generieren",
|
||||
"Get Parameters": "Parameter abrufen",
|
||||
"Go back": "Zurück",
|
||||
"Go to next step": "Gehen Sie zum nächsten Schritt",
|
||||
"Group Loan Application": "Gruppenkreditantrag",
|
||||
"Group Saving Application": "Gruppenspeicheranwendung",
|
||||
@@ -459,6 +460,7 @@
|
||||
"Pie Chart": "Kuchendiagramm",
|
||||
"Post Dividend": "Post-Dividende",
|
||||
"Previous": "Vorherige",
|
||||
"Preview": "Vorschau",
|
||||
"Print": "Drucken",
|
||||
"Proceed": "Fortfahren",
|
||||
"Productive Collection Sheet": "Produktives Sammlungsblatt",
|
||||
@@ -1070,6 +1072,7 @@
|
||||
"Reject Checker": "Überprüfung ablehnen",
|
||||
"Release Amount": "Freigabebetrag",
|
||||
"Repaid Every": "Alle zurückgezahlt",
|
||||
"Repayment Schedule Preview": "Rückzahlungsplan Vorschau",
|
||||
"Report Parameter": "Berichtsparameter",
|
||||
"Reschedule Loan": "Darlehen neu plant",
|
||||
"Revert Transaction": "Transaktion rückgängig machen",
|
||||
|
||||
@@ -426,6 +426,7 @@
|
||||
"GSIM Application": "GSIM Application",
|
||||
"Generate Report": "Generate Report",
|
||||
"Get Parameters": "Get Parameters",
|
||||
"Go back": "Go back",
|
||||
"Go to next step": "Go to next step",
|
||||
"Group Loan Application": "Group Loan Application",
|
||||
"Group Saving Application": "Group Saving Application",
|
||||
@@ -460,6 +461,7 @@
|
||||
"Pie Chart": "Pie Chart",
|
||||
"Post Dividend": "Post Dividend",
|
||||
"Previous": "Previous",
|
||||
"Preview": "Preview",
|
||||
"Print": "Print",
|
||||
"Proceed": "Proceed",
|
||||
"Productive Collection Sheet": "Productive Collection Sheet",
|
||||
@@ -1075,6 +1077,7 @@
|
||||
"Reject Checker": "Reject Checker",
|
||||
"Release Amount": "Release Amount",
|
||||
"Repaid Every": "Repaid Every",
|
||||
"Repayment Schedule Preview": "Repayment Schedule Preview",
|
||||
"Report Parameter": "Report Parameter",
|
||||
"Reschedule Loan": "Reschedule Loan",
|
||||
"Revert Transaction": "Revert Transaction",
|
||||
|
||||
@@ -425,6 +425,7 @@
|
||||
"GSIM Application": "Aplicación GSIM",
|
||||
"Generate Report": "Generar reporte",
|
||||
"Get Parameters": "Obtener parámetros",
|
||||
"Go back": "Volver",
|
||||
"Go to next step": "Ir al siguiente paso",
|
||||
"Group Loan Application": "Solicitud de Crédito grupal",
|
||||
"Group Saving Application": "Solicitud de ahorro grupal",
|
||||
@@ -459,6 +460,7 @@
|
||||
"Pie Chart": "Gráfico circular",
|
||||
"Post Dividend": "Publicar dividendo",
|
||||
"Previous": "Anterior",
|
||||
"Preview": "Vista previa",
|
||||
"Print": "Imprimir",
|
||||
"Proceed": "Proceder",
|
||||
"Productive Collection Sheet": "Hoja de Recolección Productiva",
|
||||
@@ -1069,6 +1071,7 @@
|
||||
"Reject Checker": "Rechazador",
|
||||
"Release Amount": "Liberar Monto",
|
||||
"Repaid Every": "Frecuencia de Pago",
|
||||
"Repayment Schedule Preview": "Vista previa del calendario de pagos",
|
||||
"Report Parameter": "Parámetro de reporte",
|
||||
"Reschedule Loan": "Reprogramación del Crédito",
|
||||
"Revert Transaction": "Revertir transacción",
|
||||
|
||||
@@ -425,6 +425,7 @@
|
||||
"GSIM Application": "Aplicación GSIM",
|
||||
"Generate Report": "Generar reporte",
|
||||
"Get Parameters": "Obtener parámetros",
|
||||
"Go back": "Volver",
|
||||
"Go to next step": "Ir al siguiente paso",
|
||||
"Group Loan Application": "Solicitud de Crédito grupal",
|
||||
"Group Saving Application": "Solicitud de ahorro grupal",
|
||||
@@ -459,6 +460,7 @@
|
||||
"Pie Chart": "Gráfico circular",
|
||||
"Post Dividend": "Publicar dividendo",
|
||||
"Previous": "Anterior",
|
||||
"Preview": "Vista previa",
|
||||
"Print": "Imprimir",
|
||||
"Proceed": "Proceder",
|
||||
"Productive Collection Sheet": "Hoja de Recolección Productiva",
|
||||
@@ -1069,6 +1071,7 @@
|
||||
"Reject Checker": "Rechazador",
|
||||
"Release Amount": "Liberar Monto",
|
||||
"Repaid Every": "Frecuencia de Pago",
|
||||
"Repayment Schedule Preview": "Vista previa del calendario de pagos",
|
||||
"Report Parameter": "Parámetro de reporte",
|
||||
"Reschedule Loan": "Reprogramación del Crédito",
|
||||
"Revert Transaction": "Revertir transacción",
|
||||
|
||||
@@ -425,6 +425,7 @@
|
||||
"GSIM Application": "Demande GSIM",
|
||||
"Generate Report": "Générer un rapport",
|
||||
"Get Parameters": "Obtenir les paramètres",
|
||||
"Go back": "Retour",
|
||||
"Go to next step": "Passer à l'étape suivante",
|
||||
"Group Loan Application": "Demande de prêt de groupe",
|
||||
"Group Saving Application": "Demande d'épargne de groupe",
|
||||
@@ -459,6 +460,7 @@
|
||||
"Pie Chart": "Diagramme circulaire",
|
||||
"Post Dividend": "Après dividende",
|
||||
"Previous": "Précédent",
|
||||
"Preview": "Aperçu",
|
||||
"Print": "Imprimer",
|
||||
"Proceed": "Procéder",
|
||||
"Productive Collection Sheet": "Fiche de collecte productive",
|
||||
@@ -1070,6 +1072,7 @@
|
||||
"Reject Checker": "Rejeter le vérificateur",
|
||||
"Release Amount": "Montant de la libération",
|
||||
"Repaid Every": "Remboursé tous les",
|
||||
"Repayment Schedule Preview": "Aperçu du calendrier de remboursement",
|
||||
"Report Parameter": "Paramètre de rapport",
|
||||
"Reschedule Loan": "Prêt de reproduction",
|
||||
"Revert Transaction": "Annuler la transaction",
|
||||
|
||||
@@ -425,6 +425,7 @@
|
||||
"GSIM Application": "Applicazione GSMIM",
|
||||
"Generate Report": "Genera rapporto",
|
||||
"Get Parameters": "Ottieni parametri",
|
||||
"Go back": "Indietro",
|
||||
"Go to next step": "Vai al passaggio successivo",
|
||||
"Group Loan Application": "Richiesta di prestito di gruppo",
|
||||
"Group Saving Application": "Applicazione di salvataggio di gruppo",
|
||||
@@ -459,6 +460,7 @@
|
||||
"Pie Chart": "Grafico a torta",
|
||||
"Post Dividend": "Post dividendo",
|
||||
"Previous": "Precedente",
|
||||
"Preview": "Anteprima",
|
||||
"Print": "Stampa",
|
||||
"Proceed": "Procedere",
|
||||
"Productive Collection Sheet": "Foglio di raccolta produttiva",
|
||||
@@ -1070,6 +1072,7 @@
|
||||
"Reject Checker": "Rifiutare il controllo",
|
||||
"Release Amount": "Importo di rilascio",
|
||||
"Repaid Every": "Rimborsato ogni",
|
||||
"Repayment Schedule Preview": "Anteprima piano di rimborso",
|
||||
"Report Parameter": "Parametro del report",
|
||||
"Reschedule Loan": "Prestito riprogrammato",
|
||||
"Revert Transaction": "Annulla transazione",
|
||||
|
||||
@@ -425,6 +425,7 @@
|
||||
"GSIM Application": "GSIM 애플리케이션",
|
||||
"Generate Report": "보고서 생성",
|
||||
"Get Parameters": "매개변수 가져오기",
|
||||
"Go back": "돌아가기",
|
||||
"Go to next step": "다음 단계로 이동",
|
||||
"Group Loan Application": "단체대출 신청",
|
||||
"Group Saving Application": "그룹저장 신청",
|
||||
@@ -459,6 +460,7 @@
|
||||
"Pie Chart": "파이 차트",
|
||||
"Post Dividend": "배당 후",
|
||||
"Previous": "이전의",
|
||||
"Preview": "미리보기",
|
||||
"Print": "인쇄",
|
||||
"Proceed": "진행하다",
|
||||
"Productive Collection Sheet": "생산적인 컬렉션 시트",
|
||||
@@ -1071,6 +1073,7 @@
|
||||
"Reject Checker": "검사기를 거부하십시오",
|
||||
"Release Amount": "출시 금액",
|
||||
"Repaid Every": "마다 상환",
|
||||
"Repayment Schedule Preview": "상환 일정 미리보기",
|
||||
"Report Parameter": "보고서 매개변수",
|
||||
"Reschedule Loan": "일정 조정 대출",
|
||||
"Revert Transaction": "거래 되돌리기",
|
||||
|
||||
@@ -425,6 +425,7 @@
|
||||
"GSIM Application": "GSIM programa",
|
||||
"Generate Report": "Sukurti ataskaitą",
|
||||
"Get Parameters": "Gaukite parametrus",
|
||||
"Go back": "Grįžti",
|
||||
"Go to next step": "Eikite į kitą veiksmą",
|
||||
"Group Loan Application": "Grupinės paskolos paraiška",
|
||||
"Group Saving Application": "Grupės išsaugojimo programa",
|
||||
@@ -459,6 +460,7 @@
|
||||
"Pie Chart": "Skritulinė diagrama",
|
||||
"Post Dividend": "Paskelbkite dividendus",
|
||||
"Previous": "Ankstesnis",
|
||||
"Preview": "Peržiūra",
|
||||
"Print": "Spausdinti",
|
||||
"Proceed": "Tęskite",
|
||||
"Productive Collection Sheet": "Produktyvus surinkimo lapas",
|
||||
@@ -1070,6 +1072,7 @@
|
||||
"Reject Checker": "Atmeskite tikrintuvą",
|
||||
"Release Amount": "Išleidimo suma",
|
||||
"Repaid Every": "Atlyginama kas",
|
||||
"Repayment Schedule Preview": "Grąžinimo grafiko peržiūra",
|
||||
"Report Parameter": "Ataskaitos parametras",
|
||||
"Reschedule Loan": "Paskelbta paskola",
|
||||
"Revert Transaction": "Grąžinti operaciją",
|
||||
|
||||
@@ -425,6 +425,7 @@
|
||||
"GSIM Application": "GSIM lietojumprogramma",
|
||||
"Generate Report": "Ģenerēt atskaiti",
|
||||
"Get Parameters": "Iegūstiet parametrus",
|
||||
"Go back": "Atpakaļ",
|
||||
"Go to next step": "Pārejiet uz nākamo soli",
|
||||
"Group Loan Application": "Grupas aizdevuma pieteikums",
|
||||
"Group Saving Application": "Grupas saglabāšanas lietojumprogramma",
|
||||
@@ -459,6 +460,7 @@
|
||||
"Pie Chart": "Sektoru diagramma",
|
||||
"Post Dividend": "Pēc dividendes",
|
||||
"Previous": "Iepriekšējais",
|
||||
"Preview": "Priekšskatījums",
|
||||
"Print": "Drukāt",
|
||||
"Proceed": "Turpināt",
|
||||
"Productive Collection Sheet": "Produktīva kolekcijas lapa",
|
||||
@@ -1070,6 +1072,7 @@
|
||||
"Reject Checker": "Noraidīt pārbaudītāju",
|
||||
"Release Amount": "Izlaiduma summa",
|
||||
"Repaid Every": "Atmaksāts Katrs",
|
||||
"Repayment Schedule Preview": "Atmaksas grafika priekšskatījums",
|
||||
"Report Parameter": "Pārskata parametrs",
|
||||
"Reschedule Loan": "Pārplānot aizdevumu",
|
||||
"Revert Transaction": "Atsaukt darījumu",
|
||||
|
||||
@@ -425,6 +425,7 @@
|
||||
"GSIM Application": "GSIM आवेदन",
|
||||
"Generate Report": "रिपोर्ट उत्पन्न गर्नुहोस्",
|
||||
"Get Parameters": "प्यारामिटरहरू प्राप्त गर्नुहोस्",
|
||||
"Go back": "फिर्ता जानुहोस्",
|
||||
"Go to next step": "अर्को चरणमा जानुहोस्",
|
||||
"Group Loan Application": "समूह ऋण आवेदन",
|
||||
"Group Saving Application": "समूह बचत आवेदन",
|
||||
@@ -459,6 +460,7 @@
|
||||
"Pie Chart": "पाई चार्ट",
|
||||
"Post Dividend": "लाभांश पोस्ट गर्नुहोस्",
|
||||
"Previous": "अघिल्लो",
|
||||
"Preview": "पूर्वावलोकन",
|
||||
"Print": "छाप्नुहोस्",
|
||||
"Proceed": "अगाडि बढ्नुहोस्",
|
||||
"Productive Collection Sheet": "उत्पादक संग्रह पाना",
|
||||
@@ -1070,6 +1072,7 @@
|
||||
"Reject Checker": "परीक्षकलाई अस्वीकार गर्नुहोस्",
|
||||
"Release Amount": "रिलिज रकम",
|
||||
"Repaid Every": "प्रत्येक भुक्तान गरियो",
|
||||
"Repayment Schedule Preview": "भुक्तानी तालिका पूर्वावलोकन",
|
||||
"Report Parameter": "रिपोर्ट प्यारामिटर",
|
||||
"Reschedule Loan": "Receplate ण लिएको",
|
||||
"Revert Transaction": "लेनदेन उल्टाउनुहोस्",
|
||||
|
||||
@@ -425,6 +425,7 @@
|
||||
"GSIM Application": "Aplicação GSM",
|
||||
"Generate Report": "Gerar relatório",
|
||||
"Get Parameters": "Obter parâmetros",
|
||||
"Go back": "Voltar",
|
||||
"Go to next step": "Ir para a próxima etapa",
|
||||
"Group Loan Application": "Solicitação de empréstimo em grupo",
|
||||
"Group Saving Application": "Aplicativo para salvar grupo",
|
||||
@@ -459,6 +460,7 @@
|
||||
"Pie Chart": "Gráfico de pizza",
|
||||
"Post Dividend": "Pós Dividendo",
|
||||
"Previous": "Anterior",
|
||||
"Preview": "Pré-visualização",
|
||||
"Print": "Imprimir",
|
||||
"Proceed": "Continuar",
|
||||
"Productive Collection Sheet": "Folha de Coleta Produtiva",
|
||||
@@ -1070,6 +1072,7 @@
|
||||
"Reject Checker": "Rejeitar verificador",
|
||||
"Release Amount": "Valor de liberação",
|
||||
"Repaid Every": "Reembolsado a cada",
|
||||
"Repayment Schedule Preview": "Pré-visualização do calendário de pagamentos",
|
||||
"Report Parameter": "Parâmetro de relatório",
|
||||
"Reschedule Loan": "Empréstimo de remarcado",
|
||||
"Revert Transaction": "Reverter transação",
|
||||
|
||||
@@ -425,6 +425,7 @@
|
||||
"GSIM Application": "Maombi ya GSIM",
|
||||
"Generate Report": "Tengeneza Ripoti",
|
||||
"Get Parameters": "Pata Vigezo",
|
||||
"Go back": "Rudi nyuma",
|
||||
"Go to next step": "Nenda kwenye hatua inayofuata",
|
||||
"Group Loan Application": "Maombi ya Mkopo wa Kikundi",
|
||||
"Group Saving Application": "Maombi ya Kuokoa ya Kikundi",
|
||||
@@ -459,6 +460,7 @@
|
||||
"Pie Chart": "Jedwali la mdwara",
|
||||
"Post Dividend": "Chapisha Gawio",
|
||||
"Previous": "Iliyotangulia",
|
||||
"Preview": "Onyesha awali",
|
||||
"Print": "Chapisha",
|
||||
"Proceed": "Endelea",
|
||||
"Productive Collection Sheet": "Karatasi ya Ukusanyaji Yenye Tija",
|
||||
@@ -1070,6 +1072,7 @@
|
||||
"Reject Checker": "Kukataa ukaguzi",
|
||||
"Release Amount": "Kiasi cha Kutolewa",
|
||||
"Repaid Every": "Kulipwa Kila",
|
||||
"Repayment Schedule Preview": "Onyesha awali ratiba ya malipo",
|
||||
"Report Parameter": "Ripoti Parameta",
|
||||
"Reschedule Loan": "Rejesha mkopo",
|
||||
"Revert Transaction": "Rejesha Muamala",
|
||||
|
||||
Reference in New Issue
Block a user