@rytass/wms-module-graphql 0.6.0 → 0.7.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.
- package/README.md +16 -0
- package/docs/api-reference.md +6 -0
- package/index.cjs.js +185 -20
- package/lib/helpers/loader.service.d.ts +30 -2
- package/lib/helpers/loader.service.js +64 -2
- package/lib/resolvers/aggregated-stock.resolver.d.ts +10 -1
- package/lib/resolvers/aggregated-stock.resolver.js +16 -4
- package/lib/resolvers/change-log.resolver.d.ts +9 -0
- package/lib/resolvers/change-log.resolver.js +17 -3
- package/lib/resolvers/location.resolver.d.ts +10 -1
- package/lib/resolvers/location.resolver.js +18 -4
- package/lib/resolvers/receive-inventory-order.resolver.d.ts +9 -0
- package/lib/resolvers/receive-inventory-order.resolver.js +17 -3
- package/lib/resolvers/ship-inventory-order.resolver.d.ts +18 -0
- package/lib/resolvers/ship-inventory-order.resolver.js +32 -5
- package/lib/resolvers/stock.resolver.d.ts +9 -0
- package/lib/resolvers/stock.resolver.js +17 -3
- package/lib/resolvers/transfer-order.resolver.d.ts +9 -0
- package/lib/resolvers/transfer-order.resolver.js +17 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -62,6 +62,22 @@ You register a **single** `GraphQLModule.forRootAsync(...)` of your own, mix you
|
|
|
62
62
|
|
|
63
63
|
`WmsModuleGraphqlModule` internally wires `WmsModuleCoreModule.forRootAsync` so you do not need to import the core module separately when using this package.
|
|
64
64
|
|
|
65
|
+
## Custom material entity
|
|
66
|
+
|
|
67
|
+
`materialEntity` is an ordinary `WMSBaseModuleOptions` field that reaches all the way down, so a downstream project's own item master can *be* the WMS material master — every resolver's `material` DataLoader resolves against it too:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
WmsModuleGraphqlModule.forRootAsync({
|
|
71
|
+
// a @ChildEntity() of MaterialEntityClass
|
|
72
|
+
useFactory: async () => ({ materialEntity: ItemMasterEntity }),
|
|
73
|
+
defaultLoaderSerialId: 'DEFAULT',
|
|
74
|
+
defaultLoaderTypeKey: 'DEFAULT',
|
|
75
|
+
defaultLocationKey: 'DEFAULT',
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Register the entity with TypeORM yourself (`TypeOrmModule.forFeature([ItemMasterEntity])`); the module checks at startup and refuses to boot if it is missing. Requires `@rytass/wms-base-nestjs-module` >= 0.3.0. See [`@rytass/wms-module-core`'s custom-entities guide](https://github.com/Rytass/WMS-Module/blob/main/libs/core/docs/custom-entities.md) for the single-table-inheritance caveats and which other entity options are not honoured yet.
|
|
80
|
+
|
|
65
81
|
## Authorization
|
|
66
82
|
|
|
67
83
|
Every WMS root `@Query` / `@Mutation` is annotated with `@WmsOperation({ resource, action })` — a **host-neutral** permission requirement enforced by the library's own route-level `WmsAuthGuard`, which delegates the allow/deny decision to an `authChecker` **you** supply. The library never imports your auth system; you map WMS's `resource`/`action` onto whatever you use (Casbin, RBAC, JWT scopes…).
|
package/docs/api-reference.md
CHANGED
|
@@ -311,6 +311,12 @@ static forRootAsync(
|
|
|
311
311
|
// defaultLocationKey: string — 預設儲存位置 key
|
|
312
312
|
// + WmsAuthModuleOptions:
|
|
313
313
|
// authChecker?: WmsAuthChecker — 選填;resolver 授權委派函式(見 Authorization)
|
|
314
|
+
//
|
|
315
|
+
// since 0.7.0(需 wms-base-nestjs-module >= 0.3.0):
|
|
316
|
+
// WMSBaseModuleOptions.materialEntity 會一路作用到所有 resolver 的
|
|
317
|
+
// material DataLoader。傳入 MaterialEntityClass 的 @ChildEntity() 即可,
|
|
318
|
+
// forRoot 與 async factory 皆支援;entity 需自行註冊給 TypeORM。
|
|
319
|
+
// 詳見 core 的 docs/custom-entities.md。
|
|
314
320
|
): DynamicModule
|
|
315
321
|
```
|
|
316
322
|
|
package/index.cjs.js
CHANGED
|
@@ -55,6 +55,65 @@ exports.LoaderService = class LoaderService {
|
|
|
55
55
|
const fields = ___default.default(Object.keys(__from)).sort();
|
|
56
56
|
return `${__hash}_${fields.map((field) => data[field]).join('_')}`;
|
|
57
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* resolve a `__from` property name to the physical column it is stored in.
|
|
60
|
+
*
|
|
61
|
+
* TypeORM's `FindOptionsWhere` only accepts real column properties. A
|
|
62
|
+
* `@RelationId()` property — e.g. `LocationEntityClass.parentId`, which mirrors
|
|
63
|
+
* the `parent` tree relation — is virtual and is rejected with
|
|
64
|
+
* `EntityPropertyNotFoundError`, even though it is backed by the relation's
|
|
65
|
+
* join column. Map those back to their join column so they stay batchable.
|
|
66
|
+
* @param EntityMetadata
|
|
67
|
+
* @param string
|
|
68
|
+
* @returns string | null
|
|
69
|
+
*/
|
|
70
|
+
resolveColumnName(metadata, propertyName) {
|
|
71
|
+
const column = metadata.findColumnWithPropertyName(propertyName);
|
|
72
|
+
if (column)
|
|
73
|
+
return column.databaseName;
|
|
74
|
+
const relationId = metadata.relationIds.find((candidate) => candidate.propertyName === propertyName);
|
|
75
|
+
const joinColumns = relationId?.relation.joinColumns ?? [];
|
|
76
|
+
return joinColumns.length === 1 ? joinColumns[0].databaseName : null;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* build the where clause for `__from` keys that TypeORM's find options cannot
|
|
80
|
+
* express (see {@link resolveColumnName}), by addressing the columns directly.
|
|
81
|
+
* @param SelectQueryBuilder
|
|
82
|
+
* @param EntityMetadata
|
|
83
|
+
* @param LoaderOptions[]
|
|
84
|
+
* @param (keyof T)[]
|
|
85
|
+
*/
|
|
86
|
+
applyColumnWhere(qb, metadata, options, primaryKeys) {
|
|
87
|
+
const columns = primaryKeys.map((primaryKey) => {
|
|
88
|
+
const columnName = this.resolveColumnName(metadata, String(primaryKey));
|
|
89
|
+
if (!columnName)
|
|
90
|
+
throw new Error(`Loader cannot resolve property "${String(primaryKey)}" to a column of "${metadata.name}".`);
|
|
91
|
+
return {
|
|
92
|
+
primaryKey,
|
|
93
|
+
column: `entity.${this.dataSource.driver.escape(columnName)}`,
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
if (columns.length === 1) {
|
|
97
|
+
const [{ primaryKey, column }] = columns;
|
|
98
|
+
qb.andWhere(`${column} IN (:...wmsLoaderValues)`, {
|
|
99
|
+
wmsLoaderValues: options.map(({ __from }) => __from[primaryKey]),
|
|
100
|
+
});
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
qb.andWhere(new typeorm.Brackets((where) => {
|
|
104
|
+
options.forEach(({ __from }, optionIndex) => {
|
|
105
|
+
const parameters = {};
|
|
106
|
+
const predicate = columns
|
|
107
|
+
.map(({ primaryKey, column }, columnIndex) => {
|
|
108
|
+
const parameter = `wmsLoaderValue_${optionIndex}_${columnIndex}`;
|
|
109
|
+
parameters[parameter] = __from[primaryKey];
|
|
110
|
+
return `${column} = :${parameter}`;
|
|
111
|
+
})
|
|
112
|
+
.join(' AND ');
|
|
113
|
+
where.orWhere(`(${predicate})`, parameters);
|
|
114
|
+
});
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
58
117
|
/**
|
|
59
118
|
* query data by collecting primary keys from options with same `__entity`
|
|
60
119
|
* @param LoaderOptions[]
|
|
@@ -65,7 +124,10 @@ exports.LoaderService = class LoaderService {
|
|
|
65
124
|
const repo = this.dataSource.getRepository(__entity);
|
|
66
125
|
let qb = repo.createQueryBuilder('entity');
|
|
67
126
|
const primaryKeys = Object.keys(__from);
|
|
68
|
-
|
|
127
|
+
const hasVirtualKey = primaryKeys.some((primaryKey) => !repo.metadata.findColumnWithPropertyName(String(primaryKey)));
|
|
128
|
+
if (hasVirtualKey)
|
|
129
|
+
this.applyColumnWhere(qb, repo.metadata, options, primaryKeys);
|
|
130
|
+
else if (primaryKeys.length > 1)
|
|
69
131
|
qb.setFindOptions({ where: options.map(({ __from }) => __from) });
|
|
70
132
|
else {
|
|
71
133
|
const [primaryKey] = primaryKeys;
|
|
@@ -3221,9 +3283,20 @@ Batches = tslib.__decorate([
|
|
|
3221
3283
|
], Batches);
|
|
3222
3284
|
|
|
3223
3285
|
let StockResolver = class StockResolver {
|
|
3286
|
+
materialEntity;
|
|
3287
|
+
/**
|
|
3288
|
+
* Bound to the `MaterialEntity` Symbol, so the DataLoader queries whichever
|
|
3289
|
+
* material entity the consumer configured — the built-in `MaterialEntityClass`
|
|
3290
|
+
* unless `materialEntity` was passed to `forRoot`/`forRootAsync`. Loading the
|
|
3291
|
+
* built-in class outright would filter on its single-table-inheritance
|
|
3292
|
+
* discriminator and resolve nothing for a custom entity.
|
|
3293
|
+
*/
|
|
3294
|
+
constructor(materialEntity) {
|
|
3295
|
+
this.materialEntity = materialEntity;
|
|
3296
|
+
}
|
|
3224
3297
|
material({ materialId }, { loaders }) {
|
|
3225
3298
|
return loaders.batchSingle.load({
|
|
3226
|
-
__entity:
|
|
3299
|
+
__entity: this.materialEntity,
|
|
3227
3300
|
__from: { id: materialId },
|
|
3228
3301
|
});
|
|
3229
3302
|
}
|
|
@@ -3269,7 +3342,9 @@ tslib.__decorate([
|
|
|
3269
3342
|
tslib.__metadata("design:returntype", Promise)
|
|
3270
3343
|
], StockResolver.prototype, "batch", null);
|
|
3271
3344
|
StockResolver = tslib.__decorate([
|
|
3272
|
-
graphql.Resolver(() => StockDto)
|
|
3345
|
+
graphql.Resolver(() => StockDto),
|
|
3346
|
+
tslib.__param(0, common.Inject(wmsModuleCore.MaterialEntity)),
|
|
3347
|
+
tslib.__metadata("design:paramtypes", [Function])
|
|
3273
3348
|
], StockResolver);
|
|
3274
3349
|
|
|
3275
3350
|
var MapRangeType;
|
|
@@ -3611,8 +3686,21 @@ let LocationResolver = class LocationResolver {
|
|
|
3611
3686
|
__from: { id: parentId },
|
|
3612
3687
|
});
|
|
3613
3688
|
}
|
|
3614
|
-
|
|
3615
|
-
|
|
3689
|
+
/**
|
|
3690
|
+
* `children` must never be read off the parent entity: only
|
|
3691
|
+
* `LocationQuery.location` and `LocationService.findMany` eager-load the tree
|
|
3692
|
+
* relation. Every other producer of a `LocationDto` (stock/loader/change-log/
|
|
3693
|
+
* transfer/ship/receive/warehouse-map resolvers, the `parent` field above and
|
|
3694
|
+
* the create/update mutations) hands back an entity whose `children` is
|
|
3695
|
+
* `undefined`, which breaks the non-nullable list. Always resolve through the
|
|
3696
|
+
* request-scoped loader instead.
|
|
3697
|
+
*/
|
|
3698
|
+
children({ id }, { loaders }) {
|
|
3699
|
+
return loaders.batchMany.load({
|
|
3700
|
+
__entity: wmsModuleCore.LocationEntityClass,
|
|
3701
|
+
__from: { parentId: id },
|
|
3702
|
+
__conditions: (qb) => qb.orderBy('entity."key"', 'ASC'),
|
|
3703
|
+
});
|
|
3616
3704
|
}
|
|
3617
3705
|
};
|
|
3618
3706
|
tslib.__decorate([
|
|
@@ -3634,9 +3722,10 @@ tslib.__decorate([
|
|
|
3634
3722
|
tslib.__decorate([
|
|
3635
3723
|
graphql.ResolveField(() => [LocationDto]),
|
|
3636
3724
|
tslib.__param(0, graphql.Parent()),
|
|
3725
|
+
tslib.__param(1, graphql.Context()),
|
|
3637
3726
|
tslib.__metadata("design:type", Function),
|
|
3638
|
-
tslib.__metadata("design:paramtypes", [wmsModuleCore.LocationEntityClass]),
|
|
3639
|
-
tslib.__metadata("design:returntype",
|
|
3727
|
+
tslib.__metadata("design:paramtypes", [wmsModuleCore.LocationEntityClass, Object]),
|
|
3728
|
+
tslib.__metadata("design:returntype", Promise)
|
|
3640
3729
|
], LocationResolver.prototype, "children", null);
|
|
3641
3730
|
LocationResolver = tslib.__decorate([
|
|
3642
3731
|
graphql.Resolver(() => LocationDto)
|
|
@@ -3829,15 +3918,25 @@ UnitQuery = tslib.__decorate([
|
|
|
3829
3918
|
|
|
3830
3919
|
let AggregatedStockResolver = class AggregatedStockResolver {
|
|
3831
3920
|
stockService;
|
|
3832
|
-
|
|
3921
|
+
materialEntity;
|
|
3922
|
+
/**
|
|
3923
|
+
* `materialEntity` is bound to the `MaterialEntity` Symbol, so the DataLoader
|
|
3924
|
+
* queries whichever material entity the consumer configured — the built-in
|
|
3925
|
+
* `MaterialEntityClass` unless `materialEntity` was passed to
|
|
3926
|
+
* `forRoot`/`forRootAsync`. Loading the built-in class outright would filter on
|
|
3927
|
+
* its single-table-inheritance discriminator and resolve nothing for a custom
|
|
3928
|
+
* entity.
|
|
3929
|
+
*/
|
|
3930
|
+
constructor(stockService, materialEntity) {
|
|
3833
3931
|
this.stockService = stockService;
|
|
3932
|
+
this.materialEntity = materialEntity;
|
|
3834
3933
|
}
|
|
3835
3934
|
async id(stock) {
|
|
3836
3935
|
return this.stockService.generatedAggregateKey(stock);
|
|
3837
3936
|
}
|
|
3838
3937
|
async material({ materialId }, { loaders }) {
|
|
3839
3938
|
return loaders.batchSingle.load({
|
|
3840
|
-
__entity:
|
|
3939
|
+
__entity: this.materialEntity,
|
|
3841
3940
|
__from: { id: materialId },
|
|
3842
3941
|
});
|
|
3843
3942
|
}
|
|
@@ -3905,7 +4004,8 @@ tslib.__decorate([
|
|
|
3905
4004
|
], AggregatedStockResolver.prototype, "loader", null);
|
|
3906
4005
|
AggregatedStockResolver = tslib.__decorate([
|
|
3907
4006
|
graphql.Resolver(() => AggregatedStockDto),
|
|
3908
|
-
tslib.
|
|
4007
|
+
tslib.__param(1, common.Inject(wmsModuleCore.MaterialEntity)),
|
|
4008
|
+
tslib.__metadata("design:paramtypes", [wmsModuleCore.StockService, Function])
|
|
3909
4009
|
], AggregatedStockResolver);
|
|
3910
4010
|
|
|
3911
4011
|
let CreateTransferOrderItemArgs = class CreateTransferOrderItemArgs {
|
|
@@ -4291,9 +4391,20 @@ TransferOrderResolver = tslib.__decorate([
|
|
|
4291
4391
|
graphql.Resolver(() => TransferOrderDto)
|
|
4292
4392
|
], TransferOrderResolver);
|
|
4293
4393
|
let TransferOrderItemResolver = class TransferOrderItemResolver {
|
|
4394
|
+
materialEntity;
|
|
4395
|
+
/**
|
|
4396
|
+
* Bound to the `MaterialEntity` Symbol, so the DataLoader queries whichever
|
|
4397
|
+
* material entity the consumer configured — the built-in `MaterialEntityClass`
|
|
4398
|
+
* unless `materialEntity` was passed to `forRoot`/`forRootAsync`. Loading the
|
|
4399
|
+
* built-in class outright would filter on its single-table-inheritance
|
|
4400
|
+
* discriminator and resolve nothing for a custom entity.
|
|
4401
|
+
*/
|
|
4402
|
+
constructor(materialEntity) {
|
|
4403
|
+
this.materialEntity = materialEntity;
|
|
4404
|
+
}
|
|
4294
4405
|
material({ materialId }, { loaders }) {
|
|
4295
4406
|
return loaders.batchSingle.load({
|
|
4296
|
-
__entity:
|
|
4407
|
+
__entity: this.materialEntity,
|
|
4297
4408
|
__from: { id: materialId },
|
|
4298
4409
|
});
|
|
4299
4410
|
}
|
|
@@ -4413,7 +4524,9 @@ tslib.__decorate([
|
|
|
4413
4524
|
tslib.__metadata("design:returntype", Promise)
|
|
4414
4525
|
], TransferOrderItemResolver.prototype, "transferredQuantity", null);
|
|
4415
4526
|
TransferOrderItemResolver = tslib.__decorate([
|
|
4416
|
-
graphql.Resolver(() => TransferOrderItemDto)
|
|
4527
|
+
graphql.Resolver(() => TransferOrderItemDto),
|
|
4528
|
+
tslib.__param(0, common.Inject(wmsModuleCore.MaterialEntity)),
|
|
4529
|
+
tslib.__metadata("design:paramtypes", [Function])
|
|
4417
4530
|
], TransferOrderItemResolver);
|
|
4418
4531
|
|
|
4419
4532
|
let CreateHoldInventoryOrderItemArgs = class CreateHoldInventoryOrderItemArgs {
|
|
@@ -4709,9 +4822,20 @@ BatchQuery = tslib.__decorate([
|
|
|
4709
4822
|
], BatchQuery);
|
|
4710
4823
|
|
|
4711
4824
|
let ChangeLogResolver = class ChangeLogResolver {
|
|
4825
|
+
materialEntity;
|
|
4826
|
+
/**
|
|
4827
|
+
* Bound to the `MaterialEntity` Symbol, so the DataLoader queries whichever
|
|
4828
|
+
* material entity the consumer configured — the built-in `MaterialEntityClass`
|
|
4829
|
+
* unless `materialEntity` was passed to `forRoot`/`forRootAsync`. Loading the
|
|
4830
|
+
* built-in class outright would filter on its single-table-inheritance
|
|
4831
|
+
* discriminator and resolve nothing for a custom entity.
|
|
4832
|
+
*/
|
|
4833
|
+
constructor(materialEntity) {
|
|
4834
|
+
this.materialEntity = materialEntity;
|
|
4835
|
+
}
|
|
4712
4836
|
material({ materialId }, { loaders }) {
|
|
4713
4837
|
return loaders.batchSingle.load({
|
|
4714
|
-
__entity:
|
|
4838
|
+
__entity: this.materialEntity,
|
|
4715
4839
|
__from: { id: materialId },
|
|
4716
4840
|
});
|
|
4717
4841
|
}
|
|
@@ -4757,7 +4881,9 @@ tslib.__decorate([
|
|
|
4757
4881
|
tslib.__metadata("design:returntype", Promise)
|
|
4758
4882
|
], ChangeLogResolver.prototype, "batch", null);
|
|
4759
4883
|
ChangeLogResolver = tslib.__decorate([
|
|
4760
|
-
graphql.Resolver(() => ChangeLogDto)
|
|
4884
|
+
graphql.Resolver(() => ChangeLogDto),
|
|
4885
|
+
tslib.__param(0, common.Inject(wmsModuleCore.MaterialEntity)),
|
|
4886
|
+
tslib.__metadata("design:paramtypes", [Function])
|
|
4761
4887
|
], ChangeLogResolver);
|
|
4762
4888
|
|
|
4763
4889
|
let ReceiveInventoryOrderResolver = class ReceiveInventoryOrderResolver {
|
|
@@ -4781,9 +4907,20 @@ ReceiveInventoryOrderResolver = tslib.__decorate([
|
|
|
4781
4907
|
graphql.Resolver(() => ReceiveInventoryOrderDto)
|
|
4782
4908
|
], ReceiveInventoryOrderResolver);
|
|
4783
4909
|
let ReceiveInventoryOrderItemResolver = class ReceiveInventoryOrderItemResolver {
|
|
4910
|
+
materialEntity;
|
|
4911
|
+
/**
|
|
4912
|
+
* Bound to the `MaterialEntity` Symbol, so the DataLoader queries whichever
|
|
4913
|
+
* material entity the consumer configured — the built-in `MaterialEntityClass`
|
|
4914
|
+
* unless `materialEntity` was passed to `forRoot`/`forRootAsync`. Loading the
|
|
4915
|
+
* built-in class outright would filter on its single-table-inheritance
|
|
4916
|
+
* discriminator and resolve nothing for a custom entity.
|
|
4917
|
+
*/
|
|
4918
|
+
constructor(materialEntity) {
|
|
4919
|
+
this.materialEntity = materialEntity;
|
|
4920
|
+
}
|
|
4784
4921
|
material({ materialId }, { loaders }) {
|
|
4785
4922
|
return loaders.batchSingle.load({
|
|
4786
|
-
__entity:
|
|
4923
|
+
__entity: this.materialEntity,
|
|
4787
4924
|
__from: { id: materialId },
|
|
4788
4925
|
});
|
|
4789
4926
|
}
|
|
@@ -4866,7 +5003,9 @@ tslib.__decorate([
|
|
|
4866
5003
|
tslib.__metadata("design:returntype", Promise)
|
|
4867
5004
|
], ReceiveInventoryOrderItemResolver.prototype, "receivedQuantity", null);
|
|
4868
5005
|
ReceiveInventoryOrderItemResolver = tslib.__decorate([
|
|
4869
|
-
graphql.Resolver(() => ReceiveInventoryOrderItemDto)
|
|
5006
|
+
graphql.Resolver(() => ReceiveInventoryOrderItemDto),
|
|
5007
|
+
tslib.__param(0, common.Inject(wmsModuleCore.MaterialEntity)),
|
|
5008
|
+
tslib.__metadata("design:paramtypes", [Function])
|
|
4870
5009
|
], ReceiveInventoryOrderItemResolver);
|
|
4871
5010
|
|
|
4872
5011
|
let FindAllocateInventoryOrderArgs = class FindAllocateInventoryOrderArgs extends PaginationArgs {
|
|
@@ -5203,9 +5342,20 @@ ShipInventoryOrderResolver = tslib.__decorate([
|
|
|
5203
5342
|
graphql.Resolver(() => ShipInventoryOrderDto)
|
|
5204
5343
|
], ShipInventoryOrderResolver);
|
|
5205
5344
|
let ShipInventoryOrderItemResolver = class ShipInventoryOrderItemResolver {
|
|
5345
|
+
materialEntity;
|
|
5346
|
+
/**
|
|
5347
|
+
* Bound to the `MaterialEntity` Symbol, so the DataLoader queries whichever
|
|
5348
|
+
* material entity the consumer configured — the built-in `MaterialEntityClass`
|
|
5349
|
+
* unless `materialEntity` was passed to `forRoot`/`forRootAsync`. Loading the
|
|
5350
|
+
* built-in class outright would filter on its single-table-inheritance
|
|
5351
|
+
* discriminator and resolve nothing for a custom entity.
|
|
5352
|
+
*/
|
|
5353
|
+
constructor(materialEntity) {
|
|
5354
|
+
this.materialEntity = materialEntity;
|
|
5355
|
+
}
|
|
5206
5356
|
material({ materialId }, { loaders }) {
|
|
5207
5357
|
return loaders.batchSingle.load({
|
|
5208
|
-
__entity:
|
|
5358
|
+
__entity: this.materialEntity,
|
|
5209
5359
|
__from: { id: materialId },
|
|
5210
5360
|
});
|
|
5211
5361
|
}
|
|
@@ -5333,9 +5483,22 @@ tslib.__decorate([
|
|
|
5333
5483
|
tslib.__metadata("design:returntype", Promise)
|
|
5334
5484
|
], ShipInventoryOrderItemResolver.prototype, "shippedQuantity", null);
|
|
5335
5485
|
ShipInventoryOrderItemResolver = tslib.__decorate([
|
|
5336
|
-
graphql.Resolver(() => ShipInventoryOrderItemDto)
|
|
5486
|
+
graphql.Resolver(() => ShipInventoryOrderItemDto),
|
|
5487
|
+
tslib.__param(0, common.Inject(wmsModuleCore.MaterialEntity)),
|
|
5488
|
+
tslib.__metadata("design:paramtypes", [Function])
|
|
5337
5489
|
], ShipInventoryOrderItemResolver);
|
|
5338
5490
|
let ShipInventoryOrderReferenceResolver = class ShipInventoryOrderReferenceResolver {
|
|
5491
|
+
materialEntity;
|
|
5492
|
+
/**
|
|
5493
|
+
* Bound to the `MaterialEntity` Symbol, so the DataLoader queries whichever
|
|
5494
|
+
* material entity the consumer configured — the built-in `MaterialEntityClass`
|
|
5495
|
+
* unless `materialEntity` was passed to `forRoot`/`forRootAsync`. Loading the
|
|
5496
|
+
* built-in class outright would filter on its single-table-inheritance
|
|
5497
|
+
* discriminator and resolve nothing for a custom entity.
|
|
5498
|
+
*/
|
|
5499
|
+
constructor(materialEntity) {
|
|
5500
|
+
this.materialEntity = materialEntity;
|
|
5501
|
+
}
|
|
5339
5502
|
async shippedQuantity({ orderId, serialId }, { loaders }) {
|
|
5340
5503
|
const items = await loaders.batchMany.load({
|
|
5341
5504
|
__entity: wmsModuleCore.ShipInventoryOrderItemEntityClass,
|
|
@@ -5350,7 +5513,7 @@ let ShipInventoryOrderReferenceResolver = class ShipInventoryOrderReferenceResol
|
|
|
5350
5513
|
}
|
|
5351
5514
|
material({ materialId }, { loaders }) {
|
|
5352
5515
|
return loaders.batchSingle.load({
|
|
5353
|
-
__entity:
|
|
5516
|
+
__entity: this.materialEntity,
|
|
5354
5517
|
__from: { id: materialId },
|
|
5355
5518
|
});
|
|
5356
5519
|
}
|
|
@@ -5406,7 +5569,9 @@ tslib.__decorate([
|
|
|
5406
5569
|
tslib.__metadata("design:returntype", Promise)
|
|
5407
5570
|
], ShipInventoryOrderReferenceResolver.prototype, "items", null);
|
|
5408
5571
|
ShipInventoryOrderReferenceResolver = tslib.__decorate([
|
|
5409
|
-
graphql.Resolver(() => ShipInventoryOrderReferenceDto)
|
|
5572
|
+
graphql.Resolver(() => ShipInventoryOrderReferenceDto),
|
|
5573
|
+
tslib.__param(0, common.Inject(wmsModuleCore.MaterialEntity)),
|
|
5574
|
+
tslib.__metadata("design:paramtypes", [Function])
|
|
5410
5575
|
], ShipInventoryOrderReferenceResolver);
|
|
5411
5576
|
|
|
5412
5577
|
let FindSaleOrderArgs = class FindSaleOrderArgs extends PaginationArgs {
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import { DataSource, FindOptionsWhere, ObjectLiteral, SelectQueryBuilder } from 'typeorm';
|
|
1
|
+
import { DataSource, EntityTarget, FindOptionsWhere, ObjectLiteral, SelectQueryBuilder } from 'typeorm';
|
|
2
2
|
import DataLoader from 'dataloader';
|
|
3
3
|
export interface LoaderOptions<K> {
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Widened from `ObjectLiteral` so a resolver can pass the entity it had
|
|
6
|
+
* injected from the `MaterialEntity` / `…Entity` Symbols — those are typed as
|
|
7
|
+
* `EntityTarget`, which is also exactly what `core()` hands to
|
|
8
|
+
* `getRepository()`.
|
|
9
|
+
*/
|
|
10
|
+
__entity: EntityTarget<ObjectLiteral>;
|
|
5
11
|
__from: FindOptionsWhere<K>;
|
|
6
12
|
__conditions?: (qb: SelectQueryBuilder<ObjectLiteral>) => SelectQueryBuilder<ObjectLiteral>;
|
|
7
13
|
__seed?: string;
|
|
@@ -33,6 +39,28 @@ export declare class LoaderService {
|
|
|
33
39
|
* @returns Map<string, data>
|
|
34
40
|
*/
|
|
35
41
|
private useIndex;
|
|
42
|
+
/**
|
|
43
|
+
* resolve a `__from` property name to the physical column it is stored in.
|
|
44
|
+
*
|
|
45
|
+
* TypeORM's `FindOptionsWhere` only accepts real column properties. A
|
|
46
|
+
* `@RelationId()` property — e.g. `LocationEntityClass.parentId`, which mirrors
|
|
47
|
+
* the `parent` tree relation — is virtual and is rejected with
|
|
48
|
+
* `EntityPropertyNotFoundError`, even though it is backed by the relation's
|
|
49
|
+
* join column. Map those back to their join column so they stay batchable.
|
|
50
|
+
* @param EntityMetadata
|
|
51
|
+
* @param string
|
|
52
|
+
* @returns string | null
|
|
53
|
+
*/
|
|
54
|
+
private resolveColumnName;
|
|
55
|
+
/**
|
|
56
|
+
* build the where clause for `__from` keys that TypeORM's find options cannot
|
|
57
|
+
* express (see {@link resolveColumnName}), by addressing the columns directly.
|
|
58
|
+
* @param SelectQueryBuilder
|
|
59
|
+
* @param EntityMetadata
|
|
60
|
+
* @param LoaderOptions[]
|
|
61
|
+
* @param (keyof T)[]
|
|
62
|
+
*/
|
|
63
|
+
private applyColumnWhere;
|
|
36
64
|
/**
|
|
37
65
|
* query data by collecting primary keys from options with same `__entity`
|
|
38
66
|
* @param LoaderOptions[]
|
|
@@ -3,7 +3,7 @@ import { Injectable } from '@nestjs/common';
|
|
|
3
3
|
import { createHash } from 'crypto';
|
|
4
4
|
import _ from 'lodash';
|
|
5
5
|
import { LRUCache } from 'lru-cache';
|
|
6
|
-
import { DataSource, In } from 'typeorm';
|
|
6
|
+
import { DataSource, Brackets, In } from 'typeorm';
|
|
7
7
|
import DataLoader from 'dataloader';
|
|
8
8
|
|
|
9
9
|
let LoaderService = class LoaderService {
|
|
@@ -42,6 +42,65 @@ let LoaderService = class LoaderService {
|
|
|
42
42
|
const fields = _(Object.keys(__from)).sort();
|
|
43
43
|
return `${__hash}_${fields.map((field) => data[field]).join('_')}`;
|
|
44
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* resolve a `__from` property name to the physical column it is stored in.
|
|
47
|
+
*
|
|
48
|
+
* TypeORM's `FindOptionsWhere` only accepts real column properties. A
|
|
49
|
+
* `@RelationId()` property — e.g. `LocationEntityClass.parentId`, which mirrors
|
|
50
|
+
* the `parent` tree relation — is virtual and is rejected with
|
|
51
|
+
* `EntityPropertyNotFoundError`, even though it is backed by the relation's
|
|
52
|
+
* join column. Map those back to their join column so they stay batchable.
|
|
53
|
+
* @param EntityMetadata
|
|
54
|
+
* @param string
|
|
55
|
+
* @returns string | null
|
|
56
|
+
*/
|
|
57
|
+
resolveColumnName(metadata, propertyName) {
|
|
58
|
+
const column = metadata.findColumnWithPropertyName(propertyName);
|
|
59
|
+
if (column)
|
|
60
|
+
return column.databaseName;
|
|
61
|
+
const relationId = metadata.relationIds.find((candidate) => candidate.propertyName === propertyName);
|
|
62
|
+
const joinColumns = relationId?.relation.joinColumns ?? [];
|
|
63
|
+
return joinColumns.length === 1 ? joinColumns[0].databaseName : null;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* build the where clause for `__from` keys that TypeORM's find options cannot
|
|
67
|
+
* express (see {@link resolveColumnName}), by addressing the columns directly.
|
|
68
|
+
* @param SelectQueryBuilder
|
|
69
|
+
* @param EntityMetadata
|
|
70
|
+
* @param LoaderOptions[]
|
|
71
|
+
* @param (keyof T)[]
|
|
72
|
+
*/
|
|
73
|
+
applyColumnWhere(qb, metadata, options, primaryKeys) {
|
|
74
|
+
const columns = primaryKeys.map((primaryKey) => {
|
|
75
|
+
const columnName = this.resolveColumnName(metadata, String(primaryKey));
|
|
76
|
+
if (!columnName)
|
|
77
|
+
throw new Error(`Loader cannot resolve property "${String(primaryKey)}" to a column of "${metadata.name}".`);
|
|
78
|
+
return {
|
|
79
|
+
primaryKey,
|
|
80
|
+
column: `entity.${this.dataSource.driver.escape(columnName)}`,
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
if (columns.length === 1) {
|
|
84
|
+
const [{ primaryKey, column }] = columns;
|
|
85
|
+
qb.andWhere(`${column} IN (:...wmsLoaderValues)`, {
|
|
86
|
+
wmsLoaderValues: options.map(({ __from }) => __from[primaryKey]),
|
|
87
|
+
});
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
qb.andWhere(new Brackets((where) => {
|
|
91
|
+
options.forEach(({ __from }, optionIndex) => {
|
|
92
|
+
const parameters = {};
|
|
93
|
+
const predicate = columns
|
|
94
|
+
.map(({ primaryKey, column }, columnIndex) => {
|
|
95
|
+
const parameter = `wmsLoaderValue_${optionIndex}_${columnIndex}`;
|
|
96
|
+
parameters[parameter] = __from[primaryKey];
|
|
97
|
+
return `${column} = :${parameter}`;
|
|
98
|
+
})
|
|
99
|
+
.join(' AND ');
|
|
100
|
+
where.orWhere(`(${predicate})`, parameters);
|
|
101
|
+
});
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
45
104
|
/**
|
|
46
105
|
* query data by collecting primary keys from options with same `__entity`
|
|
47
106
|
* @param LoaderOptions[]
|
|
@@ -52,7 +111,10 @@ let LoaderService = class LoaderService {
|
|
|
52
111
|
const repo = this.dataSource.getRepository(__entity);
|
|
53
112
|
let qb = repo.createQueryBuilder('entity');
|
|
54
113
|
const primaryKeys = Object.keys(__from);
|
|
55
|
-
|
|
114
|
+
const hasVirtualKey = primaryKeys.some((primaryKey) => !repo.metadata.findColumnWithPropertyName(String(primaryKey)));
|
|
115
|
+
if (hasVirtualKey)
|
|
116
|
+
this.applyColumnWhere(qb, repo.metadata, options, primaryKeys);
|
|
117
|
+
else if (primaryKeys.length > 1)
|
|
56
118
|
qb.setFindOptions({ where: options.map(({ __from }) => __from) });
|
|
57
119
|
else {
|
|
58
120
|
const [primaryKey] = primaryKeys;
|
|
@@ -5,7 +5,16 @@ import { BatchDto } from '../dto/batch.dto';
|
|
|
5
5
|
import { LocationDto } from '../dto/location.dto';
|
|
6
6
|
export declare class AggregatedStockResolver {
|
|
7
7
|
private readonly stockService;
|
|
8
|
-
|
|
8
|
+
private readonly materialEntity;
|
|
9
|
+
/**
|
|
10
|
+
* `materialEntity` is bound to the `MaterialEntity` Symbol, so the DataLoader
|
|
11
|
+
* queries whichever material entity the consumer configured — the built-in
|
|
12
|
+
* `MaterialEntityClass` unless `materialEntity` was passed to
|
|
13
|
+
* `forRoot`/`forRootAsync`. Loading the built-in class outright would filter on
|
|
14
|
+
* its single-table-inheritance discriminator and resolve nothing for a custom
|
|
15
|
+
* entity.
|
|
16
|
+
*/
|
|
17
|
+
constructor(stockService: StockService, materialEntity: new () => MaterialEntityClass);
|
|
9
18
|
id(stock: AggregatedStockDto): Promise<string>;
|
|
10
19
|
material({ materialId }: AggregatedStockDto, { loaders }: LoaderType<MaterialEntityClass>): Promise<MaterialDto>;
|
|
11
20
|
batch({ batchId }: AggregatedStockDto, { loaders }: LoaderType<BatchEntityClass>): Promise<BatchDto>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { __decorate, __param, __metadata } from 'tslib';
|
|
2
|
+
import { Inject } from '@nestjs/common';
|
|
2
3
|
import { ResolveField, ID, Parent, Context, Resolver } from '@nestjs/graphql';
|
|
3
4
|
import '../dto/loader-type.dto.js';
|
|
4
5
|
import { LoaderDto } from '../dto/loader.dto.js';
|
|
@@ -24,21 +25,31 @@ import '../dto/scrape-order.dto.js';
|
|
|
24
25
|
import '../dto/scrape-order-item.dto.js';
|
|
25
26
|
import '../dto/quality-inspection-order.dto.js';
|
|
26
27
|
import '../dto/quality-inspection-order-item.dto.js';
|
|
27
|
-
import {
|
|
28
|
+
import { MaterialEntity, StockService, BatchEntityClass, BatchGroupEntityClass, LocationEntityClass, LoadersEntityClass } from '@rytass/wms-module-core';
|
|
28
29
|
import { BatchDto } from '../dto/batch.dto.js';
|
|
29
30
|
import { LocationDto } from '../dto/location.dto.js';
|
|
30
31
|
|
|
31
32
|
let AggregatedStockResolver = class AggregatedStockResolver {
|
|
32
33
|
stockService;
|
|
33
|
-
|
|
34
|
+
materialEntity;
|
|
35
|
+
/**
|
|
36
|
+
* `materialEntity` is bound to the `MaterialEntity` Symbol, so the DataLoader
|
|
37
|
+
* queries whichever material entity the consumer configured — the built-in
|
|
38
|
+
* `MaterialEntityClass` unless `materialEntity` was passed to
|
|
39
|
+
* `forRoot`/`forRootAsync`. Loading the built-in class outright would filter on
|
|
40
|
+
* its single-table-inheritance discriminator and resolve nothing for a custom
|
|
41
|
+
* entity.
|
|
42
|
+
*/
|
|
43
|
+
constructor(stockService, materialEntity) {
|
|
34
44
|
this.stockService = stockService;
|
|
45
|
+
this.materialEntity = materialEntity;
|
|
35
46
|
}
|
|
36
47
|
async id(stock) {
|
|
37
48
|
return this.stockService.generatedAggregateKey(stock);
|
|
38
49
|
}
|
|
39
50
|
async material({ materialId }, { loaders }) {
|
|
40
51
|
return loaders.batchSingle.load({
|
|
41
|
-
__entity:
|
|
52
|
+
__entity: this.materialEntity,
|
|
42
53
|
__from: { id: materialId },
|
|
43
54
|
});
|
|
44
55
|
}
|
|
@@ -106,7 +117,8 @@ __decorate([
|
|
|
106
117
|
], AggregatedStockResolver.prototype, "loader", null);
|
|
107
118
|
AggregatedStockResolver = __decorate([
|
|
108
119
|
Resolver(() => AggregatedStockDto),
|
|
109
|
-
|
|
120
|
+
__param(1, Inject(MaterialEntity)),
|
|
121
|
+
__metadata("design:paramtypes", [StockService, Function])
|
|
110
122
|
], AggregatedStockResolver);
|
|
111
123
|
|
|
112
124
|
export { AggregatedStockResolver };
|
|
@@ -4,6 +4,15 @@ import { type LoaderType } from '../helpers';
|
|
|
4
4
|
import { LocationDto } from '../dto/location.dto';
|
|
5
5
|
import { BatchDto } from '../dto/batch.dto';
|
|
6
6
|
export declare class ChangeLogResolver {
|
|
7
|
+
private readonly materialEntity;
|
|
8
|
+
/**
|
|
9
|
+
* Bound to the `MaterialEntity` Symbol, so the DataLoader queries whichever
|
|
10
|
+
* material entity the consumer configured — the built-in `MaterialEntityClass`
|
|
11
|
+
* unless `materialEntity` was passed to `forRoot`/`forRootAsync`. Loading the
|
|
12
|
+
* built-in class outright would filter on its single-table-inheritance
|
|
13
|
+
* discriminator and resolve nothing for a custom entity.
|
|
14
|
+
*/
|
|
15
|
+
constructor(materialEntity: new () => MaterialEntityClass);
|
|
7
16
|
material({ materialId }: StockEntityClass, { loaders }: LoaderType<MaterialEntityClass>): Promise<MaterialDto>;
|
|
8
17
|
location({ locationId }: StockEntityClass, { loaders }: LoaderType<LocationEntityClass>): Promise<LocationDto>;
|
|
9
18
|
batch({ batchId }: StockEntityClass, { loaders }: LoaderType<BatchEntityClass>): Promise<BatchDto>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { __decorate, __param, __metadata } from 'tslib';
|
|
2
|
+
import { Inject } from '@nestjs/common';
|
|
2
3
|
import { ResolveField, Parent, Context, Resolver } from '@nestjs/graphql';
|
|
3
4
|
import '../dto/loader-type.dto.js';
|
|
4
5
|
import '../dto/loader.dto.js';
|
|
@@ -24,14 +25,25 @@ import '../dto/scrape-order.dto.js';
|
|
|
24
25
|
import '../dto/scrape-order-item.dto.js';
|
|
25
26
|
import '../dto/quality-inspection-order.dto.js';
|
|
26
27
|
import '../dto/quality-inspection-order-item.dto.js';
|
|
27
|
-
import { StockEntityClass,
|
|
28
|
+
import { StockEntityClass, MaterialEntity, LocationEntityClass, BatchEntityClass, BatchGroupEntityClass } from '@rytass/wms-module-core';
|
|
28
29
|
import { LocationDto } from '../dto/location.dto.js';
|
|
29
30
|
import { BatchDto } from '../dto/batch.dto.js';
|
|
30
31
|
|
|
31
32
|
let ChangeLogResolver = class ChangeLogResolver {
|
|
33
|
+
materialEntity;
|
|
34
|
+
/**
|
|
35
|
+
* Bound to the `MaterialEntity` Symbol, so the DataLoader queries whichever
|
|
36
|
+
* material entity the consumer configured — the built-in `MaterialEntityClass`
|
|
37
|
+
* unless `materialEntity` was passed to `forRoot`/`forRootAsync`. Loading the
|
|
38
|
+
* built-in class outright would filter on its single-table-inheritance
|
|
39
|
+
* discriminator and resolve nothing for a custom entity.
|
|
40
|
+
*/
|
|
41
|
+
constructor(materialEntity) {
|
|
42
|
+
this.materialEntity = materialEntity;
|
|
43
|
+
}
|
|
32
44
|
material({ materialId }, { loaders }) {
|
|
33
45
|
return loaders.batchSingle.load({
|
|
34
|
-
__entity:
|
|
46
|
+
__entity: this.materialEntity,
|
|
35
47
|
__from: { id: materialId },
|
|
36
48
|
});
|
|
37
49
|
}
|
|
@@ -77,7 +89,9 @@ __decorate([
|
|
|
77
89
|
__metadata("design:returntype", Promise)
|
|
78
90
|
], ChangeLogResolver.prototype, "batch", null);
|
|
79
91
|
ChangeLogResolver = __decorate([
|
|
80
|
-
Resolver(() => ChangeLogDto)
|
|
92
|
+
Resolver(() => ChangeLogDto),
|
|
93
|
+
__param(0, Inject(MaterialEntity)),
|
|
94
|
+
__metadata("design:paramtypes", [Function])
|
|
81
95
|
], ChangeLogResolver);
|
|
82
96
|
|
|
83
97
|
export { ChangeLogResolver };
|
|
@@ -6,5 +6,14 @@ import { LocationEntityClass } from '@rytass/wms-module-core';
|
|
|
6
6
|
export declare class LocationResolver {
|
|
7
7
|
mapData({ id }: LocationDto, { loaders }: LoaderType<WarehouseMapEntity>): Promise<MapDataDto | null>;
|
|
8
8
|
parent({ parentId }: LocationEntityClass, { loaders }: LoaderType<LocationEntityClass>): Promise<LocationEntityClass> | null;
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* `children` must never be read off the parent entity: only
|
|
11
|
+
* `LocationQuery.location` and `LocationService.findMany` eager-load the tree
|
|
12
|
+
* relation. Every other producer of a `LocationDto` (stock/loader/change-log/
|
|
13
|
+
* transfer/ship/receive/warehouse-map resolvers, the `parent` field above and
|
|
14
|
+
* the create/update mutations) hands back an entity whose `children` is
|
|
15
|
+
* `undefined`, which breaks the non-nullable list. Always resolve through the
|
|
16
|
+
* request-scoped loader instead.
|
|
17
|
+
*/
|
|
18
|
+
children({ id }: LocationEntityClass, { loaders }: LoaderType<LocationEntityClass>): Promise<LocationDto[]>;
|
|
10
19
|
}
|
|
@@ -21,8 +21,21 @@ let LocationResolver = class LocationResolver {
|
|
|
21
21
|
__from: { id: parentId },
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
/**
|
|
25
|
+
* `children` must never be read off the parent entity: only
|
|
26
|
+
* `LocationQuery.location` and `LocationService.findMany` eager-load the tree
|
|
27
|
+
* relation. Every other producer of a `LocationDto` (stock/loader/change-log/
|
|
28
|
+
* transfer/ship/receive/warehouse-map resolvers, the `parent` field above and
|
|
29
|
+
* the create/update mutations) hands back an entity whose `children` is
|
|
30
|
+
* `undefined`, which breaks the non-nullable list. Always resolve through the
|
|
31
|
+
* request-scoped loader instead.
|
|
32
|
+
*/
|
|
33
|
+
children({ id }, { loaders }) {
|
|
34
|
+
return loaders.batchMany.load({
|
|
35
|
+
__entity: LocationEntityClass,
|
|
36
|
+
__from: { parentId: id },
|
|
37
|
+
__conditions: (qb) => qb.orderBy('entity."key"', 'ASC'),
|
|
38
|
+
});
|
|
26
39
|
}
|
|
27
40
|
};
|
|
28
41
|
__decorate([
|
|
@@ -44,9 +57,10 @@ __decorate([
|
|
|
44
57
|
__decorate([
|
|
45
58
|
ResolveField(() => [LocationDto]),
|
|
46
59
|
__param(0, Parent()),
|
|
60
|
+
__param(1, Context()),
|
|
47
61
|
__metadata("design:type", Function),
|
|
48
|
-
__metadata("design:paramtypes", [LocationEntityClass]),
|
|
49
|
-
__metadata("design:returntype",
|
|
62
|
+
__metadata("design:paramtypes", [LocationEntityClass, Object]),
|
|
63
|
+
__metadata("design:returntype", Promise)
|
|
50
64
|
], LocationResolver.prototype, "children", null);
|
|
51
65
|
LocationResolver = __decorate([
|
|
52
66
|
Resolver(() => LocationDto)
|
|
@@ -7,6 +7,15 @@ export declare class ReceiveInventoryOrderResolver {
|
|
|
7
7
|
items({ id }: ReceiveInventoryOrderDto, { loaders }: LoaderType<ReceiveInventoryOrderItemEntityClass>): Promise<ReceiveInventoryOrderItemDto[]>;
|
|
8
8
|
}
|
|
9
9
|
export declare class ReceiveInventoryOrderItemResolver {
|
|
10
|
+
private readonly materialEntity;
|
|
11
|
+
/**
|
|
12
|
+
* Bound to the `MaterialEntity` Symbol, so the DataLoader queries whichever
|
|
13
|
+
* material entity the consumer configured — the built-in `MaterialEntityClass`
|
|
14
|
+
* unless `materialEntity` was passed to `forRoot`/`forRootAsync`. Loading the
|
|
15
|
+
* built-in class outright would filter on its single-table-inheritance
|
|
16
|
+
* discriminator and resolve nothing for a custom entity.
|
|
17
|
+
*/
|
|
18
|
+
constructor(materialEntity: new () => MaterialEntityClass);
|
|
10
19
|
material({ materialId }: ReceiveInventoryOrderItemEntityClass, { loaders }: LoaderType<MaterialEntityClass>): Promise<MaterialDto>;
|
|
11
20
|
batch({ batchId }: ReceiveInventoryOrderItemEntityClass, { loaders }: LoaderType<BatchEntityClass>): Promise<BatchDto | null>;
|
|
12
21
|
location({ locationId }: ReceiveInventoryOrderItemEntityClass, { loaders }: LoaderType<LocationEntityClass>): Promise<LocationDto | null>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { __decorate, __param, __metadata } from 'tslib';
|
|
2
|
+
import { Inject } from '@nestjs/common';
|
|
2
3
|
import { ResolveField, Parent, Context, Resolver, Int } from '@nestjs/graphql';
|
|
3
4
|
import '../dto/loader-type.dto.js';
|
|
4
5
|
import { LoaderDto } from '../dto/loader.dto.js';
|
|
@@ -24,7 +25,7 @@ import '../dto/scrape-order.dto.js';
|
|
|
24
25
|
import '../dto/scrape-order-item.dto.js';
|
|
25
26
|
import '../dto/quality-inspection-order.dto.js';
|
|
26
27
|
import '../dto/quality-inspection-order-item.dto.js';
|
|
27
|
-
import { ReceiveInventoryOrderItemEntityClass,
|
|
28
|
+
import { ReceiveInventoryOrderItemEntityClass, MaterialEntity, BatchEntityClass, BatchGroupEntityClass, LocationEntityClass, LoadersEntityClass, ReceiveInventoryOrderChangeEntityClass } from '@rytass/wms-module-core';
|
|
28
29
|
import { BatchDto } from '../dto/batch.dto.js';
|
|
29
30
|
import { LocationDto } from '../dto/location.dto.js';
|
|
30
31
|
|
|
@@ -49,9 +50,20 @@ ReceiveInventoryOrderResolver = __decorate([
|
|
|
49
50
|
Resolver(() => ReceiveInventoryOrderDto)
|
|
50
51
|
], ReceiveInventoryOrderResolver);
|
|
51
52
|
let ReceiveInventoryOrderItemResolver = class ReceiveInventoryOrderItemResolver {
|
|
53
|
+
materialEntity;
|
|
54
|
+
/**
|
|
55
|
+
* Bound to the `MaterialEntity` Symbol, so the DataLoader queries whichever
|
|
56
|
+
* material entity the consumer configured — the built-in `MaterialEntityClass`
|
|
57
|
+
* unless `materialEntity` was passed to `forRoot`/`forRootAsync`. Loading the
|
|
58
|
+
* built-in class outright would filter on its single-table-inheritance
|
|
59
|
+
* discriminator and resolve nothing for a custom entity.
|
|
60
|
+
*/
|
|
61
|
+
constructor(materialEntity) {
|
|
62
|
+
this.materialEntity = materialEntity;
|
|
63
|
+
}
|
|
52
64
|
material({ materialId }, { loaders }) {
|
|
53
65
|
return loaders.batchSingle.load({
|
|
54
|
-
__entity:
|
|
66
|
+
__entity: this.materialEntity,
|
|
55
67
|
__from: { id: materialId },
|
|
56
68
|
});
|
|
57
69
|
}
|
|
@@ -134,7 +146,9 @@ __decorate([
|
|
|
134
146
|
__metadata("design:returntype", Promise)
|
|
135
147
|
], ReceiveInventoryOrderItemResolver.prototype, "receivedQuantity", null);
|
|
136
148
|
ReceiveInventoryOrderItemResolver = __decorate([
|
|
137
|
-
Resolver(() => ReceiveInventoryOrderItemDto)
|
|
149
|
+
Resolver(() => ReceiveInventoryOrderItemDto),
|
|
150
|
+
__param(0, Inject(MaterialEntity)),
|
|
151
|
+
__metadata("design:paramtypes", [Function])
|
|
138
152
|
], ReceiveInventoryOrderItemResolver);
|
|
139
153
|
|
|
140
154
|
export { ReceiveInventoryOrderItemResolver, ReceiveInventoryOrderResolver };
|
|
@@ -9,6 +9,15 @@ export declare class ShipInventoryOrderResolver {
|
|
|
9
9
|
references({ id }: ShipInventoryOrderEntityClass, { loaders }: LoaderType<ShipInventoryOrderReferenceEntityClass>): Promise<ShipInventoryOrderReferenceDto[]>;
|
|
10
10
|
}
|
|
11
11
|
export declare class ShipInventoryOrderItemResolver {
|
|
12
|
+
private readonly materialEntity;
|
|
13
|
+
/**
|
|
14
|
+
* Bound to the `MaterialEntity` Symbol, so the DataLoader queries whichever
|
|
15
|
+
* material entity the consumer configured — the built-in `MaterialEntityClass`
|
|
16
|
+
* unless `materialEntity` was passed to `forRoot`/`forRootAsync`. Loading the
|
|
17
|
+
* built-in class outright would filter on its single-table-inheritance
|
|
18
|
+
* discriminator and resolve nothing for a custom entity.
|
|
19
|
+
*/
|
|
20
|
+
constructor(materialEntity: new () => MaterialEntityClass);
|
|
12
21
|
material({ materialId }: ShipInventoryOrderItemEntityClass, { loaders }: LoaderType<MaterialEntityClass>): Promise<MaterialDto>;
|
|
13
22
|
batch({ batchId }: ShipInventoryOrderItemEntityClass, { loaders }: LoaderType<BatchEntityClass>): Promise<BatchDto | null>;
|
|
14
23
|
saleId({ batchId }: ShipInventoryOrderItemEntityClass, { loaders }: LoaderType<BatchEntityClass>): Promise<string | null>;
|
|
@@ -18,6 +27,15 @@ export declare class ShipInventoryOrderItemResolver {
|
|
|
18
27
|
shippedQuantity({ id }: ShipInventoryOrderItemEntityClass, { loaders }: LoaderType<ShipInventoryOrderChangeEntityClass>): Promise<number>;
|
|
19
28
|
}
|
|
20
29
|
export declare class ShipInventoryOrderReferenceResolver {
|
|
30
|
+
private readonly materialEntity;
|
|
31
|
+
/**
|
|
32
|
+
* Bound to the `MaterialEntity` Symbol, so the DataLoader queries whichever
|
|
33
|
+
* material entity the consumer configured — the built-in `MaterialEntityClass`
|
|
34
|
+
* unless `materialEntity` was passed to `forRoot`/`forRootAsync`. Loading the
|
|
35
|
+
* built-in class outright would filter on its single-table-inheritance
|
|
36
|
+
* discriminator and resolve nothing for a custom entity.
|
|
37
|
+
*/
|
|
38
|
+
constructor(materialEntity: new () => MaterialEntityClass);
|
|
21
39
|
shippedQuantity({ orderId, serialId }: ShipInventoryOrderReferenceEntityClass, { loaders }: LoaderType<ShipInventoryOrderItemEntityClass>): Promise<number>;
|
|
22
40
|
material({ materialId }: ShipInventoryOrderReferenceEntityClass, { loaders }: LoaderType<MaterialEntityClass>): Promise<MaterialDto>;
|
|
23
41
|
batch({ batchId }: ShipInventoryOrderReferenceEntityClass, { loaders }: LoaderType<BatchEntityClass>): Promise<BatchDto | null>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { __decorate, __param, __metadata } from 'tslib';
|
|
2
|
+
import { Inject } from '@nestjs/common';
|
|
2
3
|
import { ResolveField, Parent, Context, Resolver, ID, Int } from '@nestjs/graphql';
|
|
3
4
|
import '../dto/loader-type.dto.js';
|
|
4
5
|
import { LoaderDto } from '../dto/loader.dto.js';
|
|
@@ -24,7 +25,7 @@ import '../dto/scrape-order.dto.js';
|
|
|
24
25
|
import '../dto/scrape-order-item.dto.js';
|
|
25
26
|
import '../dto/quality-inspection-order.dto.js';
|
|
26
27
|
import '../dto/quality-inspection-order-item.dto.js';
|
|
27
|
-
import { ShipInventoryOrderEntityClass, ShipInventoryOrderItemEntityClass,
|
|
28
|
+
import { ShipInventoryOrderEntityClass, ShipInventoryOrderItemEntityClass, MaterialEntity, ShipInventoryOrderReferenceEntityClass, BatchEntityClass, BatchGroupEntityClass, LocationEntityClass, LoadersEntityClass, ShipInventoryOrderChangeEntityClass } from '@rytass/wms-module-core';
|
|
28
29
|
import { BatchDto } from '../dto/batch.dto.js';
|
|
29
30
|
import { LocationDto } from '../dto/location.dto.js';
|
|
30
31
|
import { ShipInventoryOrderReferenceDto } from '../dto/ship-inventory-order-reference.dto.js';
|
|
@@ -64,9 +65,20 @@ ShipInventoryOrderResolver = __decorate([
|
|
|
64
65
|
Resolver(() => ShipInventoryOrderDto)
|
|
65
66
|
], ShipInventoryOrderResolver);
|
|
66
67
|
let ShipInventoryOrderItemResolver = class ShipInventoryOrderItemResolver {
|
|
68
|
+
materialEntity;
|
|
69
|
+
/**
|
|
70
|
+
* Bound to the `MaterialEntity` Symbol, so the DataLoader queries whichever
|
|
71
|
+
* material entity the consumer configured — the built-in `MaterialEntityClass`
|
|
72
|
+
* unless `materialEntity` was passed to `forRoot`/`forRootAsync`. Loading the
|
|
73
|
+
* built-in class outright would filter on its single-table-inheritance
|
|
74
|
+
* discriminator and resolve nothing for a custom entity.
|
|
75
|
+
*/
|
|
76
|
+
constructor(materialEntity) {
|
|
77
|
+
this.materialEntity = materialEntity;
|
|
78
|
+
}
|
|
67
79
|
material({ materialId }, { loaders }) {
|
|
68
80
|
return loaders.batchSingle.load({
|
|
69
|
-
__entity:
|
|
81
|
+
__entity: this.materialEntity,
|
|
70
82
|
__from: { id: materialId },
|
|
71
83
|
});
|
|
72
84
|
}
|
|
@@ -194,9 +206,22 @@ __decorate([
|
|
|
194
206
|
__metadata("design:returntype", Promise)
|
|
195
207
|
], ShipInventoryOrderItemResolver.prototype, "shippedQuantity", null);
|
|
196
208
|
ShipInventoryOrderItemResolver = __decorate([
|
|
197
|
-
Resolver(() => ShipInventoryOrderItemDto)
|
|
209
|
+
Resolver(() => ShipInventoryOrderItemDto),
|
|
210
|
+
__param(0, Inject(MaterialEntity)),
|
|
211
|
+
__metadata("design:paramtypes", [Function])
|
|
198
212
|
], ShipInventoryOrderItemResolver);
|
|
199
213
|
let ShipInventoryOrderReferenceResolver = class ShipInventoryOrderReferenceResolver {
|
|
214
|
+
materialEntity;
|
|
215
|
+
/**
|
|
216
|
+
* Bound to the `MaterialEntity` Symbol, so the DataLoader queries whichever
|
|
217
|
+
* material entity the consumer configured — the built-in `MaterialEntityClass`
|
|
218
|
+
* unless `materialEntity` was passed to `forRoot`/`forRootAsync`. Loading the
|
|
219
|
+
* built-in class outright would filter on its single-table-inheritance
|
|
220
|
+
* discriminator and resolve nothing for a custom entity.
|
|
221
|
+
*/
|
|
222
|
+
constructor(materialEntity) {
|
|
223
|
+
this.materialEntity = materialEntity;
|
|
224
|
+
}
|
|
200
225
|
async shippedQuantity({ orderId, serialId }, { loaders }) {
|
|
201
226
|
const items = await loaders.batchMany.load({
|
|
202
227
|
__entity: ShipInventoryOrderItemEntityClass,
|
|
@@ -211,7 +236,7 @@ let ShipInventoryOrderReferenceResolver = class ShipInventoryOrderReferenceResol
|
|
|
211
236
|
}
|
|
212
237
|
material({ materialId }, { loaders }) {
|
|
213
238
|
return loaders.batchSingle.load({
|
|
214
|
-
__entity:
|
|
239
|
+
__entity: this.materialEntity,
|
|
215
240
|
__from: { id: materialId },
|
|
216
241
|
});
|
|
217
242
|
}
|
|
@@ -267,7 +292,9 @@ __decorate([
|
|
|
267
292
|
__metadata("design:returntype", Promise)
|
|
268
293
|
], ShipInventoryOrderReferenceResolver.prototype, "items", null);
|
|
269
294
|
ShipInventoryOrderReferenceResolver = __decorate([
|
|
270
|
-
Resolver(() => ShipInventoryOrderReferenceDto)
|
|
295
|
+
Resolver(() => ShipInventoryOrderReferenceDto),
|
|
296
|
+
__param(0, Inject(MaterialEntity)),
|
|
297
|
+
__metadata("design:paramtypes", [Function])
|
|
271
298
|
], ShipInventoryOrderReferenceResolver);
|
|
272
299
|
|
|
273
300
|
export { ShipInventoryOrderItemResolver, ShipInventoryOrderReferenceResolver, ShipInventoryOrderResolver };
|
|
@@ -4,6 +4,15 @@ import { type LoaderType } from '../helpers';
|
|
|
4
4
|
import { LocationDto } from '../dto/location.dto';
|
|
5
5
|
import { BatchDto } from '../dto/batch.dto';
|
|
6
6
|
export declare class StockResolver {
|
|
7
|
+
private readonly materialEntity;
|
|
8
|
+
/**
|
|
9
|
+
* Bound to the `MaterialEntity` Symbol, so the DataLoader queries whichever
|
|
10
|
+
* material entity the consumer configured — the built-in `MaterialEntityClass`
|
|
11
|
+
* unless `materialEntity` was passed to `forRoot`/`forRootAsync`. Loading the
|
|
12
|
+
* built-in class outright would filter on its single-table-inheritance
|
|
13
|
+
* discriminator and resolve nothing for a custom entity.
|
|
14
|
+
*/
|
|
15
|
+
constructor(materialEntity: new () => MaterialEntityClass);
|
|
7
16
|
material({ materialId }: StockEntityClass, { loaders }: LoaderType<MaterialEntityClass>): Promise<MaterialDto>;
|
|
8
17
|
location({ locationId }: StockEntityClass, { loaders }: LoaderType<LocationEntityClass>): Promise<LocationDto>;
|
|
9
18
|
batch({ batchId }: StockEntityClass, { loaders }: LoaderType<BatchEntityClass>): Promise<BatchDto | null>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { __decorate, __param, __metadata } from 'tslib';
|
|
2
|
+
import { Inject } from '@nestjs/common';
|
|
2
3
|
import { ResolveField, Parent, Context, Resolver } from '@nestjs/graphql';
|
|
3
4
|
import '../dto/loader-type.dto.js';
|
|
4
5
|
import '../dto/loader.dto.js';
|
|
@@ -24,14 +25,25 @@ import '../dto/scrape-order.dto.js';
|
|
|
24
25
|
import '../dto/scrape-order-item.dto.js';
|
|
25
26
|
import '../dto/quality-inspection-order.dto.js';
|
|
26
27
|
import '../dto/quality-inspection-order-item.dto.js';
|
|
27
|
-
import { StockEntityClass,
|
|
28
|
+
import { StockEntityClass, MaterialEntity, LocationEntityClass, BatchEntityClass, BatchGroupEntityClass } from '@rytass/wms-module-core';
|
|
28
29
|
import { LocationDto } from '../dto/location.dto.js';
|
|
29
30
|
import { BatchDto } from '../dto/batch.dto.js';
|
|
30
31
|
|
|
31
32
|
let StockResolver = class StockResolver {
|
|
33
|
+
materialEntity;
|
|
34
|
+
/**
|
|
35
|
+
* Bound to the `MaterialEntity` Symbol, so the DataLoader queries whichever
|
|
36
|
+
* material entity the consumer configured — the built-in `MaterialEntityClass`
|
|
37
|
+
* unless `materialEntity` was passed to `forRoot`/`forRootAsync`. Loading the
|
|
38
|
+
* built-in class outright would filter on its single-table-inheritance
|
|
39
|
+
* discriminator and resolve nothing for a custom entity.
|
|
40
|
+
*/
|
|
41
|
+
constructor(materialEntity) {
|
|
42
|
+
this.materialEntity = materialEntity;
|
|
43
|
+
}
|
|
32
44
|
material({ materialId }, { loaders }) {
|
|
33
45
|
return loaders.batchSingle.load({
|
|
34
|
-
__entity:
|
|
46
|
+
__entity: this.materialEntity,
|
|
35
47
|
__from: { id: materialId },
|
|
36
48
|
});
|
|
37
49
|
}
|
|
@@ -77,7 +89,9 @@ __decorate([
|
|
|
77
89
|
__metadata("design:returntype", Promise)
|
|
78
90
|
], StockResolver.prototype, "batch", null);
|
|
79
91
|
StockResolver = __decorate([
|
|
80
|
-
Resolver(() => StockDto)
|
|
92
|
+
Resolver(() => StockDto),
|
|
93
|
+
__param(0, Inject(MaterialEntity)),
|
|
94
|
+
__metadata("design:paramtypes", [Function])
|
|
81
95
|
], StockResolver);
|
|
82
96
|
|
|
83
97
|
export { StockResolver };
|
|
@@ -11,6 +11,15 @@ export declare class TransferOrderResolver {
|
|
|
11
11
|
targetLoader({ id }: TransferOrderDto, { loaders }: LoaderType<TransferOrderItemEntityClass>, loaderLoader: LoaderType<LoadersEntityClass>): Promise<LoaderDto | null>;
|
|
12
12
|
}
|
|
13
13
|
export declare class TransferOrderItemResolver {
|
|
14
|
+
private readonly materialEntity;
|
|
15
|
+
/**
|
|
16
|
+
* Bound to the `MaterialEntity` Symbol, so the DataLoader queries whichever
|
|
17
|
+
* material entity the consumer configured — the built-in `MaterialEntityClass`
|
|
18
|
+
* unless `materialEntity` was passed to `forRoot`/`forRootAsync`. Loading the
|
|
19
|
+
* built-in class outright would filter on its single-table-inheritance
|
|
20
|
+
* discriminator and resolve nothing for a custom entity.
|
|
21
|
+
*/
|
|
22
|
+
constructor(materialEntity: new () => MaterialEntityClass);
|
|
14
23
|
material({ materialId }: TransferOrderItemEntityClass, { loaders }: LoaderType<MaterialEntityClass>): Promise<MaterialDto>;
|
|
15
24
|
batch({ batchId }: TransferOrderItemEntityClass, { loaders }: LoaderType<BatchEntityClass>): Promise<BatchDto | null>;
|
|
16
25
|
location({ locationId }: TransferOrderItemEntityClass, { loaders }: LoaderType<LocationEntityClass>): Promise<LocationDto | null>;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { __decorate, __param, __metadata } from 'tslib';
|
|
2
|
+
import { Inject } from '@nestjs/common';
|
|
2
3
|
import { ResolveField, Parent, Context, Resolver, ID, Int } from '@nestjs/graphql';
|
|
3
4
|
import { TransferOrderDto } from '../dto/transfer-order.dto.js';
|
|
4
5
|
import { TransferOrderItemDto } from '../dto/transfer-order-item.dto.js';
|
|
5
|
-
import { TransferOrderItemEntityClass, LocationEntityClass, LoadersEntityClass,
|
|
6
|
+
import { TransferOrderItemEntityClass, MaterialEntity, LocationEntityClass, LoadersEntityClass, BatchEntityClass, BatchGroupEntityClass, TransferOrderChangeEntityClass } from '@rytass/wms-module-core';
|
|
6
7
|
import '../dto/loader-type.dto.js';
|
|
7
8
|
import { LoaderDto } from '../dto/loader.dto.js';
|
|
8
9
|
import { MaterialDto } from '../dto/material.dto.js';
|
|
@@ -90,9 +91,20 @@ TransferOrderResolver = __decorate([
|
|
|
90
91
|
Resolver(() => TransferOrderDto)
|
|
91
92
|
], TransferOrderResolver);
|
|
92
93
|
let TransferOrderItemResolver = class TransferOrderItemResolver {
|
|
94
|
+
materialEntity;
|
|
95
|
+
/**
|
|
96
|
+
* Bound to the `MaterialEntity` Symbol, so the DataLoader queries whichever
|
|
97
|
+
* material entity the consumer configured — the built-in `MaterialEntityClass`
|
|
98
|
+
* unless `materialEntity` was passed to `forRoot`/`forRootAsync`. Loading the
|
|
99
|
+
* built-in class outright would filter on its single-table-inheritance
|
|
100
|
+
* discriminator and resolve nothing for a custom entity.
|
|
101
|
+
*/
|
|
102
|
+
constructor(materialEntity) {
|
|
103
|
+
this.materialEntity = materialEntity;
|
|
104
|
+
}
|
|
93
105
|
material({ materialId }, { loaders }) {
|
|
94
106
|
return loaders.batchSingle.load({
|
|
95
|
-
__entity:
|
|
107
|
+
__entity: this.materialEntity,
|
|
96
108
|
__from: { id: materialId },
|
|
97
109
|
});
|
|
98
110
|
}
|
|
@@ -212,7 +224,9 @@ __decorate([
|
|
|
212
224
|
__metadata("design:returntype", Promise)
|
|
213
225
|
], TransferOrderItemResolver.prototype, "transferredQuantity", null);
|
|
214
226
|
TransferOrderItemResolver = __decorate([
|
|
215
|
-
Resolver(() => TransferOrderItemDto)
|
|
227
|
+
Resolver(() => TransferOrderItemDto),
|
|
228
|
+
__param(0, Inject(MaterialEntity)),
|
|
229
|
+
__metadata("design:paramtypes", [Function])
|
|
216
230
|
], TransferOrderItemResolver);
|
|
217
231
|
|
|
218
232
|
export { TransferOrderItemResolver, TransferOrderResolver };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rytass/wms-module-graphql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Rytass WMS Module — GraphQL schema, resolvers and DTOs for warehouse management",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"rytass",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"@nestjs/apollo": ">=13.0.0 <13.2.0",
|
|
58
58
|
"@nestjs/common": "^11.0.0",
|
|
59
59
|
"@nestjs/graphql": "^13.0.0",
|
|
60
|
-
"@rytass/wms-module-core": "^0.
|
|
60
|
+
"@rytass/wms-module-core": "^0.4.0",
|
|
61
61
|
"graphql": "^16.0.0",
|
|
62
62
|
"reflect-metadata": "^0.1.13 || ^0.2.0",
|
|
63
63
|
"rxjs": "^7.8.0",
|