cabloy 5.1.112 → 5.1.114

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 (157) hide show
  1. package/.cabloy-version +1 -1
  2. package/.claude/skills/cabloy-backend-scaffold/SKILL.md +2 -0
  3. package/.claude/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +13 -0
  4. package/.github/workflows/playwright-e2e.yml +34 -2
  5. package/.github/workflows/vona-test-mysql.yml +12 -0
  6. package/.github/workflows/vona-test-pg.yml +12 -0
  7. package/CHANGELOG.md +27 -0
  8. package/CLAUDE.md +6 -0
  9. package/cabloy-docs/backend/internal-aop-guide.md +35 -0
  10. package/cabloy-docs/backend/migration-and-changes.md +13 -9
  11. package/cabloy-docs/backend/unit-testing.md +97 -1
  12. package/e2e/scripts/startE2eVona.ts +51 -13
  13. package/e2e/specs/a-commerce/commerce.spec.ts +1 -0
  14. package/e2e/specs/cabloy-basic/basic.spec.ts +12 -7
  15. package/package.json +1 -1
  16. package/vona/packages-cli/cli/package.json +1 -1
  17. package/vona/packages-cli/cli-set-api/package.json +1 -1
  18. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.bin.test.ts +6 -9
  19. package/vona/packages-cli/cli-set-api/toolsIsolate/test.ts +74 -32
  20. package/vona/packages-utils/compose/package.json +1 -1
  21. package/vona/packages-utils/compose/src/index.ts +19 -11
  22. package/vona/packages-vona/vona/package.json +1 -1
  23. package/vona/packages-vona/vona-core/package.json +1 -1
  24. package/vona/packages-vona/vona-core/src/lib/bean/beanContainer.ts +15 -3
  25. package/vona/packages-vona/vona-mock/package.json +1 -1
  26. package/vona/pnpm-lock.yaml +82 -67
  27. package/vona/src/backend/config/config/config.test.ts +1 -1
  28. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/.metadata/index.ts +8 -0
  29. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/bean/meta.version.ts +1 -0
  30. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/config/locale/en-us.ts +3 -0
  31. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/config/locale/zh-cn.ts +3 -0
  32. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/skuAttribute.tsx +17 -0
  33. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/entity/sku.tsx +10 -1
  34. package/vona/src/suite/a-commerce/modules/commerce-catalog/test/catalog.test.ts +234 -0
  35. package/vona/src/suite/a-commerce/modules/commerce-member/test/addressOwnership.test.ts +6 -1
  36. package/vona/src/suite/a-commerce/modules/commerce-payment/package.json +2 -1
  37. package/vona/src/suite/a-commerce/modules/commerce-payment/src/.metadata/index.ts +228 -0
  38. package/vona/src/suite/a-commerce/modules/commerce-payment/src/bean/meta.index.ts +15 -0
  39. package/vona/src/suite/a-commerce/modules/commerce-payment/src/bean/meta.version.ts +35 -0
  40. package/vona/src/suite/a-commerce/modules/commerce-payment/src/dto/paymentAttemptView.tsx +26 -0
  41. package/vona/src/suite/a-commerce/modules/commerce-payment/src/entity/paymentAttempt.tsx +34 -0
  42. package/vona/src/suite/a-commerce/modules/commerce-payment/src/model/paymentAttempt.ts +10 -0
  43. package/vona/src/suite/a-commerce/modules/commerce-payment/src/service/paymentAttempt.ts +41 -0
  44. package/vona/src/suite/a-commerce/modules/commerce-payment/test/paymentAttempt.test.ts +33 -0
  45. package/vona/src/suite/a-commerce/modules/commerce-promotion/package.json +4 -2
  46. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/.metadata/index.ts +533 -2
  47. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/.metadata/locales.ts +18 -0
  48. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/bean/meta.index.ts +24 -0
  49. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/bean/meta.version.ts +137 -0
  50. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/bean/ssrMenu.couponTemplate.ts +30 -0
  51. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/config/locale/en-us.ts +37 -0
  52. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/config/locale/zh-cn.ts +37 -0
  53. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/controller/coupon.ts +37 -0
  54. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/controller/couponTemplate.ts +65 -0
  55. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponIssue.tsx +22 -0
  56. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponMineItem.tsx +32 -0
  57. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateCreate.tsx +43 -0
  58. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateSelectReq.tsx +28 -0
  59. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateSelectRes.tsx +11 -0
  60. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateSelectResItem.tsx +39 -0
  61. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateUpdate.tsx +19 -0
  62. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateView.tsx +25 -0
  63. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/entity/couponAudit.tsx +73 -0
  64. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/entity/couponGrant.tsx +83 -0
  65. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/entity/couponTemplate.tsx +82 -0
  66. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/index.ts +1 -0
  67. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/model/couponAudit.ts +10 -0
  68. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/model/couponGrant.ts +10 -0
  69. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/model/couponTemplate.ts +10 -0
  70. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/service/coupon.ts +397 -0
  71. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/service/couponTemplate.ts +52 -0
  72. package/vona/src/suite/a-commerce/modules/commerce-promotion/test/couponReservation.test.ts +162 -0
  73. package/vona/src/suite/a-commerce/modules/commerce-seed/src/bean/meta.version.ts +11 -13
  74. package/vona/src/suite/a-commerce/modules/commerce-trade/package.json +4 -1
  75. package/vona/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +277 -0
  76. package/vona/src/suite/a-commerce/modules/commerce-trade/src/bean/bean.scheduleOrderExpiry.ts +26 -0
  77. package/vona/src/suite/a-commerce/modules/commerce-trade/src/bean/meta.index.ts +9 -0
  78. package/vona/src/suite/a-commerce/modules/commerce-trade/src/bean/meta.version.ts +79 -0
  79. package/vona/src/suite/a-commerce/modules/commerce-trade/src/config/locale/en-us.ts +14 -1
  80. package/vona/src/suite/a-commerce/modules/commerce-trade/src/config/locale/zh-cn.ts +14 -1
  81. package/vona/src/suite/a-commerce/modules/commerce-trade/src/controller/checkout.ts +19 -0
  82. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/checkoutCreate.tsx +19 -0
  83. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/checkoutResult.tsx +32 -0
  84. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderAddressSnapshot.tsx +33 -0
  85. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderCouponSnapshot.tsx +35 -0
  86. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderLineSkuAttributeSnapshot.tsx +15 -0
  87. package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/order.tsx +90 -0
  88. package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/orderAudit.tsx +36 -0
  89. package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/orderLine.tsx +52 -0
  90. package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/stockAudit.tsx +39 -7
  91. package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/stockReservation.tsx +4 -1
  92. package/vona/src/suite/a-commerce/modules/commerce-trade/src/model/order.ts +15 -0
  93. package/vona/src/suite/a-commerce/modules/commerce-trade/src/model/orderAudit.ts +10 -0
  94. package/vona/src/suite/a-commerce/modules/commerce-trade/src/model/orderLine.ts +10 -0
  95. package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/order.ts +556 -0
  96. package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/stockBalance.ts +32 -0
  97. package/vona/src/suite/a-commerce/modules/commerce-trade/test/cartOwnership.test.ts +8 -3
  98. package/vona/src/suite/a-commerce/modules/commerce-trade/test/checkoutReservation.test.ts +158 -0
  99. package/vona/src/suite/a-commerce/modules/commerce-trade/test/orderSnapshot.test.ts +203 -0
  100. package/vona/src/suite/a-commerce/modules/commerce-trade/test/reservationExpiry.test.ts +163 -0
  101. package/vona/src/suite/a-commerce/modules/commerce-trade/test/stockBalance.test.ts +274 -66
  102. package/vona/src/suite/a-commerce/modules/commerce-trade/test/stockReservation.test.ts +282 -82
  103. package/vona/src/suite-vendor/a-image/modules/image-cloudflare/package.json +1 -1
  104. package/vona/src/suite-vendor/a-image/modules/image-cloudflare/src/service/imageCloudflare.ts +10 -7
  105. package/vona/src/suite-vendor/a-image/package.json +1 -1
  106. package/vona/src/suite-vendor/a-vona/modules/a-aspect/package.json +1 -1
  107. package/vona/src/suite-vendor/a-vona/modules/a-aspect/src/types/aopMethod.ts +16 -3
  108. package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +4 -2
  109. package/vona/src/suite-vendor/a-vona/modules/a-core/src/bean/bean.core.ts +6 -0
  110. package/vona/src/suite-vendor/a-vona/modules/a-core/src/index.ts +1 -0
  111. package/vona/src/suite-vendor/a-vona/modules/a-core/src/lib/core.ts +6 -0
  112. package/vona/src/suite-vendor/a-vona/modules/a-core/src/types/fetch.ts +7 -0
  113. package/vona/src/suite-vendor/a-vona/modules/a-core/src/types/index.ts +1 -0
  114. package/vona/src/suite-vendor/a-vona/modules/a-executor/package.json +1 -1
  115. package/vona/src/suite-vendor/a-vona/modules/a-executor/src/lib/utils.ts +5 -3
  116. package/vona/src/suite-vendor/a-vona/modules/a-retryable/package.json +50 -0
  117. package/vona/src/suite-vendor/a-vona/modules/a-retryable/src/.metadata/index.ts +55 -0
  118. package/vona/src/suite-vendor/a-vona/modules/a-retryable/src/.metadata/this.ts +2 -0
  119. package/vona/src/suite-vendor/a-vona/modules/a-retryable/src/bean/aopMethod.retryable.ts +45 -0
  120. package/vona/src/suite-vendor/a-vona/modules/a-retryable/src/index.ts +1 -0
  121. package/vona/src/suite-vendor/a-vona/modules/a-retryable/tsconfig.build.json +11 -0
  122. package/vona/src/suite-vendor/a-vona/modules/a-retryable/tsconfig.json +7 -0
  123. package/vona/src/suite-vendor/a-vona/modules/a-startup/package.json +1 -1
  124. package/vona/src/suite-vendor/a-vona/modules/a-startup/src/service/startup.ts +2 -2
  125. package/vona/src/suite-vendor/a-vona/modules/a-version/package.json +1 -1
  126. package/vona/src/suite-vendor/a-vona/modules/a-version/src/service/version.ts +12 -12
  127. package/vona/src/suite-vendor/a-vona/modules/a-version/src/types/version.ts +4 -4
  128. package/vona/src/suite-vendor/a-vona/modules/a-vona/package.json +2 -1
  129. package/vona/src/suite-vendor/a-vona/package.json +2 -1
  130. package/vona/src/suite-vendor/a-vona/tsconfig.json +3 -0
  131. package/zova/packages-utils/zova-jsx/package.json +3 -3
  132. package/zova/packages-zova/zova/package.json +3 -3
  133. package/zova/packages-zova/zova-core/package.json +2 -2
  134. package/zova/pnpm-lock.yaml +14 -14
  135. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/page/product/controller.tsx +0 -1
  136. package/zova/src/suite/a-commerce/modules/commerce-promotion/cli/openapi.config.ts +9 -0
  137. package/zova/src/suite/a-commerce/modules/commerce-promotion/package.json +2 -1
  138. package/zova/src/suite/a-commerce/modules/commerce-promotion/src/.metadata/index.ts +115 -1
  139. package/zova/src/suite/a-commerce/modules/commerce-promotion/src/api/commercePromotionCoupon.ts +24 -0
  140. package/zova/src/suite/a-commerce/modules/commerce-promotion/src/api/openapi/baseURL.ts +5 -0
  141. package/zova/src/suite/a-commerce/modules/commerce-promotion/src/api/openapi/index.ts +3 -0
  142. package/zova/src/suite/a-commerce/modules/commerce-promotion/src/api/openapi/schemas.ts +478 -0
  143. package/zova/src/suite/a-commerce/modules/commerce-promotion/src/api/openapi/types.ts +8187 -0
  144. package/zova/src/suite/a-commerce/modules/commerce-promotion/src/apiSchema/commercePromotionCoupon.ts +13 -0
  145. package/zova/src/suite/a-commerce/modules/commerce-promotion/src/model/coupon.ts +19 -0
  146. package/zova/src/suite/a-commerce/modules/commerce-trade/cli/openapi.config.ts +1 -0
  147. package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +30 -0
  148. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/commerceTradeCheckout.ts +27 -0
  149. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/schemas.ts +92 -52
  150. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/types.ts +1389 -848
  151. package/zova/src/suite/a-commerce/modules/commerce-trade/src/apiSchema/commerceTradeCheckout.ts +13 -0
  152. package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/cart.ts +14 -0
  153. package/zova/src/suite/a-home/modules/home-layoutadmin/src/component/layoutAdmin/controller.tsx +17 -7
  154. package/zova/src/suite/a-home/modules/home-layoutadmin/src/component/layoutAdmin/render.header.tsx +1 -1
  155. package/zova/src/suite/a-home/modules/home-layoutweb/src/component/layoutWeb/controller.tsx +17 -7
  156. package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +3 -3
  157. package/zova/src/suite-vendor/a-zova/package.json +2 -2
