cabloy 5.1.126 → 5.1.127

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/.cabloy-version +1 -1
  2. package/CHANGELOG.md +21 -0
  3. package/cabloy-docs/backend/error-guide.md +17 -0
  4. package/e2e/specs/a-commerce/commerce.spec.ts +135 -4
  5. package/package.json +1 -1
  6. package/vona/packages-cli/cli/package.json +1 -1
  7. package/vona/packages-cli/cli-set-api/package.json +1 -1
  8. package/vona/packages-vona/vona/package.json +1 -1
  9. package/vona/packages-vona/vona-core/package.json +1 -1
  10. package/vona/packages-vona/vona-core/src/lib/bean/resource/error/errorClass.ts +21 -4
  11. package/vona/packages-vona/vona-core/src/lib/bean/resource/error/errorObject.ts +1 -0
  12. package/vona/packages-vona/vona-core/src/lib/bean/type.ts +3 -1
  13. package/vona/packages-vona/vona-core/src/types/interface/module.ts +6 -1
  14. package/vona/packages-vona/vona-mock/package.json +1 -1
  15. package/vona/pnpm-lock.yaml +5 -5
  16. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/.metadata/index.ts +36 -1
  17. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/config/locale/en-us.ts +1 -0
  18. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/config/locale/zh-cn.ts +1 -0
  19. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/categorySelectResItem.tsx +3 -1
  20. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/categoryView.tsx +3 -1
  21. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/entity/category.tsx +21 -2
  22. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/model/category.ts +11 -1
  23. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/service/category.ts +7 -2
  24. package/vona/src/suite/a-commerce/modules/commerce-catalog/test/categoryPresentation.test.ts +218 -0
  25. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/refundResult.tsx +3 -0
  26. package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/order.ts +2 -1
  27. package/vona/src/suite/a-commerce/modules/commerce-trade/test/refundLifecycle.test.ts +111 -3
  28. package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
  29. package/vona/src/suite-vendor/a-vona/package.json +1 -1
  30. package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/schemas.ts +8 -4
  31. package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/types.ts +65 -19
  32. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/types.ts +7 -6
  33. package/zova/src/suite/cabloy-basic/modules/basic-select/src/bean/tableCell.select.tsx +12 -6
  34. package/zova/src/suite/cabloy-basic/modules/basic-select/src/component/formFieldSelect/controller.tsx +6 -3
