@rytass/wms-module-graphql 0.8.0 → 0.9.0

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 (42) hide show
  1. package/README.md +83 -1
  2. package/docs/api-reference.md +76 -1
  3. package/docs/events.md +23 -4
  4. package/index.cjs.js +779 -1
  5. package/index.d.ts +3 -1
  6. package/index.js +2 -0
  7. package/lib/dto/index.d.ts +1 -0
  8. package/lib/dto/inventory-count-order.dto.d.ts +49 -0
  9. package/lib/dto/inventory-count-order.dto.js +146 -0
  10. package/lib/events/operation-result-map.d.ts +8 -0
  11. package/lib/graphql.module.d.ts +6 -2
  12. package/lib/graphql.module.js +18 -1
  13. package/lib/inputs/inventory-count-order.args.d.ts +55 -0
  14. package/lib/inputs/inventory-count-order.args.js +196 -0
  15. package/lib/mutations/inventory-count-order.mutation.d.ts +19 -0
  16. package/lib/mutations/inventory-count-order.mutation.js +138 -0
  17. package/lib/mutations/loader.mutation.js +1 -0
  18. package/lib/mutations/material.mutation.js +1 -0
  19. package/lib/mutations/receive-inventory-order.mutation.js +1 -0
  20. package/lib/mutations/ship-inventory-order.mutation.js +1 -0
  21. package/lib/queries/inventory-count-order.query.d.ts +9 -0
  22. package/lib/queries/inventory-count-order.query.js +44 -0
  23. package/lib/queries/loader.query.js +1 -0
  24. package/lib/queries/material.query.js +1 -0
  25. package/lib/queries/recieve-inventory-order.query.js +1 -0
  26. package/lib/queries/ship-inventory-order.query.js +1 -0
  27. package/lib/queries/stock.query.js +1 -0
  28. package/lib/registry/index.d.ts +1 -0
  29. package/lib/registry/operation-registry.d.ts +59 -0
  30. package/lib/registry/operation-registry.js +136 -0
  31. package/lib/resolvers/aggregated-stock.resolver.js +1 -0
  32. package/lib/resolvers/change-log.resolver.js +1 -0
  33. package/lib/resolvers/inventory-count-order.resolver.d.ts +34 -0
  34. package/lib/resolvers/inventory-count-order.resolver.js +148 -0
  35. package/lib/resolvers/loader-type.resolver.js +1 -0
  36. package/lib/resolvers/loader.resolver.js +1 -0
  37. package/lib/resolvers/material.resolver.js +1 -0
  38. package/lib/resolvers/receive-inventory-order.resolver.js +1 -0
  39. package/lib/resolvers/ship-inventory-order.resolver.js +1 -0
  40. package/lib/resolvers/stock.resolver.js +1 -0
  41. package/lib/resolvers/transfer-order.resolver.js +1 -0
  42. package/package.json +2 -2
