cabloy 5.1.111 → 5.1.113

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 (385) hide show
  1. package/.cabloy-version +1 -1
  2. package/.claude/skills/cabloy-backend-scaffold/SKILL.md +31 -1
  3. package/.claude/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +21 -0
  4. package/.claude/skills/cabloy-frontend-scaffold/SKILL.md +3 -0
  5. package/.claude/skills/cabloy-frontend-scaffold/references/follow-up-checklist.md +4 -0
  6. package/.claude/skills/cabloy-master-detail/SKILL.md +13 -2
  7. package/.github/workflows/playwright-e2e.yml +77 -0
  8. package/.github/workflows/vona-test-pg.yml +8 -0
  9. package/.gitignore +1 -0
  10. package/CHANGELOG.md +30 -0
  11. package/CLAUDE.md +6 -1
  12. package/README.md +8 -8
  13. package/cabloy-docs/backend/crud-workflow.md +10 -0
  14. package/cabloy-docs/backend/foundation.md +29 -4
  15. package/cabloy-docs/backend/introduction.md +1 -1
  16. package/cabloy-docs/backend/migration-and-changes.md +13 -9
  17. package/cabloy-docs/backend/model-guide.md +9 -11
  18. package/cabloy-docs/backend/multi-instance-and-instance-resolution.md +18 -0
  19. package/cabloy-docs/backend/service-guide.md +1 -1
  20. package/cabloy-docs/backend/unit-testing.md +25 -0
  21. package/cabloy-docs/frontend/a-router-guide.md +1 -1
  22. package/cabloy-docs/frontend/introduction.md +1 -1
  23. package/cabloy-docs/frontend/navigation-guards-guide.md +20 -11
  24. package/cabloy-docs/frontend/route-alias-guide.md +24 -0
  25. package/cabloy-docs/frontend/scripts.md +71 -24
  26. package/cabloy-docs/frontend/ssr-init-data.md +25 -0
  27. package/cabloy-docs/frontend/ssr-review-checklist.md +17 -7
  28. package/cabloy-docs/frontend/use-state-data-best-practices.md +4 -0
  29. package/cabloy-docs/frontend/zova-router-under-the-hood.md +4 -1
  30. package/cabloy-docs/fullstack/comparison-with-other-frameworks.md +19 -13
  31. package/cabloy-docs/fullstack/introduction.md +10 -10
  32. package/cabloy-docs/fullstack/quickstart.md +23 -1
  33. package/cabloy-docs/index.md +14 -14
  34. package/cabloy-docs/reference/package-map.md +11 -7
  35. package/cabloy-docs/reference/repo-scripts.md +108 -23
  36. package/e2e/scripts/e2e.ts +1 -1
  37. package/e2e/scripts/startE2eVona.ts +51 -13
  38. package/e2e/specs/a-commerce/commerce.spec.ts +125 -1
  39. package/e2e/specs/{a-basic → cabloy-basic}/basic.spec.ts +12 -7
  40. package/package.json +2 -1
  41. package/scripts/init.ts +6 -12
  42. package/scripts/upgrade.ts +3 -1
  43. package/vona/packages-cli/cli/package.json +1 -1
  44. package/vona/packages-cli/cli-set-api/package.json +1 -1
  45. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.bin.test.ts +6 -9
  46. package/vona/packages-cli/cli-set-api/toolsIsolate/test.ts +50 -21
  47. package/vona/packages-vona/vona/package.json +1 -1
  48. package/vona/pnpm-lock.yaml +94 -163
  49. package/vona/src/backend/config/config/config.test.ts +1 -1
  50. package/vona/src/backend/config/config/config.ts +11 -0
  51. package/vona/src/suite/a-commerce/modules/commerce-catalog/package.json +4 -2
  52. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/.metadata/index.ts +732 -2
  53. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/.metadata/locales.ts +18 -0
  54. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/bean/meta.index.ts +14 -0
  55. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/bean/meta.version.ts +52 -0
  56. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/bean/ssrMenu.category.ts +30 -0
  57. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/bean/ssrMenu.product.ts +30 -0
  58. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/bean/ssrMenu.sku.ts +30 -0
  59. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/config/locale/en-us.ts +19 -0
  60. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/config/locale/zh-cn.ts +19 -0
  61. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/controller/category.ts +65 -0
  62. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/controller/product.ts +86 -0
  63. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/controller/sku.ts +65 -0
  64. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/categoryCreate.tsx +28 -0
  65. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/categorySelectReq.tsx +25 -0
  66. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/categorySelectRes.tsx +11 -0
  67. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/categorySelectResItem.tsx +39 -0
  68. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/categoryUpdate.tsx +28 -0
  69. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/categoryView.tsx +25 -0
  70. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productCreate.tsx +28 -0
  71. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productPublic.tsx +38 -0
  72. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productPublicSelectReq.tsx +23 -0
  73. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productPublicSelectRes.tsx +11 -0
  74. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productPublicSku.tsx +25 -0
  75. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productSelectReq.tsx +25 -0
  76. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productSelectRes.tsx +11 -0
  77. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productSelectResItem.tsx +39 -0
  78. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productUpdate.tsx +28 -0
  79. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productView.tsx +25 -0
  80. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/skuCreate.tsx +28 -0
  81. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/skuSelectReq.tsx +25 -0
  82. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/skuSelectRes.tsx +11 -0
  83. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/skuSelectResItem.tsx +39 -0
  84. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/skuUpdate.tsx +28 -0
  85. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/skuView.tsx +25 -0
  86. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/entity/category.tsx +53 -0
  87. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/entity/product.tsx +48 -0
  88. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/entity/sku.tsx +66 -0
  89. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/index.ts +1 -0
  90. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/model/category.ts +15 -0
  91. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/model/product.ts +46 -0
  92. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/model/sku.ts +18 -0
  93. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/service/category.ts +47 -0
  94. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/service/product.ts +162 -0
  95. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/service/sku.ts +76 -0
  96. package/vona/src/suite/a-commerce/modules/commerce-catalog/test/catalog.test.ts +592 -0
  97. package/vona/src/suite/a-commerce/modules/commerce-catalog/test/category.test.ts +91 -0
  98. package/vona/src/suite/a-commerce/modules/commerce-catalog/test/product.test.ts +154 -0
  99. package/vona/src/suite/a-commerce/modules/commerce-catalog/test/sku.test.ts +190 -0
  100. package/vona/src/suite/a-commerce/modules/commerce-member/package.json +2 -1
  101. package/vona/src/suite/a-commerce/modules/commerce-member/src/.metadata/index.ts +342 -5
  102. package/vona/src/suite/a-commerce/modules/commerce-member/src/.metadata/locales.ts +18 -0
  103. package/vona/src/suite/a-commerce/modules/commerce-member/src/bean/meta.index.ts +12 -0
  104. package/vona/src/suite/a-commerce/modules/commerce-member/src/bean/meta.version.ts +31 -0
  105. package/vona/src/suite/a-commerce/modules/commerce-member/src/config/locale/en-us.ts +12 -0
  106. package/vona/src/suite/a-commerce/modules/commerce-member/src/config/locale/zh-cn.ts +12 -0
  107. package/vona/src/suite/a-commerce/modules/commerce-member/src/controller/address.ts +59 -0
  108. package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressCreate.tsx +39 -0
  109. package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressSelectReq.tsx +30 -0
  110. package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressSelectRes.tsx +11 -0
  111. package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressSelectResItem.tsx +53 -0
  112. package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressUpdate.tsx +39 -0
  113. package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressView.tsx +39 -0
  114. package/vona/src/suite/a-commerce/modules/commerce-member/src/entity/address.tsx +76 -0
  115. package/vona/src/suite/a-commerce/modules/commerce-member/src/index.ts +1 -0
  116. package/vona/src/suite/a-commerce/modules/commerce-member/src/model/address.ts +10 -0
  117. package/vona/src/suite/a-commerce/modules/commerce-member/src/service/address.ts +84 -0
  118. package/vona/src/suite/a-commerce/modules/commerce-member/test/addressOwnership.test.ts +203 -0
  119. package/vona/src/suite/a-commerce/modules/commerce-seed/package.json +52 -0
  120. package/vona/src/suite/a-commerce/modules/commerce-seed/src/.metadata/index.ts +55 -0
  121. package/vona/src/suite/a-commerce/modules/commerce-seed/src/.metadata/this.ts +2 -0
  122. package/vona/src/suite/a-commerce/modules/commerce-seed/src/bean/meta.version.ts +80 -0
  123. package/vona/src/suite/a-commerce/modules/commerce-seed/src/index.ts +1 -0
  124. package/vona/src/suite/a-commerce/modules/commerce-seed/tsconfig.build.json +11 -0
  125. package/vona/src/suite/a-commerce/modules/commerce-seed/tsconfig.json +7 -0
  126. package/vona/src/suite/a-commerce/modules/commerce-siteadmin/package.json +4 -2
  127. package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/.metadata/index.ts +192 -2
  128. package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/.metadata/locales.ts +18 -0
  129. package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/bean/meta.version.ts +32 -0
  130. package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/bean/ssrMenu.home.ts +3 -1
  131. package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/bean/ssrMenuGroup.catalog.ts +21 -0
  132. package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/bean/ssrMenuGroup.inventory.ts +21 -0
  133. package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/config/locale/en-us.ts +5 -0
  134. package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/config/locale/zh-cn.ts +5 -0
  135. package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/controller/operator.ts +21 -0
  136. package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/dto/operatorContext.ts +21 -0
  137. package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/index.ts +1 -0
  138. package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/service/operator.ts +18 -0
  139. package/vona/src/suite/a-commerce/modules/commerce-siteadmin/test/meta.version.test.ts +44 -0
  140. package/vona/src/suite/a-commerce/modules/commerce-siteadmin/test/operatorAccess.test.ts +55 -0
  141. package/vona/src/suite/a-commerce/modules/commerce-siteadmin/test/ssrMenu.test.ts +77 -0
  142. package/vona/src/suite/a-commerce/modules/commerce-trade/package.json +2 -1
  143. package/vona/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +773 -2
  144. package/vona/src/suite/a-commerce/modules/commerce-trade/src/.metadata/locales.ts +18 -0
  145. package/vona/src/suite/a-commerce/modules/commerce-trade/src/bean/meta.index.ts +23 -0
  146. package/vona/src/suite/a-commerce/modules/commerce-trade/src/bean/meta.version.ts +83 -0
  147. package/vona/src/suite/a-commerce/modules/commerce-trade/src/bean/ssrMenu.stockAudit.ts +30 -0
  148. package/vona/src/suite/a-commerce/modules/commerce-trade/src/bean/ssrMenu.stockBalance.ts +30 -0
  149. package/vona/src/suite/a-commerce/modules/commerce-trade/src/config/locale/en-us.ts +29 -0
  150. package/vona/src/suite/a-commerce/modules/commerce-trade/src/config/locale/zh-cn.ts +29 -0
  151. package/vona/src/suite/a-commerce/modules/commerce-trade/src/controller/cart.ts +48 -0
  152. package/vona/src/suite/a-commerce/modules/commerce-trade/src/controller/stockAudit.ts +38 -0
  153. package/vona/src/suite/a-commerce/modules/commerce-trade/src/controller/stockBalance.ts +49 -0
  154. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/cartAddItem.tsx +19 -0
  155. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/cartItem.tsx +34 -0
  156. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/cartUpdateItem.tsx +15 -0
  157. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/cartView.tsx +18 -0
  158. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockAdjust.tsx +32 -0
  159. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockAuditCreate.tsx +28 -0
  160. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockAuditSelectReq.tsx +28 -0
  161. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockAuditSelectRes.tsx +11 -0
  162. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockAuditSelectResItem.tsx +33 -0
  163. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockAuditUpdate.tsx +28 -0
  164. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockAuditView.tsx +25 -0
  165. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockBalanceCreate.tsx +28 -0
  166. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockBalanceSelectReq.tsx +28 -0
  167. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockBalanceSelectRes.tsx +11 -0
  168. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockBalanceSelectResItem.tsx +33 -0
  169. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockBalanceUpdate.tsx +28 -0
  170. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockBalanceView.tsx +25 -0
  171. package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/cart.tsx +24 -0
  172. package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/cartItem.tsx +30 -0
  173. package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/stockAudit.tsx +118 -0
  174. package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/stockBalance.tsx +53 -0
  175. package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/stockReservation.tsx +63 -0
  176. package/vona/src/suite/a-commerce/modules/commerce-trade/src/index.ts +1 -0
  177. package/vona/src/suite/a-commerce/modules/commerce-trade/src/model/cart.ts +17 -0
  178. package/vona/src/suite/a-commerce/modules/commerce-trade/src/model/cartItem.ts +10 -0
  179. package/vona/src/suite/a-commerce/modules/commerce-trade/src/model/stockAudit.ts +10 -0
  180. package/vona/src/suite/a-commerce/modules/commerce-trade/src/model/stockBalance.ts +15 -0
  181. package/vona/src/suite/a-commerce/modules/commerce-trade/src/model/stockReservation.ts +10 -0
  182. package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/cart.ts +152 -0
  183. package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/stockAudit.ts +20 -0
  184. package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/stockBalance.ts +342 -0
  185. package/vona/src/suite/a-commerce/modules/commerce-trade/test/cartOwnership.test.ts +174 -0
  186. package/vona/src/suite/a-commerce/modules/commerce-trade/test/stockAudit.test.ts +37 -0
  187. package/vona/src/suite/a-commerce/modules/commerce-trade/test/stockBalance.test.ts +389 -0
  188. package/vona/src/suite/a-commerce/modules/commerce-trade/test/stockReservation.test.ts +457 -0
  189. package/vona/src/suite/a-commerce/package.json +1 -0
  190. package/vona/src/suite/a-commerce/tsconfig.json +3 -0
  191. package/vona/src/suite/a-home/modules/home-user/src/.metadata/index.ts +7 -1
  192. package/vona/src/suite/a-home/modules/home-user/test/role.test.ts +14 -23
  193. package/vona/src/suite/a-training/modules/training-record/src/.metadata/index.ts +10 -8
  194. package/vona/src/suite/a-training/modules/training-recordsubject/src/.metadata/index.ts +2 -0
  195. package/vona/src/suite/a-training/modules/training-student/src/.metadata/index.ts +3 -1
  196. package/vona/src/suite-vendor/a-auth/modules/a-auth/package.json +1 -1
  197. package/vona/src/suite-vendor/a-auth/modules/a-auth/src/.metadata/index.ts +7 -3
  198. package/vona/src/suite-vendor/a-auth/modules/auth-simple/package.json +1 -1
  199. package/vona/src/suite-vendor/a-auth/modules/auth-simple/src/.metadata/index.ts +2 -0
  200. package/vona/src/suite-vendor/a-auth/package.json +1 -1
  201. package/vona/src/suite-vendor/a-cabloy/modules/a-datasharding/package.json +1 -1
  202. package/vona/src/suite-vendor/a-cabloy/modules/a-datasharding/src/.metadata/index.ts +1 -1
  203. package/vona/src/suite-vendor/a-cabloy/modules/a-datasource/package.json +1 -1
  204. package/vona/src/suite-vendor/a-cabloy/modules/a-datasource/src/.metadata/index.ts +3 -1
  205. package/vona/src/suite-vendor/a-cabloy/modules/a-socket/package.json +1 -1
  206. package/vona/src/suite-vendor/a-cabloy/modules/a-socket/src/.metadata/index.ts +1 -1
  207. package/vona/src/suite-vendor/a-cabloy/modules/a-ssr/package.json +1 -1
  208. package/vona/src/suite-vendor/a-cabloy/modules/a-ssr/src/.metadata/index.ts +47 -47
  209. package/vona/src/suite-vendor/a-cabloy/modules/a-ssrhmr/package.json +1 -1
  210. package/vona/src/suite-vendor/a-cabloy/modules/a-ssrhmr/src/.metadata/index.ts +1 -1
  211. package/vona/src/suite-vendor/a-cabloy/modules/a-status/package.json +1 -1
  212. package/vona/src/suite-vendor/a-cabloy/modules/a-status/src/.metadata/index.ts +2 -0
  213. package/vona/src/suite-vendor/a-cabloy/package.json +1 -1
  214. package/vona/src/suite-vendor/a-captcha/modules/a-captcha/package.json +1 -1
  215. package/vona/src/suite-vendor/a-captcha/modules/a-captcha/src/.metadata/index.ts +1 -1
  216. package/vona/src/suite-vendor/a-captcha/package.json +1 -1
  217. package/vona/src/suite-vendor/a-file/modules/a-file/package.json +1 -1
  218. package/vona/src/suite-vendor/a-file/modules/a-file/src/.metadata/index.ts +42 -38
  219. package/vona/src/suite-vendor/a-file/package.json +2 -2
  220. package/vona/src/suite-vendor/a-image/modules/a-image/package.json +1 -1
  221. package/vona/src/suite-vendor/a-image/modules/a-image/src/.metadata/index.ts +42 -38
  222. package/vona/src/suite-vendor/a-image/modules/image-cloudflare/package.json +1 -1
  223. package/vona/src/suite-vendor/a-image/modules/image-cloudflare/src/.metadata/index.ts +42 -27
  224. package/vona/src/suite-vendor/a-image/package.json +1 -1
  225. package/vona/src/suite-vendor/a-paypal/modules/a-paypal/package.json +1 -1
  226. package/vona/src/suite-vendor/a-paypal/modules/a-paypal/src/.metadata/index.ts +3 -1
  227. package/vona/src/suite-vendor/a-paypal/package.json +1 -1
  228. package/vona/src/suite-vendor/a-vona/modules/a-beanmutate/package.json +1 -1
  229. package/vona/src/suite-vendor/a-vona/modules/a-beanmutate/src/.metadata/index.ts +1 -1
  230. package/vona/src/suite-vendor/a-vona/modules/a-body/package.json +1 -1
  231. package/vona/src/suite-vendor/a-vona/modules/a-body/src/.metadata/index.ts +2 -2
  232. package/vona/src/suite-vendor/a-vona/modules/a-cache/package.json +1 -1
  233. package/vona/src/suite-vendor/a-vona/modules/a-cache/src/.metadata/index.ts +1 -1
  234. package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
  235. package/vona/src/suite-vendor/a-vona/modules/a-core/src/.metadata/index.ts +1 -1
  236. package/vona/src/suite-vendor/a-vona/modules/a-error/package.json +1 -1
  237. package/vona/src/suite-vendor/a-vona/modules/a-error/src/.metadata/index.ts +1 -1
  238. package/vona/src/suite-vendor/a-vona/modules/a-event/package.json +1 -1
  239. package/vona/src/suite-vendor/a-vona/modules/a-event/src/.metadata/index.ts +1 -1
  240. package/vona/src/suite-vendor/a-vona/modules/a-executor/package.json +1 -1
  241. package/vona/src/suite-vendor/a-vona/modules/a-executor/src/.metadata/index.ts +1 -1
  242. package/vona/src/suite-vendor/a-vona/modules/a-hmr/package.json +1 -1
  243. package/vona/src/suite-vendor/a-vona/modules/a-hmr/src/.metadata/index.ts +1 -1
  244. package/vona/src/suite-vendor/a-vona/modules/a-instance/package.json +1 -1
  245. package/vona/src/suite-vendor/a-vona/modules/a-instance/src/.metadata/index.ts +3 -1
  246. package/vona/src/suite-vendor/a-vona/modules/a-jwt/package.json +1 -1
  247. package/vona/src/suite-vendor/a-vona/modules/a-jwt/src/.metadata/index.ts +1 -1
  248. package/vona/src/suite-vendor/a-vona/modules/a-logger/package.json +1 -1
  249. package/vona/src/suite-vendor/a-vona/modules/a-logger/src/.metadata/index.ts +1 -1
  250. package/vona/src/suite-vendor/a-vona/modules/a-mail/package.json +1 -1
  251. package/vona/src/suite-vendor/a-vona/modules/a-mail/src/.metadata/index.ts +3 -1
  252. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/package.json +1 -1
  253. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/.metadata/index.ts +1 -1
  254. package/vona/src/suite-vendor/a-vona/modules/a-onion/package.json +1 -1
  255. package/vona/src/suite-vendor/a-vona/modules/a-onion/src/.metadata/index.ts +1 -1
  256. package/vona/src/suite-vendor/a-vona/modules/a-openapi/package.json +1 -1
  257. package/vona/src/suite-vendor/a-vona/modules/a-openapi/src/.metadata/index.ts +1 -1
  258. package/vona/src/suite-vendor/a-vona/modules/a-orm/cli/model/metadata/generate.ts +5 -11
  259. package/vona/src/suite-vendor/a-vona/modules/a-orm/package.json +1 -1
  260. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/bean.model/bean.model_cache.ts +52 -0
  261. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoGet.ts +4 -10
  262. package/vona/src/suite-vendor/a-vona/modules/a-redis/package.json +1 -1
  263. package/vona/src/suite-vendor/a-vona/modules/a-redis/src/.metadata/index.ts +1 -1
  264. package/vona/src/suite-vendor/a-vona/modules/a-security/package.json +1 -1
  265. package/vona/src/suite-vendor/a-vona/modules/a-security/src/.metadata/index.ts +1 -1
  266. package/vona/src/suite-vendor/a-vona/modules/a-serialization/package.json +1 -1
  267. package/vona/src/suite-vendor/a-vona/modules/a-serialization/src/.metadata/index.ts +1 -1
  268. package/vona/src/suite-vendor/a-vona/modules/a-startup/package.json +1 -1
  269. package/vona/src/suite-vendor/a-vona/modules/a-startup/src/service/startup.ts +2 -2
  270. package/vona/src/suite-vendor/a-vona/modules/a-summer/package.json +1 -1
  271. package/vona/src/suite-vendor/a-vona/modules/a-summer/src/.metadata/index.ts +1 -1
  272. package/vona/src/suite-vendor/a-vona/modules/a-user/package.json +1 -1
  273. package/vona/src/suite-vendor/a-vona/modules/a-user/src/.metadata/index.ts +4 -5
  274. package/vona/src/suite-vendor/a-vona/modules/a-validation/package.json +1 -1
  275. package/vona/src/suite-vendor/a-vona/modules/a-validation/src/.metadata/index.ts +1 -1
  276. package/vona/src/suite-vendor/a-vona/modules/a-version/package.json +1 -1
  277. package/vona/src/suite-vendor/a-vona/modules/a-version/src/.metadata/index.ts +6 -0
  278. package/vona/src/suite-vendor/a-vona/modules/a-version/src/service/version.ts +12 -12
  279. package/vona/src/suite-vendor/a-vona/modules/a-version/src/types/version.ts +4 -4
  280. package/vona/src/suite-vendor/a-vona/modules/a-web/package.json +1 -1
  281. package/vona/src/suite-vendor/a-vona/modules/a-web/src/.metadata/index.ts +1 -1
  282. package/vona/src/suite-vendor/a-vona/modules/a-worker/package.json +1 -1
  283. package/vona/src/suite-vendor/a-vona/modules/a-worker/src/.metadata/index.ts +1 -1
  284. package/vona/src/suite-vendor/a-vona/package.json +1 -1
  285. package/zova/packages-cli/cli/package.json +2 -2
  286. package/zova/packages-cli/cli-set-front/package.json +1 -1
  287. package/zova/packages-cli/cli-set-front/src/lib/bean/toolsMetadata/generateScope.ts +1 -1
  288. package/zova/packages-zova/zova/package.json +2 -2
  289. package/zova/pnpm-lock.yaml +9 -9
  290. package/zova/src/front/config/config/config.cabloyCommerce.ts +5 -1
  291. package/zova/src/front/config/config/config.cabloyCommerceAdmin.ts +2 -1
  292. package/zova/src/suite/a-commerce/modules/commerce-catalog/cli/openapi.config.ts +9 -0
  293. package/zova/src/suite/a-commerce/modules/commerce-catalog/package.json +2 -1
  294. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/.metadata/index.ts +202 -3
  295. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/.metadata/locales.ts +7 -0
  296. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/.metadata/page/catalogue.ts +23 -0
  297. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/.metadata/page/product.ts +19 -0
  298. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/api/commerceCatalogProduct.ts +52 -0
  299. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/api/openapi/baseURL.ts +5 -0
  300. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/api/openapi/index.ts +3 -0
  301. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/api/openapi/schemas.ts +412 -0
  302. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/api/openapi/types.ts +7159 -0
  303. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/apiSchema/commerceCatalogProduct.ts +20 -0
  304. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/config/locale/en-us.ts +8 -0
  305. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/config/locale/zh-cn.ts +8 -0
  306. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/index.ts +1 -0
  307. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/model/catalogue.ts +38 -0
  308. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/page/catalogue/controller.tsx +71 -0
  309. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/page/product/controller.tsx +107 -0
  310. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/routes.ts +19 -0
  311. package/zova/src/suite/a-commerce/modules/commerce-member/cli/openapi.config.ts +9 -0
  312. package/zova/src/suite/a-commerce/modules/commerce-member/package.json +2 -1
  313. package/zova/src/suite/a-commerce/modules/commerce-member/src/.metadata/index.ts +182 -3
  314. package/zova/src/suite/a-commerce/modules/commerce-member/src/.metadata/locales.ts +7 -0
  315. package/zova/src/suite/a-commerce/modules/commerce-member/src/.metadata/page/address.ts +19 -0
  316. package/zova/src/suite/a-commerce/modules/commerce-member/src/api/commerceMemberAddress.ts +111 -0
  317. package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/baseURL.ts +5 -0
  318. package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/index.ts +3 -0
  319. package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/schemas.ts +432 -0
  320. package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/types.ts +7445 -0
  321. package/zova/src/suite/a-commerce/modules/commerce-member/src/apiSchema/commerceMemberAddress.ts +35 -0
  322. package/zova/src/suite/a-commerce/modules/commerce-member/src/config/locale/en-us.ts +17 -0
  323. package/zova/src/suite/a-commerce/modules/commerce-member/src/config/locale/zh-cn.ts +17 -0
  324. package/zova/src/suite/a-commerce/modules/commerce-member/src/index.ts +1 -0
  325. package/zova/src/suite/a-commerce/modules/commerce-member/src/model/address.ts +38 -0
  326. package/zova/src/suite/a-commerce/modules/commerce-member/src/page/address/controller.tsx +194 -0
  327. package/zova/src/suite/a-commerce/modules/commerce-member/src/routes.ts +12 -0
  328. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/cli/openapi.config.ts +9 -0
  329. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/package.json +2 -1
  330. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/.metadata/index.ts +175 -3
  331. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/.metadata/locales.ts +7 -0
  332. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/.metadata/page/dashboard.ts +9 -0
  333. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/api/commerceSiteadminOperator.ts +25 -0
  334. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/api/openapi/baseURL.ts +5 -0
  335. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/api/openapi/index.ts +3 -0
  336. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/api/openapi/schemas.ts +304 -0
  337. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/api/openapi/types.ts +5710 -0
  338. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/apiSchema/commerceSiteadminOperator.ts +13 -0
  339. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/config/locale/en-us.ts +5 -0
  340. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/config/locale/zh-cn.ts +5 -0
  341. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/index.ts +1 -0
  342. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/model/operator.ts +17 -0
  343. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/page/dashboard/controller.tsx +34 -0
  344. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/routes.ts +5 -0
  345. package/zova/src/suite/a-commerce/modules/commerce-trade/cli/openapi.config.ts +15 -0
  346. package/zova/src/suite/a-commerce/modules/commerce-trade/package.json +2 -1
  347. package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +182 -3
  348. package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/locales.ts +7 -0
  349. package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/page/cart.ts +19 -0
  350. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/commerceTradeCart.ts +99 -0
  351. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/baseURL.ts +5 -0
  352. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/index.ts +3 -0
  353. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/schemas.ts +446 -0
  354. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/types.ts +7651 -0
  355. package/zova/src/suite/a-commerce/modules/commerce-trade/src/apiSchema/commerceTradeCart.ts +35 -0
  356. package/zova/src/suite/a-commerce/modules/commerce-trade/src/config/locale/en-us.ts +8 -0
  357. package/zova/src/suite/a-commerce/modules/commerce-trade/src/config/locale/zh-cn.ts +8 -0
  358. package/zova/src/suite/a-commerce/modules/commerce-trade/src/index.ts +1 -0
  359. package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/cart.ts +78 -0
  360. package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/cart/controller.tsx +108 -0
  361. package/zova/src/suite/a-commerce/modules/commerce-trade/src/routes.ts +12 -0
  362. package/zova/src/suite/a-demo/modules/demo-basic/src/.metadata/index.ts +5 -5
  363. package/zova/src/suite/a-demo/modules/demo-todo/src/.metadata/index.ts +2 -2
  364. package/zova/src/suite/a-home/modules/home-base/src/service/routerGuards.ts +18 -10
  365. package/zova/src/suite/a-home/modules/home-indexweb/src/.metadata/index.ts +2 -2
  366. package/zova/src/suite/a-home/modules/home-layoutadmin/src/component/layoutAdmin/controller.tsx +17 -7
  367. package/zova/src/suite/a-home/modules/home-layoutadmin/src/component/layoutAdmin/render.header.tsx +1 -1
  368. package/zova/src/suite/a-home/modules/home-layoutweb/src/component/layoutWeb/controller.tsx +17 -7
  369. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/package.json +1 -1
  370. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/.metadata/index.ts +4 -4
  371. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts +1 -0
  372. package/zova/src/suite-vendor/a-cabloy/package.json +2 -2
  373. package/zova/src/suite-vendor/a-zova/modules/a-bean/cli/controller/metadata/generateMetaPage.ts +3 -1
  374. package/zova/src/suite-vendor/a-zova/modules/a-bean/package.json +1 -1
  375. package/zova/src/suite-vendor/a-zova/modules/a-fetch/package.json +2 -2
  376. package/zova/src/suite-vendor/a-zova/modules/a-openapi/package.json +1 -1
  377. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/model/sdk.ts +3 -1
  378. package/zova/src/suite-vendor/a-zova/modules/a-router/package.json +1 -1
  379. package/zova/src/suite-vendor/a-zova/modules/a-router/src/bean/sys.router.ts +35 -8
  380. package/zova/src/suite-vendor/a-zova/modules/a-router/src/monkeySys.ts +28 -12
  381. package/zova/src/suite-vendor/a-zova/modules/a-router/src/service/routerGuards.ts +6 -8
  382. package/zova/src/suite-vendor/a-zova/modules/a-router/src/types/router.ts +14 -2
  383. package/zova/src/suite-vendor/a-zova/modules/a-router/src/types/utils.ts +4 -1
  384. package/zova/src/suite-vendor/a-zova/package.json +5 -5
  385. package/CLAUDE.local.md +0 -4
