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.
Files changed (244) hide show
  1. package/.cabloy-version +1 -1
  2. package/.claude/skills/cabloy-frontend-scaffold/SKILL.md +13 -3
  3. package/.claude/skills/cabloy-workflow/SKILL.md +6 -0
  4. package/.claude/skills/cabloy-workflow/evals/evals.json +6 -0
  5. package/CHANGELOG.md +24 -0
  6. package/CLAUDE.md +1 -1
  7. package/cabloy-docs/.vitepress/config.mjs +4 -0
  8. package/cabloy-docs/frontend/form-layout-guide.md +29 -7
  9. package/cabloy-docs/fullstack/parallel-worktree-environment.md +87 -0
  10. package/e2e/scripts/e2e.ts +13 -1
  11. package/e2e/scripts/startE2eVona.ts +4 -1
  12. package/e2e/specs/a-commerce/commerce.spec.ts +129 -32
  13. package/package.json +2 -1
  14. package/playwright-report/data/24ac790ec112339c76cfb0c8e2c2539c2f953a0b.zip +0 -0
  15. package/playwright-report/data/2fddcabcdbd0b695061a565acfff243cb3a4f5e3.zip +0 -0
  16. package/playwright-report/data/4738038d9e861d63fd25937c9a3570934786a62f.zip +0 -0
  17. package/playwright-report/data/72f99c7da67c7f6ea53cab7d8681798b70d79a10.md +222 -0
  18. package/playwright-report/data/7b9684a7c793e9798b898f8ff50177b660a7a733.md +222 -0
  19. package/playwright-report/data/8b31595f5f1cc9d23863af51a592e6b90dcbc4ce.zip +0 -0
  20. package/playwright-report/data/95b578407a68806202dda917a61c50c750bd285b.md +222 -0
  21. package/playwright-report/data/ad960b3a58f224f5b4cad04a24067600064ffb7b.md +222 -0
  22. package/playwright-report/index.html +90 -0
  23. package/playwright-report/trace/assets/codeMirrorModule-LEHpjmcn.js +32 -0
  24. package/playwright-report/trace/assets/defaultSettingsView-BNmKHKpQ.js +264 -0
  25. package/playwright-report/trace/assets/urlMatch-BYQrIQwR.js +1 -0
  26. package/playwright-report/trace/codeMirrorModule.DYBRYzYX.css +1 -0
  27. package/playwright-report/trace/codicon.DCmgc-ay.ttf +0 -0
  28. package/playwright-report/trace/defaultSettingsView.CjdS-WJx.css +1 -0
  29. package/playwright-report/trace/index.CzXZzn5A.css +1 -0
  30. package/playwright-report/trace/index.DMMX1gXU.js +2 -0
  31. package/playwright-report/trace/index.html +44 -0
  32. package/playwright-report/trace/manifest.webmanifest +16 -0
  33. package/playwright-report/trace/playwright-logo.svg +9 -0
  34. package/playwright-report/trace/snapshot.html +10 -0
  35. package/playwright-report/trace/snapshot.v8KI4P3m.js +2 -0
  36. package/playwright-report/trace/sw.bundle.js +5 -0
  37. package/playwright-report/trace/uiMode.BZQ54Kgt.css +1 -0
  38. package/playwright-report/trace/uiMode.Ut8wwJNp.js +6 -0
  39. package/playwright-report/trace/uiMode.html +18 -0
  40. package/playwright-report/trace/xtermModule.DYP7pi_n.css +32 -0
  41. package/vona/env/.env +12 -0
  42. package/vona/env/.env.test +7 -0
  43. package/vona/packages-cli/cli/package.json +1 -1
  44. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/src/dto/{{resourceName}}Create.tsx_ +19 -1
  45. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/src/dto/{{resourceName}}Update.tsx_ +19 -1
  46. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/src/dto/{{resourceName}}View.tsx_ +19 -1
  47. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/snippets/3-en-us.ts +6 -1
  48. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/snippets/4-zh-cn.ts +6 -1
  49. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/dto/{{resourceName}}Create.tsx_ +19 -1
  50. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/dto/{{resourceName}}Update.tsx_ +19 -1
  51. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/dto/{{resourceName}}View.tsx_ +19 -1
  52. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/snippets/3-en-us.ts +6 -1
  53. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/snippets/4-zh-cn.ts +6 -1
  54. package/vona/packages-cli/cli-set-api/package.json +1 -1
  55. package/vona/pnpm-lock.yaml +255 -12
  56. package/vona/pnpm-workspace.yaml +1 -1
  57. package/vona/src/suite/a-commerce/modules/commerce-payment/package.json +4 -1
  58. package/vona/src/suite/a-commerce/modules/commerce-payment/src/.metadata/index.ts +45 -3
  59. package/vona/src/suite/a-commerce/modules/commerce-payment/src/bean/meta.index.ts +1 -0
  60. package/vona/src/suite/a-commerce/modules/commerce-payment/src/bean/meta.version.ts +25 -1
  61. package/vona/src/suite/a-commerce/modules/commerce-payment/src/bean/payScene.commerceOrder.ts +20 -0
  62. package/vona/src/suite/a-commerce/modules/commerce-payment/src/entity/paymentAttempt.tsx +9 -0
  63. package/vona/src/suite/a-commerce/modules/commerce-payment/src/entity/paymentAudit.tsx +5 -2
  64. package/vona/src/suite/a-commerce/modules/commerce-payment/src/entity/refundAttempt.tsx +6 -0
  65. package/vona/src/suite/a-commerce/modules/commerce-payment/src/index.ts +2 -0
  66. package/vona/src/suite/a-commerce/modules/commerce-payment/src/lib/index.ts +1 -0
  67. package/vona/src/suite/a-commerce/modules/commerce-payment/src/service/commercePayScene.ts +54 -0
  68. package/vona/src/suite/a-commerce/modules/commerce-payment/src/service/paymentAttempt.ts +7 -1
  69. package/vona/src/suite/a-commerce/modules/commerce-payment/src/types/index.ts +1 -0
  70. package/vona/src/suite/a-commerce/modules/commerce-payment/test/paymentAttempt.test.ts +21 -0
  71. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/.metadata/index.ts +30 -0
  72. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/config/locale/en-us.ts +4 -0
  73. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/config/locale/zh-cn.ts +4 -0
  74. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateCreate.tsx +88 -1
  75. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateUpdate.tsx +44 -1
  76. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateView.tsx +72 -1
  77. package/vona/src/suite/a-commerce/modules/commerce-promotion/test/couponTemplateFormLayout.test.ts +121 -0
  78. package/vona/src/suite/a-commerce/modules/commerce-siteweb/src/bean/ssrMenu.home.ts +4 -1
  79. package/vona/src/suite/a-commerce/modules/commerce-trade/package.json +4 -1
  80. package/vona/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +0 -21
  81. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/checkoutResult.tsx +3 -0
  82. package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/order.ts +79 -0
  83. package/vona/src/suite/a-commerce/modules/commerce-trade/test/orderSnapshot.test.ts +227 -0
  84. package/vona/src/suite/a-commerce/modules/commerce-trade/test/paymentOutcome.test.ts +121 -13
  85. package/vona/src/suite/a-commerce/modules/commerce-trade/test/refundLifecycle.test.ts +312 -0
  86. package/vona/src/suite-vendor/a-pay/modules/a-pay/package.json +76 -0
  87. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/index.ts +842 -0
  88. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/this.ts +2 -0
  89. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/bean.payProvider.ts +92 -0
  90. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/bean.payScene.ts +105 -0
  91. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/meta.index.ts +28 -0
  92. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/meta.redlock.ts +11 -0
  93. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/meta.version.ts +113 -0
  94. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/queue.outboxDispatch.ts +31 -0
  95. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/schedule.outboxDispatch.ts +11 -0
  96. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/controller/paymentSession.ts +55 -0
  97. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/controller/webhook.ts +47 -0
  98. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/dto/paymentSessionStart.tsx +8 -0
  99. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/dto/paymentSessionView.tsx +69 -0
  100. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/dto/webhookReceipt.tsx +12 -0
  101. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/outboxEvent.tsx +46 -0
  102. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/paymentAudit.tsx +36 -0
  103. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/paymentSession.tsx +72 -0
  104. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/providerOperation.tsx +54 -0
  105. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/refundOperation.tsx +37 -0
  106. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/webhookInbox.tsx +59 -0
  107. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/index.ts +3 -0
  108. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/lib/index.ts +2 -0
  109. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/lib/payProvider.ts +7 -0
  110. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/lib/payScene.ts +7 -0
  111. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/model/outboxEvent.ts +10 -0
  112. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/model/paymentAudit.ts +10 -0
  113. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/model/paymentSession.ts +10 -0
  114. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/model/providerOperation.ts +10 -0
  115. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/model/refundOperation.ts +10 -0
  116. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/model/webhookInbox.ts +10 -0
  117. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/outbox.ts +156 -0
  118. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/paymentSession.ts +278 -0
  119. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/providerOperation.ts +5 -0
  120. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/webhook.ts +127 -0
  121. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/types/index.ts +3 -0
  122. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/types/payProvider.ts +74 -0
  123. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/types/payScene.ts +63 -0
  124. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/types/payment.ts +151 -0
  125. package/vona/src/suite-vendor/a-pay/modules/a-pay/test/outbox.test.ts +209 -0
  126. package/vona/src/suite-vendor/a-pay/modules/a-pay/test/paymentSession.test.ts +153 -0
  127. package/vona/src/suite-vendor/a-pay/modules/a-pay/test/webhook.test.ts +278 -0
  128. package/vona/src/suite-vendor/a-pay/modules/a-pay/tsconfig.build.json +11 -0
  129. package/vona/src/suite-vendor/a-pay/modules/a-pay/tsconfig.json +7 -0
  130. package/vona/src/suite-vendor/a-pay/modules/pay-mock/package.json +55 -0
  131. package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/.metadata/index.ts +182 -0
  132. package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/.metadata/this.ts +2 -0
  133. package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/bean/payProvider.mock.ts +149 -0
  134. package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/controller/mockPayment.ts +25 -0
  135. package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/dto/mockPaymentComplete.tsx +13 -0
  136. package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/dto/mockPaymentReceipt.tsx +16 -0
  137. package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/index.ts +3 -0
  138. package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/lib/index.ts +1 -0
  139. package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/service/payMock.ts +78 -0
  140. package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/types/index.ts +10 -0
  141. package/vona/src/suite-vendor/a-pay/modules/pay-mock/test/payMock.test.ts +141 -0
  142. package/vona/src/suite-vendor/a-pay/modules/pay-mock/tsconfig.build.json +11 -0
  143. package/vona/src/suite-vendor/a-pay/modules/pay-mock/tsconfig.json +7 -0
  144. package/vona/src/suite-vendor/a-pay/modules/pay-paypal/package.json +55 -0
  145. package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/.metadata/index.ts +62 -0
  146. package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/.metadata/this.ts +2 -0
  147. package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/bean/payProvider.paypal.ts +91 -0
  148. package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/index.ts +3 -0
  149. package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/lib/index.ts +1 -0
  150. package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/types/index.ts +9 -0
  151. package/vona/src/suite-vendor/a-pay/modules/pay-paypal/tsconfig.build.json +11 -0
  152. package/vona/src/suite-vendor/a-pay/modules/pay-paypal/tsconfig.json +7 -0
  153. package/vona/src/suite-vendor/a-pay/modules/pay-stripe/package.json +55 -0
  154. package/vona/src/suite-vendor/a-pay/modules/pay-stripe/src/.metadata/index.ts +62 -0
  155. package/vona/src/suite-vendor/a-pay/modules/pay-stripe/src/.metadata/this.ts +2 -0
  156. package/vona/src/suite-vendor/a-pay/modules/pay-stripe/src/bean/payProvider.stripe.ts +88 -0
  157. package/vona/src/suite-vendor/a-pay/modules/pay-stripe/src/index.ts +2 -0
  158. package/vona/src/suite-vendor/a-pay/modules/pay-stripe/src/types/index.ts +8 -0
  159. package/vona/src/suite-vendor/a-pay/modules/pay-stripe/tsconfig.build.json +11 -0
  160. package/vona/src/suite-vendor/a-pay/modules/pay-stripe/tsconfig.json +7 -0
  161. package/vona/src/suite-vendor/a-pay/package.json +15 -0
  162. package/vona/src/suite-vendor/a-pay/tsconfig.base.json +4 -0
  163. package/vona/src/suite-vendor/a-pay/tsconfig.json +19 -0
  164. package/zova/env/.env +1 -0
  165. package/zova/openapi.config.ts +5 -1
  166. package/zova/package.original.json +1 -1
  167. package/zova/packages-cli/cli/package.json +2 -2
  168. package/zova/packages-cli/cli-set-front/cli/templates/openapi/config/boilerplate/project/openapi.config.ts +5 -1
  169. package/zova/packages-cli/cli-set-front/package.json +1 -1
  170. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.openapi.generate.ts +8 -0
  171. package/zova/packages-cli/cli-set-front/src/lib/common/cliCreatePage.ts +7 -24
  172. package/zova/packages-cli/cli-set-front/src/lib/common/utils.ts +10 -1
  173. package/zova/packages-utils/zova-jsx/package.json +2 -2
  174. package/zova/packages-zova/zova/package.json +3 -3
  175. package/zova/packages-zova/zova-core/package.json +1 -1
  176. package/zova/packages-zova/zova-core/src/types/interface/component.ts +5 -0
  177. package/zova/pnpm-lock.yaml +96 -26
  178. package/zova/src/front/config/config/config.cabloyCommerce.ts +1 -1
  179. package/zova/src/suite/a-commerce/modules/commerce-promotion/src/api/openapi/schemas.ts +110 -12
  180. package/zova/src/suite/a-commerce/modules/commerce-promotion/src/api/openapi/types.ts +1292 -160
  181. package/zova/src/suite/a-commerce/modules/commerce-trade/cli/openapi.config.ts +0 -1
  182. package/zova/src/suite/a-commerce/modules/commerce-trade/package.json +4 -1
  183. package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +1 -47
  184. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/schemas.ts +23 -8
  185. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/types.ts +249 -62
  186. package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/checkout/controller.tsx +5 -1
  187. package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/payment/controller.tsx +152 -39
  188. package/zova/src/suite/a-commerce/modules/commerce-trade/src/routes.ts +1 -1
  189. package/zova/src/suite-vendor/a-pay/modules/a-pay/cli/openapi.config.ts +9 -0
  190. package/zova/src/suite-vendor/a-pay/modules/a-pay/package.json +53 -0
  191. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/component/paymentNextAction.ts +31 -0
  192. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/index.ts +217 -0
  193. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/this.ts +2 -0
  194. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/openapi/baseURL.ts +5 -0
  195. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/openapi/index.ts +3 -0
  196. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/openapi/schemas.ts +584 -0
  197. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/openapi/types.ts +9324 -0
  198. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/paymentSession.ts +52 -0
  199. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/apiSchema/paymentSession.ts +20 -0
  200. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/component/paymentNextAction/controller.tsx +76 -0
  201. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/index.ts +3 -0
  202. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/lib/index.ts +1 -0
  203. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/model/paymentSession.ts +32 -0
  204. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/service/paymentCoordinator.ts +13 -0
  205. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/types/index.ts +1 -0
  206. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/types/payment.ts +25 -0
  207. package/zova/src/suite-vendor/a-pay/modules/a-pay/tsconfig.build.json +13 -0
  208. package/zova/src/suite-vendor/a-pay/modules/a-pay/tsconfig.json +5 -0
  209. package/zova/src/suite-vendor/a-pay/modules/pay-mock/cli/openapi.config.ts +9 -0
  210. package/zova/src/suite-vendor/a-pay/modules/pay-mock/package.json +53 -0
  211. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/.metadata/index.ts +140 -0
  212. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/.metadata/this.ts +2 -0
  213. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/openapi/baseURL.ts +5 -0
  214. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/openapi/index.ts +3 -0
  215. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/openapi/schemas.ts +584 -0
  216. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/openapi/types.ts +9324 -0
  217. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/payMockPayment.ts +34 -0
  218. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/apiSchema/payMockPayment.ts +13 -0
  219. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/index.ts +1 -0
  220. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/model/payMockPayment.ts +20 -0
  221. package/zova/src/suite-vendor/a-pay/modules/pay-mock/tsconfig.build.json +13 -0
  222. package/zova/src/suite-vendor/a-pay/modules/pay-mock/tsconfig.json +5 -0
  223. package/zova/src/suite-vendor/a-pay/modules/pay-paypal/package.json +52 -0
  224. package/zova/src/suite-vendor/a-pay/modules/pay-paypal/src/.metadata/index.ts +26 -0
  225. package/zova/src/suite-vendor/a-pay/modules/pay-paypal/src/.metadata/this.ts +2 -0
  226. package/zova/src/suite-vendor/a-pay/modules/pay-paypal/src/index.ts +1 -0
  227. package/zova/src/suite-vendor/a-pay/modules/pay-paypal/tsconfig.build.json +13 -0
  228. package/zova/src/suite-vendor/a-pay/modules/pay-paypal/tsconfig.json +5 -0
  229. package/zova/src/suite-vendor/a-pay/modules/pay-stripe/package.json +52 -0
  230. package/zova/src/suite-vendor/a-pay/modules/pay-stripe/src/.metadata/index.ts +26 -0
  231. package/zova/src/suite-vendor/a-pay/modules/pay-stripe/src/.metadata/this.ts +2 -0
  232. package/zova/src/suite-vendor/a-pay/modules/pay-stripe/src/index.ts +1 -0
  233. package/zova/src/suite-vendor/a-pay/modules/pay-stripe/tsconfig.build.json +13 -0
  234. package/zova/src/suite-vendor/a-pay/modules/pay-stripe/tsconfig.json +5 -0
  235. package/zova/src/suite-vendor/a-pay/package.json +15 -0
  236. package/zova/src/suite-vendor/a-pay/tsconfig.base.json +4 -0
  237. package/zova/src/suite-vendor/a-pay/tsconfig.json +4 -0
  238. package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
  239. package/zova/src/suite-vendor/a-zova/package.json +2 -2
  240. package/vona/src/suite/a-commerce/modules/commerce-trade/src/controller/payment.ts +0 -23
  241. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/commerceTradePayment.ts +0 -36
  242. package/zova/src/suite/a-commerce/modules/commerce-trade/src/apiSchema/commerceTradePayment.ts +0 -13
  243. package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/payment.ts +0 -25
  244. /package/vona/patches/{zova-core@5.1.79.patch → zova-core@5.1.81.patch} +0 -0
