cabloy 5.1.149 → 5.1.150

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 (80) hide show
  1. package/.cabloy-version +1 -1
  2. package/.claude/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +2 -1
  3. package/.claude/skills/cabloy-frontend-scaffold/SKILL.md +1 -0
  4. package/CHANGELOG.md +22 -0
  5. package/CLAUDE.md +1 -0
  6. package/package.json +1 -1
  7. package/repo-docs/backend/dto-guide.md +7 -6
  8. package/repo-docs/backend/dto-infer-generation.md +25 -5
  9. package/repo-docs/frontend/a-model-under-the-hood.md +38 -0
  10. package/repo-docs/frontend/a-openapi-under-the-hood.md +13 -2
  11. package/repo-docs/frontend/form-layout-guide.md +26 -9
  12. package/repo-docs/frontend/model-resource-best-practices.md +2 -0
  13. package/repo-docs/frontend/model-resource-cookbook.md +7 -1
  14. package/repo-docs/frontend/use-state-data-best-practices.md +44 -0
  15. package/repo-docs/frontend/zova-form-source-reading-map.md +26 -9
  16. package/repo-docs/frontend/zova-form-under-the-hood.md +11 -0
  17. package/repo-docs/fullstack/one-to-one-companion-resource-guide.md +1 -1
  18. package/repo-e2e/specs/a-commerce.spec.ts +40 -0
  19. package/vona/packages-cli/cli/package.json +1 -1
  20. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/controller/{{resourceName}}.ts_ +2 -2
  21. package/vona/packages-cli/cli-set-api/package.json +1 -1
  22. package/vona/pnpm-lock.yaml +83 -75
  23. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/.metadata/index.ts +108 -108
  24. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/skuSelectResItem.tsx +12 -0
  25. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/service/sku.ts +19 -1
  26. package/vona/src/suite/a-commerce/modules/commerce-catalog/test/skuPresentation.test.ts +53 -4
  27. package/vona/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +148 -148
  28. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockAdjust.tsx +37 -3
  29. package/vona/src/suite/a-training/modules/training-student/src/.metadata/index.ts +2 -2
  30. package/vona/src/suite/a-training/modules/training-student/src/dto/studentCreate.tsx +7 -6
  31. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSummary.tsx +1 -1
  32. package/vona/src/suite/a-training/modules/training-student/src/dto/studentUpdate.tsx +7 -6
  33. package/vona/src/suite/a-training/modules/training-student/src/dto/studentView.tsx +10 -7
  34. package/vona/src/suite/a-training/modules/training-student/src/model/student.ts +4 -4
  35. package/vona/src/suite/a-training/modules/training-student/src/service/student.ts +39 -67
  36. package/vona/src/suite/a-training/modules/training-student/test/student.test.ts +56 -37
  37. package/zova/packages-zova/zova/package.json +2 -2
  38. package/zova/pnpm-lock.yaml +2 -2
  39. package/zova/src/suite/a-commerce/modules/commerce-trade/cli/openapi.config.ts +1 -0
  40. package/zova/src/suite/a-commerce/modules/commerce-trade/package.json +6 -1
  41. package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/component/tableCellActionAdjustStock.ts +34 -0
  42. package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +81 -6
  43. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/commerceTradeStockBalance.ts +32 -0
  44. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/schemas.ts +44 -44
  45. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/types.ts +356 -338
  46. package/zova/src/suite/a-commerce/modules/commerce-trade/src/apiSchema/commerceTradeStockBalance.ts +17 -0
  47. package/zova/src/suite/a-commerce/modules/commerce-trade/src/bean/tableCell.actionAdjustStock.tsx +35 -0
  48. package/zova/src/suite/a-commerce/modules/commerce-trade/src/component/tableCellActionAdjustStock/controller.tsx +138 -0
  49. package/zova/src/suite/a-commerce/modules/commerce-trade/src/config/locale/en-us.ts +3 -0
  50. package/zova/src/suite/a-commerce/modules/commerce-trade/src/config/locale/zh-cn.ts +3 -0
  51. package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/stockBalance.ts +36 -0
  52. package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/payment/controller.tsx +4 -4
  53. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/schemas.ts +8 -8
  54. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/types.ts +11 -11
  55. package/zova/src/suite/a-training/modules/training-student/src/bean/tableCell.actionSummary.tsx +2 -2
  56. package/zova/src/suite/cabloy-basic/modules/basic-app/src/bean/behavior.appModal.tsx +2 -0
  57. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/package.json +1 -1
  58. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts +2 -1
  59. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/test/model/resource.types.ts +11 -0
  60. package/zova/src/suite-vendor/a-cabloy/package.json +2 -2
  61. package/zova/src/suite-vendor/a-zova/modules/a-form/package.json +1 -1
  62. package/zova/src/suite-vendor/a-zova/modules/a-form/src/lib/formLayout.ts +58 -9
  63. package/zova/src/suite-vendor/a-zova/modules/a-form/test/lib/formLayout.test.ts +157 -0
  64. package/zova/src/suite-vendor/a-zova/modules/a-model/package.json +1 -1
  65. package/zova/src/suite-vendor/a-zova/modules/a-model/src/bean/bean.model/bean.model.persister.ts +3 -1
  66. package/zova/src/suite-vendor/a-zova/modules/a-model/src/bean/bean.model/bean.model.useQuery.ts +11 -13
  67. package/zova/src/suite-vendor/a-zova/modules/a-model/src/bean/bean.model/bean.model.useState.ts +9 -7
  68. package/zova/src/suite-vendor/a-zova/modules/a-model/src/bean/bean.model/bean.model.useStateGeneral.ts +5 -12
  69. package/zova/src/suite-vendor/a-zova/modules/a-model/src/lib/queryPersister.ts +17 -0
  70. package/zova/src/suite-vendor/a-zova/modules/a-model/src/lib/queryRefetch.ts +34 -0
  71. package/zova/src/suite-vendor/a-zova/modules/a-model/src/types/query.ts +27 -3
  72. package/zova/src/suite-vendor/a-zova/modules/a-model/test/lib/queryPersister.test.ts +115 -0
  73. package/zova/src/suite-vendor/a-zova/modules/a-model/test/lib/queryRefetch.test.ts +84 -0
  74. package/zova/src/suite-vendor/a-zova/modules/a-openapi/package.json +1 -1
  75. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/lib/schema.ts +27 -5
  76. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/model/sdk.ts +2 -2
  77. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/rest.ts +4 -0
  78. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/schema.ts +2 -5
  79. package/zova/src/suite-vendor/a-zova/modules/a-openapi/test/lib/schema.test.ts +179 -0
  80. package/zova/src/suite-vendor/a-zova/package.json +4 -4
