FIN-35: Show terms history (#362)

This commit is contained in:
Rinat Arsaev 2024-06-03 13:59:39 +05:00 committed by GitHub
parent a40b2f0a05
commit 9430f66865
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 303 additions and 183 deletions

8
package-lock.json generated
View File

@ -22,7 +22,7 @@
"@ngneat/input-mask": "6.0.0",
"@vality/deanonimus-proto": "2.0.1-2a02d87.0",
"@vality/domain-proto": "2.0.1-b04aba8.0",
"@vality/dominator-proto": "1.0.0",
"@vality/dominator-proto": "1.0.1-b9788c2.0",
"@vality/fistful-proto": "2.0.1-6600be9.0",
"@vality/machinegun-proto": "1.0.0",
"@vality/magista-proto": "2.0.2-28d11b9.0",
@ -6423,9 +6423,9 @@
"integrity": "sha512-AKD5RkqiS+31hTUaLfh7I3vgYZ2yytwxp8J1jQZ7iPWURz/m5+6Yg4YKNj8Vyyxu3yzO13FxxPUnkTh/poCDWg=="
},
"node_modules/@vality/dominator-proto": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@vality/dominator-proto/-/dominator-proto-1.0.0.tgz",
"integrity": "sha512-N7gTGnr419mwnZH3FB4kTIJUgbFoVzKUHKNIyzjjJuPiSnOEaWr/sj8cFfDdyuHUkpHb4CKXJ+QdF686UtGKGw=="
"version": "1.0.1-b9788c2.0",
"resolved": "https://registry.npmjs.org/@vality/dominator-proto/-/dominator-proto-1.0.1-b9788c2.0.tgz",
"integrity": "sha512-QeNZY154ZkOtX7vxTBEJZg9uyqhV/z1++bBDIFdn8hJ7sTx/TfCtFPD/krxX/07eA4DL4Wbugm4+33X9ADAGiQ=="
},
"node_modules/@vality/eslint-config": {
"version": "8.2.0",

View File

@ -30,7 +30,7 @@
"@ngneat/input-mask": "6.0.0",
"@vality/deanonimus-proto": "2.0.1-2a02d87.0",
"@vality/domain-proto": "2.0.1-b04aba8.0",
"@vality/dominator-proto": "1.0.0",
"@vality/dominator-proto": "1.0.1-b9788c2.0",
"@vality/fistful-proto": "2.0.1-6600be9.0",
"@vality/machinegun-proto": "1.0.0",
"@vality/magista-proto": "2.0.2-28d11b9.0",

View File

@ -83,7 +83,7 @@ export class AppComponent {
},
{
label: 'Terms',
url: '/tariffs',
url: '/terms',
services: TARIFFS_ROUTING_CONFIG.services,
},
],

View File