@@ -159,6 +159,77 @@ async function createPaidOrder(suffix: string): Promise<IFixture> {
159
159
  return fixture;
160
160
  }
161
161
 
162
+ async function runInMockCtx<TResult>(
163
+ customerName: string | undefined,
164
+ operation: () => Promise<TResult>,
165
+ ): Promise<TResult> {
166
+ return await app.bean.executor.mockCtx(async () => {
167
+ if (customerName === undefined) {
168
+ await app.bean.passport.signinMock();
169
+ } else {
170
+ await app.bean.passport.signinMock(customerName as any);
171
+ }
172
+ try {
173
+ return await operation();
174
+ } finally {
175
+ await app.bean.passport.signout();
176
+ }
177
+ });
178
+ }
179
+
180
+ async function withTimeout<TResult>(promise: Promise<TResult>, message: string): Promise<TResult> {
181
+ let timeout: ReturnType<typeof setTimeout> | undefined;
182
+ try {
183
+ return await Promise.race([
184
+ promise,
185
+ new Promise<never>((_, reject) => {
186
+ timeout = setTimeout(() => reject(new Error(message)), 5_000);
187
+ }),
188
+ ]);
189
+ } finally {
190
+ if (timeout) clearTimeout(timeout);
191
+ }
192
+ }
193
+
194
+ async function waitForHolderStage(
195
+ entered: Promise<void>,
196
+ holder: Promise<unknown>,
197
+ label: string,
198
+ ): Promise<void> {
199
+ return await withTimeout(
200
+ Promise.race([
201
+ entered,
202
+ holder.then(
203
+ () =>
204
+ Promise.reject(new Error(`${label} completed before reaching its lock-holding stage`)),
205
+ error => Promise.reject(error),
206
+ ),
207
+ ]),
208
+ `${label} did not reach its lock-holding stage`,
209
+ );
210
+ }
211
+
212
+ async function waitForPostgresWaiter(waiterPid: number, holderPid: number): Promise<void> {
213
+ const deadline = Date.now() + 5_000;
214
+ while (Date.now() < deadline) {
215
+ const result = await app.bean.database.current.connection.raw(
216
+ `
217
+ select wait_event_type
218
+ from pg_stat_activity
219
+ where pid = ?
220
+ and ? = any(pg_blocking_pids(pid))
221
+ `,
222
+ [waiterPid, holderPid],
223
+ );
224
+ if (result.rows[0]) {
225
+ assert.equal(result.rows[0].wait_event_type, 'Lock');
226
+ return;
227
+ }
228
+ await new Promise(resolve => setTimeout(resolve, 10));
229
+ }
230
+ assert.fail(`PostgreSQL backend ${waiterPid} was not blocked by backend ${holderPid}`);
231
+ }
232
+
162
233
  describe('refundLifecycle.test.ts', { concurrency: false, sequential: true }, () => {
163
234
  let releaseTestLock: (() => void) | undefined;
164
235
 
@@ -295,6 +366,247 @@ describe('refundLifecycle.test.ts', { concurrency: false, sequential: true }, ()
295
366
  });
296
367
  });