@@ -377,6 +377,7 @@ export * from '../dto/productSelectRes.tsx';
377
377
  export * from '../dto/productSelectResItem.tsx';
378
378
  export * from '../dto/productUpdate.tsx';
379
379
  export * from '../dto/productView.tsx';
380
+ export * from '../dto/skuAttribute.tsx';
380
381
  export * from '../dto/skuCreate.tsx';
381
382
  export * from '../dto/skuSelectReq.tsx';
382
383
  export * from '../dto/skuSelectRes.tsx';
@@ -399,6 +400,7 @@ import type { IDtoOptionsProductSelectRes } from '../dto/productSelectRes.tsx';
399
400
  import type { IDtoOptionsProductSelectResItem } from '../dto/productSelectResItem.tsx';
400
401
  import type { IDtoOptionsProductUpdate } from '../dto/productUpdate.tsx';
401
402
  import type { IDtoOptionsProductView } from '../dto/productView.tsx';
403
+ import type { IDtoOptionsSkuAttribute } from '../dto/skuAttribute.tsx';
402
404
  import type { IDtoOptionsSkuCreate } from '../dto/skuCreate.tsx';
403
405
  import type { IDtoOptionsSkuSelectReq } from '../dto/skuSelectReq.tsx';
404
406
  import type { IDtoOptionsSkuSelectRes } from '../dto/skuSelectRes.tsx';