@ -65,7 +65,7 @@ const ROUTES: Routes = [
loadChildren: () => import('./shops').then((m) => m.ShopsModule),
},
{
path: 'tariffs',
path: 'terms',
loadChildren: () => import('./tariffs').then((m) => m.TariffsModule),
},
{

View File

@ -26,11 +26,6 @@ import {
VSelectPipe,
} from '@vality/ng-core';
import { map, shareReplay } from 'rxjs/operators';
import { getInlineDecisions } from 'src/app/sections/tariffs/utils/get-inline-decisions';
import {
DomainObjectCardComponent,
getDomainObjectDetails,
} from 'src/app/shared/components/thrift-api-crud';
import { Overwrite } from 'utility-types';
import {
@ -43,9 +38,13 @@ import {
import { CurrencyFieldComponent } from '@cc/app/shared/components/currency-field';
import { MerchantFieldModule } from '@cc/app/shared/components/merchant-field';
import { SidenavInfoService } from '@cc/app/shared/components/sidenav-info';
import { createDomainObjectColumn } from '@cc/app/shared/utils/table/create-domain-object-column';
import { DEBOUNCE_TIME_MS } from '@cc/app/tokens';
import { ShopsTermSetHistoryCardComponent } from '../shops-term-set-history-card';
import { ShopsTariffsService } from './shops-tariffs.service';
import { createShopFeesColumn } from './utils/create-shop-fees-column';
type Params = Pick<CommonSearchQueryParams, 'currencies'> &
Overwrite<
@ -53,14 +52,6 @@ type Params = Pick<CommonSearchQueryParams, 'currencies'> &
{ term_sets_ids?: TermSetHierarchyRef['id'][] }
>;
function getViewedCashFlowSelectors(d: ShopTermSet) {
return (
d.current_term_set.data.term_sets
?.map?.((t) => t?.terms?.payments?.fees)
?.filter?.(Boolean) ?? []
);
}
@Component({
selector: 'cc-shops-tariffs',
standalone: true,
@ -110,61 +101,17 @@ export class ShopsTariffsComponent implements OnInit {
(d) => d.shop_id,
),
{ field: 'currency' },
{
field: 'current_term_set',
formatter: (d) =>
getDomainObjectDetails({ term_set_hierarchy: d.current_term_set })?.label,
click: (d) =>
this.sidenavInfoService.open(DomainObjectCardComponent, {
ref: { term_set_hierarchy: d?.current_term_set?.ref },
}),
},
{
field: 'condition',
formatter: (d) => getInlineDecisions(getViewedCashFlowSelectors(d)).map((v) => v.if),
},
{
field: 'fee',
formatter: (d) =>
getInlineDecisions(
getViewedCashFlowSelectors(d),
(v) => v?.source?.merchant === 0 && v?.destination?.system === 0,
).map((v) => v.value),
},
{
field: 'rreserve',
header: 'RReserve',
formatter: (d) =>
getInlineDecisions(
getViewedCashFlowSelectors(d),
(v) => v?.source?.merchant === 0 && v?.destination?.merchant === 1,
).map((v) => v.value),
},
{
field: 'other',
formatter: (d) =>
getInlineDecisions(
getViewedCashFlowSelectors(d),
(v) =>
!(
(v?.source?.merchant === 0 && v?.destination?.system === 0) ||
(v?.source?.merchant === 0 && v?.destination?.merchant === 1)
),
).map((v) => v.value),
tooltip: (d) =>
getInlineDecisions(
getViewedCashFlowSelectors(d),
(v) =>
!(
(v?.source?.merchant === 0 && v?.destination?.system === 0) ||
(v?.source?.merchant === 0 && v?.destination?.merchant === 1)
),
).map((v) => v.description),
},
createDomainObjectColumn('term_set_hierarchy', (d) => d.current_term_set.ref, {
header: 'Term Set',
}),
...createShopFeesColumn<ShopTermSet>((d) => d?.current_term_set),
{
field: 'term_set_history',
formatter: (d) => d.term_set_history?.length,
tooltip: (d) => d.term_set_history,
formatter: (d) => d.term_set_history?.length || '',
click: (d) =>
this.sidenavInfoService.open(ShopsTermSetHistoryCardComponent, {
data: d?.term_set_history?.reverse(),
}),
},
];
active$ = getValueChanges(this.filtersForm).pipe(

View File

@ -0,0 +1,17 @@
import type { TermSetHierarchyObject } from '@vality/dominator-proto/internal/proto/domain';
import { createFeesColumns } from '../../../utils/create-fees-columns';
export function getViewedCashFlowSelectors(d: TermSetHierarchyObject) {
return d?.data?.term_sets?.map?.((t) => t?.terms?.payments?.fees)?.filter?.(Boolean) ?? [];
}
export function createShopFeesColumn<T extends object = TermSetHierarchyObject>(
fn: (d: T) => TermSetHierarchyObject = (d) => d as never,
) {
return createFeesColumns<T>(
(d) => getViewedCashFlowSelectors(fn(d)),
(v) => v?.source?.merchant === 0 && v?.destination?.system === 0,
(v) => v?.source?.merchant === 0 && v?.destination?.merchant === 1,
);
}

View File

@ -0,0 +1,2 @@
export * from './shops-term-set-history-card.component';
export * from '../../utils/create-fees-columns';

View File

@ -0,0 +1,25 @@
<cc-card [title]="'Term Sets History'">
<v-table
[cellTemplate]="{
condition: arrayColumnTemplate,
fee: arrayColumnTemplate,
rreserve: arrayColumnTemplate,
other: arrayColumnTemplate
}"
[columns]="columns"
[data]="data()"
></v-table>
<ng-template #arrayColumnTemplate let-colDef="colDef" let-rowData="rowData" let-value="value">
<ng-container *ngIf="(rowData | vSelect: colDef.tooltip : '' : [colDef]) || ' ' as tooltip">
<div
*ngFor="let item of value; let index = index"
[matTooltip]="tooltip[index]"
matTooltipPosition="right"
style="white-space: nowrap; cursor: default"
>
{{ item }}
</div>
</ng-container>
</ng-template>
</cc-card>

View File

@ -0,0 +1,31 @@
import { CommonModule } from '@angular/common';
import { Component, input } from '@angular/core';
import { MatTooltip } from '@angular/material/tooltip';
import { TableModule, type Column, VSelectPipe } from '@vality/ng-core';
import type { TermSetHistory } from '@vality/dominator-proto/internal/dominator';
import { SidenavInfoModule } from '../../../../shared/components/sidenav-info';
import { getDomainObjectDetails } from '../../../../shared/components/thrift-api-crud';
import { createShopFeesColumn } from '../shops-tariffs/utils/create-shop-fees-column';
@Component({
selector: 'cc-shops-term-set-history-card',
standalone: true,
imports: [CommonModule, SidenavInfoModule, TableModule, VSelectPipe, MatTooltip],
templateUrl: './shops-term-set-history-card.component.html',
styles: ``,
})
export class ShopsTermSetHistoryCardComponent {
data = input<TermSetHistory[]>();
columns: Column<TermSetHistory>[] = [
{ field: 'applied_at', type: 'datetime' },
{
field: 'term_set',
formatter: (d) => getDomainObjectDetails({ term_set_hierarchy: d?.term_set })?.label,
description: (d) =>
getDomainObjectDetails({ term_set_hierarchy: d?.term_set })?.description,
},
...createShopFeesColumn<TermSetHistory>((d) => d.term_set),
];
}

View File

@ -0,0 +1,28 @@
import type { TermSetHierarchyObject } from '@vality/dominator-proto/internal/proto/domain';
import { formatCashVolume } from '../../../../../shared';
import { createFeesColumns } from '../../../utils/create-fees-columns';
export function getViewedCashFlowSelectors(d: TermSetHierarchyObject) {
return (
d.data.term_sets
?.map?.((t) => t?.terms?.wallets?.withdrawals?.cash_flow)
?.filter?.(Boolean) ?? []
);
}
export function createWalletFeesColumn<T extends object = TermSetHierarchyObject>(
fn: (d: T) => TermSetHierarchyObject = (d) => d as never,
getWalletId: (d: T) => string,
) {
return createFeesColumns<T>(
(d) => getViewedCashFlowSelectors(fn(d)),
(v) => v?.source?.wallet === 1 && v?.destination?.system === 0,
undefined,
(v) =>
v?.source?.wallet === 1 &&
v?.destination?.wallet === 3 &&
formatCashVolume(v?.volume) === '100%',
getWalletId,
);
}

View File

@ -32,8 +32,15 @@
<div
*ngFor="let item of value; let index = index"
[matTooltip]="tooltip[index]"
[title]="item"
matTooltipPosition="right"
style="white-space: nowrap; cursor: default"
style="
white-space: nowrap;
cursor: default;
max-width: 50vw;
overflow: hidden;
text-overflow: ellipsis;
"
>
{{ item }}
</div>

View File

@ -29,41 +29,31 @@ import {
VSelectPipe,
} from '@vality/ng-core';
import { map, shareReplay } from 'rxjs/operators';
import { WalletsTariffsService } from 'src/app/sections/tariffs/components/wallets-tariffs/wallets-tariffs.service';
import { getInlineDecisions } from 'src/app/sections/tariffs/utils/get-inline-decisions';
import {
DomainObjectCardComponent,
getDomainObjectDetails,
} from 'src/app/shared/components/thrift-api-crud';
import { Overwrite } from 'utility-types';
import {
createContractColumn,
createPartyColumn,
PageLayoutModule,
WalletFieldModule,
createWalletColumn,
formatCashVolume,
} from '@cc/app/shared';
import { CurrencyFieldComponent } from '@cc/app/shared/components/currency-field';
import { MerchantFieldModule } from '@cc/app/shared/components/merchant-field';
import { SidenavInfoService } from '@cc/app/shared/components/sidenav-info';
import { createDomainObjectColumn } from '@cc/app/shared/utils/table/create-domain-object-column';
import { DEBOUNCE_TIME_MS } from '@cc/app/tokens';
import { WalletsTermSetHistoryCardComponent } from '../wallets-term-set-history-card';
import { createWalletFeesColumn } from './utils/create-wallet-fees-column';
import { WalletsTariffsService } from './wallets-tariffs.service';
type Params = Pick<CommonSearchQueryParams, 'currencies'> &
Overwrite<
Omit<WalletSearchQuery, 'common_search_query_params'>,
{ term_sets_ids?: TermSetHierarchyRef['id'][]; identity_ids?: IdentityProviderRef['id'][] }
>;
function getViewedCashFlowSelectors(d: WalletTermSet) {
return (
d.current_term_set.data.term_sets
?.map?.((t) => t?.terms?.wallets?.withdrawals?.cash_flow)
?.filter?.(Boolean) ?? []
);
}
@Component({
selector: 'cc-wallets-tariffs',
standalone: true,
@ -108,62 +98,24 @@ export class WalletsTariffsComponent implements OnInit {
},
),
createPartyColumn<WalletTermSet>('owner_id'),
createContractColumn<WalletTermSet>(
(d) => d.contract_id,
(d) => d.owner_id,
{ field: 'contract_id', header: 'Contract' },
{ field: 'identity_id.id', header: 'Identity' },
{ field: 'currency' },
createDomainObjectColumn('term_set_hierarchy', (d) => d.current_term_set.ref, {
header: 'Term Set',
}),
...createWalletFeesColumn<WalletTermSet>(
(d) => d.current_term_set,
(d) => d.wallet_id,
),
{ field: 'currency' },
{
field: 'current_term_set',
formatter: (d) =>
getDomainObjectDetails({ term_set_hierarchy: d.current_term_set })?.label,
click: (d) =>
this.sidenavInfoService.open(DomainObjectCardComponent, {
ref: { term_set_hierarchy: d?.current_term_set?.ref },
}),
},
{
field: 'condition',
formatter: (d) => getInlineDecisions(getViewedCashFlowSelectors(d)).map((v) => v.if),
},
{
field: 'fee',
formatter: (d) =>
getInlineDecisions(
getViewedCashFlowSelectors(d),
(v) => v?.source?.wallet === 1 && v?.destination?.system === 0,
).map((v) => v.value),
},
{
field: 'other',
formatter: (d) =>
getInlineDecisions(
getViewedCashFlowSelectors(d),
(v) =>
!(
(v?.source?.wallet === 1 && v?.destination?.system === 0) ||
(v?.source?.wallet === 1 &&
v?.destination?.wallet === 3 &&
formatCashVolume(v?.volume) === '100%')
),
).map((v) => v.value),
tooltip: (d) =>
getInlineDecisions(
getViewedCashFlowSelectors(d),
(v) =>
!(
(v?.source?.wallet === 1 && v?.destination?.system === 0) ||
(v?.source?.wallet === 1 &&
v?.destination?.wallet === 3 &&
formatCashVolume(v?.volume) === '100%')
),
).map((v) => v.description),
},
{
field: 'term_set_history',
formatter: (d) => d.term_set_history?.length,
tooltip: (d) => d.term_set_history,
formatter: (d) => d.term_set_history?.length || '',
click: (d) =>
this.sidenavInfoService.open(WalletsTermSetHistoryCardComponent, {
data: d?.term_set_history?.reverse(),
walletId: d?.wallet_id,
}),
},
];
active$ = getValueChanges(this.filtersForm).pipe(

View File

@ -0,0 +1,2 @@
export * from './wallets-term-set-history-card.component';
export * from '../../utils/create-fees-columns';

View File

@ -0,0 +1,25 @@
<cc-card [title]="'Term Sets History'">
<v-table
[cellTemplate]="{
condition: arrayColumnTemplate,
fee: arrayColumnTemplate,
rreserve: arrayColumnTemplate,
other: arrayColumnTemplate
}"
[columns]="columns"
[data]="data()"
></v-table>
<ng-template #arrayColumnTemplate let-colDef="colDef" let-rowData="rowData" let-value="value">
<ng-container *ngIf="(rowData | vSelect: colDef.tooltip : '' : [colDef]) || ' ' as tooltip">
<div
*ngFor="let item of value; let index = index"
[matTooltip]="tooltip[index]"
matTooltipPosition="right"
style="white-space: nowrap; cursor: default"
>
{{ item }}
</div>
</ng-container>
</ng-template>
</cc-card>

View File

@ -0,0 +1,35 @@
import { CommonModule } from '@angular/common';
import { Component, input } from '@angular/core';
import { MatTooltip } from '@angular/material/tooltip';
import { TableModule, type Column, VSelectPipe } from '@vality/ng-core';
import type { TermSetHistory } from '@vality/dominator-proto/internal/dominator';
import { SidenavInfoModule } from '../../../../shared/components/sidenav-info';
import { getDomainObjectDetails } from '../../../../shared/components/thrift-api-crud';
import { createWalletFeesColumn } from '../wallets-tariffs/utils/create-wallet-fees-column';
@Component({
selector: 'cc-wallets-term-set-history-card',
standalone: true,
imports: [CommonModule, SidenavInfoModule, TableModule, VSelectPipe, MatTooltip],
templateUrl: './wallets-term-set-history-card.component.html',
styles: ``,
})
export class WalletsTermSetHistoryCardComponent {
data = input<TermSetHistory[]>();
walletId = input<string>();
columns: Column<TermSetHistory>[] = [
{ field: 'applied_at', type: 'datetime' },
{
field: 'term_set',
formatter: (d) => getDomainObjectDetails({ term_set_hierarchy: d?.term_set })?.label,
description: (d) =>
getDomainObjectDetails({ term_set_hierarchy: d?.term_set })?.description,
},
...createWalletFeesColumn<TermSetHistory>(
(d) => d.term_set,
() => this.walletId(),
),
];
}

View File

@ -0,0 +1,67 @@
import type {
CashFlowSelector,
CashFlowPosting,
} from '@vality/dominator-proto/internal/proto/domain';
import type { Column } from '@vality/ng-core';
import {
getInlineDecisions,
formatLevelPredicate,
type InlineCashFlowSelector,
} from './get-inline-decisions';
export function createFeesColumns<T extends object>(
getFees: (d: T) => CashFlowSelector[],
filterFee: (v: CashFlowPosting) => boolean,
filterRreserve?: (v: CashFlowPosting) => boolean,
filterOther?: (v: CashFlowPosting) => boolean,
walletId?: (d: T) => string,
): Column<T>[] {
const filterOtherFn: (v: CashFlowPosting) => boolean = (v) =>
!(
filterFee(v) ||
(filterRreserve ? filterRreserve(v) : false) ||
(filterOther ? filterOther(v) : false)
);
const filterFn = (d: T) => (v: InlineCashFlowSelector) =>
!v?.if?.condition?.party || v?.if?.condition?.party?.definition?.wallet_is === walletId(d);
return [
{
field: 'condition',
formatter: (d) =>
getInlineDecisions(getFees(d))
.filter(filterFn(d))
.map((v) => formatLevelPredicate(v)),
},
{
field: 'fee',
formatter: (d) =>
getInlineDecisions(getFees(d), filterFee)
.filter(filterFn(d))
.map((v) => v.value),
},
...(filterRreserve
? [
{
field: 'rreserve',
header: 'RReserve',
formatter: (d) =>
getInlineDecisions(getFees(d), filterRreserve)
.filter(filterFn(d))
.map((v) => v.value),
},
]
: []),
{
field: 'other',
formatter: (d) =>
getInlineDecisions(getFees(d), filterOtherFn)
.filter(filterFn(d))
.map((v) => v.value),
tooltip: (d) =>
getInlineDecisions(getFees(d), filterOtherFn)
.filter(filterFn(d))
.map((v) => v.description),
},
];
}

View File

@ -4,12 +4,13 @@ import type {
CashFlowPosting,
CashFlowSelector,
CashFlowAccount,
Predicate,
} from '@vality/dominator-proto/internal/proto/domain';
import { formatPredicate, formatCashVolumes, compareCashVolumes } from '@cc/app/shared';
export interface InlineCashFlowSelector {
if?: string;
if?: Predicate;
value?: string;
parent?: InlineCashFlowSelector;
description?: string;
@ -55,6 +56,10 @@ function formatCashFlowAccount(acc: CashFlowAccount) {
);
}
export function formatLevelPredicate(v: InlineCashFlowSelector) {
return `${' '.repeat(v.level)}${formatPredicate(v.if) || (v.level > 0 ? '↳' : '')}`;
}
export function getInlineDecisions(
d: CashFlowSelector[],
filterValue: (v: CashFlowPosting) => boolean = Boolean,
@ -88,9 +93,7 @@ export function getInlineDecisions(
);
if (d.if_) {
const ifInlineDecision = {
if: `${' '.repeat(level)}${
formatPredicate(d.if_) || (level > 0 ? '↳' : '')
}`,
if: d.if_,
level,
};
return thenInlineDecisions.length > 1

View File

@ -1,3 +0,0 @@
<cc-card [title]="data()?.data?.name">
<cc-cash-flows-selector-table [data]="feesData()"></cc-cash-flows-selector-table>
</cc-card>

View File

@ -1,22 +0,0 @@
import { Component, computed, input } from '@angular/core';
import { TermSetHierarchyObject } from '@vality/domain-proto/internal/domain';
import { CardComponent } from '../sidenav-info/components/card/card.component';
@Component({
selector: 'cc-termsets-card',
standalone: true,
imports: [CardComponent],
templateUrl: './termsets-history-card.component.html',
styles: ``,
})
export class TermsetsHistoryCardComponent {
data = input<TermSetHierarchyObject[]>();
feesData = computed(
() =>
this.data()?.map?.(
(d) =>
d?.data?.term_sets?.map?.((t) => t?.terms?.payments?.fees)?.filter?.(Boolean),
),
);
}

View File

@ -1,6 +1,6 @@
import { inject } from '@angular/core';
import { Reference } from '@vality/domain-proto/domain';
import { Column, PossiblyAsync, getPossiblyAsyncObservable } from '@vality/ng-core';
import { PossiblyAsync, getPossiblyAsyncObservable, type ColumnObject } from '@vality/ng-core';
import startCase from 'lodash-es/startCase';
import { map, switchMap, first } from 'rxjs/operators';
import { ValuesType } from 'utility-types';
@ -15,7 +15,8 @@ import {
export function createDomainObjectColumn<T extends object>(
objectKey: keyof Reference,
selectDomainObjectRef: (d: T) => PossiblyAsync<ValuesType<Reference>>,
): Column<T> {
params: Partial<ColumnObject<T>> = {},
): ColumnObject<T> {
const domainStoreService = inject(DomainStoreService);
const sidenavInfoService = inject(SidenavInfoService);
const getObjectRef = (d: T) =>
@ -36,5 +37,6 @@ export function createDomainObjectColumn<T extends object>(
sidenavInfoService.toggle(DomainObjectCardComponent, { ref });
});
},
};
...params,
} as ColumnObject<T>;
}

View File

@ -29,9 +29,11 @@ export function formatCashVolume(d: CashVolume) {
(d?.share?.rounding_method === 1 ? ' (round .5+)' : '')
);
case 'product':
return `${getUnionKey(d.product).slice(0, -3)}(${Array.from(getUnionValue(d.product))
.sort(compareCashVolumes)
.map((c) => formatCashVolume(c))
.join(', ')})`;
return getUnionValue(d.product).size <= 1
? formatCashVolume(getUnionValue(d.product)[0])
: `${getUnionKey(d.product).slice(0, -3)}(${Array.from(getUnionValue(d.product))
.sort(compareCashVolumes)
.map((c) => formatCashVolume(c))
.join(', ')})`;
}
}

View File

@ -35,14 +35,14 @@ export function formatPredicate(predicate: Predicate, level = 0) {
return `category: #${condition.category_is.id}`;
case 'cost_in':
return `cost: ${
getUnionKey(condition.cost_in.upper) === 'inclusive' ? '[' : '('
getUnionKey(condition.cost_in.lower) === 'inclusive' ? '[' : '('
}${formatCurrency(
getUnionValue(condition.cost_in.upper)?.amount,
getUnionValue(condition.cost_in.upper)?.currency?.symbolic_code,
)}, ${formatCurrency(
getUnionValue(condition.cost_in.lower)?.amount,
getUnionValue(condition.cost_in.lower)?.currency?.symbolic_code,
)}${getUnionKey(condition.cost_in.lower) === 'inclusive' ? ']' : ')'}`;
)}, ${formatCurrency(
getUnionValue(condition.cost_in.upper)?.amount,
getUnionValue(condition.cost_in.upper)?.currency?.symbolic_code,
)}${getUnionKey(condition.cost_in.upper) === 'inclusive' ? ']' : ')'}`;
case 'cost_is_multiple_of':
return `cost_is_multiple: ${formatCurrency(
condition.cost_is_multiple_of.amount,