@things-factory/operato-hub 4.3.8 → 4.3.15

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.
@@ -8,6 +8,7 @@ const graphql_tag_1 = __importDefault(require("graphql-tag"));
8
8
  const typeorm_1 = require("typeorm");
9
9
  const api_1 = require("@things-factory/api");
10
10
  const biz_base_1 = require("@things-factory/biz-base");
11
+ const integration_base_1 = require("@things-factory/integration-base");
11
12
  const product_base_1 = require("@things-factory/product-base");
12
13
  const sales_base_1 = require("@things-factory/sales-base");
13
14
  const setting_base_1 = require("@things-factory/setting-base");
@@ -21,522 +22,560 @@ api_1.restfulApiRouter.post('/unstable/warehouse/:warehouseId/add-release-order'
21
22
  const { client, domain } = context.state;
22
23
  const { warehouseId: customerBizplaceId } = context.params;
23
24
  const { t } = context;
24
- if (!customerBizplaceId)
25
- context.throw(404, t('error.warehouse id not found'));
26
- let bodyReq = context.request.body;
27
- if (typeof bodyReq === undefined || !((_a = Object.keys(bodyReq)) === null || _a === void 0 ? void 0 : _a.length)) {
28
- context.throw(400, t('error.invalid body request format'));
29
- }
30
- debug('post:/add-release-order request.body', bodyReq);
31
- await checkMandatoryKey(context, bodyReq);
32
- const isAutoAssign = bodyReq.hasOwnProperty('isAutoAssign') ? bodyReq.isAutoAssign : true;
33
- // get customer company's bizplace
34
- const custCompanyBizplace = await (0, biz_base_1.getCompanyBizplace)(null, null, customerBizplaceId, tx);
35
- const customerBizplace = await tx.getRepository(biz_base_1.Bizplace).findOne({
36
- where: { id: customerBizplaceId }
37
- });
38
- let locationSortingRules = [];
39
- const inventoryAssignmentSetting = await tx.getRepository(setting_base_1.Setting).findOne({
40
- where: { domain, name: 'rule-for-inventory-assignment' }
41
- });
42
- if (inventoryAssignmentSetting) {
43
- let locationSetting = JSON.parse(inventoryAssignmentSetting.value);
44
- for (const key in locationSetting) {
45
- locationSortingRules.push({ name: key, desc: locationSetting[key] == 'ASC' ? false : true });
25
+ const bodyReq = context.request.body;
26
+ try {
27
+ if (!customerBizplaceId)
28
+ context.throw(404, t('error.warehouse id not found'));
29
+ if (typeof bodyReq === undefined || !((_a = Object.keys(bodyReq)) === null || _a === void 0 ? void 0 : _a.length)) {
30
+ context.throw(400, t('error.invalid body request format'));
46
31
  }
47
- }
48
- else {
49
- const pickingProductSetting = await tx.getRepository(setting_base_1.Setting).findOne({
50
- where: { domain, name: 'rule-for-picking-product' }
32
+ debug('post:/add-release-order request.body', bodyReq);
33
+ await checkMandatoryKey(context, bodyReq);
34
+ const isAutoAssign = bodyReq.hasOwnProperty('isAutoAssign') ? bodyReq.isAutoAssign : true;
35
+ const requiredDraft = bodyReq.hasOwnProperty('requiredDraft') ? bodyReq.requiredDraft : true;
36
+ // get customer company's bizplace
37
+ const custCompanyBizplace = await (0, biz_base_1.getCompanyBizplace)(null, null, customerBizplaceId, tx);
38
+ const customerBizplace = await tx.getRepository(biz_base_1.Bizplace).findOne({
39
+ where: { id: customerBizplaceId }
40
+ });
41
+ let locationSortingRules = [];
42
+ const inventoryAssignmentSetting = await tx.getRepository(setting_base_1.Setting).findOne({
43
+ where: { domain, name: 'rule-for-inventory-assignment' }
51
44
  });
52
- if (pickingProductSetting) {
53
- let locationSetting = JSON.parse(pickingProductSetting.value);
45
+ if (inventoryAssignmentSetting) {
46
+ let locationSetting = JSON.parse(inventoryAssignmentSetting.value);
54
47
  for (const key in locationSetting) {
55
48
  locationSortingRules.push({ name: key, desc: locationSetting[key] == 'ASC' ? false : true });
56
49
  }
57
50
  }
58
- }
59
- const orderInventories = bodyReq.orderInventories;
60
- let newOrderInventories = [];
61
- let bundleInfo = [];
62
- await Promise.all(orderInventories.map(async (orderInventory) => {
63
- var _a, _b;
64
- const sku = (_a = orderInventory.product) === null || _a === void 0 ? void 0 : _a.sku;
65
- const refCode = (_b = orderInventory.product) === null || _b === void 0 ? void 0 : _b.refCode;
66
- const packingType = orderInventory.packingType;
67
- const qb = tx
68
- .getRepository(product_base_1.ProductDetail)
69
- .createQueryBuilder('PD')
70
- .innerJoinAndSelect('PD.product', 'PROD')
71
- .where('PROD.bizplace_id = :bizplaceId', { bizplaceId: custCompanyBizplace.id });
72
- if (!sku && !refCode) {
73
- context.throw(404, t('error.sku or refCode not found'));
74
- }
75
- if (refCode) {
76
- qb.andWhere('PD.ref_code = :refCode', { refCode });
77
- }
78
- if (sku) {
79
- qb.andWhere('PROD.sku = :sku', { sku });
80
- }
81
- if (packingType) {
82
- qb.andWhere('PD.packing_type = :packingType', { packingType });
83
- }
84
- if (!packingType && !refCode) {
85
- qb.andWhere('PD.is_default = :isDefault', { isDefault: true });
86
- }
87
- const productDetail = await qb.getOne();
88
- if (productDetail) {
89
- let newOrderInventory = Object.assign({}, orderInventory);
90
- newOrderInventory.product.sku = productDetail.product.sku;
91
- newOrderInventory.product = productDetail.product;
92
- newOrderInventory.packingType = productDetail.packingType;
93
- newOrderInventory.uomValue = productDetail.uomValue;
94
- newOrderInventories.push(newOrderInventory);
51
+ else {
52
+ const pickingProductSetting = await tx.getRepository(setting_base_1.Setting).findOne({
53
+ where: { domain, name: 'rule-for-picking-product' }
54
+ });
55
+ if (pickingProductSetting) {
56
+ let locationSetting = JSON.parse(pickingProductSetting.value);
57
+ for (const key in locationSetting) {
58
+ locationSortingRules.push({ name: key, desc: locationSetting[key] == 'ASC' ? false : true });
59
+ }
60
+ }
95
61
  }
96
- if (!productDetail) {
62
+ const orderInventories = bodyReq.orderInventories;
63
+ let newOrderInventories = [];
64
+ let bundleInfo = [];
65
+ await Promise.all(orderInventories.map(async (orderInventory) => {
66
+ var _a, _b;
67
+ const sku = (_a = orderInventory.product) === null || _a === void 0 ? void 0 : _a.sku;
68
+ const refCode = (_b = orderInventory.product) === null || _b === void 0 ? void 0 : _b.refCode;
69
+ const packingType = orderInventory.packingType;
97
70
  const qb = tx
98
- .getRepository(product_base_1.ProductBundle)
99
- .createQueryBuilder('PB')
100
- .innerJoinAndSelect('PB.productBundleSettings', 'PBS')
101
- .innerJoinAndSelect('PBS.productDetail', 'PBD')
102
- .innerJoinAndSelect('PBD.product', 'PROD')
103
- .where('PB.bizplace_id = :bizplaceId', { bizplaceId: custCompanyBizplace.id });
71
+ .getRepository(product_base_1.ProductDetail)
72
+ .createQueryBuilder('PD')
73
+ .innerJoinAndSelect('PD.product', 'PROD')
74
+ .where('PROD.bizplace_id = :bizplaceId', { bizplaceId: custCompanyBizplace.id });
104
75
  if (!sku && !refCode) {
105
76
  context.throw(404, t('error.sku or refCode not found'));
106
77
  }
107
78
  if (refCode) {
108
- qb.andWhere('PB.ref_code = :refCode', { refCode });
79
+ qb.andWhere('PD.ref_code = :refCode', { refCode });
109
80
  }
110
81
  if (sku) {
111
- qb.andWhere('PB.sku = :sku', { sku });
82
+ qb.andWhere('PROD.sku = :sku', { sku });
112
83
  }
113
84
  if (packingType) {
114
- qb.andWhere('PB.packing_type = :packingType', { packingType });
85
+ qb.andWhere('PD.packing_type = :packingType', { packingType });
115
86
  }
116
- const foundProductBundle = await qb.getOne();
117
- if (foundProductBundle) {
118
- bundleInfo.push({
119
- productBundleId: foundProductBundle.id,
120
- sku: foundProductBundle.sku,
121
- releaseQty: orderInventory.releaseQty
122
- });
123
- const bundleProductSettings = foundProductBundle.productBundleSettings;
124
- bundleProductSettings.map(bundleProductSetting => {
125
- const productDetailBundle = bundleProductSetting.productDetail;
126
- let newOrderInventory = Object.assign({}, orderInventory);
127
- newOrderInventory.product.sku = productDetailBundle.product.sku;
128
- newOrderInventory.packingType = productDetailBundle.packingType;
129
- newOrderInventory.uomValue = productDetailBundle.uomValue;
130
- newOrderInventory.releaseQty = orderInventory.releaseQty * bundleProductSetting.bundleQty;
131
- newOrderInventory.product = productDetailBundle.product;
132
- newOrderInventories.push(newOrderInventory);
133
- });
87
+ if (!packingType && !refCode) {
88
+ qb.andWhere('PD.is_default = :isDefault', { isDefault: true });
134
89
  }
135
- else {
136
- if (sku && refCode) {
137
- context.throw(404, t(`error.sku ${sku} and refCode ${refCode} not exist in product / bundle master`));
138
- }
139
- if (sku) {
140
- context.throw(404, t(`error.sku ${sku} not exist in product / bundle master`));
90
+ const productDetail = await qb.getOne();
91
+ if (productDetail) {
92
+ let newOrderInventory = Object.assign({}, orderInventory);
93
+ newOrderInventory.product.sku = productDetail.product.sku;
94
+ newOrderInventory.product = productDetail.product;
95
+ newOrderInventory.packingType = productDetail.packingType;
96
+ newOrderInventory.uomValue = productDetail.uomValue;
97
+ newOrderInventories.push(newOrderInventory);
98
+ }
99
+ if (!productDetail) {
100
+ const qb = tx
101
+ .getRepository(product_base_1.ProductBundle)
102
+ .createQueryBuilder('PB')
103
+ .innerJoinAndSelect('PB.productBundleSettings', 'PBS')
104
+ .innerJoinAndSelect('PBS.productDetail', 'PBD')
105
+ .innerJoinAndSelect('PBD.product', 'PROD')
106
+ .where('PB.bizplace_id = :bizplaceId', { bizplaceId: custCompanyBizplace.id });
107
+ if (!sku && !refCode) {
108
+ context.throw(404, t('error.sku or refCode not found'));
141
109
  }
142
110
  if (refCode) {
143
- context.throw(404, t(`error.refCode ${refCode} not exist in product / bundle master`));
111
+ qb.andWhere('PB.ref_code = :refCode', { refCode });
144
112
  }
145
- }
146
- }
147
- }));
148
- let finalOrderInventories = [];
149
- // Case 1. Every order inventories has specified batch id
150
- if (newOrderInventories.every((orderInventory) => orderInventory.batchId)) {
151
- finalOrderInventories = await Promise.all(newOrderInventories.map(async (orderInventory) => {
152
- let filters = [
153
- {
154
- name: 'batchId',
155
- operator: 'eq',
156
- value: orderInventory.batchId
157
- },
158
- {
159
- name: 'productName',
160
- operator: 'eq',
161
- value: orderInventory.product.sku
162
- },
163
- {
164
- name: 'bizplace',
165
- operator: 'in',
166
- value: [customerBizplaceId]
113
+ if (sku) {
114
+ qb.andWhere('PB.sku = :sku', { sku });
167
115
  }
168
- ];
169
- let sortings = [];
170
- switch (orderInventory.product.pickingStrategy) {
171
- case 'FIFO':
172
- sortings.push({ name: 'created_at', desc: false });
173
- break;
174
- case 'LIFO':
175
- sortings.push({ name: 'created_at', desc: true });
176
- break;
177
- case 'FEFO':
178
- sortings.push({ name: 'expiration_date', desc: false });
179
- break;
180
- case 'FMFO':
181
- sortings.push({ name: 'manufacture_date', desc: false });
182
- break;
183
- }
184
- // 2. get all inventory data according to SKU and batchId
185
- const response = await client.query({
186
- query: (0, graphql_tag_1.default) `
187
- query inventoriesByPallet($filters: [Filter], $sortings: [Sorting], $locationSortingRules: [Sorting]) {
188
- inventoriesByPallet(
189
- filters: $filters
190
- sortings: $sortings
191
- locationSortingRules: $locationSortingRules
192
- ) {
193
- items {
194
- product {
195
- id
196
- name
197
- description
198
- }
199
- batchId
200
- packingType
201
- remainQty
202
- remainUomValue
116
+ if (packingType) {
117
+ qb.andWhere('PB.packing_type = :packingType', { packingType });
203
118
  }
204
- total
205
- }
206
- }
207
- `,
208
- variables: { filters, sortings, locationSortingRules },
209
- context: Object.assign(Object.assign({}, context), { state: Object.assign(Object.assign({}, context.state), { bizplace: customerBizplace, domain }) })
210
- });
211
- if (!response.errors) {
212
- const items = response.data.inventoriesByPallet.items || [];
213
- if (!(items === null || items === void 0 ? void 0 : items.length)) {
214
- context.body = {
215
- result: await createDraftOrder(client, customerBizplace, bodyReq, bundleInfo, domain, context, orderInventories, tx)
216
- };
217
- return;
119
+ const foundProductBundle = await qb.getOne();
120
+ if (foundProductBundle) {
121
+ bundleInfo.push({
122
+ productBundleId: foundProductBundle.id,
123
+ sku: foundProductBundle.sku,
124
+ releaseQty: orderInventory.releaseQty
125
+ });
126
+ const bundleProductSettings = foundProductBundle.productBundleSettings;
127
+ bundleProductSettings.map(bundleProductSetting => {
128
+ const productDetailBundle = bundleProductSetting.productDetail;
129
+ let newOrderInventory = Object.assign({}, orderInventory);
130
+ newOrderInventory.product.sku = productDetailBundle.product.sku;
131
+ newOrderInventory.packingType = productDetailBundle.packingType;
132
+ newOrderInventory.uomValue = productDetailBundle.uomValue;
133
+ newOrderInventory.releaseQty = orderInventory.releaseQty * bundleProductSetting.bundleQty;
134
+ newOrderInventory.product = productDetailBundle.product;
135
+ newOrderInventories.push(newOrderInventory);
136
+ });
218
137
  }
219
- items.forEach(async (item) => {
220
- if (orderInventory.releaseQty > item.remainQty || orderInventory.releaseQty <= 0) {
221
- context.body = {
222
- result: await createDraftOrder(client, customerBizplace, bodyReq, bundleInfo, domain, context, orderInventories, tx)
223
- };
224
- return;
138
+ else {
139
+ if (sku && refCode) {
140
+ context.throw(404, t(`error.sku ${sku} and refCode ${refCode} not exist in product / bundle master`));
141
+ }
142
+ if (sku) {
143
+ context.throw(404, t(`error.sku ${sku} not exist in product / bundle master`));
144
+ }
145
+ if (refCode) {
146
+ context.throw(404, t(`error.refCode ${refCode} not exist in product / bundle master`));
225
147
  }
226
- // 3. add more information to orderInventory
227
- orderInventory.product.id = item.product.id;
228
- orderInventory.packingType = item.packingType;
229
- orderInventory.batchId = item.batchId;
230
- orderInventory.type = sales_base_1.ORDER_TYPES.RELEASE_OF_GOODS;
231
- orderInventory.releaseUomValue = orderInventory.releaseQty * orderInventory.uomValue;
232
- orderInventory.uom = item.uom;
233
- });
234
- return orderInventory;
235
- }
236
- else {
237
- context.body = {
238
- result: await createDraftOrder(client, customerBizplace, bodyReq, bundleInfo, domain, context, orderInventories, tx)
239
- };
240
- return;
241
- }
242
- }));
243
- }
244
- else {
245
- // Case 2. Some of order inventories doesn't have specified batch id
246
- // MMS order doesn't have batch ID field.
247
- // To cover this case first result of found inventory will be a target of RO
248
- // To combine items from different bundles
249
- newOrderInventories = combineItems(newOrderInventories);
250
- for (let i = 0; i < newOrderInventories.length; i++) {
251
- const orderInventory = newOrderInventories[i];
252
- const { product, packingType } = orderInventory;
253
- const pickingStrategy = product.pickingStrategy;
254
- if (isAutoAssign) {
255
- let qb = tx.getRepository(warehouse_base_1.Inventory).createQueryBuilder('iv');
256
- qb.leftJoinAndSelect('iv.location', 'loc')
257
- .andWhere('"iv"."domain_id" = :domainId')
258
- .andWhere('"iv"."bizplace_id" = :bizplaceId')
259
- .andWhere('"iv"."packing_type" = :packingType')
260
- .andWhere('"iv"."product_id" = :productId')
261
- .andWhere('"iv"."status" = :status')
262
- .andWhere('"loc"."type" NOT IN (:...locationTypes)')
263
- .setParameters({
264
- domainId: domain.id,
265
- bizplaceId: customerBizplace.id,
266
- packingType: packingType,
267
- productId: product.id,
268
- status: warehouse_base_1.INVENTORY_STATUS.STORED,
269
- locationTypes: [warehouse_base_1.LOCATION_TYPE.QUARANTINE, warehouse_base_1.LOCATION_TYPE.RESERVE]
270
- });
271
- switch (pickingStrategy) {
272
- case 'FIFO':
273
- qb.orderBy('"iv"."created_at"', 'ASC');
274
- if ((locationSortingRules === null || locationSortingRules === void 0 ? void 0 : locationSortingRules.length) > 0) {
275
- locationSortingRules.forEach((rule, idx) => {
276
- qb.addOrderBy(`loc.${rule.name}`, rule.desc ? 'DESC' : 'ASC');
277
- });
278
- }
279
- break;
280
- case 'LIFO':
281
- qb.orderBy('"iv"."created_at"', 'DESC');
282
- if ((locationSortingRules === null || locationSortingRules === void 0 ? void 0 : locationSortingRules.length) > 0) {
283
- locationSortingRules.forEach((rule, idx) => {
284
- qb.addOrderBy(`loc.${rule.name}`, rule.desc ? 'DESC' : 'ASC');
285
- });
286
- }
287
- break;
288
- case 'FEFO':
289
- qb.orderBy('"iv"."expiration_date"', 'ASC');
290
- if ((locationSortingRules === null || locationSortingRules === void 0 ? void 0 : locationSortingRules.length) > 0) {
291
- locationSortingRules.forEach((rule, idx) => {
292
- qb.addOrderBy(`loc.${rule.name}`, rule.desc ? 'DESC' : 'ASC');
293
- });
294
- }
295
- break;
296
- case 'FMFO':
297
- qb.orderBy('"iv"."manufacture_date"', 'ASC');
298
- if ((locationSortingRules === null || locationSortingRules === void 0 ? void 0 : locationSortingRules.length) > 0) {
299
- locationSortingRules.forEach((rule, idx) => {
300
- qb.addOrderBy(`loc.${rule.name}`, rule.desc ? 'DESC' : 'ASC');
301
- });
302
- }
303
- break;
304
- case 'LOCATION':
305
- if ((locationSortingRules === null || locationSortingRules === void 0 ? void 0 : locationSortingRules.length) > 0) {
306
- locationSortingRules.forEach((rule, idx) => {
307
- idx === 0
308
- ? qb.orderBy(`loc.${rule.name}`, rule.desc ? 'DESC' : 'ASC')
309
- : qb.addOrderBy(`loc.${rule.name}`, rule.desc ? 'DESC' : 'ASC');
310
- });
311
- }
312
- else {
313
- qb.orderBy('"loc"."name"', 'DESC');
314
- }
315
- break;
316
- }
317
- let inventories = await qb.getMany();
318
- if (!(inventories === null || inventories === void 0 ? void 0 : inventories.length)) {
319
- context.body = {
320
- result: await createDraftOrder(client, customerBizplace, bodyReq, bundleInfo, domain, context, orderInventories, tx)
321
- };
322
- return;
323
- }
324
- inventories = inventories
325
- .map(inventory => {
326
- return Object.assign(Object.assign({}, inventory), { remainQty: inventory.qty - inventory.lockedQty, remainUomValue: inventory.uomValue - inventory.lockedUomValue });
327
- })
328
- .filter(inventory => inventory.remainQty > 0);
329
- let targetInventories;
330
- try {
331
- targetInventories = _composeTargetInventories(context, product, orderInventory, inventories);
332
- }
333
- catch (e) {
334
- context.body = {
335
- result: await createDraftOrder(client, customerBizplace, bodyReq, bundleInfo, domain, context, orderInventories, tx)
336
- };
337
- return;
338
148
  }
339
- targetInventories.map(item => {
340
- finalOrderInventories.push(item.targetInventory);
341
- });
342
149
  }
343
- else {
150
+ }));
151
+ let finalOrderInventories = [];
152
+ // Case 1. Every order inventories has specified batch id
153
+ if (newOrderInventories.every((orderInventory) => orderInventory.batchId)) {
154
+ finalOrderInventories = await Promise.all(newOrderInventories.map(async (orderInventory) => {
344
155
  let filters = [
156
+ {
157
+ name: 'batchId',
158
+ operator: 'eq',
159
+ value: orderInventory.batchId
160
+ },
345
161
  {
346
162
  name: 'productName',
347
163
  operator: 'eq',
348
164
  value: orderInventory.product.sku
349
165
  },
350
166
  {
351
- name: 'bizplace_id',
352
- operator: 'eq',
353
- value: customerBizplaceId
167
+ name: 'bizplace',
168
+ operator: 'in',
169
+ value: [customerBizplaceId]
354
170
  }
355
171
  ];
172
+ let sortings = [];
173
+ switch (orderInventory.product.pickingStrategy) {
174
+ case 'FIFO':
175
+ sortings.push({ name: 'created_at', desc: false });
176
+ break;
177
+ case 'LIFO':
178
+ sortings.push({ name: 'created_at', desc: true });
179
+ break;
180
+ case 'FEFO':
181
+ sortings.push({ name: 'expiration_date', desc: false });
182
+ break;
183
+ case 'FMFO':
184
+ sortings.push({ name: 'manufacture_date', desc: false });
185
+ break;
186
+ }
356
187
  // 2. get all inventory data according to SKU and batchId
357
188
  const response = await client.query({
358
189
  query: (0, graphql_tag_1.default) `
359
- query inventoryProductGroup($filters: [Filter]) {
360
- inventoryProductGroup(filters: $filters) {
361
- items {
362
- productId
363
- productSKU
364
- productName
365
- batchId
366
- packingType
367
- remainQty
368
- remainUomValue
190
+ query inventoriesByPallet(
191
+ $filters: [Filter]
192
+ $sortings: [Sorting]
193
+ $locationSortingRules: [Sorting]
194
+ ) {
195
+ inventoriesByPallet(
196
+ filters: $filters
197
+ sortings: $sortings
198
+ locationSortingRules: $locationSortingRules
199
+ ) {
200
+ items {
201
+ product {
202
+ id
203
+ name
204
+ description
205
+ }
206
+ batchId
207
+ packingType
208
+ remainQty
209
+ remainUomValue
210
+ }
211
+ total
369
212
  }
370
- total
371
213
  }
372
- }
373
- `,
374
- variables: { filters },
214
+ `,
215
+ variables: { filters, sortings, locationSortingRules },
375
216
  context: Object.assign(Object.assign({}, context), { state: Object.assign(Object.assign({}, context.state), { bizplace: customerBizplace, domain }) })
376
217
  });
377
218
  if (!response.errors) {
378
- const items = response.data.inventoryProductGroup.items || [];
379
- if (!(items === null || items === void 0 ? void 0 : items.length)) {
380
- context.body = {
381
- result: await createDraftOrder(client, customerBizplace, bodyReq, bundleInfo, domain, context, orderInventories, tx)
382
- };
383
- return;
384
- }
385
- items.forEach(async (item) => {
386
- if (orderInventory.releaseQty > item.remainQty || orderInventory.releaseQty <= 0) {
219
+ const items = response.data.inventoriesByPallet.items || [];
220
+ if (requiredDraft) {
221
+ if (!(items === null || items === void 0 ? void 0 : items.length)) {
387
222
  context.body = {
388
223
  result: await createDraftOrder(client, customerBizplace, bodyReq, bundleInfo, domain, context, orderInventories, tx)
389
224
  };
390
225
  return;
391
226
  }
227
+ }
228
+ items.forEach(async (item) => {
229
+ if (requiredDraft) {
230
+ if (orderInventory.releaseQty > item.remainQty || orderInventory.releaseQty <= 0) {
231
+ context.body = {
232
+ result: await createDraftOrder(client, customerBizplace, bodyReq, bundleInfo, domain, context, orderInventories, tx)
233
+ };
234
+ return;
235
+ }
236
+ }
392
237
  // 3. add more information to orderInventory
393
- orderInventory.product = { id: item.productId };
238
+ orderInventory.product.id = item.product.id;
394
239
  orderInventory.packingType = item.packingType;
395
240
  orderInventory.batchId = item.batchId;
396
241
  orderInventory.type = sales_base_1.ORDER_TYPES.RELEASE_OF_GOODS;
397
242
  orderInventory.releaseUomValue = orderInventory.releaseQty * orderInventory.uomValue;
398
243
  orderInventory.uom = item.uom;
399
244
  });
400
- delete orderInventory.uomValue;
401
- finalOrderInventories.push(orderInventory);
245
+ return orderInventory;
402
246
  }
403
247
  else {
404
- context.body = {
405
- result: await createDraftOrder(client, customerBizplace, bodyReq, bundleInfo, domain, context, orderInventories, tx)
406
- };
407
- return;
248
+ if (requiredDraft) {
249
+ context.body = {
250
+ result: await createDraftOrder(client, customerBizplace, bodyReq, bundleInfo, domain, context, orderInventories, tx)
251
+ };
252
+ return;
253
+ }
408
254
  }
409
- }
255
+ }));
410
256
  }
411
- }
412
- context.body = {
413
- result: (await client.mutate({
414
- mutation: (0, graphql_tag_1.default) `
415
- mutation addReleaseGood($releaseGood: NewReleaseGood, $shippingOrder: ShippingOrderPatch, $file: Upload) {
416
- addReleaseGood(releaseGood: $releaseGood, shippingOrder: $shippingOrder, file: $file) {
417
- id
418
- name
419
- refNo
420
- status
421
- truckNo
422
- ownTransport
423
- crossDocking
424
- marketplaceOrderStatus
425
- billingAddress
426
- deliveryAddress1
427
- deliveryAddress2
428
- deliveryAddress3
429
- deliveryAddress4
430
- deliveryAddress5
431
- attentionTo
432
- attentionCompany
433
- city
434
- state
435
- postalCode
436
- country
437
- phone1
438
- phone2
439
- email
440
- transporter
441
- trackingNo
442
- airwayBill
443
- invoice
444
- type
445
- storeName
446
- storeId
447
- routeId
448
- stopId
449
- arrivalNotice {
450
- name
257
+ else {
258
+ // Case 2. Some of order inventories doesn't have specified batch id
259
+ // MMS order doesn't have batch ID field.
260
+ // To cover this case first result of found inventory will be a target of RO
261
+ // To combine items from different bundles
262
+ newOrderInventories = combineItems(newOrderInventories);
263
+ for (let i = 0; i < newOrderInventories.length; i++) {
264
+ const orderInventory = newOrderInventories[i];
265
+ const { product, packingType } = orderInventory;
266
+ const pickingStrategy = product.pickingStrategy;
267
+ if (isAutoAssign) {
268
+ let qb = tx.getRepository(warehouse_base_1.Inventory).createQueryBuilder('iv');
269
+ qb.leftJoinAndSelect('iv.location', 'loc')
270
+ .andWhere('"iv"."domain_id" = :domainId')
271
+ .andWhere('"iv"."bizplace_id" = :bizplaceId')
272
+ .andWhere('"iv"."packing_type" = :packingType')
273
+ .andWhere('"iv"."product_id" = :productId')
274
+ .andWhere('"iv"."status" = :status')
275
+ .andWhere('"loc"."type" NOT IN (:...locationTypes)')
276
+ .setParameters({
277
+ domainId: domain.id,
278
+ bizplaceId: customerBizplace.id,
279
+ packingType: packingType,
280
+ productId: product.id,
281
+ status: warehouse_base_1.INVENTORY_STATUS.STORED,
282
+ locationTypes: [warehouse_base_1.LOCATION_TYPE.QUARANTINE, warehouse_base_1.LOCATION_TYPE.RESERVE]
283
+ });
284
+ switch (pickingStrategy) {
285
+ case 'FIFO':
286
+ qb.orderBy('"iv"."created_at"', 'ASC');
287
+ if ((locationSortingRules === null || locationSortingRules === void 0 ? void 0 : locationSortingRules.length) > 0) {
288
+ locationSortingRules.forEach((rule, idx) => {
289
+ qb.addOrderBy(`loc.${rule.name}`, rule.desc ? 'DESC' : 'ASC');
290
+ });
291
+ }
292
+ break;
293
+ case 'LIFO':
294
+ qb.orderBy('"iv"."created_at"', 'DESC');
295
+ if ((locationSortingRules === null || locationSortingRules === void 0 ? void 0 : locationSortingRules.length) > 0) {
296
+ locationSortingRules.forEach((rule, idx) => {
297
+ qb.addOrderBy(`loc.${rule.name}`, rule.desc ? 'DESC' : 'ASC');
298
+ });
299
+ }
300
+ break;
301
+ case 'FEFO':
302
+ qb.orderBy('"iv"."expiration_date"', 'ASC');
303
+ if ((locationSortingRules === null || locationSortingRules === void 0 ? void 0 : locationSortingRules.length) > 0) {
304
+ locationSortingRules.forEach((rule, idx) => {
305
+ qb.addOrderBy(`loc.${rule.name}`, rule.desc ? 'DESC' : 'ASC');
306
+ });
307
+ }
308
+ break;
309
+ case 'FMFO':
310
+ qb.orderBy('"iv"."manufacture_date"', 'ASC');
311
+ if ((locationSortingRules === null || locationSortingRules === void 0 ? void 0 : locationSortingRules.length) > 0) {
312
+ locationSortingRules.forEach((rule, idx) => {
313
+ qb.addOrderBy(`loc.${rule.name}`, rule.desc ? 'DESC' : 'ASC');
314
+ });
315
+ }
316
+ break;
317
+ case 'LOCATION':
318
+ if ((locationSortingRules === null || locationSortingRules === void 0 ? void 0 : locationSortingRules.length) > 0) {
319
+ locationSortingRules.forEach((rule, idx) => {
320
+ idx === 0
321
+ ? qb.orderBy(`loc.${rule.name}`, rule.desc ? 'DESC' : 'ASC')
322
+ : qb.addOrderBy(`loc.${rule.name}`, rule.desc ? 'DESC' : 'ASC');
323
+ });
324
+ }
325
+ else {
326
+ qb.orderBy('"loc"."name"', 'DESC');
327
+ }
328
+ break;
329
+ }
330
+ let inventories = await qb.getMany();
331
+ if (requiredDraft) {
332
+ if (!(inventories === null || inventories === void 0 ? void 0 : inventories.length)) {
333
+ context.body = {
334
+ result: await createDraftOrder(client, customerBizplace, bodyReq, bundleInfo, domain, context, orderInventories, tx)
335
+ };
336
+ return;
337
+ }
338
+ }
339
+ inventories = inventories
340
+ .map(inventory => {
341
+ return Object.assign(Object.assign({}, inventory), { remainQty: inventory.qty - inventory.lockedQty, remainUomValue: inventory.uomValue - inventory.lockedUomValue });
342
+ })
343
+ .filter(inventory => inventory.remainQty > 0);
344
+ let targetInventories;
345
+ try {
346
+ targetInventories = _composeTargetInventories(context, product, orderInventory, inventories);
347
+ }
348
+ catch (e) {
349
+ if (requiredDraft) {
350
+ context.body = {
351
+ result: await createDraftOrder(client, customerBizplace, bodyReq, bundleInfo, domain, context, orderInventories, tx)
352
+ };
353
+ return;
354
+ }
355
+ else {
356
+ targetInventories = _composeTargetInventories(context, product, orderInventory, inventories);
357
+ }
358
+ }
359
+ if (targetInventories === null || targetInventories === void 0 ? void 0 : targetInventories.length) {
360
+ context.throw(404, t(`error.no inventories found`));
361
+ }
362
+ targetInventories.map(item => {
363
+ finalOrderInventories.push(item.targetInventory);
364
+ });
365
+ }
366
+ else {
367
+ let filters = [
368
+ {
369
+ name: 'productName',
370
+ operator: 'eq',
371
+ value: orderInventory.product.sku
372
+ },
373
+ {
374
+ name: 'bizplace_id',
375
+ operator: 'eq',
376
+ value: customerBizplaceId
377
+ }
378
+ ];
379
+ // 2. get all inventory data according to SKU and batchId
380
+ const response = await client.query({
381
+ query: (0, graphql_tag_1.default) `
382
+ query inventoryProductGroup($filters: [Filter]) {
383
+ inventoryProductGroup(filters: $filters) {
384
+ items {
385
+ productId
386
+ productSKU
387
+ productName
388
+ batchId
389
+ packingType
390
+ remainQty
391
+ remainUomValue
392
+ }
393
+ total
394
+ }
451
395
  }
452
- exportOption
453
- releaseDate
454
- collectionOrderNo
455
- bizplace {
396
+ `,
397
+ variables: { filters },
398
+ context: Object.assign(Object.assign({}, context), { state: Object.assign(Object.assign({}, context.state), { bizplace: customerBizplace, domain }) })
399
+ });
400
+ if (!response.errors) {
401
+ const items = response.data.inventoryProductGroup.items || [];
402
+ if (requiredDraft) {
403
+ if (!(items === null || items === void 0 ? void 0 : items.length)) {
404
+ context.body = {
405
+ result: await createDraftOrder(client, customerBizplace, bodyReq, bundleInfo, domain, context, orderInventories, tx)
406
+ };
407
+ return;
408
+ }
409
+ }
410
+ items.forEach(async (item) => {
411
+ if (requiredDraft) {
412
+ if (orderInventory.releaseQty > item.remainQty || orderInventory.releaseQty <= 0) {
413
+ context.body = {
414
+ result: await createDraftOrder(client, customerBizplace, bodyReq, bundleInfo, domain, context, orderInventories, tx)
415
+ };
416
+ return;
417
+ }
418
+ }
419
+ // 3. add more information to orderInventory
420
+ orderInventory.product = { id: item.productId };
421
+ orderInventory.packingType = item.packingType;
422
+ orderInventory.batchId = item.batchId;
423
+ orderInventory.type = sales_base_1.ORDER_TYPES.RELEASE_OF_GOODS;
424
+ orderInventory.releaseUomValue = orderInventory.releaseQty * orderInventory.uomValue;
425
+ orderInventory.uom = item.uom;
426
+ });
427
+ delete orderInventory.uomValue;
428
+ finalOrderInventories.push(orderInventory);
429
+ }
430
+ else {
431
+ if (requiredDraft) {
432
+ context.body = {
433
+ result: await createDraftOrder(client, customerBizplace, bodyReq, bundleInfo, domain, context, orderInventories, tx)
434
+ };
435
+ return;
436
+ }
437
+ }
438
+ }
439
+ }
440
+ }
441
+ context.body = {
442
+ result: (await client.mutate({
443
+ mutation: (0, graphql_tag_1.default) `
444
+ mutation addReleaseGood(
445
+ $releaseGood: NewReleaseGood
446
+ $shippingOrder: ShippingOrderPatch
447
+ $file: Upload
448
+ ) {
449
+ addReleaseGood(releaseGood: $releaseGood, shippingOrder: $shippingOrder, file: $file) {
450
+ id
456
451
  name
457
- }
458
- orderInventories {
459
- product {
460
- sku
452
+ refNo
453
+ status
454
+ truckNo
455
+ ownTransport
456
+ crossDocking
457
+ marketplaceOrderStatus
458
+ billingAddress
459
+ deliveryAddress1
460
+ deliveryAddress2
461
+ deliveryAddress3
462
+ deliveryAddress4
463
+ deliveryAddress5
464
+ attentionTo
465
+ attentionCompany
466
+ city
467
+ state
468
+ postalCode
469
+ country
470
+ phone1
471
+ phone2
472
+ email
473
+ transporter
474
+ trackingNo
475
+ airwayBill
476
+ invoice
477
+ type
478
+ storeName
479
+ storeId
480
+ routeId
481
+ stopId
482
+ arrivalNotice {
461
483
  name
462
- description
463
484
  }
464
- batchId
465
- packingType
466
- packingSize
467
- releaseQty
468
- releaseUomValue
469
- }
470
- orderVass {
471
- vas {
485
+ exportOption
486
+ releaseDate
487
+ collectionOrderNo
488
+ bizplace {
472
489
  name
473
- operationGuide
474
- operationGuideType
475
490
  }
476
- set
477
- targetType
478
- targetBatchId
479
- targetProduct {
480
- name
491
+ orderInventories {
492
+ product {
493
+ sku
494
+ name
495
+ description
496
+ }
497
+ batchId
498
+ packingType
499
+ packingSize
500
+ releaseQty
501
+ releaseUomValue
502
+ }
503
+ orderVass {
504
+ vas {
505
+ name
506
+ operationGuide
507
+ operationGuideType
508
+ }
509
+ set
510
+ targetType
511
+ targetBatchId
512
+ targetProduct {
513
+ name
514
+ description
515
+ }
516
+ packingType
517
+ qty
518
+ uomValue
519
+ otherTarget
481
520
  description
521
+ remark
522
+ status
523
+ operationGuide
482
524
  }
483
- packingType
484
- qty
485
- uomValue
486
- otherTarget
487
- description
488
- remark
489
- status
490
- operationGuide
491
525
  }
492
526
  }
493
- }
494
- `,
495
- variables: {
496
- releaseGood: {
497
- customerBizplaceId: customerBizplace.id,
498
- courierOption: bodyReq.courierOption,
499
- collectionOrderNo: bodyReq.collectionOrderNo,
500
- exportOption: bodyReq.exportOption,
501
- orderInventories: finalOrderInventories,
502
- ownTransport: bodyReq.ownTransport,
503
- packingOption: bodyReq.packingOption,
504
- refNo: bodyReq.refNo,
505
- refNo2: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.refNo2,
506
- releaseDate: bodyReq.releaseDate,
507
- type: bodyReq.type,
508
- marketplaceOrderStatus: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.marketplaceOrderStatus,
509
- remark: (bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.remark) || null,
510
- billingAddress: ((_b = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.billTo) === null || _b === void 0 ? void 0 : _b.billingAddress) || null,
511
- deliveryAddress1: ((_c = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _c === void 0 ? void 0 : _c.deliveryAddress1) || null,
512
- deliveryAddress2: ((_d = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _d === void 0 ? void 0 : _d.deliveryAddress2) || null,
513
- deliveryAddress3: ((_e = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _e === void 0 ? void 0 : _e.deliveryAddress3) || null,
514
- deliveryAddress4: ((_f = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _f === void 0 ? void 0 : _f.deliveryAddress4) || null,
515
- deliveryAddress5: ((_g = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _g === void 0 ? void 0 : _g.deliveryAddress5) || null,
516
- attentionTo: ((_h = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _h === void 0 ? void 0 : _h.attentionTo) || null,
517
- attentionCompany: ((_j = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _j === void 0 ? void 0 : _j.attentionCompany) || null,
518
- city: ((_k = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _k === void 0 ? void 0 : _k.city) || null,
519
- state: ((_l = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _l === void 0 ? void 0 : _l.state) || null,
520
- postalCode: ((_m = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _m === void 0 ? void 0 : _m.postalCode) || null,
521
- country: ((_o = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _o === void 0 ? void 0 : _o.country) || null,
522
- phone1: ((_p = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _p === void 0 ? void 0 : _p.phone1) || null,
523
- phone2: ((_q = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _q === void 0 ? void 0 : _q.phone2) || null,
524
- email: ((_r = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _r === void 0 ? void 0 : _r.email) || null,
525
- transporter: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.transporter,
526
- trackingNo: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.trackingNo,
527
- airwayBill: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.airwayBill,
528
- invoice: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.invoice,
529
- bundleInfo: JSON.stringify(bundleInfo),
530
- storeName: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.storeName,
531
- storeId: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.storeId,
532
- routeId: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.routeId,
533
- stopId: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.stopId
534
- }
535
- },
536
- context: Object.assign(Object.assign({}, context), { hasUpload: true, state: Object.assign(Object.assign({}, context.state), { customerBizplace,
537
- domain, type: 'api' }) })
538
- })).data
539
- };
527
+ `,
528
+ variables: {
529
+ releaseGood: {
530
+ customerBizplaceId: customerBizplace.id,
531
+ courierOption: bodyReq.courierOption,
532
+ collectionOrderNo: bodyReq.collectionOrderNo,
533
+ exportOption: bodyReq.exportOption,
534
+ orderInventories: finalOrderInventories,
535
+ ownTransport: bodyReq.ownTransport,
536
+ packingOption: bodyReq.packingOption,
537
+ refNo: bodyReq.refNo,
538
+ refNo2: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.refNo2,
539
+ releaseDate: bodyReq.releaseDate,
540
+ type: bodyReq.type,
541
+ marketplaceOrderStatus: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.marketplaceOrderStatus,
542
+ remark: (bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.remark) || null,
543
+ billingAddress: ((_b = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.billTo) === null || _b === void 0 ? void 0 : _b.billingAddress) || null,
544
+ deliveryAddress1: ((_c = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _c === void 0 ? void 0 : _c.deliveryAddress1) || null,
545
+ deliveryAddress2: ((_d = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _d === void 0 ? void 0 : _d.deliveryAddress2) || null,
546
+ deliveryAddress3: ((_e = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _e === void 0 ? void 0 : _e.deliveryAddress3) || null,
547
+ deliveryAddress4: ((_f = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _f === void 0 ? void 0 : _f.deliveryAddress4) || null,
548
+ deliveryAddress5: ((_g = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _g === void 0 ? void 0 : _g.deliveryAddress5) || null,
549
+ attentionTo: ((_h = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _h === void 0 ? void 0 : _h.attentionTo) || null,
550
+ attentionCompany: ((_j = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _j === void 0 ? void 0 : _j.attentionCompany) || null,
551
+ city: ((_k = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _k === void 0 ? void 0 : _k.city) || null,
552
+ state: ((_l = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _l === void 0 ? void 0 : _l.state) || null,
553
+ postalCode: ((_m = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _m === void 0 ? void 0 : _m.postalCode) || null,
554
+ country: ((_o = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _o === void 0 ? void 0 : _o.country) || null,
555
+ phone1: ((_p = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _p === void 0 ? void 0 : _p.phone1) || null,
556
+ phone2: ((_q = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _q === void 0 ? void 0 : _q.phone2) || null,
557
+ email: ((_r = bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.deliverTo) === null || _r === void 0 ? void 0 : _r.email) || null,
558
+ transporter: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.transporter,
559
+ trackingNo: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.trackingNo,
560
+ airwayBill: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.airwayBill,
561
+ invoice: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.invoice,
562
+ bundleInfo: JSON.stringify(bundleInfo),
563
+ storeName: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.storeName,
564
+ storeId: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.storeId,
565
+ routeId: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.routeId,
566
+ stopId: bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.stopId
567
+ }
568
+ },
569
+ context: Object.assign(Object.assign({}, context), { hasUpload: true, state: Object.assign(Object.assign({}, context.state), { customerBizplace,
570
+ domain, type: 'api' }) })
571
+ })).data
572
+ };
573
+ (0, integration_base_1.createPayloadLog)(customerBizplaceId, '/unstable/warehouse/:warehouseId/add-release-order', bodyReq, context.body, context, integration_base_1.PayloadType.INGESTION);
574
+ }
575
+ catch (error) {
576
+ (0, integration_base_1.createPayloadLog)(customerBizplaceId, '/unstable/warehouse/:warehouseId/add-release-order', bodyReq, error, context, integration_base_1.PayloadType.INGESTION);
577
+ throw error;
578
+ }
540
579
  });
541
580
  });
542
581
  async function checkMandatoryKey(context, params) {