feat: interbank transfer (#2299)
This commit is contained in:
+66
-4
@@ -1,5 +1,11 @@
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<div *ngIf="isLoading" 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-card *ngIf="!isLoading">
|
||||
<mat-card-content>
|
||||
<div fxLayout="row wrap" fxLayout.lt-md="column">
|
||||
<h3 class="mat-h3" fxFlexFill>{{ 'labels.heading.Transferring From Details' | translate }}</h3>
|
||||
@@ -36,11 +42,52 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="mat-h3" fxFlexFill>{{ 'labels.heading.Transferred To' | translate }}</h3>
|
||||
<div *ngIf="interbank">
|
||||
<div fxFlexFill>
|
||||
<h3 class="mat-h3" fxFlex="40%" fxLayoutAlign="start center">
|
||||
{{ 'labels.heading.Transferred To' | translate }}
|
||||
</h3>
|
||||
<mat-form-field fxFlex="40%">
|
||||
<mat-label>{{ 'labels.inputs.Phone Number' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[disabled]="interbankTransferForm"
|
||||
type="tel"
|
||||
#input
|
||||
[(ngModel)]="phoneAccount"
|
||||
maxlength="10"
|
||||
required
|
||||
/><!-- formControlName="phoneNumber" -->
|
||||
<mat-hint align="end">{{ phoneAccount.length || 0 }}/10</mat-hint>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<mat-card-actions
|
||||
*ngIf="!interbankTransferForm"
|
||||
fxLayout="row"
|
||||
fxLayout.xs="column"
|
||||
fxLayoutAlign="center"
|
||||
fxLayoutGap="5px"
|
||||
>
|
||||
<button type="button" mat-raised-button [routerLink]="['../..']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
[disabled]="phoneAccount.length !== 10"
|
||||
(click)="searchAccountByNumber()"
|
||||
*mifosxHasPermission="'CREATE_ACCOUNTTRANSFER'"
|
||||
id="search-button"
|
||||
>
|
||||
{{ 'labels.buttons.Search' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</div>
|
||||
|
||||
<mat-divider [inset]="true"></mat-divider>
|
||||
|
||||
<form [formGroup]="makeAccountTransferForm">
|
||||
<form *ngIf="!interbank" [formGroup]="makeAccountTransferForm">
|
||||
<div fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||
<mat-form-field fxFlex="98%" (click)="transferDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Transaction Date' | translate }}</mat-label>
|
||||
@@ -121,6 +168,10 @@
|
||||
{{ 'labels.inputs.Amount' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="makeAccountTransferForm.get('transferAmount')?.hasError('amountExceedsBalance')">
|
||||
<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 fxFlex="98%">
|
||||
@@ -138,9 +189,20 @@
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</form>
|
||||
<mifosx-make-account-interbank-transfers
|
||||
*ngIf="interbank && interbankTransferForm"
|
||||
[makeAccountTransferForm]="makeAccountTransferForm"
|
||||
[balance]="balance"
|
||||
></mifosx-make-account-interbank-transfers>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
|
||||
<mat-card-actions
|
||||
*ngIf="!interbank === !interbankTransferForm"
|
||||
fxLayout="row"
|
||||
fxLayout.xs="column"
|
||||
fxLayoutAlign="center"
|
||||
fxLayoutGap="5px"
|
||||
>
|
||||
<button type="button" mat-raised-button [routerLink]="['../..']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
|
||||
+16
@@ -20,3 +20,19 @@ mat-divider {
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
}
|
||||
|
||||
::ng-deep mat-form-field.error-warn.mat-form-field-invalid .mat-form-field-ripple {
|
||||
background-color: #000000de !important;
|
||||
}
|
||||
|
||||
::ng-deep mat-form-field.error-warn.mat-form-field-invalid .mat-form-field-label {
|
||||
color: #0009 !important;
|
||||
|
||||
.mat-form-field-required-marker {
|
||||
color: #0009 !important;
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep mat-form-field.error-warn.mat-form-field-invalid .mat-error {
|
||||
color: #0009 !important;
|
||||
}
|
||||
|
||||
+145
-12
@@ -1,13 +1,24 @@
|
||||
/** Angular Imports */
|
||||
import { Component, OnInit, AfterViewInit } from '@angular/core';
|
||||
import { Component, OnInit, AfterViewInit, ViewChild, ElementRef } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import {
|
||||
AbstractControl,
|
||||
FormGroup,
|
||||
UntypedFormBuilder,
|
||||
UntypedFormGroup,
|
||||
ValidationErrors,
|
||||
Validators
|
||||
} from '@angular/forms';
|
||||
|
||||
/** Custom Services */
|
||||
import { AccountTransfersService } from '../account-transfers.service';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { ClientsService } from 'app/clients/clients.service';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
import { MatInput } from '@angular/material/input';
|
||||
|
||||
/** Environment Configuration */
|
||||
import { environment } from 'environments/environment';
|
||||
|
||||
/**
|
||||
* Create account transfers
|
||||
@@ -26,6 +37,7 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
maxDate = new Date(2100, 0, 1);
|
||||
/** Edit Standing Instructions form. */
|
||||
makeAccountTransferForm: UntypedFormGroup;
|
||||
//makeAccountInterbankTransferForm: FormGroup;
|
||||
/** To Office Type Data */
|
||||
toOfficeTypeData: any;
|
||||
/** To Client Type Data */
|
||||
@@ -42,6 +54,13 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
id: any;
|
||||
/** Clients Data */
|
||||
clientsData: any;
|
||||
/** interbank transfer */
|
||||
interbank: boolean = false;
|
||||
/** Reference of phoneAccount search */
|
||||
phoneAccount = '';
|
||||
interbankTransferForm: boolean = false;
|
||||
balance: number = 0;
|
||||
isLoading: boolean = false;
|
||||
|
||||
/**
|
||||
* Retrieves the standing instructions template from `resolve`.
|
||||
@@ -77,8 +96,12 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
this.id = this.route.snapshot.queryParams['loanId'];
|
||||
break;
|
||||
case 'fromsavings':
|
||||
case 'interbank':
|
||||
this.accountTypeId = '2';
|
||||
this.id = this.route.snapshot.queryParams['savingsId'];
|
||||
this.interbank = this.route.snapshot.queryParams['interbank'] === 'true';
|
||||
this.balance = this.router.getCurrentNavigation().extras.state.balance;
|
||||
console.log('is interbank?', this.interbank);
|
||||
break;
|
||||
default:
|
||||
this.accountTypeId = '0';
|
||||
@@ -90,7 +113,9 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.maxDate = this.settingsService.businessDate;
|
||||
this.createMakeAccountTransferForm();
|
||||
if (!this.interbank) {
|
||||
this.createMakeAccountTransferForm();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,7 +141,10 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
],
|
||||
transferAmount: [
|
||||
this.accountTransferTemplateData.transferAmount,
|
||||
Validators.required
|
||||
[
|
||||
Validators.required,
|
||||
Validators.min(0.01),
|
||||
this.amountExceedsBalanceValidator.bind(this)]
|
||||
],
|
||||
transferDate: [
|
||||
this.settingsService.businessDate,
|
||||
@@ -129,6 +157,48 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
});
|
||||
}
|
||||
|
||||
createMakeAccountInterbankTransferForm(account: any) {
|
||||
/* --> */ this.makeAccountTransferForm = this.formBuilder.group({
|
||||
toBank: [
|
||||
{ value: account.sourceFspId, disabled: true },
|
||||
Validators.required
|
||||
],
|
||||
toClientId: [
|
||||
{ value: account.firsName + ' ' + account.lastName, disabled: true },
|
||||
Validators.required
|
||||
],
|
||||
toAccountType: [
|
||||
{ value: 'Saving Account', disabled: true },
|
||||
Validators.required
|
||||
],
|
||||
toAccountId: [
|
||||
{ value: account.partyId, disabled: true },
|
||||
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
|
||||
]
|
||||
});
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
amountExceedsBalanceValidator(control: AbstractControl): ValidationErrors | null {
|
||||
const amount = control.value;
|
||||
return amount > this.balance ? { amountExceedsBalance: true } : null;
|
||||
}
|
||||
|
||||
/** Sets options value */
|
||||
setOptions() {
|
||||
this.toOfficeTypeData = this.accountTransferTemplateData.toOfficeOptions;
|
||||
@@ -172,14 +242,16 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
* Subscribes to Clients search filter:
|
||||
*/
|
||||
ngAfterViewInit() {
|
||||
this.makeAccountTransferForm.controls.toClientId.valueChanges.subscribe((value: string) => {
|
||||
if (value.length >= 2) {
|
||||
this.clientsService.getFilteredClients('displayName', 'ASC', true, value).subscribe((data: any) => {
|
||||
this.clientsData = data.pageItems;
|
||||
});
|
||||
this.changeEvent();
|
||||
}
|
||||
});
|
||||
if (!this.interbank) {
|
||||
this.makeAccountTransferForm.controls.toClientId.valueChanges.subscribe((value: string) => {
|
||||
if (value.length >= 2) {
|
||||
this.clientsService.getFilteredClients('displayName', 'ASC', true, value).subscribe((data: any) => {
|
||||
this.clientsData = data.pageItems;
|
||||
});
|
||||
this.changeEvent();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,6 +267,11 @@ export class MakeAccountTransfersComponent implements OnInit, AfterViewInit {
|
||||
* Submits the standing instructions form
|
||||
*/
|
||||
submit() {
|
||||
this.interbank ? this.makeInterbankTransfer() : this.makeTransfer();
|
||||
}
|
||||
|
||||
makeTransfer() {
|
||||
this.isLoading = true;
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
const locale = this.settingsService.language.code;
|
||||
const makeAccountTransferData = {
|
||||
@@ -209,7 +286,63 @@ 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 });
|
||||
});
|
||||
}
|
||||
|
||||
makeInterbankTransfer() {
|
||||
this.isLoading = true;
|
||||
const payload = {
|
||||
homeTransactionId: crypto.randomUUID(),
|
||||
from: {
|
||||
fspId: environment.fineractPlatformTenantId,
|
||||
idType: 'MSISDN',
|
||||
idValue: this.accountTransferTemplateData.fromAccount.externalId.trim()
|
||||
},
|
||||
to: {
|
||||
fspId: this.makeAccountTransferForm.controls.toBank.value,
|
||||
idType: 'MSISDN',
|
||||
idValue: this.makeAccountTransferForm.controls.toAccountId.value
|
||||
},
|
||||
amountType: 'SEND',
|
||||
amount: {
|
||||
currencyCode: this.accountTransferTemplateData.currency.code,
|
||||
amount: this.makeAccountTransferForm.controls.transferAmount.value
|
||||
},
|
||||
transactionType: {
|
||||
scenario: 'TRANSFER',
|
||||
subScenario: 'DOMESTIC',
|
||||
initiator: 'PAYER',
|
||||
initiatorType: 'CUSTOMER'
|
||||
},
|
||||
note: this.makeAccountTransferForm.controls.transferDescription.value
|
||||
};
|
||||
this.accountTransfersService.sendInterbankTransfer(JSON.stringify(payload)).subscribe(
|
||||
(trnsfr) => {
|
||||
if (trnsfr.systemMessage) {
|
||||
this.isLoading = false;
|
||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
this.isLoading = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
searchAccountByNumber() {
|
||||
this.isLoading = true;
|
||||
this.accountTransfersService
|
||||
.getAccountByNumber(this.phoneAccount, this.accountTransferTemplateData.currency.code)
|
||||
.subscribe(
|
||||
(acc) => {
|
||||
this.interbankTransferForm = true;
|
||||
this.createMakeAccountInterbankTransferForm(acc);
|
||||
},
|
||||
(error) => {
|
||||
this.isLoading = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user