cabloy 5.1.122 → 5.1.124
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-frontend-scaffold/SKILL.md +13 -3
- package/.claude/skills/cabloy-workflow/SKILL.md +6 -0
- package/.claude/skills/cabloy-workflow/evals/evals.json +6 -0
- package/CHANGELOG.md +24 -0
- package/CLAUDE.md +1 -1
- package/cabloy-docs/.vitepress/config.mjs +4 -0
- package/cabloy-docs/frontend/form-layout-guide.md +29 -7
- package/cabloy-docs/fullstack/parallel-worktree-environment.md +87 -0
- package/e2e/scripts/e2e.ts +13 -1
- package/e2e/scripts/startE2eVona.ts +4 -1
- package/e2e/specs/a-commerce/commerce.spec.ts +129 -32
- package/package.json +2 -1
- package/playwright-report/data/24ac790ec112339c76cfb0c8e2c2539c2f953a0b.zip +0 -0
- package/playwright-report/data/2fddcabcdbd0b695061a565acfff243cb3a4f5e3.zip +0 -0
- package/playwright-report/data/4738038d9e861d63fd25937c9a3570934786a62f.zip +0 -0
- package/playwright-report/data/72f99c7da67c7f6ea53cab7d8681798b70d79a10.md +222 -0
- package/playwright-report/data/7b9684a7c793e9798b898f8ff50177b660a7a733.md +222 -0
- package/playwright-report/data/8b31595f5f1cc9d23863af51a592e6b90dcbc4ce.zip +0 -0
- package/playwright-report/data/95b578407a68806202dda917a61c50c750bd285b.md +222 -0
- package/playwright-report/data/ad960b3a58f224f5b4cad04a24067600064ffb7b.md +222 -0
- package/playwright-report/index.html +90 -0
- package/playwright-report/trace/assets/codeMirrorModule-LEHpjmcn.js +32 -0
- package/playwright-report/trace/assets/defaultSettingsView-BNmKHKpQ.js +264 -0
- package/playwright-report/trace/assets/urlMatch-BYQrIQwR.js +1 -0
- package/playwright-report/trace/codeMirrorModule.DYBRYzYX.css +1 -0
- package/playwright-report/trace/codicon.DCmgc-ay.ttf +0 -0
- package/playwright-report/trace/defaultSettingsView.CjdS-WJx.css +1 -0
- package/playwright-report/trace/index.CzXZzn5A.css +1 -0
- package/playwright-report/trace/index.DMMX1gXU.js +2 -0
- package/playwright-report/trace/index.html +44 -0
- package/playwright-report/trace/manifest.webmanifest +16 -0
- package/playwright-report/trace/playwright-logo.svg +9 -0
- package/playwright-report/trace/snapshot.html +10 -0
- package/playwright-report/trace/snapshot.v8KI4P3m.js +2 -0
- package/playwright-report/trace/sw.bundle.js +5 -0
- package/playwright-report/trace/uiMode.BZQ54Kgt.css +1 -0
- package/playwright-report/trace/uiMode.Ut8wwJNp.js +6 -0
- package/playwright-report/trace/uiMode.html +18 -0
- package/playwright-report/trace/xtermModule.DYP7pi_n.css +32 -0
- package/vona/env/.env +12 -0
- package/vona/env/.env.test +7 -0
- package/vona/packages-cli/cli/package.json +1 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/src/dto/{{resourceName}}Create.tsx_ +19 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/src/dto/{{resourceName}}Update.tsx_ +19 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/src/dto/{{resourceName}}View.tsx_ +19 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/snippets/3-en-us.ts +6 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/snippets/4-zh-cn.ts +6 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/dto/{{resourceName}}Create.tsx_ +19 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/dto/{{resourceName}}Update.tsx_ +19 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/dto/{{resourceName}}View.tsx_ +19 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/snippets/3-en-us.ts +6 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/snippets/4-zh-cn.ts +6 -1
- package/vona/packages-cli/cli-set-api/package.json +1 -1
- package/vona/pnpm-lock.yaml +255 -12
- package/vona/pnpm-workspace.yaml +1 -1
- package/vona/src/suite/a-commerce/modules/commerce-payment/package.json +4 -1
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/.metadata/index.ts +45 -3
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/bean/meta.index.ts +1 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/bean/meta.version.ts +25 -1
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/bean/payScene.commerceOrder.ts +20 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/entity/paymentAttempt.tsx +9 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/entity/paymentAudit.tsx +5 -2
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/entity/refundAttempt.tsx +6 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/index.ts +2 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/lib/index.ts +1 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/service/commercePayScene.ts +54 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/service/paymentAttempt.ts +7 -1
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/types/index.ts +1 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/test/paymentAttempt.test.ts +21 -0
- package/vona/src/suite/a-commerce/modules/commerce-promotion/src/.metadata/index.ts +30 -0
- package/vona/src/suite/a-commerce/modules/commerce-promotion/src/config/locale/en-us.ts +4 -0
- package/vona/src/suite/a-commerce/modules/commerce-promotion/src/config/locale/zh-cn.ts +4 -0
- package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateCreate.tsx +88 -1
- package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateUpdate.tsx +44 -1
- package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateView.tsx +72 -1
- package/vona/src/suite/a-commerce/modules/commerce-promotion/test/couponTemplateFormLayout.test.ts +121 -0
- package/vona/src/suite/a-commerce/modules/commerce-siteweb/src/bean/ssrMenu.home.ts +4 -1
- package/vona/src/suite/a-commerce/modules/commerce-trade/package.json +4 -1
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +0 -21
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/checkoutResult.tsx +3 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/order.ts +79 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/orderSnapshot.test.ts +227 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/paymentOutcome.test.ts +121 -13
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/refundLifecycle.test.ts +312 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/package.json +76 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/index.ts +842 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/this.ts +2 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/bean.payProvider.ts +92 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/bean.payScene.ts +105 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/meta.index.ts +28 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/meta.redlock.ts +11 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/meta.version.ts +113 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/queue.outboxDispatch.ts +31 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/schedule.outboxDispatch.ts +11 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/controller/paymentSession.ts +55 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/controller/webhook.ts +47 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/dto/paymentSessionStart.tsx +8 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/dto/paymentSessionView.tsx +69 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/dto/webhookReceipt.tsx +12 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/outboxEvent.tsx +46 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/paymentAudit.tsx +36 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/paymentSession.tsx +72 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/providerOperation.tsx +54 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/refundOperation.tsx +37 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/webhookInbox.tsx +59 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/index.ts +3 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/lib/index.ts +2 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/lib/payProvider.ts +7 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/lib/payScene.ts +7 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/model/outboxEvent.ts +10 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/model/paymentAudit.ts +10 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/model/paymentSession.ts +10 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/model/providerOperation.ts +10 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/model/refundOperation.ts +10 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/model/webhookInbox.ts +10 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/outbox.ts +156 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/paymentSession.ts +278 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/providerOperation.ts +5 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/webhook.ts +127 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/types/index.ts +3 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/types/payProvider.ts +74 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/types/payScene.ts +63 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/types/payment.ts +151 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/test/outbox.test.ts +209 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/test/paymentSession.test.ts +153 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/test/webhook.test.ts +278 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/tsconfig.build.json +11 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/tsconfig.json +7 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/package.json +55 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/.metadata/index.ts +182 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/.metadata/this.ts +2 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/bean/payProvider.mock.ts +149 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/controller/mockPayment.ts +25 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/dto/mockPaymentComplete.tsx +13 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/dto/mockPaymentReceipt.tsx +16 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/index.ts +3 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/lib/index.ts +1 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/service/payMock.ts +78 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/types/index.ts +10 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/test/payMock.test.ts +141 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/tsconfig.build.json +11 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/tsconfig.json +7 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/package.json +55 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/.metadata/index.ts +62 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/.metadata/this.ts +2 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/bean/payProvider.paypal.ts +91 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/index.ts +3 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/lib/index.ts +1 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/types/index.ts +9 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/tsconfig.build.json +11 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/tsconfig.json +7 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/package.json +55 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/src/.metadata/index.ts +62 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/src/.metadata/this.ts +2 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/src/bean/payProvider.stripe.ts +88 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/src/index.ts +2 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/src/types/index.ts +8 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/tsconfig.build.json +11 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/tsconfig.json +7 -0
- package/vona/src/suite-vendor/a-pay/package.json +15 -0
- package/vona/src/suite-vendor/a-pay/tsconfig.base.json +4 -0
- package/vona/src/suite-vendor/a-pay/tsconfig.json +19 -0
- package/zova/env/.env +1 -0
- package/zova/openapi.config.ts +5 -1
- package/zova/package.original.json +1 -1
- package/zova/packages-cli/cli/package.json +2 -2
- package/zova/packages-cli/cli-set-front/cli/templates/openapi/config/boilerplate/project/openapi.config.ts +5 -1
- package/zova/packages-cli/cli-set-front/package.json +1 -1
- package/zova/packages-cli/cli-set-front/src/lib/bean/cli.openapi.generate.ts +8 -0
- package/zova/packages-cli/cli-set-front/src/lib/common/cliCreatePage.ts +7 -24
- package/zova/packages-cli/cli-set-front/src/lib/common/utils.ts +10 -1
- package/zova/packages-utils/zova-jsx/package.json +2 -2
- package/zova/packages-zova/zova/package.json +3 -3
- package/zova/packages-zova/zova-core/package.json +1 -1
- package/zova/packages-zova/zova-core/src/types/interface/component.ts +5 -0
- package/zova/pnpm-lock.yaml +96 -26
- package/zova/src/front/config/config/config.cabloyCommerce.ts +1 -1
- package/zova/src/suite/a-commerce/modules/commerce-promotion/src/api/openapi/schemas.ts +110 -12
- package/zova/src/suite/a-commerce/modules/commerce-promotion/src/api/openapi/types.ts +1292 -160
- package/zova/src/suite/a-commerce/modules/commerce-trade/cli/openapi.config.ts +0 -1
- package/zova/src/suite/a-commerce/modules/commerce-trade/package.json +4 -1
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +1 -47
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/schemas.ts +23 -8
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/types.ts +249 -62
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/checkout/controller.tsx +5 -1
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/payment/controller.tsx +152 -39
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/routes.ts +1 -1
- package/zova/src/suite-vendor/a-pay/modules/a-pay/cli/openapi.config.ts +9 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/package.json +53 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/component/paymentNextAction.ts +31 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/index.ts +217 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/this.ts +2 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/openapi/baseURL.ts +5 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/openapi/index.ts +3 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/openapi/schemas.ts +584 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/openapi/types.ts +9324 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/paymentSession.ts +52 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/apiSchema/paymentSession.ts +20 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/component/paymentNextAction/controller.tsx +76 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/index.ts +3 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/lib/index.ts +1 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/model/paymentSession.ts +32 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/service/paymentCoordinator.ts +13 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/types/index.ts +1 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/types/payment.ts +25 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/tsconfig.build.json +13 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/tsconfig.json +5 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/cli/openapi.config.ts +9 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/package.json +53 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/.metadata/index.ts +140 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/.metadata/this.ts +2 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/openapi/baseURL.ts +5 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/openapi/index.ts +3 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/openapi/schemas.ts +584 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/openapi/types.ts +9324 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/payMockPayment.ts +34 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/apiSchema/payMockPayment.ts +13 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/index.ts +1 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/model/payMockPayment.ts +20 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/tsconfig.build.json +13 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/tsconfig.json +5 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-paypal/package.json +52 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-paypal/src/.metadata/index.ts +26 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-paypal/src/.metadata/this.ts +2 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-paypal/src/index.ts +1 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-paypal/tsconfig.build.json +13 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-paypal/tsconfig.json +5 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-stripe/package.json +52 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-stripe/src/.metadata/index.ts +26 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-stripe/src/.metadata/this.ts +2 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-stripe/src/index.ts +1 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-stripe/tsconfig.build.json +13 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-stripe/tsconfig.json +5 -0
- package/zova/src/suite-vendor/a-pay/package.json +15 -0
- package/zova/src/suite-vendor/a-pay/tsconfig.base.json +4 -0
- package/zova/src/suite-vendor/a-pay/tsconfig.json +4 -0
- package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
- package/zova/src/suite-vendor/a-zova/package.json +2 -2
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/controller/payment.ts +0 -23
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/commerceTradePayment.ts +0 -36
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/apiSchema/commerceTradePayment.ts +0 -13
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/payment.ts +0 -25
- /package/vona/patches/{zova-core@5.1.79.patch → zova-core@5.1.81.patch} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { TableIdentity } from 'table-identity';
|
|
2
|
+
import type { IRefundOutcomeEvent } from 'vona-module-a-pay';
|
|
3
|
+
|
|
4
|
+
import { BeanBase } from 'vona';
|
|
5
|
+
import { Service } from 'vona-module-a-bean';
|
|
6
|
+
import { Core } from 'vona-module-a-core';
|
|
7
|
+
|
|
8
|
+
import type { EntityPaymentAttempt } from '../entity/paymentAttempt.tsx';
|
|
9
|
+
|
|
10
|
+
@Service()
|
|
11
|
+
export class ServiceCommercePayScene extends BeanBase {
|
|
12
|
+
async createSession(attempt: EntityPaymentAttempt) {
|
|
13
|
+
const session = await this.$scope.pay.service.paymentSession.create({
|
|
14
|
+
userId: attempt.userId,
|
|
15
|
+
payScene: 'commerce-payment:commerceOrder',
|
|
16
|
+
businessReference: String(attempt.id),
|
|
17
|
+
amountMinor: attempt.amountCents,
|
|
18
|
+
currency: attempt.currency,
|
|
19
|
+
correlationId: `${attempt.correlationId}:session`,
|
|
20
|
+
});
|
|
21
|
+
await this.scope.model.paymentAttempt.updateById(attempt.id, {
|
|
22
|
+
paymentSessionId: session.id,
|
|
23
|
+
providerName: session.providerName,
|
|
24
|
+
});
|
|
25
|
+
return session;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@Core.transaction({ isolationLevel: 'SERIALIZABLE' })
|
|
29
|
+
async linkRefundOperation(refundAttemptId: TableIdentity, refundOperationId: TableIdentity) {
|
|
30
|
+
const refundAttempt = await this.scope.model.refundAttempt.getByIdForUpdate(refundAttemptId);
|
|
31
|
+
if (!refundAttempt) this.app.throw(404, 'commerce refund attempt not found');
|
|
32
|
+
await this.scope.model.refundAttempt.updateById(refundAttempt.id, { refundOperationId });
|
|
33
|
+
return { ...refundAttempt, refundOperationId };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@Core.transaction({ isolationLevel: 'SERIALIZABLE' })
|
|
37
|
+
async acceptRefundOutcome(event: IRefundOutcomeEvent) {
|
|
38
|
+
const refundAttempt = await this.scope.model.refundAttempt.getForUpdate({
|
|
39
|
+
refundOperationId: event.refundOperationId,
|
|
40
|
+
});
|
|
41
|
+
if (!refundAttempt) this.app.throw(404, 'commerce refund attempt not found');
|
|
42
|
+
if (
|
|
43
|
+
refundAttempt.amountCents !== event.amountMinor ||
|
|
44
|
+
refundAttempt.currency !== event.currency
|
|
45
|
+
) {
|
|
46
|
+
this.app.throw(409, 'commerce refund amount conflicts with the refund operation');
|
|
47
|
+
}
|
|
48
|
+
if (refundAttempt.state !== 'created') return refundAttempt;
|
|
49
|
+
await this.scope.model.refundAttempt.updateById(refundAttempt.id, {
|
|
50
|
+
providerRefundId: event.providerRefundId,
|
|
51
|
+
});
|
|
52
|
+
return { ...refundAttempt, providerRefundId: event.providerRefundId };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -22,7 +22,7 @@ export type TypePaymentAttemptFinalState = Extract<
|
|
|
22
22
|
@Service()
|
|
23
23
|
export class ServicePaymentAttempt extends BeanBase {
|
|
24
24
|
async create(command: IPaymentAttemptCreateCommand): Promise<EntityPaymentAttempt> {
|
|
25
|
-
|
|
25
|
+
const attempt = await this.scope.model.paymentAttempt.insert({
|
|
26
26
|
orderId: command.orderId,
|
|
27
27
|
userId: command.userId,
|
|
28
28
|
state: 'created',
|
|
@@ -30,6 +30,12 @@ export class ServicePaymentAttempt extends BeanBase {
|
|
|
30
30
|
amountCents: command.amountCents,
|
|
31
31
|
correlationId: command.correlationId,
|
|
32
32
|
});
|
|
33
|
+
const session = await this.scope.service.commercePayScene.createSession(attempt);
|
|
34
|
+
return {
|
|
35
|
+
...attempt,
|
|
36
|
+
paymentSessionId: session.id,
|
|
37
|
+
providerName: session.providerName,
|
|
38
|
+
};
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
async finalize(
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -9,8 +9,11 @@ describe('paymentAttempt.test.ts', { concurrency: false }, () => {
|
|
|
9
9
|
const scope = app.scope('commerce-payment');
|
|
10
10
|
const suffix = randomUUID().slice(0, 12);
|
|
11
11
|
let attemptId: number | undefined;
|
|
12
|
+
let paymentSessionId: number | undefined;
|
|
13
|
+
let userId: number | undefined;
|
|
12
14
|
try {
|
|
13
15
|
const user = await app.bean.user.register({ name: `payment-${suffix}` }, true);
|
|
16
|
+
userId = user.id as number;
|
|
14
17
|
const created = await scope.service.paymentAttempt.create({
|
|
15
18
|
orderId: 900_001,
|
|
16
19
|
userId: user.id,
|
|
@@ -19,14 +22,32 @@ describe('paymentAttempt.test.ts', { concurrency: false }, () => {
|
|
|
19
22
|
correlationId: `payment-${suffix}`,
|
|
20
23
|
});
|
|
21
24
|
attemptId = created.id as number;
|
|
25
|
+
paymentSessionId = created.paymentSessionId as number;
|
|
22
26
|
assert.equal(created.state, 'created');
|
|
27
|
+
const session = await app.scope('a-pay').model.paymentSession.getById(paymentSessionId);
|
|
28
|
+
assert.equal(session?.payScene, 'commerce-payment:commerceOrder');
|
|
29
|
+
assert.equal(session?.providerName, 'pay-mock:mock');
|
|
30
|
+
assert.equal(session?.clientName, 'default');
|
|
31
|
+
assert.equal(session?.environment, 'sandbox');
|
|
32
|
+
assert.ok((session?.expiresAt.getTime() ?? 0) > Date.now() + 29 * 60 * 1000);
|
|
23
33
|
const cancelled = await scope.service.paymentAttempt.cancel(created.orderId);
|
|
24
34
|
assert.equal(cancelled?.state, 'cancelled');
|
|
25
35
|
const replay = await scope.service.paymentAttempt.cancel(created.orderId);
|
|
26
36
|
assert.equal(replay?.id, created.id);
|
|
27
37
|
assert.equal(replay?.state, 'cancelled');
|
|
28
38
|
} finally {
|
|
39
|
+
if (paymentSessionId !== undefined) {
|
|
40
|
+
const pay = app.scope('a-pay');
|
|
41
|
+
await pay.model.outboxEvent.delete({ paymentSessionId });
|
|
42
|
+
await pay.model.paymentAudit.delete({ paymentSessionId });
|
|
43
|
+
await pay.model.webhookInbox.delete({ paymentSessionId });
|
|
44
|
+
await pay.model.paymentSession.delete({ id: paymentSessionId });
|
|
45
|
+
}
|
|
29
46
|
if (attemptId !== undefined) await scope.model.paymentAttempt.delete({ id: attemptId });
|
|
47
|
+
if (userId !== undefined) {
|
|
48
|
+
await app.scope('home-user').model.roleUser.delete({ userId });
|
|
49
|
+
await app.bean.user.removeById(userId);
|
|
50
|
+
}
|
|
30
51
|
}
|
|
31
52
|
});
|
|
32
53
|
});
|
|
@@ -148,7 +148,17 @@ declare module 'vona-module-commerce-promotion' {
|
|
|
148
148
|
[SymbolKeyEntityMeta]: EntityCouponAuditMeta;
|
|
149
149
|
[SymbolKeyModelOptions]: IModelOptionsCouponAudit;
|
|
150
150
|
get<T extends IModelGetOptions<EntityCouponAudit,ModelCouponAudit>>(where: TypeModelWhere<EntityCouponAudit>, options?: T): Promise<TypeModelRelationResult<EntityCouponAudit, ModelCouponAudit, T> | undefined>;
|
|
151
|
+
/**
|
|
152
|
+
* Retrieves one matching primary row with a pessimistic FOR UPDATE lock.
|
|
153
|
+
* Requires an active transaction. The lock is released when that transaction completes.
|
|
154
|
+
* Entity and query caches are bypassed.
|
|
155
|
+
*/
|
|
151
156
|
getForUpdate<T extends IModelGetOptions<EntityCouponAudit,ModelCouponAudit>>(where: TypeModelWhere<EntityCouponAudit>, options?: T): Promise<TypeModelRelationResult<EntityCouponAudit, ModelCouponAudit, T> | undefined>;
|
|
157
|
+
/**
|
|
158
|
+
* Retrieves a primary row by ID with the same pessimistic FOR UPDATE lock semantics.
|
|
159
|
+
* Requires an active transaction. The lock is released when that transaction completes.
|
|
160
|
+
* Entity and query caches are bypassed.
|
|
161
|
+
*/
|
|
152
162
|
getByIdForUpdate<T extends IModelGetOptions<EntityCouponAudit,ModelCouponAudit>>(id: TableIdentity, options?: T): Promise<TypeModelRelationResult<EntityCouponAudit, ModelCouponAudit, T> | undefined>;
|
|
153
163
|
mget<T extends IModelGetOptions<EntityCouponAudit,ModelCouponAudit>>(ids: TableIdentity[], options?: T): Promise<TypeModelRelationResult<EntityCouponAudit, ModelCouponAudit, T>[]>;
|
|
154
164
|
selectAndCount<T extends IModelSelectParams<EntityCouponAudit,ModelCouponAudit,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelSelectAndCount<EntityCouponAudit, ModelCouponAudit, T>>;
|
|
@@ -175,7 +185,17 @@ export interface ModelCouponGrant {
|
|
|
175
185
|
[SymbolKeyEntityMeta]: EntityCouponGrantMeta;
|
|
176
186
|
[SymbolKeyModelOptions]: IModelOptionsCouponGrant;
|
|
177
187
|
get<T extends IModelGetOptions<EntityCouponGrant,ModelCouponGrant>>(where: TypeModelWhere<EntityCouponGrant>, options?: T): Promise<TypeModelRelationResult<EntityCouponGrant, ModelCouponGrant, T> | undefined>;
|
|
188
|
+
/**
|
|
189
|
+
* Retrieves one matching primary row with a pessimistic FOR UPDATE lock.
|
|
190
|
+
* Requires an active transaction. The lock is released when that transaction completes.
|
|
191
|
+
* Entity and query caches are bypassed.
|
|
192
|
+
*/
|
|
178
193
|
getForUpdate<T extends IModelGetOptions<EntityCouponGrant,ModelCouponGrant>>(where: TypeModelWhere<EntityCouponGrant>, options?: T): Promise<TypeModelRelationResult<EntityCouponGrant, ModelCouponGrant, T> | undefined>;
|
|
194
|
+
/**
|
|
195
|
+
* Retrieves a primary row by ID with the same pessimistic FOR UPDATE lock semantics.
|
|
196
|
+
* Requires an active transaction. The lock is released when that transaction completes.
|
|
197
|
+
* Entity and query caches are bypassed.
|
|
198
|
+
*/
|
|
179
199
|
getByIdForUpdate<T extends IModelGetOptions<EntityCouponGrant,ModelCouponGrant>>(id: TableIdentity, options?: T): Promise<TypeModelRelationResult<EntityCouponGrant, ModelCouponGrant, T> | undefined>;
|
|
180
200
|
mget<T extends IModelGetOptions<EntityCouponGrant,ModelCouponGrant>>(ids: TableIdentity[], options?: T): Promise<TypeModelRelationResult<EntityCouponGrant, ModelCouponGrant, T>[]>;
|
|
181
201
|
selectAndCount<T extends IModelSelectParams<EntityCouponGrant,ModelCouponGrant,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelSelectAndCount<EntityCouponGrant, ModelCouponGrant, T>>;
|
|
@@ -202,7 +222,17 @@ export interface ModelCouponTemplate {
|
|
|
202
222
|
[SymbolKeyEntityMeta]: EntityCouponTemplateMeta;
|
|
203
223
|
[SymbolKeyModelOptions]: IModelOptionsCouponTemplate;
|
|
204
224
|
get<T extends IModelGetOptions<EntityCouponTemplate,ModelCouponTemplate>>(where: TypeModelWhere<EntityCouponTemplate>, options?: T): Promise<TypeModelRelationResult<EntityCouponTemplate, ModelCouponTemplate, T> | undefined>;
|
|
225
|
+
/**
|
|
226
|
+
* Retrieves one matching primary row with a pessimistic FOR UPDATE lock.
|
|
227
|
+
* Requires an active transaction. The lock is released when that transaction completes.
|
|
228
|
+
* Entity and query caches are bypassed.
|
|
229
|
+
*/
|
|
205
230
|
getForUpdate<T extends IModelGetOptions<EntityCouponTemplate,ModelCouponTemplate>>(where: TypeModelWhere<EntityCouponTemplate>, options?: T): Promise<TypeModelRelationResult<EntityCouponTemplate, ModelCouponTemplate, T> | undefined>;
|
|
231
|
+
/**
|
|
232
|
+
* Retrieves a primary row by ID with the same pessimistic FOR UPDATE lock semantics.
|
|
233
|
+
* Requires an active transaction. The lock is released when that transaction completes.
|
|
234
|
+
* Entity and query caches are bypassed.
|
|
235
|
+
*/
|
|
206
236
|
getByIdForUpdate<T extends IModelGetOptions<EntityCouponTemplate,ModelCouponTemplate>>(id: TableIdentity, options?: T): Promise<TypeModelRelationResult<EntityCouponTemplate, ModelCouponTemplate, T> | undefined>;
|
|
207
237
|
mget<T extends IModelGetOptions<EntityCouponTemplate,ModelCouponTemplate>>(ids: TableIdentity[], options?: T): Promise<TypeModelRelationResult<EntityCouponTemplate, ModelCouponTemplate, T>[]>;
|
|
208
238
|
selectAndCount<T extends IModelSelectParams<EntityCouponTemplate,ModelCouponTemplate,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelSelectAndCount<EntityCouponTemplate, ModelCouponTemplate, T>>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
ActorId: 'Actor ID',
|
|
3
|
+
BasicInformation: 'Basic Information',
|
|
3
4
|
CouponAudit: 'Coupon Audit',
|
|
4
5
|
CouponCode: 'Coupon Code',
|
|
5
6
|
CouponGrant: 'Coupon Grant',
|
|
@@ -13,6 +14,7 @@ export default {
|
|
|
13
14
|
Currency: 'Currency',
|
|
14
15
|
Description: 'Description',
|
|
15
16
|
DiscountCents: 'Fixed Discount (Cents)',
|
|
17
|
+
DiscountPolicy: 'Discount Policy',
|
|
16
18
|
FromState: 'Previous State',
|
|
17
19
|
IssuedCount: 'Issued Count',
|
|
18
20
|
MinSpendCents: 'Minimum Spend (Cents)',
|
|
@@ -31,7 +33,9 @@ export default {
|
|
|
31
33
|
ToState: 'New State',
|
|
32
34
|
TotalIssueLimit: 'Total Issue Limit',
|
|
33
35
|
TotalUsageLimit: 'Total Usage Limit',
|
|
36
|
+
UsageLimits: 'Usage Limits',
|
|
34
37
|
UserId: 'User ID',
|
|
35
38
|
ValidFrom: 'Valid From',
|
|
39
|
+
ValidityWindow: 'Validity Window',
|
|
36
40
|
ValidUntil: 'Valid Until',
|
|
37
41
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
ActorId: '操作人 ID',
|
|
3
|
+
BasicInformation: '基本信息',
|
|
3
4
|
CouponAudit: '优惠券审计',
|
|
4
5
|
CouponCode: '优惠券代码',
|
|
5
6
|
CouponGrant: '优惠券发放',
|
|
@@ -13,6 +14,7 @@ export default {
|
|
|
13
14
|
Currency: '币种',
|
|
14
15
|
Description: '描述',
|
|
15
16
|
DiscountCents: '固定优惠(分)',
|
|
17
|
+
DiscountPolicy: '优惠策略',
|
|
16
18
|
FromState: '原状态',
|
|
17
19
|
IssuedCount: '已发放数',
|
|
18
20
|
MinSpendCents: '最低消费(分)',
|
|
@@ -31,7 +33,9 @@ export default {
|
|
|
31
33
|
ToState: '新状态',
|
|
32
34
|
TotalIssueLimit: '总发放上限',
|
|
33
35
|
TotalUsageLimit: '总使用上限',
|
|
36
|
+
UsageLimits: '使用限制',
|
|
34
37
|
UserId: '用户 ID',
|
|
35
38
|
ValidFrom: '开始时间',
|
|
39
|
+
ValidityWindow: '有效期',
|
|
36
40
|
ValidUntil: '结束时间',
|
|
37
41
|
};
|
package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateCreate.tsx
CHANGED
|
@@ -3,10 +3,97 @@ import type { IDecoratorDtoOptions } from 'vona-module-a-web';
|
|
|
3
3
|
import { Api, v } from 'vona-module-a-openapiutils';
|
|
4
4
|
import { Dto } from 'vona-module-a-web';
|
|
5
5
|
import { z } from 'zod';
|
|
6
|
+
import { ZovaRender } from 'zova-rest-cabloy-basic-admin';
|
|
7
|
+
|
|
8
|
+
import { $locale } from '../.metadata/locales.ts';
|
|
6
9
|
|
|
7
10
|
export interface IDtoOptionsCouponTemplateCreate extends IDecoratorDtoOptions {}
|
|
8
11
|
|
|
9
|
-
@Dto<IDtoOptionsCouponTemplateCreate>(
|
|
12
|
+
@Dto<IDtoOptionsCouponTemplateCreate>({
|
|
13
|
+
blocks: [
|
|
14
|
+
ZovaRender.block('basic-pageentry:blockPageEntry', {
|
|
15
|
+
blocks: [
|
|
16
|
+
ZovaRender.block('basic-pageentry:blockForm', {
|
|
17
|
+
blocks: [
|
|
18
|
+
ZovaRender.block('basic-form:blockFormLayout', {
|
|
19
|
+
formLayout: {
|
|
20
|
+
children: [
|
|
21
|
+
{
|
|
22
|
+
type: 'group',
|
|
23
|
+
title: $locale('BasicInformation'),
|
|
24
|
+
children: [
|
|
25
|
+
{
|
|
26
|
+
type: 'section',
|
|
27
|
+
columns: { default: 1, md: 2 },
|
|
28
|
+
children: [
|
|
29
|
+
{ type: 'field', name: 'name' },
|
|
30
|
+
{ type: 'field', name: 'state' },
|
|
31
|
+
{ type: 'field', name: 'description', span: { default: 1, md: 2 } },
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
type: 'group',
|
|
38
|
+
title: $locale('DiscountPolicy'),
|
|
39
|
+
children: [
|
|
40
|
+
{
|
|
41
|
+
type: 'section',
|
|
42
|
+
columns: { default: 1, md: 2 },
|
|
43
|
+
children: [
|
|
44
|
+
{ type: 'field', name: 'currency' },
|
|
45
|
+
{ type: 'field', name: 'discountCents' },
|
|
46
|
+
{ type: 'field', name: 'minSpendCents' },
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
type: 'group',
|
|
53
|
+
title: $locale('ValidityWindow'),
|
|
54
|
+
children: [
|
|
55
|
+
{
|
|
56
|
+
type: 'section',
|
|
57
|
+
columns: { default: 1, md: 2 },
|
|
58
|
+
children: [
|
|
59
|
+
{ type: 'field', name: 'validFrom' },
|
|
60
|
+
{ type: 'field', name: 'validUntil' },
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
type: 'group',
|
|
67
|
+
title: $locale('UsageLimits'),
|
|
68
|
+
children: [
|
|
69
|
+
{
|
|
70
|
+
type: 'section',
|
|
71
|
+
columns: { default: 1, md: 2 },
|
|
72
|
+
children: [
|
|
73
|
+
{ type: 'field', name: 'totalIssueLimit' },
|
|
74
|
+
{ type: 'field', name: 'totalUsageLimit' },
|
|
75
|
+
{ type: 'field', name: 'perCustomerIssueLimit' },
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
}),
|
|
83
|
+
],
|
|
84
|
+
}),
|
|
85
|
+
ZovaRender.block('basic-pageentry:blockToolbarRow', {
|
|
86
|
+
actions: [
|
|
87
|
+
ZovaRender.formActionRow('basic-form:actionSubmit', {
|
|
88
|
+
permission: { actionInherit: 'update', formScene: ['create', 'edit'] },
|
|
89
|
+
}),
|
|
90
|
+
ZovaRender.formActionRow('basic-form:actionBack', { permission: { public: true } }),
|
|
91
|
+
],
|
|
92
|
+
}),
|
|
93
|
+
],
|
|
94
|
+
}),
|
|
95
|
+
],
|
|
96
|
+
})
|
|
10
97
|
export class DtoCouponTemplateCreate {
|
|
11
98
|
@Api.field(v.required(), v.min(2), v.max(100))
|
|
12
99
|
name: string;
|
package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateUpdate.tsx
CHANGED
|
@@ -3,10 +3,53 @@ import type { IDecoratorDtoOptions } from 'vona-module-a-web';
|
|
|
3
3
|
import { Api, v } from 'vona-module-a-openapiutils';
|
|
4
4
|
import { Dto } from 'vona-module-a-web';
|
|
5
5
|
import { z } from 'zod';
|
|
6
|
+
import { ZovaRender } from 'zova-rest-cabloy-basic-admin';
|
|
7
|
+
|
|
8
|
+
import { $locale } from '../.metadata/locales.ts';
|
|
6
9
|
|
|
7
10
|
export interface IDtoOptionsCouponTemplateUpdate extends IDecoratorDtoOptions {}
|
|
8
11
|
|
|
9
|
-
@Dto<IDtoOptionsCouponTemplateUpdate>(
|
|
12
|
+
@Dto<IDtoOptionsCouponTemplateUpdate>({
|
|
13
|
+
blocks: [
|
|
14
|
+
ZovaRender.block('basic-pageentry:blockPageEntry', {
|
|
15
|
+
blocks: [
|
|
16
|
+
ZovaRender.block('basic-pageentry:blockForm', {
|
|
17
|
+
blocks: [
|
|
18
|
+
ZovaRender.block('basic-form:blockFormLayout', {
|
|
19
|
+
formLayout: {
|
|
20
|
+
children: [
|
|
21
|
+
{
|
|
22
|
+
type: 'group',
|
|
23
|
+
title: $locale('BasicInformation'),
|
|
24
|
+
children: [
|
|
25
|
+
{
|
|
26
|
+
type: 'section',
|
|
27
|
+
columns: { default: 1, md: 2 },
|
|
28
|
+
children: [
|
|
29
|
+
{ type: 'field', name: 'name' },
|
|
30
|
+
{ type: 'field', name: 'state' },
|
|
31
|
+
{ type: 'field', name: 'description', span: { default: 1, md: 2 } },
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
}),
|
|
39
|
+
],
|
|
40
|
+
}),
|
|
41
|
+
ZovaRender.block('basic-pageentry:blockToolbarRow', {
|
|
42
|
+
actions: [
|
|
43
|
+
ZovaRender.formActionRow('basic-form:actionSubmit', {
|
|
44
|
+
permission: { actionInherit: 'update', formScene: ['create', 'edit'] },
|
|
45
|
+
}),
|
|
46
|
+
ZovaRender.formActionRow('basic-form:actionBack', { permission: { public: true } }),
|
|
47
|
+
],
|
|
48
|
+
}),
|
|
49
|
+
],
|
|
50
|
+
}),
|
|
51
|
+
],
|
|
52
|
+
})
|
|
10
53
|
export class DtoCouponTemplateUpdate {
|
|
11
54
|
@Api.field(v.optional(), v.min(2), v.max(100))
|
|
12
55
|
name?: string;
|
|
@@ -4,6 +4,7 @@ import { $Dto } from 'vona-module-a-orm';
|
|
|
4
4
|
import { Dto } from 'vona-module-a-web';
|
|
5
5
|
import { ZovaRender } from 'zova-rest-cabloy-basic-admin';
|
|
6
6
|
|
|
7
|
+
import { $locale } from '../.metadata/locales.ts';
|
|
7
8
|
import { ModelCouponTemplate } from '../model/couponTemplate.ts';
|
|
8
9
|
|
|
9
10
|
export interface IDtoOptionsCouponTemplateView extends IDecoratorDtoOptions {}
|
|
@@ -12,7 +13,77 @@ export interface IDtoOptionsCouponTemplateView extends IDecoratorDtoOptions {}
|
|
|
12
13
|
blocks: [
|
|
13
14
|
ZovaRender.block('basic-pageentry:blockPageEntry', {
|
|
14
15
|
blocks: [
|
|
15
|
-
ZovaRender.block('basic-pageentry:blockForm'
|
|
16
|
+
ZovaRender.block('basic-pageentry:blockForm', {
|
|
17
|
+
blocks: [
|
|
18
|
+
ZovaRender.block('basic-form:blockFormLayout', {
|
|
19
|
+
formLayout: {
|
|
20
|
+
children: [
|
|
21
|
+
{
|
|
22
|
+
type: 'group',
|
|
23
|
+
title: $locale('BasicInformation'),
|
|
24
|
+
children: [
|
|
25
|
+
{
|
|
26
|
+
type: 'section',
|
|
27
|
+
columns: { default: 1, md: 2 },
|
|
28
|
+
children: [
|
|
29
|
+
{ type: 'field', name: 'name' },
|
|
30
|
+
{ type: 'field', name: 'state' },
|
|
31
|
+
{ type: 'field', name: 'description', span: { default: 1, md: 2 } },
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
type: 'group',
|
|
38
|
+
title: $locale('DiscountPolicy'),
|
|
39
|
+
children: [
|
|
40
|
+
{
|
|
41
|
+
type: 'section',
|
|
42
|
+
columns: { default: 1, md: 2 },
|
|
43
|
+
children: [
|
|
44
|
+
{ type: 'field', name: 'currency' },
|
|
45
|
+
{ type: 'field', name: 'discountCents' },
|
|
46
|
+
{ type: 'field', name: 'minSpendCents' },
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
type: 'group',
|
|
53
|
+
title: $locale('ValidityWindow'),
|
|
54
|
+
children: [
|
|
55
|
+
{
|
|
56
|
+
type: 'section',
|
|
57
|
+
columns: { default: 1, md: 2 },
|
|
58
|
+
children: [
|
|
59
|
+
{ type: 'field', name: 'validFrom' },
|
|
60
|
+
{ type: 'field', name: 'validUntil' },
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
type: 'group',
|
|
67
|
+
title: $locale('UsageLimits'),
|
|
68
|
+
children: [
|
|
69
|
+
{
|
|
70
|
+
type: 'section',
|
|
71
|
+
columns: { default: 1, md: 2 },
|
|
72
|
+
children: [
|
|
73
|
+
{ type: 'field', name: 'totalIssueLimit' },
|
|
74
|
+
{ type: 'field', name: 'totalUsageLimit' },
|
|
75
|
+
{ type: 'field', name: 'perCustomerIssueLimit' },
|
|
76
|
+
{ type: 'field', name: 'issuedCount' },
|
|
77
|
+
{ type: 'field', name: 'redeemedCount' },
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
}),
|
|
85
|
+
],
|
|
86
|
+
}),
|
|
16
87
|
ZovaRender.block('basic-pageentry:blockToolbarRow', {
|
|
17
88
|
actions: [
|
|
18
89
|
ZovaRender.formActionRow('basic-form:actionBack', { permission: { public: true } }),
|
package/vona/src/suite/a-commerce/modules/commerce-promotion/test/couponTemplateFormLayout.test.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { describe, it } from 'node:test';
|
|
3
|
+
import { app } from 'vona-mock';
|
|
4
|
+
import {
|
|
5
|
+
DtoCouponTemplateCreate,
|
|
6
|
+
DtoCouponTemplateSelectResItem,
|
|
7
|
+
DtoCouponTemplateUpdate,
|
|
8
|
+
DtoCouponTemplateView,
|
|
9
|
+
} from 'vona-module-commerce-promotion';
|
|
10
|
+
|
|
11
|
+
function getEntryFormLayout(component: any) {
|
|
12
|
+
const pageEntry = component?.rest?.blocks?.[0];
|
|
13
|
+
const formBlock = pageEntry?.options?.blocks?.[0];
|
|
14
|
+
const layoutBlock = formBlock?.options?.blocks?.[0];
|
|
15
|
+
assert.equal(pageEntry?.render, 'basic-pageentry:blockPageEntry');
|
|
16
|
+
assert.equal(formBlock?.render, 'basic-pageentry:blockForm');
|
|
17
|
+
assert.equal(layoutBlock?.render, 'basic-form:blockFormLayout');
|
|
18
|
+
return layoutBlock?.options?.formLayout;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function getGroupFields(group: any) {
|
|
22
|
+
const section = group?.children?.[0];
|
|
23
|
+
assert.equal(group?.type, 'group');
|
|
24
|
+
assert.equal(section?.type, 'section');
|
|
25
|
+
assert.deepEqual(section?.columns, { default: 1, md: 2 });
|
|
26
|
+
return section?.children;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function findComponent(apiJson: any, predicate: (properties: any) => boolean) {
|
|
30
|
+
return Object.values(apiJson.components!.schemas as any).find(item => {
|
|
31
|
+
return predicate((item as any).properties);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
describe('couponTemplateFormLayout.test.ts', () => {
|
|
36
|
+
it('action:couponTemplate:formLayoutMetadata', async () => {
|
|
37
|
+
await app.bean.executor.mockCtx(async () => {
|
|
38
|
+
const createJson = await app.bean.openapi.generateJsonOfClass(DtoCouponTemplateCreate);
|
|
39
|
+
const createComponent = findComponent(createJson, properties => {
|
|
40
|
+
return properties?.discountCents && properties?.totalIssueLimit;
|
|
41
|
+
});
|
|
42
|
+
const createLayout = getEntryFormLayout(createComponent);
|
|
43
|
+
assert.deepEqual(
|
|
44
|
+
createLayout?.children.map((group: any) =>
|
|
45
|
+
getGroupFields(group).map((field: any) => field.name),
|
|
46
|
+
),
|
|
47
|
+
[
|
|
48
|
+
['name', 'state', 'description'],
|
|
49
|
+
['currency', 'discountCents', 'minSpendCents'],
|
|
50
|
+
['validFrom', 'validUntil'],
|
|
51
|
+
['totalIssueLimit', 'totalUsageLimit', 'perCustomerIssueLimit'],
|
|
52
|
+
],
|
|
53
|
+
);
|
|
54
|
+
assert.deepEqual(getGroupFields(createLayout?.children[0])?.[2]?.span, { default: 1, md: 2 });
|
|
55
|
+
|
|
56
|
+
const updateJson = await app.bean.openapi.generateJsonOfClass(DtoCouponTemplateUpdate);
|
|
57
|
+
const updateComponent = findComponent(updateJson, properties => {
|
|
58
|
+
return (
|
|
59
|
+
properties?.name && properties?.state && properties?.description && !properties?.currency
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
const updateLayout = getEntryFormLayout(updateComponent);
|
|
63
|
+
assert.equal(updateLayout?.children.length, 1);
|
|
64
|
+
assert.deepEqual(
|
|
65
|
+
getGroupFields(updateLayout?.children[0]).map((field: any) => field.name),
|
|
66
|
+
['name', 'state', 'description'],
|
|
67
|
+
);
|
|
68
|
+
assert.deepEqual(getGroupFields(updateLayout?.children[0])?.[2]?.span, { default: 1, md: 2 });
|
|
69
|
+
|
|
70
|
+
const viewJson = await app.bean.openapi.generateJsonOfClass(DtoCouponTemplateView);
|
|
71
|
+
const viewComponent = findComponent(viewJson, properties => {
|
|
72
|
+
return properties?.issuedCount && properties?.redeemedCount;
|
|
73
|
+
});
|
|
74
|
+
const viewLayout = getEntryFormLayout(viewComponent);
|
|
75
|
+
assert.deepEqual(
|
|
76
|
+
viewLayout?.children.map((group: any) =>
|
|
77
|
+
getGroupFields(group).map((field: any) => field.name),
|
|
78
|
+
),
|
|
79
|
+
[
|
|
80
|
+
['name', 'state', 'description'],
|
|
81
|
+
['currency', 'discountCents', 'minSpendCents'],
|
|
82
|
+
['validFrom', 'validUntil'],
|
|
83
|
+
[
|
|
84
|
+
'totalIssueLimit',
|
|
85
|
+
'totalUsageLimit',
|
|
86
|
+
'perCustomerIssueLimit',
|
|
87
|
+
'issuedCount',
|
|
88
|
+
'redeemedCount',
|
|
89
|
+
],
|
|
90
|
+
],
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('action:couponTemplate:filterFormLayoutMetadata', async () => {
|
|
96
|
+
await app.bean.executor.mockCtx(async () => {
|
|
97
|
+
const apiJson = await app.bean.openapi.generateJsonOfClass(DtoCouponTemplateSelectResItem);
|
|
98
|
+
const component = findComponent(apiJson, properties => properties?._operationsRow);
|
|
99
|
+
const filterBlock = (component as any)?.rest?.blocks?.[0]?.options?.blocks?.[0];
|
|
100
|
+
assert.equal(filterBlock?.render, 'basic-page:blockFilter');
|
|
101
|
+
assert.equal(filterBlock?.options?.formFieldLayout?.inline, true);
|
|
102
|
+
assert.deepEqual(
|
|
103
|
+
filterBlock?.options?.blocks?.map((block: any) => block.render),
|
|
104
|
+
['basic-form:blockFormLayout'],
|
|
105
|
+
);
|
|
106
|
+
const filterLayout = filterBlock?.options?.blocks?.[0]?.options?.formLayout;
|
|
107
|
+
const section = filterLayout?.children?.[0];
|
|
108
|
+
assert.equal(section?.type, 'section');
|
|
109
|
+
assert.equal(section?.layout, 'flow');
|
|
110
|
+
assert.deepEqual(
|
|
111
|
+
section?.children?.map((child: any) => child.type),
|
|
112
|
+
['field', 'field', 'block'],
|
|
113
|
+
);
|
|
114
|
+
assert.deepEqual(
|
|
115
|
+
section?.children?.slice(0, 2).map((field: any) => field.name),
|
|
116
|
+
['name', 'createdAt'],
|
|
117
|
+
);
|
|
118
|
+
assert.equal(section?.children?.[2]?.block?.render, 'basic-page:blockFilterActions');
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
});
|
|
@@ -13,7 +13,10 @@ export interface ISsrMenuOptionsHome extends IDecoratorSsrMenuOptions<ISsrSiteOp
|
|
|
13
13
|
title: 'Commerce',
|
|
14
14
|
order: $order(1),
|
|
15
15
|
icon: undefined,
|
|
16
|
-
link: '
|
|
16
|
+
link: '/:locale' as never,
|
|
17
|
+
meta: {
|
|
18
|
+
params: { locale: true },
|
|
19
|
+
},
|
|
17
20
|
},
|
|
18
21
|
site: ['commerce-siteweb:commerce'],
|
|
19
22
|
})
|
|
@@ -30,7 +30,9 @@
|
|
|
30
30
|
"prepack": "clean-package",
|
|
31
31
|
"postpack": "clean-package restore"
|
|
32
32
|
},
|
|
33
|
-
"dependencies": {
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"vona-module-a-pay": "workspace:*"
|
|
35
|
+
},
|
|
34
36
|
"devDependencies": {
|
|
35
37
|
"clean-package": "^2.2.0",
|
|
36
38
|
"rimraf": "^6.1.3"
|
|
@@ -46,6 +48,7 @@
|
|
|
46
48
|
"title": "commerce-trade",
|
|
47
49
|
"vonaModule": {
|
|
48
50
|
"dependencies": {
|
|
51
|
+
"a-pay": "5.0.0",
|
|
49
52
|
"a-vona": "5.0.0",
|
|
50
53
|
"commerce-member": "5.0.0",
|
|
51
54
|
"commerce-payment": "5.0.0",
|