mirror of
https://github.com/valitydev/control-center.git
synced 2024-11-06 02:25:17 +00:00
IMP-241: Fix create deposits by file minor to major amount and when an error occurs (#368)
This commit is contained in:
parent
6876deeab4
commit
ba1e7c266b
8
package-lock.json
generated
8
package-lock.json
generated
@ -26,7 +26,7 @@
|
||||
"@vality/fistful-proto": "2.0.1-6600be9.0",
|
||||
"@vality/machinegun-proto": "1.0.0",
|
||||
"@vality/magista-proto": "2.0.2-28d11b9.0",
|
||||
"@vality/ng-core": "17.2.1-pr-64-42bc8db.0",
|
||||
"@vality/ng-core": "17.2.1-pr-64-0a6dad2.0",
|
||||
"@vality/ng-thrift": "17.0.1-pr-5-2ce0f11.0",
|
||||
"@vality/payout-manager-proto": "2.0.1-eb4091a.0",
|
||||
"@vality/repairer-proto": "2.0.2-07b73e9.0",
|
||||
@ -6462,9 +6462,9 @@
|
||||
"integrity": "sha512-BsDy5ejotfTtUlwuoX3kz+PYJ5NSTW6m5ZRGv+p5HaKXSjR7tserPdv0q133Wp4T+sg0ED0Qr9Peqsrn+9XlDQ=="
|
||||
},
|
||||
"node_modules/@vality/ng-core": {
|
||||
"version": "17.2.1-pr-64-42bc8db.0",
|
||||
"resolved": "https://registry.npmjs.org/@vality/ng-core/-/ng-core-17.2.1-pr-64-42bc8db.0.tgz",
|
||||
"integrity": "sha512-DWninh/LAka4i5vaQ/8TOCigTwEDdsMMe5tMg1F8N+xE8OuxuoqQPBjnpzFjULYL59fJg8ghppy21ikCY6ffUw==",
|
||||
"version": "17.2.1-pr-64-0a6dad2.0",
|
||||
"resolved": "https://registry.npmjs.org/@vality/ng-core/-/ng-core-17.2.1-pr-64-0a6dad2.0.tgz",
|
||||
"integrity": "sha512-8MdMpFhhuJDmxp6rxUphfOOetEU3y+PV0Q23n4PfPRQo92bnPuI9G9tKnGOGZkmg/BrlGidFKNlkBp/lFH8DUg==",
|
||||
"dependencies": {
|
||||
"@angular/material-date-fns-adapter": "^17.2.0",
|
||||
"@ng-matero/extensions": "^17.1.0",
|
||||
|
@ -34,7 +34,7 @@
|
||||
"@vality/fistful-proto": "2.0.1-6600be9.0",
|
||||
"@vality/machinegun-proto": "1.0.0",
|
||||
"@vality/magista-proto": "2.0.2-28d11b9.0",
|
||||
"@vality/ng-core": "17.2.1-pr-64-42bc8db.0",
|
||||
"@vality/ng-core": "17.2.1-pr-64-0a6dad2.0",
|
||||
"@vality/ng-thrift": "17.0.1-pr-5-2ce0f11.0",
|
||||
"@vality/payout-manager-proto": "2.0.1-eb4091a.0",
|
||||
"@vality/repairer-proto": "2.0.2-07b73e9.0",
|
||||
|
@ -1,8 +1,9 @@
|
||||
<v-dialog [progress]="progress$ | async" title="Create chargebacks">
|
||||
<cc-upload-csv
|
||||
[(selected)]="selected"
|
||||
[errors]="errors"
|
||||
[formatDescription]="['reason.category: fraud, dispute, authorisation, processing_error']"
|
||||
[props]="props"
|
||||
(selectedChange)="selected = $event"
|
||||
></cc-upload-csv>
|
||||
<v-dialog-actions>
|
||||
<button
|
||||
|
@ -29,6 +29,7 @@ export class CreateChargebacksByFileDialogComponent extends DialogSuperclass<
|
||||
selected: CsvChargeback[] = [];
|
||||
successfullyChargebacks: InvoicePaymentChargeback[] = [];
|
||||
props = CSV_CHARGEBACK_PROPS;
|
||||
errors?: Map<CsvChargeback, unknown>;
|
||||
|
||||
constructor(
|
||||
private invoicingService: InvoicingService,
|
||||
@ -59,6 +60,9 @@ export class CreateChargebacksByFileDialogComponent extends DialogSuperclass<
|
||||
`Creating ${chargebacksWithError.length} chargebacks ended in an error. They were re-selected in the table.`,
|
||||
);
|
||||
this.selected = chargebacksWithError.map((c) => selected[c.index]);
|
||||
this.errors = new Map(
|
||||
chargebacksWithError.map((c) => [selected[c.index], c.error]),
|
||||
);
|
||||
} else {
|
||||
this.log.successOperation('create', 'chargebacks');
|
||||
this.closeWithSuccess();
|
||||
|
@ -1,5 +1,5 @@
|
||||
<v-dialog [progress]="progress$ | async" title="Create deposits">
|
||||
<cc-upload-csv [props]="props" (selectedChange)="selected = $event"></cc-upload-csv>
|
||||
<cc-upload-csv [(selected)]="selected" [errors]="errors" [props]="props"></cc-upload-csv>
|
||||
<v-dialog-actions>
|
||||
<button
|
||||
*ngIf="successfully?.length"
|
||||
@ -7,7 +7,7 @@
|
||||
mat-button
|
||||
(click)="closeWithSuccess()"
|
||||
>
|
||||
Close and find {{ successfully.length }} successful deposits
|
||||
Close and reload list ({{ successfully.length }} successful)
|
||||
</button>
|
||||
<button
|
||||
[disabled]="!selected?.length || !!(progress$ | async)"
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
DialogModule,
|
||||
forkJoinToResult,
|
||||
} from '@vality/ng-core';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { BehaviorSubject, switchMap } from 'rxjs';
|
||||
|
||||
import { UploadCsvComponent } from '../../../../../components/upload-csv';
|
||||
import { DepositManagementService } from '../../../../api/deposit';
|
||||
@ -35,6 +35,7 @@ export class CreateDepositsByFileDialogComponent extends DialogSuperclass<
|
||||
selected: CsvDeposit[] = [];
|
||||
successfully: DepositState[] = [];
|
||||
props = CSV_DEPOSIT_PROPS;
|
||||
errors?: Map<CsvDeposit, unknown>;
|
||||
|
||||
constructor(
|
||||
private depositManagementService: DepositManagementService,
|
||||
@ -49,8 +50,8 @@ export class CreateDepositsByFileDialogComponent extends DialogSuperclass<
|
||||
const selected = this.selected;
|
||||
forkJoinToResult(
|
||||
selected.map((c) =>
|
||||
this.depositManagementService.Create(
|
||||
...runInInjectionContext(this.injector, () => getCreateDepositArgs(c)),
|
||||
runInInjectionContext(this.injector, () => getCreateDepositArgs(c)).pipe(
|
||||
switchMap((params) => this.depositManagementService.Create(...params)),
|
||||
),
|
||||
),
|
||||
this.progress$,
|
||||
@ -66,6 +67,7 @@ export class CreateDepositsByFileDialogComponent extends DialogSuperclass<
|
||||
`Creating ${withError.length} deposits ended in an error. They were re-selected in the table.`,
|
||||
);
|
||||
this.selected = withError.map((c) => selected[c.index]);
|
||||
this.errors = new Map(withError.map((c) => [selected[c.index], c.error]));
|
||||
} else {
|
||||
this.log.successOperation('create', 'deposits');
|
||||
this.closeWithSuccess();
|
||||
|
@ -1,29 +1,38 @@
|
||||
import { inject } from '@angular/core';
|
||||
import { CodegenClient } from '@vality/fistful-proto/internal/deposit-Management';
|
||||
import { clean } from '@vality/ng-core';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { UserInfoBasedIdGeneratorService } from '../../../../../shared/services';
|
||||
import {
|
||||
UserInfoBasedIdGeneratorService,
|
||||
AmountCurrencyService,
|
||||
} from '../../../../../shared/services';
|
||||
import { CsvDeposit } from '../types/csv-deposit';
|
||||
|
||||
export function getCreateDepositArgs(c: CsvDeposit): Parameters<CodegenClient['Create']> {
|
||||
export function getCreateDepositArgs(c: CsvDeposit) {
|
||||
const userInfoBasedIdGeneratorService = inject(UserInfoBasedIdGeneratorService);
|
||||
return [
|
||||
clean(
|
||||
{
|
||||
id: userInfoBasedIdGeneratorService.getUsernameBasedId(),
|
||||
wallet_id: c.wallet_id,
|
||||
source_id: c.source_id,
|
||||
body: {
|
||||
amount: Number(c['body.amount']),
|
||||
currency: { symbolic_code: c['body.currency'] },
|
||||
},
|
||||
external_id: c.external_id,
|
||||
metadata: c.metadata ? JSON.parse(c.metadata) : undefined,
|
||||
description: c.description,
|
||||
},
|
||||
false,
|
||||
true,
|
||||
const amountCurrencyService = inject(AmountCurrencyService);
|
||||
return amountCurrencyService.toMinor(Number(c['body.amount']), c['body.currency']).pipe(
|
||||
map(
|
||||
(amount): Parameters<CodegenClient['Create']> => [
|
||||
clean(
|
||||
{
|
||||
id: userInfoBasedIdGeneratorService.getUsernameBasedId(),
|
||||
wallet_id: c.wallet_id,
|
||||
source_id: c.source_id,
|
||||
body: {
|
||||
amount,
|
||||
currency: { symbolic_code: c['body.currency'] },
|
||||
},
|
||||
external_id: c.external_id,
|
||||
metadata: c.metadata ? JSON.parse(c.metadata) : undefined,
|
||||
description: c.description,
|
||||
},
|
||||
false,
|
||||
true,
|
||||
),
|
||||
new Map(),
|
||||
],
|
||||
),
|
||||
new Map(),
|
||||
];
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { toMajorByExponent } from '@vality/ng-core';
|
||||
import { toMajorByExponent, toMinorByExponent } from '@vality/ng-core';
|
||||
import { map, first } from 'rxjs/operators';
|
||||
|
||||
import { DomainStoreService } from '@cc/app/api/domain-config';
|
||||
@ -17,6 +17,13 @@ export class AmountCurrencyService {
|
||||
);
|
||||
}
|
||||
|
||||
toMinor(amount: number, symbolicCode: string) {
|
||||
return this.getCurrency(symbolicCode).pipe(
|
||||
first(),
|
||||
map((currency) => toMinorByExponent(amount, currency?.data?.exponent)),
|
||||
);
|
||||
}
|
||||
|
||||
getCurrency(symbolicCode: string) {
|
||||
return this.domainStoreService
|
||||
.getObjects('currency')
|
||||
|
@ -71,6 +71,7 @@ function getCsvObjectErrors<R extends string, O extends string>(
|
||||
export class UploadCsvComponent<R extends string, O extends string> implements OnInit {
|
||||
props = input<CsvProps<R, O>>({});
|
||||
formatDescription = input<string[]>();
|
||||
errors = input<Map<CsvProps<R, O>, { name?: string; message?: string }>>();
|
||||
|
||||
selected = input<CsvObject<R, O>[]>([]);
|
||||
@Output() selectedChange = new EventEmitter<CsvObject<R, O>[]>();
|
||||
@ -116,12 +117,18 @@ export class UploadCsvComponent<R extends string, O extends string> implements O
|
||||
}),
|
||||
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||
);
|
||||
columns = computed<Column<CsvObject<R, O>>[]>(() =>
|
||||
this.propsList().map((p) => ({
|
||||
columns = computed<Column<CsvObject<R, O>>[]>(() => [
|
||||
...this.propsList().map((p) => ({
|
||||
field: p,
|
||||
header: startCase(p),
|
||||
})),
|
||||
);
|
||||
...(this.errors()?.size
|
||||
? [
|
||||
{ field: 'error_code', formatter: (d) => this.errors().get(d)?.name },
|
||||
{ field: 'error_message', formatter: (d) => this.errors().get(d)?.message },
|
||||
]
|
||||
: []),
|
||||
]);
|
||||
|
||||
constructor(
|
||||
private log: NotifyLogService,
|
||||
|
Loading…
Reference in New Issue
Block a user