@@ -425,6 +427,7 @@ declare module 'vona-module-a-web' {
425
427
  'commerce-catalog:productSelectResItem': IDtoOptionsProductSelectResItem;
426
428
  'commerce-catalog:productUpdate': IDtoOptionsProductUpdate;
427
429
  'commerce-catalog:productView': IDtoOptionsProductView;
430
+ 'commerce-catalog:skuAttribute': IDtoOptionsSkuAttribute;
428
431
  'commerce-catalog:skuCreate': IDtoOptionsSkuCreate;
429
432
  'commerce-catalog:skuSelectReq': IDtoOptionsSkuSelectReq;
430
433
  'commerce-catalog:skuSelectRes': IDtoOptionsSkuSelectRes;
@@ -456,6 +459,7 @@ import type { DtoProductSelectRes } from '../dto/productSelectRes.tsx';
456
459
  import type { DtoProductSelectResItem } from '../dto/productSelectResItem.tsx';
457
460
  import type { DtoProductUpdate } from '../dto/productUpdate.tsx';
458
461
  import type { DtoProductView } from '../dto/productView.tsx';
462
+ import type { DtoSkuAttribute } from '../dto/skuAttribute.tsx';
459
463
  import type { DtoSkuCreate } from '../dto/skuCreate.tsx';
460
464
  import type { DtoSkuSelectReq } from '../dto/skuSelectReq.tsx';
461
465
  import type { DtoSkuSelectRes } from '../dto/skuSelectRes.tsx';
@@ -528,6 +532,10 @@ declare module 'vona-module-commerce-catalog' {
528
532
  fields?: TypeEntityOptionsFields<DtoProductView, IDtoOptionsProductView[TypeSymbolKeyFieldsMore]>;
529
533
  }
530
534
 
535
+ export interface IDtoOptionsSkuAttribute {
536
+ fields?: TypeEntityOptionsFields<DtoSkuAttribute, IDtoOptionsSkuAttribute[TypeSymbolKeyFieldsMore]>;
537
+ }
538
+
531
539
  export interface IDtoOptionsSkuCreate {
532
540
  fields?: TypeEntityOptionsFields<DtoSkuCreate, IDtoOptionsSkuCreate[TypeSymbolKeyFieldsMore]>;
533
541
  }
@@ -42,6 +42,7 @@ export class MetaVersion extends BeanBase implements IMetaVersionUpdate {
42
42
  table.tableIdentity(entitySku.productId).comment(entitySku.$comment.productId);
43
43
  table.string(entitySku.code, 100).comment(entitySku.$comment.code);
44
44
  table.integer(entitySku.priceCents).comment(entitySku.$comment.priceCents);
45
+ table.json(entitySku.attributes).comment(entitySku.$comment.attributes);
45
46
  table.string(entitySku.lifecycle, 20).comment(entitySku.$comment.lifecycle);
46
47
  table.index([entitySku.productId], `idx_${entitySku.$table}_productId`);
47
48
  table.index([entitySku.lifecycle], `idx_${entitySku.$table}_lifecycle`);
@@ -10,6 +10,9 @@ export default {
10
10
  ProductTitle: 'Product title',
11
11
  Published: 'Published',
12
12
  Sku: 'SKU',
13
+ SkuAttributeName: 'SKU attribute name',
14
+ SkuAttributeValue: 'SKU attribute value',
15
+ SkuAttributes: 'SKU attributes',
13
16
  SkuCode: 'SKU code',
14
17
  SkuLifecycle: 'SKU lifecycle',
15
18
  SkuLifecycleActive: 'Active',
@@ -10,6 +10,9 @@ export default {
10
10
  ProductTitle: '商品标题',
11
11
  Published: '已发布',
12
12
  Sku: 'SKU',
13
+ SkuAttributeName: 'SKU 属性名',
14
+ SkuAttributeValue: 'SKU 属性值',
15
+ SkuAttributes: 'SKU 属性',
13
16
  SkuCode: 'SKU 编码',
14
17
  SkuLifecycle: 'SKU 生命周期',
15
18
  SkuLifecycleActive: '已启用',
@@ -0,0 +1,17 @@
1
+ import type { IDecoratorDtoOptions } from 'vona-module-a-web';
2
+
3
+ import { Api, v } from 'vona-module-a-openapiutils';
4
+ import { Dto } from 'vona-module-a-web';
5
+
6
+ import { $locale } from '../.metadata/locales.ts';
7
+
8
+ export interface IDtoOptionsSkuAttribute extends IDecoratorDtoOptions {}
9
+
10
+ @Dto<IDtoOptionsSkuAttribute>()
11
+ export class DtoSkuAttribute {
12
+ @Api.field(v.title($locale('SkuAttributeName')), v.required(), v.min(1), v.max(100))
13
+ name: string;
14
+
15
+ @Api.field(v.title($locale('SkuAttributeValue')), v.required(), v.min(1), v.max(255))
16
+ value: string;
17
+ }
@@ -7,6 +7,7 @@ import z from 'zod';
7
7
  import { ZovaRender } from 'zova-rest-cabloy-basic-admin';
8
8
 
9
9
  import { $locale } from '../.metadata/locales.ts';
10
+ import { DtoSkuAttribute } from '../dto/skuAttribute.tsx';
10
11
 
11
12
  export const skuLifecycleItems = [
12
13
  { value: 'draft', title: $locale('SkuLifecycleDraft') },
@@ -56,10 +57,18 @@ export class EntitySku extends EntityBase {
56
57
  )
57
58
  priceCents: number;
58
59
 
60
+ @Api.field(
61
+ v.title($locale('SkuAttributes')),
62
+ v.default([]),
63
+ v.array(v.object(DtoSkuAttribute)),
64
+ ZovaRender.order(4),
65
+ )
66
+ attributes: DtoSkuAttribute[];
67
+
59
68
  @Api.field(
60
69
  v.title($locale('SkuLifecycle')),
61
70
  v.default('draft'),
62
- ZovaRender.order(4),
71
+ ZovaRender.order(5),
63
72
  z.enum(['draft', 'active', 'inactive', 'archived']),
64
73
  )
65
74
  lifecycle: 'draft' | 'active' | 'inactive' | 'archived';
@@ -1,3 +1,4 @@
1
+ import { catchError } from '@cabloy/utils';
1
2
  import assert from 'node:assert';
2
3
  import { describe, it } from 'node:test';
3
4
  import { app } from 'vona-mock';
@@ -355,4 +356,237 @@ describe('catalog.test.ts', () => {
355
356
  { instanceName: 'shareTest' as any },
356
357
  );
357
358
  });
359
+
360
+ it('treats foreign operator catalogue resources as absent', async () => {
361
+ const prefix = `__catalog-foreign-${Date.now()}__`;
362
+ let defaultCatalog!: Awaited<ReturnType<typeof createCatalog>>;
363
+ await app.bean.executor.mockCtx(async () => {
364
+ defaultCatalog = await createCatalog(prefix, 'active');
365
+ });
366
+
367
+ await app.bean.executor.mockCtx(
368
+ async () => {
369
+ await app.bean.passport.signinMock();
370
+ try {
371
+ const resources = [
372
+ ['category', defaultCatalog.categoryId, { name: 'foreign category', published: false }],
373
+ [
374
+ 'product',
375
+ defaultCatalog.productId,
376
+ {
377
+ categoryId: defaultCatalog.categoryId,
378
+ title: 'foreign product',
379
+ published: false,
380
+ },
381
+ ],
382
+ [
383
+ 'sku',
384
+ defaultCatalog.skuId,
385
+ {
386
+ productId: defaultCatalog.productId,
387
+ code: 'foreign-sku',
388
+ priceCents: 100,
389
+ lifecycle: 'inactive',
390
+ },
391
+ ],
392
+ ] as const;
393
+ for (const [resource, id, body] of resources) {
394
+ assert.equal(
395
+ await app.bean.executor.performAction('get', `/commerce/catalog/${resource}/:id`, {
396
+ params: { id },
397
+ }),
398
+ undefined,
399
+ );
400
+ const selected = await app.bean.executor.performAction(
401
+ 'get',
402
+ `/commerce/catalog/${resource}`,
403
+ );
404
+ assert.equal(
405
+ selected.list.some((item: { id: unknown }) => String(item.id) === String(id)),
406
+ false,
407
+ );
408
+ const update = () =>
409
+ app.bean.executor.performAction('patch', `/commerce/catalog/${resource}/:id`, {
410
+ params: { id },
411
+ body,
412
+ });
413
+ if (resource === 'category') {
414
+ assert.equal(await update(), null);
415
+ } else {
416
+ await assert.rejects(update);
417
+ }
418
+ assert.equal(
419
+ await app.bean.executor.performAction('delete', `/commerce/catalog/${resource}/:id`, {
420
+ params: { id },
421
+ }),
422
+ null,
423
+ );
424
+ }
425
+ } finally {
426
+ await app.bean.passport.signout();
427
+ }
428
+ },
429
+ { instanceName: 'shareTest' as any },
430
+ );
431
+
432
+ await app.bean.executor.mockCtx(async () => {
433
+ const category = await app
434
+ .scope('commerce-catalog')
435
+ .model.category.getById(defaultCatalog.categoryId);
436
+ const product = await app
437
+ .scope('commerce-catalog')
438
+ .model.product.getById(defaultCatalog.productId);
439
+ const sku = await app.scope('commerce-catalog').model.sku.getById(defaultCatalog.skuId);
440
+ assert.equal(category?.name, `${prefix} category`);
441
+ assert.equal(product?.title, `${prefix} product`);
442
+ assert.equal(sku?.code, `${prefix}-sku`);
443
+ });
444
+ });
445
+
446
+ it('rejects foreign catalogue relation identifiers without local writes', async () => {
447
+ const suffix = `${Date.now()}`;
448
+ let foreignCatalog!: Awaited<ReturnType<typeof createCatalog>>;
449
+ await app.bean.executor.mockCtx(
450
+ async () => {
451
+ foreignCatalog = await createCatalog(`crf-${suffix}`, 'active');
452
+ },
453
+ { instanceName: 'shareTest' as any },
454
+ );
455
+
456
+ await app.bean.executor.mockCtx(async () => {
457
+ await app.bean.passport.signinMock();
458
+ try {
459
+ const parentCategoryId = await app.bean.executor.performAction(
460
+ 'post',
461
+ '/commerce/catalog/category',
462
+ { body: { name: `relation-parent-${suffix}`, published: true } },
463
+ );
464
+ const categoryId = await app.bean.executor.performAction(
465
+ 'post',
466
+ '/commerce/catalog/category',
467
+ {
468
+ body: {
469
+ name: `relation-category-${suffix}`,
470
+ parentId: parentCategoryId,
471
+ published: true,
472
+ },
473
+ },
474
+ );
475
+ const productId = await app.bean.executor.performAction(
476
+ 'post',
477
+ '/commerce/catalog/product',
478
+ {
479
+ body: {
480
+ categoryId,
481
+ title: `relation-product-${suffix}`,
482
+ published: true,
483
+ },
484
+ },
485
+ );
486
+ const skuId = await app.bean.executor.performAction('post', '/commerce/catalog/sku', {
487
+ body: {
488
+ productId,
489
+ code: `relation-sku-${suffix}`,
490
+ priceCents: 100,
491
+ lifecycle: 'draft',
492
+ },
493
+ });
494
+ const operations = [
495
+ () =>
496
+ app.bean.executor.performAction('post', '/commerce/catalog/category', {
497
+ body: {
498
+ name: `foreign-parent-category-${suffix}`,
499
+ parentId: foreignCatalog.categoryId,
500
+ published: true,
501
+ },
502
+ }),
503
+ () =>
504
+ app.bean.executor.performAction('patch', '/commerce/catalog/category/:id', {
505
+ params: { id: categoryId },
506
+ body: {
507
+ name: `relation-category-updated-${suffix}`,
508
+ parentId: foreignCatalog.categoryId,
509
+ published: false,
510
+ },
511
+ }),
512
+ () =>
513
+ app.bean.executor.performAction('post', '/commerce/catalog/product', {
514
+ body: {
515
+ categoryId: foreignCatalog.categoryId,
516
+ title: `foreign-category-product-${suffix}`,
517
+ published: true,
518
+ },
519
+ }),
520
+ () =>
521
+ app.bean.executor.performAction('patch', '/commerce/catalog/product/:id', {
522
+ params: { id: productId },
523
+ body: {
524
+ categoryId: foreignCatalog.categoryId,
525
+ title: `relation-product-updated-${suffix}`,
526
+ published: false,
527
+ },
528
+ }),
529
+ () =>
530
+ app.bean.executor.performAction('post', '/commerce/catalog/sku', {
531
+ body: {
532
+ productId: foreignCatalog.productId,
533
+ code: `foreign-product-sku-${suffix}`,
534
+ priceCents: 100,
535
+ lifecycle: 'draft',
536
+ },
537
+ }),
538
+ () =>
539
+ app.bean.executor.performAction('patch', '/commerce/catalog/sku/:id', {
540
+ params: { id: skuId },
541
+ body: {
542
+ productId: foreignCatalog.productId,
543
+ code: `relation-sku-updated-${suffix}`,
544
+ priceCents: 200,
545
+ lifecycle: 'active',
546
+ },
547
+ }),
548
+ ];
549
+ for (const operation of operations) {
550
+ const [_, err] = await catchError(operation);
551
+ assert.equal(err?.code, 404);
552
+ }
553
+
554
+ const category = await app.scope('commerce-catalog').model.category.getById(categoryId);
555
+ const product = await app.scope('commerce-catalog').model.product.getById(productId);
556
+ const sku = await app.scope('commerce-catalog').model.sku.getById(skuId);
557
+ assert.deepEqual(
558
+ [category?.name, category?.parentId, category?.published],
559
+ [`relation-category-${suffix}`, parentCategoryId, true],
560
+ );
561
+ assert.deepEqual(
562
+ [product?.categoryId, product?.title, product?.published],
563
+ [categoryId, `relation-product-${suffix}`, true],
564
+ );
565
+ assert.deepEqual(
566
+ [sku?.productId, sku?.code, sku?.priceCents, sku?.lifecycle],
567
+ [productId, `relation-sku-${suffix}`, 100, 'draft'],
568
+ );
569
+ assert.equal(
570
+ await app.scope('commerce-catalog').model.category.get({
571
+ name: `foreign-parent-category-${suffix}`,
572
+ }),
573
+ undefined,
574
+ );
575
+ assert.equal(
576
+ await app.scope('commerce-catalog').model.product.get({
577
+ title: `foreign-category-product-${suffix}`,
578
+ }),
579
+ undefined,
580
+ );
581
+ assert.equal(
582
+ await app.scope('commerce-catalog').model.sku.get({
583
+ code: `foreign-product-sku-${suffix}`,
584
+ }),
585
+ undefined,
586
+ );
587
+ } finally {
588
+ await app.bean.passport.signout();
589
+ }
590
+ });
591
+ });
358
592
  });
@@ -6,11 +6,16 @@ import type {
6
6
 
7
7
  import { catchError } from '@cabloy/utils';
8
8
  import assert from 'node:assert';
9
+ import { randomUUID } from 'node:crypto';
9
10
  import { describe, it } from 'node:test';
10
11
  import { app } from 'vona-mock';
11
12
 
12
13
  const actionPath = '/commerce/member/address';
13
14
 
15
+ function createTestId() {
16
+ return randomUUID().slice(0, 12);
17
+ }
18
+
14
19
  function createAddress(suffix: string): DtoAddressCreate {
15
20
  return {
16
21
  recipientName: `Recipient ${suffix}`,
@@ -60,7 +65,7 @@ describe('address.test.ts', () => {
60
65
 
61
66
  it('derives ownership from the authenticated customer and scopes every action', async () => {
62
67
  await app.bean.executor.mockCtx(async () => {
63
- const suffix = `${Date.now()}`;
68
+ const suffix = createTestId();
64
69
  const customerA = await registerAndSignin(`address-a-${suffix}`);
65
70
  const customerB = await registerAndSignin(`address-b-${suffix}`);
66
71
  const addressData = createAddress(suffix);
@@ -47,6 +47,7 @@
47
47
  "vonaModule": {
48
48
  "dependencies": {
49
49
  "a-vona": "5.0.0"
50
- }
50
+ },
51
+ "fileVersion": 1
51
52
  }
52
53
  }
@@ -1,4 +1,229 @@
1
1
  // eslint-disable
2
+ import type { TypeEntityMeta,TypeModelsClassLikeGeneral,TypeSymbolKeyFieldsMore } from 'vona-module-a-orm';
3
+ import type { TypeEntityOptionsFields } from 'vona-module-a-openapi';
4
+ import type { TableIdentity } from 'table-identity';
5
+ /** entity: begin */
6
+ export * from '../entity/paymentAttempt.tsx';
7
+ import type { IEntityOptionsPaymentAttempt } from '../entity/paymentAttempt.tsx';
8
+ import 'vona-module-a-orm';
9
+ declare module 'vona-module-a-orm' {
10
+
11
+ export interface IEntityRecord {
12
+ 'commerce-payment:paymentAttempt': IEntityOptionsPaymentAttempt;
13
+ }
14
+
15
+
16
+ }
17
+ declare module 'vona-module-commerce-payment' {
18
+
19
+ }
20
+ /** entity: end */
21
+ /** entity: begin */
22
+ import type { EntityPaymentAttempt } from '../entity/paymentAttempt.tsx';
23
+ export interface IModuleEntity {
24
+ 'paymentAttempt': EntityPaymentAttemptMeta;
25
+ }
26
+ /** entity: end */
27
+ /** entity: begin */
28
+ export type EntityPaymentAttemptTableName = 'commercePaymentAttempt';
29
+ export type EntityPaymentAttemptMeta=TypeEntityMeta<EntityPaymentAttempt,EntityPaymentAttemptTableName>;
30
+ declare module 'vona-module-a-orm' {
31
+ export interface ITableRecord {
32
+ 'commercePaymentAttempt': EntityPaymentAttemptMeta;
33
+ }
34
+ }
35
+ declare module 'vona-module-commerce-payment' {
36
+
37
+ export interface IEntityOptionsPaymentAttempt {
38
+ fields?: TypeEntityOptionsFields<EntityPaymentAttempt, IEntityOptionsPaymentAttempt[TypeSymbolKeyFieldsMore]>;
39
+ }
40
+ }
41
+ /** entity: end */
42
+ /** model: begin */
43
+ export * from '../model/paymentAttempt.ts';
44
+ import type { IModelOptionsPaymentAttempt } from '../model/paymentAttempt.ts';
45
+ import 'vona-module-a-orm';
46
+ declare module 'vona-module-a-orm' {
47
+
48
+ export interface IModelRecord {
49
+ 'commerce-payment:paymentAttempt': IModelOptionsPaymentAttempt;
50
+ }
51
+
52
+
53
+ }
54
+ declare module 'vona-module-commerce-payment' {
55
+
56
+ export interface ModelPaymentAttempt {
57
+ /** @internal */
58
+ get scope(): ScopeModuleCommercePayment;
59
+ }
60
+
61
+ export interface ModelPaymentAttempt {
62
+ get $beanFullName(): 'commerce-payment.model.paymentAttempt';
63
+ get $onionName(): 'commerce-payment:paymentAttempt';
64
+ get $onionOptions(): IModelOptionsPaymentAttempt;
65
+ }
66
+ }
67
+ /** model: end */
68
+ /** model: begin */
69
+ import type { ModelPaymentAttempt } from '../model/paymentAttempt.ts';
70
+ export interface IModuleModel {
71
+ 'paymentAttempt': ModelPaymentAttempt;
72
+ }
73
+ /** model: end */
74
+ /** model: begin */
75
+
76
+ import 'vona';
77
+ declare module 'vona' {
78
+ export interface IBeanRecordGeneral {
79
+ 'commerce-payment.model.paymentAttempt': ModelPaymentAttempt;
80
+ }
81
+ }
82
+ /** model: end */
83
+ /** model: begin */
84
+ import type { IModelGetOptions, IModelMethodOptions, IModelSelectParams, TypeModelSelectAndCount, TypeModelRelationResult, TypeModelWhere, IModelInsertOptions, TypeModelMutateRelationData, IModelDeleteOptions, IModelUpdateOptions, IModelMutateOptions, IModelSelectCountParams, IModelIncrementParams, IModelSelectAggrParams, TypeModelAggrRelationResult, IModelSelectGroupParams, TypeModelGroupRelationResult } from 'vona-module-a-orm';
85
+ import { SymbolKeyEntity, SymbolKeyEntityMeta, SymbolKeyModelOptions } from 'vona-module-a-orm';
86
+ declare module 'vona-module-commerce-payment' {
87
+
88
+ export interface ModelPaymentAttempt {
89
+ [SymbolKeyEntity]: EntityPaymentAttempt;
90
+ [SymbolKeyEntityMeta]: EntityPaymentAttemptMeta;
91
+ [SymbolKeyModelOptions]: IModelOptionsPaymentAttempt;
92
+ get<T extends IModelGetOptions<EntityPaymentAttempt,ModelPaymentAttempt>>(where: TypeModelWhere<EntityPaymentAttempt>, options?: T): Promise<TypeModelRelationResult<EntityPaymentAttempt, ModelPaymentAttempt, T> | undefined>;
93
+ getForUpdate<T extends IModelGetOptions<EntityPaymentAttempt,ModelPaymentAttempt>>(where: TypeModelWhere<EntityPaymentAttempt>, options?: T): Promise<TypeModelRelationResult<EntityPaymentAttempt, ModelPaymentAttempt, T> | undefined>;
94
+ getByIdForUpdate<T extends IModelGetOptions<EntityPaymentAttempt,ModelPaymentAttempt>>(id: TableIdentity, options?: T): Promise<TypeModelRelationResult<EntityPaymentAttempt, ModelPaymentAttempt, T> | undefined>;
95
+ mget<T extends IModelGetOptions<EntityPaymentAttempt,ModelPaymentAttempt>>(ids: TableIdentity[], options?: T): Promise<TypeModelRelationResult<EntityPaymentAttempt, ModelPaymentAttempt, T>[]>;
96
+ selectAndCount<T extends IModelSelectParams<EntityPaymentAttempt,ModelPaymentAttempt,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelSelectAndCount<EntityPaymentAttempt, ModelPaymentAttempt, T>>;
97
+ select<T extends IModelSelectParams<EntityPaymentAttempt,ModelPaymentAttempt,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelRelationResult<EntityPaymentAttempt, ModelPaymentAttempt, T>[]>;
98
+ insert<T extends IModelInsertOptions<EntityPaymentAttempt,ModelPaymentAttempt>>(data?: TypeModelMutateRelationData<EntityPaymentAttempt,ModelPaymentAttempt, T>, options?: T): Promise<TypeModelMutateRelationData<EntityPaymentAttempt,ModelPaymentAttempt, T, true>>;
99
+ insertBulk<T extends IModelInsertOptions<EntityPaymentAttempt,ModelPaymentAttempt>>(items: TypeModelMutateRelationData<EntityPaymentAttempt,ModelPaymentAttempt, T>[], options?: T): Promise<TypeModelMutateRelationData<EntityPaymentAttempt,ModelPaymentAttempt, T, true>[]>;
100
+ update<T extends IModelUpdateOptions<EntityPaymentAttempt,ModelPaymentAttempt>>(data: TypeModelMutateRelationData<EntityPaymentAttempt,ModelPaymentAttempt, T>, options?: T): Promise<TypeModelMutateRelationData<EntityPaymentAttempt,ModelPaymentAttempt, T>>;
101
+ updateBulk<T extends IModelUpdateOptions<EntityPaymentAttempt,ModelPaymentAttempt>>(items: TypeModelMutateRelationData<EntityPaymentAttempt,ModelPaymentAttempt, T>[], options?: T): Promise<TypeModelMutateRelationData<EntityPaymentAttempt,ModelPaymentAttempt, T>[]>;
102
+ delete<T extends IModelDeleteOptions<EntityPaymentAttempt,ModelPaymentAttempt>>(where?: TypeModelWhere<EntityPaymentAttempt>, options?: T): Promise<void>;
103
+ deleteBulk<T extends IModelDeleteOptions<EntityPaymentAttempt,ModelPaymentAttempt>>(ids: TableIdentity[], options?: T): Promise<void>;
104
+ mutate<T extends IModelMutateOptions<EntityPaymentAttempt,ModelPaymentAttempt>>(data?: TypeModelMutateRelationData<EntityPaymentAttempt,ModelPaymentAttempt, T>, options?: T): Promise<TypeModelMutateRelationData<EntityPaymentAttempt,ModelPaymentAttempt, T>>;
105
+ mutateBulk<T extends IModelMutateOptions<EntityPaymentAttempt,ModelPaymentAttempt>>(items: TypeModelMutateRelationData<EntityPaymentAttempt,ModelPaymentAttempt, T>[], options?: T): Promise<TypeModelMutateRelationData<EntityPaymentAttempt,ModelPaymentAttempt, T>[]>;
106
+ count<T extends IModelSelectCountParams<EntityPaymentAttempt,ModelPaymentAttempt,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<string | undefined>;
107
+ increment<T extends IModelIncrementParams<EntityPaymentAttempt,ModelPaymentAttempt,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<number>;
108
+ decrement<T extends IModelIncrementParams<EntityPaymentAttempt,ModelPaymentAttempt,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<number>;
109
+ aggregate<T extends IModelSelectAggrParams<EntityPaymentAttempt,ModelPaymentAttempt,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelAggrRelationResult<T>>;
110
+ group<T extends IModelSelectGroupParams<EntityPaymentAttempt,ModelPaymentAttempt,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelGroupRelationResult<EntityPaymentAttempt, T>[]>;
111
+ getById<T extends IModelGetOptions<EntityPaymentAttempt,ModelPaymentAttempt>>(id: TableIdentity, options?: T): Promise<TypeModelRelationResult<EntityPaymentAttempt, ModelPaymentAttempt, T> | undefined>;
112
+ updateById<T extends IModelUpdateOptions<EntityPaymentAttempt,ModelPaymentAttempt>>(id: TableIdentity, data: TypeModelMutateRelationData<EntityPaymentAttempt,ModelPaymentAttempt, T>, options?: T): Promise<TypeModelMutateRelationData<EntityPaymentAttempt,ModelPaymentAttempt, T>>;
113
+ deleteById<T extends IModelDeleteOptions<EntityPaymentAttempt,ModelPaymentAttempt>>(id: TableIdentity, options?: T): Promise<void>;
114
+ }
115
+ }
116
+ declare module 'vona-module-a-orm' {
117
+ export interface IModelClassRecord {
118
+ 'commerce-payment:paymentAttempt': ModelPaymentAttempt;
119
+ }
120
+ }
121
+ /** model: end */
122
+ /** service: begin */
123
+ export * from '../service/paymentAttempt.ts';
124
+
125
+ import 'vona-module-a-bean';
126
+ declare module 'vona-module-a-bean' {
127
+
128
+ export interface IServiceRecord {
129
+ 'commerce-payment:paymentAttempt': never;
130
+ }
131
+
132
+
133
+ }
134
+ declare module 'vona-module-commerce-payment' {
135
+
136
+ export interface ServicePaymentAttempt {
137
+ /** @internal */
138
+ get scope(): ScopeModuleCommercePayment;
139
+ }
140
+
141
+ export interface ServicePaymentAttempt {
142
+ get $beanFullName(): 'commerce-payment.service.paymentAttempt';
143
+ get $onionName(): 'commerce-payment:paymentAttempt';
144
+
145
+ }
146
+ }
147
+ /** service: end */
148
+ /** service: begin */
149
+ import type { ServicePaymentAttempt } from '../service/paymentAttempt.ts';
150
+ export interface IModuleService {
151
+ 'paymentAttempt': ServicePaymentAttempt;
152
+ }
153
+ /** service: end */
154
+ /** service: begin */
155
+
156
+ import 'vona';
157
+ declare module 'vona' {
158
+ export interface IBeanRecordGeneral {
159
+ 'commerce-payment.service.paymentAttempt': ServicePaymentAttempt;
160
+ }
161
+ }
162
+ /** service: end */
163
+ /** meta: begin */
164
+ export * from '../bean/meta.index.ts';
165
+ export * from '../bean/meta.version.ts';
166
+ import type { IMetaOptionsIndex } from 'vona-module-a-index';
167
+ import 'vona-module-a-meta';
168
+ declare module 'vona-module-a-meta' {
169
+
170
+ export interface IMetaRecord {
171
+ 'commerce-payment:index': IMetaOptionsIndex;
172
+ 'commerce-payment:version': never;
173
+ }
174
+
175
+
176
+ }
177
+ declare module 'vona-module-commerce-payment' {
178
+
179
+ export interface MetaIndex {
180
+ /** @internal */
181
+ get scope(): ScopeModuleCommercePayment;
182
+ }
183
+
184
+ export interface MetaIndex {
185
+ get $beanFullName(): 'commerce-payment.meta.index';
186
+ get $onionName(): 'commerce-payment:index';
187
+ get $onionOptions(): IMetaOptionsIndex;
188
+ }
189
+
190
+ export interface MetaVersion {
191
+ /** @internal */
192
+ get scope(): ScopeModuleCommercePayment;
193
+ }
194
+
195
+ export interface MetaVersion {
196
+ get $beanFullName(): 'commerce-payment.meta.version';
197
+ get $onionName(): 'commerce-payment:version';
198
+
199
+ }
200
+ }
201
+ /** meta: end */
202
+ /** dto: begin */
203
+ export * from '../dto/paymentAttemptView.tsx';
204
+ import type { IDtoOptionsPaymentAttemptView } from '../dto/paymentAttemptView.tsx';
205
+ import 'vona-module-a-web';
206
+ declare module 'vona-module-a-web' {
207
+
208
+ export interface IDtoRecord {
209
+ 'commerce-payment:paymentAttemptView': IDtoOptionsPaymentAttemptView;
210
+ }
211
+
212
+
213
+ }
214
+ declare module 'vona-module-commerce-payment' {
215
+
216
+ }
217
+ /** dto: end */
218
+ /** dto: begin */
219
+ import type { DtoPaymentAttemptView } from '../dto/paymentAttemptView.tsx';
220
+ declare module 'vona-module-commerce-payment' {
221
+
222
+ export interface IDtoOptionsPaymentAttemptView {
223
+ fields?: TypeEntityOptionsFields<DtoPaymentAttemptView, IDtoOptionsPaymentAttemptView[TypeSymbolKeyFieldsMore]>;
224
+ }
225
+ }
226
+ /** dto: end */
2
227
  /** scope: begin */
3
228
  import { BeanScopeBase, type BeanScopeUtil } from 'vona';
4
229
  import { Scope } from 'vona-module-a-bean';
@@ -8,6 +233,9 @@ export class ScopeModuleCommercePayment extends BeanScopeBase {}
8
233
 
9
234
  export interface ScopeModuleCommercePayment {
10
235
  util: BeanScopeUtil;
236
+ entity: IModuleEntity;
237
+ model: IModuleModel;
238
+ service: IModuleService;
11
239
  }
12
240
 
13
241
  import 'vona';
@@ -0,0 +1,15 @@
1
+ import type { IMetaOptionsIndex } from 'vona-module-a-index';
2
+
3
+ import { BeanBase } from 'vona';
4
+ import { Meta } from 'vona-module-a-meta';
5
+ import { $tableColumns } from 'vona-module-a-ormutils';
6
+
7
+ @Meta<IMetaOptionsIndex>({
8
+ indexes: {
9
+ ...$tableColumns('commercePaymentAttempt', 'orderId'),
10
+ ...$tableColumns('commercePaymentAttempt', 'userId'),
11
+ ...$tableColumns('commercePaymentAttempt', 'state'),
12
+ ...$tableColumns('commercePaymentAttempt', 'correlationId'),
13
+ },
14
+ })
15
+ export class MetaIndex extends BeanBase {}