WEB-677: Improve Transfer Funds UX with vertical stepper (#3107)
- Refactored Transfer Funds page into a 3-step vertical stepper: Step 1: Beneficiary Selection Step 2: Transfer Details Step 3: Transfer Status (success/failure) - Split single form into beneficiaryForm and transferDetailsForm - Added MatStepper with custom icons and linear progression - Added transfer status display with success/failure states - Added missing i18n translation keys across all 13 locale files - Fixed MatHint import for NG1010 compilation error
This commit is contained in:
+434
-347
@@ -7,384 +7,471 @@
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
@if (isLoading) {
|
||||
<div class="loader-wrapper">
|
||||
<div class="bottom triangle"></div>
|
||||
<div class="top triangle"></div>
|
||||
<div class="left triangle"></div>
|
||||
<div class="right triangle"></div>
|
||||
</div>
|
||||
}
|
||||
<mat-stepper orientation="vertical" [linear]="true" class="mat-elevation-z8" labelPosition="bottom" #transferStepper>
|
||||
<!-- Custom Step Icons -->
|
||||
<ng-template matStepperIcon="number">
|
||||
<fa-icon icon="pencil-alt" size="sm"></fa-icon>
|
||||
</ng-template>
|
||||
<ng-template matStepperIcon="edit">
|
||||
<fa-icon icon="pencil-alt" size="sm"></fa-icon>
|
||||
</ng-template>
|
||||
<ng-template matStepperIcon="done">
|
||||
<fa-icon icon="check" size="sm"></fa-icon>
|
||||
</ng-template>
|
||||
<ng-template matStepperIcon="error">
|
||||
<fa-icon icon="exclamation-triangle" size="lg"></fa-icon>
|
||||
</ng-template>
|
||||
|
||||
@if (!isLoading) {
|
||||
<mat-card class="transfer-card">
|
||||
<mat-card-content>
|
||||
<!-- Source Account Details Section -->
|
||||
<div class="section-container">
|
||||
<h3 class="section-title transfer-heading">{{ 'labels.heading.Transferring From Details' | translate }}</h3>
|
||||
<mat-divider></mat-divider>
|
||||
<div class="info-grid">
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Applicant' | translate }}</div>
|
||||
<div class="info-value">{{ accountTransferTemplateData.fromClient.displayName }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Office' | translate }}</div>
|
||||
<div class="info-value">{{ accountTransferTemplateData.fromOffice.name }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.From Account' | translate }}</div>
|
||||
<div class="info-value">
|
||||
{{ accountTransferTemplateData.fromAccount.productName }} - #{{
|
||||
accountTransferTemplateData.fromAccount.accountNo
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.From Account Type' | translate }}</div>
|
||||
<div class="info-value">{{ accountTransferTemplateData.fromAccountType.value }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Currency' | translate }}</div>
|
||||
<div class="info-value">{{ accountTransferTemplateData.currency.name }}</div>
|
||||
<!-- ==================== STEP 1: Beneficiary Selection ==================== -->
|
||||
<mat-step [stepControl]="beneficiaryForm" [editable]="!transferComplete">
|
||||
<ng-template matStepLabel>{{ 'labels.heading.Beneficiary Selection' | translate }}</ng-template>
|
||||
|
||||
<!-- Source Account Details (Read-Only) -->
|
||||
<div class="section-container">
|
||||
<h3 class="section-title transfer-heading">{{ 'labels.heading.Transferring From Details' | translate }}</h3>
|
||||
<mat-divider></mat-divider>
|
||||
<div class="info-grid">
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Applicant' | translate }}</div>
|
||||
<div class="info-value">{{ accountTransferTemplateData.fromClient.displayName }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Office' | translate }}</div>
|
||||
<div class="info-value">{{ accountTransferTemplateData.fromOffice.name }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.From Account' | translate }}</div>
|
||||
<div class="info-value">
|
||||
{{ accountTransferTemplateData.fromAccount.productName }} - #{{
|
||||
accountTransferTemplateData.fromAccount.accountNo
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.From Account Type' | translate }}</div>
|
||||
<div class="info-value">{{ accountTransferTemplateData.fromAccountType.value }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Currency' | translate }}</div>
|
||||
<div class="info-value">{{ accountTransferTemplateData.currency.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Interbank Section -->
|
||||
@if (interbank) {
|
||||
<div class="section-container">
|
||||
<div class="interbank-section">
|
||||
<h3 class="section-title transfer-heading">{{ 'labels.heading.Transferred To' | translate }}</h3>
|
||||
<mat-form-field class="full-width">
|
||||
</div>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<!-- Beneficiary Form -->
|
||||
@if (interbank) {
|
||||
<!-- Interbank: Phone Number Search -->
|
||||
<div class="section-container">
|
||||
<h3 class="section-title transfer-heading">{{ 'labels.heading.Transferred To' | translate }}</h3>
|
||||
<form [formGroup]="beneficiaryForm" class="transfer-form">
|
||||
<div class="form-grid">
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labels.inputs.Phone Number' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[readonly]="interbankTransferForm"
|
||||
type="tel"
|
||||
#input
|
||||
[(ngModel)]="phoneAccount"
|
||||
formControlName="phoneNumber"
|
||||
maxlength="10"
|
||||
required
|
||||
placeholder="{{ 'labels.text.EnterPhoneNumber' | translate }}"
|
||||
title="Phone number"
|
||||
/>
|
||||
<mat-hint align="end">{{ phoneAccount.length || 0 }}/10</mat-hint>
|
||||
<mat-hint align="end">{{ beneficiaryForm.get('phoneNumber')?.value?.length || 0 }}/10</mat-hint>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<!--interbank -->
|
||||
@if (!interbankTransferForm) {
|
||||
<mat-card-actions class="action-buttons">
|
||||
<div class="action-buttons step-actions">
|
||||
<ng-container *mifosxHasPermission="'CREATE_ACCOUNTTRANSFER'">
|
||||
<button
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
[disabled]="phoneAccount.length !== 10"
|
||||
[disabled]="beneficiaryForm.get('phoneNumber')?.value?.length !== 10"
|
||||
(click)="searchAccountByNumber()"
|
||||
id="search-button"
|
||||
class="primary-button"
|
||||
>
|
||||
{{ 'labels.buttons.Search' | translate }}
|
||||
</button>
|
||||
</ng-container>
|
||||
</mat-card-actions>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Interbank Beneficiary Preview (Read-Only) -->
|
||||
@if (interbankTransferForm) {
|
||||
<div class="info-grid beneficiary-preview">
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Bank' | translate }}</div>
|
||||
<div class="info-value">{{ beneficiaryForm.get('toBank')?.value }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Client' | translate }}</div>
|
||||
<div class="info-value">{{ beneficiaryForm.get('toClientId')?.value }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Account Type' | translate }}</div>
|
||||
<div class="info-value">{{ beneficiaryForm.get('toAccountType')?.value }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Account' | translate }}</div>
|
||||
<div class="info-value">{{ beneficiaryForm.get('toAccountId')?.value }}</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
} @else {
|
||||
<!-- Normal Transfer: Office/Client/Account Selection -->
|
||||
<form [formGroup]="beneficiaryForm" class="transfer-form">
|
||||
<h3 class="section-title transfer-heading">{{ 'labels.heading.Transferred To' | translate }}</h3>
|
||||
<div class="form-grid">
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labels.inputs.Office' | translate }}</mat-label>
|
||||
<mat-select required formControlName="toOfficeId" (selectionChange)="changeEvent()">
|
||||
@for (toOfficeType of toOfficeTypeData; track toOfficeType) {
|
||||
<mat-option [value]="toOfficeType.id">
|
||||
{{ toOfficeType.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (beneficiaryForm.controls['toOfficeId'].hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Office' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labels.inputs.Client' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="toClientId"
|
||||
[matAutocomplete]="clientsAutocomplete"
|
||||
placeholder="{{ 'labels.text.SelectOrTypeClientName' | translate }}"
|
||||
title="Client name"
|
||||
/>
|
||||
@if (beneficiaryForm.controls['toClientId'].hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Client' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-autocomplete
|
||||
autoActiveFirstOption
|
||||
#clientsAutocomplete="matAutocomplete"
|
||||
[displayWith]="displayClient"
|
||||
>
|
||||
@for (client of clientsData; track client) {
|
||||
<mat-option [value]="client"> {{ client.id }} - {{ client.displayName }} </mat-option>
|
||||
}
|
||||
</mat-autocomplete>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labels.inputs.Account Type' | translate }}</mat-label>
|
||||
<mat-select required formControlName="toAccountType" (selectionChange)="changeEvent()">
|
||||
@for (toAccountType of toAccountTypeData; track toAccountType) {
|
||||
<mat-option [value]="toAccountType.id">
|
||||
{{ toAccountType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (beneficiaryForm.controls['toAccountType'].hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Account Type' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labels.inputs.Account' | translate }}</mat-label>
|
||||
<mat-select required formControlName="toAccountId" (selectionChange)="changeEvent()">
|
||||
@for (toAccount of toAccountData; track toAccount) {
|
||||
<mat-option [value]="toAccount.id">
|
||||
{{ toAccount.productName }} - {{ toAccount.accountNo }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (beneficiaryForm.controls['toAccountId'].hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Account' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</form>
|
||||
}
|
||||
|
||||
<!-- Step 1 Navigation -->
|
||||
<div class="layout-row align-center gap-2percent margin-t responsive-column">
|
||||
<button mat-raised-button matStepperPrevious disabled>
|
||||
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Previous' | translate }}
|
||||
</button>
|
||||
<button
|
||||
mat-raised-button
|
||||
matStepperNext
|
||||
[disabled]="interbank ? !interbankTransferForm : !beneficiaryForm.valid"
|
||||
>
|
||||
{{ 'labels.buttons.Next' | translate }}
|
||||
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
|
||||
</button>
|
||||
<button mat-raised-button [routerLink]="['../..']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</mat-step>
|
||||
|
||||
<!-- ==================== STEP 2: Transfer Details ==================== -->
|
||||
<mat-step [stepControl]="transferDetailsForm" [editable]="!transferComplete">
|
||||
<ng-template matStepLabel>{{ 'labels.heading.Transfer Details' | translate }}</ng-template>
|
||||
|
||||
@if (isLoading) {
|
||||
<div class="loader-wrapper">
|
||||
<div class="bottom triangle"></div>
|
||||
<div class="top triangle"></div>
|
||||
<div class="left triangle"></div>
|
||||
<div class="right triangle"></div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (!isLoading) {
|
||||
<!-- Beneficiary Summary (Read-Only) -->
|
||||
<div class="section-container beneficiary-summary">
|
||||
<h3 class="section-title transfer-heading">{{ 'labels.heading.Beneficiary' | translate }}</h3>
|
||||
<div class="info-grid">
|
||||
@if (interbank && interbankTransferForm) {
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Bank' | translate }}</div>
|
||||
<div class="info-value">{{ beneficiaryForm.get('toBank')?.value }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Client' | translate }}</div>
|
||||
<div class="info-value">{{ beneficiaryForm.get('toClientId')?.value }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Account' | translate }}</div>
|
||||
<div class="info-value">{{ beneficiaryForm.get('toAccountId')?.value }}</div>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Office' | translate }}</div>
|
||||
<div class="info-value">{{ getSelectedOfficeName() }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Client' | translate }}</div>
|
||||
<div class="info-value">{{ getSelectedClientName() }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Account Type' | translate }}</div>
|
||||
<div class="info-value">{{ getSelectedAccountTypeName() }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Account' | translate }}</div>
|
||||
<div class="info-value">{{ getSelectedAccountName() }}</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (!interbank) {
|
||||
<mat-divider></mat-divider>
|
||||
}
|
||||
<!-- Transfer Form Section (Normal) -->
|
||||
@if (!interbank && makeAccountTransferForm) {
|
||||
<form [formGroup]="makeAccountTransferForm" class="transfer-form">
|
||||
<h3 class="section-title transfer-heading">{{ 'labels.heading.Transfer Details' | translate }}</h3>
|
||||
<div class="form-grid">
|
||||
<mat-form-field class="form-field" (click)="transferDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Transaction Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="transferDatePicker"
|
||||
required
|
||||
formControlName="transferDate"
|
||||
placeholder="{{ 'labels.text.SelectDate' | translate }}"
|
||||
title="Transaction Date"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="transferDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #transferDatePicker></mat-datepicker>
|
||||
@if (makeAccountTransferForm.controls.transferDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Transaction Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labels.inputs.Office' | translate }}</mat-label>
|
||||
<mat-select required formControlName="toOfficeId" (selectionChange)="changeEvent()">
|
||||
@for (toOfficeType of toOfficeTypeData; track toOfficeType) {
|
||||
<mat-option [value]="toOfficeType.id">
|
||||
{{ toOfficeType.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (makeAccountTransferForm.controls.toOfficeId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Office' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labels.inputs.Client' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="toClientId"
|
||||
[matAutocomplete]="clientsAutocomplete"
|
||||
placeholder="{{ 'labels.text.SelectOrTypeClientName' | translate }}"
|
||||
title="Client name"
|
||||
/>
|
||||
@if (makeAccountTransferForm.controls.toClientId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Client' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-autocomplete
|
||||
autoActiveFirstOption
|
||||
#clientsAutocomplete="matAutocomplete"
|
||||
[displayWith]="displayClient"
|
||||
>
|
||||
@for (client of clientsData; track client) {
|
||||
<mat-option [value]="client"> {{ client.id }} - {{ client.displayName }} </mat-option>
|
||||
}
|
||||
</mat-autocomplete>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labels.inputs.Account Type' | translate }}</mat-label>
|
||||
<mat-select required formControlName="toAccountType" (selectionChange)="changeEvent()">
|
||||
@for (toAccountType of toAccountTypeData; track toAccountType) {
|
||||
<mat-option [value]="toAccountType.id">
|
||||
{{ toAccountType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (makeAccountTransferForm.controls.toAccountType.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Account Type' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labels.inputs.Account' | translate }}</mat-label>
|
||||
<mat-select required formControlName="toAccountId" (selectionChange)="changeEvent()">
|
||||
@for (toAccount of toAccountData; track toAccount) {
|
||||
<mat-option [value]="toAccount.id">
|
||||
{{ toAccount.productName }} - {{ toAccount.accountNo }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (makeAccountTransferForm.controls.toAccountId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Account' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labels.inputs.Amount' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
matInput
|
||||
required
|
||||
formControlName="transferAmount"
|
||||
placeholder="{{ 'labels.text.EnterAmount' | translate }}"
|
||||
title="Transfer amount"
|
||||
min="0.01"
|
||||
step="0.01"
|
||||
/>
|
||||
@if (makeAccountTransferForm.controls.transferAmount.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Amount' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
@if (makeAccountTransferForm.get('transferAmount')?.hasError('amountExceedsBalance')) {
|
||||
<mat-error>
|
||||
<fa-icon icon="exclamation-triangle" size="md"></fa-icon>
|
||||
{{ 'errors.validation.msg.savingsproduct.insufficient.balance' | translate: { balance } }}
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field description-field">
|
||||
<mat-label>{{ 'labels.inputs.Description' | translate }}</mat-label>
|
||||
<textarea
|
||||
matInput
|
||||
formControlName="transferDescription"
|
||||
cdkTextareaAutosize
|
||||
cdkAutosizeMinRows="2"
|
||||
placeholder="{{ 'labels.text.EnterTransferDescription' | translate }}"
|
||||
title="Transfer description"
|
||||
></textarea>
|
||||
@if (makeAccountTransferForm.controls.transferDescription.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Transfer Description' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</form>
|
||||
}
|
||||
<!-- Interbank Transfer Form Section -->
|
||||
@if (interbank && interbankTransferForm && makeAccountTransferForm) {
|
||||
<form [formGroup]="makeAccountTransferForm" class="transfer-form">
|
||||
<h3 class="section-title transfer-heading">{{ 'labels.heading.Transfer Details' | translate }}</h3>
|
||||
<div class="form-grid">
|
||||
<mat-form-field class="form-field" (click)="transferDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Transaction Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="transferDatePicker"
|
||||
required
|
||||
formControlName="transferDate"
|
||||
placeholder="{{ 'labels.text.SelectDate' | translate }}"
|
||||
title="Transaction Date"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="transferDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #transferDatePicker></mat-datepicker>
|
||||
@if (makeAccountTransferForm.controls.transferDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Transaction Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labels.inputs.Bank' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="toBank"
|
||||
[readonly]="true"
|
||||
placeholder="{{ 'labels.inputs.Bank' | translate }}"
|
||||
title="Bank"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labels.inputs.Client' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="toClientId"
|
||||
[readonly]="true"
|
||||
placeholder="{{ 'labels.inputs.Client' | translate }}"
|
||||
title="Client"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labels.inputs.Account Type' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="toAccountType"
|
||||
[readonly]="true"
|
||||
placeholder="{{ 'labels.inputs.Account Type' | translate }}"
|
||||
title="Account Type"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labels.inputs.Account' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="toAccountId"
|
||||
[readonly]="true"
|
||||
placeholder="{{ 'labels.inputs.Account' | translate }}"
|
||||
title="Account"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labels.inputs.Amount' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
matInput
|
||||
required
|
||||
formControlName="transferAmount"
|
||||
placeholder="{{ 'labels.text.EnterAmount' | translate }}"
|
||||
title="Transfer amount"
|
||||
min="0.01"
|
||||
step="0.01"
|
||||
/>
|
||||
@if (makeAccountTransferForm.controls.transferAmount.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Amount' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
@if (makeAccountTransferForm.controls.transferAmount.hasError('min')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Amount' | translate }} {{ 'labels.commons.mustBeAtLeast' | translate }} 0.01
|
||||
</mat-error>
|
||||
}
|
||||
@if (makeAccountTransferForm.get('transferAmount')?.hasError('amountExceedsBalance')) {
|
||||
<mat-error>
|
||||
<fa-icon icon="exclamation-triangle" size="md"></fa-icon>
|
||||
{{ 'errors.validation.msg.savingsproduct.insufficient.balance' | translate: { balance } }}
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field description-field">
|
||||
<mat-label>{{ 'labels.inputs.Description' | translate }}</mat-label>
|
||||
<textarea
|
||||
matInput
|
||||
formControlName="transferDescription"
|
||||
cdkTextareaAutosize
|
||||
cdkAutosizeMinRows="2"
|
||||
placeholder="{{ 'labels.text.EnterTransferDescription' | translate }}"
|
||||
title="Transfer description"
|
||||
></textarea>
|
||||
@if (makeAccountTransferForm.controls.transferDescription.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Transfer Description' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</form>
|
||||
}
|
||||
</mat-card-content>
|
||||
@if (!isLoading && makeAccountTransferForm) {
|
||||
<mat-card-actions class="action-buttons">
|
||||
<button type="button" mat-raised-button [routerLink]="['../..']" class="cancel-button">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</div>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<!-- Transfer Details Form -->
|
||||
<form [formGroup]="transferDetailsForm" class="transfer-form">
|
||||
<h3 class="section-title transfer-heading">{{ 'labels.heading.Transfer Details' | translate }}</h3>
|
||||
<div class="form-grid">
|
||||
<mat-form-field class="form-field" (click)="transferDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Transaction Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="transferDatePicker"
|
||||
required
|
||||
formControlName="transferDate"
|
||||
placeholder="{{ 'labels.text.SelectDate' | translate }}"
|
||||
title="Transaction Date"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="transferDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #transferDatePicker></mat-datepicker>
|
||||
@if (transferDetailsForm.controls['transferDate'].hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Transaction Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labels.inputs.Amount' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
matInput
|
||||
required
|
||||
formControlName="transferAmount"
|
||||
placeholder="{{ 'labels.text.EnterAmount' | translate }}"
|
||||
title="Transfer amount"
|
||||
min="0.01"
|
||||
step="0.01"
|
||||
/>
|
||||
@if (transferDetailsForm.controls['transferAmount'].hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Amount' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
@if (transferDetailsForm.get('transferAmount')?.hasError('amountExceedsBalance')) {
|
||||
<mat-error>
|
||||
<fa-icon icon="exclamation-triangle" size="md"></fa-icon>
|
||||
{{ 'errors.validation.msg.savingsproduct.insufficient.balance' | translate: { balance } }}
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field description-field">
|
||||
<mat-label>{{ 'labels.inputs.Description' | translate }}</mat-label>
|
||||
<textarea
|
||||
matInput
|
||||
formControlName="transferDescription"
|
||||
cdkTextareaAutosize
|
||||
cdkAutosizeMinRows="2"
|
||||
placeholder="{{ 'labels.text.EnterTransferDescription' | translate }}"
|
||||
title="Transfer description"
|
||||
></textarea>
|
||||
@if (transferDetailsForm.controls['transferDescription'].hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Transfer Description' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Step 2 Navigation -->
|
||||
<div class="layout-row align-center gap-2percent margin-t responsive-column">
|
||||
<button mat-raised-button matStepperPrevious>
|
||||
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Previous' | translate }}
|
||||
</button>
|
||||
<ng-container *mifosxHasPermission="'CREATE_ACCOUNTTRANSFER'">
|
||||
@if (interbank && interbankTransferForm) {
|
||||
<button
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
[disabled]="!makeAccountTransferForm.valid"
|
||||
(click)="submit()"
|
||||
class="primary-button"
|
||||
>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
}
|
||||
@if (!interbank) {
|
||||
<button
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
[disabled]="!makeAccountTransferForm.valid"
|
||||
(click)="submit()"
|
||||
class="primary-button"
|
||||
>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
}
|
||||
<button mat-raised-button color="primary" [disabled]="!transferDetailsForm.valid" (click)="submit()">
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</ng-container>
|
||||
</mat-card-actions>
|
||||
<button mat-raised-button [routerLink]="['../..']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</mat-card>
|
||||
}
|
||||
</mat-step>
|
||||
|
||||
<!-- ==================== STEP 3: Transfer Status ==================== -->
|
||||
<mat-step [editable]="false">
|
||||
<ng-template matStepLabel>{{ 'labels.heading.Transfer Status' | translate }}</ng-template>
|
||||
|
||||
@if (isLoading) {
|
||||
<div class="loader-wrapper">
|
||||
<div class="bottom triangle"></div>
|
||||
<div class="top triangle"></div>
|
||||
<div class="left triangle"></div>
|
||||
<div class="right triangle"></div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (!isLoading && transferComplete) {
|
||||
<div class="transfer-status-container">
|
||||
@if (transferSuccess) {
|
||||
<div class="status-icon success">
|
||||
<fa-icon icon="check-circle" size="3x"></fa-icon>
|
||||
</div>
|
||||
<h3 class="status-title success-text">{{ 'labels.heading.Transfer Successful' | translate }}</h3>
|
||||
} @else {
|
||||
<div class="status-icon error">
|
||||
<fa-icon icon="times-circle" size="3x"></fa-icon>
|
||||
</div>
|
||||
<h3 class="status-title error-text">{{ 'labels.heading.Transfer Failed' | translate }}</h3>
|
||||
@if (transferErrorMessage) {
|
||||
<p class="status-message error-text">{{ transferErrorMessage }}</p>
|
||||
}
|
||||
}
|
||||
|
||||
<!-- Transfer Summary -->
|
||||
<div class="section-container transfer-summary">
|
||||
<h3 class="section-title transfer-heading">{{ 'labels.heading.Transfer Summary' | translate }}</h3>
|
||||
<mat-divider></mat-divider>
|
||||
<div class="info-grid">
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.From Account' | translate }}</div>
|
||||
<div class="info-value">
|
||||
{{ accountTransferTemplateData.fromAccount.productName }} - #{{
|
||||
accountTransferTemplateData.fromAccount.accountNo
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
@if (interbank && interbankTransferForm) {
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Bank' | translate }}</div>
|
||||
<div class="info-value">{{ beneficiaryForm.get('toBank')?.value }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Client' | translate }}</div>
|
||||
<div class="info-value">{{ beneficiaryForm.get('toClientId')?.value }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Account' | translate }}</div>
|
||||
<div class="info-value">{{ beneficiaryForm.get('toAccountId')?.value }}</div>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Office' | translate }}</div>
|
||||
<div class="info-value">{{ getSelectedOfficeName() }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Client' | translate }}</div>
|
||||
<div class="info-value">{{ getSelectedClientName() }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Account' | translate }}</div>
|
||||
<div class="info-value">{{ getSelectedAccountName() }}</div>
|
||||
</div>
|
||||
}
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Amount' | translate }}</div>
|
||||
<div class="info-value">
|
||||
{{ transferDetailsForm.get('transferAmount')?.value }} {{ accountTransferTemplateData.currency.code }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Transaction Date' | translate }}</div>
|
||||
<div class="info-value">{{ transferDetailsForm.get('transferDate')?.value | date }}</div>
|
||||
</div>
|
||||
@if (transferDetailsForm.get('transferDescription')?.value) {
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Description' | translate }}</div>
|
||||
<div class="info-value">{{ transferDetailsForm.get('transferDescription')?.value }}</div>
|
||||
</div>
|
||||
}
|
||||
@if (transferReferenceId) {
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ 'labels.inputs.Transaction ID' | translate }}</div>
|
||||
<div class="info-value">{{ transferReferenceId }}</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 Navigation -->
|
||||
<div class="layout-row align-center gap-2percent margin-t responsive-column">
|
||||
<button mat-raised-button [routerLink]="['../../transactions']">
|
||||
<fa-icon icon="list" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.View Transactions' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button [routerLink]="['../..']">
|
||||
{{ 'labels.buttons.Back to Account' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</mat-step>
|
||||
</mat-stepper>
|
||||
</div>
|
||||
|
||||
+61
-8
@@ -12,14 +12,6 @@
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
// Card styling
|
||||
.transfer-card {
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgb(0 0 0 / 8%);
|
||||
margin-bottom: 1.5rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// Section styling
|
||||
.section-container {
|
||||
margin-bottom: 2rem;
|
||||
@@ -82,6 +74,12 @@ mat-divider {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
// Beneficiary preview and summary
|
||||
.beneficiary-preview,
|
||||
.beneficiary-summary {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
// Form styling
|
||||
.transfer-form {
|
||||
margin-top: 1rem;
|
||||
@@ -178,6 +176,53 @@ mat-divider {
|
||||
}
|
||||
}
|
||||
|
||||
// Step navigation buttons (matching loans stepper pattern)
|
||||
.step-actions {
|
||||
padding: 1rem 0;
|
||||
}
|
||||
|
||||
// Transfer Status (Step 3)
|
||||
.transfer-status-container {
|
||||
text-align: center;
|
||||
padding: 1.5rem 0;
|
||||
}
|
||||
|
||||
.status-icon {
|
||||
margin-bottom: 1rem;
|
||||
|
||||
&.success {
|
||||
color: #4caf50;
|
||||
}
|
||||
|
||||
&.error {
|
||||
color: #f44336;
|
||||
}
|
||||
}
|
||||
|
||||
.status-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 0.5rem;
|
||||
}
|
||||
|
||||
.success-text {
|
||||
color: #4caf50;
|
||||
}
|
||||
|
||||
.error-text {
|
||||
color: #f44336;
|
||||
}
|
||||
|
||||
.status-message {
|
||||
font-size: 0.875rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.transfer-summary {
|
||||
text-align: left;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
// Loader styling
|
||||
.loader-wrapper {
|
||||
display: flex;
|
||||
@@ -254,6 +299,14 @@ mat-divider {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.status-icon.success {
|
||||
color: #66bb6a;
|
||||
}
|
||||
|
||||
.status-icon.error {
|
||||
color: #ef5350;
|
||||
}
|
||||
}
|
||||
|
||||
// Higher specificity selectors
|
||||
|
||||
+153
-135
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
/** Angular Imports */
|
||||
import { Component, OnInit, AfterViewInit, inject } from '@angular/core';
|
||||
import { Component, OnInit, AfterViewInit, ViewChild, inject } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import {
|
||||
AbstractControl,
|
||||
@@ -27,8 +27,16 @@ import { Dates } from 'app/core/utils/dates';
|
||||
/** Environment Configuration */
|
||||
import { environment } from '../../../environments/environment';
|
||||
import { MatDivider } from '@angular/material/divider';
|
||||
import { MatFormField, MatLabel, MatHint, MatError } from '@angular/material/form-field';
|
||||
import { MatHint } from '@angular/material/form-field';
|
||||
import { MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autocomplete';
|
||||
import {
|
||||
MatStepper,
|
||||
MatStepperIcon,
|
||||
MatStep,
|
||||
MatStepLabel,
|
||||
MatStepperNext,
|
||||
MatStepperPrevious
|
||||
} from '@angular/material/stepper';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
@@ -47,6 +55,12 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
MatHint,
|
||||
MatAutocompleteTrigger,
|
||||
MatAutocomplete,
|
||||
MatStepper,
|
||||
MatStepperIcon,
|
||||
MatStep,
|
||||
MatStepLabel,
|
||||
MatStepperNext,
|
||||
MatStepperPrevious,
|
||||
FaIconComponent,
|
||||
CdkTextareaAutosize
|
||||
]
|
||||
@@ -60,14 +74,19 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
private settingsService = inject(SettingsService);
|
||||
private clientsService = inject(ClientsService);
|
||||
|
||||
/** Stepper reference */
|
||||
@ViewChild('transferStepper') transferStepper: MatStepper;
|
||||
|
||||
/** Standing Instructions Data */
|
||||
accountTransferTemplateData: any;
|
||||
/** Minimum date allowed. */
|
||||
minDate = new Date(2000, 0, 1);
|
||||
/** Maximum date allowed. */
|
||||
maxDate = new Date(2100, 0, 1);
|
||||
/** Edit Standing Instructions form. */
|
||||
makeAccountTransferForm: UntypedFormGroup;
|
||||
/** Beneficiary selection form (Step 1) */
|
||||
beneficiaryForm: UntypedFormGroup;
|
||||
/** Transfer details form (Step 2) */
|
||||
transferDetailsForm: UntypedFormGroup;
|
||||
/** To Office Type Data */
|
||||
toOfficeTypeData: any;
|
||||
/** To Client Type Data */
|
||||
@@ -86,22 +105,18 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
clientsData: any;
|
||||
/** interbank transfer */
|
||||
interbank: boolean = false;
|
||||
/** Reference of phoneAccount search */
|
||||
phoneAccount = '';
|
||||
/** Interbank transfer form flag */
|
||||
interbankTransferForm: boolean = false;
|
||||
balance: number = 0;
|
||||
isLoading: boolean = false;
|
||||
/** Transfer status flags (Step 3) */
|
||||
transferComplete: boolean = false;
|
||||
transferSuccess: boolean = false;
|
||||
transferErrorMessage: string = '';
|
||||
transferReferenceId: string = '';
|
||||
|
||||
/**
|
||||
* Retrieves the standing instructions template from `resolve`.
|
||||
* @param {ActivatedRoute} route Activated Route.
|
||||
* @param {FormBuilder} formBuilder Form Builder
|
||||
* @param {Router} router Router
|
||||
* @param {AccountTransfersService} accountTransfersService Account Transfers Service
|
||||
* @param {Dates} dateUtils Date Utils
|
||||
* @param {SettingsService} settingsService Settings Service
|
||||
* @param {ClientsService} clientsService Clients Service
|
||||
*/
|
||||
constructor() {
|
||||
this.route.data.subscribe((data: { accountTransferTemplate: any }) => {
|
||||
@@ -111,7 +126,6 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
});
|
||||
}
|
||||
|
||||
/** Sets the value from the URL */
|
||||
/** Sets the value from the URL */
|
||||
setParams() {
|
||||
this.accountType = this.route.snapshot.queryParams['accountType'];
|
||||
@@ -139,62 +153,23 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and sets the create standing instructions form.
|
||||
* Creates and sets the beneficiary and transfer details forms.
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.maxDate = this.settingsService.businessDate;
|
||||
if (!this.interbank) {
|
||||
this.createMakeAccountTransferForm();
|
||||
this.createNormalBeneficiaryForm();
|
||||
} else {
|
||||
this.createEmptyInterbankForm();
|
||||
this.createEmptyInterbankBeneficiaryForm();
|
||||
}
|
||||
this.createTransferDetailsForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea un formulario vacío para interbank mientras se carga
|
||||
* Creates the beneficiary form for normal (non-interbank) transfers.
|
||||
*/
|
||||
createEmptyInterbankForm() {
|
||||
this.makeAccountTransferForm = this.formBuilder.group({
|
||||
toBank: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
toClientId: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
toAccountType: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
toAccountId: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
transferAmount: [
|
||||
0,
|
||||
[
|
||||
Validators.required,
|
||||
Validators.min(0.01),
|
||||
this.amountExceedsBalanceValidator.bind(this)
|
||||
]
|
||||
],
|
||||
transferDate: [
|
||||
this.settingsService.businessDate,
|
||||
Validators.required
|
||||
],
|
||||
transferDescription: [
|
||||
'',
|
||||
Validators.required
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the standing instruction form.
|
||||
*/
|
||||
createMakeAccountTransferForm() {
|
||||
this.makeAccountTransferForm = this.formBuilder.group({
|
||||
createNormalBeneficiaryForm() {
|
||||
this.beneficiaryForm = this.formBuilder.group({
|
||||
toOfficeId: [
|
||||
'',
|
||||
Validators.required
|
||||
@@ -210,51 +185,61 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
toAccountId: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
transferAmount: [
|
||||
this.accountTransferTemplateData.transferAmount,
|
||||
[
|
||||
Validators.required,
|
||||
Validators.min(0.01),
|
||||
this.amountExceedsBalanceValidator.bind(this)
|
||||
]
|
||||
],
|
||||
transferDate: [
|
||||
this.settingsService.businessDate,
|
||||
Validators.required
|
||||
],
|
||||
transferDescription: [
|
||||
'',
|
||||
Validators.required
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
createMakeAccountInterbankTransferForm(account: any) {
|
||||
/**
|
||||
* Creates an empty beneficiary form for interbank transfers (phone search).
|
||||
*/
|
||||
createEmptyInterbankBeneficiaryForm() {
|
||||
this.beneficiaryForm = this.formBuilder.group({
|
||||
phoneNumber: [
|
||||
'',
|
||||
[
|
||||
Validators.required,
|
||||
Validators.minLength(10),
|
||||
Validators.maxLength(10)
|
||||
]
|
||||
],
|
||||
toBank: [''],
|
||||
toClientId: [''],
|
||||
toAccountType: [''],
|
||||
toAccountId: ['']
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the interbank beneficiary form after phone search resolves an account.
|
||||
*/
|
||||
populateInterbankBeneficiary(account: any) {
|
||||
if (!account) {
|
||||
console.error('Account data is undefined');
|
||||
this.isLoading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const defaultAmount =
|
||||
this.accountTransferTemplateData?.transferAmount > 0 ? this.accountTransferTemplateData.transferAmount : 1;
|
||||
this.beneficiaryForm.patchValue({
|
||||
toBank: account.destinationFspId || '',
|
||||
toClientId: (account.firstName || account.firsName || '') + ' ' + (account.lastName || ''),
|
||||
toAccountType: 'Saving Account',
|
||||
toAccountId: account.partyId || ''
|
||||
});
|
||||
|
||||
this.makeAccountTransferForm = this.formBuilder.group({
|
||||
toBank: [
|
||||
account.destinationFspId || '',
|
||||
Validators.required
|
||||
],
|
||||
toClientId: [
|
||||
(account.firstName || account.firsName || '') + ' ' + (account.lastName || ''),
|
||||
Validators.required
|
||||
],
|
||||
toAccountType: [
|
||||
'Saving Account',
|
||||
Validators.required
|
||||
],
|
||||
toAccountId: [
|
||||
account.partyId || '',
|
||||
this.interbankTransferForm = true;
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the transfer details form (Step 2).
|
||||
*/
|
||||
createTransferDetailsForm() {
|
||||
const defaultAmount =
|
||||
this.accountTransferTemplateData?.transferAmount > 0 ? this.accountTransferTemplateData.transferAmount : '';
|
||||
|
||||
this.transferDetailsForm = this.formBuilder.group({
|
||||
transferDate: [
|
||||
this.settingsService.businessDate,
|
||||
Validators.required
|
||||
],
|
||||
transferAmount: [
|
||||
@@ -265,16 +250,11 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
this.amountExceedsBalanceValidator.bind(this)
|
||||
]
|
||||
],
|
||||
transferDate: [
|
||||
this.settingsService.businessDate,
|
||||
Validators.required
|
||||
],
|
||||
transferDescription: [
|
||||
'Transferencia interbancaria',
|
||||
'',
|
||||
Validators.required
|
||||
]
|
||||
});
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
amountExceedsBalanceValidator(control: AbstractControl): ValidationErrors | null {
|
||||
@@ -291,7 +271,7 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
|
||||
/** Executes on change of various select options */
|
||||
changeEvent() {
|
||||
const formValue = this.refineObject(this.makeAccountTransferForm.value);
|
||||
const formValue = this.refineObject({ ...this.beneficiaryForm.value });
|
||||
this.accountTransfersService
|
||||
.newAccountTranferResource(this.id, this.accountTypeId, formValue)
|
||||
.subscribe((response: any) => {
|
||||
@@ -304,10 +284,7 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
/** Refine Object
|
||||
* Removes the object param with null or '' values
|
||||
*/
|
||||
refineObject(dataObj: { [x: string]: any; transferAmount: any; transferDate: any; transferDescription: any }) {
|
||||
delete dataObj.transferAmount;
|
||||
delete dataObj.transferDate;
|
||||
delete dataObj.transferDescription;
|
||||
refineObject(dataObj: any) {
|
||||
if (dataObj.toClientId && typeof dataObj.toClientId === 'object') {
|
||||
dataObj.toClientId = dataObj.toClientId.id;
|
||||
}
|
||||
@@ -325,8 +302,8 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
* Subscribes to Clients search filter:
|
||||
*/
|
||||
ngAfterViewInit() {
|
||||
if (!this.interbank && this.makeAccountTransferForm) {
|
||||
this.makeAccountTransferForm.controls.toClientId.valueChanges.subscribe((value: any) => {
|
||||
if (!this.interbank && this.beneficiaryForm) {
|
||||
this.beneficiaryForm.controls.toClientId.valueChanges.subscribe((value: any) => {
|
||||
if (typeof value === 'string' && value.length >= 2) {
|
||||
this.clientsService.getFilteredClients('displayName', 'ASC', true, value).subscribe((data: any) => {
|
||||
this.clientsData = data.pageItems;
|
||||
@@ -346,8 +323,35 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
return client ? client.displayName : undefined;
|
||||
}
|
||||
|
||||
/** Helper methods for displaying selected beneficiary info in Step 2 summary */
|
||||
getSelectedOfficeName(): string {
|
||||
const officeId = this.beneficiaryForm?.get('toOfficeId')?.value;
|
||||
const office = this.toOfficeTypeData?.find((o: any) => o.id === officeId);
|
||||
return office ? office.name : '';
|
||||
}
|
||||
|
||||
getSelectedClientName(): string {
|
||||
const client = this.beneficiaryForm?.get('toClientId')?.value;
|
||||
if (typeof client === 'object' && client) {
|
||||
return client.displayName;
|
||||
}
|
||||
return client || '';
|
||||
}
|
||||
|
||||
getSelectedAccountTypeName(): string {
|
||||
const typeId = this.beneficiaryForm?.get('toAccountType')?.value;
|
||||
const type = this.toAccountTypeData?.find((t: any) => t.id === typeId);
|
||||
return type ? type.value : '';
|
||||
}
|
||||
|
||||
getSelectedAccountName(): string {
|
||||
const accountId = this.beneficiaryForm?.get('toAccountId')?.value;
|
||||
const account = this.toAccountData?.find((a: any) => a.id === accountId);
|
||||
return account ? `${account.productName} - ${account.accountNo}` : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits the standing instructions form
|
||||
* Submits the transfer
|
||||
*/
|
||||
submit() {
|
||||
this.interbank ? this.makeInterbankTransfer() : this.makeTransfer();
|
||||
@@ -359,15 +363,16 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
const locale = this.settingsService.language.code;
|
||||
|
||||
let toClientIdValue: any;
|
||||
if (typeof this.makeAccountTransferForm.controls.toClientId.value === 'object') {
|
||||
toClientIdValue = this.makeAccountTransferForm.controls.toClientId.value.id;
|
||||
if (typeof this.beneficiaryForm.controls.toClientId.value === 'object') {
|
||||
toClientIdValue = this.beneficiaryForm.controls.toClientId.value.id;
|
||||
} else {
|
||||
toClientIdValue = this.makeAccountTransferForm.controls.toClientId.value;
|
||||
toClientIdValue = this.beneficiaryForm.controls.toClientId.value;
|
||||
}
|
||||
|
||||
const makeAccountTransferData = {
|
||||
...this.makeAccountTransferForm.value,
|
||||
transferDate: this.dateUtils.formatDate(this.makeAccountTransferForm.value.transferDate, dateFormat),
|
||||
...this.beneficiaryForm.value,
|
||||
...this.transferDetailsForm.value,
|
||||
transferDate: this.dateUtils.formatDate(this.transferDetailsForm.value.transferDate, dateFormat),
|
||||
dateFormat,
|
||||
locale,
|
||||
toClientId: toClientIdValue,
|
||||
@@ -377,21 +382,28 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
fromOfficeId: this.accountTransferTemplateData.fromClient.officeId
|
||||
};
|
||||
|
||||
this.accountTransfersService.createAccountTransfer(makeAccountTransferData).subscribe(() => {
|
||||
this.isLoading = false;
|
||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||
});
|
||||
this.accountTransfersService.createAccountTransfer(makeAccountTransferData).subscribe(
|
||||
(response: any) => {
|
||||
this.isLoading = false;
|
||||
this.transferComplete = true;
|
||||
this.transferSuccess = true;
|
||||
this.transferReferenceId = response?.resourceId || response?.transactionId || '';
|
||||
this.transferStepper.next();
|
||||
},
|
||||
(error: any) => {
|
||||
this.isLoading = false;
|
||||
this.transferComplete = true;
|
||||
this.transferSuccess = false;
|
||||
this.transferErrorMessage =
|
||||
error?.error?.defaultUserMessage || error?.message || 'An unexpected error occurred.';
|
||||
this.transferStepper.next();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
makeInterbankTransfer() {
|
||||
this.isLoading = true;
|
||||
|
||||
if (!this.makeAccountTransferForm.valid) {
|
||||
console.error('Interbank form is not valid');
|
||||
this.isLoading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const payload = {
|
||||
homeTransactionId: crypto.randomUUID(),
|
||||
from: {
|
||||
@@ -400,14 +412,14 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
idValue: this.accountTransferTemplateData.fromAccount.externalId?.trim() || ''
|
||||
},
|
||||
to: {
|
||||
fspId: this.makeAccountTransferForm.controls.toBank.value,
|
||||
fspId: this.beneficiaryForm.controls.toBank.value,
|
||||
idType: 'MSISDN',
|
||||
idValue: this.makeAccountTransferForm.controls.toAccountId.value
|
||||
idValue: this.beneficiaryForm.controls.toAccountId.value
|
||||
},
|
||||
amountType: 'SEND',
|
||||
amount: {
|
||||
currencyCode: this.accountTransferTemplateData.currency.code,
|
||||
amount: this.makeAccountTransferForm.controls.transferAmount.value
|
||||
amount: this.transferDetailsForm.controls.transferAmount.value
|
||||
},
|
||||
transactionType: {
|
||||
scenario: 'TRANSFER',
|
||||
@@ -415,35 +427,41 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
initiator: 'PAYER',
|
||||
initiatorType: 'CUSTOMER'
|
||||
},
|
||||
note: this.makeAccountTransferForm.controls.transferDescription.value
|
||||
note: this.transferDetailsForm.controls.transferDescription.value
|
||||
};
|
||||
|
||||
this.accountTransfersService.sendInterbankTransfer(JSON.stringify(payload)).subscribe(
|
||||
(trnsfr) => {
|
||||
if (trnsfr.systemMessage) {
|
||||
this.isLoading = false;
|
||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||
}
|
||||
this.isLoading = false;
|
||||
this.transferComplete = true;
|
||||
this.transferSuccess = true;
|
||||
this.transferReferenceId = trnsfr?.systemMessage || '';
|
||||
this.transferStepper.next();
|
||||
},
|
||||
(error) => {
|
||||
console.error('Interbank transfer error:', error);
|
||||
this.isLoading = false;
|
||||
this.transferComplete = true;
|
||||
this.transferSuccess = false;
|
||||
this.transferErrorMessage =
|
||||
error?.error?.defaultUserMessage || error?.message || 'An unexpected error occurred.';
|
||||
this.transferStepper.next();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
searchAccountByNumber() {
|
||||
if (!this.phoneAccount || this.phoneAccount.length !== 10) {
|
||||
const phoneNumber = this.beneficiaryForm.get('phoneNumber')?.value;
|
||||
if (!phoneNumber || phoneNumber.length !== 10) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isLoading = true;
|
||||
this.accountTransfersService
|
||||
.getAccountByNumber(this.phoneAccount, this.accountTransferTemplateData.currency.code)
|
||||
.getAccountByNumber(phoneNumber, this.accountTransferTemplateData.currency.code)
|
||||
.subscribe(
|
||||
(acc) => {
|
||||
this.interbankTransferForm = true;
|
||||
this.createMakeAccountInterbankTransferForm(acc);
|
||||
this.populateInterbankBeneficiary(acc);
|
||||
},
|
||||
(error) => {
|
||||
console.error('searching account error:', error);
|
||||
|
||||
@@ -347,6 +347,7 @@
|
||||
"Attach Meeting": "Připojit schůzku",
|
||||
"Attendance": "Účast",
|
||||
"Back": "Zadní",
|
||||
"Back to Account": "Zpět na účet",
|
||||
"Bar Chart": "Sloupcový graf",
|
||||
"Browse": "Procházet",
|
||||
"Bulk JLG Loan Application": "Hromadná žádost o půjčku JLG",
|
||||
@@ -548,6 +549,7 @@
|
||||
"View Journal Entries": "Zobrazit záznamy deníku",
|
||||
"View Standing Instructions": "Prohlédněte si stálé pokyny",
|
||||
"View Transactions History": "Zobrazit historii transakcí",
|
||||
"View Transactions": "Zobrazit transakce",
|
||||
"Waive": "vzdát se",
|
||||
"Waive Charge": "Zřeknutí se poplatku",
|
||||
"Week": "Týden",
|
||||
@@ -926,6 +928,8 @@
|
||||
"Assets / Liability": "Aktiva / pasiva",
|
||||
"Audit Trails": "Audit Trails",
|
||||
"Balance": "Zůstatek",
|
||||
"Beneficiary": "Příjemce",
|
||||
"Beneficiary Selection": "Výběr příjemce",
|
||||
"Block Savings Account": "Blokovat spořicí účet",
|
||||
"Bulk Import": "Hromadný import",
|
||||
"Bulk Loan Reassignment": "Hromadné přeřazení půjčky",
|
||||
@@ -1231,6 +1235,10 @@
|
||||
"Transaction Reverted": "Transakce vrácena",
|
||||
"Transactions": "Transakce",
|
||||
"Transfer Details": "Podrobnosti o převodu",
|
||||
"Transfer Failed": "Převod se nezdařil",
|
||||
"Transfer Status": "Stav převodu",
|
||||
"Transfer Successful": "Převod úspěšný",
|
||||
"Transfer Summary": "Souhrn převodu",
|
||||
"Transferred From": "Převedeno z",
|
||||
"Transferred To": "Převeden k",
|
||||
"Transferring From Details": "Přenos z podrobností",
|
||||
|
||||
@@ -347,6 +347,7 @@
|
||||
"Attach Meeting": "Besprechung anhängen",
|
||||
"Attendance": "Teilnahme",
|
||||
"Back": "Zurück",
|
||||
"Back to Account": "Zurück zum Konto",
|
||||
"Bar Chart": "Balkendiagramm",
|
||||
"Browse": "Durchsuche",
|
||||
"Bulk JLG Loan Application": "Massenantrag für einen JLG-Kredit",
|
||||
@@ -548,6 +549,7 @@
|
||||
"View Journal Entries": "Journaleinträge anzeigen",
|
||||
"View Standing Instructions": "Ständige Anweisungen anzeigen",
|
||||
"View Transactions History": "Transaktionsverlauf anzeigen",
|
||||
"View Transactions": "Transaktionen anzeigen",
|
||||
"Waive": "Verzichten",
|
||||
"Waive Charge": "Auf Gebühr verzichten",
|
||||
"Week": "Woche",
|
||||
@@ -927,6 +929,8 @@
|
||||
"Assets / Liability": "Vermögenswerte / Verbindlichkeiten",
|
||||
"Audit Trails": "Buchungsprotokolle",
|
||||
"Balance": "Gleichgewicht",
|
||||
"Beneficiary": "Begünstigter",
|
||||
"Beneficiary Selection": "Begünstigtenauswahl",
|
||||
"Block Savings Account": "Sparkonto sperren",
|
||||
"Bulk Import": "Massenimport",
|
||||
"Bulk Loan Reassignment": "Neuzuweisung von Massenkrediten",
|
||||
@@ -1232,6 +1236,10 @@
|
||||
"Transaction Reverted": "Transaktion rückgängig gemacht",
|
||||
"Transactions": "Transaktionen",
|
||||
"Transfer Details": "Transferdetails",
|
||||
"Transfer Failed": "Überweisung fehlgeschlagen",
|
||||
"Transfer Status": "Überweisungsstatus",
|
||||
"Transfer Successful": "Überweisung erfolgreich",
|
||||
"Transfer Summary": "Überweisungszusammenfassung",
|
||||
"Transferred From": "Transferiert von",
|
||||
"Transferred To": "Übertragen auf",
|
||||
"Transferring From Details": "Von Details übertragen",
|
||||
|
||||
@@ -351,6 +351,7 @@
|
||||
"Attach Meeting": "Attach Meeting",
|
||||
"Attendance": "Attendance",
|
||||
"Back": "Back",
|
||||
"Back to Account": "Back to Account",
|
||||
"Bar Chart": "Bar Chart",
|
||||
"Browse": "Browse",
|
||||
"Bulk JLG Loan Application": "Bulk JLG Loan Application",
|
||||
@@ -552,6 +553,7 @@
|
||||
"View Journal Entries": "View Journal Entries",
|
||||
"View Standing Instructions": "View Standing Instructions",
|
||||
"View Transactions History": "View Transactions History",
|
||||
"View Transactions": "View Transactions",
|
||||
"Waive": "Waive",
|
||||
"Waive Charge": "Waive Charge",
|
||||
"Week": "Week",
|
||||
@@ -932,6 +934,8 @@
|
||||
"Assets / Liability": "Assets / Liability",
|
||||
"Audit Trails": "Audit Trails",
|
||||
"Balance": "Balance",
|
||||
"Beneficiary": "Beneficiary",
|
||||
"Beneficiary Selection": "Beneficiary Selection",
|
||||
"Block Savings Account": "Block Savings Account",
|
||||
"Bulk Import": "Bulk Import",
|
||||
"Bulk Loan Reassignment": "Bulk Loan Reassignment",
|
||||
@@ -1245,6 +1249,10 @@
|
||||
"Transaction Reverted": "Transaction Reverted",
|
||||
"Transactions": "Transactions",
|
||||
"Transfer Details": "Transfer Details",
|
||||
"Transfer Failed": "Transfer Failed",
|
||||
"Transfer Status": "Transfer Status",
|
||||
"Transfer Successful": "Transfer Successful",
|
||||
"Transfer Summary": "Transfer Summary",
|
||||
"Transferred From": "Transferred From",
|
||||
"Transferred To": "Transferred To",
|
||||
"Transferring From Details": "Transferring From Details",
|
||||
@@ -1438,6 +1446,7 @@
|
||||
"Base Price": "Base Price",
|
||||
"Base Percentage": "Base Percentage",
|
||||
"Beneficiary": "Beneficiary",
|
||||
"Beneficiary Selection": "Beneficiary Selection",
|
||||
"Branch": "Branch",
|
||||
"Branch Office": "Branch Office",
|
||||
"Breakdown": "Breakdown",
|
||||
|
||||
@@ -347,6 +347,7 @@
|
||||
"Attach Meeting": "Adjuntar reunión",
|
||||
"Attendance": "Asistencia",
|
||||
"Back": "Atrás",
|
||||
"Back to Account": "Volver a la Cuenta",
|
||||
"Bar Chart": "Gráfico de barras",
|
||||
"Browse": "Buscar",
|
||||
"Bulk JLG Loan Application": "Solicitud de Crédito JLG a granel",
|
||||
@@ -548,6 +549,7 @@
|
||||
"View Journal Entries": "Ver entradas de diario",
|
||||
"View Standing Instructions": "Ver instrucciones permanentes",
|
||||
"View Transactions History": "Ver historial de transacciones",
|
||||
"View Transactions": "Ver transacciones",
|
||||
"Waive": "Renunciar",
|
||||
"Waive Charge": "Renunciar a Comisión",
|
||||
"Week": "Semana",
|
||||
@@ -926,6 +928,8 @@
|
||||
"Assets / Liability": "Activo / Pasivo",
|
||||
"Audit Trails": "Pistas de auditoría",
|
||||
"Balance": "Saldo",
|
||||
"Beneficiary": "Beneficiario",
|
||||
"Beneficiary Selection": "Selección de Beneficiario",
|
||||
"Block Savings Account": "Bloquear Cuenta de Ahorros",
|
||||
"Bulk Import": "Importación masiva",
|
||||
"Bulk Loan Reassignment": "Reasignación de Créditos másiva",
|
||||
@@ -1232,6 +1236,10 @@
|
||||
"Transaction Reverted": "Transacción revertida",
|
||||
"Transactions": "Transacciones",
|
||||
"Transfer Details": "Detalles de la transferencia",
|
||||
"Transfer Failed": "Transferencia fallida",
|
||||
"Transfer Status": "Estado de la transferencia",
|
||||
"Transfer Successful": "Transferencia exitosa",
|
||||
"Transfer Summary": "Resumen de la transferencia",
|
||||
"Transferred From": "Transferido desde",
|
||||
"Transferred To": "Transferido a",
|
||||
"Transferring From Details": "Transferir desde detalles",
|
||||
|
||||
@@ -347,6 +347,7 @@
|
||||
"Attach Meeting": "Adjuntar reunión",
|
||||
"Attendance": "Asistencia",
|
||||
"Back": "Atrás",
|
||||
"Back to Account": "Volver a la Cuenta",
|
||||
"Bar Chart": "Gráfico de barras",
|
||||
"Browse": "Buscar",
|
||||
"Bulk JLG Loan Application": "Solicitud de Crédito JLG a granel",
|
||||
@@ -548,6 +549,7 @@
|
||||
"View Journal Entries": "Ver entradas de diario",
|
||||
"View Standing Instructions": "Ver instrucciones permanentes",
|
||||
"View Transactions History": "Ver historial de transacciones",
|
||||
"View Transactions": "Ver transacciones",
|
||||
"Waive": "Renunciar",
|
||||
"Waive Charge": "Renunciar a Comisión",
|
||||
"Week": "Semana",
|
||||
@@ -926,6 +928,8 @@
|
||||
"Assets / Liability": "Activo / Pasivo",
|
||||
"Audit Trails": "Pistas de auditoría",
|
||||
"Balance": "Saldo",
|
||||
"Beneficiary": "Beneficiario",
|
||||
"Beneficiary Selection": "Selección de Beneficiario",
|
||||
"Block Savings Account": "Bloquear Cuenta de Ahorros",
|
||||
"Bulk Import": "Importación masiva",
|
||||
"Bulk Loan Reassignment": "Reasignación de Créditos másiva",
|
||||
@@ -1231,6 +1235,10 @@
|
||||
"Transaction Reverted": "Transacción revertida",
|
||||
"Transactions": "Transacciones",
|
||||
"Transfer Details": "Detalles de la transferencia",
|
||||
"Transfer Failed": "Transferencia fallida",
|
||||
"Transfer Status": "Estado de la transferencia",
|
||||
"Transfer Successful": "Transferencia exitosa",
|
||||
"Transfer Summary": "Resumen de la transferencia",
|
||||
"Transferred From": "Transferido desde",
|
||||
"Transferred To": "Transferido a",
|
||||
"Transferring From Details": "Transferir desde detalles",
|
||||
|
||||
@@ -347,6 +347,7 @@
|
||||
"Attach Meeting": "Joindre une réunion",
|
||||
"Attendance": "Présence",
|
||||
"Back": "Dos",
|
||||
"Back to Account": "Retour au compte",
|
||||
"Bar Chart": "Diagramme à bandes",
|
||||
"Browse": "Parcourir",
|
||||
"Bulk JLG Loan Application": "Demande de prêt JLG en masse",
|
||||
@@ -548,6 +549,7 @@
|
||||
"View Journal Entries": "Afficher les entrées de journal",
|
||||
"View Standing Instructions": "Voir les instructions permanentes",
|
||||
"View Transactions History": "Afficher l'historique des transactions",
|
||||
"View Transactions": "Voir les transactions",
|
||||
"Waive": "Renoncer à",
|
||||
"Waive Charge": "Renoncer aux frais",
|
||||
"Week": "Semaine",
|
||||
@@ -927,6 +929,8 @@
|
||||
"Assets / Liability": "Actif / Passif",
|
||||
"Audit Trails": "Des pistes de vérification",
|
||||
"Balance": "Équilibre",
|
||||
"Beneficiary": "Bénéficiaire",
|
||||
"Beneficiary Selection": "Sélection du bénéficiaire",
|
||||
"Block Savings Account": "Bloquer le compte d'épargne",
|
||||
"Bulk Import": "Importation en masse",
|
||||
"Bulk Loan Reassignment": "Réaffectation groupée de prêts",
|
||||
@@ -1232,6 +1236,10 @@
|
||||
"Transaction Reverted": "Transaction annulée",
|
||||
"Transactions": "Transactions",
|
||||
"Transfer Details": "Détails du transfert",
|
||||
"Transfer Failed": "Transfert échoué",
|
||||
"Transfer Status": "Statut du transfert",
|
||||
"Transfer Successful": "Transfert réussi",
|
||||
"Transfer Summary": "Résumé du transfert",
|
||||
"Transferred From": "Transféré de",
|
||||
"Transferred To": "Transféré à",
|
||||
"Transferring From Details": "Transfert depuis les détails",
|
||||
|
||||
@@ -347,6 +347,7 @@
|
||||
"Attach Meeting": "Allega riunione",
|
||||
"Attendance": "Partecipazione",
|
||||
"Back": "Indietro",
|
||||
"Back to Account": "Torna al conto",
|
||||
"Bar Chart": "Grafico a barre",
|
||||
"Browse": "Navigare",
|
||||
"Bulk JLG Loan Application": "Richiesta di prestito JLG in blocco",
|
||||
@@ -548,6 +549,7 @@
|
||||
"View Journal Entries": "Visualizza le voci del diario",
|
||||
"View Standing Instructions": "Visualizza le istruzioni per la posizione in piedi",
|
||||
"View Transactions History": "Visualizza la cronologia delle transazioni",
|
||||
"View Transactions": "Visualizza transazioni",
|
||||
"Waive": "Rinuncia",
|
||||
"Waive Charge": "Rinuncia all'addebito",
|
||||
"Week": "Settimana",
|
||||
@@ -926,6 +928,8 @@
|
||||
"Assets / Liability": "Attività/Passività",
|
||||
"Audit Trails": "Percorsi di controllo",
|
||||
"Balance": "Bilancia",
|
||||
"Beneficiary": "Beneficiario",
|
||||
"Beneficiary Selection": "Selezione del beneficiario",
|
||||
"Block Savings Account": "Bloccare il conto di risparmio",
|
||||
"Bulk Import": "Importazione in blocco",
|
||||
"Bulk Loan Reassignment": "Riassegnazione del prestito in blocco",
|
||||
@@ -1231,6 +1235,10 @@
|
||||
"Transaction Reverted": "Transazione annullata",
|
||||
"Transactions": "Transazioni",
|
||||
"Transfer Details": "Dettagli del trasferimento",
|
||||
"Transfer Failed": "Trasferimento fallito",
|
||||
"Transfer Status": "Stato del trasferimento",
|
||||
"Transfer Successful": "Trasferimento riuscito",
|
||||
"Transfer Summary": "Riepilogo del trasferimento",
|
||||
"Transferred From": "Trasferito da",
|
||||
"Transferred To": "Trasferito a",
|
||||
"Transferring From Details": "Trasferimento dai dettagli",
|
||||
|
||||
@@ -347,6 +347,7 @@
|
||||
"Attach Meeting": "회의 첨부",
|
||||
"Attendance": "출석",
|
||||
"Back": "뒤쪽에",
|
||||
"Back to Account": "계좌로 돌아가기",
|
||||
"Bar Chart": "막대 차트",
|
||||
"Browse": "검색",
|
||||
"Bulk JLG Loan Application": "대량 JLG 대출 신청",
|
||||
@@ -548,6 +549,7 @@
|
||||
"View Journal Entries": "저널 항목 보기",
|
||||
"View Standing Instructions": "기립 지침 보기",
|
||||
"View Transactions History": "거래 내역 보기",
|
||||
"View Transactions": "거래 보기",
|
||||
"Waive": "면제",
|
||||
"Waive Charge": "요금 면제",
|
||||
"Week": "주",
|
||||
@@ -927,6 +929,8 @@
|
||||
"Assets / Liability": "자산/부채",
|
||||
"Audit Trails": "감사 추적",
|
||||
"Balance": "균형",
|
||||
"Beneficiary": "수익자",
|
||||
"Beneficiary Selection": "수익자 선택",
|
||||
"Block Savings Account": "블록저축계좌",
|
||||
"Bulk Import": "대량 가져오기",
|
||||
"Bulk Loan Reassignment": "대량대출 재할당",
|
||||
@@ -1233,6 +1237,10 @@
|
||||
"Transaction Reverted": "거래가 되돌려졌습니다.",
|
||||
"Transactions": "업무",
|
||||
"Transfer Details": "전송 세부 정보",
|
||||
"Transfer Failed": "이체 실패",
|
||||
"Transfer Status": "이체 상태",
|
||||
"Transfer Successful": "이체 성공",
|
||||
"Transfer Summary": "이체 요약",
|
||||
"Transferred From": "다음에서 전송됨",
|
||||
"Transferred To": "로 전송",
|
||||
"Transferring From Details": "세부정보에서 전송 중",
|
||||
|
||||
@@ -347,6 +347,7 @@
|
||||
"Attach Meeting": "Pridėti susitikimą",
|
||||
"Attendance": "Lankomumas",
|
||||
"Back": "Atgal",
|
||||
"Back to Account": "Grįžti į sąskaitą",
|
||||
"Bar Chart": "Juostinė diagrama",
|
||||
"Browse": "Naršyti",
|
||||
"Bulk JLG Loan Application": "Masinės JLG paskolos paraiška",
|
||||
@@ -548,6 +549,7 @@
|
||||
"View Journal Entries": "Peržiūrėkite žurnalo įrašus",
|
||||
"View Standing Instructions": "Peržiūrėkite nuolatines instrukcijas",
|
||||
"View Transactions History": "Peržiūrėkite operacijų istoriją",
|
||||
"View Transactions": "Peržiūrėti operacijas",
|
||||
"Waive": "Atsisakyti",
|
||||
"Waive Charge": "Atsisakyti mokesčio",
|
||||
"Week": "Savaitė",
|
||||
@@ -925,6 +927,8 @@
|
||||
"Assets / Liability": "Turtas / įsipareigojimai",
|
||||
"Audit Trails": "Audito takai",
|
||||
"Balance": "Balansas",
|
||||
"Beneficiary": "Gavėjas",
|
||||
"Beneficiary Selection": "Gavėjo pasirinkimas",
|
||||
"Block Savings Account": "Blokuoti taupomąją sąskaitą",
|
||||
"Bulk Import": "Masinis importas",
|
||||
"Bulk Loan Reassignment": "Masinės paskolos perskirstymas",
|
||||
@@ -1230,6 +1234,10 @@
|
||||
"Transaction Reverted": "Sandoris grąžintas",
|
||||
"Transactions": "Sandoriai",
|
||||
"Transfer Details": "Pervedimo informacija",
|
||||
"Transfer Failed": "Pervedimas nepavyko",
|
||||
"Transfer Status": "Pervedimo būsena",
|
||||
"Transfer Successful": "Pervedimas sėkmingas",
|
||||
"Transfer Summary": "Pervedimo santrauka",
|
||||
"Transferred From": "Perkelta iš",
|
||||
"Transferred To": "Perkelta į",
|
||||
"Transferring From Details": "Perkėlimas iš detalių",
|
||||
|
||||
@@ -347,6 +347,7 @@
|
||||
"Attach Meeting": "Pievienot sapulci",
|
||||
"Attendance": "Apmeklējums",
|
||||
"Back": "Atpakaļ",
|
||||
"Back to Account": "Atpakaļ uz kontu",
|
||||
"Bar Chart": "Joslu diagramma",
|
||||
"Browse": "Pārlūkot",
|
||||
"Bulk JLG Loan Application": "Lielapjoma JLG aizdevuma pieteikums",
|
||||
@@ -548,6 +549,7 @@
|
||||
"View Journal Entries": "Skatīt žurnāla ierakstus",
|
||||
"View Standing Instructions": "Skatiet pastāvīgās instrukcijas",
|
||||
"View Transactions History": "Skatiet darījumu vēsturi",
|
||||
"View Transactions": "Skatīt darījumus",
|
||||
"Waive": "Atteikties",
|
||||
"Waive Charge": "Atteikties no maksas",
|
||||
"Week": "nedēļa",
|
||||
@@ -927,6 +929,8 @@
|
||||
"Assets / Liability": "Aktīvi / Pasīvi",
|
||||
"Audit Trails": "Revīzijas pēdas",
|
||||
"Balance": "Līdzsvars",
|
||||
"Beneficiary": "Saņēmējs",
|
||||
"Beneficiary Selection": "Saņēmēja izvēle",
|
||||
"Block Savings Account": "Bloķēt krājkontu",
|
||||
"Bulk Import": "Lielapjoma importēšana",
|
||||
"Bulk Loan Reassignment": "Lielapjoma aizdevuma pārcelšana",
|
||||
@@ -1232,6 +1236,10 @@
|
||||
"Transaction Reverted": "Darījums ir atsaukts",
|
||||
"Transactions": "Darījumi",
|
||||
"Transfer Details": "Pārskaitījuma informācija",
|
||||
"Transfer Failed": "Pārskaitījums neizdevās",
|
||||
"Transfer Status": "Pārskaitījuma statuss",
|
||||
"Transfer Successful": "Pārskaitījums veiksmīgs",
|
||||
"Transfer Summary": "Pārskaitījuma kopsavilkums",
|
||||
"Transferred From": "Pārsūtīts no",
|
||||
"Transferred To": "Pārsūtīts uz",
|
||||
"Transferring From Details": "Pārsūtīšana no detaļām",
|
||||
|
||||
@@ -347,6 +347,7 @@
|
||||
"Attach Meeting": "बैठक संलग्न गर्नुहोस्",
|
||||
"Attendance": "उपस्थित",
|
||||
"Back": "पछाडि",
|
||||
"Back to Account": "खातामा फर्कनुहोस्",
|
||||
"Bar Chart": "बार चार्ट",
|
||||
"Browse": "ब्राउज गर्नुहोस्",
|
||||
"Bulk JLG Loan Application": "थोक JLG ऋण आवेदन",
|
||||
@@ -548,6 +549,7 @@
|
||||
"View Journal Entries": "जर्नल प्रविष्टिहरू हेर्नुहोस्",
|
||||
"View Standing Instructions": "स्थायी निर्देशनहरू हेर्नुहोस्",
|
||||
"View Transactions History": "लेनदेन इतिहास हेर्नुहोस्",
|
||||
"View Transactions": "लेनदेन हेर्नुहोस्",
|
||||
"Waive": "छुट",
|
||||
"Waive Charge": "शुल्क छुट",
|
||||
"Week": "हप्ता",
|
||||
@@ -925,6 +927,8 @@
|
||||
"Assets / Liability": "सम्पत्ति / दायित्व",
|
||||
"Audit Trails": "अडिट ट्रेलहरू",
|
||||
"Balance": "सन्तुलन",
|
||||
"Beneficiary": "लाभग्राही",
|
||||
"Beneficiary Selection": "लाभग्राही छनोट",
|
||||
"Block Savings Account": "बचत खाता रोक्नुहोस्",
|
||||
"Bulk Import": "थोक आयात",
|
||||
"Bulk Loan Reassignment": "बल्क ऋण पुन: असाइनमेन्ट",
|
||||
@@ -1230,6 +1234,10 @@
|
||||
"Transaction Reverted": "कारोबार फिर्ता गरियो",
|
||||
"Transactions": "लेनदेन",
|
||||
"Transfer Details": "स्थानान्तरण विवरणहरू",
|
||||
"Transfer Failed": "स्थानान्तरण असफल भयो",
|
||||
"Transfer Status": "स्थानान्तरण स्थिति",
|
||||
"Transfer Successful": "स्थानान्तरण सफल भयो",
|
||||
"Transfer Summary": "स्थानान्तरण सारांश",
|
||||
"Transferred From": "बाट स्थानान्तरण गरियो",
|
||||
"Transferred To": "मा हस्तान्तरण गरियो",
|
||||
"Transferring From Details": "विवरणहरूबाट स्थानान्तरण गर्दै",
|
||||
|
||||
@@ -347,6 +347,7 @@
|
||||
"Attach Meeting": "Anexar reunião",
|
||||
"Attendance": "Comparecimento",
|
||||
"Back": "Voltar",
|
||||
"Back to Account": "Voltar para a Conta",
|
||||
"Bar Chart": "Gráfico de barras",
|
||||
"Browse": "Navegar",
|
||||
"Bulk JLG Loan Application": "Solicitação de empréstimo JLG em massa",
|
||||
@@ -548,6 +549,7 @@
|
||||
"View Journal Entries": "Ver lançamentos contábeis manuais",
|
||||
"View Standing Instructions": "Ver instruções permanentes",
|
||||
"View Transactions History": "Ver histórico de transações",
|
||||
"View Transactions": "Ver transações",
|
||||
"Waive": "Renunciar",
|
||||
"Waive Charge": "Isenção de cobrança",
|
||||
"Week": "Semana",
|
||||
@@ -927,6 +929,8 @@
|
||||
"Assets / Liability": "Ativos/Passivos",
|
||||
"Audit Trails": "Trilhas de auditoria",
|
||||
"Balance": "Equilíbrio",
|
||||
"Beneficiary": "Beneficiário",
|
||||
"Beneficiary Selection": "Seleção de Beneficiário",
|
||||
"Block Savings Account": "Bloquear conta poupança",
|
||||
"Bulk Import": "Importação em massa",
|
||||
"Bulk Loan Reassignment": "Reatribuição de empréstimo em massa",
|
||||
@@ -1231,6 +1235,10 @@
|
||||
"Transaction Reverted": "Transação revertida",
|
||||
"Transactions": "Transações",
|
||||
"Transfer Details": "Detalhes da transferência",
|
||||
"Transfer Failed": "Transferência falhou",
|
||||
"Transfer Status": "Status da transferência",
|
||||
"Transfer Successful": "Transferência bem-sucedida",
|
||||
"Transfer Summary": "Resumo da transferência",
|
||||
"Transferred From": "Transferido de",
|
||||
"Transferred To": "Transferido para",
|
||||
"Transferring From Details": "Transferindo de detalhes",
|
||||
|
||||
@@ -347,6 +347,7 @@
|
||||
"Attach Meeting": "Ambatanisha Mkutano",
|
||||
"Attendance": "Mahudhurio",
|
||||
"Back": "Nyuma",
|
||||
"Back to Account": "Rudi kwa Akaunti",
|
||||
"Bar Chart": "Chati ya Baa",
|
||||
"Browse": "Vinjari",
|
||||
"Bulk JLG Loan Application": "Maombi ya Mkopo wa Wingi wa JLG",
|
||||
@@ -548,6 +549,7 @@
|
||||
"View Journal Entries": "Tazama Maingizo ya Jarida",
|
||||
"View Standing Instructions": "Tazama Maagizo ya Kudumu",
|
||||
"View Transactions History": "Tazama Historia ya Shughuli",
|
||||
"View Transactions": "Tazama Shughuli",
|
||||
"Waive": "Acha",
|
||||
"Waive Charge": "Kuondoa Malipo",
|
||||
"Week": "Wiki",
|
||||
@@ -925,6 +927,8 @@
|
||||
"Assets / Liability": "Mali / Dhima",
|
||||
"Audit Trails": "Njia za Ukaguzi",
|
||||
"Balance": "Mizani",
|
||||
"Beneficiary": "Mnufaika",
|
||||
"Beneficiary Selection": "Uchaguzi wa Mnufaika",
|
||||
"Block Savings Account": "Zuia Akaunti ya Akiba",
|
||||
"Bulk Import": "Ingiza Wingi",
|
||||
"Bulk Loan Reassignment": "Ugawaji upya wa mkopo kwa wingi",
|
||||
@@ -1228,6 +1232,11 @@
|
||||
"Transaction Details": "Maelezo ya Muamala",
|
||||
"Transaction Reverted": "Muamala Umerejeshwa",
|
||||
"Transactions": "Shughuli",
|
||||
"Transfer Details": "Maelezo ya Uhamisho",
|
||||
"Transfer Failed": "Uhamisho Umeshindwa",
|
||||
"Transfer Status": "Hali ya Uhamisho",
|
||||
"Transfer Successful": "Uhamisho Umefanikiwa",
|
||||
"Transfer Summary": "Muhtasari wa Uhamisho",
|
||||
"Transferred From": "Imehamishwa Kutoka",
|
||||
"Transferred To": "Imehamishwa Kwa",
|
||||
"Transferring From Details": "Kuhamisha Kutoka kwa Maelezo",
|
||||
|
||||
Reference in New Issue
Block a user