mirror of
https://github.com/valitydev/control-center.git
synced 2024-11-06 02:25:17 +00:00
IMP-216: Show terminal balances (#353)
This commit is contained in:
parent
af263c950b
commit
9145b78845
8
package-lock.json
generated
8
package-lock.json
generated
@ -28,7 +28,7 @@
|
||||
"@vality/ng-core": "17.2.1-pr-60-8d151ad.0",
|
||||
"@vality/payout-manager-proto": "2.0.1-eb4091a.0",
|
||||
"@vality/repairer-proto": "2.0.2-07b73e9.0",
|
||||
"@vality/scrooge-proto": "0.1.0",
|
||||
"@vality/scrooge-proto": "0.1.1-9ce7fc6.0",
|
||||
"@vality/thrift-ts": "2.4.1-8ad5123.0",
|
||||
"@vality/woody": "0.1.3",
|
||||
"date-fns": "^3.3.1",
|
||||
@ -6504,9 +6504,9 @@
|
||||
"integrity": "sha512-PwWTzgIrqTKqZVRW235ZPIoQz+Rvf0RavVhTrPwMxRDvkZLcRd7WN6O6rIYNcz84BZXJ5r4YnyN0kWCaLvGdqw=="
|
||||
},
|
||||
"node_modules/@vality/scrooge-proto": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@vality/scrooge-proto/-/scrooge-proto-0.1.0.tgz",
|
||||
"integrity": "sha512-yZkzqVUBpkNtM8lT1HT5yRiZ5tVh+nxVj+gP7NUQB36FIfP0ZSJWxZIdedvulWApiYXbn1M/oDsyhnc62iz2Mw=="
|
||||
"version": "0.1.1-9ce7fc6.0",
|
||||
"resolved": "https://registry.npmjs.org/@vality/scrooge-proto/-/scrooge-proto-0.1.1-9ce7fc6.0.tgz",
|
||||
"integrity": "sha512-g/G5W8Bci84gk7TUT27sOCwgdOUv0tOYkF9K0fgD8deZ/5lvJ55Zz7g5/XuV+LhBm0NGTEZvNwAWHTtSI3C4dw=="
|
||||
},
|
||||
"node_modules/@vality/thrift-ts": {
|
||||
"version": "2.4.1-8ad5123.0",
|
||||
|
@ -36,7 +36,7 @@
|
||||
"@vality/ng-core": "17.2.1-pr-60-8d151ad.0",
|
||||
"@vality/payout-manager-proto": "2.0.1-eb4091a.0",
|
||||
"@vality/repairer-proto": "2.0.2-07b73e9.0",
|
||||
"@vality/scrooge-proto": "0.1.0",
|
||||
"@vality/scrooge-proto": "0.1.1-9ce7fc6.0",
|
||||
"@vality/thrift-ts": "2.4.1-8ad5123.0",
|
||||
"@vality/woody": "0.1.3",
|
||||
"date-fns": "^3.3.1",
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { getImportValue } from '@vality/ng-core';
|
||||
import {
|
||||
terminal_balance_TerminalServiceCodegenClient,
|
||||
account_balance_AccountServiceCodegenClient,
|
||||
ThriftAstMetadata,
|
||||
terminal_balance_TerminalService,
|
||||
account_balance_AccountService,
|
||||
} from '@vality/scrooge-proto';
|
||||
import { combineLatest, map, Observable, switchMap } from 'rxjs';
|
||||
|
||||
@ -12,8 +12,8 @@ import { ConfigService } from '../../core/config.service';
|
||||
import { KeycloakTokenInfoService, toWachterHeaders } from '../../shared/services';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class TerminalBalanceService {
|
||||
private client$: Observable<terminal_balance_TerminalServiceCodegenClient>;
|
||||
export class AccountBalanceService {
|
||||
private client$: Observable<account_balance_AccountServiceCodegenClient>;
|
||||
|
||||
constructor(
|
||||
private keycloakTokenInfoService: KeycloakTokenInfoService,
|
||||
@ -25,7 +25,7 @@ export class TerminalBalanceService {
|
||||
);
|
||||
this.client$ = combineLatest([metadata$, headers$]).pipe(
|
||||
switchMap(([metadata, headers]) =>
|
||||
terminal_balance_TerminalService({
|
||||
account_balance_AccountService({
|
||||
metadata,
|
||||
headers,
|
||||
logging: environment.logging.requests,
|
||||
@ -37,6 +37,6 @@ export class TerminalBalanceService {
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
GetTerminalBalances() {
|
||||
return this.client$.pipe(switchMap((c) => c.GetTerminalBalances()));
|
||||
return this.client$.pipe(switchMap((c) => c.GetAccountBalances()));
|
||||
}
|
||||
}
|
@ -1,2 +1,2 @@
|
||||
export * from './terminal-balance.service';
|
||||
export * from './stores/terminal-balances-store.service';
|
||||
export * from './account-balance.service';
|
||||
export * from './stores/account-balances-store.service';
|
||||
|
@ -0,0 +1,45 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AccountBalance } from '@vality/scrooge-proto/internal/account_balance';
|
||||
import isNil from 'lodash-es/isNil';
|
||||
import { of, Observable } from 'rxjs';
|
||||
import { shareReplay, map, catchError, startWith } from 'rxjs/operators';
|
||||
|
||||
import { AccountBalanceService } from '../account-balance.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class AccountBalancesStoreService {
|
||||
balances$: Observable<AccountBalance[]> = this.terminalBalanceService
|
||||
.GetTerminalBalances()
|
||||
.pipe(
|
||||
map((b) => b.balances),
|
||||
startWith([]),
|
||||
catchError(() => {
|
||||
console.error('Account balances are not loaded');
|
||||
return of([]);
|
||||
}),
|
||||
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||
);
|
||||
|
||||
constructor(private terminalBalanceService: AccountBalanceService) {}
|
||||
|
||||
getAccountBalance(id: string | number) {
|
||||
return this.balances$.pipe(
|
||||
map((balances) => balances.find((b) => b.account_id === String(id))),
|
||||
);
|
||||
}
|
||||
|
||||
getTerminalBalances(id: string | number, providerId?: string | number) {
|
||||
return this.balances$.pipe(
|
||||
map((balances) =>
|
||||
balances.filter(
|
||||
(b) =>
|
||||
!isNil(providerId) &&
|
||||
b.provider.id === String(providerId) &&
|
||||
b.terminal.id === String(id),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { TerminalBalance } from '@vality/scrooge-proto/internal/terminal_balance';
|
||||
import { of, Observable } from 'rxjs';
|
||||
import { shareReplay, map, catchError, startWith } from 'rxjs/operators';
|
||||
|
||||
import { TerminalBalanceService } from '../terminal-balance.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class TerminalBalancesStoreService {
|
||||
balances$: Observable<TerminalBalance[]> = this.terminalBalanceService
|
||||
.GetTerminalBalances()
|
||||
.pipe(
|
||||
map((b) => b.balances),
|
||||
startWith([]),
|
||||
catchError(() => {
|
||||
console.error('Terminal balances are not loaded');
|
||||
return of([]);
|
||||
}),
|
||||
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||
);
|
||||
|
||||
constructor(private terminalBalanceService: TerminalBalanceService) {}
|
||||
|
||||
getTerminalBalance(id: string | number) {
|
||||
return this.balances$.pipe(
|
||||
map((balances) => balances.find((b) => b.terminal.id === String(id))),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { Component, DestroyRef, isDevMode } from '@angular/core';
|
||||
import { Component, DestroyRef } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { Sort } from '@angular/material/sort';
|
||||
import { TerminalObject } from '@vality/domain-proto/domain';
|
||||
@ -7,8 +7,8 @@ import { of } from 'rxjs';
|
||||
import { map, take } from 'rxjs/operators';
|
||||
|
||||
import { DomainStoreService } from '../../api/domain-config';
|
||||
import { TerminalBalancesStoreService } from '../../api/terminal-balance';
|
||||
import { createPredicateColumn, createCurrencyColumn } from '../../shared';
|
||||
import { AccountBalancesStoreService } from '../../api/terminal-balance';
|
||||
import { createPredicateColumn, createCurrenciesColumn } from '../../shared';
|
||||
import { SidenavInfoService } from '../../shared/components/sidenav-info';
|
||||
import { TerminalDelegatesCardComponent } from '../../shared/components/terminal-delegates-card/terminal-delegates-card.component';
|
||||
import {
|
||||
@ -69,26 +69,34 @@ export class TerminalsComponent {
|
||||
});
|
||||
},
|
||||
},
|
||||
...(isDevMode()
|
||||
? [
|
||||
createCurrencyColumn<TerminalObject>(
|
||||
'balance',
|
||||
(d) =>
|
||||
this.terminalBalancesStoreService
|
||||
.getTerminalBalance(d.ref.id)
|
||||
.pipe(
|
||||
map((b) =>
|
||||
b?.balance?.amount ? Number(b.balance.amount) : undefined,
|
||||
),
|
||||
),
|
||||
(d) =>
|
||||
this.terminalBalancesStoreService
|
||||
.getTerminalBalance(d.ref.id)
|
||||
.pipe(map((b) => b?.balance?.currency_code)),
|
||||
{ sortable: true },
|
||||
),
|
||||
]
|
||||
: []),
|
||||
createCurrenciesColumn<TerminalObject>(
|
||||
'balances',
|
||||
(d) =>
|
||||
this.accountBalancesStoreService
|
||||
.getTerminalBalances(d.ref.id, d.data.provider_ref.id)
|
||||
.pipe(
|
||||
map((b) =>
|
||||
b.map((a) => ({
|
||||
amount: a.balance.amount,
|
||||
symbolicCode: a.balance.currency_code,
|
||||
})),
|
||||
),
|
||||
),
|
||||
{
|
||||
sortable: true,
|
||||
tooltip: (d) =>
|
||||
this.accountBalancesStoreService
|
||||
.getTerminalBalances(d.ref.id, d.data.provider_ref.id)
|
||||
.pipe(
|
||||
map((accountBalance) =>
|
||||
accountBalance
|
||||
.sort((a, b) => b.balance.amount - a.balance.amount)
|
||||
.map((a) => a.account_id)
|
||||
.join(', '),
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
];
|
||||
data$ = this.domainStoreService.getObjects('terminal');
|
||||
progress$ = this.domainStoreService.isLoading$;
|
||||
@ -99,7 +107,7 @@ export class TerminalsComponent {
|
||||
private sidenavInfoService: SidenavInfoService,
|
||||
private destroyRef: DestroyRef,
|
||||
private dialogService: DialogService,
|
||||
private terminalBalancesStoreService: TerminalBalancesStoreService,
|
||||
private accountBalancesStoreService: AccountBalancesStoreService,
|
||||
) {}
|
||||
|
||||
update() {
|
||||
|
@ -1,7 +1,14 @@
|
||||
import { inject } from '@angular/core';
|
||||
import { CurrencyColumn, PossiblyAsync, getPossiblyAsyncObservable } from '@vality/ng-core';
|
||||
import { inject, LOCALE_ID } from '@angular/core';
|
||||
import {
|
||||
CurrencyColumn,
|
||||
PossiblyAsync,
|
||||
getPossiblyAsyncObservable,
|
||||
Column,
|
||||
switchCombineWith,
|
||||
formatCurrency,
|
||||
} from '@vality/ng-core';
|
||||
import isNil from 'lodash-es/isNil';
|
||||
import { combineLatest, switchMap, of } from 'rxjs';
|
||||
import { combineLatest, switchMap, of, forkJoin, Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { AmountCurrencyService } from '../../services';
|
||||
@ -36,3 +43,53 @@ export function createCurrencyColumn<T extends object>(
|
||||
...params,
|
||||
};
|
||||
}
|
||||
|
||||
export function createCurrenciesColumn<T extends object>(
|
||||
field: CurrencyColumn<T>['field'],
|
||||
selectAmountSymbolicCode: (d: T) => PossiblyAsync<{ amount: number; symbolicCode: string }[]>,
|
||||
params: Partial<CurrencyColumn<T>> = {},
|
||||
): Column<T> {
|
||||
const amountCurrencyService = inject(AmountCurrencyService);
|
||||
const localeId = inject(LOCALE_ID);
|
||||
|
||||
function getBalancesList(amountCodes$: Observable<{ amount: number; symbolicCode: string }[]>) {
|
||||
return amountCodes$.pipe(
|
||||
switchCombineWith((amountCodes) =>
|
||||
!amountCodes?.length
|
||||
? ([] as Observable<number[]>[])
|
||||
: [
|
||||
forkJoin(
|
||||
amountCodes.map((a) =>
|
||||
amountCurrencyService.toMajor(a.amount, a.symbolicCode),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
map(([amountCodes, majorAmounts]) =>
|
||||
amountCodes
|
||||
.map((a, idx) =>
|
||||
formatCurrency(
|
||||
majorAmounts[idx],
|
||||
a.symbolicCode,
|
||||
undefined,
|
||||
localeId,
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
)
|
||||
.join(' / '),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
const getAmountCodes = (d: T) =>
|
||||
getPossiblyAsyncObservable(selectAmountSymbolicCode(d)).pipe(
|
||||
map((amountCodes) => (amountCodes || []).sort((a, b) => b.amount - a.amount)),
|
||||
);
|
||||
return {
|
||||
field,
|
||||
formatter: (d: T) => getBalancesList(getAmountCodes(d).pipe(map((a) => a?.slice?.(0, 1)))),
|
||||
description: (d: T) => getBalancesList(getAmountCodes(d).pipe(map((a) => a?.slice?.(1)))),
|
||||
...params,
|
||||
} as Column<T>;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user