mirror of
https://github.com/valitydev/control-center.git
synced 2024-11-06 02:25:17 +00:00
Moving to table2 with lazy column (#405)
This commit is contained in:
parent
753ad0d727
commit
9e3b6d5ae8
8
package-lock.json
generated
8
package-lock.json
generated
@ -26,7 +26,7 @@
|
|||||||
"@vality/fistful-proto": "2.0.1-88e69a5.0",
|
"@vality/fistful-proto": "2.0.1-88e69a5.0",
|
||||||
"@vality/machinegun-proto": "1.0.1-3decc8f.0",
|
"@vality/machinegun-proto": "1.0.1-3decc8f.0",
|
||||||
"@vality/magista-proto": "2.0.2-ec1bdb9.0",
|
"@vality/magista-proto": "2.0.2-ec1bdb9.0",
|
||||||
"@vality/ng-core": "18.4.1-pr-74-55d4acd.0",
|
"@vality/ng-core": "18.4.1-pr-78-9131f9a.0",
|
||||||
"@vality/ng-thrift": "18.0.1-pr-13-bdb6d51.0",
|
"@vality/ng-thrift": "18.0.1-pr-13-bdb6d51.0",
|
||||||
"@vality/repairer-proto": "2.0.2-07b73e9.0",
|
"@vality/repairer-proto": "2.0.2-07b73e9.0",
|
||||||
"@vality/scrooge-proto": "0.1.1-9ce7fc6.0",
|
"@vality/scrooge-proto": "0.1.1-9ce7fc6.0",
|
||||||
@ -5969,9 +5969,9 @@
|
|||||||
"integrity": "sha512-XWF7qM/CARRAey0scGVhfGU6jNq+UdlGE2mg3jn4eIFDuIWQJqsT+Bah300RBUrl+XgFsmj95C6HWRfeA5Q8kw=="
|
"integrity": "sha512-XWF7qM/CARRAey0scGVhfGU6jNq+UdlGE2mg3jn4eIFDuIWQJqsT+Bah300RBUrl+XgFsmj95C6HWRfeA5Q8kw=="
|
||||||
},
|
},
|
||||||
"node_modules/@vality/ng-core": {
|
"node_modules/@vality/ng-core": {
|
||||||
"version": "18.4.1-pr-74-55d4acd.0",
|
"version": "18.4.1-pr-78-9131f9a.0",
|
||||||
"resolved": "https://registry.npmjs.org/@vality/ng-core/-/ng-core-18.4.1-pr-74-55d4acd.0.tgz",
|
"resolved": "https://registry.npmjs.org/@vality/ng-core/-/ng-core-18.4.1-pr-78-9131f9a.0.tgz",
|
||||||
"integrity": "sha512-EkGTPth5+HA0MLc+BYLIV5ie7xnwBrXftTxoVJw+5zlcWoLm5V1+10AGz6wmhX4VIunFFZR/p9XUNAhNqvluVw==",
|
"integrity": "sha512-qmTGnGe+pBWlIQ+cX64pt2aLWdoLM6M2Apc180dQQrLca4VBHB4Oh8yo7vvv/sxws1DLXEzWutgNzi9/bRdtZQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/material-date-fns-adapter": "^18.2.2",
|
"@angular/material-date-fns-adapter": "^18.2.2",
|
||||||
"@ng-matero/extensions": "^18.2.0",
|
"@ng-matero/extensions": "^18.2.0",
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
"@vality/fistful-proto": "2.0.1-88e69a5.0",
|
"@vality/fistful-proto": "2.0.1-88e69a5.0",
|
||||||
"@vality/machinegun-proto": "1.0.1-3decc8f.0",
|
"@vality/machinegun-proto": "1.0.1-3decc8f.0",
|
||||||
"@vality/magista-proto": "2.0.2-ec1bdb9.0",
|
"@vality/magista-proto": "2.0.2-ec1bdb9.0",
|
||||||
"@vality/ng-core": "18.4.1-pr-74-55d4acd.0",
|
"@vality/ng-core": "18.4.1-pr-78-9131f9a.0",
|
||||||
"@vality/ng-thrift": "18.0.1-pr-13-bdb6d51.0",
|
"@vality/ng-thrift": "18.0.1-pr-13-bdb6d51.0",
|
||||||
"@vality/repairer-proto": "2.0.2-07b73e9.0",
|
"@vality/repairer-proto": "2.0.2-07b73e9.0",
|
||||||
"@vality/scrooge-proto": "0.1.1-9ce7fc6.0",
|
"@vality/scrooge-proto": "0.1.1-9ce7fc6.0",
|
||||||
|
@ -12,8 +12,8 @@ import { environment } from '../environments/environment';
|
|||||||
import { ROUTING_CONFIG as CLAIMS_ROUTING_CONFIG } from './sections/claims/routing-config';
|
import { ROUTING_CONFIG as CLAIMS_ROUTING_CONFIG } from './sections/claims/routing-config';
|
||||||
import { ROUTING_CONFIG as DEPOSITS_ROUTING_CONFIG } from './sections/deposits/routing-config';
|
import { ROUTING_CONFIG as DEPOSITS_ROUTING_CONFIG } from './sections/deposits/routing-config';
|
||||||
import { ROUTING_CONFIG as DOMAIN_ROUTING_CONFIG } from './sections/domain/routing-config';
|
import { ROUTING_CONFIG as DOMAIN_ROUTING_CONFIG } from './sections/domain/routing-config';
|
||||||
|
import { ROUTING_CONFIG as MACHINES_ROUTING_CONFIG } from './sections/machines/routing-config';
|
||||||
import { ROUTING_CONFIG as PAYMENTS_ROUTING_CONFIG } from './sections/payments/routing-config';
|
import { ROUTING_CONFIG as PAYMENTS_ROUTING_CONFIG } from './sections/payments/routing-config';
|
||||||
import { ROUTING_CONFIG as REPAIRING_ROUTING_CONFIG } from './sections/repairing/routing-config';
|
|
||||||
import { ROUTING_CONFIG as PARTIES_ROUTING_CONFIG } from './sections/search-parties/routing-config';
|
import { ROUTING_CONFIG as PARTIES_ROUTING_CONFIG } from './sections/search-parties/routing-config';
|
||||||
import { SHOPS_ROUTING_CONFIG } from './sections/shops';
|
import { SHOPS_ROUTING_CONFIG } from './sections/shops';
|
||||||
import { ROUTING_CONFIG as SOURCES_ROUTING_CONFIG } from './sections/sources/routing-config';
|
import { ROUTING_CONFIG as SOURCES_ROUTING_CONFIG } from './sections/sources/routing-config';
|
||||||
@ -73,7 +73,7 @@ export class AppComponent {
|
|||||||
{
|
{
|
||||||
label: 'Machines',
|
label: 'Machines',
|
||||||
url: '/machines',
|
url: '/machines',
|
||||||
services: REPAIRING_ROUTING_CONFIG.services,
|
services: MACHINES_ROUTING_CONFIG.services,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Sources',
|
label: 'Sources',
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<cc-page-layout title="Chargebacks">
|
<cc-page-layout fullHeight title="Chargebacks">
|
||||||
<cc-page-layout-actions>
|
<cc-page-layout-actions>
|
||||||
<v-more-filters-button [filters]="filters"></v-more-filters-button>
|
<v-more-filters-button [filters]="filters"></v-more-filters-button>
|
||||||
</cc-page-layout-actions>
|
</cc-page-layout-actions>
|
||||||
@ -47,14 +47,6 @@
|
|||||||
(more)="more()"
|
(more)="more()"
|
||||||
(update)="reload($event)"
|
(update)="reload($event)"
|
||||||
>
|
>
|
||||||
<button
|
|
||||||
[disabled]="!selected.length"
|
|
||||||
color="primary"
|
|
||||||
mat-raised-button
|
|
||||||
(click)="changeStatuses()"
|
|
||||||
>
|
|
||||||
Change statuses
|
|
||||||
</button>
|
|
||||||
<button color="primary" mat-raised-button (click)="create()">Create by file</button>
|
<button color="primary" mat-raised-button (click)="create()">Create by file</button>
|
||||||
</cc-chargebacks-table>
|
</cc-chargebacks-table>
|
||||||
</cc-page-layout>
|
</cc-page-layout>
|
||||||
|
@ -29,7 +29,6 @@ import {
|
|||||||
CHARGEBACK_CATEGORIES,
|
CHARGEBACK_CATEGORIES,
|
||||||
} from '@cc/app/api/fistful-stat';
|
} from '@cc/app/api/fistful-stat';
|
||||||
|
|
||||||
import { ChangeChargebacksStatusDialogComponent } from '../../shared/components/change-chargebacks-status-dialog';
|
|
||||||
import { DATE_RANGE_DAYS, DEBOUNCE_TIME_MS } from '../../tokens';
|
import { DATE_RANGE_DAYS, DEBOUNCE_TIME_MS } from '../../tokens';
|
||||||
|
|
||||||
import { CreateChargebacksByFileDialogComponent } from './components/create-chargebacks-by-file-dialog/create-chargebacks-by-file-dialog.component';
|
import { CreateChargebacksByFileDialogComponent } from './components/create-chargebacks-by-file-dialog/create-chargebacks-by-file-dialog.component';
|
||||||
@ -46,7 +45,7 @@ type FormValue = {
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'cc-chargebacks',
|
selector: 'cc-chargebacks',
|
||||||
templateUrl: './chargebacks.component.html',
|
templateUrl: './chargebacks.component.html',
|
||||||
styles: [],
|
providers: [FetchChargebacksService],
|
||||||
})
|
})
|
||||||
export class ChargebacksComponent implements OnInit {
|
export class ChargebacksComponent implements OnInit {
|
||||||
filtersForm = new FormGroup(
|
filtersForm = new FormGroup(
|
||||||
@ -141,17 +140,4 @@ export class ChargebacksComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
changeStatuses() {
|
|
||||||
this.dialog
|
|
||||||
.open(ChangeChargebacksStatusDialogComponent, { chargebacks: this.selected })
|
|
||||||
.afterClosed()
|
|
||||||
.pipe(
|
|
||||||
filter((res) => res.status === DialogResponseStatus.Success),
|
|
||||||
takeUntilDestroyed(this.dr),
|
|
||||||
)
|
|
||||||
.subscribe(() => {
|
|
||||||
this.reload();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@ import {
|
|||||||
} from '@vality/ng-core';
|
} from '@vality/ng-core';
|
||||||
import { ThriftPipesModule } from '@vality/ng-thrift';
|
import { ThriftPipesModule } from '@vality/ng-thrift';
|
||||||
|
|
||||||
|
import { ChargebacksTableComponent } from '@cc/app/shared/components/chargebacks-table';
|
||||||
|
|
||||||
import { UploadCsvComponent } from '../../../components/upload-csv';
|
import { UploadCsvComponent } from '../../../components/upload-csv';
|
||||||
import { PageLayoutModule, ShopFieldModule } from '../../shared';
|
import { PageLayoutModule, ShopFieldModule } from '../../shared';
|
||||||
import { MerchantFieldModule } from '../../shared/components/merchant-field';
|
import { MerchantFieldModule } from '../../shared/components/merchant-field';
|
||||||
@ -31,15 +33,10 @@ import {
|
|||||||
|
|
||||||
import { ChargebacksRoutingModule } from './chargebacks-routing.module';
|
import { ChargebacksRoutingModule } from './chargebacks-routing.module';
|
||||||
import { ChargebacksComponent } from './chargebacks.component';
|
import { ChargebacksComponent } from './chargebacks.component';
|
||||||
import { ChargebacksTableComponent } from './components/chargebacks-table/chargebacks-table.component';
|
|
||||||
import { CreateChargebacksByFileDialogComponent } from './components/create-chargebacks-by-file-dialog/create-chargebacks-by-file-dialog.component';
|
import { CreateChargebacksByFileDialogComponent } from './components/create-chargebacks-by-file-dialog/create-chargebacks-by-file-dialog.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [ChargebacksComponent, CreateChargebacksByFileDialogComponent],
|
||||||
ChargebacksComponent,
|
|
||||||
ChargebacksTableComponent,
|
|
||||||
CreateChargebacksByFileDialogComponent,
|
|
||||||
],
|
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
ChargebacksRoutingModule,
|
ChargebacksRoutingModule,
|
||||||
@ -67,6 +64,7 @@ import { CreateChargebacksByFileDialogComponent } from './components/create-char
|
|||||||
MatInputModule,
|
MatInputModule,
|
||||||
MatCheckboxModule,
|
MatCheckboxModule,
|
||||||
UploadCsvComponent,
|
UploadCsvComponent,
|
||||||
|
ChargebacksTableComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class ChargebacksModule {}
|
export class ChargebacksModule {}
|
||||||
|
@ -1,144 +0,0 @@
|
|||||||
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|
||||||
import { InvoicePaymentChargebackStatus } from '@vality/magista-proto/internal/proto/domain';
|
|
||||||
import { StatChargeback } from '@vality/magista-proto/magista';
|
|
||||||
import { LoadOptions, Column, TagColumn } from '@vality/ng-core';
|
|
||||||
import { getUnionKey } from '@vality/ng-thrift';
|
|
||||||
import startCase from 'lodash-es/startCase';
|
|
||||||
|
|
||||||
import { AmountCurrencyService } from '../../../../shared/services';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'cc-chargebacks-table',
|
|
||||||
templateUrl: './chargebacks-table.component.html',
|
|
||||||
styles: [],
|
|
||||||
})
|
|
||||||
export class ChargebacksTableComponent {
|
|
||||||
@Input() data!: StatChargeback[];
|
|
||||||
@Input() isLoading?: boolean | null;
|
|
||||||
@Input() hasMore?: boolean | null;
|
|
||||||
@Input() selected?: StatChargeback[];
|
|
||||||
|
|
||||||
@Output() selectedChange = new EventEmitter<StatChargeback[]>();
|
|
||||||
@Output() update = new EventEmitter<LoadOptions>();
|
|
||||||
@Output() more = new EventEmitter<void>();
|
|
||||||
|
|
||||||
columns: Column<StatChargeback>[] = [
|
|
||||||
{ field: 'chargeback_id', header: 'Id' },
|
|
||||||
{
|
|
||||||
field: 'chargeback_reason',
|
|
||||||
header: 'Reason',
|
|
||||||
formatter: (data) => startCase(getUnionKey(data.chargeback_reason.category)),
|
|
||||||
description: (data) => data.chargeback_reason.code,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'chargeback_status',
|
|
||||||
type: 'tag',
|
|
||||||
header: 'Status',
|
|
||||||
formatter: (data) => getUnionKey(data.chargeback_status),
|
|
||||||
typeParameters: {
|
|
||||||
label: (data) => startCase(getUnionKey(data.chargeback_status)),
|
|
||||||
tags: {
|
|
||||||
pending: { color: 'pending' },
|
|
||||||
accepted: { color: 'success' },
|
|
||||||
rejected: { color: 'warn' },
|
|
||||||
cancelled: { color: 'neutral' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as TagColumn<StatChargeback, keyof InvoicePaymentChargebackStatus>,
|
|
||||||
{
|
|
||||||
field: 'amount',
|
|
||||||
type: 'currency',
|
|
||||||
formatter: (data) =>
|
|
||||||
this.amountCurrencyService.toMajor(data.amount, data.currency_code.symbolic_code),
|
|
||||||
typeParameters: {
|
|
||||||
currencyCode: (data) => data.currency_code.symbolic_code,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'levy_amount',
|
|
||||||
type: 'currency',
|
|
||||||
formatter: (data) =>
|
|
||||||
this.amountCurrencyService.toMajor(
|
|
||||||
data.levy_amount,
|
|
||||||
data.levy_currency_code.symbolic_code,
|
|
||||||
),
|
|
||||||
typeParameters: {
|
|
||||||
currencyCode: (data) => data.levy_currency_code.symbolic_code,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'fee',
|
|
||||||
type: 'currency',
|
|
||||||
formatter: (data) =>
|
|
||||||
this.amountCurrencyService.toMajor(data.fee, data.currency_code.symbolic_code),
|
|
||||||
typeParameters: {
|
|
||||||
currencyCode: (data) => data.currency_code.symbolic_code,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'provider_fee',
|
|
||||||
type: 'currency',
|
|
||||||
formatter: (data) =>
|
|
||||||
this.amountCurrencyService.toMajor(
|
|
||||||
data.provider_fee,
|
|
||||||
data.currency_code.symbolic_code,
|
|
||||||
),
|
|
||||||
typeParameters: {
|
|
||||||
currencyCode: (data) => data.currency_code.symbolic_code,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'external_fee',
|
|
||||||
type: 'currency',
|
|
||||||
formatter: (data) =>
|
|
||||||
this.amountCurrencyService.toMajor(
|
|
||||||
data.external_fee,
|
|
||||||
data.currency_code.symbolic_code,
|
|
||||||
),
|
|
||||||
typeParameters: {
|
|
||||||
currencyCode: (data) => data.currency_code.symbolic_code,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'stage',
|
|
||||||
formatter: (data) => getUnionKey(data.stage),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'invoice_id',
|
|
||||||
header: 'Invoice Id (Payment Id)',
|
|
||||||
description: 'payment_id',
|
|
||||||
link: (data) =>
|
|
||||||
`/party/${data.party_id}/invoice/${data.invoice_id}/payment/${data.payment_id}`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'created_at',
|
|
||||||
type: 'datetime',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'party_id',
|
|
||||||
header: 'Party',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'shop_id',
|
|
||||||
header: 'Shop',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'external_id',
|
|
||||||
hide: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'content.type',
|
|
||||||
description: 'content.data',
|
|
||||||
header: 'Content',
|
|
||||||
hide: true,
|
|
||||||
},
|
|
||||||
// createOperationColumn<StatChargeback>([
|
|
||||||
// {
|
|
||||||
// label: 'Change status',
|
|
||||||
// click: (data) => undefined,
|
|
||||||
// },
|
|
||||||
// ]),
|
|
||||||
];
|
|
||||||
|
|
||||||
constructor(private amountCurrencyService: AmountCurrencyService) {}
|
|
||||||
}
|
|
@ -6,9 +6,7 @@ import { map, catchError } from 'rxjs/operators';
|
|||||||
|
|
||||||
import { MerchantStatisticsService } from '../../api/magista';
|
import { MerchantStatisticsService } from '../../api/magista';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable()
|
||||||
providedIn: 'root',
|
|
||||||
})
|
|
||||||
export class FetchChargebacksService extends FetchSuperclass<
|
export class FetchChargebacksService extends FetchSuperclass<
|
||||||
StatChargeback,
|
StatChargeback,
|
||||||
ChargebackSearchQuery
|
ChargebackSearchQuery
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<v-table
|
<v-table2
|
||||||
[columns]="columns()"
|
[columns]="columns"
|
||||||
[data]="data"
|
[data]="data"
|
||||||
[hasMore]="hasMore"
|
[hasMore]="hasMore"
|
||||||
[progress]="isLoading"
|
[progress]="isLoading"
|
||||||
@ -7,4 +7,4 @@
|
|||||||
(update)="update.emit($event)"
|
(update)="update.emit($event)"
|
||||||
>
|
>
|
||||||
<v-table-actions><ng-content></ng-content></v-table-actions>
|
<v-table-actions><ng-content></ng-content></v-table-actions>
|
||||||
</v-table>
|
</v-table2>
|
||||||
|
@ -1,20 +1,11 @@
|
|||||||
import {
|
import { Component, Input, Output, EventEmitter, booleanAttribute, input } from '@angular/core';
|
||||||
Component,
|
import { toObservable } from '@angular/core/rxjs-interop';
|
||||||
Input,
|
import { Claim } from '@vality/domain-proto/claim_management';
|
||||||
Output,
|
import { Column2, LoadOptions, createMenuColumn } from '@vality/ng-core';
|
||||||
EventEmitter,
|
|
||||||
booleanAttribute,
|
|
||||||
input,
|
|
||||||
computed,
|
|
||||||
} from '@angular/core';
|
|
||||||
import { Router } from '@angular/router';
|
|
||||||
import { Claim, ClaimStatus } from '@vality/domain-proto/claim_management';
|
|
||||||
import { Column, LoadOptions, TagColumn, createOperationColumn } from '@vality/ng-core';
|
|
||||||
import { getUnionKey } from '@vality/ng-thrift';
|
import { getUnionKey } from '@vality/ng-thrift';
|
||||||
import isObject from 'lodash-es/isObject';
|
|
||||||
import startCase from 'lodash-es/startCase';
|
import startCase from 'lodash-es/startCase';
|
||||||
|
|
||||||
import { createPartyColumn } from '../../../shared';
|
import { createPartyColumn } from '@cc/app/shared/utils/table2';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'cc-claims-table',
|
selector: 'cc-claims-table',
|
||||||
@ -30,48 +21,33 @@ export class ClaimsTableComponent {
|
|||||||
@Output() update = new EventEmitter<LoadOptions>();
|
@Output() update = new EventEmitter<LoadOptions>();
|
||||||
@Output() more = new EventEmitter<void>();
|
@Output() more = new EventEmitter<void>();
|
||||||
|
|
||||||
columns = computed<Column<Claim>[]>(() =>
|
columns: Column2<Claim>[] = [
|
||||||
this.sourceColumns.filter(
|
{ field: 'id', cell: (d) => ({ link: () => `/party/${d.party_id}/claim/${d.id}` }) },
|
||||||
(c) => (isObject(c) && c?.field !== 'party_id') || !this.noParty(),
|
createPartyColumn((d) => ({ id: d.party_id }), { hidden: toObservable(this.noParty) }),
|
||||||
),
|
|
||||||
);
|
|
||||||
private sourceColumns: Column<Claim>[] = [
|
|
||||||
{ field: 'id', link: (d) => this.getClaimLink(d.party_id, d.id) },
|
|
||||||
createPartyColumn('party_id'),
|
|
||||||
{
|
{
|
||||||
field: 'status',
|
field: 'status',
|
||||||
type: 'tag',
|
cell: (d) => ({
|
||||||
formatter: (claim) => getUnionKey(claim.status),
|
value: startCase(getUnionKey(d.status)),
|
||||||
typeParameters: {
|
|
||||||
label: (claim) => startCase(getUnionKey(claim.status)),
|
|
||||||
tags: {
|
tags: {
|
||||||
pending: { color: 'pending' },
|
pending: 'pending',
|
||||||
review: { color: 'pending' },
|
review: 'pending',
|
||||||
pending_acceptance: { color: 'pending' },
|
pending_acceptance: 'pending',
|
||||||
accepted: { color: 'success' },
|
accepted: 'success',
|
||||||
denied: { color: 'warn' },
|
denied: 'warn',
|
||||||
revoked: { color: 'neutral' },
|
revoked: 'neutral',
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
} as TagColumn<Claim, keyof ClaimStatus>,
|
},
|
||||||
'revision',
|
{ field: 'revision' },
|
||||||
{ field: 'created_at', type: 'datetime' },
|
{ field: 'created_at', cell: { type: 'datetime' } },
|
||||||
{ field: 'updated_at', type: 'datetime' },
|
{ field: 'updated_at', cell: { type: 'datetime' } },
|
||||||
createOperationColumn<Claim>([
|
createMenuColumn((d) => ({
|
||||||
{
|
items: [
|
||||||
label: 'Details',
|
{
|
||||||
click: (claim) => this.navigateToClaim(claim.party_id, claim.id),
|
label: 'Details',
|
||||||
},
|
link: () => `/party/${d.party_id}/claim/${d.id}`,
|
||||||
]),
|
},
|
||||||
|
],
|
||||||
|
})),
|
||||||
];
|
];
|
||||||
|
|
||||||
constructor(private router: Router) {}
|
|
||||||
|
|
||||||
navigateToClaim(partyId: string, claimID: number) {
|
|
||||||
void this.router.navigate([this.getClaimLink(partyId, claimID)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private getClaimLink(partyId: string, claimID: number): string {
|
|
||||||
return `/party/${partyId}/claim/${claimID}`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<cc-page-layout title="Claims">
|
<cc-page-layout fullHeight title="Claims">
|
||||||
<cc-page-layout-actions
|
<cc-page-layout-actions
|
||||||
><v-more-filters-button [filters]="filters"></v-more-filters-button
|
><v-more-filters-button [filters]="filters"></v-more-filters-button
|
||||||
></cc-page-layout-actions>
|
></cc-page-layout-actions>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<div style="display: flex; flex-direction: column; gap: 24px">
|
<div style="display: flex; flex-direction: column; gap: 24px">
|
||||||
<h1 class="mat-headline-5">Reverts</h1>
|
<h1 class="mat-headline-5">Reverts</h1>
|
||||||
<v-table
|
<v-table2
|
||||||
[columns]="columns"
|
[columns]="columns"
|
||||||
[data]="reverts$ | async"
|
[data]="reverts$ | async"
|
||||||
[hasMore]="hasMore$ | async"
|
[hasMore]="hasMore$ | async"
|
||||||
@ -18,5 +18,5 @@
|
|||||||
Create revert
|
Create revert
|
||||||
</button>
|
</button>
|
||||||
</v-table-actions>
|
</v-table-actions>
|
||||||
</v-table>
|
</v-table2>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
|
||||||
import { DepositStatus, StatDeposit, StatDepositRevert } from '@vality/fistful-proto/fistful_stat';
|
import { DepositStatus, StatDeposit, StatDepositRevert } from '@vality/fistful-proto/fistful_stat';
|
||||||
import { DialogService, Column, UpdateOptions } from '@vality/ng-core';
|
import { DialogService, UpdateOptions, Column2 } from '@vality/ng-core';
|
||||||
import { getUnionKey } from '@vality/ng-thrift';
|
import { getUnionKey } from '@vality/ng-thrift';
|
||||||
import startCase from 'lodash-es/startCase';
|
import startCase from 'lodash-es/startCase';
|
||||||
import { filter } from 'rxjs/operators';
|
import { filter } from 'rxjs/operators';
|
||||||
|
|
||||||
import { createCurrencyColumn } from '@cc/app/shared/utils';
|
import { createCurrencyColumn } from '@cc/app/shared/utils/table2';
|
||||||
|
|
||||||
import { CreateRevertDialogComponent } from './create-revert-dialog/create-revert-dialog.component';
|
import { CreateRevertDialogComponent } from './create-revert-dialog/create-revert-dialog.component';
|
||||||
import { FetchRevertsService } from './services/fetch-reverts/fetch-reverts.service';
|
import { FetchRevertsService } from './services/fetch-reverts/fetch-reverts.service';
|
||||||
@ -23,27 +23,29 @@ export class RevertsComponent implements OnInit {
|
|||||||
reverts$ = this.fetchRevertsService.result$;
|
reverts$ = this.fetchRevertsService.result$;
|
||||||
hasMore$ = this.fetchRevertsService.hasMore$;
|
hasMore$ = this.fetchRevertsService.hasMore$;
|
||||||
isLoading$ = this.fetchRevertsService.isLoading$;
|
isLoading$ = this.fetchRevertsService.isLoading$;
|
||||||
columns: Column<StatDepositRevert>[] = [
|
columns: Column2<StatDepositRevert>[] = [
|
||||||
{ field: 'id' },
|
{ field: 'id' },
|
||||||
{
|
{
|
||||||
field: 'status',
|
field: 'status',
|
||||||
type: 'tag',
|
cell: (d) => ({
|
||||||
formatter: (d) => getUnionKey(d.status),
|
value: startCase(getUnionKey(d.status)),
|
||||||
typeParameters: {
|
color: (
|
||||||
label: (d) => startCase(getUnionKey(d.status)),
|
{
|
||||||
tags: {
|
pending: 'pending',
|
||||||
pending: { color: 'pending' },
|
succeeded: 'success',
|
||||||
succeeded: { color: 'success' },
|
failed: 'warn',
|
||||||
failed: { color: 'warn' },
|
} as const
|
||||||
},
|
)[getUnionKey(d.status)],
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
createCurrencyColumn(
|
createCurrencyColumn(
|
||||||
'amount',
|
(d) => ({
|
||||||
(d) => d.body.amount,
|
amount: d.body.amount,
|
||||||
(d) => d.body.currency.symbolic_code,
|
code: d.body.currency.symbolic_code,
|
||||||
|
}),
|
||||||
|
{ header: 'Amount' },
|
||||||
),
|
),
|
||||||
{ field: 'created_at', type: 'datetime' },
|
{ field: 'created_at', cell: { type: 'datetime' } },
|
||||||
];
|
];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<cc-page-layout title="Deposits">
|
<cc-page-layout fullHeight title="Deposits">
|
||||||
<cc-page-layout-actions>
|
<cc-page-layout-actions>
|
||||||
<v-more-filters-button [filters]="filters"></v-more-filters-button>
|
<v-more-filters-button [filters]="filters"></v-more-filters-button>
|
||||||
</cc-page-layout-actions>
|
</cc-page-layout-actions>
|
||||||
@ -22,7 +22,7 @@
|
|||||||
<cc-merchant-field formControlName="party_id"></cc-merchant-field>
|
<cc-merchant-field formControlName="party_id"></cc-merchant-field>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</v-filters>
|
</v-filters>
|
||||||
<v-table
|
<v-table2
|
||||||
[columns]="columns"
|
[columns]="columns"
|
||||||
[data]="deposits$ | async"
|
[data]="deposits$ | async"
|
||||||
[hasMore]="hasMore$ | async"
|
[hasMore]="hasMore$ | async"
|
||||||
@ -31,10 +31,8 @@
|
|||||||
(update)="reload($event)"
|
(update)="reload($event)"
|
||||||
>
|
>
|
||||||
<v-table-actions>
|
<v-table-actions>
|
||||||
<button color="primary" mat-raised-button (click)="createByFile()">
|
<button mat-raised-button (click)="createByFile()">Create by file</button>
|
||||||
Create by file
|
|
||||||
</button>
|
|
||||||
<button color="primary" mat-raised-button (click)="createDeposit()">Create</button>
|
<button color="primary" mat-raised-button (click)="createDeposit()">Create</button>
|
||||||
</v-table-actions>
|
</v-table-actions>
|
||||||
</v-table>
|
</v-table2>
|
||||||
</cc-page-layout>
|
</cc-page-layout>
|
||||||
|
@ -2,10 +2,9 @@ import { ChangeDetectionStrategy, Component, OnInit, Inject, DestroyRef } from '
|
|||||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { NonNullableFormBuilder } from '@angular/forms';
|
import { NonNullableFormBuilder } from '@angular/forms';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { StatDeposit, RevertStatus } from '@vality/fistful-proto/fistful_stat';
|
import { fistful_stat } from '@vality/fistful-proto';
|
||||||
|
import { StatDeposit } from '@vality/fistful-proto/fistful_stat';
|
||||||
import {
|
import {
|
||||||
Column,
|
|
||||||
createOperationColumn,
|
|
||||||
UpdateOptions,
|
UpdateOptions,
|
||||||
createDateRangeToToday,
|
createDateRangeToToday,
|
||||||
QueryParamsService,
|
QueryParamsService,
|
||||||
@ -17,26 +16,24 @@ import {
|
|||||||
debounceTimeWithFirst,
|
debounceTimeWithFirst,
|
||||||
getValueChanges,
|
getValueChanges,
|
||||||
countChanged,
|
countChanged,
|
||||||
|
Column2,
|
||||||
|
getEnumKey,
|
||||||
|
createMenuColumn,
|
||||||
} from '@vality/ng-core';
|
} from '@vality/ng-core';
|
||||||
import { getUnionKey } from '@vality/ng-thrift';
|
import { getUnionKey } from '@vality/ng-thrift';
|
||||||
import { endOfDay } from 'date-fns';
|
import { endOfDay } from 'date-fns';
|
||||||
import startCase from 'lodash-es/startCase';
|
import startCase from 'lodash-es/startCase';
|
||||||
import { filter, map, shareReplay } from 'rxjs/operators';
|
import { filter, map, shareReplay } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { createCurrencyColumn } from '@cc/app/shared/utils/table2';
|
||||||
|
|
||||||
import { QueryDsl } from '../../api/fistful-stat';
|
import { QueryDsl } from '../../api/fistful-stat';
|
||||||
import { createCurrencyColumn } from '../../shared';
|
|
||||||
import { DATE_RANGE_DAYS, DEBOUNCE_TIME_MS } from '../../tokens';
|
import { DATE_RANGE_DAYS, DEBOUNCE_TIME_MS } from '../../tokens';
|
||||||
|
|
||||||
import { CreateDepositDialogComponent } from './components/create-deposit-dialog/create-deposit-dialog.component';
|
import { CreateDepositDialogComponent } from './components/create-deposit-dialog/create-deposit-dialog.component';
|
||||||
import { CreateDepositsByFileDialogComponent } from './components/create-deposits-by-file-dialog/create-deposits-by-file-dialog.component';
|
import { CreateDepositsByFileDialogComponent } from './components/create-deposits-by-file-dialog/create-deposits-by-file-dialog.component';
|
||||||
import { FetchDepositsService } from './services/fetch-deposits/fetch-deposits.service';
|
import { FetchDepositsService } from './services/fetch-deposits/fetch-deposits.service';
|
||||||
|
|
||||||
const REVERT_STATUS: { [N in RevertStatus]: string } = {
|
|
||||||
0: 'none',
|
|
||||||
1: 'partial',
|
|
||||||
2: 'full',
|
|
||||||
};
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: 'deposits.component.html',
|
templateUrl: 'deposits.component.html',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
@ -56,30 +53,31 @@ export class DepositsComponent implements OnInit {
|
|||||||
deposits$ = this.fetchDepositsService.result$;
|
deposits$ = this.fetchDepositsService.result$;
|
||||||
hasMore$ = this.fetchDepositsService.hasMore$;
|
hasMore$ = this.fetchDepositsService.hasMore$;
|
||||||
isLoading$ = this.fetchDepositsService.isLoading$;
|
isLoading$ = this.fetchDepositsService.isLoading$;
|
||||||
columns: Column<StatDeposit>[] = [
|
columns: Column2<StatDeposit>[] = [
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
formatter: (d) => d.description || `#${d.id}`,
|
cell: (d) => ({
|
||||||
link: (d) => `/deposits/${d.id}`,
|
value: d.description || `#${d.id}`,
|
||||||
description: 'id',
|
link: () => `/deposits/${d.id}`,
|
||||||
maxWidth: 'max(300px, 30vw)',
|
description: d.id,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'status',
|
field: 'status',
|
||||||
type: 'tag',
|
cell: (d) => ({
|
||||||
formatter: (d) => getUnionKey(d.status),
|
value: startCase(getUnionKey(d.status)),
|
||||||
typeParameters: {
|
color: (
|
||||||
label: (d) => startCase(getUnionKey(d.status)),
|
{
|
||||||
tags: {
|
pending: 'pending',
|
||||||
pending: { color: 'pending' },
|
succeeded: 'success',
|
||||||
succeeded: { color: 'success' },
|
failed: 'warn',
|
||||||
failed: { color: 'warn' },
|
} as const
|
||||||
},
|
)[getUnionKey(d.status)],
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'created_at',
|
field: 'created_at',
|
||||||
type: 'datetime',
|
cell: { type: 'datetime' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'destination_id',
|
field: 'destination_id',
|
||||||
@ -87,36 +85,33 @@ export class DepositsComponent implements OnInit {
|
|||||||
{
|
{
|
||||||
field: 'identity_id',
|
field: 'identity_id',
|
||||||
},
|
},
|
||||||
createCurrencyColumn(
|
createCurrencyColumn((d) => ({ amount: d.amount, code: d.currency_symbolic_code }), {
|
||||||
'amount',
|
header: 'Amount',
|
||||||
(d) => d.amount,
|
}),
|
||||||
(d) => d.currency_symbolic_code,
|
createCurrencyColumn((d) => ({ amount: d.fee, code: d.currency_symbolic_code }), {
|
||||||
),
|
header: 'Fee',
|
||||||
createCurrencyColumn(
|
}),
|
||||||
'fee',
|
|
||||||
(d) => d.fee,
|
|
||||||
(d) => d.currency_symbolic_code,
|
|
||||||
{ hide: true },
|
|
||||||
),
|
|
||||||
{
|
|
||||||
field: 'source_id',
|
|
||||||
hide: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
field: 'revert_status',
|
field: 'revert_status',
|
||||||
type: 'tag',
|
cell: (d) => ({
|
||||||
formatter: (d) => REVERT_STATUS[d.revert_status],
|
value: startCase(getEnumKey(fistful_stat.RevertStatus, d.revert_status)),
|
||||||
typeParameters: {
|
color: (
|
||||||
label: (d) => startCase(REVERT_STATUS[d.revert_status]),
|
{
|
||||||
tags: {},
|
none: 'neutral',
|
||||||
},
|
partial: 'pending',
|
||||||
|
full: 'success',
|
||||||
|
} as const
|
||||||
|
)[getEnumKey(fistful_stat.RevertStatus, d.revert_status)],
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
createOperationColumn([
|
createMenuColumn((d) => ({
|
||||||
{
|
items: [
|
||||||
label: 'Details',
|
{
|
||||||
click: (d) => this.router.navigate([`/deposits/${d.id}`]),
|
label: 'Details',
|
||||||
},
|
click: () => this.router.navigate([`/deposits/${d.id}`]),
|
||||||
]),
|
},
|
||||||
|
],
|
||||||
|
})),
|
||||||
];
|
];
|
||||||
depositStatuses: QueryDsl['query']['deposits']['status'][] = ['Pending', 'Succeeded', 'Failed'];
|
depositStatuses: QueryDsl['query']['deposits']['status'][] = ['Pending', 'Succeeded', 'Failed'];
|
||||||
active$ = getValueChanges(this.filtersForm).pipe(
|
active$ = getValueChanges(this.filtersForm).pipe(
|
||||||
|
@ -13,7 +13,6 @@ import {
|
|||||||
getValueChanges,
|
getValueChanges,
|
||||||
Column2,
|
Column2,
|
||||||
createMenuColumn,
|
createMenuColumn,
|
||||||
TABLE_WRAPPER_STYLE,
|
|
||||||
} from '@vality/ng-core';
|
} from '@vality/ng-core';
|
||||||
import sortBy from 'lodash-es/sortBy';
|
import sortBy from 'lodash-es/sortBy';
|
||||||
import startCase from 'lodash-es/startCase';
|
import startCase from 'lodash-es/startCase';
|
||||||
@ -51,7 +50,6 @@ interface DomainObjectData {
|
|||||||
ActionsModule,
|
ActionsModule,
|
||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
],
|
],
|
||||||
host: { style: TABLE_WRAPPER_STYLE },
|
|
||||||
})
|
})
|
||||||
export class DomainObjectsTableComponent implements OnInit {
|
export class DomainObjectsTableComponent implements OnInit {
|
||||||
@Output() selectedChange = new EventEmitter<string[]>();
|
@Output() selectedChange = new EventEmitter<string[]>();
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
import { Component, input } from '@angular/core';
|
||||||
|
import { Column2, getEnumKey, TableModule } from '@vality/ng-core';
|
||||||
|
import { repairer } from '@vality/repairer-proto';
|
||||||
|
import { StatusHistory } from '@vality/repairer-proto/repairer';
|
||||||
|
import { startCase } from 'lodash-es';
|
||||||
|
|
||||||
|
import { SidenavInfoModule } from '@cc/app/shared/components/sidenav-info';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
standalone: true,
|
||||||
|
template: `<cc-card title="Machine #{{ id() }} Status History"
|
||||||
|
><v-table2 [columns]="columns" [data]="history()"></v-table2
|
||||||
|
></cc-card>`,
|
||||||
|
imports: [TableModule, SidenavInfoModule],
|
||||||
|
})
|
||||||
|
export class MachineStatusHistoryCardComponent {
|
||||||
|
history = input<StatusHistory[]>([]);
|
||||||
|
id = input<string>('');
|
||||||
|
|
||||||
|
columns: Column2<StatusHistory>[] = [
|
||||||
|
{ field: 'changed_at', cell: { type: 'datetime' } },
|
||||||
|
{
|
||||||
|
field: 'status',
|
||||||
|
cell: (d) => ({
|
||||||
|
value: startCase(getEnumKey(repairer.RepairStatus, d.status)),
|
||||||
|
color: (
|
||||||
|
{
|
||||||
|
failed: 'warn',
|
||||||
|
in_progress: 'pending',
|
||||||
|
repaired: 'success',
|
||||||
|
} as const
|
||||||
|
)[getEnumKey(repairer.RepairStatus, d.status)],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
@ -3,7 +3,7 @@ import { RouterModule } from '@angular/router';
|
|||||||
|
|
||||||
import { AppAuthGuardService } from '../../shared/services';
|
import { AppAuthGuardService } from '../../shared/services';
|
||||||
|
|
||||||
import { RepairingComponent } from './repairing.component';
|
import { MachinesComponent } from './machines.component';
|
||||||
import { ROUTING_CONFIG } from './routing-config';
|
import { ROUTING_CONFIG } from './routing-config';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -11,7 +11,7 @@ import { ROUTING_CONFIG } from './routing-config';
|
|||||||
RouterModule.forChild([
|
RouterModule.forChild([
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: RepairingComponent,
|
component: MachinesComponent,
|
||||||
canActivate: [AppAuthGuardService],
|
canActivate: [AppAuthGuardService],
|
||||||
data: ROUTING_CONFIG,
|
data: ROUTING_CONFIG,
|
||||||
},
|
},
|
||||||
@ -19,4 +19,4 @@ import { ROUTING_CONFIG } from './routing-config';
|
|||||||
],
|
],
|
||||||
exports: [RouterModule],
|
exports: [RouterModule],
|
||||||
})
|
})
|
||||||
export class RepairingRoutingModule {}
|
export class MachinesRoutingModule {}
|
@ -1,4 +1,4 @@
|
|||||||
<cc-page-layout title="Machines">
|
<cc-page-layout fullHeight title="Machines">
|
||||||
<cc-page-layout-actions>
|
<cc-page-layout-actions>
|
||||||
<v-more-filters-button [filters]="filters"></v-more-filters-button>
|
<v-more-filters-button [filters]="filters"></v-more-filters-button>
|
||||||
</cc-page-layout-actions>
|
</cc-page-layout-actions>
|
||||||
@ -33,7 +33,7 @@
|
|||||||
</ng-template>
|
</ng-template>
|
||||||
</v-filters>
|
</v-filters>
|
||||||
|
|
||||||
<v-table
|
<v-table2
|
||||||
[columns]="columns"
|
[columns]="columns"
|
||||||
[data]="machines$ | async"
|
[data]="machines$ | async"
|
||||||
[hasMore]="hasMore$ | async"
|
[hasMore]="hasMore$ | async"
|
||||||
@ -61,5 +61,5 @@
|
|||||||
Simple repair
|
Simple repair
|
||||||
</button>
|
</button>
|
||||||
</v-table-actions>
|
</v-table-actions>
|
||||||
</v-table>
|
</v-table2>
|
||||||
</cc-page-layout>
|
</cc-page-layout>
|
@ -5,7 +5,6 @@ import {
|
|||||||
DialogResponseStatus,
|
DialogResponseStatus,
|
||||||
DialogService,
|
DialogService,
|
||||||
clean,
|
clean,
|
||||||
Column,
|
|
||||||
ConfirmDialogComponent,
|
ConfirmDialogComponent,
|
||||||
QueryParamsService,
|
QueryParamsService,
|
||||||
NotifyLogService,
|
NotifyLogService,
|
||||||
@ -18,6 +17,7 @@ import {
|
|||||||
debounceTimeWithFirst,
|
debounceTimeWithFirst,
|
||||||
FetchOptions,
|
FetchOptions,
|
||||||
getEnumKey,
|
getEnumKey,
|
||||||
|
Column2,
|
||||||
} from '@vality/ng-core';
|
} from '@vality/ng-core';
|
||||||
import { repairer } from '@vality/repairer-proto';
|
import { repairer } from '@vality/repairer-proto';
|
||||||
import { Namespace, ProviderID, RepairStatus, Machine } from '@vality/repairer-proto/repairer';
|
import { Namespace, ProviderID, RepairStatus, Machine } from '@vality/repairer-proto/repairer';
|
||||||
@ -27,10 +27,13 @@ import startCase from 'lodash-es/startCase';
|
|||||||
import { BehaviorSubject } from 'rxjs';
|
import { BehaviorSubject } from 'rxjs';
|
||||||
import { filter, switchMap, map, shareReplay } from 'rxjs/operators';
|
import { filter, switchMap, map, shareReplay } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { SidenavInfoService } from '@cc/app/shared/components/sidenav-info';
|
||||||
|
import { createDomainObjectColumn } from '@cc/app/shared/utils/table2';
|
||||||
|
|
||||||
import { RepairManagementService } from '../../api/repairer';
|
import { RepairManagementService } from '../../api/repairer';
|
||||||
import { createProviderColumn } from '../../shared/utils/table/create-provider-column';
|
|
||||||
import { DATE_RANGE_DAYS, DEBOUNCE_TIME_MS } from '../../tokens';
|
import { DATE_RANGE_DAYS, DEBOUNCE_TIME_MS } from '../../tokens';
|
||||||
|
|
||||||
|
import { MachineStatusHistoryCardComponent } from './components/machine-status-history-card.component';
|
||||||
import { RepairByScenarioDialogComponent } from './components/repair-by-scenario-dialog/repair-by-scenario-dialog.component';
|
import { RepairByScenarioDialogComponent } from './components/repair-by-scenario-dialog/repair-by-scenario-dialog.component';
|
||||||
import { MachinesService } from './services/machines.service';
|
import { MachinesService } from './services/machines.service';
|
||||||
|
|
||||||
@ -44,11 +47,11 @@ interface Filters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'cc-repairing',
|
selector: 'cc-machines',
|
||||||
templateUrl: './repairing.component.html',
|
templateUrl: './machines.component.html',
|
||||||
providers: [MachinesService],
|
providers: [MachinesService],
|
||||||
})
|
})
|
||||||
export class RepairingComponent implements OnInit {
|
export class MachinesComponent implements OnInit {
|
||||||
machines$ = this.machinesService.result$;
|
machines$ = this.machinesService.result$;
|
||||||
inProgress$ = this.machinesService.isLoading$;
|
inProgress$ = this.machinesService.isLoading$;
|
||||||
hasMore$ = this.machinesService.hasMore$;
|
hasMore$ = this.machinesService.hasMore$;
|
||||||
@ -62,28 +65,36 @@ export class RepairingComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
selected$ = new BehaviorSubject<Machine[]>([]);
|
selected$ = new BehaviorSubject<Machine[]>([]);
|
||||||
status = repairer.RepairStatus;
|
status = repairer.RepairStatus;
|
||||||
columns: Column<Machine>[] = [
|
columns: Column2<Machine>[] = [
|
||||||
{ field: 'id' },
|
{ field: 'id', sticky: 'start' },
|
||||||
{ header: 'Namespace', field: 'ns' },
|
{ header: 'Namespace', field: 'ns' },
|
||||||
{ field: 'created_at', type: 'datetime' },
|
{ field: 'created_at', cell: { type: 'datetime' } },
|
||||||
createProviderColumn((d) => Number(d.provider_id)),
|
createDomainObjectColumn((d) => ({ ref: { terminal: { id: Number(d.provider_id) } } }), {
|
||||||
|
header: 'Terminal',
|
||||||
|
}),
|
||||||
{
|
{
|
||||||
field: 'status',
|
field: 'status',
|
||||||
formatter: (d) => getEnumKey(repairer.RepairStatus, d.status),
|
cell: (d) => ({
|
||||||
type: 'tag',
|
value: startCase(getEnumKey(repairer.RepairStatus, d.status)),
|
||||||
typeParameters: {
|
color: (
|
||||||
label: (d) => startCase(getEnumKey(repairer.RepairStatus, d.status)),
|
{
|
||||||
tags: {
|
failed: 'warn',
|
||||||
failed: { color: 'warn' },
|
in_progress: 'pending',
|
||||||
in_progress: { color: 'pending' },
|
repaired: 'success',
|
||||||
repaired: { color: 'success' },
|
} as const
|
||||||
},
|
)[getEnumKey(repairer.RepairStatus, d.status)],
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'history',
|
field: 'history',
|
||||||
formatter: (data) => (data.history?.length ? String(data.history.length) : ''),
|
cell: (d) => ({
|
||||||
tooltip: 'history',
|
value: d.history?.length ? String(d.history.length) : '',
|
||||||
|
click: () => {
|
||||||
|
this.sidenavInfoService.toggle(MachineStatusHistoryCardComponent, {
|
||||||
|
history: d.history,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'error_message',
|
field: 'error_message',
|
||||||
@ -106,6 +117,7 @@ export class RepairingComponent implements OnInit {
|
|||||||
private destroyRef: DestroyRef,
|
private destroyRef: DestroyRef,
|
||||||
@Inject(DATE_RANGE_DAYS) private dateRangeDays: number,
|
@Inject(DATE_RANGE_DAYS) private dateRangeDays: number,
|
||||||
@Inject(DEBOUNCE_TIME_MS) private debounceTimeMs: number,
|
@Inject(DEBOUNCE_TIME_MS) private debounceTimeMs: number,
|
||||||
|
private sidenavInfoService: SidenavInfoService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
@ -28,13 +28,13 @@ import { ThriftFormModule } from '@cc/app/shared/components/metadata-form';
|
|||||||
import { DomainObjectFieldComponent } from '@cc/app/shared/components/thrift-api-crud';
|
import { DomainObjectFieldComponent } from '@cc/app/shared/components/thrift-api-crud';
|
||||||
|
|
||||||
import { RepairByScenarioDialogComponent } from './components/repair-by-scenario-dialog/repair-by-scenario-dialog.component';
|
import { RepairByScenarioDialogComponent } from './components/repair-by-scenario-dialog/repair-by-scenario-dialog.component';
|
||||||
import { RepairingRoutingModule } from './repairing-routing.module';
|
import { MachinesRoutingModule } from './machines-routing.module';
|
||||||
import { RepairingComponent } from './repairing.component';
|
import { MachinesComponent } from './machines.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
RepairingRoutingModule,
|
MachinesRoutingModule,
|
||||||
TableModule,
|
TableModule,
|
||||||
MatCardModule,
|
MatCardModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
@ -59,6 +59,6 @@ import { RepairingComponent } from './repairing.component';
|
|||||||
ThriftPipesModule,
|
ThriftPipesModule,
|
||||||
FiltersModule,
|
FiltersModule,
|
||||||
],
|
],
|
||||||
declarations: [RepairingComponent, RepairByScenarioDialogComponent],
|
declarations: [MachinesComponent, RepairByScenarioDialogComponent],
|
||||||
})
|
})
|
||||||
export class RepairingModule {}
|
export class MachinesModule {}
|
@ -1,4 +1,4 @@
|
|||||||
<cc-page-layout title="Shops">
|
<cc-page-layout fullHeight title="Shops">
|
||||||
<cc-shops-table
|
<cc-shops-table
|
||||||
[progress]="progress$ | async"
|
[progress]="progress$ | async"
|
||||||
[shops]="shopsParty$ | async"
|
[shops]="shopsParty$ | async"
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
<cc-sub-page-layout [links]="links" [tags]="tags$ | async"
|
<cc-sub-page-layout [links]="links">
|
||||||
><router-outlet></router-outlet
|
<router-outlet></router-outlet>
|
||||||
></cc-sub-page-layout>
|
</cc-sub-page-layout>
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
<cc-page-layout [progress]="isLoading$ | async" title="Chargebacks">
|
<cc-page-layout [progress]="isLoading$ | async" fullHeight title="Chargebacks">
|
||||||
<cc-page-layout-actions>
|
<cc-chargebacks-table
|
||||||
|
[data]="chargebacks$ | async"
|
||||||
|
[hasMore]="fetchChargebacksService.hasMore$ | async"
|
||||||
|
[isLoading]="isLoading$ | async"
|
||||||
|
onePayment
|
||||||
|
(more)="fetchChargebacksService.more()"
|
||||||
|
(update)="update()"
|
||||||
|
>
|
||||||
<button color="primary" mat-raised-button (click)="createChargeback()">Create</button>
|
<button color="primary" mat-raised-button (click)="createChargeback()">Create</button>
|
||||||
</cc-page-layout-actions>
|
</cc-chargebacks-table>
|
||||||
<cc-chargebacks
|
|
||||||
[chargebacks]="chargebacks$ | async"
|
|
||||||
[invoiceId]="(payment$ | async).invoice_id"
|
|
||||||
[paymentId]="(payment$ | async).id"
|
|
||||||
></cc-chargebacks>
|
|
||||||
</cc-page-layout>
|
</cc-page-layout>
|
||||||
|
@ -1,49 +1,42 @@
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { Component, DestroyRef } from '@angular/core';
|
import { Component, DestroyRef, OnInit } from '@angular/core';
|
||||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { MatButton } from '@angular/material/button';
|
import { MatButton } from '@angular/material/button';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { DialogResponseStatus, DialogService } from '@vality/ng-core';
|
import { DialogResponseStatus, DialogService } from '@vality/ng-core';
|
||||||
import { merge, defer, Subject } from 'rxjs';
|
import { first } from 'rxjs';
|
||||||
import { map, switchMap, shareReplay } from 'rxjs/operators';
|
|
||||||
|
import { FetchChargebacksService } from '@cc/app/sections/chargebacks/fetch-chargebacks.service';
|
||||||
|
import { ChargebacksTableComponent } from '@cc/app/shared/components/chargebacks-table';
|
||||||
|
|
||||||
import { InvoicingService } from '../../../../api/payment-processing';
|
|
||||||
import { PageLayoutModule } from '../../../../shared';
|
import { PageLayoutModule } from '../../../../shared';
|
||||||
import { ChargebacksComponent } from '../../../../shared/components/chargebacks/chargebacks.component';
|
|
||||||
import { CreateChargebackDialogComponent } from '../../create-chargeback-dialog/create-chargeback-dialog.component';
|
import { CreateChargebackDialogComponent } from '../../create-chargeback-dialog/create-chargeback-dialog.component';
|
||||||
import { PaymentDetailsService } from '../../payment-details.service';
|
import { PaymentDetailsService } from '../../payment-details.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'cc-payment-chargebacks',
|
selector: 'cc-payment-chargebacks',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, PageLayoutModule, MatButton, ChargebacksComponent],
|
imports: [CommonModule, PageLayoutModule, MatButton, ChargebacksTableComponent],
|
||||||
templateUrl: './payment-chargebacks.component.html',
|
templateUrl: './payment-chargebacks.component.html',
|
||||||
styles: ``,
|
providers: [FetchChargebacksService],
|
||||||
})
|
})
|
||||||
export class PaymentChargebacksComponent {
|
export class PaymentChargebacksComponent implements OnInit {
|
||||||
payment$ = this.paymentDetailsService.payment$;
|
payment$ = this.paymentDetailsService.payment$;
|
||||||
isLoading$ = this.paymentDetailsService.isLoading$;
|
isLoading$ = this.paymentDetailsService.isLoading$;
|
||||||
chargebacks$ = merge(
|
chargebacks$ = this.fetchChargebacksService.result$;
|
||||||
this.route.params,
|
|
||||||
defer(() => this.updateChargebacks$),
|
|
||||||
).pipe(
|
|
||||||
map(() => this.route.snapshot.params as Record<'invoiceID' | 'paymentID', string>),
|
|
||||||
switchMap(({ invoiceID, paymentID }) =>
|
|
||||||
this.invoicingService.GetPayment(invoiceID, paymentID),
|
|
||||||
),
|
|
||||||
map(({ chargebacks }) => chargebacks),
|
|
||||||
shareReplay({ refCount: true, bufferSize: 1 }),
|
|
||||||
);
|
|
||||||
private updateChargebacks$ = new Subject<void>();
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private invoicingService: InvoicingService,
|
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
private dr: DestroyRef,
|
private dr: DestroyRef,
|
||||||
private paymentDetailsService: PaymentDetailsService,
|
private paymentDetailsService: PaymentDetailsService,
|
||||||
|
protected fetchChargebacksService: FetchChargebacksService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
createChargeback() {
|
createChargeback() {
|
||||||
this.dialogService
|
this.dialogService
|
||||||
.open(
|
.open(
|
||||||
@ -54,8 +47,21 @@ export class PaymentChargebacksComponent {
|
|||||||
.pipe(takeUntilDestroyed(this.dr))
|
.pipe(takeUntilDestroyed(this.dr))
|
||||||
.subscribe(({ status }) => {
|
.subscribe(({ status }) => {
|
||||||
if (status === DialogResponseStatus.Success) {
|
if (status === DialogResponseStatus.Success) {
|
||||||
this.updateChargebacks$.next();
|
this.update();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
this.payment$.pipe(first(), takeUntilDestroyed(this.dr)).subscribe((p) => {
|
||||||
|
this.fetchChargebacksService.load({
|
||||||
|
common_search_query_params: {
|
||||||
|
from_time: new Date(0).toISOString(),
|
||||||
|
to_time: new Date().toISOString(),
|
||||||
|
},
|
||||||
|
payment_id: p.id,
|
||||||
|
invoice_ids: [p.invoice_id],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|||||||
import { FormControl } from '@angular/forms';
|
import { FormControl } from '@angular/forms';
|
||||||
import { InvoicePaymentChargeback } from '@vality/domain-proto/domain';
|
import { InvoicePaymentChargeback } from '@vality/domain-proto/domain';
|
||||||
import { InvoicePaymentChargebackParams } from '@vality/domain-proto/payment_processing';
|
import { InvoicePaymentChargebackParams } from '@vality/domain-proto/payment_processing';
|
||||||
import { DialogSuperclass, NotifyLogService } from '@vality/ng-core';
|
import { DialogSuperclass, getImportValue, NotifyLogService } from '@vality/ng-core';
|
||||||
import { from } from 'rxjs';
|
import { ThriftAstMetadata } from '@vality/ng-thrift';
|
||||||
import short from 'short-uuid';
|
import short from 'short-uuid';
|
||||||
|
|
||||||
import { InvoicingService } from '@cc/app/api/payment-processing';
|
import { InvoicingService } from '@cc/app/api/payment-processing';
|
||||||
@ -20,7 +20,7 @@ export class CreateChargebackDialogComponent extends DialogSuperclass<
|
|||||||
InvoicePaymentChargeback
|
InvoicePaymentChargeback
|
||||||
> {
|
> {
|
||||||
form = new FormControl<Partial<InvoicePaymentChargebackParams>>({ id: short().generate() });
|
form = new FormControl<Partial<InvoicePaymentChargebackParams>>({ id: short().generate() });
|
||||||
metadata$ = from(import('@vality/domain-proto/metadata.json').then((m) => m.default));
|
metadata$ = getImportValue<ThriftAstMetadata[]>(import('@vality/domain-proto/metadata.json'));
|
||||||
extensions$ = this.domainMetadataFormExtensionsService.extensions$;
|
extensions$ = this.domainMetadataFormExtensionsService.extensions$;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
{ label: 'Refunds', url: 'refunds' },
|
{ label: 'Refunds', url: 'refunds' },
|
||||||
{ label: 'Chargebacks', url: 'chargebacks' }
|
{ label: 'Chargebacks', url: 'chargebacks' }
|
||||||
]"
|
]"
|
||||||
[tags]="tags$ | async"
|
|
||||||
id="{{
|
id="{{
|
||||||
(payment$ | async) ? (payment$ | async)?.invoice_id + '.' + (payment$ | async)?.id : ''
|
(payment$ | async) ? (payment$ | async)?.invoice_id + '.' + (payment$ | async)?.id : ''
|
||||||
}}"
|
}}"
|
||||||
|
@ -12,7 +12,6 @@ import { StatusModule, PageLayoutModule, SubPageLayoutComponent } from '@cc/app/
|
|||||||
import { DetailsItemModule } from '@cc/components/details-item';
|
import { DetailsItemModule } from '@cc/components/details-item';
|
||||||
import { HeadlineModule } from '@cc/components/headline';
|
import { HeadlineModule } from '@cc/components/headline';
|
||||||
|
|
||||||
import { ChargebacksComponent } from '../../shared/components/chargebacks/chargebacks.component';
|
|
||||||
import { JsonViewerModule } from '../../shared/components/json-viewer';
|
import { JsonViewerModule } from '../../shared/components/json-viewer';
|
||||||
import { ThriftFormModule } from '../../shared/components/metadata-form';
|
import { ThriftFormModule } from '../../shared/components/metadata-form';
|
||||||
import { MagistaThriftViewerComponent } from '../../shared/components/thrift-api-crud';
|
import { MagistaThriftViewerComponent } from '../../shared/components/thrift-api-crud';
|
||||||
@ -34,7 +33,6 @@ import { RefundsTableModule } from './refunds-table';
|
|||||||
MatProgressSpinnerModule,
|
MatProgressSpinnerModule,
|
||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
MatDialogModule,
|
MatDialogModule,
|
||||||
ChargebacksComponent,
|
|
||||||
ActionsModule,
|
ActionsModule,
|
||||||
DialogModule,
|
DialogModule,
|
||||||
ThriftFormModule,
|
ThriftFormModule,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { StatPayment } from '@vality/magista-proto/magista';
|
import { StatPayment } from '@vality/magista-proto/magista';
|
||||||
import { LoadOptions, Column2, createMenuColumn, TABLE_WRAPPER_STYLE } from '@vality/ng-core';
|
import { LoadOptions, Column2, createMenuColumn } from '@vality/ng-core';
|
||||||
import { getUnionKey } from '@vality/ng-thrift';
|
import { getUnionKey } from '@vality/ng-thrift';
|
||||||
import startCase from 'lodash-es/startCase';
|
import startCase from 'lodash-es/startCase';
|
||||||
|
|
||||||
@ -18,7 +18,6 @@ import {
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'cc-payments-table',
|
selector: 'cc-payments-table',
|
||||||
templateUrl: './payments-table.component.html',
|
templateUrl: './payments-table.component.html',
|
||||||
host: { style: TABLE_WRAPPER_STYLE },
|
|
||||||
})
|
})
|
||||||
export class PaymentsTableComponent {
|
export class PaymentsTableComponent {
|
||||||
@Input() data!: StatPayment[];
|
@Input() data!: StatPayment[];
|
||||||
|
@ -34,7 +34,7 @@ const ROUTES: Routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'machines',
|
path: 'machines',
|
||||||
loadChildren: () => import('./repairing/repairing.module').then((m) => m.RepairingModule),
|
loadChildren: () => import('./machines/machines.module').then((m) => m.MachinesModule),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'payments',
|
path: 'payments',
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
<cc-page-layout title="Shops">
|
<cc-page-layout fullHeight title="Shops">
|
||||||
<cc-page-layout-actions></cc-page-layout-actions>
|
|
||||||
<cc-shops-table
|
<cc-shops-table
|
||||||
[progress]="progress$ | async"
|
[progress]="progress$ | async"
|
||||||
[shops]="shopsParty$ | async"
|
[shops]="shopsParty$ | async"
|
||||||
noSort
|
|
||||||
(filterChange)="filterChange$.next($event)"
|
(filterChange)="filterChange$.next($event)"
|
||||||
(update)="update()"
|
(update)="update()"
|
||||||
></cc-shops-table>
|
></cc-shops-table>
|
||||||
|
@ -2,7 +2,14 @@ import { Component } from '@angular/core';
|
|||||||
import { SearchShopHit } from '@vality/deanonimus-proto/deanonimus';
|
import { SearchShopHit } from '@vality/deanonimus-proto/deanonimus';
|
||||||
import { Column, progressTo, NotifyLogService } from '@vality/ng-core';
|
import { Column, progressTo, NotifyLogService } from '@vality/ng-core';
|
||||||
import { BehaviorSubject, defer, of, combineLatest, Subject, Observable } from 'rxjs';
|
import { BehaviorSubject, defer, of, combineLatest, Subject, Observable } from 'rxjs';
|
||||||
import { switchMap, shareReplay, catchError, map } from 'rxjs/operators';
|
import {
|
||||||
|
switchMap,
|
||||||
|
shareReplay,
|
||||||
|
catchError,
|
||||||
|
map,
|
||||||
|
debounceTime,
|
||||||
|
distinctUntilChanged,
|
||||||
|
} from 'rxjs/operators';
|
||||||
|
|
||||||
import { DeanonimusService } from '../../api/deanonimus';
|
import { DeanonimusService } from '../../api/deanonimus';
|
||||||
import { ShopParty } from '../../shared/components/shops-table';
|
import { ShopParty } from '../../shared/components/shops-table';
|
||||||
@ -14,7 +21,7 @@ import { ShopParty } from '../../shared/components/shops-table';
|
|||||||
export class ShopsComponent {
|
export class ShopsComponent {
|
||||||
filterChange$ = new Subject<string>();
|
filterChange$ = new Subject<string>();
|
||||||
shopsParty$: Observable<ShopParty[]> = combineLatest([
|
shopsParty$: Observable<ShopParty[]> = combineLatest([
|
||||||
this.filterChange$,
|
this.filterChange$.pipe(distinctUntilChanged(), debounceTime(500)),
|
||||||
defer(() => this.updateShops$),
|
defer(() => this.updateShops$),
|
||||||
]).pipe(
|
]).pipe(
|
||||||
switchMap(([search]) =>
|
switchMap(([search]) =>
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
<cc-page-layout title="Sources">
|
<cc-page-layout fullHeight title="Sources">
|
||||||
<cc-page-layout-actions>
|
<cc-page-layout-actions>
|
||||||
<button color="primary" mat-raised-button (click)="create()">Create</button>
|
<button color="primary" mat-raised-button (click)="create()">Create</button>
|
||||||
</cc-page-layout-actions>
|
</cc-page-layout-actions>
|
||||||
<v-table
|
<v-table2
|
||||||
|
[(sort)]="sort"
|
||||||
[columns]="columns"
|
[columns]="columns"
|
||||||
[data]="sources$ | async"
|
[data]="sources$ | async"
|
||||||
[progress]="!!(progress$ | async)"
|
[progress]="!!(progress$ | async)"
|
||||||
[sort]="{ direction: 'asc', active: 'name' }"
|
standaloneFilter
|
||||||
noActions
|
></v-table2>
|
||||||
sortOnFront
|
|
||||||
></v-table>
|
|
||||||
</cc-page-layout>
|
</cc-page-layout>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
import { Sort } from '@angular/material/sort';
|
||||||
import { Source } from '@vality/fistful-proto/internal/source';
|
import { Source } from '@vality/fistful-proto/internal/source';
|
||||||
import { DialogService, Column } from '@vality/ng-core';
|
import { DialogService, Column2 } from '@vality/ng-core';
|
||||||
|
|
||||||
import { CreateSourceComponent } from './create-source/create-source.component';
|
import { CreateSourceComponent } from './create-source/create-source.component';
|
||||||
import { FetchSourcesService } from './fetch-sources.service';
|
import { FetchSourcesService } from './fetch-sources.service';
|
||||||
@ -11,13 +12,14 @@ import { FetchSourcesService } from './fetch-sources.service';
|
|||||||
export class SourcesComponent {
|
export class SourcesComponent {
|
||||||
sources$ = this.fetchSourcesService.sources$;
|
sources$ = this.fetchSourcesService.sources$;
|
||||||
progress$ = this.fetchSourcesService.progress$;
|
progress$ = this.fetchSourcesService.progress$;
|
||||||
columns: Column<Source>[] = [
|
columns: Column2<Source>[] = [
|
||||||
{ field: 'id' },
|
{ field: 'id' },
|
||||||
{ field: 'name', sortable: true },
|
{ field: 'name' },
|
||||||
'identity',
|
{ field: 'identity' },
|
||||||
{ field: 'currency_symbolic_code', sortable: true },
|
{ field: 'currency_symbolic_code' },
|
||||||
{ field: 'created_at', type: 'datetime' },
|
{ field: 'created_at', cell: { type: 'datetime' } },
|
||||||
];
|
];
|
||||||
|
sort: Sort = { direction: 'asc', active: 'name' };
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private fetchSourcesService: FetchSourcesService,
|
private fetchSourcesService: FetchSourcesService,
|
||||||
|
@ -1,53 +1,53 @@
|
|||||||
<cc-page-layout title="Wallets">
|
<cc-page-layout fullHeight title="Wallets">
|
||||||
<cc-page-layout-actions>
|
<cc-page-layout-actions>
|
||||||
<v-more-filters-button *ngIf="filters" [filters]="filters"></v-more-filters-button>
|
<v-more-filters-button *ngIf="filters" [filters]="filters"></v-more-filters-button>
|
||||||
<v-switch-button
|
@if (!(party$ | async)) {
|
||||||
[formControl]="isFilterControl"
|
<v-switch-button
|
||||||
[states]="[
|
[formControl]="isFilterControl"
|
||||||
{ label: 'full-text search', icon: 'travel_explore' },
|
[states]="[
|
||||||
{ label: 'filters', icon: 'manage_search' }
|
{ label: 'full-text search', icon: 'travel_explore' },
|
||||||
]"
|
{ label: 'filters', icon: 'manage_search' }
|
||||||
></v-switch-button>
|
]"
|
||||||
|
></v-switch-button>
|
||||||
|
}
|
||||||
</cc-page-layout-actions>
|
</cc-page-layout-actions>
|
||||||
<v-filters
|
@if (isFilterTable$ | async) {
|
||||||
*ngIf="isFilterControl.value"
|
<v-filters [active]="active$ | async" merge (clear)="filtersForm.reset()">
|
||||||
[active]="active$ | async"
|
<ng-template [formGroup]="filtersForm">
|
||||||
merge
|
<cc-merchant-field
|
||||||
(clear)="filtersForm.reset()"
|
*ngIf="!(party$ | async)"
|
||||||
>
|
formControlName="party_id"
|
||||||
<ng-template [formGroup]="filtersForm">
|
></cc-merchant-field>
|
||||||
<cc-merchant-field
|
<v-list-field formControlName="wallet_id" label="Wallet IDs"></v-list-field>
|
||||||
*ngIf="!(party$ | async)"
|
<mat-form-field>
|
||||||
formControlName="party_id"
|
<mat-label>Identity ID</mat-label>
|
||||||
></cc-merchant-field>
|
<input formControlName="identity_id" matInput />
|
||||||
<v-list-field formControlName="wallet_id" label="Wallet IDs"></v-list-field>
|
</mat-form-field>
|
||||||
<mat-form-field>
|
<cc-currency-field formControlName="currency_code"></cc-currency-field>
|
||||||
<mat-label>Identity ID</mat-label>
|
</ng-template>
|
||||||
<input formControlName="identity_id" matInput />
|
</v-filters>
|
||||||
</mat-form-field>
|
}
|
||||||
<cc-currency-field formControlName="currency_code"></cc-currency-field>
|
|
||||||
</ng-template>
|
|
||||||
</v-filters>
|
|
||||||
|
|
||||||
<v-table
|
@if (isFilterTable$ | async) {
|
||||||
*ngIf="isFilterControl.value"
|
<v-table2
|
||||||
[columns]="filterColumns$ | async"
|
[columns]="filterColumns"
|
||||||
[data]="filterWallets$ | async"
|
[data]="filterWallets$ | async"
|
||||||
[hasMore]="filterHasMore$ | async"
|
[hasMore]="filterHasMore$ | async"
|
||||||
[progress]="filtersLoading$ | async"
|
[progress]="filtersLoading$ | async"
|
||||||
name="filterWallets"
|
name="filterWallets"
|
||||||
(more)="filterMore()"
|
(more)="filterMore()"
|
||||||
(update)="filterSearch($event)"
|
(update)="filterSearch($event)"
|
||||||
></v-table>
|
></v-table2>
|
||||||
<v-table
|
} @else {
|
||||||
*ngIf="!isFilterControl.value"
|
<v-table2
|
||||||
[columns]="fullTextSearchColumns"
|
[columns]="fullTextSearchColumns"
|
||||||
[data]="fullTextSearchWallets$ | async"
|
[data]="fullTextSearchWallets$ | async"
|
||||||
[progress]="fullTextSearchLoading$ | async"
|
[progress]="fullTextSearchLoading$ | async"
|
||||||
externalFilter
|
externalFilter
|
||||||
name="ftsWallets"
|
name="ftsWallets"
|
||||||
noActions
|
standaloneFilter
|
||||||
(filterChange)="fullTextSearch($event)"
|
(filterChange)="fullTextSearch($event)"
|
||||||
(update)="fullTextSearchReload()"
|
(update)="fullTextSearchReload()"
|
||||||
></v-table>
|
></v-table2>
|
||||||
|
}
|
||||||
</cc-page-layout>
|
</cc-page-layout>
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
import {
|
import { Component, OnInit, Inject, ViewChild, DestroyRef } from '@angular/core';
|
||||||
Component,
|
|
||||||
OnInit,
|
|
||||||
Inject,
|
|
||||||
ViewChild,
|
|
||||||
DestroyRef,
|
|
||||||
Injector,
|
|
||||||
runInInjectionContext,
|
|
||||||
} from '@angular/core';
|
|
||||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { FormControl, NonNullableFormBuilder } from '@angular/forms';
|
import { FormControl, NonNullableFormBuilder } from '@angular/forms';
|
||||||
import { SearchWalletHit } from '@vality/deanonimus-proto/internal/deanonimus';
|
import { SearchWalletHit } from '@vality/deanonimus-proto/internal/deanonimus';
|
||||||
@ -15,17 +7,17 @@ import { AccountBalance } from '@vality/fistful-proto/internal/account';
|
|||||||
import { StatWallet } from '@vality/fistful-proto/internal/fistful_stat';
|
import { StatWallet } from '@vality/fistful-proto/internal/fistful_stat';
|
||||||
import {
|
import {
|
||||||
clean,
|
clean,
|
||||||
Column,
|
|
||||||
QueryParamsService,
|
QueryParamsService,
|
||||||
NotifyLogService,
|
|
||||||
FiltersComponent,
|
FiltersComponent,
|
||||||
UpdateOptions,
|
UpdateOptions,
|
||||||
getValueChanges,
|
getValueChanges,
|
||||||
countChanged,
|
countChanged,
|
||||||
debounceTimeWithFirst,
|
debounceTimeWithFirst,
|
||||||
|
Column2,
|
||||||
|
DebounceTime,
|
||||||
} from '@vality/ng-core';
|
} from '@vality/ng-core';
|
||||||
import isNil from 'lodash-es/isNil';
|
import isNil from 'lodash-es/isNil';
|
||||||
import { of } from 'rxjs';
|
import { combineLatest, of } from 'rxjs';
|
||||||
import { map, shareReplay, catchError, take } from 'rxjs/operators';
|
import { map, shareReplay, catchError, take } from 'rxjs/operators';
|
||||||
import { MemoizeExpiring } from 'typescript-memoize';
|
import { MemoizeExpiring } from 'typescript-memoize';
|
||||||
|
|
||||||
@ -33,7 +25,7 @@ import { WalletParams } from '@cc/app/api/fistful-stat/query-dsl/types/wallet';
|
|||||||
import { ManagementService } from '@cc/app/api/wallet';
|
import { ManagementService } from '@cc/app/api/wallet';
|
||||||
|
|
||||||
import { IdentityManagementService } from '../../api/identity';
|
import { IdentityManagementService } from '../../api/identity';
|
||||||
import { createCurrencyColumn, createPartyColumn } from '../../shared';
|
import { createCurrencyColumn, createPartyColumn } from '../../shared/utils/table2';
|
||||||
import { DEBOUNCE_TIME_MS } from '../../tokens';
|
import { DEBOUNCE_TIME_MS } from '../../tokens';
|
||||||
import { PartyStoreService } from '../party';
|
import { PartyStoreService } from '../party';
|
||||||
|
|
||||||
@ -55,81 +47,81 @@ export class WalletsComponent implements OnInit {
|
|||||||
fullTextSearchWallets$ = this.fetchWalletsTextService.result$;
|
fullTextSearchWallets$ = this.fetchWalletsTextService.result$;
|
||||||
fullTextSearchLoading$ = this.fetchWalletsTextService.isLoading$;
|
fullTextSearchLoading$ = this.fetchWalletsTextService.isLoading$;
|
||||||
|
|
||||||
filterColumns$ = this.partyStoreService.party$.pipe(
|
filterColumns: Column2<StatWallet>[] = [
|
||||||
map((party) =>
|
{ field: 'id' },
|
||||||
runInInjectionContext(this.injector, () => [
|
{ field: 'name' },
|
||||||
{ field: 'id' },
|
{ field: 'currency_symbolic_code' },
|
||||||
{ field: 'name' },
|
{ field: 'identity_id' },
|
||||||
'currency_symbolic_code',
|
{ field: 'created_at', cell: { type: 'datetime' } },
|
||||||
'identity_id',
|
createCurrencyColumn(
|
||||||
{ field: 'created_at', type: 'datetime' },
|
(d) =>
|
||||||
createCurrencyColumn<StatWallet>(
|
this.getBalance(d.id).pipe(
|
||||||
'balance',
|
map((b) => ({ amount: b.current, code: b.currency.symbolic_code })),
|
||||||
(d) => this.getBalance(d.id).pipe(map((b) => b.current)),
|
|
||||||
(d) => this.getBalance(d.id).pipe(map((b) => b.currency.symbolic_code)),
|
|
||||||
{ lazy: true },
|
|
||||||
),
|
),
|
||||||
createCurrencyColumn<StatWallet>(
|
{ header: 'Balance', isLazyCell: true },
|
||||||
'hold',
|
|
||||||
(d) => this.getBalance(d.id).pipe(map((b) => b.current - b.expected_min)),
|
|
||||||
(d) => this.getBalance(d.id).pipe(map((b) => b.currency.symbolic_code)),
|
|
||||||
{ lazy: true },
|
|
||||||
),
|
|
||||||
createCurrencyColumn<StatWallet>(
|
|
||||||
'expected_min',
|
|
||||||
(d) => this.getBalance(d.id).pipe(map((b) => b.expected_min)),
|
|
||||||
(d) => this.getBalance(d.id).pipe(map((b) => b.currency.symbolic_code)),
|
|
||||||
{ lazy: true },
|
|
||||||
),
|
|
||||||
{
|
|
||||||
field: 'contract_id',
|
|
||||||
formatter: (d) =>
|
|
||||||
this.getIdentity(d.identity_id).pipe(
|
|
||||||
map((identity) => identity.contract_id),
|
|
||||||
),
|
|
||||||
lazy: true,
|
|
||||||
},
|
|
||||||
...(party
|
|
||||||
? []
|
|
||||||
: [
|
|
||||||
createPartyColumn<StatWallet>(
|
|
||||||
'party',
|
|
||||||
(d) =>
|
|
||||||
this.getIdentity(d.identity_id).pipe(
|
|
||||||
map((identity) => identity.party_id),
|
|
||||||
),
|
|
||||||
undefined,
|
|
||||||
{ lazy: true },
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
]),
|
|
||||||
),
|
),
|
||||||
);
|
createCurrencyColumn(
|
||||||
fullTextSearchColumns: Column<SearchWalletHit>[] = [
|
(d) =>
|
||||||
|
this.getBalance(d.id).pipe(
|
||||||
|
map((b) => ({
|
||||||
|
amount: b.current - b.expected_min,
|
||||||
|
code: b.currency.symbolic_code,
|
||||||
|
})),
|
||||||
|
),
|
||||||
|
{ header: 'Hold', isLazyCell: true },
|
||||||
|
),
|
||||||
|
createCurrencyColumn(
|
||||||
|
(d) =>
|
||||||
|
this.getBalance(d.id).pipe(
|
||||||
|
map((b) => ({ amount: b.expected_min, code: b.currency.symbolic_code })),
|
||||||
|
),
|
||||||
|
{ header: 'Expected Min', isLazyCell: true },
|
||||||
|
),
|
||||||
|
{
|
||||||
|
field: 'contract_id',
|
||||||
|
lazyCell: (d) =>
|
||||||
|
this.getIdentity(d.identity_id).pipe(
|
||||||
|
map((identity) => ({ value: identity.contract_id })),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
createPartyColumn(
|
||||||
|
(d) =>
|
||||||
|
this.getIdentity(d.identity_id).pipe(
|
||||||
|
map((identity) => ({ id: identity.party_id })),
|
||||||
|
),
|
||||||
|
{ hidden: this.partyStoreService.party$.pipe(map((p) => !p)) },
|
||||||
|
),
|
||||||
|
];
|
||||||
|
fullTextSearchColumns: Column2<SearchWalletHit>[] = [
|
||||||
{ field: 'wallet.id' },
|
{ field: 'wallet.id' },
|
||||||
{ field: 'wallet.name' },
|
{ field: 'wallet.name' },
|
||||||
createPartyColumn<SearchWalletHit>(
|
createPartyColumn((d) => ({
|
||||||
'party',
|
id: d.party.id,
|
||||||
(d) => d.party.id,
|
partyName: d.party.email,
|
||||||
(d) => d.party.email,
|
})),
|
||||||
|
createCurrencyColumn(
|
||||||
|
(d) =>
|
||||||
|
this.getBalance(d.wallet.id).pipe(
|
||||||
|
map((b) => ({ amount: b.current, code: b.currency.symbolic_code })),
|
||||||
|
),
|
||||||
|
{ header: 'Balance', isLazyCell: true },
|
||||||
),
|
),
|
||||||
createCurrencyColumn<SearchWalletHit>(
|
createCurrencyColumn(
|
||||||
'balance',
|
(d) =>
|
||||||
(d) => this.getBalance(d.wallet.id).pipe(map((b) => b.current)),
|
this.getBalance(d.wallet.id).pipe(
|
||||||
(d) => this.getBalance(d.wallet.id).pipe(map((b) => b.currency.symbolic_code)),
|
map((b) => ({
|
||||||
{ lazy: true },
|
amount: b.current - b.expected_min,
|
||||||
|
code: b.currency.symbolic_code,
|
||||||
|
})),
|
||||||
|
),
|
||||||
|
{ header: 'Hold', isLazyCell: true },
|
||||||
),
|
),
|
||||||
createCurrencyColumn<SearchWalletHit>(
|
createCurrencyColumn(
|
||||||
'hold',
|
(d) =>
|
||||||
(d) => this.getBalance(d.wallet.id).pipe(map((b) => b.current - b.expected_min)),
|
this.getBalance(d.wallet.id).pipe(
|
||||||
(d) => this.getBalance(d.wallet.id).pipe(map((b) => b.currency.symbolic_code)),
|
map((b) => ({ amount: b.expected_min, code: b.currency.symbolic_code })),
|
||||||
{ lazy: true },
|
),
|
||||||
),
|
{ header: 'Expected Min', isLazyCell: true },
|
||||||
createCurrencyColumn<SearchWalletHit>(
|
|
||||||
'expected_min',
|
|
||||||
(d) => this.getBalance(d.wallet.id).pipe(map((b) => b.expected_min)),
|
|
||||||
(d) => this.getBalance(d.wallet.id).pipe(map((b) => b.currency.symbolic_code)),
|
|
||||||
{ lazy: true },
|
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
filtersForm = this.fb.group({
|
filtersForm = this.fb.group({
|
||||||
@ -145,6 +137,10 @@ export class WalletsComponent implements OnInit {
|
|||||||
@ViewChild(FiltersComponent) filters!: FiltersComponent;
|
@ViewChild(FiltersComponent) filters!: FiltersComponent;
|
||||||
typeQp = this.qp.createNamespace<{ isFilter: boolean }>('type');
|
typeQp = this.qp.createNamespace<{ isFilter: boolean }>('type');
|
||||||
party$ = this.partyStoreService.party$;
|
party$ = this.partyStoreService.party$;
|
||||||
|
isFilterTable$ = combineLatest([getValueChanges(this.isFilterControl), this.party$]).pipe(
|
||||||
|
map(([isFilterControl, party]) => isFilterControl || !!party),
|
||||||
|
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||||
|
);
|
||||||
|
|
||||||
private initFilters = this.filtersForm.value;
|
private initFilters = this.filtersForm.value;
|
||||||
|
|
||||||
@ -154,12 +150,10 @@ export class WalletsComponent implements OnInit {
|
|||||||
private qp: QueryParamsService<WalletParams>,
|
private qp: QueryParamsService<WalletParams>,
|
||||||
private fb: NonNullableFormBuilder,
|
private fb: NonNullableFormBuilder,
|
||||||
private walletManagementService: ManagementService,
|
private walletManagementService: ManagementService,
|
||||||
private log: NotifyLogService,
|
|
||||||
@Inject(DEBOUNCE_TIME_MS) private debounceTimeMs: number,
|
@Inject(DEBOUNCE_TIME_MS) private debounceTimeMs: number,
|
||||||
private destroyRef: DestroyRef,
|
private destroyRef: DestroyRef,
|
||||||
private identityManagementService: IdentityManagementService,
|
private identityManagementService: IdentityManagementService,
|
||||||
private partyStoreService: PartyStoreService,
|
private partyStoreService: PartyStoreService,
|
||||||
private injector: Injector,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@ -198,6 +192,7 @@ export class WalletsComponent implements OnInit {
|
|||||||
this.fetchWalletsService.more();
|
this.fetchWalletsService.more();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DebounceTime()
|
||||||
fullTextSearch(text: string) {
|
fullTextSearch(text: string) {
|
||||||
this.fetchWalletsTextService.load(text);
|
this.fetchWalletsTextService.load(text);
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,10 @@ import {
|
|||||||
NotifyLogService,
|
NotifyLogService,
|
||||||
EnumKeysPipe,
|
EnumKeysPipe,
|
||||||
EnumKeyPipe,
|
EnumKeyPipe,
|
||||||
|
getImportValue,
|
||||||
} from '@vality/ng-core';
|
} from '@vality/ng-core';
|
||||||
import { from, BehaviorSubject } from 'rxjs';
|
import { ThriftAstMetadata } from '@vality/ng-thrift';
|
||||||
|
import { BehaviorSubject } from 'rxjs';
|
||||||
|
|
||||||
import { InvoicingService } from '@cc/app/api/payment-processing';
|
import { InvoicingService } from '@cc/app/api/payment-processing';
|
||||||
import { DomainMetadataFormExtensionsService } from '@cc/app/shared/services';
|
import { DomainMetadataFormExtensionsService } from '@cc/app/shared/services';
|
||||||
@ -57,7 +59,7 @@ export class ChangeChargebacksStatusDialogComponent
|
|||||||
>
|
>
|
||||||
implements OnInit
|
implements OnInit
|
||||||
{
|
{
|
||||||
metadata$ = from(import('@vality/domain-proto/metadata.json').then((m) => m.default));
|
metadata$ = getImportValue<ThriftAstMetadata[]>(import('@vality/domain-proto/metadata.json'));
|
||||||
extensions$ = this.domainMetadataFormExtensionsService.extensions$;
|
extensions$ = this.domainMetadataFormExtensionsService.extensions$;
|
||||||
control = new FormControl();
|
control = new FormControl();
|
||||||
actionControl = new FormControl<Action>(null, Validators.required);
|
actionControl = new FormControl<Action>(null, Validators.required);
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
<v-table
|
<v-table2
|
||||||
|
[(rowSelected)]="selected"
|
||||||
[columns]="columns"
|
[columns]="columns"
|
||||||
[data]="data"
|
[data]="data"
|
||||||
[hasMore]="hasMore"
|
[hasMore]="hasMore"
|
||||||
[progress]="isLoading"
|
[progress]="isLoading"
|
||||||
[rowSelected]="selected"
|
|
||||||
rowSelectable
|
rowSelectable
|
||||||
(more)="more.emit()"
|
(more)="more.emit()"
|
||||||
(rowSelectedChange)="selectedChange.emit($event)"
|
|
||||||
(update)="update.emit($event)"
|
(update)="update.emit($event)"
|
||||||
>
|
>
|
||||||
<v-table-actions>
|
<v-table-actions>
|
||||||
|
<button [disabled]="!selected().length" mat-raised-button (click)="changeStatuses()">
|
||||||
|
Change statuses
|
||||||
|
</button>
|
||||||
<ng-content></ng-content>
|
<ng-content></ng-content>
|
||||||
</v-table-actions>
|
</v-table-actions>
|
||||||
</v-table>
|
</v-table2>
|
@ -0,0 +1,155 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
Input,
|
||||||
|
Output,
|
||||||
|
EventEmitter,
|
||||||
|
booleanAttribute,
|
||||||
|
input,
|
||||||
|
DestroyRef,
|
||||||
|
model,
|
||||||
|
} from '@angular/core';
|
||||||
|
import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { StatChargeback } from '@vality/magista-proto/magista';
|
||||||
|
import {
|
||||||
|
LoadOptions,
|
||||||
|
Column2,
|
||||||
|
TableModule,
|
||||||
|
DialogService,
|
||||||
|
createMenuColumn,
|
||||||
|
DialogResponseStatus,
|
||||||
|
} from '@vality/ng-core';
|
||||||
|
import { getUnionKey } from '@vality/ng-thrift';
|
||||||
|
import startCase from 'lodash-es/startCase';
|
||||||
|
import { filter } from 'rxjs';
|
||||||
|
|
||||||
|
import { createCurrencyColumn, createPartyColumn, createShopColumn } from '../../utils/table2';
|
||||||
|
import { ChangeChargebacksStatusDialogComponent } from '../change-chargebacks-status-dialog';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
standalone: true,
|
||||||
|
selector: 'cc-chargebacks-table',
|
||||||
|
templateUrl: './chargebacks-table.component.html',
|
||||||
|
imports: [CommonModule, TableModule, MatButtonModule],
|
||||||
|
})
|
||||||
|
export class ChargebacksTableComponent {
|
||||||
|
@Input() data!: StatChargeback[];
|
||||||
|
@Input() isLoading?: boolean | null;
|
||||||
|
@Input() hasMore?: boolean | null;
|
||||||
|
selected = model<StatChargeback[]>([]);
|
||||||
|
onePayment = input(false, { transform: booleanAttribute });
|
||||||
|
|
||||||
|
@Output() selectedChange = new EventEmitter<StatChargeback[]>();
|
||||||
|
@Output() update = new EventEmitter<LoadOptions>();
|
||||||
|
@Output() more = new EventEmitter<void>();
|
||||||
|
|
||||||
|
columns: Column2<StatChargeback>[] = [
|
||||||
|
{ field: 'chargeback_id', header: 'Id' },
|
||||||
|
{
|
||||||
|
field: 'chargeback_reason',
|
||||||
|
header: 'Reason',
|
||||||
|
cell: (d) => ({
|
||||||
|
value: startCase(getUnionKey(d.chargeback_reason.category)),
|
||||||
|
description: d.chargeback_reason.code,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'chargeback_status',
|
||||||
|
header: 'Status',
|
||||||
|
cell: (d) => ({
|
||||||
|
value: startCase(getUnionKey(d.chargeback_status)),
|
||||||
|
color: (
|
||||||
|
{
|
||||||
|
pending: 'pending',
|
||||||
|
accepted: 'success',
|
||||||
|
rejected: 'warn',
|
||||||
|
cancelled: 'neutral',
|
||||||
|
} as const
|
||||||
|
)[getUnionKey(d.chargeback_status)],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
createCurrencyColumn((d) => ({ amount: d.amount, code: d.currency_code.symbolic_code }), {
|
||||||
|
header: 'Amount',
|
||||||
|
}),
|
||||||
|
createCurrencyColumn(
|
||||||
|
(d) => ({ amount: d.levy_amount, code: d.levy_currency_code.symbolic_code }),
|
||||||
|
{ header: 'Levy Amount' },
|
||||||
|
),
|
||||||
|
createCurrencyColumn((d) => ({ amount: d.fee, code: d.currency_code.symbolic_code }), {
|
||||||
|
header: 'Fee',
|
||||||
|
}),
|
||||||
|
createCurrencyColumn(
|
||||||
|
(d) => ({ amount: d.provider_fee, code: d.currency_code.symbolic_code }),
|
||||||
|
{ header: 'Provider Fee' },
|
||||||
|
),
|
||||||
|
createCurrencyColumn(
|
||||||
|
(d) => ({ amount: d.external_fee, code: d.currency_code.symbolic_code }),
|
||||||
|
{ header: 'External Fee' },
|
||||||
|
),
|
||||||
|
{
|
||||||
|
field: 'stage',
|
||||||
|
cell: (d) => ({ value: startCase(getUnionKey(d.stage)) }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'invoice_id',
|
||||||
|
header: {
|
||||||
|
value: 'Invoice Id',
|
||||||
|
description: 'Payment Id',
|
||||||
|
},
|
||||||
|
cell: (d) => ({
|
||||||
|
description: d.payment_id,
|
||||||
|
link: () => `/party/${d.party_id}/invoice/${d.invoice_id}/payment/${d.payment_id}`,
|
||||||
|
}),
|
||||||
|
hidden: toObservable(this.onePayment),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'created_at',
|
||||||
|
cell: { type: 'datetime' },
|
||||||
|
},
|
||||||
|
createPartyColumn((d) => ({ id: d.party_id }), { hidden: toObservable(this.onePayment) }),
|
||||||
|
createShopColumn((d) => ({ shopId: d.shop_id, partyId: d.party_id }), {
|
||||||
|
hidden: toObservable(this.onePayment),
|
||||||
|
}),
|
||||||
|
createMenuColumn((d) => ({
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: 'Change status',
|
||||||
|
click: () => {
|
||||||
|
this.changeStatus(d);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})),
|
||||||
|
];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private dialogService: DialogService,
|
||||||
|
private dr: DestroyRef,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
changeStatus(chargeback: StatChargeback) {
|
||||||
|
this.dialogService.open(ChangeChargebacksStatusDialogComponent, {
|
||||||
|
chargebacks: [
|
||||||
|
{
|
||||||
|
payment_id: chargeback.payment_id,
|
||||||
|
invoice_id: chargeback.invoice_id,
|
||||||
|
chargeback_id: chargeback.chargeback_id,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
changeStatuses() {
|
||||||
|
this.dialogService
|
||||||
|
.open(ChangeChargebacksStatusDialogComponent, { chargebacks: this.selected() })
|
||||||
|
.afterClosed()
|
||||||
|
.pipe(
|
||||||
|
filter((res) => res.status === DialogResponseStatus.Success),
|
||||||
|
takeUntilDestroyed(this.dr),
|
||||||
|
)
|
||||||
|
.subscribe(() => {
|
||||||
|
this.update.emit();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
1
src/app/shared/components/chargebacks-table/index.ts
Normal file
1
src/app/shared/components/chargebacks-table/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './chargebacks-table.component';
|
@ -1 +0,0 @@
|
|||||||
<v-table [columns]="columns" [data]="chargebacks"></v-table>
|
|
@ -1,84 +0,0 @@
|
|||||||
import { CommonModule } from '@angular/common';
|
|
||||||
import { Component, Input } from '@angular/core';
|
|
||||||
import { InvoicePaymentChargeback } from '@vality/domain-proto/payment_processing';
|
|
||||||
import { DialogService, Column, TableModule, createOperationColumn } from '@vality/ng-core';
|
|
||||||
import { getUnionKey } from '@vality/ng-thrift';
|
|
||||||
import startCase from 'lodash-es/startCase';
|
|
||||||
|
|
||||||
import { createCurrencyColumn } from '@cc/app/shared';
|
|
||||||
import { DetailsDialogComponent } from '@cc/app/shared/components/details-dialog/details-dialog.component';
|
|
||||||
|
|
||||||
import { ChangeChargebacksStatusDialogComponent } from '../change-chargebacks-status-dialog';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
standalone: true,
|
|
||||||
selector: 'cc-chargebacks',
|
|
||||||
templateUrl: './chargebacks.component.html',
|
|
||||||
imports: [CommonModule, TableModule],
|
|
||||||
})
|
|
||||||
export class ChargebacksComponent {
|
|
||||||
@Input() chargebacks: InvoicePaymentChargeback[];
|
|
||||||
@Input() paymentId: string;
|
|
||||||
@Input() invoiceId: string;
|
|
||||||
|
|
||||||
columns: Column<InvoicePaymentChargeback>[] = [
|
|
||||||
'chargeback.id',
|
|
||||||
{
|
|
||||||
field: 'status',
|
|
||||||
type: 'tag',
|
|
||||||
formatter: (d) => getUnionKey(d.chargeback.status),
|
|
||||||
typeParameters: {
|
|
||||||
label: (d) => startCase(getUnionKey(d.chargeback.status)),
|
|
||||||
tags: {
|
|
||||||
pending: { color: 'pending' },
|
|
||||||
accepted: { color: 'success' },
|
|
||||||
rejected: { color: 'warn' },
|
|
||||||
cancelled: { color: 'neutral' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ field: 'chargeback.created_at', type: 'datetime' },
|
|
||||||
createCurrencyColumn(
|
|
||||||
'body',
|
|
||||||
(d) => d.chargeback.body.amount,
|
|
||||||
(d) => d.chargeback.body.currency.symbolic_code,
|
|
||||||
),
|
|
||||||
createCurrencyColumn(
|
|
||||||
'levy',
|
|
||||||
(d) => d.chargeback.levy.amount,
|
|
||||||
(d) => d.chargeback.levy.currency.symbolic_code,
|
|
||||||
),
|
|
||||||
{ field: 'stage', formatter: (d) => getUnionKey(d.chargeback.stage) },
|
|
||||||
createOperationColumn([
|
|
||||||
{
|
|
||||||
label: 'Details',
|
|
||||||
click: (d) => this.showDetails(d),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Change status',
|
|
||||||
click: (d) => this.changeStatus(d.chargeback.id),
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
];
|
|
||||||
|
|
||||||
constructor(private dialogService: DialogService) {}
|
|
||||||
|
|
||||||
changeStatus(id: string) {
|
|
||||||
this.dialogService.open(ChangeChargebacksStatusDialogComponent, {
|
|
||||||
chargebacks: [
|
|
||||||
{
|
|
||||||
payment_id: this.paymentId,
|
|
||||||
invoice_id: this.invoiceId,
|
|
||||||
chargeback_id: id,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
showDetails(chargeback: InvoicePaymentChargeback) {
|
|
||||||
this.dialogService.open(DetailsDialogComponent, {
|
|
||||||
title: 'Chargeback details',
|
|
||||||
json: chargeback,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,44 +4,44 @@
|
|||||||
(extensionResult$ | async)?.type || (extensionResult$ | async)?.template;
|
(extensionResult$ | async)?.type || (extensionResult$ | async)?.template;
|
||||||
else defaultFields
|
else defaultFields
|
||||||
"
|
"
|
||||||
[data]="data"
|
[data]="$any(data)"
|
||||||
[extensions]="extensions"
|
[extensions]="extensions"
|
||||||
[formControl]="control"
|
[formControl]="control"
|
||||||
></cc-extension-field>
|
></cc-extension-field>
|
||||||
<ng-template #defaultFields>
|
<ng-template #defaultFields>
|
||||||
<cc-primitive-field
|
<cc-primitive-field
|
||||||
*ngSwitchCase="'primitive'"
|
*ngSwitchCase="'primitive'"
|
||||||
[data]="data"
|
[data]="$any(data)"
|
||||||
[extensions]="extensions"
|
[extensions]="extensions"
|
||||||
[formControl]="control"
|
[formControl]="control"
|
||||||
></cc-primitive-field>
|
></cc-primitive-field>
|
||||||
<cc-complex-form
|
<cc-complex-form
|
||||||
*ngSwitchCase="'complex'"
|
*ngSwitchCase="'complex'"
|
||||||
[data]="data"
|
[data]="$any(data)"
|
||||||
[extensions]="extensions"
|
[extensions]="extensions"
|
||||||
[formControl]="control"
|
[formControl]="control"
|
||||||
></cc-complex-form>
|
></cc-complex-form>
|
||||||
<ng-container *ngSwitchCase="'object'" [ngSwitch]="data.objectType">
|
<ng-container *ngSwitchCase="'object'" [ngSwitch]="data.objectType">
|
||||||
<cc-struct-form
|
<cc-struct-form
|
||||||
*ngSwitchCase="'struct'"
|
*ngSwitchCase="'struct'"
|
||||||
[data]="data"
|
[data]="$any(data)"
|
||||||
[extensions]="extensions"
|
[extensions]="extensions"
|
||||||
[formControl]="control"
|
[formControl]="control"
|
||||||
></cc-struct-form>
|
></cc-struct-form>
|
||||||
<cc-union-field
|
<cc-union-field
|
||||||
*ngSwitchCase="'union'"
|
*ngSwitchCase="'union'"
|
||||||
[data]="data"
|
[data]="$any(data)"
|
||||||
[extensions]="extensions"
|
[extensions]="extensions"
|
||||||
[formControl]="control"
|
[formControl]="control"
|
||||||
></cc-union-field>
|
></cc-union-field>
|
||||||
<cc-enum-field
|
<cc-enum-field
|
||||||
*ngSwitchCase="'enum'"
|
*ngSwitchCase="'enum'"
|
||||||
[data]="data"
|
[data]="$any(data)"
|
||||||
[formControl]="control"
|
[formControl]="control"
|
||||||
></cc-enum-field>
|
></cc-enum-field>
|
||||||
<cc-typedef-form
|
<cc-typedef-form
|
||||||
*ngSwitchCase="'typedef'"
|
*ngSwitchCase="'typedef'"
|
||||||
[data]="data"
|
[data]="$any(data)"
|
||||||
[extensions]="extensions"
|
[extensions]="extensions"
|
||||||
[formControl]="control"
|
[formControl]="control"
|
||||||
></cc-typedef-form>
|
></cc-typedef-form>
|
||||||
|
@ -16,4 +16,9 @@ $offset: 24px;
|
|||||||
min-height: 48px;
|
min-height: 48px;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::ng-deep & > *:last-child {
|
||||||
|
min-height: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import { CardComponent } from '../sidenav-info/components/card/card.component';
|
|||||||
import { DomainThriftViewerComponent } from '../thrift-api-crud';
|
import { DomainThriftViewerComponent } from '../thrift-api-crud';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'cc-contract-card',
|
selector: 'cc-shop-contract-card',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, CardComponent, DomainThriftViewerComponent],
|
imports: [CommonModule, CardComponent, DomainThriftViewerComponent],
|
||||||
templateUrl: './shop-contract-card.component.html',
|
templateUrl: './shop-contract-card.component.html',
|
||||||
|
@ -18,6 +18,7 @@ import {
|
|||||||
Option,
|
Option,
|
||||||
NotifyLogService,
|
NotifyLogService,
|
||||||
progressTo,
|
progressTo,
|
||||||
|
SelectFieldComponent,
|
||||||
} from '@vality/ng-core';
|
} from '@vality/ng-core';
|
||||||
import {
|
import {
|
||||||
BehaviorSubject,
|
BehaviorSubject,
|
||||||
@ -47,8 +48,8 @@ export class ShopFieldComponent
|
|||||||
{
|
{
|
||||||
@Input() label: string;
|
@Input() label: string;
|
||||||
@Input({ transform: booleanAttribute }) required: boolean;
|
@Input({ transform: booleanAttribute }) required: boolean;
|
||||||
@Input() size?: string;
|
@Input() size?: SelectFieldComponent['size'];
|
||||||
@Input() appearance?: string;
|
@Input() appearance?: SelectFieldComponent['appearance'];
|
||||||
@Input() hint?: string;
|
@Input() hint?: string;
|
||||||
@Input({ transform: booleanAttribute }) multiple = false;
|
@Input({ transform: booleanAttribute }) multiple = false;
|
||||||
partyId = input<PartyID>();
|
partyId = input<PartyID>();
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
<v-table
|
<v-table2
|
||||||
[(sort)]="sort"
|
[(sort)]="sort"
|
||||||
[columns]="columns$ | async"
|
[columns]="columns"
|
||||||
[data]="shops()"
|
[data]="shops()"
|
||||||
[externalFilter]="filterChange.observed"
|
[externalFilter]="filterChange.observed"
|
||||||
[progress]="progress"
|
[progress]="progress"
|
||||||
[size]="100"
|
|
||||||
name="shops"
|
name="shops"
|
||||||
noActions
|
|
||||||
sortOnFront
|
|
||||||
standaloneFilter
|
standaloneFilter
|
||||||
(filterChange)="filterChange.emit($event)"
|
(filterChange)="filterChange.emit($event)"
|
||||||
(update)="update.emit()"
|
(update)="update.emit()"
|
||||||
></v-table>
|
></v-table2>
|
||||||
|
@ -5,8 +5,8 @@ import {
|
|||||||
EventEmitter,
|
EventEmitter,
|
||||||
Input,
|
Input,
|
||||||
booleanAttribute,
|
booleanAttribute,
|
||||||
OnChanges,
|
|
||||||
input,
|
input,
|
||||||
|
Injector,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { toObservable } from '@angular/core/rxjs-interop';
|
import { toObservable } from '@angular/core/rxjs-interop';
|
||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card';
|
||||||
@ -16,18 +16,17 @@ import { Shop, Party, PartyID, RoutingRulesetRef } from '@vality/domain-proto/do
|
|||||||
import {
|
import {
|
||||||
InputFieldModule,
|
InputFieldModule,
|
||||||
TableModule,
|
TableModule,
|
||||||
Column,
|
|
||||||
createOperationColumn,
|
|
||||||
DialogService,
|
DialogService,
|
||||||
NotifyLogService,
|
NotifyLogService,
|
||||||
ConfirmDialogComponent,
|
ConfirmDialogComponent,
|
||||||
DialogResponseStatus,
|
DialogResponseStatus,
|
||||||
ComponentChanges,
|
Column2,
|
||||||
|
createMenuColumn,
|
||||||
} from '@vality/ng-core';
|
} from '@vality/ng-core';
|
||||||
import { getUnionKey } from '@vality/ng-thrift';
|
import { getUnionKey } from '@vality/ng-thrift';
|
||||||
import isNil from 'lodash-es/isNil';
|
import { isNil } from 'lodash-es';
|
||||||
import startCase from 'lodash-es/startCase';
|
import startCase from 'lodash-es/startCase';
|
||||||
import { map, switchMap, Subject, defer, combineLatest, of } from 'rxjs';
|
import { map, switchMap, combineLatest, of } from 'rxjs';
|
||||||
import { filter, shareReplay, startWith, take, first } from 'rxjs/operators';
|
import { filter, shareReplay, startWith, take, first } from 'rxjs/operators';
|
||||||
import { MemoizeExpiring } from 'typescript-memoize';
|
import { MemoizeExpiring } from 'typescript-memoize';
|
||||||
|
|
||||||
@ -38,6 +37,7 @@ import {
|
|||||||
DelegateWithPaymentInstitution,
|
DelegateWithPaymentInstitution,
|
||||||
} from '../../../sections/routing-rules/party-delegate-rulesets';
|
} from '../../../sections/routing-rules/party-delegate-rulesets';
|
||||||
import { RoutingRulesType } from '../../../sections/routing-rules/types/routing-rules-type';
|
import { RoutingRulesType } from '../../../sections/routing-rules/types/routing-rules-type';
|
||||||
|
import { createPartyColumn } from '../../utils/table2';
|
||||||
import { ShopCardComponent } from '../shop-card/shop-card.component';
|
import { ShopCardComponent } from '../shop-card/shop-card.component';
|
||||||
import { ShopContractCardComponent } from '../shop-contract-card/shop-contract-card.component';
|
import { ShopContractCardComponent } from '../shop-contract-card/shop-contract-card.component';
|
||||||
import { SidenavInfoService } from '../sidenav-info';
|
import { SidenavInfoService } from '../sidenav-info';
|
||||||
@ -68,172 +68,140 @@ export interface ShopParty {
|
|||||||
templateUrl: './shops-table.component.html',
|
templateUrl: './shops-table.component.html',
|
||||||
providers: [PartyDelegateRulesetsService],
|
providers: [PartyDelegateRulesetsService],
|
||||||
})
|
})
|
||||||
export class ShopsTableComponent implements OnChanges {
|
export class ShopsTableComponent {
|
||||||
shops = input<ShopParty[]>([]);
|
shops = input<ShopParty[]>([]);
|
||||||
@Input({ transform: booleanAttribute }) changed!: boolean;
|
|
||||||
@Input() progress: number | boolean = false;
|
@Input() progress: number | boolean = false;
|
||||||
@Output() update = new EventEmitter<void>();
|
@Output() update = new EventEmitter<void>();
|
||||||
@Output() filterChange = new EventEmitter<string>();
|
@Output() filterChange = new EventEmitter<string>();
|
||||||
|
|
||||||
@Input({ transform: booleanAttribute }) noSort: boolean = false;
|
noPartyColumn = input(false, { transform: booleanAttribute });
|
||||||
@Input({ transform: booleanAttribute }) noPartyColumn: boolean = false;
|
|
||||||
|
|
||||||
columns$ = combineLatest([
|
columns: Column2<ShopParty>[] = [
|
||||||
toObservable(this.shops).pipe(
|
{
|
||||||
startWith(null),
|
field: 'shop.id',
|
||||||
map((shops) =>
|
},
|
||||||
shops?.length ? Array.from(new Set(shops.map((s) => s.party.id))) : [],
|
{
|
||||||
),
|
field: 'shop.details.name',
|
||||||
switchMap((parties) =>
|
cell: (d) => ({
|
||||||
parties?.length
|
description: d.shop.details.description,
|
||||||
? combineLatest(
|
click: () => {
|
||||||
parties.map((id) =>
|
|
||||||
this.partyDelegateRulesetsService.getDelegatesWithPaymentInstitution(
|
|
||||||
RoutingRulesType.Payment,
|
|
||||||
id,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
).pipe(map((rules) => new Map(rules.map((r, idx) => [parties[idx], r]))))
|
|
||||||
: of(new Map<string, DelegateWithPaymentInstitution[]>()),
|
|
||||||
),
|
|
||||||
map((delegatesWithPaymentInstitutionByParty) => ({
|
|
||||||
delegatesWithPaymentInstitutionByParty,
|
|
||||||
rulesetIds: Array.from(
|
|
||||||
Array.from(delegatesWithPaymentInstitutionByParty.values()).reduce((acc, d) => {
|
|
||||||
d?.map((v) => v?.partyDelegate?.ruleset?.id).forEach((v) => acc.add(v));
|
|
||||||
return acc;
|
|
||||||
}, new Set<number>([])),
|
|
||||||
),
|
|
||||||
})),
|
|
||||||
),
|
|
||||||
defer(() => this.updateColumns$).pipe(startWith(null)),
|
|
||||||
]).pipe(
|
|
||||||
map(([delegatesByParty]): Column<ShopParty>[] => [
|
|
||||||
{
|
|
||||||
field: 'shop.id',
|
|
||||||
sortable: !this.noSort,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'shop.details.name',
|
|
||||||
description: 'shop.details.description',
|
|
||||||
click: (d) => {
|
|
||||||
this.sidenavInfoService.toggle(ShopCardComponent, {
|
this.sidenavInfoService.toggle(ShopCardComponent, {
|
||||||
partyId: d.party.id,
|
partyId: d.party.id,
|
||||||
id: d.shop.id,
|
id: d.shop.id,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
sortable: !this.noSort,
|
}),
|
||||||
},
|
},
|
||||||
...(this.noPartyColumn
|
createPartyColumn(
|
||||||
? []
|
(d) => ({
|
||||||
: [
|
id: d.party.id,
|
||||||
{
|
partyName: d.party.email,
|
||||||
field: 'party.email',
|
}),
|
||||||
header: 'Party',
|
|
||||||
description: 'party.id',
|
|
||||||
link: (d) => `/party/${d.party.id}`,
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
{
|
{
|
||||||
field: 'shop.contract_id',
|
hidden: toObservable(this.noPartyColumn),
|
||||||
header: 'Contract',
|
},
|
||||||
click: (d) => {
|
),
|
||||||
|
{
|
||||||
|
field: 'shop.contract_id',
|
||||||
|
header: 'Contract',
|
||||||
|
cell: (d) => ({
|
||||||
|
click: () => {
|
||||||
this.sidenavInfoService.toggle(ShopContractCardComponent, {
|
this.sidenavInfoService.toggle(ShopContractCardComponent, {
|
||||||
partyId: d.party.id,
|
partyId: d.party.id,
|
||||||
id: d.shop.id,
|
id: d.shop.id,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
{
|
},
|
||||||
field: 'terms',
|
{
|
||||||
formatter: (d) =>
|
field: 'terms',
|
||||||
this.getTerms(d.party.id, d.shop.id).pipe(
|
lazyCell: (d) =>
|
||||||
map((terms) => getDomainObjectDetails(terms).label),
|
this.getTerms(d.party.id, d.shop.id).pipe(
|
||||||
),
|
map((terms) => getDomainObjectDetails(terms)),
|
||||||
description: (d) =>
|
map((details) => ({
|
||||||
this.getTerms(d.party.id, d.shop.id).pipe(
|
value: details.label,
|
||||||
map((terms) => getDomainObjectDetails(terms).id),
|
description: details.description,
|
||||||
),
|
click: () => {
|
||||||
lazy: true,
|
this.getTerms(d.party.id, d.shop.id).subscribe((terms) => {
|
||||||
click: (d) => {
|
this.sidenavInfoService.toggle(DomainObjectCardComponent, {
|
||||||
this.getTerms(d.party.id, d.shop.id).subscribe((terms) => {
|
ref: {
|
||||||
this.sidenavInfoService.toggle(DomainObjectCardComponent, {
|
term_set_hierarchy: terms.term_set_hierarchy.ref,
|
||||||
ref: { term_set_hierarchy: terms.term_set_hierarchy.ref },
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
})),
|
||||||
{
|
),
|
||||||
field: 'shop.location.url',
|
},
|
||||||
},
|
{
|
||||||
{
|
field: 'shop.location.url',
|
||||||
field: 'shop.account.currency.symbolic_code',
|
},
|
||||||
header: 'Currency',
|
{
|
||||||
},
|
field: 'shop.account.currency.symbolic_code',
|
||||||
{
|
header: 'Currency',
|
||||||
field: 'shop.blocking',
|
},
|
||||||
type: 'tag',
|
{
|
||||||
formatter: ({ shop }) => getUnionKey(shop.blocking),
|
field: 'shop.blocking',
|
||||||
typeParameters: {
|
cell: (d) => ({
|
||||||
label: ({ shop }) => startCase(getUnionKey(shop.blocking)),
|
value: startCase(getUnionKey(d.shop.blocking)),
|
||||||
tags: {
|
color: (
|
||||||
blocked: { color: 'warn' },
|
{
|
||||||
unblocked: { color: 'success' },
|
blocked: 'warn',
|
||||||
},
|
unblocked: 'success',
|
||||||
},
|
} as const
|
||||||
},
|
)[getUnionKey(d.shop.blocking)],
|
||||||
{
|
}),
|
||||||
field: 'shop.suspension',
|
},
|
||||||
type: 'tag',
|
{
|
||||||
formatter: ({ shop }) => getUnionKey(shop.suspension),
|
field: 'shop.suspension',
|
||||||
typeParameters: {
|
cell: (d) => ({
|
||||||
label: ({ shop }) => startCase(getUnionKey(shop.suspension)),
|
value: startCase(getUnionKey(d.shop.suspension)),
|
||||||
tags: {
|
color: (
|
||||||
suspended: { color: 'warn' },
|
{
|
||||||
active: { color: 'success' },
|
suspended: 'warn',
|
||||||
},
|
active: 'success',
|
||||||
},
|
} as const
|
||||||
},
|
)[getUnionKey(d.shop.suspension)],
|
||||||
createOperationColumn<ShopParty>([
|
}),
|
||||||
...delegatesByParty.rulesetIds.map((id) => ({
|
},
|
||||||
label: `Routing rules #${id}`,
|
createMenuColumn((d) =>
|
||||||
click: ({ shop, party }) =>
|
this.getDelegatesByParty().pipe(
|
||||||
this.openRoutingRules(
|
map((delegatesByParty) => ({
|
||||||
delegatesByParty.delegatesWithPaymentInstitutionByParty
|
items: [
|
||||||
.get(party.id)
|
...delegatesByParty.rulesetIds.map((id) => {
|
||||||
.find((d) => d?.partyDelegate?.ruleset?.id === id)?.partyDelegate
|
const rulesetId =
|
||||||
?.ruleset?.id,
|
delegatesByParty.delegatesWithPaymentInstitutionByParty
|
||||||
shop.id,
|
?.get?.(d.party.id)
|
||||||
party.id,
|
?.find?.((v) => v?.partyDelegate?.ruleset?.id === id)
|
||||||
),
|
?.partyDelegate?.ruleset?.id;
|
||||||
disabled: ({ party }) =>
|
return {
|
||||||
isNil(
|
label: `Routing rules #${id}`,
|
||||||
delegatesByParty.delegatesWithPaymentInstitutionByParty
|
click: () =>
|
||||||
.get(party.id)
|
this.openRoutingRules(rulesetId, d.shop.id, d.party.id),
|
||||||
.find((d) => d?.partyDelegate?.ruleset?.id === id)?.partyDelegate
|
disabled: isNil(rulesetId),
|
||||||
?.ruleset?.id,
|
};
|
||||||
),
|
}),
|
||||||
|
{
|
||||||
|
label:
|
||||||
|
getUnionKey(d.shop.suspension) === 'suspended'
|
||||||
|
? 'Activate'
|
||||||
|
: 'Suspend',
|
||||||
|
click: () => {
|
||||||
|
this.toggleSuspension(d);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: getUnionKey(d.shop.blocking) === 'blocked' ? 'Unblock' : 'Block',
|
||||||
|
click: () => {
|
||||||
|
this.toggleBlocking(d);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
})),
|
})),
|
||||||
{
|
),
|
||||||
label: ({ shop }) =>
|
),
|
||||||
getUnionKey(shop.suspension) === 'suspended' ? 'Activate' : 'Suspend',
|
];
|
||||||
click: (d) => {
|
|
||||||
this.toggleSuspension(d);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: ({ shop }) =>
|
|
||||||
getUnionKey(shop.blocking) === 'blocked' ? 'Unblock' : 'Block',
|
|
||||||
click: (d) => {
|
|
||||||
this.toggleBlocking(d);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
]),
|
|
||||||
shareReplay({ refCount: true, bufferSize: 1 }),
|
|
||||||
);
|
|
||||||
sort: Sort = { active: 'shop.details.name', direction: 'asc' };
|
sort: Sort = { active: 'shop.details.name', direction: 'asc' };
|
||||||
private updateColumns$ = new Subject<void>();
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private sidenavInfoService: SidenavInfoService,
|
private sidenavInfoService: SidenavInfoService,
|
||||||
@ -243,17 +211,9 @@ export class ShopsTableComponent implements OnChanges {
|
|||||||
private router: Router,
|
private router: Router,
|
||||||
private partyDelegateRulesetsService: PartyDelegateRulesetsService,
|
private partyDelegateRulesetsService: PartyDelegateRulesetsService,
|
||||||
private domainStoreService: DomainStoreService,
|
private domainStoreService: DomainStoreService,
|
||||||
|
private injector: Injector,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnChanges(changes: ComponentChanges<ShopsTableComponent>) {
|
|
||||||
if (changes.noSort || changes.noPartyColumn) {
|
|
||||||
if (this.noSort) {
|
|
||||||
this.sort = { active: '', direction: '' };
|
|
||||||
}
|
|
||||||
this.updateColumns$.next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleBlocking({ party, shop }: ShopParty) {
|
toggleBlocking({ party, shop }: ShopParty) {
|
||||||
this.dialogService
|
this.dialogService
|
||||||
.open(ConfirmDialogComponent, {
|
.open(ConfirmDialogComponent, {
|
||||||
@ -369,4 +329,34 @@ export class ShopsTableComponent implements OnChanges {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getDelegatesByParty() {
|
||||||
|
return toObservable(this.shops, { injector: this.injector }).pipe(
|
||||||
|
startWith(null),
|
||||||
|
map((shops) =>
|
||||||
|
shops?.length ? Array.from(new Set(shops.map((s) => s.party.id))) : [],
|
||||||
|
),
|
||||||
|
switchMap((parties) =>
|
||||||
|
parties?.length
|
||||||
|
? combineLatest(
|
||||||
|
parties.map((id) =>
|
||||||
|
this.partyDelegateRulesetsService.getDelegatesWithPaymentInstitution(
|
||||||
|
RoutingRulesType.Payment,
|
||||||
|
id,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).pipe(map((rules) => new Map(rules.map((r, idx) => [parties[idx], r]))))
|
||||||
|
: of(new Map<string, DelegateWithPaymentInstitution[]>()),
|
||||||
|
),
|
||||||
|
map((delegatesWithPaymentInstitutionByParty) => ({
|
||||||
|
delegatesWithPaymentInstitutionByParty,
|
||||||
|
rulesetIds: Array.from(
|
||||||
|
Array.from(delegatesWithPaymentInstitutionByParty.values()).reduce((acc, d) => {
|
||||||
|
d?.map((v) => v?.partyDelegate?.ruleset?.id).forEach((v) => acc.add(v));
|
||||||
|
return acc;
|
||||||
|
}, new Set<number>([])),
|
||||||
|
),
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { Component, Input, booleanAttribute } from '@angular/core';
|
import { Component, Input, booleanAttribute } from '@angular/core';
|
||||||
import { ThriftAstMetadata } from '@vality/domain-proto';
|
import { ThriftAstMetadata } from '@vality/domain-proto';
|
||||||
import { getImportValue } from '@vality/ng-core';
|
import { getImportValue, UnionEnum } from '@vality/ng-core';
|
||||||
import { ValueType } from '@vality/thrift-ts';
|
import { ValueType } from '@vality/thrift-ts';
|
||||||
|
|
||||||
import { ThriftViewerModule, ViewerKind } from '../../../thrift-viewer';
|
import { ThriftViewerModule, ViewerKind } from '../../../thrift-viewer';
|
||||||
@ -15,7 +15,7 @@ import { DomainMetadataViewExtensionsService } from './services/domain-metadata-
|
|||||||
imports: [CommonModule, ThriftViewerModule],
|
imports: [CommonModule, ThriftViewerModule],
|
||||||
})
|
})
|
||||||
export class DomainThriftViewerComponent<T> {
|
export class DomainThriftViewerComponent<T> {
|
||||||
@Input() kind: ViewerKind = ViewerKind.Component;
|
@Input() kind: UnionEnum<ViewerKind> = ViewerKind.Component;
|
||||||
@Input() value: T;
|
@Input() value: T;
|
||||||
@Input() compared?: T;
|
@Input() compared?: T;
|
||||||
@Input() type: ValueType;
|
@Input() type: ValueType;
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
FormControlSuperclass,
|
FormControlSuperclass,
|
||||||
} from '@vality/ng-core';
|
} from '@vality/ng-core';
|
||||||
import { toJson } from '@vality/ng-thrift';
|
import { toJson } from '@vality/ng-thrift';
|
||||||
|
import { ValueType } from '@vality/thrift-ts';
|
||||||
import { merge, defer, of, Subject } from 'rxjs';
|
import { merge, defer, of, Subject } from 'rxjs';
|
||||||
import { map, filter, shareReplay } from 'rxjs/operators';
|
import { map, filter, shareReplay } from 'rxjs/operators';
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ export class ThriftEditorComponent<T> extends FormControlSuperclass<T> {
|
|||||||
|
|
||||||
@Input() metadata: ThriftAstMetadata[];
|
@Input() metadata: ThriftAstMetadata[];
|
||||||
@Input() namespace: string;
|
@Input() namespace: string;
|
||||||
@Input() type: string;
|
@Input() type: ValueType;
|
||||||
@Input() extensions: MetadataFormExtension[];
|
@Input() extensions: MetadataFormExtension[];
|
||||||
@Input({ transform: booleanAttribute }) noChangeKind = false;
|
@Input({ transform: booleanAttribute }) noChangeKind = false;
|
||||||
@Input({ transform: booleanAttribute }) noToolbar = false;
|
@Input({ transform: booleanAttribute }) noToolbar = false;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Component, Input, OnChanges, Output, EventEmitter, booleanAttribute } from '@angular/core';
|
import { Component, Input, OnChanges, Output, EventEmitter, booleanAttribute } from '@angular/core';
|
||||||
import { ThriftAstMetadata } from '@vality/domain-proto';
|
import { ThriftAstMetadata } from '@vality/domain-proto';
|
||||||
import { ComponentChanges } from '@vality/ng-core';
|
import { ComponentChanges, UnionEnum } from '@vality/ng-core';
|
||||||
import { toJson } from '@vality/ng-thrift';
|
import { toJson } from '@vality/ng-thrift';
|
||||||
import { ValueType } from '@vality/thrift-ts';
|
import { ValueType } from '@vality/thrift-ts';
|
||||||
import { DiffEditorModel } from 'ngx-monaco-editor-v2';
|
import { DiffEditorModel } from 'ngx-monaco-editor-v2';
|
||||||
@ -19,7 +19,7 @@ export enum ViewerKind {
|
|||||||
styleUrls: ['./thrift-viewer.component.scss'],
|
styleUrls: ['./thrift-viewer.component.scss'],
|
||||||
})
|
})
|
||||||
export class ThriftViewerComponent<T> implements OnChanges {
|
export class ThriftViewerComponent<T> implements OnChanges {
|
||||||
@Input() kind: ViewerKind = ViewerKind.Component;
|
@Input() kind: UnionEnum<ViewerKind> = ViewerKind.Component;
|
||||||
@Input() value: T;
|
@Input() value: T;
|
||||||
@Input() compared?: T;
|
@Input() compared?: T;
|
||||||
@Input({ transform: booleanAttribute }) progress: boolean = false;
|
@Input({ transform: booleanAttribute }) progress: boolean = false;
|
||||||
@ -62,6 +62,6 @@ export class ThriftViewerComponent<T> implements OnChanges {
|
|||||||
this.kind = ViewerKind.Editor;
|
this.kind = ViewerKind.Editor;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.changeKind.emit(this.kind);
|
this.changeKind.emit(this.kind as ViewerKind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ import {
|
|||||||
createControlProviders,
|
createControlProviders,
|
||||||
debounceTimeWithFirst,
|
debounceTimeWithFirst,
|
||||||
progressTo,
|
progressTo,
|
||||||
|
SelectFieldComponent,
|
||||||
} from '@vality/ng-core';
|
} from '@vality/ng-core';
|
||||||
import { BehaviorSubject, Observable, of, ReplaySubject, Subject, concat, forkJoin } from 'rxjs';
|
import { BehaviorSubject, Observable, of, ReplaySubject, Subject, concat, forkJoin } from 'rxjs';
|
||||||
import { catchError, map, switchMap, tap, distinctUntilChanged } from 'rxjs/operators';
|
import { catchError, map, switchMap, tap, distinctUntilChanged } from 'rxjs/operators';
|
||||||
@ -34,8 +35,8 @@ export class WalletFieldComponent
|
|||||||
{
|
{
|
||||||
@Input() label: string;
|
@Input() label: string;
|
||||||
@Input({ transform: booleanAttribute }) required: boolean;
|
@Input({ transform: booleanAttribute }) required: boolean;
|
||||||
@Input() size?: string;
|
@Input() size?: SelectFieldComponent['size'];
|
||||||
@Input() appearance?: string;
|
@Input() appearance?: SelectFieldComponent['appearance'];
|
||||||
@Input() hint?: string;
|
@Input() hint?: string;
|
||||||
@Input({ transform: booleanAttribute }) multiple = false;
|
@Input({ transform: booleanAttribute }) multiple = false;
|
||||||
|
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
import { Column, PossiblyAsync, getPossiblyAsyncObservable } from '@vality/ng-core';
|
|
||||||
import { map } from 'rxjs/operators';
|
|
||||||
|
|
||||||
import { createDomainObjectColumn } from './create-domain-object-column';
|
|
||||||
|
|
||||||
export function createProviderColumn<T extends object>(
|
|
||||||
selectTerminalId: (d: T) => PossiblyAsync<number>,
|
|
||||||
): Column<T> {
|
|
||||||
return createDomainObjectColumn('provider', (d) =>
|
|
||||||
getPossiblyAsyncObservable(selectTerminalId(d)).pipe(map((id) => ({ id }))),
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,5 +1,4 @@
|
|||||||
import { inject } from '@angular/core';
|
import { inject } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
|
||||||
import { createColumn } from '@vality/ng-core';
|
import { createColumn } from '@vality/ng-core';
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import { map, startWith } from 'rxjs/operators';
|
import { map, startWith } from 'rxjs/operators';
|
||||||
@ -16,9 +15,7 @@ export const createPartyColumn = createColumn(
|
|||||||
.pipe(map((party) => party.contact_info.registration_email));
|
.pipe(map((party) => party.contact_info.registration_email));
|
||||||
const partyCell = {
|
const partyCell = {
|
||||||
description: id,
|
description: id,
|
||||||
link: () => {
|
link: () => `/party/${id}`,
|
||||||
void inject(Router).navigate([`/party/${id}`]);
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
return partyName$.pipe(
|
return partyName$.pipe(
|
||||||
map((partyName) => ({
|
map((partyName) => ({
|
||||||
|
Loading…
Reference in New Issue
Block a user