package/index.cjs.js CHANGED
@@ -465,6 +465,138 @@ exports.WmsMutationInterceptor = tslib.__decorate([
465
465
  */
466
466
  const WmsMutationEvent = (config) => common.applyDecorators(common.SetMetadata(WMS_MUTATION_EVENT_METADATA, config), common.UseInterceptors(exports.WmsMutationInterceptor));
467
467
 
468
+ function resolveDisabled(options) {
469
+ const { enabledOperations, disabledOperations, disabledFields } = options;
470
+ if (enabledOperations && disabledOperations) {
471
+ throw new Error('[wms-module-graphql] `enabledOperations` and `disabledOperations` are mutually exclusive — pass one or the other, not both.');
472
+ }
473
+ const enabled = enabledOperations ? new Set(enabledOperations) : null;
474
+ const disabled = disabledOperations
475
+ ? new Set(disabledOperations)
476
+ : null;
477
+ const fields = new Set(disabledFields ?? []);
478
+ return {
479
+ hasSwitches: enabled !== null || disabled !== null || fields.size > 0,
480
+ isOperationDisabled: (name) => {
481
+ if (enabled) {
482
+ return !enabled.has(name);
483
+ }
484
+ if (disabled) {
485
+ return disabled.has(name);
486
+ }
487
+ return false;
488
+ },
489
+ disabledFields: fields,
490
+ };
491
+ }
492
+ /** Methods already pruned, so the metadata filter can drop their entries. */
493
+ const prunedMethods = new WeakMap();
494
+ let metadataFilterInstalled = false;
495
+ /**
496
+ * Stop the pruned operations from ever entering `TypeMetadataStorage`.
497
+ *
498
+ * The resolver metadata is **lazy**: `@Query()` / `@Mutation()` only register a
499
+ * thunk with `LazyMetadataStorage`, and the thunk calls `add*Metadata` when
500
+ * `GraphQLSchemaBuilder.build()` loads it. At `forRootAsync` time the storage
501
+ * arrays are therefore still empty, and filtering them then would remove
502
+ * nothing — so the filter has to sit on the writes instead.
503
+ */
504
+ function installMetadataFilter() {
505
+ if (metadataFilterInstalled) {
506
+ return;
507
+ }
508
+ const storage = graphql.TypeMetadataStorage;
509
+ const addQuery = storage.addQueryMetadata.bind(storage);
510
+ const addMutation = storage.addMutationMetadata.bind(storage);
511
+ const isPruned = (metadata) => prunedMethods.get(metadata.target)?.has(metadata.methodName) === true;
512
+ storage.addQueryMetadata = (metadata) => {
513
+ if (isPruned(metadata)) {
514
+ return;
515
+ }
516
+ addQuery(metadata);
517
+ };
518
+ storage.addMutationMetadata = (metadata) => {
519
+ if (isPruned(metadata)) {
520
+ return;
521
+ }
522
+ addMutation(metadata);
523
+ };
524
+ metadataFilterInstalled = true;
525
+ }
526
+ /** The GraphQL field name a root handler ends up under. */
527
+ function schemaNameOf(handler, methodName) {
528
+ const explicit = Reflect.getMetadata(graphql.RESOLVER_NAME_METADATA, handler);
529
+ return explicit || methodName;
530
+ }
531
+ /**
532
+ * Remove the switched-off root operations before the schema is built.
533
+ *
534
+ * Two edits are needed, at two different moments, and they must happen together:
535
+ *
536
+ * 1. **now** — `delete Resolver.prototype[method]`, because
537
+ * `ResolversExplorerService.explore()` walks the prototype with
538
+ * `MetadataScanner` and runs *before* the schema builder loads the lazy
539
+ * metadata. Leaving the method in place would put `Query.foo` in the resolver
540
+ * map with no matching field in the typeDefs, and `makeExecutableSchema`
541
+ * rejects the whole schema (`requireResolversToMatchSchema`).
542
+ * 2. **at load time** — drop the metadata entry ({@link installMetadataFilter}),
543
+ * or the SDL would still declare a field that resolves to `null`: present,
544
+ * but dead.
545
+ *
546
+ * Deleting the prototype method does not disturb step 2's type reflection:
547
+ * `design:returntype` is stored against the prototype and property key, not
548
+ * against the function object, so it survives the delete.
549
+ *
550
+ * This runs synchronously from `forRootAsync`, i.e. while `AppModule` is still
551
+ * being defined. Both the classes and the storage are process-global, so a
552
+ * process may register `WmsModuleGraphqlModule` only once.
553
+ */
554
+ function pruneDisabledOperations(resolverClasses, options) {
555
+ const { hasSwitches, isOperationDisabled, disabledFields } = resolveDisabled(options);
556
+ if (!hasSwitches) {
557
+ return { queries: [], mutations: [] };
558
+ }
559
+ installMetadataFilter();
560
+ const queries = [];
561
+ const mutations = [];
562
+ for (const resolverClass of resolverClasses) {
563
+ const prototype = resolverClass.prototype;
564
+ if (!prototype) {
565
+ continue;
566
+ }
567
+ for (const methodName of Object.getOwnPropertyNames(prototype)) {
568
+ if (methodName === 'constructor') {
569
+ continue;
570
+ }
571
+ const handler = prototype[methodName];
572
+ if (typeof handler !== 'function') {
573
+ continue;
574
+ }
575
+ const resolverType = Reflect.getMetadata(graphql.RESOLVER_TYPE_METADATA, handler);
576
+ // Only root operations are switchable. `@ResolveField` handlers are
577
+ // reached exclusively through an already-registered root field, so
578
+ // removing one would break the type rather than the deployment surface.
579
+ if (resolverType !== 'Query' && resolverType !== 'Mutation') {
580
+ continue;
581
+ }
582
+ const schemaName = schemaNameOf(handler, methodName);
583
+ const requirement = Reflect.getMetadata(WMS_OPERATION_METADATA, handler);
584
+ const disabled = disabledFields.has(schemaName) ||
585
+ (requirement !== undefined &&
586
+ isOperationDisabled(`${requirement.resource}:${requirement.action}`));
587
+ if (!disabled) {
588
+ continue;
589
+ }
590
+ const alreadyPruned = prunedMethods.get(resolverClass) ?? new Set();
591
+ alreadyPruned.add(methodName);
592
+ prunedMethods.set(resolverClass, alreadyPruned);
593
+ delete prototype[methodName];
594
+ (resolverType === 'Query' ? queries : mutations).push(schemaName);
595
+ }
596
+ }
597
+ return { queries, mutations };
598
+ }
599
+
468
600
  const IdGenFunction = (input) => {
469
601
  const hash = crypto.createHash('sha256');
470
602
  hash.update(input);
@@ -1602,6 +1734,146 @@ QualityInspectionOrders = tslib.__decorate([
1602
1734
  graphql.ObjectType()
1603
1735
  ], QualityInspectionOrders);
1604
1736
 
1737
+ graphql.registerEnumType(wmsModuleCore.InventoryCountStatus, {
1738
+ name: 'InventoryCountStatus',
1739
+ description: 'Lifecycle of an inventory count: PENDING (尚未執行) → COUNTING (盤點中) → COMPLETED (已完成), or CANCELLED (已取消).',
1740
+ });
1741
+ /**
1742
+ * A count-sheet line.
1743
+ *
1744
+ * `material` / `batch` / `location` / `loader` are deliberately absent from this
1745
+ * class: they are added to the schema by `InventoryCountOrderItemResolver` as
1746
+ * `@ResolveField`s so they load through DataLoaders, and declaring them here
1747
+ * would make the class stop matching the entity the service returns.
1748
+ */
1749
+ let InventoryCountOrderItemDto = class InventoryCountOrderItemDto {
1750
+ id;
1751
+ orderId;
1752
+ materialId;
1753
+ batchId;
1754
+ locationId;
1755
+ loaderId;
1756
+ unitId;
1757
+ /** Ledger quantity in base units, frozen when counting started. */
1758
+ bookQuantity;
1759
+ /** What was found, expressed in `unitId`. `null` until someone counts it. */
1760
+ countedQuantity;
1761
+ /** `true` for a line added during counting for stock the books never had. */
1762
+ isAddition;
1763
+ };
1764
+ tslib.__decorate([
1765
+ graphql.Field(() => graphql.ID),
1766
+ tslib.__metadata("design:type", String)
1767
+ ], InventoryCountOrderItemDto.prototype, "id", void 0);
1768
+ tslib.__decorate([
1769
+ graphql.Field(() => graphql.ID),
1770
+ tslib.__metadata("design:type", String)
1771
+ ], InventoryCountOrderItemDto.prototype, "orderId", void 0);
1772
+ tslib.__decorate([
1773
+ graphql.Field(() => graphql.ID),
1774
+ tslib.__metadata("design:type", String)
1775
+ ], InventoryCountOrderItemDto.prototype, "materialId", void 0);
1776
+ tslib.__decorate([
1777
+ graphql.Field(() => graphql.ID),
1778
+ tslib.__metadata("design:type", String)
1779
+ ], InventoryCountOrderItemDto.prototype, "batchId", void 0);
1780
+ tslib.__decorate([
1781
+ graphql.Field(() => graphql.ID, { nullable: true }),
1782
+ tslib.__metadata("design:type", Object)
1783
+ ], InventoryCountOrderItemDto.prototype, "locationId", void 0);
1784
+ tslib.__decorate([
1785
+ graphql.Field(() => graphql.ID, { nullable: true }),
1786
+ tslib.__metadata("design:type", Object)
1787
+ ], InventoryCountOrderItemDto.prototype, "loaderId", void 0);
1788
+ tslib.__decorate([
1789
+ graphql.Field(() => graphql.ID, { nullable: true }),
1790
+ tslib.__metadata("design:type", Object)
1791
+ ], InventoryCountOrderItemDto.prototype, "unitId", void 0);
1792
+ tslib.__decorate([
1793
+ graphql.Field(() => graphql.Float),
1794
+ tslib.__metadata("design:type", Number)
1795
+ ], InventoryCountOrderItemDto.prototype, "bookQuantity", void 0);
1796
+ tslib.__decorate([
1797
+ graphql.Field(() => graphql.Float, { nullable: true }),
1798
+ tslib.__metadata("design:type", Object)
1799
+ ], InventoryCountOrderItemDto.prototype, "countedQuantity", void 0);
1800
+ tslib.__decorate([
1801
+ graphql.Field(() => Boolean),
1802
+ tslib.__metadata("design:type", Boolean)
1803
+ ], InventoryCountOrderItemDto.prototype, "isAddition", void 0);
1804
+ InventoryCountOrderItemDto = tslib.__decorate([
1805
+ graphql.ObjectType()
1806
+ ], InventoryCountOrderItemDto);
1807
+ /**
1808
+ * A count order. `items` and `locations` come from
1809
+ * `InventoryCountOrderResolver`, for the same reason as above; `locations`
1810
+ * exposes the roots the user picked, not the expanded subtree.
1811
+ */
1812
+ let InventoryCountOrderDto = class InventoryCountOrderDto {
1813
+ id;
1814
+ key;
1815
+ name;
1816
+ /**
1817
+ * The count's base date. Stock adjustments from settlement are reported under
1818
+ * this date rather than the day settlement happened to run.
1819
+ */
1820
+ countDate;
1821
+ status;
1822
+ createdBy;
1823
+ startedAt;
1824
+ settledAt;
1825
+ cancelledAt;
1826
+ createdAt;
1827
+ };
1828
+ tslib.__decorate([
1829
+ graphql.Field(() => graphql.ID),
1830
+ tslib.__metadata("design:type", String)
1831
+ ], InventoryCountOrderDto.prototype, "id", void 0);
1832
+ tslib.__decorate([
1833
+ graphql.Field(() => String),
1834
+ tslib.__metadata("design:type", String)
1835
+ ], InventoryCountOrderDto.prototype, "key", void 0);
1836
+ tslib.__decorate([
1837
+ graphql.Field(() => String),
1838
+ tslib.__metadata("design:type", String)
1839
+ ], InventoryCountOrderDto.prototype, "name", void 0);
1840
+ tslib.__decorate([
1841
+ graphql.Field(() => String),
1842
+ tslib.__metadata("design:type", String)
1843
+ ], InventoryCountOrderDto.prototype, "countDate", void 0);
1844
+ tslib.__decorate([
1845
+ graphql.Field(() => wmsModuleCore.InventoryCountStatus),
1846
+ tslib.__metadata("design:type", String)
1847
+ ], InventoryCountOrderDto.prototype, "status", void 0);
1848
+ tslib.__decorate([
1849
+ graphql.Field(() => String, { nullable: true }),
1850
+ tslib.__metadata("design:type", Object)
1851
+ ], InventoryCountOrderDto.prototype, "createdBy", void 0);
1852
+ tslib.__decorate([
1853
+ graphql.Field(() => Date, { nullable: true }),
1854
+ tslib.__metadata("design:type", Object)
1855
+ ], InventoryCountOrderDto.prototype, "startedAt", void 0);
1856
+ tslib.__decorate([
1857
+ graphql.Field(() => Date, { nullable: true }),
1858
+ tslib.__metadata("design:type", Object)
1859
+ ], InventoryCountOrderDto.prototype, "settledAt", void 0);
1860
+ tslib.__decorate([
1861
+ graphql.Field(() => Date, { nullable: true }),
1862
+ tslib.__metadata("design:type", Object)
1863
+ ], InventoryCountOrderDto.prototype, "cancelledAt", void 0);
1864
+ tslib.__decorate([
1865
+ graphql.Field(() => Date),
1866
+ tslib.__metadata("design:type", Date)
1867
+ ], InventoryCountOrderDto.prototype, "createdAt", void 0);
1868
+ InventoryCountOrderDto = tslib.__decorate([
1869
+ graphql.ObjectType()
1870
+ ], InventoryCountOrderDto);
1871
+ let InventoryCountOrders = class InventoryCountOrders extends PaginatedResponse(InventoryCountOrderDto) {
1872
+ };
1873
+ InventoryCountOrders = tslib.__decorate([
1874
+ graphql.ObjectType()
1875
+ ], InventoryCountOrders);
1876
+
1605
1877
  let CreateLoaderTypeArgs = class CreateLoaderTypeArgs {
1606
1878
  description;
1607
1879
  key;
@@ -6678,6 +6950,494 @@ MapRangeUnionResolver = tslib.__decorate([
6678
6950
  tslib.__metadata("design:paramtypes", [wmsModuleCore.WmsEntities])
6679
6951
  ], MapRangeUnionResolver);
6680
6952
 
6953
+ let FindInventoryCountOrderArgs = class FindInventoryCountOrderArgs extends PaginationArgs {
6954
+ name;
6955
+ statuses;
6956
+ createdBy;
6957
+ /** Inclusive lower bound on `countDate`, `YYYY-MM-DD`. */
6958
+ countDateFrom;
6959
+ /** Inclusive upper bound on `countDate`, `YYYY-MM-DD`. */
6960
+ countDateTo;
6961
+ /**
6962
+ * Matches against the expanded scope, not the roots the user picked, so
6963
+ * filtering by a shelf finds the count that covers its whole aisle.
6964
+ */
6965
+ locationIds;
6966
+ };
6967
+ tslib.__decorate([
6968
+ graphql.Field(() => String, { nullable: true }),
6969
+ tslib.__metadata("design:type", String)
6970
+ ], FindInventoryCountOrderArgs.prototype, "name", void 0);
6971
+ tslib.__decorate([
6972
+ graphql.Field(() => [wmsModuleCore.InventoryCountStatus], { nullable: true }),
6973
+ tslib.__metadata("design:type", Array)
6974
+ ], FindInventoryCountOrderArgs.prototype, "statuses", void 0);
6975
+ tslib.__decorate([
6976
+ graphql.Field(() => String, { nullable: true }),
6977
+ tslib.__metadata("design:type", String)
6978
+ ], FindInventoryCountOrderArgs.prototype, "createdBy", void 0);
6979
+ tslib.__decorate([
6980
+ graphql.Field(() => String, { nullable: true }),
6981
+ tslib.__metadata("design:type", String)
6982
+ ], FindInventoryCountOrderArgs.prototype, "countDateFrom", void 0);
6983
+ tslib.__decorate([
6984
+ graphql.Field(() => String, { nullable: true }),
6985
+ tslib.__metadata("design:type", String)
6986
+ ], FindInventoryCountOrderArgs.prototype, "countDateTo", void 0);
6987
+ tslib.__decorate([
6988
+ graphql.Field(() => [graphql.ID], { nullable: true }),
6989
+ tslib.__metadata("design:type", Array)
6990
+ ], FindInventoryCountOrderArgs.prototype, "locationIds", void 0);
6991
+ FindInventoryCountOrderArgs = tslib.__decorate([
6992
+ graphql.ArgsType()
6993
+ ], FindInventoryCountOrderArgs);
6994
+ let CreateInventoryCountOrderArgs = class CreateInventoryCountOrderArgs {
6995
+ name;
6996
+ countDate;
6997
+ /** Root locations; every descendant is pulled into scope automatically. */
6998
+ locationIds;
6999
+ };
7000
+ tslib.__decorate([
7001
+ graphql.Field(() => String),
7002
+ tslib.__metadata("design:type", String)
7003
+ ], CreateInventoryCountOrderArgs.prototype, "name", void 0);
7004
+ tslib.__decorate([
7005
+ graphql.Field(() => String),
7006
+ tslib.__metadata("design:type", String)
7007
+ ], CreateInventoryCountOrderArgs.prototype, "countDate", void 0);
7008
+ tslib.__decorate([
7009
+ graphql.Field(() => [graphql.ID]),
7010
+ tslib.__metadata("design:type", Array)
7011
+ ], CreateInventoryCountOrderArgs.prototype, "locationIds", void 0);
7012
+ CreateInventoryCountOrderArgs = tslib.__decorate([
7013
+ graphql.ArgsType()
7014
+ ], CreateInventoryCountOrderArgs);
7015
+ let UpdateInventoryCountOrderArgs = class UpdateInventoryCountOrderArgs {
7016
+ id;
7017
+ name;
7018
+ countDate;
7019
+ locationIds;
7020
+ };
7021
+ tslib.__decorate([
7022
+ graphql.Field(() => graphql.ID),
7023
+ tslib.__metadata("design:type", String)
7024
+ ], UpdateInventoryCountOrderArgs.prototype, "id", void 0);
7025
+ tslib.__decorate([
7026
+ graphql.Field(() => String, { nullable: true }),
7027
+ tslib.__metadata("design:type", String)
7028
+ ], UpdateInventoryCountOrderArgs.prototype, "name", void 0);
7029
+ tslib.__decorate([
7030
+ graphql.Field(() => String, { nullable: true }),
7031
+ tslib.__metadata("design:type", String)
7032
+ ], UpdateInventoryCountOrderArgs.prototype, "countDate", void 0);
7033
+ tslib.__decorate([
7034
+ graphql.Field(() => [graphql.ID], { nullable: true }),
7035
+ tslib.__metadata("design:type", Array)
7036
+ ], UpdateInventoryCountOrderArgs.prototype, "locationIds", void 0);
7037
+ UpdateInventoryCountOrderArgs = tslib.__decorate([
7038
+ graphql.ArgsType()
7039
+ ], UpdateInventoryCountOrderArgs);
7040
+ let CountInventoryItemInput = class CountInventoryItemInput {
7041
+ itemId;
7042
+ /** `null` clears the entry, putting the line back to "not counted". */
7043
+ countedQuantity;
7044
+ unitId;
7045
+ };
7046
+ tslib.__decorate([
7047
+ graphql.Field(() => graphql.ID),
7048
+ tslib.__metadata("design:type", String)
7049
+ ], CountInventoryItemInput.prototype, "itemId", void 0);
7050
+ tslib.__decorate([
7051
+ graphql.Field(() => graphql.Float, { nullable: true }),
7052
+ tslib.__metadata("design:type", Object)
7053
+ ], CountInventoryItemInput.prototype, "countedQuantity", void 0);
7054
+ tslib.__decorate([
7055
+ graphql.Field(() => graphql.ID, { nullable: true }),
7056
+ tslib.__metadata("design:type", Object)
7057
+ ], CountInventoryItemInput.prototype, "unitId", void 0);
7058
+ CountInventoryItemInput = tslib.__decorate([
7059
+ graphql.InputType()
7060
+ ], CountInventoryItemInput);
7061
+ let CountInventoryArgs = class CountInventoryArgs {
7062
+ id;
7063
+ items;
7064
+ };
7065
+ tslib.__decorate([
7066
+ graphql.Field(() => graphql.ID),
7067
+ tslib.__metadata("design:type", String)
7068
+ ], CountInventoryArgs.prototype, "id", void 0);
7069
+ tslib.__decorate([
7070
+ graphql.Field(() => [CountInventoryItemInput]),
7071
+ tslib.__metadata("design:type", Array)
7072
+ ], CountInventoryArgs.prototype, "items", void 0);
7073
+ CountInventoryArgs = tslib.__decorate([
7074
+ graphql.ArgsType()
7075
+ ], CountInventoryArgs);
7076
+ let AddInventoryCountItemArgs = class AddInventoryCountItemArgs {
7077
+ id;
7078
+ materialId;
7079
+ /** An existing batch key, or a new one — the batch is created on demand. */
7080
+ batchKey;
7081
+ locationId;
7082
+ loaderId;
7083
+ countedQuantity;
7084
+ unitId;
7085
+ };
7086
+ tslib.__decorate([
7087
+ graphql.Field(() => graphql.ID),
7088
+ tslib.__metadata("design:type", String)
7089
+ ], AddInventoryCountItemArgs.prototype, "id", void 0);
7090
+ tslib.__decorate([
7091
+ graphql.Field(() => graphql.ID),
7092
+ tslib.__metadata("design:type", String)
7093
+ ], AddInventoryCountItemArgs.prototype, "materialId", void 0);
7094
+ tslib.__decorate([
7095
+ graphql.Field(() => String),
7096
+ tslib.__metadata("design:type", String)
7097
+ ], AddInventoryCountItemArgs.prototype, "batchKey", void 0);
7098
+ tslib.__decorate([
7099
+ graphql.Field(() => graphql.ID),
7100
+ tslib.__metadata("design:type", String)
7101
+ ], AddInventoryCountItemArgs.prototype, "locationId", void 0);
7102
+ tslib.__decorate([
7103
+ graphql.Field(() => graphql.ID, { nullable: true }),
7104
+ tslib.__metadata("design:type", Object)
7105
+ ], AddInventoryCountItemArgs.prototype, "loaderId", void 0);
7106
+ tslib.__decorate([
7107
+ graphql.Field(() => graphql.Float),
7108
+ tslib.__metadata("design:type", Number)
7109
+ ], AddInventoryCountItemArgs.prototype, "countedQuantity", void 0);
7110
+ tslib.__decorate([
7111
+ graphql.Field(() => graphql.ID, { nullable: true }),
7112
+ tslib.__metadata("design:type", Object)
7113
+ ], AddInventoryCountItemArgs.prototype, "unitId", void 0);
7114
+ AddInventoryCountItemArgs = tslib.__decorate([
7115
+ graphql.ArgsType()
7116
+ ], AddInventoryCountItemArgs);
7117
+ let RemoveInventoryCountItemArgs = class RemoveInventoryCountItemArgs {
7118
+ id;
7119
+ itemId;
7120
+ };
7121
+ tslib.__decorate([
7122
+ graphql.Field(() => graphql.ID),
7123
+ tslib.__metadata("design:type", String)
7124
+ ], RemoveInventoryCountItemArgs.prototype, "id", void 0);
7125
+ tslib.__decorate([
7126
+ graphql.Field(() => graphql.ID),
7127
+ tslib.__metadata("design:type", String)
7128
+ ], RemoveInventoryCountItemArgs.prototype, "itemId", void 0);
7129
+ RemoveInventoryCountItemArgs = tslib.__decorate([
7130
+ graphql.ArgsType()
7131
+ ], RemoveInventoryCountItemArgs);
7132
+ let InventoryCountOrderIdArgs = class InventoryCountOrderIdArgs {
7133
+ id;
7134
+ };
7135
+ tslib.__decorate([
7136
+ graphql.Field(() => graphql.ID),
7137
+ tslib.__metadata("design:type", String)
7138
+ ], InventoryCountOrderIdArgs.prototype, "id", void 0);
7139
+ InventoryCountOrderIdArgs = tslib.__decorate([
7140
+ graphql.ArgsType()
7141
+ ], InventoryCountOrderIdArgs);
7142
+
7143
+ let InventoryCountOrderQuery = class InventoryCountOrderQuery {
7144
+ inventoryCountOrderService;
7145
+ constructor(inventoryCountOrderService) {
7146
+ this.inventoryCountOrderService = inventoryCountOrderService;
7147
+ }
7148
+ async inventoryCountOrders(args) {
7149
+ const [items, total] = await this.inventoryCountOrderService.findMany(args);
7150
+ return { items, total };
7151
+ }
7152
+ async inventoryCountOrder({ id }) {
7153
+ return this.inventoryCountOrderService.findOne(id);
7154
+ }
7155
+ };
7156
+ tslib.__decorate([
7157
+ graphql.Query(() => InventoryCountOrders),
7158
+ WmsOperation({ resource: 'inventory-count-order', action: 'read' }),
7159
+ tslib.__param(0, graphql.Args()),
7160
+ tslib.__metadata("design:type", Function),
7161
+ tslib.__metadata("design:paramtypes", [FindInventoryCountOrderArgs]),
7162
+ tslib.__metadata("design:returntype", Promise)
7163
+ ], InventoryCountOrderQuery.prototype, "inventoryCountOrders", null);
7164
+ tslib.__decorate([
7165
+ graphql.Query(() => InventoryCountOrderDto),
7166
+ WmsOperation({ resource: 'inventory-count-order', action: 'read' }),
7167
+ tslib.__param(0, graphql.Args()),
7168
+ tslib.__metadata("design:type", Function),
7169
+ tslib.__metadata("design:paramtypes", [InventoryCountOrderIdArgs]),
7170
+ tslib.__metadata("design:returntype", Promise)
7171
+ ], InventoryCountOrderQuery.prototype, "inventoryCountOrder", null);
7172
+ InventoryCountOrderQuery = tslib.__decorate([
7173
+ common.Injectable(),
7174
+ tslib.__metadata("design:paramtypes", [wmsModuleCore.InventoryCountOrderService])
7175
+ ], InventoryCountOrderQuery);
7176
+
7177
+ let InventoryCountOrderMutation = class InventoryCountOrderMutation {
7178
+ inventoryCountOrderService;
7179
+ constructor(inventoryCountOrderService) {
7180
+ this.inventoryCountOrderService = inventoryCountOrderService;
7181
+ }
7182
+ async createInventoryCountOrder(args) {
7183
+ return this.inventoryCountOrderService.create(args);
7184
+ }
7185
+ async updateInventoryCountOrder({ id, ...input }) {
7186
+ return this.inventoryCountOrderService.update(id, input);
7187
+ }
7188
+ async startInventoryCount({ id }) {
7189
+ return this.inventoryCountOrderService.start(id);
7190
+ }
7191
+ /** "暫存結果" — record what was counted without touching stock. */
7192
+ async countInventory({ id, items }) {
7193
+ return this.inventoryCountOrderService.count(id, items.map((item) => ({
7194
+ itemId: item.itemId,
7195
+ countedQuantity: item.countedQuantity ?? null,
7196
+ unitId: item.unitId,
7197
+ })));
7198
+ }
7199
+ async addInventoryCountItem({ id, ...input }) {
7200
+ return this.inventoryCountOrderService.addItem(id, input);
7201
+ }
7202
+ async removeInventoryCountItem({ id, itemId }) {
7203
+ return this.inventoryCountOrderService.removeItem(id, itemId);
7204
+ }
7205
+ /** "清空重填" — discard the counting, keep the lock and the status. */
7206
+ async resetInventoryCount({ id }) {
7207
+ return this.inventoryCountOrderService.reset(id);
7208
+ }
7209
+ async cancelInventoryCount({ id }) {
7210
+ return this.inventoryCountOrderService.cancel(id);
7211
+ }
7212
+ /** "執行盤差" — the only mutation here that changes stock. */
7213
+ async settleInventoryCount({ id }) {
7214
+ return this.inventoryCountOrderService.settle(id);
7215
+ }
7216
+ };
7217
+ tslib.__decorate([
7218
+ graphql.Mutation(() => InventoryCountOrderDto),
7219
+ WmsOperation({ resource: 'inventory-count-order', action: 'create' }),
7220
+ WmsMutationEvent({ event: 'inventory-count-order.created' }),
7221
+ tslib.__param(0, graphql.Args()),
7222
+ tslib.__metadata("design:type", Function),
7223
+ tslib.__metadata("design:paramtypes", [CreateInventoryCountOrderArgs]),
7224
+ tslib.__metadata("design:returntype", Promise)
7225
+ ], InventoryCountOrderMutation.prototype, "createInventoryCountOrder", null);
7226
+ tslib.__decorate([
7227
+ graphql.Mutation(() => InventoryCountOrderDto),
7228
+ WmsOperation({ resource: 'inventory-count-order', action: 'update' }),
7229
+ WmsMutationEvent({ event: 'inventory-count-order.updated' }),
7230
+ tslib.__param(0, graphql.Args()),
7231
+ tslib.__metadata("design:type", Function),
7232
+ tslib.__metadata("design:paramtypes", [UpdateInventoryCountOrderArgs]),
7233
+ tslib.__metadata("design:returntype", Promise)
7234
+ ], InventoryCountOrderMutation.prototype, "updateInventoryCountOrder", null);
7235
+ tslib.__decorate([
7236
+ graphql.Mutation(() => InventoryCountOrderDto),
7237
+ WmsOperation({ resource: 'inventory-count-order', action: 'start' }),
7238
+ WmsMutationEvent({ event: 'inventory-count-order.started' }),
7239
+ tslib.__param(0, graphql.Args()),
7240
+ tslib.__metadata("design:type", Function),
7241
+ tslib.__metadata("design:paramtypes", [InventoryCountOrderIdArgs]),
7242
+ tslib.__metadata("design:returntype", Promise)
7243
+ ], InventoryCountOrderMutation.prototype, "startInventoryCount", null);
7244
+ tslib.__decorate([
7245
+ graphql.Mutation(() => InventoryCountOrderDto),
7246
+ WmsOperation({ resource: 'inventory-count-order', action: 'count' }),
7247
+ WmsMutationEvent({ event: 'inventory-count-order.counted' }),
7248
+ tslib.__param(0, graphql.Args()),
7249
+ tslib.__metadata("design:type", Function),
7250
+ tslib.__metadata("design:paramtypes", [CountInventoryArgs]),
7251
+ tslib.__metadata("design:returntype", Promise)
7252
+ ], InventoryCountOrderMutation.prototype, "countInventory", null);
7253
+ tslib.__decorate([
7254
+ graphql.Mutation(() => InventoryCountOrderItemDto),
7255
+ WmsOperation({ resource: 'inventory-count-order', action: 'add-item' }),
7256
+ WmsMutationEvent({ event: 'inventory-count-order.updated' }),
7257
+ tslib.__param(0, graphql.Args()),
7258
+ tslib.__metadata("design:type", Function),
7259
+ tslib.__metadata("design:paramtypes", [AddInventoryCountItemArgs]),
7260
+ tslib.__metadata("design:returntype", Promise)
7261
+ ], InventoryCountOrderMutation.prototype, "addInventoryCountItem", null);
7262
+ tslib.__decorate([
7263
+ graphql.Mutation(() => InventoryCountOrderDto),
7264
+ WmsOperation({ resource: 'inventory-count-order', action: 'remove-item' }),
7265
+ WmsMutationEvent({ event: 'inventory-count-order.updated' }),
7266
+ tslib.__param(0, graphql.Args()),
7267
+ tslib.__metadata("design:type", Function),
7268
+ tslib.__metadata("design:paramtypes", [RemoveInventoryCountItemArgs]),
7269
+ tslib.__metadata("design:returntype", Promise)
7270
+ ], InventoryCountOrderMutation.prototype, "removeInventoryCountItem", null);
7271
+ tslib.__decorate([
7272
+ graphql.Mutation(() => InventoryCountOrderDto),
7273
+ WmsOperation({ resource: 'inventory-count-order', action: 'reset' }),
7274
+ WmsMutationEvent({ event: 'inventory-count-order.reset' }),
7275
+ tslib.__param(0, graphql.Args()),
7276
+ tslib.__metadata("design:type", Function),
7277
+ tslib.__metadata("design:paramtypes", [InventoryCountOrderIdArgs]),
7278
+ tslib.__metadata("design:returntype", Promise)
7279
+ ], InventoryCountOrderMutation.prototype, "resetInventoryCount", null);
7280
+ tslib.__decorate([
7281
+ graphql.Mutation(() => InventoryCountOrderDto),
7282
+ WmsOperation({ resource: 'inventory-count-order', action: 'cancel' }),
7283
+ WmsMutationEvent({ event: 'inventory-count-order.cancelled' }),
7284
+ tslib.__param(0, graphql.Args()),
7285
+ tslib.__metadata("design:type", Function),
7286
+ tslib.__metadata("design:paramtypes", [InventoryCountOrderIdArgs]),
7287
+ tslib.__metadata("design:returntype", Promise)
7288
+ ], InventoryCountOrderMutation.prototype, "cancelInventoryCount", null);
7289
+ tslib.__decorate([
7290
+ graphql.Mutation(() => InventoryCountOrderDto),
7291
+ WmsOperation({ resource: 'inventory-count-order', action: 'settle' }),
7292
+ WmsMutationEvent({ event: 'inventory-count-order.settled' }),
7293
+ tslib.__param(0, graphql.Args()),
7294
+ tslib.__metadata("design:type", Function),
7295
+ tslib.__metadata("design:paramtypes", [InventoryCountOrderIdArgs]),
7296
+ tslib.__metadata("design:returntype", Promise)
7297
+ ], InventoryCountOrderMutation.prototype, "settleInventoryCount", null);
7298
+ InventoryCountOrderMutation = tslib.__decorate([
7299
+ common.Injectable(),
7300
+ tslib.__metadata("design:paramtypes", [wmsModuleCore.InventoryCountOrderService])
7301
+ ], InventoryCountOrderMutation);
7302
+
7303
+ let InventoryCountOrderResolver = class InventoryCountOrderResolver {
7304
+ entities;
7305
+ constructor(entities) {
7306
+ this.entities = entities;
7307
+ }
7308
+ items({ id }, { loaders }) {
7309
+ return loaders.batchMany.load({
7310
+ __entity: wmsModuleCore.InventoryCountOrderItemEntityClass,
7311
+ __from: { orderId: id },
7312
+ });
7313
+ }
7314
+ /**
7315
+ * The locations the user picked.
7316
+ *
7317
+ * Only the roots: the scope table also holds every descendant the backend
7318
+ * expanded into, and listing a whole aisle's shelves as chips would bury the
7319
+ * one thing the operator actually chose. The expansion still exists in the
7320
+ * database — it is what the lock reads — it just is not this field.
7321
+ */
7322
+ async locations({ id }, { loaders }) {
7323
+ const scope = (await loaders.batchMany.load({
7324
+ __entity: wmsModuleCore.InventoryCountOrderLocationEntityClass,
7325
+ __from: { orderId: id },
7326
+ }));
7327
+ // The join rows carry `locationId`, not a loaded `location` relation, so
7328
+ // each one has to go back through the location DataLoader. Returning
7329
+ // `row.location` directly yields `undefined`, and the non-nullable list then
7330
+ // fails the whole query with "Cannot return null for non-nullable field".
7331
+ return Promise.all(scope
7332
+ .filter(({ isRoot }) => isRoot)
7333
+ .map(({ locationId }) => loaders.batchSingle.load({
7334
+ __entity: this.entities.location,
7335
+ __from: { id: locationId },
7336
+ })));
7337
+ }
7338
+ };
7339
+ tslib.__decorate([
7340
+ graphql.ResolveField(() => [InventoryCountOrderItemDto]),
7341
+ tslib.__param(0, graphql.Parent()),
7342
+ tslib.__param(1, graphql.Context()),
7343
+ tslib.__metadata("design:type", Function),
7344
+ tslib.__metadata("design:paramtypes", [InventoryCountOrderDto, Object]),
7345
+ tslib.__metadata("design:returntype", Promise)
7346
+ ], InventoryCountOrderResolver.prototype, "items", null);
7347
+ tslib.__decorate([
7348
+ graphql.ResolveField(() => [LocationDto]),
7349
+ tslib.__param(0, graphql.Parent()),
7350
+ tslib.__param(1, graphql.Context()),
7351
+ tslib.__metadata("design:type", Function),
7352
+ tslib.__metadata("design:paramtypes", [InventoryCountOrderDto, Object]),
7353
+ tslib.__metadata("design:returntype", Promise)
7354
+ ], InventoryCountOrderResolver.prototype, "locations", null);
7355
+ InventoryCountOrderResolver = tslib.__decorate([
7356
+ graphql.Resolver(() => InventoryCountOrderDto),
7357
+ tslib.__metadata("design:paramtypes", [wmsModuleCore.WmsEntities])
7358
+ ], InventoryCountOrderResolver);
7359
+ let InventoryCountOrderItemResolver = class InventoryCountOrderItemResolver {
7360
+ entities;
7361
+ /**
7362
+ * The configured entities, not the built-in classes: `__entity` decides which
7363
+ * repository the DataLoader opens, so it has to follow whatever the consumer
7364
+ * passed to `WMSBaseModuleOptions`.
7365
+ */
7366
+ constructor(entities) {
7367
+ this.entities = entities;
7368
+ }
7369
+ material({ materialId }, { loaders }) {
7370
+ return loaders.batchSingle.load({
7371
+ __entity: this.entities.material,
7372
+ __from: { id: materialId },
7373
+ });
7374
+ }
7375
+ async batch({ batchId }, { loaders }) {
7376
+ const { groupId } = await loaders.batchSingle.load({
7377
+ __entity: this.entities.batch,
7378
+ __from: { id: batchId },
7379
+ });
7380
+ return loaders.batchSingle.load({
7381
+ __entity: wmsModuleCore.BatchGroupEntityClass,
7382
+ __from: { id: groupId },
7383
+ });
7384
+ }
7385
+ location({ locationId }, { loaders }) {
7386
+ if (!locationId) {
7387
+ return null;
7388
+ }
7389
+ return loaders.batchSingle.load({
7390
+ __entity: this.entities.location,
7391
+ __from: { id: locationId },
7392
+ });
7393
+ }
7394
+ loader({ loaderId }, { loaders }) {
7395
+ if (!loaderId) {
7396
+ return null;
7397
+ }
7398
+ return loaders.batchSingle.load({
7399
+ __entity: wmsModuleCore.LoadersEntityClass,
7400
+ __from: { id: loaderId },
7401
+ });
7402
+ }
7403
+ };
7404
+ tslib.__decorate([
7405
+ graphql.ResolveField(() => MaterialDto),
7406
+ tslib.__param(0, graphql.Parent()),
7407
+ tslib.__param(1, graphql.Context()),
7408
+ tslib.__metadata("design:type", Function),
7409
+ tslib.__metadata("design:paramtypes", [InventoryCountOrderItemDto, Object]),
7410
+ tslib.__metadata("design:returntype", Promise)
7411
+ ], InventoryCountOrderItemResolver.prototype, "material", null);
7412
+ tslib.__decorate([
7413
+ graphql.ResolveField(() => BatchDto),
7414
+ tslib.__param(0, graphql.Parent()),
7415
+ tslib.__param(1, graphql.Context()),
7416
+ tslib.__metadata("design:type", Function),
7417
+ tslib.__metadata("design:paramtypes", [InventoryCountOrderItemDto, Object]),
7418
+ tslib.__metadata("design:returntype", Promise)
7419
+ ], InventoryCountOrderItemResolver.prototype, "batch", null);
7420
+ tslib.__decorate([
7421
+ graphql.ResolveField(() => LocationDto, { nullable: true }),
7422
+ tslib.__param(0, graphql.Parent()),
7423
+ tslib.__param(1, graphql.Context()),
7424
+ tslib.__metadata("design:type", Function),
7425
+ tslib.__metadata("design:paramtypes", [InventoryCountOrderItemDto, Object]),
7426
+ tslib.__metadata("design:returntype", Object)
7427
+ ], InventoryCountOrderItemResolver.prototype, "location", null);
7428
+ tslib.__decorate([
7429
+ graphql.ResolveField(() => LoaderDto, { nullable: true }),
7430
+ tslib.__param(0, graphql.Parent()),
7431
+ tslib.__param(1, graphql.Context()),
7432
+ tslib.__metadata("design:type", Function),
7433
+ tslib.__metadata("design:paramtypes", [InventoryCountOrderItemDto, Object]),
7434
+ tslib.__metadata("design:returntype", Object)
7435
+ ], InventoryCountOrderItemResolver.prototype, "loader", null);
7436
+ InventoryCountOrderItemResolver = tslib.__decorate([
7437
+ graphql.Resolver(() => InventoryCountOrderItemDto),
7438
+ tslib.__metadata("design:paramtypes", [wmsModuleCore.WmsEntities])
7439
+ ], InventoryCountOrderItemResolver);
7440
+
6681
7441
  var WmsModuleGraphqlModule_1;
6682
7442
  const exportDependencies = [
6683
7443
  UnitQuery,
@@ -6732,10 +7492,23 @@ const exportDependencies = [
6732
7492
  QualityInspectionOrderMutation,
6733
7493
  WarehouseMapDataQuery,
6734
7494
  MapRangeUnionResolver,
7495
+ InventoryCountOrderQuery,
7496
+ InventoryCountOrderMutation,
7497
+ InventoryCountOrderResolver,
7498
+ InventoryCountOrderItemResolver,
6735
7499
  ];
6736
7500
  exports.WmsModuleGraphqlModule = WmsModuleGraphqlModule_1 = class WmsModuleGraphqlModule {
6737
7501
  static forRootAsync(options) {
6738
- const { authChecker, beforeHooks, afterListeners, actorExtractor, eventEmitterBridge, ...coreOptions } = options;
7502
+ const { authChecker, beforeHooks, afterListeners, actorExtractor, eventEmitterBridge, enabledOperations, disabledOperations, disabledFields, ...coreOptions } = options;
7503
+ // Must run before `GraphQLModule` builds the schema. `forRootAsync` is
7504
+ // called while `AppModule` is still being defined, so this is the earliest
7505
+ // point at which the deployment's switches are known — and it is early
7506
+ // enough: the schema is not built until the app bootstraps.
7507
+ pruneDisabledOperations(exportDependencies, {
7508
+ enabledOperations,
7509
+ disabledOperations,
7510
+ disabledFields,
7511
+ });
6739
7512
  // coreOptions still carries `enrichStockEvents`, forwarded to the core module.
6740
7513
  const coreModule = wmsModuleCore.WmsModuleCoreModule.forRootAsync(coreOptions);
6741
7514
  const authOptions = { authChecker };
@@ -6770,6 +7543,10 @@ exports.WmsModuleGraphqlModule = WmsModuleGraphqlModule_1 = tslib.__decorate([
6770
7543
  })
6771
7544
  ], exports.WmsModuleGraphqlModule);
6772
7545
 
7546
+ Object.defineProperty(exports, "WMS_OPERATION_NAMES", {
7547
+ enumerable: true,
7548
+ get: function () { return wmsModuleCore.WMS_OPERATION_NAMES; }
7549
+ });
6773
7550
  exports.HOST_SKIP_METADATA_KEY = HOST_SKIP_METADATA_KEY;
6774
7551
  exports.WMS_AUTH_OPTIONS = WMS_AUTH_OPTIONS;
6775
7552
  exports.WMS_MUTATION_EVENT_METADATA = WMS_MUTATION_EVENT_METADATA;
@@ -6777,3 +7554,4 @@ exports.WMS_OPERATION_METADATA = WMS_OPERATION_METADATA;
6777
7554
  exports.WmsMutationEvent = WmsMutationEvent;
6778
7555
  exports.WmsOperation = WmsOperation;
6779
7556
  exports.createWmsLoaders = createWmsLoaders;
7557
+ exports.pruneDisabledOperations = pruneDisabledOperations;