mirror of
https://github.com/valitydev/control-center.git
synced 2024-11-06 02:25:17 +00:00
IMP-134: Add withdrawals and payments errors search (#318)
This commit is contained in:
parent
598c778fae
commit
115de955b4
4034
package-lock.json
generated
4034
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
33
package.json
33
package.json
@ -16,23 +16,23 @@
|
||||
"fix": "npm run lint:fix && npm run format:fix && npm run spell:fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "17.0.8",
|
||||
"@angular/cdk": "17.0.4",
|
||||
"@angular/common": "17.0.8",
|
||||
"@angular/compiler": "17.0.8",
|
||||
"@angular/core": "17.0.8",
|
||||
"@angular/forms": "17.0.8",
|
||||
"@angular/material": "17.0.4",
|
||||
"@angular/platform-browser": "17.0.8",
|
||||
"@angular/platform-browser-dynamic": "17.0.8",
|
||||
"@angular/platform-server": "17.0.8",
|
||||
"@angular/router": "17.0.8",
|
||||
"@angular/animations": "17.1.1",
|
||||
"@angular/cdk": "17.1.1",
|
||||
"@angular/common": "17.1.1",
|
||||
"@angular/compiler": "17.1.1",
|
||||
"@angular/core": "17.1.1",
|
||||
"@angular/forms": "17.1.1",
|
||||
"@angular/material": "17.1.1",
|
||||
"@angular/platform-browser": "17.1.1",
|
||||
"@angular/platform-browser-dynamic": "17.1.1",
|
||||
"@angular/platform-server": "17.1.1",
|
||||
"@angular/router": "17.1.1",
|
||||
"@ngneat/input-mask": "6.0.0",
|
||||
"@vality/deanonimus-proto": "2.0.1-2a02d87.0",
|
||||
"@vality/domain-proto": "2.0.1-23211ff.0",
|
||||
"@vality/fistful-proto": "2.0.1-3b9a0a7.0",
|
||||
"@vality/fistful-proto": "2.0.1-f2ca9b5.0",
|
||||
"@vality/machinegun-proto": "1.0.0",
|
||||
"@vality/magista-proto": "2.0.2-4383410.0",
|
||||
"@vality/magista-proto": "2.0.2-28d11b9.0",
|
||||
"@vality/ng-core": "^17.1.1-pr-57-8ca06c2.0",
|
||||
"@vality/payout-manager-proto": "2.0.1-eb4091a.0",
|
||||
"@vality/repairer-proto": "2.0.2-07b73e9.0",
|
||||
@ -54,12 +54,11 @@
|
||||
"zone.js": "0.14.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "17.0.8",
|
||||
"@angular-devkit/build-angular": "17.1.1",
|
||||
"@angular-eslint/builder": "17.1.1",
|
||||
"@angular-eslint/schematics": "17.1.1",
|
||||
"@angular/cli": "17.0.8",
|
||||
"@angular/compiler-cli": "17.0.8",
|
||||
"@types/element-resize-detector": "1.1.3",
|
||||
"@angular/cli": "17.1.1",
|
||||
"@angular/compiler-cli": "17.1.1",
|
||||
"@types/inputmask": "5.0.3",
|
||||
"@types/jasmine": "4.0.3",
|
||||
"@types/jwt-decode": "2.2.1",
|
||||
|
@ -50,8 +50,9 @@ export class DomainStoreService {
|
||||
}
|
||||
|
||||
getDomain(raw = false): Observable<Domain> {
|
||||
return this.snapshot$.pipe(
|
||||
map((s) => s?.domain),
|
||||
return combineLatest([defer(() => this.snapshot$), defer(() => this.progress$)]).pipe(
|
||||
filter(([, p]) => !p),
|
||||
map(([s]) => s?.domain),
|
||||
map((d) => (raw ? d : this.domainSecretService.reduceDomain(d))),
|
||||
);
|
||||
}
|
||||
|
@ -17,4 +17,5 @@ export interface WithdrawalParams extends PagedBaseParameters {
|
||||
currency_code?: string;
|
||||
from_time?: string;
|
||||
to_time?: string;
|
||||
error_message?: string;
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ import { PartiesStoreService } from '@cc/app/api/payment-processing';
|
||||
import { AmountCurrencyService } from '@cc/app/shared/services';
|
||||
import { getUnionKey } from '@cc/utils';
|
||||
|
||||
import { createFailureColumn } from '../../../../shared';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-payments-table',
|
||||
templateUrl: './payments-table.component.html',
|
||||
@ -82,6 +84,13 @@ export class PaymentsTableComponent {
|
||||
'domain_revision',
|
||||
{ field: 'terminal_id.id', header: 'Terminal' },
|
||||
{ field: 'provider_id.id', header: 'Provider' },
|
||||
createFailureColumn<StatPayment>(
|
||||
(d) => d.status?.failed?.failure?.failure,
|
||||
(d) =>
|
||||
getUnionKey(d.status?.failed?.failure) === 'failure'
|
||||
? ''
|
||||
: startCase(getUnionKey(d.status?.failed?.failure)),
|
||||
),
|
||||
createOperationColumn<StatPayment>([
|
||||
{
|
||||
label: 'Details',
|
||||
|
@ -21,6 +21,7 @@
|
||||
<v-input-field formControlName="payment_last4" label="Card PAN"></v-input-field>
|
||||
<v-input-field formControlName="payment_rrn" label="Payment RRN"></v-input-field>
|
||||
<v-input-field formControlName="payment_email" label="Payer email"></v-input-field>
|
||||
<v-input-field formControlName="error_message" label="Error message"></v-input-field>
|
||||
</ng-template>
|
||||
<ng-template vOtherFilters>
|
||||
<cc-metadata-form
|
||||
|
@ -45,6 +45,7 @@ export class PaymentsComponent implements OnInit {
|
||||
payment_last4: undefined as string,
|
||||
payment_rrn: undefined as string,
|
||||
payment_email: undefined as string,
|
||||
error_message: undefined as string,
|
||||
});
|
||||
otherFiltersControl = this.fb.control({
|
||||
common_search_query_params: {},
|
||||
@ -64,6 +65,7 @@ export class PaymentsComponent implements OnInit {
|
||||
'payment_first6',
|
||||
'payment_last4',
|
||||
'payment_rrn',
|
||||
'error_message',
|
||||
].includes(data?.field?.name),
|
||||
),
|
||||
extension: () => of({ hidden: true }),
|
||||
@ -122,6 +124,7 @@ export class PaymentsComponent implements OnInit {
|
||||
payment_first6: filters.payment_first6,
|
||||
payment_last4: filters.payment_last4,
|
||||
payment_rrn: filters.payment_rrn,
|
||||
error_message: filters.error_message,
|
||||
},
|
||||
invoice_ids: filters.invoice_ids,
|
||||
}),
|
||||
|
@ -20,14 +20,8 @@
|
||||
<mat-label>Wallet ID</mat-label>
|
||||
<input formControlName="walletId" matInput />
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>Amount from</mat-label>
|
||||
<input formControlName="amountFrom" matInput type="number" />
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>Amount to</mat-label>
|
||||
<input formControlName="amountTo" matInput type="number" />
|
||||
</mat-form-field>
|
||||
<v-number-range-field formControlName="amount" label="Amount"></v-number-range-field>
|
||||
<v-input-field formControlName="errorMessage" label="Error message"></v-input-field>
|
||||
</ng-template>
|
||||
</v-filters>
|
||||
|
||||
|
@ -13,13 +13,16 @@ import {
|
||||
DateRange,
|
||||
getNoTimeZoneIsoString,
|
||||
DialogResponseStatus,
|
||||
NumberRange,
|
||||
} from '@vality/ng-core';
|
||||
import { endOfDay } from 'date-fns';
|
||||
import startCase from 'lodash-es/startCase';
|
||||
import { debounceTime } from 'rxjs/operators';
|
||||
|
||||
import { WithdrawalParams } from '@cc/app/api/fistful-stat';
|
||||
|
||||
import { getUnionKey } from '../../../utils';
|
||||
import { createFailureColumn } from '../../shared';
|
||||
import { FailMachinesDialogComponent, Type } from '../../shared/components/fail-machines-dialog';
|
||||
import { AmountCurrencyService } from '../../shared/services';
|
||||
|
||||
@ -30,10 +33,10 @@ interface WithdrawalsForm {
|
||||
dateRange: DateRange;
|
||||
merchant: PartyID;
|
||||
status: WithdrawalParams['status'];
|
||||
amountFrom: WithdrawalParams['amount_from'];
|
||||
amountTo: WithdrawalParams['amount_to'];
|
||||
amount: NumberRange;
|
||||
withdrawalIds: WithdrawalParams['withdrawal_ids'];
|
||||
walletId: WithdrawalParams['wallet_id'];
|
||||
errorMessage: WithdrawalParams['error_message'];
|
||||
}
|
||||
|
||||
@Component({
|
||||
@ -46,10 +49,10 @@ export class WithdrawalsComponent implements OnInit {
|
||||
dateRange: null,
|
||||
merchant: null,
|
||||
status: null,
|
||||
amountFrom: null,
|
||||
amountTo: null,
|
||||
amount: null,
|
||||
withdrawalIds: null,
|
||||
walletId: null,
|
||||
errorMessage: null,
|
||||
...this.qp.params,
|
||||
});
|
||||
active = 0;
|
||||
@ -93,6 +96,7 @@ export class WithdrawalsComponent implements OnInit {
|
||||
},
|
||||
},
|
||||
},
|
||||
createFailureColumn<StatWithdrawal>((d) => d.status?.failed?.base_failure),
|
||||
];
|
||||
selected: StatWithdrawal[] = [];
|
||||
statuses: WithdrawalParams['status'][] = ['Pending', 'Succeeded', 'Failed'];
|
||||
@ -110,26 +114,27 @@ export class WithdrawalsComponent implements OnInit {
|
||||
this.filtersForm.valueChanges
|
||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe((v) => void this.qp.set(clean(v)));
|
||||
this.qp.params$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => this.update());
|
||||
this.qp.params$
|
||||
.pipe(debounceTime(500), takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe(() => this.update());
|
||||
}
|
||||
|
||||
update(options?: UpdateOptions) {
|
||||
const { dateRange, merchant, status, amountFrom, amountTo, withdrawalIds, walletId } =
|
||||
const { dateRange, merchant, status, amount, withdrawalIds, walletId, errorMessage } =
|
||||
this.qp.params;
|
||||
this.fetchWithdrawalsService.load(
|
||||
clean({
|
||||
const params = clean({
|
||||
party_id: merchant,
|
||||
from_time: dateRange?.start && getNoTimeZoneIsoString(dateRange?.start),
|
||||
to_time: dateRange?.end && getNoTimeZoneIsoString(endOfDay(dateRange?.end)),
|
||||
status: status,
|
||||
amount_from: amountFrom,
|
||||
amount_to: amountTo,
|
||||
amount_from: amount?.start,
|
||||
amount_to: amount?.end,
|
||||
withdrawal_ids: withdrawalIds,
|
||||
wallet_id: walletId,
|
||||
}),
|
||||
options,
|
||||
);
|
||||
this.active = countProps(clean(this.qp.params));
|
||||
error_message: errorMessage,
|
||||
});
|
||||
this.fetchWithdrawalsService.load(params, options);
|
||||
this.active = countProps(params);
|
||||
}
|
||||
|
||||
more() {
|
||||
|
@ -17,6 +17,7 @@ import {
|
||||
FiltersModule,
|
||||
NumberRangeFieldModule,
|
||||
DateRangeFieldModule,
|
||||
InputFieldModule,
|
||||
} from '@vality/ng-core';
|
||||
|
||||
import { PageLayoutModule } from '../../shared';
|
||||
@ -52,6 +53,8 @@ import { WithdrawalsComponent } from './withdrawals.component';
|
||||
FiltersModule,
|
||||
NumberRangeFieldModule,
|
||||
DateRangeFieldModule,
|
||||
InputFieldModule,
|
||||
NumberRangeFieldModule,
|
||||
],
|
||||
declarations: [WithdrawalsComponent, CreateAdjustmentDialogComponent],
|
||||
})
|
||||
|
@ -14,7 +14,7 @@ import {
|
||||
getValueChanges,
|
||||
progressTo,
|
||||
} from '@vality/ng-core';
|
||||
import { BehaviorSubject, switchMap, EMPTY, combineLatest, defer } from 'rxjs';
|
||||
import { BehaviorSubject, switchMap, EMPTY, combineLatest, defer, Observable } from 'rxjs';
|
||||
import { first, map, shareReplay, catchError, distinctUntilChanged } from 'rxjs/operators';
|
||||
import { ValuesType } from 'utility-types';
|
||||
|
||||
@ -73,12 +73,7 @@ export class EditDomainObjectDialogComponent extends DialogSuperclass<
|
||||
map((f) => String(f.type)),
|
||||
first(),
|
||||
);
|
||||
currentObject$ = this.domainStoreService
|
||||
.getObject({
|
||||
[getUnionKey(this.dialogData.domainObject)]: getUnionValue(this.dialogData.domainObject)
|
||||
.ref,
|
||||
})
|
||||
.pipe(shareReplay({ refCount: true, bufferSize: 1 }));
|
||||
currentObject$ = this.getCurrentObject().pipe(shareReplay({ refCount: true, bufferSize: 1 }));
|
||||
newObject$ = getValueChanges(this.control).pipe(
|
||||
map(() => this.getNewObject()),
|
||||
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||
@ -114,7 +109,7 @@ export class EditDomainObjectDialogComponent extends DialogSuperclass<
|
||||
}
|
||||
|
||||
update(isRepeat = false) {
|
||||
this.currentObject$
|
||||
this.getCurrentObject()
|
||||
.pipe(
|
||||
first(),
|
||||
switchMap((currentObject) => {
|
||||
@ -169,6 +164,13 @@ export class EditDomainObjectDialogComponent extends DialogSuperclass<
|
||||
});
|
||||
}
|
||||
|
||||
private getCurrentObject(): Observable<DomainObject> {
|
||||
return this.domainStoreService.getObject({
|
||||
[getUnionKey(this.dialogData.domainObject)]: getUnionValue(this.dialogData.domainObject)
|
||||
.ref,
|
||||
});
|
||||
}
|
||||
|
||||
private getNewObject(): DomainObject {
|
||||
return {
|
||||
[getUnionKey(this.dialogData.domainObject)]: {
|
||||
|
47
src/app/shared/utils/table/create-failure-column.ts
Normal file
47
src/app/shared/utils/table/create-failure-column.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import { Failure } from '@vality/domain-proto/domain';
|
||||
import { PossiblyAsync, ColumnObject, getPossiblyAsyncObservable } from '@vality/ng-core';
|
||||
import { of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
|
||||
function getFailureMessageTree(failure: Failure, withReason = true, level = Infinity) {
|
||||
if (!failure) {
|
||||
return '';
|
||||
}
|
||||
return (
|
||||
(failure.code || '') +
|
||||
(withReason && failure.reason ? ` (${failure.reason})` : '') +
|
||||
(level > 1 && failure?.sub
|
||||
? ` > ${getFailureMessageTree(failure.sub, withReason, level - 1)}`
|
||||
: '')
|
||||
);
|
||||
}
|
||||
|
||||
export function createFailureColumn<T extends object>(
|
||||
selectFailure: (d: T) => PossiblyAsync<Failure>,
|
||||
selectNoFailureMessage: (d: T) => PossiblyAsync<string> = () => '',
|
||||
params: Partial<ColumnObject<T>> = {},
|
||||
): ColumnObject<T> {
|
||||
return {
|
||||
field: 'failure',
|
||||
formatter: (d) =>
|
||||
getPossiblyAsyncObservable(selectNoFailureMessage(d)).pipe(
|
||||
switchMap((msg) => {
|
||||
if (msg) {
|
||||
return of(msg);
|
||||
}
|
||||
return getPossiblyAsyncObservable(selectFailure(d)).pipe(
|
||||
map((failure) => getFailureMessageTree(failure, false, 2)),
|
||||
);
|
||||
}),
|
||||
),
|
||||
description: (d) =>
|
||||
getPossiblyAsyncObservable(selectFailure(d)).pipe(
|
||||
map((failure) => failure?.reason || ''),
|
||||
),
|
||||
tooltip: (d) =>
|
||||
getPossiblyAsyncObservable(selectFailure(d)).pipe(
|
||||
map((failure) => getFailureMessageTree(failure?.sub?.sub)),
|
||||
),
|
||||
...params,
|
||||
} as ColumnObject<T>;
|
||||
}
|
@ -2,3 +2,4 @@ export * from './create-currency-column';
|
||||
export * from './create-party-column';
|
||||
export * from './create-shop-column';
|
||||
export * from './create-predicate-column';
|
||||
export * from './create-failure-column';
|
||||
|
Loading…
Reference in New Issue
Block a user