@@ -178,12 +178,21 @@ describe('skuPresentation.test.ts', () => {
178
178
  listComponent.properties.productId.rest?.table?.columnProps,
179
179
  productPickerOptions,
180
180
  );
181
+ assert.equal(listComponent.properties.available.rest?.table?.order, undefined);
182
+ assert.equal(listComponent.properties.available.rest?.table?.render, undefined);
183
+ assert.equal(listComponent.properties.available.type, 'integer');
184
+ assert.equal(listComponent.properties.available.minimum, 0);
185
+ assert.equal(listComponent.properties.available.title.toJSON(), 'Available');
186
+ const actions = listComponent.properties._operationsRow.rest.table.columnProps.actions;
181
187
  assert.deepEqual(
182
- listComponent.properties._operationsRow.rest.table.columnProps.actions.map(
183
- (action: any) => action.render,
184
- ),
185
- ['basic-table:actionUpdate', 'basic-table:actionDelete'],
188
+ actions.map((action: any) => action.render),
189
+ [
190
+ 'commerce-trade:actionAdjustStock',
191
+ 'basic-table:actionUpdate',
192
+ 'basic-table:actionDelete',
193
+ ],
186
194
  );
195
+ assert.deepEqual(actions[0].options.permission, { actionInherit: 'update' });
187
196
 
188
197
  const filterBlock = listComponent.rest.blocks[0].options.blocks[0];
189
198
  const filterLayout = filterBlock.options.blocks[0].options.formLayout;
@@ -204,6 +213,7 @@ describe('skuPresentation.test.ts', () => {
204
213
  let categoryId: number | string | undefined;
205
214
  let productId: number | string | undefined;
206
215
  let skuId: number | string | undefined;
216
+ let skuIdWithBalance: number | string | undefined;
207
217
  await app.bean.passport.signinMock();
208
218
  try {
209
219
  categoryId = await app.bean.executor.performAction('post', '/commerce/catalog/category', {
@@ -224,6 +234,26 @@ describe('skuPresentation.test.ts', () => {
224
234
  lifecycle: 'draft',
225
235
  },
226
236
  });
237
+ const skuIdWithBalance = await app.bean.executor.performAction(
238
+ 'post',
239
+ '/commerce/catalog/sku',
240
+ {
241
+ body: {
242
+ code: `presentation-sku-balance-${suffix}`,
243
+ productId,
244
+ priceCents: 2345,
245
+ lifecycle: 'draft',
246
+ },
247
+ },
248
+ );
249
+ await app.bean.executor.performAction('post', '/commerce/trade/stockBalance/adjustStock', {
250
+ body: {
251
+ skuId: skuIdWithBalance,
252
+ delta: 7,
253
+ reason: `presentation stock ${suffix}`,
254
+ correlationId: `presentation-${suffix}`,
255
+ },
256
+ });
227
257
 
228
258
  const view: any = await app.bean.executor.performAction(
229
259
  'get',
@@ -247,12 +277,31 @@ describe('skuPresentation.test.ts', () => {
247
277
  });
248
278
  assert.equal(select.list.length, 1);
249
279
  assert.equal(String(select.list[0].id), String(skuId));
280
+ assert.equal(select.list[0].available, 0);
250
281
  assert.deepEqual(select.list[0].product, {
251
282
  id: productId,
252
283
  title: `presentation-sku-product-${suffix}`,
253
284
  });
254
285
  assert.equal(select.list[0].attributes, undefined);
286
+
287
+ const balanceSelect: any = await app.bean.executor.performAction(
288
+ 'get',
289
+ '/commerce/catalog/sku',
290
+ { query: { code: `presentation-sku-balance-${suffix}` } },
291
+ );
292
+ assert.equal(balanceSelect.list.length, 1);
293
+ assert.equal(String(balanceSelect.list[0].id), String(skuIdWithBalance));
294
+ assert.equal(balanceSelect.list[0].available, 7);
255
295
  } finally {
296
+ const tradeScope = app.scope('commerce-trade');
297
+ if (skuIdWithBalance) {
298
+ await tradeScope.model.stockAudit.delete({ skuId: skuIdWithBalance });
299
+ await tradeScope.model.stockReservation.delete({ skuId: skuIdWithBalance });
300
+ await tradeScope.model.stockBalance.delete({ skuId: skuIdWithBalance });
301
+ await app.bean.executor.performAction('delete', '/commerce/catalog/sku/:id', {
302
+ params: { id: skuIdWithBalance },
303
+ });
304
+ }
256
305
  if (skuId) {
257
306
  await app.bean.executor.performAction('delete', '/commerce/catalog/sku/:id', {
258
307
  params: { id: skuId },
@@ -675,154 +675,6 @@ declare module 'vona-module-a-orm' {
675
675
  }
676
676
  }
677
677
  /** model: end */
678
- /** bean: begin */
679
- export * from '../bean/bean.scheduleOrderExpiry.ts';
680
-
681
- import 'vona';
682
- declare module 'vona' {
683
-
684
-
685
- }
686
- declare module 'vona-module-commerce-trade' {
687
-
688
- export interface BeanScheduleOrderExpiry {
689
- /** @internal */
690
- get scope(): ScopeModuleCommerceTrade;
691
- }
692
- }
693
- /** bean: end */
694
- /** bean: begin */
695
- import type { BeanScheduleOrderExpiry } from '../bean/bean.scheduleOrderExpiry.ts';
696
- import 'vona';
697
- declare module 'vona' {
698
- export interface IBeanRecordGlobal {
699
- 'scheduleOrderExpiry': BeanScheduleOrderExpiry;
700
- }
701
- }
702
- /** bean: end */
703
- /** service: begin */
704
- export * from '../service/cart.ts';
705
- export * from '../service/order.ts';
706
- export * from '../service/stockAudit.ts';
707
- export * from '../service/stockBalance.ts';
708
-
709
- import 'vona-module-a-bean';
710
- declare module 'vona-module-a-bean' {
711
-
712
- export interface IServiceRecord {
713
- 'commerce-trade:cart': never;
714
- 'commerce-trade:order': never;
715
- 'commerce-trade:stockAudit': never;
716
- 'commerce-trade:stockBalance': never;
717
- }
718
-
719
-
720
- }
721
- declare module 'vona-module-commerce-trade' {
722
-
723
- export interface ServiceCart {
724
- /** @internal */
725
- get scope(): ScopeModuleCommerceTrade;
726
- }
727
-
728
- export interface ServiceCart {
729
- get $beanFullName(): 'commerce-trade.service.cart';
730
- get $onionName(): 'commerce-trade:cart';
731
- }
732
-
733
- export interface ServiceOrder {
734
- /** @internal */
735
- get scope(): ScopeModuleCommerceTrade;
736
- }
737
-
738
- export interface ServiceOrder {
739
- get $beanFullName(): 'commerce-trade.service.order';
740
- get $onionName(): 'commerce-trade:order';
741
- }
742
-
743
- export interface ServiceStockAudit {
744
- /** @internal */
745
- get scope(): ScopeModuleCommerceTrade;
746
- }
747
-
748
- export interface ServiceStockAudit {
749
- get $beanFullName(): 'commerce-trade.service.stockAudit';
750
- get $onionName(): 'commerce-trade:stockAudit';
751
- }
752
-
753
- export interface ServiceStockBalance {
754
- /** @internal */
755
- get scope(): ScopeModuleCommerceTrade;
756
- }
757
-
758
- export interface ServiceStockBalance {
759
- get $beanFullName(): 'commerce-trade.service.stockBalance';
760
- get $onionName(): 'commerce-trade:stockBalance';
761
- }
762
- }
763
- /** service: end */
764
- /** service: begin */
765
- import type { ServiceCart } from '../service/cart.ts';
766
- import type { ServiceOrder } from '../service/order.ts';
767
- import type { ServiceStockAudit } from '../service/stockAudit.ts';
768
- import type { ServiceStockBalance } from '../service/stockBalance.ts';
769
- export interface IModuleService {
770
- 'cart': ServiceCart;
771
- 'order': ServiceOrder;
772
- 'stockAudit': ServiceStockAudit;
773
- 'stockBalance': ServiceStockBalance;
774
- }
775
- /** service: end */
776
- /** service: begin */
777
-
778
- import 'vona';
779
- declare module 'vona' {
780
- export interface IBeanRecordGeneral {
781
- 'commerce-trade.service.cart': ServiceCart;
782
- 'commerce-trade.service.order': ServiceOrder;
783
- 'commerce-trade.service.stockAudit': ServiceStockAudit;
784
- 'commerce-trade.service.stockBalance': ServiceStockBalance;
785
- }
786
- }
787
- /** service: end */
788
- /** meta: begin */
789
- export * from '../bean/meta.index.ts';
790
- export * from '../bean/meta.version.ts';
791
- import type { IMetaOptionsIndex } from 'vona-module-a-index';
792
- import 'vona-module-a-meta';
793
- declare module 'vona-module-a-meta' {
794
-
795
- export interface IMetaRecord {
796
- 'commerce-trade:index': IMetaOptionsIndex;
797
- 'commerce-trade:version': never;
798
- }
799
-
800
-
801
- }
802
- declare module 'vona-module-commerce-trade' {
803
-
804
- export interface MetaIndex {
805
- /** @internal */
806
- get scope(): ScopeModuleCommerceTrade;
807
- }
808
-
809
- export interface MetaIndex {
810
- get $beanFullName(): 'commerce-trade.meta.index';
811
- get $onionName(): 'commerce-trade:index';
812
- get $onionOptions(): IMetaOptionsIndex;
813
- }
814
-
815
- export interface MetaVersion {
816
- /** @internal */
817
- get scope(): ScopeModuleCommerceTrade;
818
- }
819
-
820
- export interface MetaVersion {
821
- get $beanFullName(): 'commerce-trade.meta.version';
822
- get $onionName(): 'commerce-trade:version';
823
- }
824
- }
825
- /** meta: end */
826
678
  /** dto: begin */
827
679
  export * from '../dto/cartAddItem.tsx';
828
680
  export * from '../dto/cartItem.tsx';
@@ -1368,6 +1220,154 @@ import 'vona-module-a-openapi';
1368
1220
  }
1369
1221
 
1370
1222
  /** controller: end */
1223
+ /** bean: begin */
1224
+ export * from '../bean/bean.scheduleOrderExpiry.ts';
1225
+
1226
+ import 'vona';
1227
+ declare module 'vona' {
1228
+
1229
+
1230
+ }
1231
+ declare module 'vona-module-commerce-trade' {
1232
+
1233
+ export interface BeanScheduleOrderExpiry {
1234
+ /** @internal */
1235
+ get scope(): ScopeModuleCommerceTrade;
1236
+ }
1237
+ }
1238
+ /** bean: end */
1239
+ /** bean: begin */
1240
+ import type { BeanScheduleOrderExpiry } from '../bean/bean.scheduleOrderExpiry.ts';
1241
+ import 'vona';
1242
+ declare module 'vona' {
1243
+ export interface IBeanRecordGlobal {
1244
+ 'scheduleOrderExpiry': BeanScheduleOrderExpiry;
1245
+ }
1246
+ }
1247
+ /** bean: end */
1248
+ /** service: begin */
1249
+ export * from '../service/cart.ts';
1250
+ export * from '../service/order.ts';
1251
+ export * from '../service/stockAudit.ts';
1252
+ export * from '../service/stockBalance.ts';
1253
+
1254
+ import 'vona-module-a-bean';
1255
+ declare module 'vona-module-a-bean' {
1256
+
1257
+ export interface IServiceRecord {
1258
+ 'commerce-trade:cart': never;
1259
+ 'commerce-trade:order': never;
1260
+ 'commerce-trade:stockAudit': never;
1261
+ 'commerce-trade:stockBalance': never;
1262
+ }
1263
+
1264
+
1265
+ }
1266
+ declare module 'vona-module-commerce-trade' {
1267
+
1268
+ export interface ServiceCart {
1269
+ /** @internal */
1270
+ get scope(): ScopeModuleCommerceTrade;
1271
+ }
1272
+
1273
+ export interface ServiceCart {
1274
+ get $beanFullName(): 'commerce-trade.service.cart';
1275
+ get $onionName(): 'commerce-trade:cart';
1276
+ }
1277
+
1278
+ export interface ServiceOrder {
1279
+ /** @internal */
1280
+ get scope(): ScopeModuleCommerceTrade;
1281
+ }
1282
+
1283
+ export interface ServiceOrder {
1284
+ get $beanFullName(): 'commerce-trade.service.order';
1285
+ get $onionName(): 'commerce-trade:order';
1286
+ }
1287
+
1288
+ export interface ServiceStockAudit {
1289
+ /** @internal */
1290
+ get scope(): ScopeModuleCommerceTrade;
1291
+ }
1292
+
1293
+ export interface ServiceStockAudit {
1294
+ get $beanFullName(): 'commerce-trade.service.stockAudit';
1295
+ get $onionName(): 'commerce-trade:stockAudit';
1296
+ }
1297
+
1298
+ export interface ServiceStockBalance {
1299
+ /** @internal */
1300
+ get scope(): ScopeModuleCommerceTrade;
1301
+ }
1302
+
1303
+ export interface ServiceStockBalance {
1304
+ get $beanFullName(): 'commerce-trade.service.stockBalance';
1305
+ get $onionName(): 'commerce-trade:stockBalance';
1306
+ }
1307
+ }
1308
+ /** service: end */
1309
+ /** service: begin */
1310
+ import type { ServiceCart } from '../service/cart.ts';
1311
+ import type { ServiceOrder } from '../service/order.ts';
1312
+ import type { ServiceStockAudit } from '../service/stockAudit.ts';
1313
+ import type { ServiceStockBalance } from '../service/stockBalance.ts';
1314
+ export interface IModuleService {
1315
+ 'cart': ServiceCart;
1316
+ 'order': ServiceOrder;
1317
+ 'stockAudit': ServiceStockAudit;
1318
+ 'stockBalance': ServiceStockBalance;
1319
+ }
1320
+ /** service: end */
1321
+ /** service: begin */
1322
+
1323
+ import 'vona';
1324
+ declare module 'vona' {
1325
+ export interface IBeanRecordGeneral {
1326
+ 'commerce-trade.service.cart': ServiceCart;
1327
+ 'commerce-trade.service.order': ServiceOrder;
1328
+ 'commerce-trade.service.stockAudit': ServiceStockAudit;
1329
+ 'commerce-trade.service.stockBalance': ServiceStockBalance;
1330
+ }
1331
+ }
1332
+ /** service: end */
1333
+ /** meta: begin */
1334
+ export * from '../bean/meta.index.ts';
1335
+ export * from '../bean/meta.version.ts';
1336
+ import type { IMetaOptionsIndex } from 'vona-module-a-index';
1337
+ import 'vona-module-a-meta';
1338
+ declare module 'vona-module-a-meta' {
1339
+
1340
+ export interface IMetaRecord {
1341
+ 'commerce-trade:index': IMetaOptionsIndex;
1342
+ 'commerce-trade:version': never;
1343
+ }
1344
+
1345
+
1346
+ }
1347
+ declare module 'vona-module-commerce-trade' {
1348
+
1349
+ export interface MetaIndex {
1350
+ /** @internal */
1351
+ get scope(): ScopeModuleCommerceTrade;
1352
+ }
1353
+
1354
+ export interface MetaIndex {
1355
+ get $beanFullName(): 'commerce-trade.meta.index';
1356
+ get $onionName(): 'commerce-trade:index';
1357
+ get $onionOptions(): IMetaOptionsIndex;
1358
+ }
1359
+
1360
+ export interface MetaVersion {
1361
+ /** @internal */
1362
+ get scope(): ScopeModuleCommerceTrade;
1363
+ }
1364
+
1365
+ export interface MetaVersion {
1366
+ get $beanFullName(): 'commerce-trade.meta.version';
1367
+ get $onionName(): 'commerce-trade:version';
1368
+ }
1369
+ }
1370
+ /** meta: end */
1371
1371
  /** ssrMenu: begin */
1372
1372
  export * from '../bean/ssrMenu.order.ts';
1373
1373
  export * from '../bean/ssrMenu.stockAudit.ts';
@@ -4,19 +4,47 @@ import type { IDecoratorDtoOptions } from 'vona-module-a-web';
4
4
  import { Api, v } from 'vona-module-a-openapiutils';
5
5
  import { Dto } from 'vona-module-a-web';
6
6
  import { z } from 'zod';
7
+ import { ZovaRender } from 'zova-rest-cabloy-basic-admin';
7
8
 
8
9
  import { $locale } from '../.metadata/locales.ts';
9
10
 
10
11
  export interface IDtoOptionsStockAdjust extends IDecoratorDtoOptions {}
11
12
 
12
- @Dto<IDtoOptionsStockAdjust>({ openapi: { title: $locale('AdjustStock') } })
13
+ @Dto<IDtoOptionsStockAdjust>({
14
+ openapi: { title: $locale('AdjustStock') },
15
+ blocks: [
16
+ ZovaRender.block('basic-pageentry:blockPageEntry', {
17
+ blocks: [
18
+ ZovaRender.block('basic-pageentry:blockForm', {
19
+ blocks: [
20
+ ZovaRender.block('basic-form:blockFormLayout', {
21
+ formLayout: {
22
+ children: [
23
+ {
24
+ type: 'section',
25
+ layout: 'flow',
26
+ children: [
27
+ { type: 'field', name: 'delta' },
28
+ { type: 'field', name: 'reason' },
29
+ ],
30
+ },
31
+ ],
32
+ },
33
+ }),
34
+ ],
35
+ }),
36
+ ],
37
+ }),
38
+ ],
39
+ })
13
40
  export class DtoStockAdjust {
14
- @Api.field(v.title($locale('SkuId')), v.required(), v.tableIdentity())
41
+ @Api.field(v.title($locale('SkuId')), v.required(), v.tableIdentity(), ZovaRender.visible(false))
15
42
  skuId: TableIdentity;
16
43
 
17
44
  @Api.field(
18
45
  v.title($locale('Delta')),
19
46
  v.required(),
47
+ ZovaRender.field('basic-input:formFieldInput', { type: 'number' }),
20
48
  z
21
49
  .number()
22
50
  .int()
@@ -27,6 +55,12 @@ export class DtoStockAdjust {
27
55
  @Api.field(v.title($locale('Reason')), v.required(), v.min(1), v.max(255))
28
56
  reason: string;
29
57
 
30
- @Api.field(v.title($locale('CorrelationId')), v.required(), v.min(1), v.max(100))
58
+ @Api.field(
59
+ v.title($locale('CorrelationId')),
60
+ v.required(),
61
+ v.min(1),
62
+ v.max(100),
63
+ ZovaRender.visible(false),
64
+ )
31
65
  correlationId: string;
32
66
  }
@@ -116,8 +116,8 @@ declare module 'vona-module-training-student' {
116
116
  export interface IModelOptionsStudent {
117
117
  relations: {
118
118
  trainingRecords: IModelRelationHasMany<'training-record:record', 'studentId', false, 'id'|'name'|'subjectCount'|'totalScore'|'averageScore'|'trainingTime'|'sceneImageIds'|'dossierFileIds'|'description', undefined, undefined, undefined>;
119
- studentContent: IModelRelationHasOne<'training-student:studentContent', 'studentId', false, 'id'|'studentId'|'descriptionMarkdown'|'descriptionHtml'>;
120
- studentContentForm: IModelRelationHasOne<'training-student:studentContent', 'studentId', false, 'id'|'studentId'|'descriptionMarkdown'>;
119
+ content: IModelRelationHasOne<'training-student:studentContent', 'studentId', false, 'id'|'descriptionMarkdown'>;
120
+ contentHtml: IModelRelationHasOne<'training-student:studentContent', 'studentId', false, 'id'|'descriptionHtml'>;
121
121
  };
122
122
  }
123
123
  export interface IModelOptionsStudentContent {
@@ -10,12 +10,12 @@ import { ModelStudent } from '../model/student.ts';
10
10
  import { DtoDetailRecordMutate } from './detailRecordMutate.tsx';
11
11
  import { DtoDetailRecordResItem } from './detailRecordResItem.tsx';
12
12
 
13
- const studentContentFormField = $makeMetadata(
14
- ZovaRender.fieldSource('studentContentForm.descriptionMarkdown'),
13
+ const studentContentField = $makeMetadata(
14
+ ZovaRender.fieldSource('content.descriptionMarkdown'),
15
15
  ZovaRender.field('basic-markdown:formFieldMarkdown'),
16
16
  );
17
17
 
18
- export interface IDtoOptionsStudentCreate extends IDecoratorDtoOptions<'studentContentForm'> {}
18
+ export interface IDtoOptionsStudentCreate extends IDecoratorDtoOptions<'content'> {}
19
19
 
20
20
  @Dto<IDtoOptionsStudentCreate>({
21
21
  blocks: [
@@ -54,7 +54,7 @@ export interface IDtoOptionsStudentCreate extends IDecoratorDtoOptions<'studentC
54
54
  children: [
55
55
  {
56
56
  type: 'section',
57
- children: [{ type: 'field', name: 'studentContentForm' }],
57
+ children: [{ type: 'field', name: 'content' }],
58
58
  },
59
59
  ],
60
60
  },
@@ -93,7 +93,7 @@ export interface IDtoOptionsStudentCreate extends IDecoratorDtoOptions<'studentC
93
93
  }),
94
94
  ],
95
95
  fields: {
96
- studentContentForm: studentContentFormField,
96
+ content: studentContentField,
97
97
  trainingRecords: $makeMetadata(
98
98
  v.title($locale('TrainingRecords')),
99
99
  ZovaRender.order(6),
@@ -103,8 +103,9 @@ export interface IDtoOptionsStudentCreate extends IDecoratorDtoOptions<'studentC
103
103
  },
104
104
  })
105
105
  export class DtoStudentCreate extends $Dto.create(() => ModelStudent, {
106
+ columns: ['name', 'mobile', 'imageId', 'level'],
106
107
  include: {
107
- studentContentForm: true,
108
+ content: { columns: ['descriptionMarkdown'] },
108
109
  trainingRecords: { dtoClass: DtoDetailRecordMutate },
109
110
  },
110
111
  }) {
@@ -14,7 +14,7 @@ export class DtoStudentSummary extends $Dto.get(() => ModelStudent, {
14
14
  columns: ['id', 'name', 'mobile', 'level'],
15
15
  }) {
16
16
  @Api.field(v.title($locale('Description')), v.optional())
17
- description?: string;
17
+ descriptionMarkdown?: string;
18
18
 
19
19
  @Api.field(v.title($locale('DescriptionHtml')), v.optional())
20
20
  descriptionHtml?: string;
@@ -10,12 +10,12 @@ import { ModelStudent } from '../model/student.ts';
10
10
  import { DtoDetailRecordMutate } from './detailRecordMutate.tsx';
11
11
  import { DtoDetailRecordResItem } from './detailRecordResItem.tsx';
12
12
 
13
- const studentContentFormField = $makeMetadata(
14
- ZovaRender.fieldSource('studentContentForm.descriptionMarkdown'),
13
+ const studentContentField = $makeMetadata(
14
+ ZovaRender.fieldSource('content.descriptionMarkdown'),
15
15
  ZovaRender.field('basic-markdown:formFieldMarkdown'),
16
16
  );
17
17
 
18
- export interface IDtoOptionsStudentUpdate extends IDecoratorDtoOptions<'studentContentForm'> {}
18
+ export interface IDtoOptionsStudentUpdate extends IDecoratorDtoOptions<'content'> {}
19
19
 
20
20
  @Dto<IDtoOptionsStudentUpdate>({
21
21
  blocks: [
@@ -54,7 +54,7 @@ export interface IDtoOptionsStudentUpdate extends IDecoratorDtoOptions<'studentC
54
54
  children: [
55
55
  {
56
56
  type: 'section',
57
- children: [{ type: 'field', name: 'studentContentForm' }],
57
+ children: [{ type: 'field', name: 'content' }],
58
58
  },
59
59
  ],
60
60
  },
@@ -90,7 +90,7 @@ export interface IDtoOptionsStudentUpdate extends IDecoratorDtoOptions<'studentC
90
90
  }),
91
91
  ],
92
92
  fields: {
93
- studentContentForm: studentContentFormField,
93
+ content: studentContentField,
94
94
  trainingRecords: $makeMetadata(
95
95
  v.title($locale('TrainingRecords')),
96
96
  ZovaRender.order(6),
@@ -99,8 +99,9 @@ export interface IDtoOptionsStudentUpdate extends IDecoratorDtoOptions<'studentC
99
99
  },
100
100
  })
101
101
  export class DtoStudentUpdate extends $Dto.update(() => ModelStudent, {
102
+ columns: ['name', 'mobile', 'imageId', 'level'],
102
103
  include: {
103
- studentContentForm: true,
104
+ content: { columns: ['descriptionMarkdown'] },
104
105
  trainingRecords: { dtoClass: DtoDetailRecordMutate },
105
106
  },
106
107
  }) {
@@ -1,9 +1,10 @@
1
1
  import type { IDecoratorDtoOptions } from 'vona-module-a-web';
2
2
 
3
3
  import { DtoImageView } from 'vona-module-a-image';
4
- import { $makeMetadata, Api, v } from 'vona-module-a-openapiutils';
4
+ import { $makeMetadata, $makeSchema, Api, v } from 'vona-module-a-openapiutils';
5
5
  import { $Dto } from 'vona-module-a-orm';
6
6
  import { Dto } from 'vona-module-a-web';
7
+ import z from 'zod';
7
8
  import { ZovaRender } from 'zova-rest-cabloy-basic-admin';
8
9
 
9
10
  import { $locale } from '../.metadata/locales.ts';
@@ -11,12 +12,14 @@ import { ModelStudent } from '../model/student.ts';
11
12
  import { DtoDetailRecordResItem } from './detailRecordResItem.tsx';
12
13
  import { DtoDetailRecordView } from './detailRecordView.tsx';
13
14
 
14
- const studentContentFormField = $makeMetadata(
15
- ZovaRender.fieldSource('studentContentForm.descriptionMarkdown'),
15
+ const studentContentField = $makeSchema(
16
+ ZovaRender.fieldSource('content.descriptionMarkdown'),
16
17
  ZovaRender.field('basic-markdown:formFieldMarkdown'),
18
+ v.optional(),
19
+ z.string(),
17
20
  );
18
21
 
19
- export interface IDtoOptionsStudentView extends IDecoratorDtoOptions<'studentContentForm'> {}
22
+ export interface IDtoOptionsStudentView extends IDecoratorDtoOptions<'_descriptionMarkdown'> {}
20
23
 
21
24
  @Dto<IDtoOptionsStudentView>({
22
25
  blocks: [
@@ -55,7 +58,7 @@ export interface IDtoOptionsStudentView extends IDecoratorDtoOptions<'studentCon
55
58
  children: [
56
59
  {
57
60
  type: 'section',
58
- children: [{ type: 'field', name: 'studentContentForm' }],
61
+ children: [{ type: 'field', name: '_descriptionMarkdown' }],
59
62
  },
60
63
  ],
61
64
  },
@@ -88,7 +91,7 @@ export interface IDtoOptionsStudentView extends IDecoratorDtoOptions<'studentCon
88
91
  }),
89
92
  ],
90
93
  fields: {
91
- studentContentForm: studentContentFormField,
94
+ _descriptionMarkdown: studentContentField,
92
95
  trainingRecords: $makeMetadata(
93
96
  v.title($locale('TrainingRecords')),
94
97
  ZovaRender.order(6),
@@ -98,7 +101,7 @@ export interface IDtoOptionsStudentView extends IDecoratorDtoOptions<'studentCon
98
101
  })
99
102
  export class DtoStudentView extends $Dto.get(() => ModelStudent, {
100
103
  include: {
101
- studentContentForm: true,
104
+ content: { columns: ['descriptionMarkdown'] },
102
105
  trainingRecords: { dtoClass: DtoDetailRecordView },
103
106
  },
104
107
  }) {
@@ -22,11 +22,11 @@ export interface IModelOptionsStudent extends IDecoratorModelOptions<EntityStude
22
22
  'description',
23
23
  ],
24
24
  }),
25
- studentContent: $relation.hasOne('training-student:studentContent', 'studentId', {
26
- columns: ['id', 'studentId', 'descriptionMarkdown', 'descriptionHtml'],
25
+ content: $relation.hasOne('training-student:studentContent', 'studentId', {
26
+ columns: ['id', 'descriptionMarkdown'],
27
27
  }),
28
- studentContentForm: $relation.hasOne('training-student:studentContent', 'studentId', {
29
- columns: ['id', 'studentId', 'descriptionMarkdown'],
28
+ contentHtml: $relation.hasOne('training-student:studentContent', 'studentId', {
29
+ columns: ['id', 'descriptionHtml'],
30
30
  }),
31
31
  },
32
32
  })