@@ -0,0 +1,457 @@
1
+ import type { EntityStockReservation } from 'vona-module-commerce-trade';
2
+
3
+ import { catchError } from '@cabloy/utils';
4
+ import assert from 'node:assert';
5
+ import { describe, it } from 'node:test';
6
+ import { app } from 'vona-mock';
7
+
8
+ interface IStockFixture {
9
+ categoryId: number;
10
+ productId: number;
11
+ skuId: number;
12
+ }
13
+
14
+ type IStockFixturePartial = Partial<IStockFixture>;
15
+
16
+ async function createSku(suffix: string, fixtures: IStockFixturePartial[]): Promise<IStockFixture> {
17
+ const fixture: IStockFixturePartial = {};
18
+ fixtures.push(fixture);
19
+ fixture.categoryId = await app.bean.executor.performAction('post', '/commerce/catalog/category', {
20
+ body: { name: `reservation-category-${suffix}`, published: true },
21
+ });
22
+ fixture.productId = await app.bean.executor.performAction('post', '/commerce/catalog/product', {
23
+ body: {
24
+ categoryId: fixture.categoryId,
25
+ title: `reservation-product-${suffix}`,
26
+ published: true,
27
+ },
28
+ });
29
+ fixture.skuId = await app.bean.executor.performAction('post', '/commerce/catalog/sku', {
30
+ body: {
31
+ productId: fixture.productId,
32
+ code: `reservation-sku-${suffix}`,
33
+ priceCents: 100,
34
+ lifecycle: 'active',
35
+ },
36
+ });
37
+ return fixture as IStockFixture;
38
+ }
39
+
40
+ async function prepareStock(
41
+ suffix: string,
42
+ fixtures: IStockFixturePartial[],
43
+ quantity = 3,
44
+ ): Promise<IStockFixture> {
45
+ const fixture = await createSku(suffix, fixtures);
46
+ await app.scope('commerce-trade').service.stockBalance.adjustStock({
47
+ skuId: fixture.skuId,
48
+ delta: quantity,
49
+ reason: 'reservation test setup',
50
+ correlationId: `reservation-setup-${suffix}`,
51
+ });
52
+ return fixture;
53
+ }
54
+
55
+ async function dropStockFixtures(fixtures: IStockFixturePartial[]) {
56
+ const scopeTrade = app.scope('commerce-trade');
57
+ const scopeCatalog = app.scope('commerce-catalog');
58
+ for (const fixture of fixtures.toReversed()) {
59
+ if (fixture.skuId !== undefined) {
60
+ await scopeTrade.model.stockAudit.delete({ skuId: fixture.skuId });
61
+ await scopeTrade.model.stockReservation.delete({ skuId: fixture.skuId });
62
+ await scopeTrade.model.stockBalance.delete({ skuId: fixture.skuId });
63
+ await scopeCatalog.model.sku.delete({ id: fixture.skuId });
64
+ }
65
+ if (fixture.productId !== undefined) {
66
+ await scopeCatalog.model.product.delete({ id: fixture.productId });
67
+ }
68
+ if (fixture.categoryId !== undefined) {
69
+ await scopeCatalog.model.category.delete({ id: fixture.categoryId });
70
+ }
71
+ }
72
+ }
73
+
74
+ async function reserve(
75
+ skuId: number,
76
+ suffix: string,
77
+ quantity = 2,
78
+ ): Promise<EntityStockReservation> {
79
+ return await app.scope('commerce-trade').service.stockBalance.reserve({
80
+ skuId,
81
+ quantity,
82
+ reason: 'reservation test',
83
+ correlationId: `reservation-${suffix}`,
84
+ });
85
+ }
86
+
87
+ async function assertReservationRejected(skuId: number, suffix: string, expectedCode: number) {
88
+ const [_, err] = await catchError(() => reserve(skuId, suffix));
89
+ assert.equal(err?.code, expectedCode);
90
+ const balance = await app.scope('commerce-trade').model.stockBalance.get({ skuId });
91
+ assert.deepEqual([balance?.onHand, balance?.reserved, balance?.available], [3, 0, 3]);
92
+ assert.equal(await app.scope('commerce-trade').model.stockReservation.get({ skuId }), undefined);
93
+ const audits = await app.scope('commerce-trade').model.stockAudit.select({ where: { skuId } });
94
+ assert.deepEqual(
95
+ audits.map(audit => audit.operation),
96
+ ['adjust'],
97
+ );
98
+ }
99
+
100
+ describe('stockReservation.test.ts', () => {
101
+ it('reserves and consumes stock exactly once with traceable audits', async () => {
102
+ await app.bean.executor.mockCtx(async () => {
103
+ const fixtures: IStockFixturePartial[] = [];
104
+ await app.bean.passport.signinMock();
105
+ try {
106
+ const suffix = `${Date.now()}`;
107
+ const fixture = await prepareStock(suffix, fixtures);
108
+ const reservation = await reserve(fixture.skuId, suffix);
109
+ const balanceAfterReserve = await app
110
+ .scope('commerce-trade')
111
+ .model.stockBalance.get({ skuId: fixture.skuId });
112
+ assert.deepEqual(
113
+ [
114
+ balanceAfterReserve?.onHand,
115
+ balanceAfterReserve?.reserved,
116
+ balanceAfterReserve?.available,
117
+ ],
118
+ [3, 2, 1],
119
+ );
120
+
121
+ const duplicate = await reserve(fixture.skuId, suffix);
122
+ assert.equal(duplicate.id, reservation.id);
123
+ const consumed = await app.scope('commerce-trade').service.stockBalance.consume({
124
+ reservationId: reservation.id,
125
+ reason: 'payment success',
126
+ });
127
+ assert.equal(consumed.state, 'consumed');
128
+ const duplicateConsume = await app.scope('commerce-trade').service.stockBalance.consume({
129
+ reservationId: reservation.id,
130
+ reason: 'payment success retry',
131
+ });
132
+ assert.equal(duplicateConsume.state, 'consumed');
133
+
134
+ const balanceAfterConsume = await app
135
+ .scope('commerce-trade')
136
+ .model.stockBalance.get({ skuId: fixture.skuId });
137
+ assert.deepEqual(
138
+ [
139
+ balanceAfterConsume?.onHand,
140
+ balanceAfterConsume?.reserved,
141
+ balanceAfterConsume?.available,
142
+ ],
143
+ [1, 0, 1],
144
+ );
145
+ const audits = await app.scope('commerce-trade').model.stockAudit.select({
146
+ where: { skuId: fixture.skuId },
147
+ });
148
+ assert.deepEqual(
149
+ audits.map(audit => audit.operation),
150
+ ['adjust', 'reserve', 'consume'],
151
+ );
152
+ assert.equal(audits[1].stockReservationId, reservation.id);
153
+ } finally {
154
+ await dropStockFixtures(fixtures);
155
+ await app.bean.passport.signout();
156
+ }
157
+ });
158
+ });
159
+
160
+ it('rejects reservations for inactive or unpublished catalog data without writes', async () => {
161
+ await app.bean.executor.mockCtx(async () => {
162
+ const fixtures: IStockFixturePartial[] = [];
163
+ await app.bean.passport.signinMock();
164
+ try {
165
+ const suffix = `${Date.now()}`;
166
+ const inactiveSku = await prepareStock(`${suffix}-inactive`, fixtures);
167
+ await app.scope('commerce-catalog').model.sku.updateById(inactiveSku.skuId, {
168
+ lifecycle: 'inactive',
169
+ });
170
+ await assertReservationRejected(inactiveSku.skuId, `${suffix}-inactive`, 404);
171
+
172
+ const unpublishedProductSku = await prepareStock(`${suffix}-product`, fixtures);
173
+ await app
174
+ .scope('commerce-catalog')
175
+ .model.product.updateById(unpublishedProductSku.productId, { published: false });
176
+ await assertReservationRejected(unpublishedProductSku.skuId, `${suffix}-product`, 409);
177
+
178
+ const unpublishedCategorySku = await prepareStock(`${suffix}-category`, fixtures);
179
+ await app
180
+ .scope('commerce-catalog')
181
+ .model.category.updateById(unpublishedCategorySku.categoryId, { published: false });
182
+ await assertReservationRejected(unpublishedCategorySku.skuId, `${suffix}-category`, 409);
183
+ } finally {
184
+ await dropStockFixtures(fixtures);
185
+ await app.bean.passport.signout();
186
+ }
187
+ });
188
+ });
189
+
190
+ it('releases and restores stock only from legal reservation states', async () => {
191
+ await app.bean.executor.mockCtx(async () => {
192
+ const fixtures: IStockFixturePartial[] = [];
193
+ await app.bean.passport.signinMock();
194
+ try {
195
+ const suffix = `${Date.now()}`;
196
+ const fixture = await prepareStock(suffix, fixtures);
197
+ const releasedReservation = await reserve(fixture.skuId, `${suffix}-release`);
198
+ const released = await app.scope('commerce-trade').service.stockBalance.release({
199
+ reservationId: releasedReservation.id,
200
+ reason: 'payment failed',
201
+ });
202
+ assert.equal(released.state, 'released');
203
+ const duplicateRelease = await app.scope('commerce-trade').service.stockBalance.release({
204
+ reservationId: releasedReservation.id,
205
+ reason: 'payment failed retry',
206
+ });
207
+ assert.equal(duplicateRelease.state, 'released');
208
+
209
+ const consumedReservation = await reserve(fixture.skuId, `${suffix}-restore`, 1);
210
+ await app.scope('commerce-trade').service.stockBalance.consume({
211
+ reservationId: consumedReservation.id,
212
+ reason: 'payment success',
213
+ });
214
+ const restored = await app.scope('commerce-trade').service.stockBalance.restore({
215
+ reservationId: consumedReservation.id,
216
+ reason: 'refund success',
217
+ });
218
+ assert.equal(restored.state, 'restored');
219
+ const duplicateRestore = await app.scope('commerce-trade').service.stockBalance.restore({
220
+ reservationId: consumedReservation.id,
221
+ reason: 'refund success retry',
222
+ });
223
+ assert.equal(duplicateRestore.state, 'restored');
224
+
225
+ const [_, err] = await catchError(() =>
226
+ app.scope('commerce-trade').service.stockBalance.consume({
227
+ reservationId: releasedReservation.id,
228
+ reason: 'invalid replay',
229
+ }),
230
+ );
231
+ assert.equal(err?.code, 409);
232
+ const balance = await app
233
+ .scope('commerce-trade')
234
+ .model.stockBalance.get({ skuId: fixture.skuId });
235
+ assert.deepEqual([balance?.onHand, balance?.reserved, balance?.available], [3, 0, 3]);
236
+ const audits = await app.scope('commerce-trade').model.stockAudit.select({
237
+ where: { skuId: fixture.skuId },
238
+ });
239
+ assert.equal(audits.length, 6);
240
+ assert.deepEqual(
241
+ audits.map(audit => audit.operation),
242
+ ['adjust', 'reserve', 'release', 'reserve', 'consume', 'restore'],
243
+ );
244
+ assert.deepEqual(
245
+ audits.map(audit => audit.stockBalanceId),
246
+ audits.map(() => balance?.id),
247
+ );
248
+ assert.deepEqual(
249
+ audits.map(audit => audit.stockReservationId),
250
+ [
251
+ null,
252
+ releasedReservation.id,
253
+ releasedReservation.id,
254
+ consumedReservation.id,
255
+ consumedReservation.id,
256
+ consumedReservation.id,
257
+ ],
258
+ );
259
+ assert.deepEqual(
260
+ audits.map(audit => audit.correlationId),
261
+ [
262
+ `reservation-setup-${suffix}`,
263
+ `reservation-${suffix}-release`,
264
+ `reservation-${suffix}-release`,
265
+ `reservation-${suffix}-restore`,
266
+ `reservation-${suffix}-restore`,
267
+ `reservation-${suffix}-restore`,
268
+ ],
269
+ );
270
+ assert.deepEqual(
271
+ audits.map(audit => audit.reason),
272
+ [
273
+ 'reservation test setup',
274
+ 'reservation test',
275
+ 'payment failed',
276
+ 'reservation test',
277
+ 'payment success',
278
+ 'refund success',
279
+ ],
280
+ );
281
+ assert.deepEqual(
282
+ audits.map(audit => [
283
+ audit.delta,
284
+ audit.priorOnHand,
285
+ audit.priorReserved,
286
+ audit.priorAvailable,
287
+ audit.onHand,
288
+ audit.reserved,
289
+ audit.available,
290
+ ]),
291
+ [
292
+ [3, 0, 0, 0, 3, 0, 3],
293
+ [-2, 3, 0, 3, 3, 2, 1],
294
+ [0, 3, 2, 1, 3, 0, 3],
295
+ [-1, 3, 0, 3, 3, 1, 2],
296
+ [-1, 3, 1, 2, 2, 0, 2],
297
+ [1, 2, 0, 2, 3, 0, 3],
298
+ ],
299
+ );
300
+ } finally {
301
+ await dropStockFixtures(fixtures);
302
+ await app.bean.passport.signout();
303
+ }
304
+ });
305
+ });
306
+
307
+ it('allows exactly one independent reservation for the final unit', async t => {
308
+ if (process.env.DATABASE_DEFAULT_CLIENT !== 'pg') {
309
+ t.skip('requires PostgreSQL row-lock contention');
310
+ return;
311
+ }
312
+ const fixtures: IStockFixturePartial[] = [];
313
+ const suffix = `${Date.now()}`;
314
+ let fixture!: IStockFixture;
315
+ try {
316
+ await app.bean.executor.mockCtx(async () => {
317
+ await app.bean.passport.signinMock();
318
+ try {
319
+ fixture = await prepareStock(suffix, fixtures, 1);
320
+ } finally {
321
+ await app.bean.passport.signout();
322
+ }
323
+ });
324
+
325
+ const reserveInContext = async (correlationSuffix: string) => {
326
+ return await app.bean.executor.mockCtx(async () => {
327
+ await app.bean.passport.signinMock();
328
+ try {
329
+ return await reserve(fixture.skuId, correlationSuffix, 1);
330
+ } finally {
331
+ await app.bean.passport.signout();
332
+ }
333
+ });
334
+ };
335
+ const results = await Promise.allSettled([
336
+ reserveInContext(`${suffix}-first`),
337
+ reserveInContext(`${suffix}-second`),
338
+ ]);
339
+ assert.equal(
340
+ results.filter(result => result.status === 'fulfilled').length,
341
+ 1,
342
+ JSON.stringify(results),
343
+ );
344
+ assert.equal(
345
+ results.filter(result => result.status === 'rejected').length,
346
+ 1,
347
+ JSON.stringify(results),
348
+ );
349
+ const rejected = results.find(result => result.status === 'rejected');
350
+ assert.equal(
351
+ (rejected as PromiseRejectedResult | undefined)?.reason?.code,
352
+ 409,
353
+ String((rejected as PromiseRejectedResult | undefined)?.reason),
354
+ );
355
+
356
+ await app.bean.executor.mockCtx(async () => {
357
+ const balance = await app
358
+ .scope('commerce-trade')
359
+ .model.stockBalance.get({ skuId: fixture.skuId });
360
+ assert.deepEqual([balance?.onHand, balance?.reserved, balance?.available], [1, 1, 0]);
361
+ const reservations = await app.scope('commerce-trade').model.stockReservation.select({
362
+ where: { skuId: fixture.skuId },
363
+ });
364
+ const audits = await app.scope('commerce-trade').model.stockAudit.select({
365
+ where: { skuId: fixture.skuId },
366
+ });
367
+ assert.equal(reservations.length, 1);
368
+ assert.deepEqual(
369
+ audits.map(audit => audit.operation),
370
+ ['adjust', 'reserve'],
371
+ );
372
+ assert.equal(audits.filter(audit => audit.operation === 'reserve').length, 1);
373
+ assert.equal(
374
+ audits.some(audit => audit.correlationId === `reservation-${suffix}-first`) ||
375
+ audits.some(audit => audit.correlationId === `reservation-${suffix}-second`),
376
+ true,
377
+ );
378
+ });
379
+ } finally {
380
+ await app.bean.executor.mockCtx(async () => {
381
+ await dropStockFixtures(fixtures);
382
+ });
383
+ }
384
+ });
385
+
386
+ it('rolls back reservation, balance, and audit writes in one transaction', async () => {
387
+ await app.bean.executor.mockCtx(async () => {
388
+ const fixtures: IStockFixturePartial[] = [];
389
+ await app.bean.passport.signinMock();
390
+ try {
391
+ const suffix = `${Date.now()}`;
392
+ const fixture = await prepareStock(suffix, fixtures);
393
+ const balance = await app.scope('commerce-trade').model.stockBalance.get({
394
+ skuId: fixture.skuId,
395
+ });
396
+ const db = app.ctx.db;
397
+ const [_, err] = await catchError(async () => {
398
+ await db.transaction.begin(async () => {
399
+ const modelStockBalance = app
400
+ .scope('commerce-trade')
401
+ .model.stockBalance.newInstance(db);
402
+ const modelStockReservation = app
403
+ .scope('commerce-trade')
404
+ .model.stockReservation.newInstance(db);
405
+ const modelStockAudit = app.scope('commerce-trade').model.stockAudit.newInstance(db);
406
+ const reservation = await modelStockReservation.insert({
407
+ stockBalanceId: balance!.id,
408
+ skuId: fixture.skuId,
409
+ quantity: 2,
410
+ state: 'reserved',
411
+ correlationId: `reservation-${suffix}-rollback`,
412
+ });
413
+ await modelStockBalance.updateById(balance!.id, {
414
+ onHand: 3,
415
+ reserved: 2,
416
+ available: 1,
417
+ });
418
+ await modelStockAudit.insert({
419
+ stockBalanceId: balance!.id,
420
+ skuId: fixture.skuId,
421
+ stockReservationId: reservation.id,
422
+ actorId: app.bean.passport.currentUser!.id,
423
+ operation: 'reserve',
424
+ delta: -2,
425
+ reason: 'transaction rollback proof',
426
+ correlationId: reservation.correlationId,
427
+ priorOnHand: 3,
428
+ priorReserved: 0,
429
+ priorAvailable: 3,
430
+ onHand: 3,
431
+ reserved: 2,
432
+ available: 1,
433
+ });
434
+ throw new Error('transaction rollback proof');
435
+ });
436
+ });
437
+ assert.match(err?.message ?? '', /transaction rollback proof/);
438
+
439
+ const unchanged = await app
440
+ .scope('commerce-trade')
441
+ .model.stockBalance.get({ skuId: fixture.skuId });
442
+ assert.deepEqual([unchanged?.onHand, unchanged?.reserved, unchanged?.available], [3, 0, 3]);
443
+ assert.equal(
444
+ await app.scope('commerce-trade').model.stockReservation.get({ skuId: fixture.skuId }),
445
+ undefined,
446
+ );
447
+ const audits = await app.scope('commerce-trade').model.stockAudit.select({
448
+ where: { skuId: fixture.skuId },
449
+ });
450
+ assert.equal(audits.length, 1);
451
+ } finally {
452
+ await dropStockFixtures(fixtures);
453
+ await app.bean.passport.signout();
454
+ }
455
+ });
456
+ });
457
+ });
@@ -10,6 +10,7 @@
10
10
  "vona-module-commerce-member": "^5.0.0",
