cabloy 5.1.115 → 5.1.117
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.
- package/.cabloy-version +1 -1
- package/.claude/skills/cabloy-contract-loop/SKILL.md +8 -2
- package/.claude/skills/cabloy-contract-loop/evals/evals.json +6 -0
- package/.claude/skills/cabloy-contract-loop/references/contract-loop-map.md +13 -0
- package/.claude/skills/cabloy-contract-loop/references/resource-custom-state-pattern.md +16 -3
- package/.claude/skills/cabloy-contract-loop/references/verification-checklist.md +12 -0
- package/.github/workflows/vona-test-mysql.yml +6 -10
- package/.github/workflows/vona-test-pg.yml +9 -10
- package/.github/workflows/vona-test-sqlite3.yml +3 -0
- package/CHANGELOG.md +35 -0
- package/CLAUDE.md +2 -0
- package/cabloy-docs/.vitepress/config.mjs +6 -0
- package/cabloy-docs/ai/docs-skills-rules-mapping.md +7 -0
- package/cabloy-docs/backend/aop-overview.md +16 -24
- package/cabloy-docs/backend/backend-source-reading-roadmap.md +26 -2
- package/cabloy-docs/backend/controller-aop-guide.md +38 -14
- package/cabloy-docs/backend/logger-guide.md +1 -0
- package/cabloy-docs/backend/menu-guide.md +1 -1
- package/cabloy-docs/backend/orm-mutation-guide.md +36 -10
- package/cabloy-docs/backend/orm-select-guide.md +15 -10
- package/cabloy-docs/backend/rate-limit-guide.md +97 -0
- package/cabloy-docs/backend/telemetry-guide.md +93 -0
- package/cabloy-docs/backend/vona-source-reading-map.md +44 -1
- package/cabloy-docs/frontend/model-resource-owner-pattern.md +2 -0
- package/cabloy-docs/frontend/ssr-overview.md +2 -0
- package/cabloy-docs/fullstack/admin-resource-and-web-self-service.md +329 -0
- package/cabloy-docs/fullstack/contract-loop-playbook.md +1 -1
- package/cabloy-docs/fullstack/introduction.md +1 -0
- package/e2e/specs/a-commerce/commerce.spec.ts +479 -1
- package/package.json +1 -1
- package/vona/packages-cli/cli/package.json +1 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/masterDetail/boilerplate/dto/<%=argv.detailDtoBaseName%>.tsx_ +1 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/masterDetail/boilerplate/dto/<%=argv.detailDtoMutateName%>.tsx_ +2 -2
- package/vona/packages-cli/cli-set-api/cli/templates/tools/masterDetail/boilerplate/dto/<%=argv.detailDtoResItemName%>.tsx_ +10 -10
- package/vona/packages-cli/cli-set-api/cli/templates/tools/masterDetail/boilerplate/dto/<%=argv.detailDtoViewName%>.tsx_ +2 -2
- package/vona/packages-cli/cli-set-api/package.json +1 -1
- package/vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.masterDetail.ts +13 -4
- package/vona/packages-vona/vona/package.json +1 -1
- package/vona/packages-vona/vona-core/package.json +1 -1
- package/vona/packages-vona/vona-core/src/lib/core/logger/utils.ts +12 -3
- package/vona/packages-vona/vona-mock/package.json +1 -1
- package/vona/pnpm-lock.yaml +237 -164
- package/vona/src/backend/config/config/config.ts +1 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/test/sku.test.ts +1 -1
- package/vona/src/suite/a-commerce/modules/commerce-member/src/.metadata/index.ts +81 -25
- package/vona/src/suite/a-commerce/modules/commerce-member/src/bean/ssrMenu.address.ts +30 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/controller/address.ts +42 -20
- package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressMineCreate.tsx +35 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressMineItem.tsx +39 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressMineReq.tsx +11 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressMineRes.tsx +11 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressMineUpdate.tsx +10 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressMineView.tsx +10 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressSelectResItem.tsx +1 -7
- package/vona/src/suite/a-commerce/modules/commerce-member/src/service/address.ts +43 -42
- package/vona/src/suite/a-commerce/modules/commerce-member/test/addressOwnership.test.ts +168 -127
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/.metadata/index.ts +76 -3
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/bean/meta.index.ts +3 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/bean/meta.version.ts +37 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/dto/paymentAttemptView.tsx +2 -2
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/entity/paymentAttempt.tsx +5 -2
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/entity/paymentAudit.tsx +54 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/model/paymentAudit.ts +10 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/service/mockPaymentAdapter.ts +18 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/service/paymentAttempt.ts +22 -7
- package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponIssue.tsx +1 -1
- package/vona/src/suite/a-commerce/modules/commerce-promotion/src/service/coupon.ts +6 -1
- package/vona/src/suite/a-commerce/modules/commerce-promotion/test/couponReservation.test.ts +480 -8
- package/vona/src/suite/a-commerce/modules/commerce-siteadmin/test/ssrMenu.test.ts +14 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +309 -3
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/bean/meta.index.ts +2 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/bean/meta.version.ts +16 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/bean/ssrMenu.order.ts +30 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/controller/order.ts +69 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/controller/payment.ts +23 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/checkoutResult.tsx +4 -4
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderDetail.tsx +72 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderMineReq.tsx +21 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderMineRes.tsx +11 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderSelectReq.tsx +25 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderSelectRes.tsx +11 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderSelectResItem.tsx +38 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderShip.tsx +15 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderSummary.tsx +26 -0
- package/vona/src/suite/a-commerce/modules/{commerce-member/src/dto/addressCreate.tsx → commerce-trade/src/dto/orderView.tsx} +5 -17
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/paymentOutcomeCreate.tsx +16 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/paymentOutcomeResult.tsx +29 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/shipmentView.tsx +22 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/orderAudit.tsx +13 -7
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/shipment.tsx +28 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/model/order.ts +1 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/model/shipment.ts +10 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/cart.ts +14 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/order.ts +436 -34
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/stockBalance.ts +4 -3
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/cartOwnership.test.ts +160 -80
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/checkoutReservation.test.ts +773 -2
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/checkoutTransaction.test.ts +212 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/order.test.ts +37 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/orderSnapshot.test.ts +29 -5
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/paymentOutcome.test.ts +714 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/reservationExpiry.test.ts +282 -9
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/shipment.test.ts +260 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/stockBalance.test.ts +15 -1
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/stockReservation.test.ts +20 -2
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/testLock.ts +11 -0
- package/vona/src/suite/a-home/modules/home-user/src/.metadata/index.ts +21 -0
- package/vona/src/suite/a-home/modules/home-user/src/controller/passportTest.ts +21 -0
- package/vona/src/suite/a-home/modules/home-user/test/passportTest.test.ts +77 -0
- package/vona/src/suite-vendor/a-vona/modules/a-broadcast/package.json +2 -1
- package/vona/src/suite-vendor/a-vona/modules/a-broadcast/src/service/broadcast.ts +84 -23
- package/vona/src/suite-vendor/a-vona/modules/a-broadcast/src/types/broadcast.ts +7 -1
- package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-core/src/lib/core.ts +8 -0
- package/vona/src/suite-vendor/a-vona/modules/a-executor/package.json +4 -2
- package/vona/src/suite-vendor/a-vona/modules/a-executor/src/service/executor.ts +68 -53
- package/vona/src/suite-vendor/a-vona/modules/a-orm/cli/model/metadata/generate.ts +10 -0
- package/vona/src/suite-vendor/a-vona/modules/a-orm/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/bean.model/bean.model_cache.ts +12 -0
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/bean.model/bean.model_crud_inner.ts +3 -0
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/bean.model/bean.model_utils.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-queue/package.json +4 -2
- package/vona/src/suite-vendor/a-vona/modules/a-queue/src/service/queue.ts +103 -54
- package/vona/src/suite-vendor/a-vona/modules/a-queue/src/types/queue.ts +5 -0
- package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/package.json +48 -0
- package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/src/.metadata/index.ts +100 -0
- package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/src/.metadata/this.ts +2 -0
- package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/src/bean/interceptor.rateLimit.ts +72 -0
- package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/src/index.ts +2 -0
- package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/src/main.ts +28 -0
- package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/src/service/rateLimit.ts +75 -0
- package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/src/types/index.ts +1 -0
- package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/src/types/rateLimit.ts +19 -0
- package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/tsconfig.build.json +11 -0
- package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/tsconfig.json +7 -0
- package/vona/src/suite-vendor/a-vona/modules/a-redis/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-redis/src/service/redis.ts +1 -2
- package/vona/src/suite-vendor/a-vona/modules/a-redis/src/types/redis.ts +1 -0
- package/vona/src/suite-vendor/a-vona/modules/a-telemetry/package.json +63 -0
- package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/.metadata/index.ts +132 -0
- package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/.metadata/this.ts +2 -0
- package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/bean/bean.telemetry.ts +71 -0
- package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/bean/middlewareSystem.trace.ts +73 -0
- package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/config/config.ts +83 -0
- package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/index.ts +2 -0
- package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/lib/ingress.ts +34 -0
- package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/monkey.ts +22 -0
- package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/service/telemetry.ts +201 -0
- package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/types/index.ts +1 -0
- package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/types/telemetry.ts +22 -0
- package/vona/src/suite-vendor/a-vona/modules/a-telemetry/test/telemetry.test.ts +339 -0
- package/vona/src/suite-vendor/a-vona/modules/a-telemetry/tsconfig.build.json +11 -0
- package/vona/src/suite-vendor/a-vona/modules/a-telemetry/tsconfig.json +7 -0
- package/vona/src/suite-vendor/a-vona/package.json +3 -1
- package/vona/src/suite-vendor/a-vona/tsconfig.json +3 -0
- package/zova/package.original.json +1 -1
- package/zova/packages-cli/cli/package.json +2 -2
- package/zova/packages-cli/cli-set-front/package.json +1 -1
- package/zova/packages-cli/cli-set-front/src/lib/bean/cli.bin.buildRest.ts +3 -2
- package/zova/packages-zova/zova/package.json +2 -2
- package/zova/pnpm-lock.yaml +87 -127
- package/zova/src/front/config/config/config.cabloyCommerce.ts +4 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/cli/openapi.config.ts +9 -1
- package/zova/src/suite/a-commerce/modules/commerce-member/src/.metadata/index.ts +16 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/src/api/commerceMemberAddress.ts +94 -50
- package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/schemas.ts +162 -52
- package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/types.ts +2656 -1298
- package/zova/src/suite/a-commerce/modules/commerce-member/src/apiSchema/commerceMemberAddress.ts +23 -13
- package/zova/src/suite/a-commerce/modules/commerce-member/src/model/addressMine.ts +67 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/src/page/address/controller.tsx +21 -11
- package/zova/src/suite/a-commerce/modules/commerce-promotion/src/api/openapi/schemas.ts +40 -32
- package/zova/src/suite/a-commerce/modules/commerce-promotion/src/api/openapi/types.ts +638 -633
- package/zova/src/suite/a-commerce/modules/commerce-trade/cli/openapi.config.ts +6 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/component/tableCellActionShip.ts +31 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +248 -1
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/page/checkout.ts +19 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/page/order.ts +19 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/page/orders.ts +19 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/page/payment.ts +19 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/commerceTradeOrder.ts +114 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/commerceTradePayment.ts +36 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/schemas.ts +75 -8
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/types.ts +762 -46
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/apiSchema/commerceTradeOrder.ts +35 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/apiSchema/commerceTradePayment.ts +13 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/bean/tableCell.actionShip.tsx +41 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/component/tableCellActionShip/controller.tsx +66 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/config/locale/en-us.ts +2 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/config/locale/zh-cn.ts +2 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/order.ts +38 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/orderMine.ts +31 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/payment.ts +25 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/cart/controller.tsx +14 -3
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/checkout/controller.tsx +124 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/order/controller.tsx +105 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/orders/controller.tsx +95 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/payment/controller.tsx +88 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/routes.ts +28 -0
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/command.delete.tsx +3 -2
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/tableCell.actionUpdate.tsx +2 -1
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/tableCell.actionView.tsx +1 -1
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/config/locale/en-us.ts +1 -0
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/config/locale/zh-cn.ts +1 -0
- package/zova/src/suite-vendor/a-zova/modules/a-ssr/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/lib/ssr.ts +4 -0
- package/zova/src/suite-vendor/a-zova/package.json +2 -2
- package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressUpdate.tsx +0 -39
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
DtoAddressMineCreate,
|
|
3
|
+
DtoAddressMineUpdate,
|
|
4
4
|
EntityAddress,
|
|
5
5
|
} from 'vona-module-commerce-member';
|
|
6
6
|
|
|
@@ -11,12 +11,17 @@ import { describe, it } from 'node:test';
|
|
|
11
11
|
import { app } from 'vona-mock';
|
|
12
12
|
|
|
13
13
|
const actionPath = '/commerce/member/address';
|
|
14
|
+
const minePath = `${actionPath}/mine`;
|
|
15
|
+
const viewMinePath = `${actionPath}/viewMine/:id`;
|
|
16
|
+
const createMinePath = `${actionPath}/createMine`;
|
|
17
|
+
const updateMinePath = `${actionPath}/updateMine/:id`;
|
|
18
|
+
const deleteMinePath = `${actionPath}/deleteMine/:id`;
|
|
14
19
|
|
|
15
20
|
function createTestId() {
|
|
16
21
|
return randomUUID().slice(0, 12);
|
|
17
22
|
}
|
|
18
23
|
|
|
19
|
-
function createAddress(suffix: string):
|
|
24
|
+
function createAddress(suffix: string): DtoAddressMineCreate {
|
|
20
25
|
return {
|
|
21
26
|
recipientName: `Recipient ${suffix}`,
|
|
22
27
|
phone: '15555550123',
|
|
@@ -45,15 +50,23 @@ async function registerAndSignin(name: string) {
|
|
|
45
50
|
return { token: token.accessToken, user: app.bean.passport.currentUser! };
|
|
46
51
|
}
|
|
47
52
|
|
|
48
|
-
|
|
49
|
-
|
|
53
|
+
async function deleteOwnedAddresses(ids: Array<number | string | undefined>) {
|
|
54
|
+
for (const id of ids) {
|
|
55
|
+
if (id !== undefined) await app.scope('commerce-member').model.address.deleteById(id);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
describe('addressOwnership.test.ts', () => {
|
|
60
|
+
it('denies anonymous Admin and Web Address actions', async () => {
|
|
50
61
|
await app.bean.executor.mockCtx(async () => {
|
|
51
62
|
for (const [method, path, options] of [
|
|
52
|
-
['post', actionPath, { body: createAddress('anonymous') }],
|
|
53
63
|
['get', actionPath, {}],
|
|
54
64
|
['get', `${actionPath}/:id`, { params: { id: 999999 } }],
|
|
55
|
-
['
|
|
56
|
-
['
|
|
65
|
+
['get', minePath, {}],
|
|
66
|
+
['get', viewMinePath, { params: { id: 999999 } }],
|
|
67
|
+
['post', createMinePath, { body: createAddress('anonymous') }],
|
|
68
|
+
['patch', updateMinePath, { params: { id: 999999 }, body: createAddress('anonymous') }],
|
|
69
|
+
['delete', deleteMinePath, { params: { id: 999999 } }],
|
|
57
70
|
] as const) {
|
|
58
71
|
const [_, err] = await catchError(() =>
|
|
59
72
|
app.bean.executor.performAction(method, path, { ...options, innerAccess: false }),
|
|
@@ -63,146 +76,174 @@ describe('address.test.ts', () => {
|
|
|
63
76
|
});
|
|
64
77
|
});
|
|
65
78
|
|
|
66
|
-
it('derives ownership from
|
|
67
|
-
await app.bean.executor.mockCtx(async () => {
|
|
68
|
-
const suffix = createTestId();
|
|
69
|
-
const customerA = await registerAndSignin(`address-a-${suffix}`);
|
|
70
|
-
const customerB = await registerAndSignin(`address-b-${suffix}`);
|
|
71
|
-
const addressData = createAddress(suffix);
|
|
72
|
-
const addressId = await performAs(customerA.token, 'post', actionPath, {
|
|
73
|
-
body: { ...addressData, userId: customerB.user.id, iid: 999999 } as any,
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const persisted = await app.scope('commerce-member').model.address.getById(addressId);
|
|
77
|
-
assert.equal(String(persisted?.userId), String(customerA.user.id));
|
|
78
|
-
assert.equal(persisted?.iid, app.ctx.instance.id);
|
|
79
|
-
|
|
80
|
-
const ownList = await performAs(customerA.token, 'get', actionPath);
|
|
81
|
-
assert.equal(
|
|
82
|
-
ownList.list.some(item => String(item.id) === String(addressId)),
|
|
83
|
-
true,
|
|
84
|
-
);
|
|
85
|
-
assert.equal(
|
|
86
|
-
ownList.list.every(item => !Object.hasOwn(item, 'userId')),
|
|
87
|
-
true,
|
|
88
|
-
);
|
|
89
|
-
assert.equal(
|
|
90
|
-
ownList.list.every(item => !Object.hasOwn(item, 'iid')),
|
|
91
|
-
true,
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
const update: DtoAddressUpdate = { ...addressData, city: 'Oakland', addressLine2: undefined };
|
|
95
|
-
assert.equal(
|
|
96
|
-
await performAs(customerA.token, 'patch', `${actionPath}/:id`, {
|
|
97
|
-
params: { id: addressId },
|
|
98
|
-
body: update,
|
|
99
|
-
}),
|
|
100
|
-
null,
|
|
101
|
-
);
|
|
102
|
-
const ownAddress: EntityAddress = await performAs(
|
|
103
|
-
customerA.token,
|
|
104
|
-
'get',
|
|
105
|
-
`${actionPath}/:id`,
|
|
106
|
-
{
|
|
107
|
-
params: { id: addressId },
|
|
108
|
-
},
|
|
109
|
-
);
|
|
110
|
-
assert.equal(ownAddress.city, update.city);
|
|
111
|
-
assert.equal(ownAddress.addressLine2, addressData.addressLine2);
|
|
112
|
-
assert.equal(Object.hasOwn(ownAddress, 'userId'), false);
|
|
113
|
-
assert.equal(Object.hasOwn(ownAddress, 'iid'), false);
|
|
114
|
-
|
|
115
|
-
const foreignList = await performAs(customerB.token, 'get', actionPath);
|
|
116
|
-
assert.equal(
|
|
117
|
-
foreignList.list.some(item => String(item.id) === String(addressId)),
|
|
118
|
-
false,
|
|
119
|
-
);
|
|
120
|
-
assert.equal(
|
|
121
|
-
await performAs(customerB.token, 'get', `${actionPath}/:id`, { params: { id: addressId } }),
|
|
122
|
-
undefined,
|
|
123
|
-
);
|
|
124
|
-
assert.equal(
|
|
125
|
-
await performAs(customerB.token, 'patch', `${actionPath}/:id`, {
|
|
126
|
-
params: { id: addressId },
|
|
127
|
-
body: { ...addressData, city: 'Los Angeles' },
|
|
128
|
-
}),
|
|
129
|
-
null,
|
|
130
|
-
);
|
|
131
|
-
assert.equal(
|
|
132
|
-
await performAs(customerB.token, 'delete', `${actionPath}/:id`, {
|
|
133
|
-
params: { id: addressId },
|
|
134
|
-
}),
|
|
135
|
-
null,
|
|
136
|
-
);
|
|
137
|
-
assert.equal(
|
|
138
|
-
(await app.scope('commerce-member').model.address.getById(addressId))?.city,
|
|
139
|
-
'Oakland',
|
|
140
|
-
);
|
|
141
|
-
|
|
142
|
-
assert.equal(
|
|
143
|
-
await performAs(customerA.token, 'delete', `${actionPath}/:id`, {
|
|
144
|
-
params: { id: addressId },
|
|
145
|
-
}),
|
|
146
|
-
null,
|
|
147
|
-
);
|
|
148
|
-
assert.equal(
|
|
149
|
-
await performAs(customerA.token, 'get', `${actionPath}/:id`, { params: { id: addressId } }),
|
|
150
|
-
undefined,
|
|
151
|
-
);
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it('treats another instance address as absent', async () => {
|
|
156
|
-
let addressId!: number;
|
|
157
|
-
let customerDefault!: Awaited<ReturnType<typeof registerAndSignin>>;
|
|
158
|
-
const addressDefault = createAddress('default');
|
|
79
|
+
it('derives Web ownership from Passport and treats foreign rows as absent', async () => {
|
|
159
80
|
await app.bean.executor.mockCtx(async () => {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
81
|
+
let addressId: number | undefined;
|
|
82
|
+
try {
|
|
83
|
+
const suffix = createTestId();
|
|
84
|
+
const customerA = await registerAndSignin(`address-a-${suffix}`);
|
|
85
|
+
const customerB = await registerAndSignin(`address-b-${suffix}`);
|
|
86
|
+
const addressData = createAddress(suffix);
|
|
87
|
+
addressId = await performAs(customerA.token, 'post', createMinePath, {
|
|
88
|
+
body: { ...addressData, userId: customerB.user.id, iid: 999999 } as any,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const persisted = await app.scope('commerce-member').model.address.getById(addressId);
|
|
92
|
+
assert.equal(String(persisted?.userId), String(customerA.user.id));
|
|
93
|
+
assert.equal(persisted?.iid, app.ctx.instance.id);
|
|
94
|
+
|
|
95
|
+
const ownList = await performAs(customerA.token, 'get', minePath);
|
|
96
|
+
assert.equal(
|
|
97
|
+
ownList.list.some(item => String(item.id) === String(addressId)),
|
|
98
|
+
true,
|
|
99
|
+
);
|
|
100
|
+
assert.equal(
|
|
101
|
+
ownList.list.every(item => !Object.hasOwn(item, 'userId')),
|
|
102
|
+
true,
|
|
103
|
+
);
|
|
104
|
+
assert.equal(
|
|
105
|
+
ownList.list.every(item => !Object.hasOwn(item, 'iid')),
|
|
106
|
+
true,
|
|
107
|
+
);
|
|
165
108
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
109
|
+
const { addressLine2: _, ...update } = {
|
|
110
|
+
...addressData,
|
|
111
|
+
city: 'Oakland',
|
|
112
|
+
} satisfies DtoAddressMineUpdate;
|
|
169
113
|
assert.equal(
|
|
170
|
-
await performAs(
|
|
114
|
+
await performAs(customerA.token, 'patch', updateMinePath, {
|
|
171
115
|
params: { id: addressId },
|
|
116
|
+
body: update,
|
|
172
117
|
}),
|
|
173
|
-
|
|
118
|
+
null,
|
|
174
119
|
);
|
|
175
|
-
const
|
|
120
|
+
const ownAddress: EntityAddress = await performAs(customerA.token, 'get', viewMinePath, {
|
|
121
|
+
params: { id: addressId },
|
|
122
|
+
});
|
|
123
|
+
assert.equal(ownAddress.city, update.city);
|
|
124
|
+
assert.equal(ownAddress.addressLine2, addressData.addressLine2);
|
|
125
|
+
assert.equal(Object.hasOwn(ownAddress, 'userId'), false);
|
|
126
|
+
assert.equal(Object.hasOwn(ownAddress, 'iid'), false);
|
|
127
|
+
|
|
128
|
+
const foreignList = await performAs(customerB.token, 'get', minePath);
|
|
176
129
|
assert.equal(
|
|
177
|
-
|
|
130
|
+
foreignList.list.some(item => String(item.id) === String(addressId)),
|
|
178
131
|
false,
|
|
179
132
|
);
|
|
180
133
|
assert.equal(
|
|
181
|
-
await performAs(
|
|
134
|
+
await performAs(customerB.token, 'get', viewMinePath, { params: { id: addressId } }),
|
|
135
|
+
undefined,
|
|
136
|
+
);
|
|
137
|
+
assert.equal(
|
|
138
|
+
await performAs(customerB.token, 'patch', updateMinePath, {
|
|
182
139
|
params: { id: addressId },
|
|
183
|
-
body: { ...
|
|
140
|
+
body: { ...addressData, city: 'Los Angeles' },
|
|
184
141
|
}),
|
|
185
142
|
null,
|
|
186
143
|
);
|
|
187
144
|
assert.equal(
|
|
188
|
-
await performAs(
|
|
189
|
-
params: { id: addressId },
|
|
190
|
-
}),
|
|
145
|
+
await performAs(customerB.token, 'delete', deleteMinePath, { params: { id: addressId } }),
|
|
191
146
|
null,
|
|
192
147
|
);
|
|
193
148
|
assert.equal(
|
|
194
|
-
await app.scope('commerce-member').model.address.getById(addressId),
|
|
195
|
-
|
|
149
|
+
(await app.scope('commerce-member').model.address.getById(addressId))?.city,
|
|
150
|
+
'Oakland',
|
|
196
151
|
);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
|
|
152
|
+
} finally {
|
|
153
|
+
await deleteOwnedAddresses([addressId]);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
});
|
|
200
157
|
|
|
158
|
+
it('exposes active-instance Address inspection only to systemAdmin', async () => {
|
|
201
159
|
await app.bean.executor.mockCtx(async () => {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
160
|
+
let addressId: number | undefined;
|
|
161
|
+
try {
|
|
162
|
+
const suffix = createTestId();
|
|
163
|
+
const customer = await registerAndSignin(`address-admin-${suffix}`);
|
|
164
|
+
addressId = await performAs(customer.token, 'post', createMinePath, {
|
|
165
|
+
body: createAddress(suffix),
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const [_, nonAdminError] = await catchError(() =>
|
|
169
|
+
performAs(customer.token, 'get', actionPath),
|
|
170
|
+
);
|
|
171
|
+
assert.equal(nonAdminError?.code, 403);
|
|
172
|
+
|
|
173
|
+
const admin = await app.bean.passport.signinMock();
|
|
174
|
+
const list = await performAs(admin.accessToken, 'get', actionPath);
|
|
175
|
+
assert.equal(
|
|
176
|
+
list.list.some(item => String(item.id) === String(addressId)),
|
|
177
|
+
true,
|
|
178
|
+
);
|
|
179
|
+
const address = await performAs(admin.accessToken, 'get', `${actionPath}/:id`, {
|
|
180
|
+
params: { id: addressId },
|
|
181
|
+
});
|
|
182
|
+
assert.equal(address?.id, addressId);
|
|
183
|
+
|
|
184
|
+
const permissions = await Promise.all(
|
|
185
|
+
['create', 'update', 'delete'].map(action =>
|
|
186
|
+
app.bean.permission.retrievePermissionAction('commerce-member:address', action),
|
|
187
|
+
),
|
|
188
|
+
);
|
|
189
|
+
assert.deepEqual(permissions, [false, false, false]);
|
|
190
|
+
} finally {
|
|
191
|
+
await deleteOwnedAddresses([addressId]);
|
|
192
|
+
}
|
|
206
193
|
});
|
|
207
194
|
});
|
|
195
|
+
|
|
196
|
+
it('treats another instance Address as absent on Web actions', async () => {
|
|
197
|
+
let addressId: number | undefined;
|
|
198
|
+
let customerDefault!: Awaited<ReturnType<typeof registerAndSignin>>;
|
|
199
|
+
const addressDefault = createAddress('default');
|
|
200
|
+
try {
|
|
201
|
+
await app.bean.executor.mockCtx(async () => {
|
|
202
|
+
customerDefault = await registerAndSignin(`address-default-${createTestId()}`);
|
|
203
|
+
addressId = await performAs(customerDefault.token, 'post', createMinePath, {
|
|
204
|
+
body: addressDefault,
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
await app.bean.executor.mockCtx(
|
|
209
|
+
async () => {
|
|
210
|
+
const customer = await registerAndSignin(`address-share-${createTestId()}`);
|
|
211
|
+
assert.equal(
|
|
212
|
+
await performAs(customer.token, 'get', viewMinePath, { params: { id: addressId } }),
|
|
213
|
+
undefined,
|
|
214
|
+
);
|
|
215
|
+
const list = await performAs(customer.token, 'get', minePath);
|
|
216
|
+
assert.equal(
|
|
217
|
+
list.list.some(item => String(item.id) === String(addressId)),
|
|
218
|
+
false,
|
|
219
|
+
);
|
|
220
|
+
assert.equal(
|
|
221
|
+
await performAs(customer.token, 'patch', updateMinePath, {
|
|
222
|
+
params: { id: addressId },
|
|
223
|
+
body: { ...createAddress('foreign'), city: 'Other city' },
|
|
224
|
+
}),
|
|
225
|
+
null,
|
|
226
|
+
);
|
|
227
|
+
assert.equal(
|
|
228
|
+
await performAs(customer.token, 'delete', deleteMinePath, {
|
|
229
|
+
params: { id: addressId },
|
|
230
|
+
}),
|
|
231
|
+
null,
|
|
232
|
+
);
|
|
233
|
+
},
|
|
234
|
+
{ instanceName: 'shareTest' as any },
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
await app.bean.executor.mockCtx(async () => {
|
|
238
|
+
const address = await performAs(customerDefault.token, 'get', viewMinePath, {
|
|
239
|
+
params: { id: addressId },
|
|
240
|
+
});
|
|
241
|
+
assert.equal(address.city, addressDefault.city);
|
|
242
|
+
});
|
|
243
|
+
} finally {
|
|
244
|
+
await app.bean.executor.mockCtx(async () => {
|
|
245
|
+
await deleteOwnedAddresses([addressId]);
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
});
|
|
208
249
|
});
|
|
@@ -4,12 +4,15 @@ import type { TypeEntityOptionsFields } from 'vona-module-a-openapi';
|
|
|
4
4
|
import type { TableIdentity } from 'table-identity';
|
|
5
5
|
/** entity: begin */
|
|
6
6
|
export * from '../entity/paymentAttempt.tsx';
|
|
7
|
+
export * from '../entity/paymentAudit.tsx';
|
|
7
8
|
import type { IEntityOptionsPaymentAttempt } from '../entity/paymentAttempt.tsx';
|
|
9
|
+
import type { IEntityOptionsPaymentAudit } from '../entity/paymentAudit.tsx';
|
|
8
10
|
import 'vona-module-a-orm';
|
|
9
11
|
declare module 'vona-module-a-orm' {
|
|
10
12
|
|
|
11
13
|
export interface IEntityRecord {
|
|
12
14
|
'commerce-payment:paymentAttempt': IEntityOptionsPaymentAttempt;
|
|
15
|
+
'commerce-payment:paymentAudit': IEntityOptionsPaymentAudit;
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
|
|
@@ -20,16 +23,21 @@ declare module 'vona-module-commerce-payment' {
|
|
|
20
23
|
/** entity: end */
|
|
21
24
|
/** entity: begin */
|
|
22
25
|
import type { EntityPaymentAttempt } from '../entity/paymentAttempt.tsx';
|
|
26
|
+
import type { EntityPaymentAudit } from '../entity/paymentAudit.tsx';
|
|
23
27
|
export interface IModuleEntity {
|
|
24
28
|
'paymentAttempt': EntityPaymentAttemptMeta;
|
|
29
|
+
'paymentAudit': EntityPaymentAuditMeta;
|
|
25
30
|
}
|
|
26
31
|
/** entity: end */
|
|
27
32
|
/** entity: begin */
|
|
28
33
|
export type EntityPaymentAttemptTableName = 'commercePaymentAttempt';
|
|
34
|
+
export type EntityPaymentAuditTableName = 'commercePaymentAudit';
|
|
29
35
|
export type EntityPaymentAttemptMeta=TypeEntityMeta<EntityPaymentAttempt,EntityPaymentAttemptTableName>;
|
|
36
|
+
export type EntityPaymentAuditMeta=TypeEntityMeta<EntityPaymentAudit,EntityPaymentAuditTableName>;
|
|
30
37
|
declare module 'vona-module-a-orm' {
|
|
31
38
|
export interface ITableRecord {
|
|
32
39
|
'commercePaymentAttempt': EntityPaymentAttemptMeta;
|
|
40
|
+
'commercePaymentAudit': EntityPaymentAuditMeta;
|
|
33
41
|
}
|
|
34
42
|
}
|
|
35
43
|
declare module 'vona-module-commerce-payment' {
|
|
@@ -37,16 +45,23 @@ declare module 'vona-module-commerce-payment' {
|
|
|
37
45
|
export interface IEntityOptionsPaymentAttempt {
|
|
38
46
|
fields?: TypeEntityOptionsFields<EntityPaymentAttempt, IEntityOptionsPaymentAttempt[TypeSymbolKeyFieldsMore]>;
|
|
39
47
|
}
|
|
48
|
+
|
|
49
|
+
export interface IEntityOptionsPaymentAudit {
|
|
50
|
+
fields?: TypeEntityOptionsFields<EntityPaymentAudit, IEntityOptionsPaymentAudit[TypeSymbolKeyFieldsMore]>;
|
|
51
|
+
}
|
|
40
52
|
}
|
|
41
53
|
/** entity: end */
|
|
42
54
|
/** model: begin */
|
|
43
55
|
export * from '../model/paymentAttempt.ts';
|
|
56
|
+
export * from '../model/paymentAudit.ts';
|
|
44
57
|
import type { IModelOptionsPaymentAttempt } from '../model/paymentAttempt.ts';
|
|
58
|
+
import type { IModelOptionsPaymentAudit } from '../model/paymentAudit.ts';
|
|
45
59
|
import 'vona-module-a-orm';
|
|
46
60
|
declare module 'vona-module-a-orm' {
|
|
47
61
|
|
|
48
62
|
export interface IModelRecord {
|
|
49
63
|
'commerce-payment:paymentAttempt': IModelOptionsPaymentAttempt;
|
|
64
|
+
'commerce-payment:paymentAudit': IModelOptionsPaymentAudit;
|
|
50
65
|
}
|
|
51
66
|
|
|
52
67
|
|
|
@@ -62,13 +77,26 @@ declare module 'vona-module-commerce-payment' {
|
|
|
62
77
|
get $beanFullName(): 'commerce-payment.model.paymentAttempt';
|
|
63
78
|
get $onionName(): 'commerce-payment:paymentAttempt';
|
|
64
79
|
get $onionOptions(): IModelOptionsPaymentAttempt;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface ModelPaymentAudit {
|
|
83
|
+
/** @internal */
|
|
84
|
+
get scope(): ScopeModuleCommercePayment;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface ModelPaymentAudit {
|
|
88
|
+
get $beanFullName(): 'commerce-payment.model.paymentAudit';
|
|
89
|
+
get $onionName(): 'commerce-payment:paymentAudit';
|
|
90
|
+
get $onionOptions(): IModelOptionsPaymentAudit;
|
|
65
91
|
}
|
|
66
92
|
}
|
|
67
93
|
/** model: end */
|
|
68
94
|
/** model: begin */
|
|
69
95
|
import type { ModelPaymentAttempt } from '../model/paymentAttempt.ts';
|
|
96
|
+
import type { ModelPaymentAudit } from '../model/paymentAudit.ts';
|
|
70
97
|
export interface IModuleModel {
|
|
71
98
|
'paymentAttempt': ModelPaymentAttempt;
|
|
99
|
+
'paymentAudit': ModelPaymentAudit;
|
|
72
100
|
}
|
|
73
101
|
/** model: end */
|
|
74
102
|
/** model: begin */
|
|
@@ -77,6 +105,7 @@ import 'vona';
|
|
|
77
105
|
declare module 'vona' {
|
|
78
106
|
export interface IBeanRecordGeneral {
|
|
79
107
|
'commerce-payment.model.paymentAttempt': ModelPaymentAttempt;
|
|
108
|
+
'commerce-payment.model.paymentAudit': ModelPaymentAudit;
|
|
80
109
|
}
|
|
81
110
|
}
|
|
82
111
|
/** model: end */
|
|
@@ -112,27 +141,68 @@ declare module 'vona-module-commerce-payment' {
|
|
|
112
141
|
updateById<T extends IModelUpdateOptions<EntityPaymentAttempt,ModelPaymentAttempt>>(id: TableIdentity, data: TypeModelMutateRelationData<EntityPaymentAttempt,ModelPaymentAttempt, T>, options?: T): Promise<TypeModelMutateRelationData<EntityPaymentAttempt,ModelPaymentAttempt, T>>;
|
|
113
142
|
deleteById<T extends IModelDeleteOptions<EntityPaymentAttempt,ModelPaymentAttempt>>(id: TableIdentity, options?: T): Promise<void>;
|
|
114
143
|
}
|
|
144
|
+
export interface ModelPaymentAudit {
|
|
145
|
+
[SymbolKeyEntity]: EntityPaymentAudit;
|
|
146
|
+
[SymbolKeyEntityMeta]: EntityPaymentAuditMeta;
|
|
147
|
+
[SymbolKeyModelOptions]: IModelOptionsPaymentAudit;
|
|
148
|
+
get<T extends IModelGetOptions<EntityPaymentAudit,ModelPaymentAudit>>(where: TypeModelWhere<EntityPaymentAudit>, options?: T): Promise<TypeModelRelationResult<EntityPaymentAudit, ModelPaymentAudit, T> | undefined>;
|
|
149
|
+
getForUpdate<T extends IModelGetOptions<EntityPaymentAudit,ModelPaymentAudit>>(where: TypeModelWhere<EntityPaymentAudit>, options?: T): Promise<TypeModelRelationResult<EntityPaymentAudit, ModelPaymentAudit, T> | undefined>;
|
|
150
|
+
getByIdForUpdate<T extends IModelGetOptions<EntityPaymentAudit,ModelPaymentAudit>>(id: TableIdentity, options?: T): Promise<TypeModelRelationResult<EntityPaymentAudit, ModelPaymentAudit, T> | undefined>;
|
|
151
|
+
mget<T extends IModelGetOptions<EntityPaymentAudit,ModelPaymentAudit>>(ids: TableIdentity[], options?: T): Promise<TypeModelRelationResult<EntityPaymentAudit, ModelPaymentAudit, T>[]>;
|
|
152
|
+
selectAndCount<T extends IModelSelectParams<EntityPaymentAudit,ModelPaymentAudit,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelSelectAndCount<EntityPaymentAudit, ModelPaymentAudit, T>>;
|
|
153
|
+
select<T extends IModelSelectParams<EntityPaymentAudit,ModelPaymentAudit,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelRelationResult<EntityPaymentAudit, ModelPaymentAudit, T>[]>;
|
|
154
|
+
insert<T extends IModelInsertOptions<EntityPaymentAudit,ModelPaymentAudit>>(data?: TypeModelMutateRelationData<EntityPaymentAudit,ModelPaymentAudit, T>, options?: T): Promise<TypeModelMutateRelationData<EntityPaymentAudit,ModelPaymentAudit, T, true>>;
|
|
155
|
+
insertBulk<T extends IModelInsertOptions<EntityPaymentAudit,ModelPaymentAudit>>(items: TypeModelMutateRelationData<EntityPaymentAudit,ModelPaymentAudit, T>[], options?: T): Promise<TypeModelMutateRelationData<EntityPaymentAudit,ModelPaymentAudit, T, true>[]>;
|
|
156
|
+
update<T extends IModelUpdateOptions<EntityPaymentAudit,ModelPaymentAudit>>(data: TypeModelMutateRelationData<EntityPaymentAudit,ModelPaymentAudit, T>, options?: T): Promise<TypeModelMutateRelationData<EntityPaymentAudit,ModelPaymentAudit, T>>;
|
|
157
|
+
updateBulk<T extends IModelUpdateOptions<EntityPaymentAudit,ModelPaymentAudit>>(items: TypeModelMutateRelationData<EntityPaymentAudit,ModelPaymentAudit, T>[], options?: T): Promise<TypeModelMutateRelationData<EntityPaymentAudit,ModelPaymentAudit, T>[]>;
|
|
158
|
+
delete<T extends IModelDeleteOptions<EntityPaymentAudit,ModelPaymentAudit>>(where?: TypeModelWhere<EntityPaymentAudit>, options?: T): Promise<void>;
|
|
159
|
+
deleteBulk<T extends IModelDeleteOptions<EntityPaymentAudit,ModelPaymentAudit>>(ids: TableIdentity[], options?: T): Promise<void>;
|
|
160
|
+
mutate<T extends IModelMutateOptions<EntityPaymentAudit,ModelPaymentAudit>>(data?: TypeModelMutateRelationData<EntityPaymentAudit,ModelPaymentAudit, T>, options?: T): Promise<TypeModelMutateRelationData<EntityPaymentAudit,ModelPaymentAudit, T>>;
|
|
161
|
+
mutateBulk<T extends IModelMutateOptions<EntityPaymentAudit,ModelPaymentAudit>>(items: TypeModelMutateRelationData<EntityPaymentAudit,ModelPaymentAudit, T>[], options?: T): Promise<TypeModelMutateRelationData<EntityPaymentAudit,ModelPaymentAudit, T>[]>;
|
|
162
|
+
count<T extends IModelSelectCountParams<EntityPaymentAudit,ModelPaymentAudit,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<string | undefined>;
|
|
163
|
+
increment<T extends IModelIncrementParams<EntityPaymentAudit,ModelPaymentAudit,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<number>;
|
|
164
|
+
decrement<T extends IModelIncrementParams<EntityPaymentAudit,ModelPaymentAudit,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<number>;
|
|
165
|
+
aggregate<T extends IModelSelectAggrParams<EntityPaymentAudit,ModelPaymentAudit,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelAggrRelationResult<T>>;
|
|
166
|
+
group<T extends IModelSelectGroupParams<EntityPaymentAudit,ModelPaymentAudit,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelGroupRelationResult<EntityPaymentAudit, T>[]>;
|
|
167
|
+
getById<T extends IModelGetOptions<EntityPaymentAudit,ModelPaymentAudit>>(id: TableIdentity, options?: T): Promise<TypeModelRelationResult<EntityPaymentAudit, ModelPaymentAudit, T> | undefined>;
|
|
168
|
+
updateById<T extends IModelUpdateOptions<EntityPaymentAudit,ModelPaymentAudit>>(id: TableIdentity, data: TypeModelMutateRelationData<EntityPaymentAudit,ModelPaymentAudit, T>, options?: T): Promise<TypeModelMutateRelationData<EntityPaymentAudit,ModelPaymentAudit, T>>;
|
|
169
|
+
deleteById<T extends IModelDeleteOptions<EntityPaymentAudit,ModelPaymentAudit>>(id: TableIdentity, options?: T): Promise<void>;
|
|
170
|
+
}
|
|
115
171
|
}
|
|
116
172
|
declare module 'vona-module-a-orm' {
|
|
117
173
|
export interface IModelClassRecord {
|
|
118
174
|
'commerce-payment:paymentAttempt': ModelPaymentAttempt;
|
|
175
|
+
'commerce-payment:paymentAudit': ModelPaymentAudit;
|
|
119
176
|
}
|
|
120
177
|
}
|
|
121
178
|
/** model: end */
|
|
122
179
|
/** service: begin */
|
|
180
|
+
export * from '../service/mockPaymentAdapter.ts';
|
|
123
181
|
export * from '../service/paymentAttempt.ts';
|
|
124
182
|
|
|
125
183
|
import 'vona-module-a-bean';
|
|
126
184
|
declare module 'vona-module-a-bean' {
|
|
127
185
|
|
|
128
186
|
export interface IServiceRecord {
|
|
129
|
-
'commerce-payment:
|
|
187
|
+
'commerce-payment:mockPaymentAdapter': never;
|
|
188
|
+
'commerce-payment:paymentAttempt': never;
|
|
130
189
|
}
|
|
131
190
|
|
|
132
191
|
|
|
133
192
|
}
|
|
134
193
|
declare module 'vona-module-commerce-payment' {
|
|
135
194
|
|
|
195
|
+
export interface ServiceMockPaymentAdapter {
|
|
196
|
+
/** @internal */
|
|
197
|
+
get scope(): ScopeModuleCommercePayment;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export interface ServiceMockPaymentAdapter {
|
|
201
|
+
get $beanFullName(): 'commerce-payment.service.mockPaymentAdapter';
|
|
202
|
+
get $onionName(): 'commerce-payment:mockPaymentAdapter';
|
|
203
|
+
|
|
204
|
+
}
|
|
205
|
+
|
|
136
206
|
export interface ServicePaymentAttempt {
|
|
137
207
|
/** @internal */
|
|
138
208
|
get scope(): ScopeModuleCommercePayment;
|
|
@@ -146,9 +216,11 @@ declare module 'vona-module-commerce-payment' {
|
|
|
146
216
|
}
|
|
147
217
|
/** service: end */
|
|
148
218
|
/** service: begin */
|
|
219
|
+
import type { ServiceMockPaymentAdapter } from '../service/mockPaymentAdapter.ts';
|
|
149
220
|
import type { ServicePaymentAttempt } from '../service/paymentAttempt.ts';
|
|
150
221
|
export interface IModuleService {
|
|
151
|
-
'
|
|
222
|
+
'mockPaymentAdapter': ServiceMockPaymentAdapter;
|
|
223
|
+
'paymentAttempt': ServicePaymentAttempt;
|
|
152
224
|
}
|
|
153
225
|
/** service: end */
|
|
154
226
|
/** service: begin */
|
|
@@ -156,7 +228,8 @@ export interface IModuleService {
|
|
|
156
228
|
import 'vona';
|
|
157
229
|
declare module 'vona' {
|
|
158
230
|
export interface IBeanRecordGeneral {
|
|
159
|
-
'commerce-payment.service.
|
|
231
|
+
'commerce-payment.service.mockPaymentAdapter': ServiceMockPaymentAdapter;
|
|
232
|
+
'commerce-payment.service.paymentAttempt': ServicePaymentAttempt;
|
|
160
233
|
}
|
|
161
234
|
}
|
|
162
235
|
/** service: end */
|
|
@@ -10,6 +10,9 @@ import { $tableColumns } from 'vona-module-a-ormutils';
|
|
|
10
10
|
...$tableColumns('commercePaymentAttempt', 'userId'),
|
|
11
11
|
...$tableColumns('commercePaymentAttempt', 'state'),
|
|
12
12
|
...$tableColumns('commercePaymentAttempt', 'correlationId'),
|
|
13
|
+
...$tableColumns('commercePaymentAudit', 'paymentAttemptId'),
|
|
14
|
+
...$tableColumns('commercePaymentAudit', 'orderId'),
|
|
15
|
+
...$tableColumns('commercePaymentAudit', 'idempotencyKey'),
|
|
13
16
|
},
|
|
14
17
|
})
|
|
15
18
|
export class MetaIndex extends BeanBase {}
|
|
@@ -26,10 +26,47 @@ export class MetaVersion extends BeanBase implements IMetaVersionUpdate {
|
|
|
26
26
|
table
|
|
27
27
|
.string(entityPaymentAttempt.correlationId, 100)
|
|
28
28
|
.comment(entityPaymentAttempt.$comment.correlationId);
|
|
29
|
+
table
|
|
30
|
+
.dateTime(entityPaymentAttempt.finalizedAt)
|
|
31
|
+
.nullable()
|
|
32
|
+
.comment(entityPaymentAttempt.$comment.finalizedAt);
|
|
29
33
|
table
|
|
30
34
|
.dateTime(entityPaymentAttempt.cancelledAt)
|
|
31
35
|
.nullable()
|
|
32
36
|
.comment(entityPaymentAttempt.$comment.cancelledAt);
|
|
33
37
|
});
|
|
38
|
+
|
|
39
|
+
const entityPaymentAudit = this.scope.entity.paymentAudit;
|
|
40
|
+
await this.bean.model.createTable(entityPaymentAudit.$table, table => {
|
|
41
|
+
table.comment(entityPaymentAudit.$comment.$table);
|
|
42
|
+
table.basicFields();
|
|
43
|
+
table
|
|
44
|
+
.tableIdentity(entityPaymentAudit.paymentAttemptId)
|
|
45
|
+
.comment(entityPaymentAudit.$comment.paymentAttemptId);
|
|
46
|
+
table.tableIdentity(entityPaymentAudit.orderId).comment(entityPaymentAudit.$comment.orderId);
|
|
47
|
+
table.userId(entityPaymentAudit.userId).comment(entityPaymentAudit.$comment.userId);
|
|
48
|
+
table.string(entityPaymentAudit.provider, 20).comment(entityPaymentAudit.$comment.provider);
|
|
49
|
+
table.string(entityPaymentAudit.outcome, 20).comment(entityPaymentAudit.$comment.outcome);
|
|
50
|
+
table
|
|
51
|
+
.string(entityPaymentAudit.fromAttemptState, 20)
|
|
52
|
+
.comment(entityPaymentAudit.$comment.fromAttemptState);
|
|
53
|
+
table
|
|
54
|
+
.string(entityPaymentAudit.toOrderState, 30)
|
|
55
|
+
.comment(entityPaymentAudit.$comment.toOrderState);
|
|
56
|
+
table
|
|
57
|
+
.string(entityPaymentAudit.idempotencyKey, 100)
|
|
58
|
+
.comment(entityPaymentAudit.$comment.idempotencyKey);
|
|
59
|
+
table
|
|
60
|
+
.string(entityPaymentAudit.correlationId, 100)
|
|
61
|
+
.comment(entityPaymentAudit.$comment.correlationId);
|
|
62
|
+
table.string(entityPaymentAudit.reason, 255).comment(entityPaymentAudit.$comment.reason);
|
|
63
|
+
table
|
|
64
|
+
.userId(entityPaymentAudit.actorId)
|
|
65
|
+
.nullable()
|
|
66
|
+
.comment(entityPaymentAudit.$comment.actorId);
|
|
67
|
+
table
|
|
68
|
+
.dateTime(entityPaymentAudit.processedAt)
|
|
69
|
+
.comment(entityPaymentAudit.$comment.processedAt);
|
|
70
|
+
});
|
|
34
71
|
}
|
|
35
72
|
}
|
|
@@ -15,8 +15,8 @@ export class DtoPaymentAttemptView {
|
|
|
15
15
|
@Api.field(v.tableIdentity())
|
|
16
16
|
orderId: TableIdentity;
|
|
17
17
|
|
|
18
|
-
@Api.field(z.enum(['created', 'cancelled']))
|
|
19
|
-
state: 'created' | 'cancelled';
|
|
18
|
+
@Api.field(z.enum(['created', 'succeeded', 'failed', 'cancelled']))
|
|
19
|
+
state: 'created' | 'succeeded' | 'failed' | 'cancelled';
|
|
20
20
|
|
|
21
21
|
@Api.field(z.literal('USD'))
|
|
22
22
|
currency: 'USD';
|
|
@@ -5,7 +5,7 @@ import { Api, v } from 'vona-module-a-openapiutils';
|
|
|
5
5
|
import { Entity, EntityBase } from 'vona-module-a-orm';
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
|
|
8
|
-
export type TypePaymentAttemptState = 'created' | 'cancelled';
|
|
8
|
+
export type TypePaymentAttemptState = 'created' | 'succeeded' | 'failed' | 'cancelled';
|
|
9
9
|
|
|
10
10
|
export interface IEntityOptionsPaymentAttempt extends IDecoratorEntityOptions {}
|
|
11
11
|
|
|
@@ -17,7 +17,7 @@ export class EntityPaymentAttempt extends EntityBase {
|
|
|
17
17
|
@Api.field(v.tableIdentity())
|
|
18
18
|
userId: TableIdentity;
|
|
19
19
|
|
|
20
|
-
@Api.field(z.enum(['created', 'cancelled']))
|
|
20
|
+
@Api.field(z.enum(['created', 'succeeded', 'failed', 'cancelled']))
|
|
21
21
|
state: TypePaymentAttemptState;
|
|
22
22
|
|
|
23
23
|
@Api.field(z.literal('USD'))
|
|
@@ -29,6 +29,9 @@ export class EntityPaymentAttempt extends EntityBase {
|
|
|
29
29
|
@Api.field(v.required(), v.min(1), v.max(100))
|
|
30
30
|
correlationId: string;
|
|
31
31
|
|
|
32
|
+
@Api.field(v.optional())
|
|
33
|
+
finalizedAt?: Date;
|
|
34
|
+
|
|
32
35
|
@Api.field(v.optional())
|
|
33
36
|
cancelledAt?: Date;
|
|
34
37
|
}
|