@@ -0,0 +1,218 @@
1
+ import assert from 'node:assert';
2
+ import { describe, it } from 'node:test';
3
+ import { app } from 'vona-mock';
4
+ import {
5
+ DtoCategoryCreate,
6
+ DtoCategorySelectResItem,
7
+ DtoCategoryUpdate,
8
+ DtoCategoryView,
9
+ } from 'vona-module-commerce-catalog';
10
+
11
+ function findComponent(apiJson: any, predicate: (properties: any) => boolean) {
12
+ return Object.values(apiJson.components!.schemas as any).find(item => {
13
+ return predicate((item as any).properties);
14
+ }) as any;
15
+ }
16
+
17
+ function getEntryForm(component: any) {
18
+ const pageEntry = component?.rest?.blocks?.[0];
19
+ const formBlock = pageEntry?.options?.blocks?.[0];
20
+ const toolbarBlock = pageEntry?.options?.blocks?.[1];
21
+ assert.equal(pageEntry?.render, 'basic-pageentry:blockPageEntry');
22
+ assert.equal(formBlock?.render, 'basic-pageentry:blockForm');
23
+ assert.equal(toolbarBlock?.render, 'basic-pageentry:blockToolbarRow');
24
+ return toolbarBlock;
25
+ }
26
+
27
+ describe('categoryPresentation.test.ts', () => {
28
+ it('action:category:presentationMetadata', async () => {
29
+ await app.bean.executor.mockCtx(async () => {
30
+ const createJson = await app.bean.openapi.generateJsonOfClass(DtoCategoryCreate);
31
+ const createComponent = findComponent(createJson, properties => {
32
+ return (
33
+ properties?.name &&
34
+ properties?.parentId &&
35
+ properties?.published &&
36
+ properties?.description
37
+ );
38
+ });
39
+ const createProperties = createComponent.properties;
40
+ assert.deepEqual(Object.keys(createProperties).sort(), [
41
+ 'description',
42
+ 'name',
43
+ 'parentId',
44
+ 'published',
45
+ ]);
46
+ assert.equal(
47
+ createProperties.parentId.rest.form.render,
48
+ 'basic-resource:formFieldResourcePicker',
49
+ );
50
+ assert.deepEqual(createProperties.parentId.rest.form.options, {
51
+ resource: 'commerce-catalog:category',
52
+ relationName: 'parent',
53
+ });
54
+ assert.equal(createProperties.published.rest.form.render, 'basic-select:formFieldSelect');
55
+ assert.deepEqual(
56
+ createProperties.published.rest.form.options.items.map((item: any) => item.value),
57
+ [false, true],
58
+ );
59
+ assert.ok(
60
+ createProperties.published.rest.form.options.items.every(
61
+ (item: any) => item.title?.toJSON && item.title?.toString,
62
+ ),
63
+ );
64
+ const createToolbar = getEntryForm(createComponent);
65
+ assert.deepEqual(
66
+ createToolbar.options.actions.map((action: any) => action.render),
67
+ ['basic-form:actionSubmit', 'basic-form:actionBack'],
68
+ );
69
+
70
+ const updateJson = await app.bean.openapi.generateJsonOfClass(DtoCategoryUpdate);
71
+ const updateComponent = findComponent(updateJson, properties => {
72
+ return (
73
+ properties?.name &&
74
+ properties?.parentId &&
75
+ properties?.published &&
76
+ properties?.description
77
+ );
78
+ });
79
+ assert.deepEqual(Object.keys(updateComponent.properties).sort(), [
80
+ 'description',
81
+ 'name',
82
+ 'parentId',
83
+ 'published',
84
+ ]);
85
+ assert.equal(
86
+ updateComponent.properties.parentId.rest.form.render,
87
+ 'basic-resource:formFieldResourcePicker',
88
+ );
89
+ assert.equal(
90
+ updateComponent.properties.published.rest.form.render,
91
+ 'basic-select:formFieldSelect',
92
+ );
93
+
94
+ const viewJson = await app.bean.openapi.generateJsonOfClass(DtoCategoryView);
95
+ const viewComponent = findComponent(viewJson, properties => {
96
+ return (
97
+ properties?.id && properties?.parentId && properties?.parent && properties?.published
98
+ );
99
+ });
100
+ assert.deepEqual(Object.keys(viewComponent.properties.parent.properties).sort(), [
101
+ 'id',
102
+ 'name',
103
+ ]);
104
+ assert.equal(viewComponent.properties.iid.rest.visible, false);
105
+ assert.equal(viewComponent.properties.deleted.rest.visible, false);
106
+ assert.equal(
107
+ viewComponent.properties.parentId.rest.form.render,
108
+ 'basic-resource:formFieldResourcePicker',
109
+ );
110
+ assert.equal(
111
+ viewComponent.properties.published.rest.form.render,
112
+ 'basic-select:formFieldSelect',
113
+ );
114
+ const viewToolbar = getEntryForm(viewComponent);
115
+ assert.deepEqual(
116
+ viewToolbar.options.actions.map((action: any) => action.render),
117
+ ['basic-form:actionBack'],
118
+ );
119
+
120
+ const listJson = await app.bean.openapi.generateJsonOfClass(DtoCategorySelectResItem);
121
+ const listComponent = findComponent(listJson, properties => properties?._operationsRow);
122
+ const listProperties = listComponent.properties;
123
+ assert.deepEqual(Object.keys(listProperties.parent.properties).sort(), ['id', 'name']);
124
+ assert.equal(listProperties.parentId.rest.table.render, 'basic-resource:resourcePicker');
125
+ assert.deepEqual(listProperties.parentId.rest.table.columnProps, {
126
+ resource: 'commerce-catalog:category',
127
+ relationName: 'parent',
128
+ });
129
+ assert.equal(listProperties.published.rest.table.render, 'basic-select:select');
130
+ assert.deepEqual(
131
+ listProperties.published.rest.table.columnProps.items.map((item: any) => item.value),
132
+ [false, true],
133
+ );
134
+ assert.deepEqual(
135
+ listProperties._operationsRow.rest.table.columnProps.actions.map(
136
+ (action: any) => action.render,
137
+ ),
138
+ ['basic-table:actionUpdate', 'basic-table:actionDelete'],
139
+ );
140
+
141
+ const filterBlock = listComponent.rest.blocks[0].options.blocks[0];
142
+ const filterLayout = filterBlock.options.blocks[0].options.formLayout;
143
+ const section = filterLayout.children[0];
144
+ assert.equal(section.type, 'section');
145
+ assert.equal(section.layout, 'flow');
146
+ assert.deepEqual(
147
+ section.children.slice(0, 2).map((field: any) => field.name),
148
+ ['name', 'createdAt'],
149
+ );
150
+ assert.equal(section.children[2].block.render, 'basic-page:blockFilterActions');
151
+ });
152
+ });
153
+
154
+ it('action:category:parentProjection', async () => {
155
+ await app.bean.executor.mockCtx(async () => {
156
+ const suffix = `${Date.now()}`;
157
+ let parentId: number | string | undefined;
158
+ let childId: number | string | undefined;
159
+ await app.bean.passport.signinMock();
160
+ try {
161
+ parentId = await app.bean.executor.performAction('post', '/commerce/catalog/category', {
162
+ body: { name: `presentation-parent-${suffix}`, published: false },
163
+ });
164
+ childId = await app.bean.executor.performAction('post', '/commerce/catalog/category', {
165
+ body: {
166
+ name: `presentation-child-${suffix}`,
167
+ parentId,
168
+ published: true,
169
+ },
170
+ });
171
+
172
+ const view: any = await app.bean.executor.performAction(
173
+ 'get',
174
+ '/commerce/catalog/category/:id',
175
+ { params: { id: childId } },
176
+ );
177
+ assert.equal(String(view.parentId), String(parentId));
178
+ assert.deepEqual(view.parent, { id: parentId, name: `presentation-parent-${suffix}` });
179
+ assert.equal(view.published, true);
180
+
181
+ const select: any = await app.bean.executor.performAction(
182
+ 'get',
183
+ '/commerce/catalog/category',
184
+ );
185
+ const root = select.list.find((item: any) => String(item.id) === String(parentId));
186
+ const child = select.list.find((item: any) => String(item.id) === String(childId));
187
+ assert.equal(root.parent, undefined);
188
+ assert.equal(root.published, false);
189
+ assert.equal(String(child.parentId), String(parentId));
190
+ assert.deepEqual(child.parent, { id: parentId, name: `presentation-parent-${suffix}` });
191
+ assert.equal(child.published, true);
192
+
193
+ await assert.rejects(
194
+ app.bean.executor.performAction('patch', '/commerce/catalog/category/:id', {
195
+ params: { id: childId },
196
+ body: {
197
+ name: `presentation-child-${suffix}`,
198
+ parentId: childId,
199
+ published: true,
200
+ },
201
+ }),
202
+ );
203
+ } finally {
204
+ if (childId) {
205
+ await app.bean.executor.performAction('delete', '/commerce/catalog/category/:id', {
206
+ params: { id: childId },
207
+ });
208
+ }
209
+ if (parentId) {
210
+ await app.bean.executor.performAction('delete', '/commerce/catalog/category/:id', {
211
+ params: { id: parentId },
212
+ });
213
+ }
214
+ await app.bean.passport.signout();
215
+ }
216
+ });
217
+ });
218
+ });
@@ -18,6 +18,9 @@ export class DtoRefundResult {
18
18
  @Api.field(v.optional(), v.tableIdentity())
19
19
  refundAttemptId?: TableIdentity;
20
20
 
21
+ @Api.field(v.optional(), v.tableIdentity())
22
+ refundOperationId?: TableIdentity;
23
+
21
24
  @Api.field(z.enum(['paid', 'refund_requested', 'refund_approved', 'refund_rejected', 'refunded']))
22
25
  orderState: 'paid' | 'refund_requested' | 'refund_approved' | 'refund_rejected' | 'refunded';
23
26
 
@@ -1157,7 +1157,7 @@ export class ServiceOrder extends BeanBase {
1157
1157
  private _refundResult(
1158
1158
  order: Pick<EntityOrder, 'id' | 'state' | 'currency'>,
1159
1159
  refundRequest: Pick<EntityRefundRequest, 'id' | 'state' | 'amountCents'>,
1160
- refundAttempt?: Pick<EntityRefundAttempt, 'id' | 'state'>,
1160
+ refundAttempt?: Pick<EntityRefundAttempt, 'id' | 'state' | 'refundOperationId'>,
1161
1161
  ): DtoRefundResult {
1162
1162
  if (
1163
1163
  order.state !== 'paid' &&
@@ -1172,6 +1172,7 @@ export class ServiceOrder extends BeanBase {
1172
1172
  orderId: order.id,
1173
1173
  refundRequestId: refundRequest.id,
1174
1174
  refundAttemptId: refundAttempt?.id,
1175
+ refundOperationId: refundAttempt?.refundOperationId,
1175
1176
  orderState: order.state,
1176
1177
  refundState: refundRequest.state,
1177
1178
  refundAttemptState: refundAttempt?.state,
@@ -16,6 +16,7 @@ interface IFixture {
16
16
  customerName?: string;
17
17
  orderId?: number;
18
18
  paymentAttemptId?: number;
19
+ paymentSessionId?: number;
19
20
  }
20
21
 
21
22
  async function cleanup(fixture: IFixture) {
@@ -24,6 +25,21 @@ async function cleanup(fixture: IFixture) {
24
25
  const promotion = app.scope('commerce-promotion');
25
26
  const catalog = app.scope('commerce-catalog');
26
27
  const member = app.scope('commerce-member');
28
+ const pay = app.scope('a-pay');
29
+ if (fixture.paymentSessionId !== undefined) {
30
+ const refundOperations = await pay.model.refundOperation.select({
31
+ where: { paymentSessionId: fixture.paymentSessionId },
32
+ });
33
+ for (const refundOperation of refundOperations) {
34
+ await pay.model.providerOperation.delete({ refundOperationId: refundOperation.id });
35
+ await pay.model.outboxEvent.delete({ refundOperationId: refundOperation.id });
36
+ await pay.model.webhookInbox.delete({ refundOperationId: refundOperation.id });
37
+ await pay.model.refundOperation.delete({ id: refundOperation.id });
38
+ }
39
+ await pay.model.outboxEvent.delete({ paymentSessionId: fixture.paymentSessionId });
40
+ await pay.model.webhookInbox.delete({ paymentSessionId: fixture.paymentSessionId });
41
+ await pay.model.providerOperation.delete({ paymentSessionId: fixture.paymentSessionId });
42
+ }
27
43
  if (fixture.orderId !== undefined) {
28
44
  const requests = await payment.model.refundRequest.select({
29
45
  where: { orderId: fixture.orderId },
@@ -39,6 +55,8 @@ async function cleanup(fixture: IFixture) {
39
55
  await payment.model.paymentAudit.delete({ paymentAttemptId: fixture.paymentAttemptId });
40
56
  await payment.model.paymentAttempt.delete({ id: fixture.paymentAttemptId });
41
57
  }
58
+ if (fixture.paymentSessionId !== undefined)
59
+ await pay.model.paymentSession.delete({ id: fixture.paymentSessionId });
42
60
  if (fixture.orderId !== undefined)
43
61
  await trade.model.orderAudit.delete({ orderId: fixture.orderId });
44
62
  if (fixture.skuId !== undefined) await trade.model.stockAudit.delete({ skuId: fixture.skuId });
@@ -152,10 +170,17 @@ async function createPaidOrder(suffix: string): Promise<IFixture> {
152
170
  });
153
171
  fixture.orderId = checkout.orderId as number;
154
172
  fixture.paymentAttemptId = checkout.paymentAttemptId as number;
155
- await app.scope('commerce-trade').service.order.applyPaymentOutcome(fixture.paymentAttemptId, {
156
- outcome: 'succeeded',
157
- idempotencyKey: `refund-payment-${suffix}`,
173
+ fixture.paymentSessionId = checkout.paymentSessionId as number;
174
+ const pay = app.scope('a-pay');
175
+ await pay.service.paymentSession.start(fixture.paymentSessionId);
176
+ await app
177
+ .scope('pay-mock')
178
+ .service.payMock.completePaymentSession(fixture.paymentSessionId, 'succeeded');
179
+ const outbox = await pay.model.outboxEvent.get({
180
+ paymentSessionId: fixture.paymentSessionId,
181
+ eventType: 'payment.outcome.v1',
158
182
  });
183
+ await pay.queue.outboxDispatch.pushAsync({ outboxEventId: outbox!.id });
159
184
  return fixture;
160
185
  }
161
186
 
@@ -310,6 +335,89 @@ describe('refundLifecycle.test.ts', { concurrency: false, sequential: true }, ()
310
335
  });
311
336
  });
312
337
 
338
+ it('settles an executed mock-provider refund through the durable outbox', async () => {
339
+ await app.bean.executor.mockCtx(async () => {
340
+ const fixture: IFixture = {};
341
+ try {
342
+ Object.assign(fixture, await createPaidOrder(randomUUID().slice(0, 12)));
343
+ const order = app.scope('commerce-trade').service.order;
344
+ await order.requestRefund(fixture.orderId!, {
345
+ reason: 'provider-backed refund',
346
+ idempotencyKey: 'provider-backed-request-1',
347
+ });
348
+ await app.bean.passport.signout();
349
+ await app.bean.passport.signinMock();
350
+ await order.approveRefund(fixture.orderId!, {
351
+ reason: 'provider-backed approval',
352
+ idempotencyKey: 'provider-backed-approve-1',
353
+ });
354
+ const executed = await order.executeRefund(fixture.orderId!);
355
+ assert.ok(executed.refundAttemptId);
356
+ assert.ok(executed.refundOperationId);
357
+ assert.deepEqual(
358
+ [executed.orderState, executed.refundState, executed.refundAttemptState],
359
+ ['refund_approved', 'approved', 'created'],
360
+ );
361
+ const pay = app.scope('a-pay');
362
+ const refundOperation = await pay.model.refundOperation.getById(executed.refundOperationId);
363
+ const refundAttempt = await app
364
+ .scope('commerce-payment')
365
+ .model.refundAttempt.getById(executed.refundAttemptId);
366
+ assert.equal(String(refundAttempt?.refundOperationId), String(executed.refundOperationId));
367
+ assert.equal(refundOperation?.state, 'pending');
368
+ const receipt = await app
369
+ .scope('pay-mock')
370
+ .service.payMock.completeRefundOperation(executed.refundOperationId, 'succeeded');
371
+ assert.deepEqual(receipt, {
372
+ refundOperationId: executed.refundOperationId,
373
+ accepted: true,
374
+ });
375
+ const outbox = await pay.model.outboxEvent.get({
376
+ refundOperationId: executed.refundOperationId,
377
+ eventType: 'refund.outcome.v1',
378
+ });
379
+ assert.ok(outbox);
380
+ await pay.queue.outboxDispatch.pushAsync({ outboxEventId: outbox.id });
381
+ await pay.queue.outboxDispatch.pushAsync({ outboxEventId: outbox.id });
382
+ const [
383
+ dispatched,
384
+ settledOrder,
385
+ settledRequest,
386
+ settledAttempt,
387
+ line,
388
+ balance,
389
+ grant,
390
+ audits,
391
+ ] = await Promise.all([
392
+ pay.model.outboxEvent.getById(outbox.id),
393
+ app.scope('commerce-trade').model.order.getById(fixture.orderId!),
394
+ app.scope('commerce-payment').model.refundRequest.getById(executed.refundRequestId),
395
+ app.scope('commerce-payment').model.refundAttempt.getById(executed.refundAttemptId),
396
+ app.scope('commerce-trade').model.orderLine.get({ orderId: fixture.orderId }),
397
+ app.scope('commerce-trade').model.stockBalance.getById(fixture.balanceId!),
398
+ app.scope('commerce-promotion').model.couponGrant.getById(fixture.grantId!),
399
+ app
400
+ .scope('commerce-payment')
401
+ .model.refundAudit.select({ where: { orderId: fixture.orderId } }),
402
+ ]);
403
+ const reservation = await app
404
+ .scope('commerce-trade')
405
+ .model.stockReservation.get({ orderLineId: line?.id });
406
+ assert.deepEqual([dispatched?.state, dispatched?.attemptCount], ['dispatched', 1]);
407
+ assert.deepEqual(
408
+ [settledOrder?.state, settledRequest?.state, settledAttempt?.state, reservation?.state],
409
+ ['refunded', 'refunded', 'succeeded', 'restored'],
410
+ );
411
+ assert.deepEqual([balance?.onHand, balance?.reserved, balance?.available], [1, 0, 1]);
412
+ assert.equal(grant?.state, 'redeemed');
413
+ assert.equal(audits.filter(audit => audit.toRefundState === 'refunded').length, 1);
414
+ } finally {
415
+ await app.bean.passport.signout();
416
+ await cleanup(fixture);
417
+ }
418
+ });
419
+ });
420
+
313
421
  it('preserves rejected and failed cycles while permitting a fresh request', async () => {
314
422
  await app.bean.executor.mockCtx(async () => {
315
423
  const fixture: IFixture = {};
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-module-a-core",
3
- "version": "5.1.47",
3
+ "version": "5.1.48",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "",
6
6
  "keywords": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-suite-a-vona",
3
- "version": "5.1.76",
3
+ "version": "5.1.77",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "",
6
6
  "author": "",
@@ -165,10 +165,6 @@ export type ApiSchemaCommerceTradeDtoRefundReview =
165
165
  components['schemas']['commerce-trade.dto.refundReview'];
166
166
  export type ApiSchemaCommerceTradeDtoRefundReviewPartial =
167
167
  Partial<ApiSchemaCommerceTradeDtoRefundReview>;
168
- export type ApiSchemaCommerceTradeDtoRefundOutcomeCreate =
169
- components['schemas']['commerce-trade.dto.refundOutcomeCreate'];
170
- export type ApiSchemaCommerceTradeDtoRefundOutcomeCreatePartial =
171
- Partial<ApiSchemaCommerceTradeDtoRefundOutcomeCreate>;
172
168
  export type ApiSchemaCommerceTradeDtoShipmentView =
173
169
  components['schemas']['commerce-trade.dto.shipmentView'];
174
170
  export type ApiSchemaCommerceTradeDtoShipmentViewPartial =
@@ -461,6 +457,14 @@ export type ApiSchemaPayMockDtoMockPaymentComplete =
461
457
  components['schemas']['pay-mock.dto.mockPaymentComplete'];
462
458
  export type ApiSchemaPayMockDtoMockPaymentCompletePartial =
463
459
  Partial<ApiSchemaPayMockDtoMockPaymentComplete>;
460
+ export type ApiSchemaPayMockDtoMockRefundReceipt =
461
+ components['schemas']['pay-mock.dto.mockRefundReceipt'];
462
+ export type ApiSchemaPayMockDtoMockRefundReceiptPartial =
463
+ Partial<ApiSchemaPayMockDtoMockRefundReceipt>;
464
+ export type ApiSchemaPayMockDtoMockRefundComplete =
465
+ components['schemas']['pay-mock.dto.mockRefundComplete'];
466
+ export type ApiSchemaPayMockDtoMockRefundCompletePartial =
467
+ Partial<ApiSchemaPayMockDtoMockRefundComplete>;
464
468
  export type ApiSchemaAPaypalEntityPaypalRecord =
465
469
  components['schemas']['a-paypal.entity.paypalRecord'];
466
470
  export type ApiSchemaAPaypalEntityPaypalRecordPartial = Partial<ApiSchemaAPaypalEntityPaypalRecord>;
@@ -623,7 +623,7 @@ export interface paths {
623
623
  patch?: never;
624
624
  trace?: never;
625
625
  };
626
- '/api/commerce/trade/order/{id}/refundOutcome': {
626
+ '/api/commerce/trade/order/{id}/executeRefund': {
627
627
  parameters: {
628
628
  query?: never;
629
629
  header?: never;
@@ -632,7 +632,7 @@ export interface paths {
632
632
  };
633
633
  get?: never;
634
634
  put?: never;
635
- post: operations['CommerceTradeOrder_refundOutcome'];
635
+ post: operations['CommerceTradeOrder_executeRefund'];
636
636
  delete?: never;
637
637
  options?: never;
638
638
  head?: never;
@@ -1264,6 +1264,22 @@ export interface paths {
1264
1264
  patch?: never;
1265
1265
  trace?: never;
1266
1266
  };
1267
+ '/api/pay/mock/payment-session/refund-operation/{id}/complete': {
1268
+ parameters: {
1269
+ query?: never;
1270
+ header?: never;
1271
+ path?: never;
1272
+ cookie?: never;
1273
+ };
1274
+ get?: never;
1275
+ put?: never;
1276
+ post: operations['PayMockPayment_completeRefund'];
1277
+ delete?: never;
1278
+ options?: never;
1279
+ head?: never;
1280
+ patch?: never;
1281
+ trace?: never;
1282
+ };
1267
1283
  '/api/paypal/getRecord/{recordId}': {
1268
1284
  parameters: {
1269
1285
  query?: never;
@@ -2446,9 +2462,9 @@ export interface components {
2446
2462
  * @enum {string}
2447
2463
  */
2448
2464
  currency: 'USD';
2449
- /** @description Fixed Discount (Cents) */
2465
+ /** @description Fixed Discount */
2450
2466
  discountCents: number;
2451
- /** @description Minimum Spend (Cents) */
2467
+ /** @description Minimum Spend */
2452
2468
  minSpendCents: number;
2453
2469
  /**
2454
2470
  * Format: date-time
@@ -2511,9 +2527,9 @@ export interface components {
2511
2527
  * @enum {string}
2512
2528
  */
2513
2529
  currency: 'USD';
2514
- /** @description Fixed Discount (Cents) */
2530
+ /** @description Fixed Discount */
2515
2531
  discountCents: number;
2516
- /** @description Minimum Spend (Cents) */
2532
+ /** @description Minimum Spend */
2517
2533
  minSpendCents: number;
2518
2534
  /**
2519
2535
  * Format: date-time
@@ -2576,9 +2592,9 @@ export interface components {
2576
2592
  * @enum {string}
2577
2593
  */
2578
2594
  currency: 'USD';
2579
- /** @description Fixed Discount (Cents) */
2595
+ /** @description Fixed Discount */
2580
2596
  discountCents: number;
2581
- /** @description Minimum Spend (Cents) */
2597
+ /** @description Minimum Spend */
2582
2598
  minSpendCents: number;
2583
2599
  /**
2584
2600
  * Format: date-time
@@ -2761,6 +2777,7 @@ export interface components {
2761
2777
  orderId: number | string;
2762
2778
  refundRequestId: number | string;
2763
2779
  refundAttemptId?: number | string | undefined;
2780
+ refundOperationId?: number | string | undefined;
2764
2781
  /** @enum {string} */
2765
2782
  orderState: 'paid' | 'refund_requested' | 'refund_approved' | 'refund_rejected' | 'refunded';
2766
2783
  /** @enum {string} */
@@ -2779,11 +2796,6 @@ export interface components {
2779
2796
  reason: string;
2780
2797
  idempotencyKey: string;
2781
2798
  };
2782
- 'commerce-trade.dto.refundOutcomeCreate': {
2783
- /** @enum {string} */
2784
- outcome: 'succeeded' | 'failed';
2785
- idempotencyKey: string;
2786
- };
2787
2799
  'commerce-trade.dto.shipmentView': {
2788
2800
  /** @description ID */
2789
2801
  id: number | string;
@@ -4483,6 +4495,14 @@ export interface components {
4483
4495
  /** @enum {string} */
4484
4496
  outcome: 'succeeded' | 'failed' | 'cancelled';
4485
4497
  };
4498
+ 'pay-mock.dto.mockRefundReceipt': {
4499
+ refundOperationId: number | string;
4500
+ accepted: boolean;
4501
+ };
4502
+ 'pay-mock.dto.mockRefundComplete': {
4503
+ /** @enum {string} */
4504
+ outcome: 'succeeded' | 'failed' | 'cancelled';
4505
+ };
4486
4506
  'a-paypal.entity.paypalRecord': {
4487
4507
  /**
4488
4508
  * Format: date-time
@@ -6273,7 +6293,7 @@ export interface operations {
6273
6293
  };
6274
6294
  authToken: true;
6275
6295
  };
6276
- CommerceTradeOrder_refundOutcome: {
6296
+ CommerceTradeOrder_executeRefund: {
6277
6297
  parameters: {
6278
6298
  query?: never;
6279
6299
  header?: never;
@@ -6282,11 +6302,7 @@ export interface operations {
6282
6302
  };
6283
6303
  cookie?: never;
6284
6304
  };
6285
- requestBody: {
6286
- content: {
6287
- 'application/json': components['schemas']['commerce-trade.dto.refundOutcomeCreate'];
6288
- };
6289
- };
6305
+ requestBody?: never;
6290
6306
  responses: {
6291
6307
  200: {
6292
6308
  headers: {
@@ -7854,6 +7870,36 @@ export interface operations {
7854
7870
  };
7855
7871
  authToken: true;
7856
7872
  };
7873
+ PayMockPayment_completeRefund: {
7874
+ parameters: {
7875
+ query?: never;
7876
+ header?: never;
7877
+ path: {
7878
+ id: number | string;
7879
+ };
7880
+ cookie?: never;
7881
+ };
7882
+ requestBody: {
7883
+ content: {
7884
+ 'application/json': components['schemas']['pay-mock.dto.mockRefundComplete'];
7885
+ };
7886
+ };
7887
+ responses: {
7888
+ 200: {
7889
+ headers: {
7890
+ [name: string]: unknown;
7891
+ };
7892
+ content: {
7893
+ 'application/json': {
7894
+ code: string;
7895
+ message: string;
7896
+ data: components['schemas']['pay-mock.dto.mockRefundReceipt'];
7897
+ };
7898
+ };
7899
+ };
7900
+ };
7901
+ authToken: true;
7902
+ };
7857
7903
  Paypal_getRecord: {
7858
7904
  parameters: {
7859
7905
  query?: never;
@@ -2462,9 +2462,9 @@ export interface components {
2462
2462
  * @enum {string}
2463
2463
  */
2464
2464
  currency: 'USD';
2465
- /** @description Fixed Discount (Cents) */
2465
+ /** @description Fixed Discount */
2466
2466
  discountCents: number;
2467
- /** @description Minimum Spend (Cents) */
2467
+ /** @description Minimum Spend */
2468
2468
  minSpendCents: number;
2469
2469
  /**
2470
2470
  * Format: date-time
@@ -2527,9 +2527,9 @@ export interface components {
2527
2527
  * @enum {string}
2528
2528
  */
2529
2529
  currency: 'USD';
2530
- /** @description Fixed Discount (Cents) */
2530
+ /** @description Fixed Discount */
2531
2531
  discountCents: number;
2532
- /** @description Minimum Spend (Cents) */
2532
+ /** @description Minimum Spend */
2533
2533
  minSpendCents: number;
2534
2534
  /**
2535
2535
  * Format: date-time
@@ -2592,9 +2592,9 @@ export interface components {
2592
2592
  * @enum {string}
2593
2593
  */
2594
2594
  currency: 'USD';
2595
- /** @description Fixed Discount (Cents) */
2595
+ /** @description Fixed Discount */
2596
2596
  discountCents: number;
2597
- /** @description Minimum Spend (Cents) */
2597
+ /** @description Minimum Spend */
2598
2598
  minSpendCents: number;
2599
2599
  /**
2600
2600
  * Format: date-time
@@ -2777,6 +2777,7 @@ export interface components {
2777
2777
  orderId: number | string;
2778
2778
  refundRequestId: number | string;
2779
2779
  refundAttemptId?: number | string | undefined;
2780
+ refundOperationId?: number | string | undefined;
2780
2781
  /** @enum {string} */
2781
2782
  orderState: 'paid' | 'refund_requested' | 'refund_approved' | 'refund_rejected' | 'refunded';
2782
2783
  /** @enum {string} */
@@ -26,13 +26,19 @@ export class TableCellSelect extends BeanBase implements ITableCellRender {
26
26
  render(
27
27
  options: ITableCellOptionsSelect,
28
28
  _renderContext: IJsxRenderContextTableCell,
29
- next: NextTableCellRender,
29
+ _next: NextTableCellRender,
30
30
  ) {
31
- const value = next();
32
- const item = options.items?.find(
33
- item => String(item[String(options.itemValue)]) === String(value),
34
- );
35
- const value2 = item?.[String(options.itemTitle)];
31
+ const value = _next();
32
+ const items = options.items;
33
+ const itemValue = options.itemValue;
34
+ const itemTitle = options.itemTitle;
35
+ const item = items?.find(item => {
36
+ const itemValue2 = item[String(itemValue)];
37
+ if (String(itemValue2) === String(value)) return true;
38
+ if (typeof itemValue2 !== 'boolean') return false;
39
+ return itemValue2 ? value === 1 || value === '1' : value === 0 || value === '0';
40
+ });
41
+ const value2 = item?.[String(itemTitle)];
36
42
  if (!options.class) return value2;
37
43
  return <div class={options.class}>{value2}</div>;
38
44
  }