297
368
 
369
+ it('accepts one concurrent PostgreSQL refund success without duplicate effects', async t => {
370
+ if (process.env.DATABASE_DEFAULT_CLIENT !== 'pg') {
371
+ t.skip('requires PostgreSQL row-lock contention');
372
+ return;
373
+ }
374
+ const fixture: IFixture = {};
375
+ try {
376
+ await app.bean.executor.mockCtx(async () => {
377
+ Object.assign(fixture, await createPaidOrder(randomUUID().slice(0, 12)));
378
+ await app.bean.passport.signout();
379
+ });
380
+ await runInMockCtx(fixture.customerName, async () => {
381
+ await app.scope('commerce-trade').service.order.requestRefund(fixture.orderId!, {
382
+ reason: 'concurrent outcome request',
383
+ idempotencyKey: 'concurrent-outcome-request-1',
384
+ });
385
+ });
386
+ await runInMockCtx(undefined, async () => {
387
+ await app.scope('commerce-trade').service.order.approveRefund(fixture.orderId!, {
388
+ reason: 'concurrent outcome approval',
389
+ idempotencyKey: 'concurrent-outcome-approval-1',
390
+ });
391
+ });
392
+
393
+ const entered = Promise.withResolvers<void>();
394
+ const release = Promise.withResolvers<void>();
395
+ let holderPid: number | undefined;
396
+ const holder = runInMockCtx(undefined, async () => {
397
+ return await app
398
+ .scope('commerce-trade')
399
+ .service.order.applyRefundOutcomeForTest(
400
+ fixture.orderId!,
401
+ { outcome: 'succeeded', idempotencyKey: 'concurrent-outcome-success-1' },
402
+ async stage => {
403
+ if (stage !== 'afterRefundAttemptState') return;
404
+ const result = await app.bean.database.current.connection.raw(
405
+ 'select pg_backend_pid() as pid',
406
+ );
407
+ holderPid = result.rows[0].pid;
408
+ entered.resolve();
409
+ await release.promise;
410
+ },
411
+ );
412
+ });
413
+ const waiterReady = Promise.withResolvers<void>();
414
+ const releaseWaiter = Promise.withResolvers<void>();
415
+ let waiterPid: number | undefined;
416
+ let waiter: Promise<unknown> | undefined;
417
+ let results: PromiseSettledResult<unknown>[] | undefined;
418
+ try {
419
+ await waitForHolderStage(entered.promise, holder, 'refund success holder');
420
+ assert.notEqual(holderPid, undefined);
421
+ waiter = runInMockCtx(undefined, async () => {
422
+ return await app
423
+ .scope('commerce-trade')
424
+ .service.order.applyRefundOutcomeForTest(
425
+ fixture.orderId!,
426
+ { outcome: 'succeeded', idempotencyKey: 'concurrent-outcome-success-1' },
427
+ async stage => {
428
+ if (stage !== 'beforeRefundOutcomeOrderLock') return;
429
+ const result = await app.bean.database.current.connection.raw(
430
+ 'select pg_backend_pid() as pid',
431
+ );
432
+ waiterPid = result.rows[0].pid;
433
+ waiterReady.resolve();
434
+ await releaseWaiter.promise;
435
+ },
436
+ );
437
+ });
438
+ await waitForHolderStage(waiterReady.promise, waiter, 'refund success waiter');
439
+ assert.notEqual(waiterPid, undefined);
440
+ releaseWaiter.resolve();
441
+ await app.bean.executor.mockCtx(async () => {
442
+ await waitForPostgresWaiter(waiterPid!, holderPid!);
443
+ });
444
+ } finally {
445
+ releaseWaiter.resolve();
446
+ release.resolve();
447
+ results = await Promise.allSettled([holder, waiter].filter(Boolean));
448
+ }
449
+ assert.equal(
450
+ results!.filter(result => result.status === 'fulfilled').length,
451
+ 2,
452
+ JSON.stringify(results),
453
+ );
454
+ const [first, second] = results!;
455
+ if (first.status !== 'fulfilled' || second.status !== 'fulfilled') return;
456
+ assert.deepEqual(second.value, first.value);
457
+ await app.bean.executor.mockCtx(async () => {
458
+ const trade = app.scope('commerce-trade');
459
+ const payment = app.scope('commerce-payment');
460
+ const line = await trade.model.orderLine.get({ orderId: fixture.orderId });
461
+ const reservation = await trade.model.stockReservation.get({ orderLineId: line?.id });
462
+ const balance = await trade.model.stockBalance.getById(fixture.balanceId!);
463
+ const grant = await app
464
+ .scope('commerce-promotion')
465
+ .model.couponGrant.getById(fixture.grantId!);
466
+ const requests = await payment.model.refundRequest.select({
467
+ where: { orderId: fixture.orderId },
468
+ });
469
+ const attempts = await payment.model.refundAttempt.select({
470
+ where: { refundRequestId: requests[0]?.id },
471
+ });
472
+ const refundAudits = await payment.model.refundAudit.select({
473
+ where: { orderId: fixture.orderId },
474
+ });
475
+ const orderAudits = await trade.model.orderAudit.select({
476
+ where: { orderId: fixture.orderId },
477
+ });
478
+ const stockAudits = await trade.model.stockAudit.select({
479
+ where: { skuId: fixture.skuId },
480
+ });
481
+ assert.deepEqual(
482
+ [requests.length, requests[0]?.state, attempts.length, attempts[0]?.state],
483
+ [1, 'refunded', 1, 'succeeded'],
484
+ );
485
+ assert.equal(reservation?.state, 'restored');
486
+ assert.deepEqual([balance?.onHand, balance?.reserved, balance?.available], [1, 0, 1]);
487
+ assert.equal(grant?.state, 'redeemed');
488
+ assert.equal(refundAudits.filter(audit => audit.toRefundState === 'refunded').length, 1);
489
+ assert.equal(orderAudits.filter(audit => audit.operation === 'refunded').length, 1);
490
+ assert.equal(stockAudits.filter(audit => audit.operation === 'restore').length, 1);
491
+ });
492
+ } finally {
493
+ await app.bean.executor.mockCtx(async () => {
494
+ await cleanup(fixture);
495
+ });
496
+ }
497
+ });
498
+
499
+ it('treats foreign customers and instances as absent without creating refund effects', async () => {
500
+ const fixture: IFixture = {};
501
+ let foreignUserId: number | undefined;
502
+ let foreignInstanceUserId: number | undefined;
503
+ try {
504
+ await app.bean.executor.mockCtx(async () => {
505
+ Object.assign(fixture, await createPaidOrder(randomUUID().slice(0, 12)));
506
+ const foreignName = `refund-foreign-${randomUUID().slice(0, 12)}`;
507
+ const foreign = await app.bean.user.register({ name: foreignName }, true);
508
+ foreignUserId = foreign.id as number;
509
+ await app.bean.passport.signout();
510
+ await app.bean.passport.signinMock(foreignName as any);
511
+ try {
512
+ assert.equal(
513
+ await app.scope('commerce-trade').service.order.viewMine(fixture.orderId!),
514
+ undefined,
515
+ );
516
+ await assert.rejects(
517
+ app.scope('commerce-trade').service.order.requestRefund(fixture.orderId!, {
518
+ reason: 'foreign customer',
519
+ idempotencyKey: 'foreign-customer-refund-1',
520
+ }),
521
+ (error: any) => error.code === 404,
522
+ );
523
+ } finally {
524
+ await app.bean.passport.signout();
525
+ }
526
+ });
527
+ await app.bean.executor.mockCtx(
528
+ async () => {
529
+ const foreignName = `refund-instance-${randomUUID().slice(0, 12)}`;
530
+ const foreign = await app.bean.user.register({ name: foreignName }, true);
531
+ foreignInstanceUserId = foreign.id as number;
532
+ await app.bean.passport.signinMock(foreignName as any);
533
+ try {
534
+ assert.equal(
535
+ await app.scope('commerce-trade').service.order.viewMine(fixture.orderId!),
536
+ undefined,
537
+ );
538
+ await assert.rejects(
539
+ app.scope('commerce-trade').service.order.requestRefund(fixture.orderId!, {
540
+ reason: 'foreign instance request',
541
+ idempotencyKey: 'foreign-instance-refund-request-1',
542
+ }),
543
+ (error: any) => error.code === 404,
544
+ );
545
+ await app.bean.passport.signout();
546
+ await app.bean.passport.signinMock();
547
+ for (const operation of [
548
+ () =>
549
+ app.scope('commerce-trade').service.order.approveRefund(fixture.orderId!, {
550
+ reason: 'foreign instance approval',
551
+ idempotencyKey: 'foreign-instance-refund-approval-1',
552
+ }),
553
+ () =>
554
+ app.scope('commerce-trade').service.order.applyRefundOutcome(fixture.orderId!, {
555
+ outcome: 'succeeded',
556
+ idempotencyKey: 'foreign-instance-refund-outcome-1',
557
+ }),
558
+ ]) {
559
+ await assert.rejects(operation(), (error: any) => error.code === 404);
560
+ }
561
+ } finally {
562
+ await app.bean.passport.signout();
563
+ }
564
+ },
565
+ { instanceName: 'shareTest' as any },
566
+ );
567
+ await app.bean.executor.mockCtx(async () => {
568
+ const order = await app.scope('commerce-trade').model.order.getById(fixture.orderId!);
569
+ const requests = await app.scope('commerce-payment').model.refundRequest.select({
570
+ where: { orderId: fixture.orderId },
571
+ });
572
+ const line = await app
573
+ .scope('commerce-trade')
574
+ .model.orderLine.get({ orderId: fixture.orderId });
575
+ const reservation = await app.scope('commerce-trade').model.stockReservation.get({
576
+ orderLineId: line?.id,
577
+ });
578
+ const balance = await app
579
+ .scope('commerce-trade')
580
+ .model.stockBalance.getById(fixture.balanceId!);
581
+ const grant = await app
582
+ .scope('commerce-promotion')
583
+ .model.couponGrant.getById(fixture.grantId!);
584
+ assert.equal(order?.state, 'paid');
585
+ assert.equal(requests.length, 0);
586
+ assert.equal(reservation?.state, 'consumed');
587
+ assert.deepEqual([balance?.onHand, balance?.reserved, balance?.available], [0, 0, 0]);
588
+ assert.equal(grant?.state, 'redeemed');
589
+ });
590
+ } finally {
591
+ await app.bean.executor.mockCtx(async () => {
592
+ if (foreignUserId !== undefined) {
593
+ await app.scope('home-user').model.roleUser.delete({ userId: foreignUserId });
594
+ await app.bean.user.removeById(foreignUserId);
595
+ }
596
+ await cleanup(fixture);
597
+ });
598
+ await app.bean.executor.mockCtx(
599
+ async () => {
600
+ if (foreignInstanceUserId !== undefined) {
601
+ await app.scope('home-user').model.roleUser.delete({ userId: foreignInstanceUserId });
602
+ await app.bean.user.removeById(foreignInstanceUserId);
603
+ }
604
+ },
605
+ { instanceName: 'shareTest' as any },
606
+ );
607
+ }
608
+ });
609
+
298
610
  it('denies anonymous and non-admin refund actions', async () => {
299
611
  await app.bean.executor.mockCtx(async () => {
300
612
  const fixture: IFixture = {};
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "vona-module-a-pay",
3
+ "version": "5.0.1",
4
+ "description": "",
5
+ "keywords": [
6
+ "Vona Module"
7
+ ],
8
+ "author": "",
9
+ "files": [
10
+ "assets",
11
+ "dist",
12
+ "src",
13
+ "cli"
14
+ ],
15
+ "type": "module",
16
+ "exports": {
17
+ ".": {
18
+ "types": [
19
+ "./src/index.ts",
20
+ "./dist/index.d.ts"
21
+ ],
22
+ "import": "./src/index.ts",
23
+ "default": "./dist/index.js"
24
+ },
25
+ "./package.json": "./package.json"
26
+ },
27
+ "scripts": {
28
+ "clean": "rimraf dist tsconfig.build.tsbuildinfo",
29
+ "tsc:publish": "npm run clean && node ../../../../../packages-cli/cli/src/bin/vona.ts :bin:buildModule --sourcemap && tsc -p tsconfig.build.json",
30
+ "prepublishOnly": "npm run tsc:publish",
31
+ "prepack": "clean-package",
32
+ "postpack": "clean-package restore"
33
+ },
34
+ "dependencies": {},
35
+ "devDependencies": {
36
+ "clean-package": "^2.2.0",
37
+ "rimraf": "^6.1.3"
38
+ },
39
+ "clean-package": {
40
+ "indent": 2,
41
+ "remove": [
42
+ "clean-package",
43
+ "devDependencies",
44
+ "exports.\\..import"
45
+ ]
46
+ },
47
+ "title": "a-pay",
48
+ "vonaModule": {
49
+ "fileVersion": 1,
50
+ "dependencies": {
51
+ "a-core": "5.0.0",
52
+ "a-index": "5.0.0",
53
+ "a-orm": "5.0.0",
54
+ "a-ormutils": "5.0.0",
55
+ "a-queue": "5.0.0",
56
+ "a-redlock": "5.0.0",
57
+ "a-schedule": "5.0.0",
58
+ "a-user": "5.0.0",
59
+ "a-vona": "5.0.0",
60
+ "a-web": "5.0.0"
61
+ },
62
+ "onions": {
63
+ "payProvider": {
64
+ "optionsGlobalInterfaceName": "IDecoratorPayProviderOptions",
65
+ "optionsGlobalInterfaceFrom": "vona-module-a-pay",
66
+ "scopeResource": true,
67
+ "boilerplate": "payProvider/boilerplate"
68
+ },
69
+ "payScene": {
70
+ "optionsGlobalInterfaceName": "IDecoratorPaySceneOptions",
71
+ "optionsGlobalInterfaceFrom": "vona-module-a-pay",
72
+ "boilerplate": "payScene/boilerplate"
73
+ }
74
+ }
75
+ }
76
+ }