11
11
  "vona-module-commerce-payment": "^5.0.0",
12
12
  "vona-module-commerce-promotion": "^5.0.0",
13
+ "vona-module-commerce-seed": "^5.0.0",
13
14
  "vona-module-commerce-siteadmin": "^5.0.0",
14
15
  "vona-module-commerce-siteweb": "^5.0.0",
15
16
  "vona-module-commerce-trade": "^5.0.0"
@@ -22,6 +22,9 @@
22
22
  },
23
23
  {
24
24
  "path": "modules/commerce-siteadmin/tsconfig.build.json"
25
+ },
26
+ {
27
+ "path": "modules/commerce-seed/tsconfig.build.json"
25
28
  }
26
29
  ],
27
30
  "exclude": ["modules"]
@@ -144,7 +144,7 @@ import { SymbolKeyEntity, SymbolKeyEntityMeta, SymbolKeyModelOptions } from 'von
144
144
  declare module 'vona-module-home-user' {
145
145
  export interface IModelOptionsUser {
146
146
  relations: {
147
- roles: IModelRelationBelongsToMany<'home-user:roleUser', 'home-user:role', false, undefined,undefined,undefined,undefined>;
147
+ roles: IModelRelationBelongsToMany<'home-user:roleUser', 'home-user:role', false, '*',undefined,undefined,undefined>;
148
148
  };
149
149
  }
150
150
  export interface ModelRole {
@@ -152,6 +152,8 @@ declare module 'vona-module-home-user' {
152
152
  [SymbolKeyEntityMeta]: EntityRoleMeta;
153
153
  [SymbolKeyModelOptions]: IModelOptionsRole;
154
154
  get<T extends IModelGetOptions<EntityRole,ModelRole>>(where: TypeModelWhere<EntityRole>, options?: T): Promise<TypeModelRelationResult<EntityRole, ModelRole, T> | undefined>;
155
+ getForUpdate<T extends IModelGetOptions<EntityRole,ModelRole>>(where: TypeModelWhere<EntityRole>, options?: T): Promise<TypeModelRelationResult<EntityRole, ModelRole, T> | undefined>;
156
+ getByIdForUpdate<T extends IModelGetOptions<EntityRole,ModelRole>>(id: TableIdentity, options?: T): Promise<TypeModelRelationResult<EntityRole, ModelRole, T> | undefined>;
155
157
  mget<T extends IModelGetOptions<EntityRole,ModelRole>>(ids: TableIdentity[], options?: T): Promise<TypeModelRelationResult<EntityRole, ModelRole, T>[]>;
156
158
  selectAndCount<T extends IModelSelectParams<EntityRole,ModelRole,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelSelectAndCount<EntityRole, ModelRole, T>>;
157
159
  select<T extends IModelSelectParams<EntityRole,ModelRole,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelRelationResult<EntityRole, ModelRole, T>[]>;
@@ -181,6 +183,8 @@ export interface ModelRoleUser {
181
183
  [SymbolKeyEntityMeta]: EntityRoleUserMeta;
182
184
  [SymbolKeyModelOptions]: IModelOptionsRoleUser;
183
185
  get<T extends IModelGetOptions<EntityRoleUser,ModelRoleUser>>(where: TypeModelWhere<EntityRoleUser>, options?: T): Promise<TypeModelRelationResult<EntityRoleUser, ModelRoleUser, T> | undefined>;
186
+ getForUpdate<T extends IModelGetOptions<EntityRoleUser,ModelRoleUser>>(where: TypeModelWhere<EntityRoleUser>, options?: T): Promise<TypeModelRelationResult<EntityRoleUser, ModelRoleUser, T> | undefined>;
187
+ getByIdForUpdate<T extends IModelGetOptions<EntityRoleUser,ModelRoleUser>>(id: TableIdentity, options?: T): Promise<TypeModelRelationResult<EntityRoleUser, ModelRoleUser, T> | undefined>;
184
188
  mget<T extends IModelGetOptions<EntityRoleUser,ModelRoleUser>>(ids: TableIdentity[], options?: T): Promise<TypeModelRelationResult<EntityRoleUser, ModelRoleUser, T>[]>;
185
189
  selectAndCount<T extends IModelSelectParams<EntityRoleUser,ModelRoleUser,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelSelectAndCount<EntityRoleUser, ModelRoleUser, T>>;
186
190
  select<T extends IModelSelectParams<EntityRoleUser,ModelRoleUser,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelRelationResult<EntityRoleUser, ModelRoleUser, T>[]>;
@@ -206,6 +210,8 @@ export interface ModelUser {
206
210
  [SymbolKeyEntityMeta]: EntityUserMeta;
207
211
  [SymbolKeyModelOptions]: IModelOptionsUser;
208
212
  get<T extends IModelGetOptions<EntityUser,ModelUser>>(where: TypeModelWhere<EntityUser>, options?: T): Promise<TypeModelRelationResult<EntityUser, ModelUser, T> | undefined>;
213
+ getForUpdate<T extends IModelGetOptions<EntityUser,ModelUser>>(where: TypeModelWhere<EntityUser>, options?: T): Promise<TypeModelRelationResult<EntityUser, ModelUser, T> | undefined>;
214
+ getByIdForUpdate<T extends IModelGetOptions<EntityUser,ModelUser>>(id: TableIdentity, options?: T): Promise<TypeModelRelationResult<EntityUser, ModelUser, T> | undefined>;
209
215
  mget<T extends IModelGetOptions<EntityUser,ModelUser>>(ids: TableIdentity[], options?: T): Promise<TypeModelRelationResult<EntityUser, ModelUser, T>[]>;
210
216
  selectAndCount<T extends IModelSelectParams<EntityUser,ModelUser,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelSelectAndCount<EntityUser, ModelUser, T>>;
211
217
  select<T extends IModelSelectParams<EntityUser,ModelUser,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelRelationResult<EntityUser, ModelUser, T>[]>;
@@ -9,37 +9,28 @@ describe('role.test.ts', () => {
9
9
  const roleRegisteredUser = await scope.model.role.getByName('registeredUser');
10
10
  assert.equal(roleRegisteredUser?.title, 'Registered User');
11
11
  assert.deepEqual(roleRegisteredUser?.locales, { 'zh-cn': '注册用户' });
12
- assert.deepEqual(roleRegisteredUser?.siteIds, ['web']);
12
+ assert.ok(roleRegisteredUser?.siteIds.includes('web'));
13
13
 
14
14
  const roleSystemAdmin = await scope.model.role.getByName('systemAdmin');
15
15
  assert.equal(roleSystemAdmin?.title, 'System Administrator');
16
16
  assert.deepEqual(roleSystemAdmin?.locales, { 'zh-cn': '系统管理员' });
17
- assert.deepEqual(roleSystemAdmin?.siteIds, ['web', 'admin']);
17
+ assert.ok(roleSystemAdmin?.siteIds.includes('web'));
18
+ assert.ok(roleSystemAdmin?.siteIds.includes('admin'));
18
19
 
19
20
  await app.bean.passport.signinMock();
20
21
  const passport = await app.bean.executor.performAction('get', '/home/user/passport/current');
21
- assert.deepEqual(
22
- passport.roles.map(role => ({
23
- name: role.name,
24
- title: role.title,
25
- locales: role.locales,
26
- siteIds: role.siteIds,
27
- })),
28
- [
29
- {
30
- name: 'registeredUser',
31
- title: 'Registered User',
32
- locales: { 'zh-cn': '注册用户' },
33
- siteIds: ['web'],
34
- },
35
- {
36
- name: 'systemAdmin',
37
- title: 'System Administrator',
38
- locales: { 'zh-cn': '系统管理员' },
39
- siteIds: ['web', 'admin'],
40
- },
41
- ],
22
+ const passportRegisteredUser = passport.roles.find(
23
+ (role: any) => role.name === 'registeredUser',
42
24
  );
25
+ assert.equal(passportRegisteredUser?.title, 'Registered User');
26
+ assert.deepEqual(passportRegisteredUser?.locales, { 'zh-cn': '注册用户' });
27
+ assert.ok(passportRegisteredUser?.siteIds.includes('web'));
28
+
29
+ const passportSystemAdmin = passport.roles.find((role: any) => role.name === 'systemAdmin');
30
+ assert.equal(passportSystemAdmin?.title, 'System Administrator');
31
+ assert.deepEqual(passportSystemAdmin?.locales, { 'zh-cn': '系统管理员' });
32
+ assert.ok(passportSystemAdmin?.siteIds.includes('web'));
33
+ assert.ok(passportSystemAdmin?.siteIds.includes('admin'));
43
34
  });
44
35
  });
45
36
  });
@@ -95,6 +95,8 @@ trainingRecordSubjects: IModelRelationHasMany<'training-recordsubject:subject',
95
95
  [SymbolKeyEntityMeta]: EntityRecordMeta;
96
96
  [SymbolKeyModelOptions]: IModelOptionsRecord;
97
97
  get<T extends IModelGetOptions<EntityRecord,ModelRecord>>(where: TypeModelWhere<EntityRecord>, options?: T): Promise<TypeModelRelationResult<EntityRecord, ModelRecord, T> | undefined>;
98
+ getForUpdate<T extends IModelGetOptions<EntityRecord,ModelRecord>>(where: TypeModelWhere<EntityRecord>, options?: T): Promise<TypeModelRelationResult<EntityRecord, ModelRecord, T> | undefined>;
99
+ getByIdForUpdate<T extends IModelGetOptions<EntityRecord,ModelRecord>>(id: TableIdentity, options?: T): Promise<TypeModelRelationResult<EntityRecord, ModelRecord, T> | undefined>;
98
100
  mget<T extends IModelGetOptions<EntityRecord,ModelRecord>>(ids: TableIdentity[], options?: T): Promise<TypeModelRelationResult<EntityRecord, ModelRecord, T>[]>;
99
101
  selectAndCount<T extends IModelSelectParams<EntityRecord,ModelRecord,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelSelectAndCount<EntityRecord, ModelRecord, T>>;
100
102
  select<T extends IModelSelectParams<EntityRecord,ModelRecord,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelRelationResult<EntityRecord, ModelRecord, T>[]>;
@@ -393,15 +395,15 @@ export * from '../bean/fileScene.dossierFile.ts';
393
395
 
394
396
  import { type IDecoratorFileSceneOptions } from 'vona-module-a-file';
395
397
  declare module 'vona-module-a-file' {
396
-
398
+
397
399
  export interface IFileSceneRecord {
398
400
  'training-record:dossierFile': IDecoratorFileSceneOptions;
399
401
  }
400
402
 
401
-
403
+
402
404
  }
403
405
  declare module 'vona-module-training-record' {
404
-
406
+
405
407
  export interface FileSceneDossierFile {
406
408
  /** @internal */
407
409
  get scope(): ScopeModuleTrainingRecord;
@@ -411,7 +413,7 @@ declare module 'vona-module-training-record' {
411
413
  get $beanFullName(): 'training-record.fileScene.dossierFile';
412
414
  get $onionName(): 'training-record:dossierFile';
413
415
  get $onionOptions(): IDecoratorFileSceneOptions;
414
- }
416
+ }
415
417
  }
416
418
  /** fileScene: end */
417
419
  /** imageScene: begin */
@@ -419,15 +421,15 @@ export * from '../bean/imageScene.sceneImage.ts';
419
421
 
420
422
  import { type IDecoratorImageSceneOptions } from 'vona-module-a-image';
421
423
  declare module 'vona-module-a-image' {
422
-
424
+
423
425
  export interface IImageSceneRecord {
424
426
  'training-record:sceneImage': IDecoratorImageSceneOptions;
425
427
  }
426
428
 
427
-
429
+
428
430
  }
429
431
  declare module 'vona-module-training-record' {
430
-
432
+
431
433
  export interface ImageSceneSceneImage {
432
434
  /** @internal */
433
435
  get scope(): ScopeModuleTrainingRecord;
@@ -437,7 +439,7 @@ declare module 'vona-module-training-record' {
437
439
  get $beanFullName(): 'training-record.imageScene.sceneImage';
438
440
  get $onionName(): 'training-record:sceneImage';
439
441
  get $onionOptions(): IDecoratorImageSceneOptions;
440
- }
442
+ }
441
443
  }
442
444
  /** imageScene: end */
443
445
  /** locale: begin */
@@ -90,6 +90,8 @@ declare module 'vona-module-training-recordsubject' {
90
90
  [SymbolKeyEntityMeta]: EntitySubjectMeta;
91
91
  [SymbolKeyModelOptions]: IModelOptionsSubject;
92
92
  get<T extends IModelGetOptions<EntitySubject,ModelSubject>>(where: TypeModelWhere<EntitySubject>, options?: T): Promise<TypeModelRelationResult<EntitySubject, ModelSubject, T> | undefined>;
93
+ getForUpdate<T extends IModelGetOptions<EntitySubject,ModelSubject>>(where: TypeModelWhere<EntitySubject>, options?: T): Promise<TypeModelRelationResult<EntitySubject, ModelSubject, T> | undefined>;
94
+ getByIdForUpdate<T extends IModelGetOptions<EntitySubject,ModelSubject>>(id: TableIdentity, options?: T): Promise<TypeModelRelationResult<EntitySubject, ModelSubject, T> | undefined>;
93
95
  mget<T extends IModelGetOptions<EntitySubject,ModelSubject>>(ids: TableIdentity[], options?: T): Promise<TypeModelRelationResult<EntitySubject, ModelSubject, T>[]>;
94
96
  selectAndCount<T extends IModelSelectParams<EntitySubject,ModelSubject,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelSelectAndCount<EntitySubject, ModelSubject, T>>;
95
97
  select<T extends IModelSelectParams<EntitySubject,ModelSubject,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelRelationResult<EntitySubject, ModelSubject, T>[]>;
@@ -86,7 +86,7 @@ import { SymbolKeyEntity, SymbolKeyEntityMeta, SymbolKeyModelOptions } from 'von
86
86
  declare module 'vona-module-training-student' {
87
87
  export interface IModelOptionsStudent {
88
88
  relations: {
89
- trainingRecords: IModelRelationHasMany<'training-record:record', 'studentId', false, 'id'|'name'|'subjectCount'|'totalScore'|'averageScore'|'trainingTime'|'sceneImageIds'|'description', undefined, undefined, undefined>;
89
+ trainingRecords: IModelRelationHasMany<'training-record:record', 'studentId', false, 'id'|'name'|'subjectCount'|'totalScore'|'averageScore'|'trainingTime'|'sceneImageIds'|'dossierFileIds'|'description', undefined, undefined, undefined>;
90
90
  };
91
91
  }
92
92
  export interface ModelStudent {
@@ -94,6 +94,8 @@ declare module 'vona-module-training-student' {
94
94
  [SymbolKeyEntityMeta]: EntityStudentMeta;
95
95
  [SymbolKeyModelOptions]: IModelOptionsStudent;
96
96
  get<T extends IModelGetOptions<EntityStudent,ModelStudent>>(where: TypeModelWhere<EntityStudent>, options?: T): Promise<TypeModelRelationResult<EntityStudent, ModelStudent, T> | undefined>;
97
+ getForUpdate<T extends IModelGetOptions<EntityStudent,ModelStudent>>(where: TypeModelWhere<EntityStudent>, options?: T): Promise<TypeModelRelationResult<EntityStudent, ModelStudent, T> | undefined>;
98
+ getByIdForUpdate<T extends IModelGetOptions<EntityStudent,ModelStudent>>(id: TableIdentity, options?: T): Promise<TypeModelRelationResult<EntityStudent, ModelStudent, T> | undefined>;
97
99
  mget<T extends IModelGetOptions<EntityStudent,ModelStudent>>(ids: TableIdentity[], options?: T): Promise<TypeModelRelationResult<EntityStudent, ModelStudent, T>[]>;
98
100
  selectAndCount<T extends IModelSelectParams<EntityStudent,ModelStudent,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelSelectAndCount<EntityStudent, ModelStudent, T>>;
99
101
  select<T extends IModelSelectParams<EntityStudent,ModelStudent,ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelRelationResult<EntityStudent, ModelStudent, T>[]>;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-module-a-auth",
3
- "version": "5.1.20",
3
+ "version": "5.1.21",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "",
6
6
  "keywords": [