@things-factory/worksheet-base 5.0.0-alpha.50 → 5.0.0-alpha.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/dist-server/controllers/ecommerce/sellercraft-controller.js +15 -7
  2. package/dist-server/controllers/ecommerce/sellercraft-controller.js.map +1 -1
  3. package/dist-server/controllers/inbound/putaway-worksheet-controller.js +22 -13
  4. package/dist-server/controllers/inbound/putaway-worksheet-controller.js.map +1 -1
  5. package/dist-server/controllers/inbound/unloading-worksheet-controller.js +1 -1
  6. package/dist-server/controllers/inbound/unloading-worksheet-controller.js.map +1 -1
  7. package/dist-server/controllers/outbound/loading-worksheet-controller.js +47 -10
  8. package/dist-server/controllers/outbound/loading-worksheet-controller.js.map +1 -1
  9. package/dist-server/controllers/outbound/picking-worksheet-controller.js +148 -7
  10. package/dist-server/controllers/outbound/picking-worksheet-controller.js.map +1 -1
  11. package/dist-server/controllers/outbound/sorting-worksheet-controller.js +116 -20
  12. package/dist-server/controllers/outbound/sorting-worksheet-controller.js.map +1 -1
  13. package/dist-server/controllers/render-grn.js +35 -27
  14. package/dist-server/controllers/render-grn.js.map +1 -1
  15. package/dist-server/controllers/render-manifest.js +12 -5
  16. package/dist-server/controllers/render-manifest.js.map +1 -1
  17. package/dist-server/controllers/worksheet-controller.js +8 -1
  18. package/dist-server/controllers/worksheet-controller.js.map +1 -1
  19. package/dist-server/entities/index.js +2 -1
  20. package/dist-server/entities/index.js.map +1 -1
  21. package/dist-server/entities/warehouse-bizplace-onhand-inventory.js +174 -0
  22. package/dist-server/entities/warehouse-bizplace-onhand-inventory.js.map +1 -0
  23. package/dist-server/graphql/resolvers/worksheet/batch-picking-worksheet.js +14 -1
  24. package/dist-server/graphql/resolvers/worksheet/batch-picking-worksheet.js.map +1 -1
  25. package/dist-server/graphql/resolvers/worksheet/cancel-draft-release-order.js +17 -0
  26. package/dist-server/graphql/resolvers/worksheet/cancel-draft-release-order.js.map +1 -0
  27. package/dist-server/graphql/resolvers/worksheet/cycle-count-adjustment.js +2 -1
  28. package/dist-server/graphql/resolvers/worksheet/cycle-count-adjustment.js.map +1 -1
  29. package/dist-server/graphql/resolvers/worksheet/index.js +2 -1
  30. package/dist-server/graphql/resolvers/worksheet/index.js.map +1 -1
  31. package/dist-server/graphql/resolvers/worksheet/loading/complete-loading.js +40 -18
  32. package/dist-server/graphql/resolvers/worksheet/loading/complete-loading.js.map +1 -1
  33. package/dist-server/graphql/resolvers/worksheet/loading/loading.js +3 -10
  34. package/dist-server/graphql/resolvers/worksheet/loading/loading.js.map +1 -1
  35. package/dist-server/graphql/resolvers/worksheet/loading-worksheet.js +55 -21
  36. package/dist-server/graphql/resolvers/worksheet/loading-worksheet.js.map +1 -1
  37. package/dist-server/graphql/resolvers/worksheet/packing-worksheet.js +1 -0
  38. package/dist-server/graphql/resolvers/worksheet/packing-worksheet.js.map +1 -1
  39. package/dist-server/graphql/resolvers/worksheet/palletizing-pallets.js +2 -5
  40. package/dist-server/graphql/resolvers/worksheet/palletizing-pallets.js.map +1 -1
  41. package/dist-server/graphql/resolvers/worksheet/picking/complete-batch-picking.js +1 -1
  42. package/dist-server/graphql/resolvers/worksheet/picking/complete-batch-picking.js.map +1 -1
  43. package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js +8 -6
  44. package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js.map +1 -1
  45. package/dist-server/graphql/resolvers/worksheet/picking/index.js +2 -1
  46. package/dist-server/graphql/resolvers/worksheet/picking/index.js.map +1 -1
  47. package/dist-server/graphql/resolvers/worksheet/picking/picking.js +4 -4
  48. package/dist-server/graphql/resolvers/worksheet/picking/picking.js.map +1 -1
  49. package/dist-server/graphql/resolvers/worksheet/picking/scan-product-picking.js +4 -4
  50. package/dist-server/graphql/resolvers/worksheet/picking/scan-product-picking.js.map +1 -1
  51. package/dist-server/graphql/resolvers/worksheet/picking/seal-tote.js +15 -0
  52. package/dist-server/graphql/resolvers/worksheet/picking/seal-tote.js.map +1 -0
  53. package/dist-server/graphql/resolvers/worksheet/picking-worksheet.js +10 -1
  54. package/dist-server/graphql/resolvers/worksheet/picking-worksheet.js.map +1 -1
  55. package/dist-server/graphql/resolvers/worksheet/putaway/complete-putaway.js +36 -0
  56. package/dist-server/graphql/resolvers/worksheet/putaway/complete-putaway.js.map +1 -1
  57. package/dist-server/graphql/resolvers/worksheet/sorting/complete-order-sorting.js +11 -6
  58. package/dist-server/graphql/resolvers/worksheet/sorting/complete-order-sorting.js.map +1 -1
  59. package/dist-server/graphql/resolvers/worksheet/sorting/scan-product-sorting.js +4 -4
  60. package/dist-server/graphql/resolvers/worksheet/sorting/scan-product-sorting.js.map +1 -1
  61. package/dist-server/graphql/resolvers/worksheet/sorting/sorting-product.js +4 -4
  62. package/dist-server/graphql/resolvers/worksheet/sorting/sorting-product.js.map +1 -1
  63. package/dist-server/graphql/resolvers/worksheet/unloading/complete-unloading.js +0 -21
  64. package/dist-server/graphql/resolvers/worksheet/unloading/complete-unloading.js.map +1 -1
  65. package/dist-server/graphql/resolvers/worksheet/worksheet.js +2 -0
  66. package/dist-server/graphql/resolvers/worksheet/worksheet.js.map +1 -1
  67. package/dist-server/graphql/resolvers/worksheet/worksheets.js +19 -4
  68. package/dist-server/graphql/resolvers/worksheet/worksheets.js.map +1 -1
  69. package/dist-server/graphql/resolvers/worksheet-detail/generate-batch-picking-worksheet-details-by-bulk.js +9 -3
  70. package/dist-server/graphql/resolvers/worksheet-detail/generate-batch-picking-worksheet-details-by-bulk.js.map +1 -1
  71. package/dist-server/graphql/resolvers/worksheet-detail/generate-batch-picking-worksheet-details.js +19 -4
  72. package/dist-server/graphql/resolvers/worksheet-detail/generate-batch-picking-worksheet-details.js.map +1 -1
  73. package/dist-server/graphql/resolvers/worksheet-detail/generate-pallet-id.js +24 -34
  74. package/dist-server/graphql/resolvers/worksheet-detail/generate-pallet-id.js.map +1 -1
  75. package/dist-server/graphql/resolvers/worksheet-detail/generate-picking-worksheet-details.js +8 -1
  76. package/dist-server/graphql/resolvers/worksheet-detail/generate-picking-worksheet-details.js.map +1 -1
  77. package/dist-server/graphql/resolvers/worksheet-detail/generate-release-good-worksheet-details.js +10 -2
  78. package/dist-server/graphql/resolvers/worksheet-detail/generate-release-good-worksheet-details.js.map +1 -1
  79. package/dist-server/graphql/resolvers/worksheet-movement/create-worksheet-movement.js +2 -5
  80. package/dist-server/graphql/resolvers/worksheet-movement/create-worksheet-movement.js.map +1 -1
  81. package/dist-server/graphql/types/worksheet/index.js +14 -0
  82. package/dist-server/graphql/types/worksheet/index.js.map +1 -1
  83. package/dist-server/graphql/types/worksheet/loaded-worksheet-detail.js +1 -0
  84. package/dist-server/graphql/types/worksheet/loaded-worksheet-detail.js.map +1 -1
  85. package/dist-server/graphql/types/worksheet/worksheet-detail-info.js +2 -0
  86. package/dist-server/graphql/types/worksheet/worksheet-detail-info.js.map +1 -1
  87. package/dist-server/graphql/types/worksheet/worksheet-info.js +2 -0
  88. package/dist-server/graphql/types/worksheet/worksheet-info.js.map +1 -1
  89. package/dist-server/graphql/types/worksheet/worksheet.js +1 -0
  90. package/dist-server/graphql/types/worksheet/worksheet.js.map +1 -1
  91. package/dist-server/graphql/types/worksheet-detail/inventory-detail.js +3 -0
  92. package/dist-server/graphql/types/worksheet-detail/inventory-detail.js.map +1 -1
  93. package/dist-server/utils/worksheet-no-generator.js +25 -28
  94. package/dist-server/utils/worksheet-no-generator.js.map +1 -1
  95. package/package.json +17 -17
  96. package/server/controllers/ecommerce/sellercraft-controller.ts +28 -7
  97. package/server/controllers/inbound/putaway-worksheet-controller.ts +27 -13
  98. package/server/controllers/inbound/unloading-worksheet-controller.ts +1 -1
  99. package/server/controllers/outbound/loading-worksheet-controller.ts +83 -17
  100. package/server/controllers/outbound/picking-worksheet-controller.ts +189 -9
  101. package/server/controllers/outbound/sorting-worksheet-controller.ts +167 -27
  102. package/server/controllers/render-grn.ts +46 -37
  103. package/server/controllers/render-manifest.ts +12 -5
  104. package/server/controllers/worksheet-controller.ts +14 -1
  105. package/server/entities/index.ts +2 -1
  106. package/server/entities/warehouse-bizplace-onhand-inventory.ts +147 -0
  107. package/server/graphql/resolvers/worksheet/batch-picking-worksheet.ts +14 -0
  108. package/server/graphql/resolvers/worksheet/cancel-draft-release-order.ts +27 -0
  109. package/server/graphql/resolvers/worksheet/cycle-count-adjustment.ts +2 -1
  110. package/server/graphql/resolvers/worksheet/index.ts +3 -1
  111. package/server/graphql/resolvers/worksheet/loading/complete-loading.ts +44 -18
  112. package/server/graphql/resolvers/worksheet/loading/loading.ts +5 -12
  113. package/server/graphql/resolvers/worksheet/loading-worksheet.ts +66 -13
  114. package/server/graphql/resolvers/worksheet/packing-worksheet.ts +1 -1
  115. package/server/graphql/resolvers/worksheet/palletizing-pallets.ts +2 -2
  116. package/server/graphql/resolvers/worksheet/picking/complete-batch-picking.ts +1 -1
  117. package/server/graphql/resolvers/worksheet/picking/complete-picking.ts +13 -11
  118. package/server/graphql/resolvers/worksheet/picking/index.ts +3 -1
  119. package/server/graphql/resolvers/worksheet/picking/picking.ts +30 -4
  120. package/server/graphql/resolvers/worksheet/picking/scan-product-picking.ts +7 -4
  121. package/server/graphql/resolvers/worksheet/picking/seal-tote.ts +25 -0
  122. package/server/graphql/resolvers/worksheet/picking-worksheet.ts +13 -2
  123. package/server/graphql/resolvers/worksheet/putaway/complete-putaway.ts +45 -2
  124. package/server/graphql/resolvers/worksheet/sorting/complete-order-sorting.ts +13 -9
  125. package/server/graphql/resolvers/worksheet/sorting/scan-product-sorting.ts +5 -4
  126. package/server/graphql/resolvers/worksheet/sorting/sorting-product.ts +5 -4
  127. package/server/graphql/resolvers/worksheet/unloading/complete-unloading.ts +0 -25
  128. package/server/graphql/resolvers/worksheet/worksheet.ts +2 -0
  129. package/server/graphql/resolvers/worksheet/worksheets.ts +28 -4
  130. package/server/graphql/resolvers/worksheet-detail/generate-batch-picking-worksheet-details-by-bulk.ts +21 -3
  131. package/server/graphql/resolvers/worksheet-detail/generate-batch-picking-worksheet-details.ts +39 -11
  132. package/server/graphql/resolvers/worksheet-detail/generate-pallet-id.ts +46 -49
  133. package/server/graphql/resolvers/worksheet-detail/generate-picking-worksheet-details.ts +11 -1
  134. package/server/graphql/resolvers/worksheet-detail/generate-release-good-worksheet-details.ts +18 -1
  135. package/server/graphql/resolvers/worksheet-movement/create-worksheet-movement.ts +2 -2
  136. package/server/graphql/types/worksheet/index.ts +14 -0
  137. package/server/graphql/types/worksheet/loaded-worksheet-detail.ts +1 -0
  138. package/server/graphql/types/worksheet/worksheet-detail-info.ts +2 -0
  139. package/server/graphql/types/worksheet/worksheet-info.ts +2 -0
  140. package/server/graphql/types/worksheet/worksheet.ts +1 -0
  141. package/server/graphql/types/worksheet-detail/inventory-detail.ts +3 -0
  142. package/server/utils/worksheet-no-generator.ts +25 -25
@@ -1,3 +1,5 @@
1
+ import { IsNull, In } from 'typeorm'
2
+
1
3
  import { VasWorksheetController } from '../vas/vas-worksheet-controller'
2
4
  import { Product, ProductDetail } from '@things-factory/product-base'
3
5
  import {
@@ -6,11 +8,22 @@ import {
6
8
  InventoryItem,
7
9
  INVENTORY_STATUS,
8
10
  InventoryNoGenerator,
9
- INVENTORY_ITEM_SOURCE
11
+ INVENTORY_ITEM_SOURCE,
12
+ Tote,
13
+ TOTE_STATUS
10
14
  } from '@things-factory/warehouse-base'
11
- import { ReleaseGood, OrderInventory, ORDER_INVENTORY_STATUS, ORDER_STATUS } from '@things-factory/sales-base'
15
+ import {
16
+ ReleaseGood,
17
+ OrderInventory,
18
+ ORDER_INVENTORY_STATUS,
19
+ ORDER_STATUS,
20
+ OrderTote,
21
+ OrderToteItem,
22
+ OrderNoGenerator
23
+ } from '@things-factory/sales-base'
12
24
  import { Worksheet, WorksheetDetail } from '../../entities'
13
25
  import { WORKSHEET_STATUS, WORKSHEET_TYPE } from '../../constants'
26
+ import { temporaryGetRemainInventoryAmount } from 'server/graphql/resolvers/worksheet/vas-transactions/common-utils'
14
27
 
15
28
  export class SortingWorksheetController extends VasWorksheetController {
16
29
  async generateSortingWorksheet(
@@ -62,7 +75,8 @@ export class SortingWorksheetController extends VasWorksheetController {
62
75
  taskNo: string,
63
76
  releaseGoodNo: string,
64
77
  productBarcode: string,
65
- serialNumber: string
78
+ serialNumber: string,
79
+ toteNo: string
66
80
  ): Promise<void> {
67
81
  const worksheet: Worksheet = await this.trxMgr.getRepository(Worksheet).findOne({
68
82
  where: {
@@ -75,6 +89,8 @@ export class SortingWorksheetController extends VasWorksheetController {
75
89
  'worksheetDetails',
76
90
  'worksheetDetails.targetInventory',
77
91
  'worksheetDetails.targetInventory.product',
92
+ 'worksheetDetails.targetInventory.orderProduct',
93
+ 'worksheetDetails.targetInventory.bizplace',
78
94
  'worksheetDetails.targetInventory.inventory',
79
95
  'worksheetDetails.targetInventory.inventory.product',
80
96
  'worksheetDetails.targetInventory.inventory.product.productDetails',
@@ -204,6 +220,17 @@ export class SortingWorksheetController extends VasWorksheetController {
204
220
  } else {
205
221
  await this.updateOrderTargets([matchingOI])
206
222
  }
223
+
224
+ if (toteNo) {
225
+ await this.toteScanning(
226
+ toteNo,
227
+ matchingOI.orderProduct,
228
+ matchingOI,
229
+ 1,
230
+ releaseGood,
231
+ matchingOI.bizplace
232
+ )
233
+ }
207
234
  }
208
235
  })
209
236
  )
@@ -216,7 +243,8 @@ export class SortingWorksheetController extends VasWorksheetController {
216
243
  releaseGoodNo: string,
217
244
  productId: string,
218
245
  sortingQty: number,
219
- serialNumber: string
246
+ serialNumber: string,
247
+ toteNo: string
220
248
  ): Promise<void> {
221
249
  const worksheet: Worksheet = await this.trxMgr.getRepository(Worksheet).findOne({
222
250
  where: {
@@ -229,6 +257,8 @@ export class SortingWorksheetController extends VasWorksheetController {
229
257
  'worksheetDetails',
230
258
  'worksheetDetails.targetInventory',
231
259
  'worksheetDetails.targetInventory.product',
260
+ 'worksheetDetails.targetInventory.orderProduct',
261
+ 'worksheetDetails.targetInventory.bizplace',
232
262
  'worksheetDetails.targetInventory.inventory',
233
263
  'worksheetDetails.targetInventory.inventory.product',
234
264
  'worksheetDetails.targetInventory.inventory.product.productDetails',
@@ -294,6 +324,17 @@ export class SortingWorksheetController extends VasWorksheetController {
294
324
  }
295
325
  }
296
326
 
327
+ if (toteNo) {
328
+ await this.toteScanning(
329
+ toteNo,
330
+ matchingOI.orderProduct,
331
+ matchingOI,
332
+ sortingQty,
333
+ releaseGood,
334
+ matchingOI.bizplace
335
+ )
336
+ }
337
+
297
338
  if (releaseQty != matchingOI?.sortedQty && sortingQty != 0) {
298
339
  if (product?.isRequireSerialNumberScanningOutbound) {
299
340
  matchingOI.sortedQty += sortingQty
@@ -338,34 +379,50 @@ export class SortingWorksheetController extends VasWorksheetController {
338
379
  }
339
380
 
340
381
  async completeOrderSorting(releaseGoodNo: string): Promise<ReleaseGood> {
341
- let releaseGood: ReleaseGood = await this.findRefOrder(
342
- ReleaseGood,
343
- {
344
- domain: this.domain,
345
- name: releaseGoodNo,
346
- status: ORDER_STATUS.SORTING
347
- },
348
- ['bizplace', 'orderInventories']
349
- )
382
+ try {
383
+ let releaseGood: ReleaseGood = await this.findRefOrder(
384
+ ReleaseGood,
385
+ {
386
+ domain: this.domain,
387
+ name: releaseGoodNo,
388
+ status: ORDER_STATUS.SORTING
389
+ },
390
+ ['bizplace', 'orderInventories']
391
+ )
350
392
 
351
- releaseGood.status = ORDER_STATUS.READY_TO_LOAD
352
- releaseGood.updater = this.user
353
- await this.trxMgr.getRepository(ReleaseGood).save(releaseGood)
393
+ if (!releaseGood) {
394
+ throw new Error('Order is already sorted')
395
+ }
354
396
 
355
- let inventoryItems: InventoryItem = await this.trxMgr
356
- .getRepository(InventoryItem)
357
- .find({ where: { outboundOrderId: releaseGood.id } })
397
+ const foundNotSealedOrderTote = await this.trxMgr
398
+ .getRepository(OrderTote)
399
+ .findOne({ where: { releaseGood, closedDate: IsNull() } })
358
400
 
359
- if (inventoryItems.length > 0) {
360
- inventoryItems.forEach((itm: InventoryItem) => {
361
- itm.status = INVENTORY_STATUS.TERMINATED
362
- itm.updater = this.user
363
- })
401
+ if (foundNotSealedOrderTote) {
402
+ throw new Error('Please seal the tote(s) before proceeding')
403
+ }
364
404
 
365
- await this.trxMgr.getRepository(InventoryItem).save(inventoryItems)
366
- }
405
+ releaseGood.status = ORDER_STATUS.READY_TO_LOAD
406
+ releaseGood.updater = this.user
407
+ await this.trxMgr.getRepository(ReleaseGood).save(releaseGood)
408
+
409
+ let inventoryItems: InventoryItem = await this.trxMgr
410
+ .getRepository(InventoryItem)
411
+ .find({ where: { outboundOrderId: releaseGood.id } })
412
+
413
+ if (inventoryItems.length > 0) {
414
+ inventoryItems.forEach((itm: InventoryItem) => {
415
+ itm.status = INVENTORY_STATUS.TERMINATED
416
+ itm.updater = this.user
417
+ })
418
+
419
+ await this.trxMgr.getRepository(InventoryItem).save(inventoryItems)
420
+ }
367
421
 
368
- return releaseGood
422
+ return releaseGood
423
+ } catch (e) {
424
+ throw e
425
+ }
369
426
  }
370
427
 
371
428
  async completeWorksheetSorting(taskNo: string): Promise<Worksheet> {
@@ -383,6 +440,16 @@ export class SortingWorksheetController extends VasWorksheetController {
383
440
  ]
384
441
  })
385
442
 
443
+ let releaseGoodIds = worksheet.worksheetDetails.map(itm => itm.targetInventory.releaseGood.id)
444
+
445
+ const foundNotSealedOrderTote = await this.trxMgr
446
+ .getRepository(OrderTote)
447
+ .findOne({ where: { releaseGood: In(releaseGoodIds), closedDate: IsNull() } })
448
+
449
+ if (foundNotSealedOrderTote) {
450
+ throw new Error('Please seal the tote(s) before proceeding')
451
+ }
452
+
386
453
  this.checkRecordValidity(worksheet, { status: WORKSHEET_STATUS.EXECUTING })
387
454
 
388
455
  const worksheetDetails: WorksheetDetail[] = worksheet.worksheetDetails
@@ -398,4 +465,77 @@ export class SortingWorksheetController extends VasWorksheetController {
398
465
 
399
466
  return worksheet
400
467
  }
468
+
469
+ private async toteScanning(toteNo, targetProduct, targetInventory, pickedQty, releaseGood, bizplace) {
470
+ //1. find tote
471
+ let foundTote: Tote = await this.trxMgr
472
+ .getRepository(Tote)
473
+ .findOne({ where: { bizplace, name: toteNo, deletedAt: IsNull() } })
474
+
475
+ if (foundTote?.status == TOTE_STATUS.DAMAGED) {
476
+ throw new Error('Tote is damaged')
477
+ }
478
+
479
+ if (foundTote?.status == TOTE_STATUS.DISPATCHED) {
480
+ throw new Error('Tote is dispatched')
481
+ }
482
+
483
+ //2. find order tote
484
+ let foundOrderTote: OrderTote = await this.trxMgr
485
+ .getRepository(OrderTote)
486
+ .findOne({ where: { domain: this.domain, name: toteNo, releaseGood } })
487
+
488
+ //if order tote not found the create one, if tote not found means it's tote box
489
+ //create order tote item
490
+ if (!foundOrderTote) {
491
+ const orderTote = await this.trxMgr.getRepository(OrderTote).save({
492
+ name: toteNo,
493
+ domain: this.domain,
494
+ releaseGood,
495
+ tote: foundTote ? foundTote : null,
496
+ updater: this.user
497
+ })
498
+
499
+ const orderToteItem = await this.trxMgr.getRepository(OrderToteItem).save({
500
+ domain: this.domain,
501
+ name: OrderNoGenerator.orderToteItem(),
502
+ orderProduct: targetProduct,
503
+ orderInventory: targetInventory,
504
+ orderTote,
505
+ qty: pickedQty,
506
+ updater: this.user
507
+ })
508
+ } else {
509
+ if (foundOrderTote.closedDate) {
510
+ throw new Error('Tote has been sealed, please try another tote!')
511
+ }
512
+
513
+ //if found order tote then check if order tote item exist
514
+ const foundOrderToteItem: OrderToteItem = await this.trxMgr.getRepository(OrderToteItem).findOne({
515
+ domain: this.domain,
516
+ orderProduct: targetProduct,
517
+ orderInventory: targetInventory,
518
+ orderTote: foundOrderTote
519
+ })
520
+
521
+ //if not order tote item doesnt exist then create one
522
+ if (!foundOrderToteItem) {
523
+ const orderToteItem = await this.trxMgr.getRepository(OrderToteItem).save({
524
+ domain: this.domain,
525
+ name: OrderNoGenerator.orderToteItem(),
526
+ orderProduct: targetProduct,
527
+ orderInventory: targetInventory,
528
+ orderTote: foundOrderTote,
529
+ qty: pickedQty,
530
+ updater: this.user
531
+ })
532
+ } else {
533
+ //if found order tote item found then add the quantity
534
+ const orderToteItem = await this.trxMgr.getRepository(OrderToteItem).save({
535
+ ...foundOrderToteItem,
536
+ qty: foundOrderToteItem.qty + pickedQty
537
+ })
538
+ }
539
+ }
540
+ }
401
541
  }
@@ -71,6 +71,7 @@ export async function renderGRN({ grnNo, timezoneOffSet }, context: any) {
71
71
  .addGroupBy('batch_id')
72
72
  .addGroupBy('packing_type')
73
73
  .addGroupBy('uom')
74
+ .addGroupBy('expiration_date')
74
75
  .getRawMany()
75
76
 
76
77
  // 5. find domain contact point
@@ -168,11 +169,9 @@ export async function renderGRN({ grnNo, timezoneOffSet }, context: any) {
168
169
  })
169
170
 
170
171
  tempIndexArr.forEach((t, index) => {
171
- if (t >= 0)
172
- foundInventoryItem[t].totalQuantity = tempTotalQuantity[index]
172
+ if (t >= 0) foundInventoryItem[t].totalQuantity = tempTotalQuantity[index]
173
173
  })
174
174
 
175
-
176
175
  const data = {
177
176
  logo_url: logo,
178
177
  sign_url: signature,
@@ -208,40 +207,50 @@ export async function renderGRN({ grnNo, timezoneOffSet }, context: any) {
208
207
  account_no: foundPartnerCP ? foundPartnerCP.accountNo : '',
209
208
  unloaded_by: foundWS ? foundWS.updater.name : '',
210
209
  putaway_by: foundPutawayWS ? foundPutawayWS.updater.name : '',
211
- product_list: targetProducts.map((item, idx) => {
212
- let unloadInvHistory = inboundInventories.find(
213
- ih =>
214
- ih.productId == item.product.id &&
215
- ih.batchId == item.batchId &&
216
- ih.packingType == item.packingType &&
217
- ih.uom == item.uom
218
- )
219
-
220
- return {
221
- list_no: idx + 1,
222
- product_sku: `${item.product.sku}`,
223
- product_brand_sku: `${item.product.brandSku}`,
224
- product_name: `${item.product.name}(${item.product.description})`,
225
- product_desc: item.product.description,
226
- product_nameOnly: item.product.name,
227
- product_type: item.packingType,
228
- product_size: item.packingSize,
229
- product_batch: item.batchId,
230
- batch_id_ref: item?.batchIdRef ? item.batchIdRef : '',
231
- pallet_qty: item.actualPalletQty,
232
- product_qty: unloadInvHistory.qty || item.actualPackQty,
233
- product_unit_uom_value: `${Math.round(item.uomValue * 100) / 100}`,
234
- product_total_uom_value: `${Math.round((unloadInvHistory.uomValue || item.uomValue * item.actualPackQty) * 100) / 100
235
- }`,
236
- product_uom: `${unloadInvHistory.uom || item.uom}`,
237
- product_gross_weight: item.product.grossWeight || null,
238
- unit_price: item.unitPrice || null,
239
- expiry_date: unloadInvHistory.expiryDate || '',
240
- manufacture_date: item.manufactureDate,
241
- reusable_pallet_id: unloadInvHistory.reusablePalletId || '',
242
- remark: (item.remark ? item.remark : '') + (item.issue ? ' [Issue]: ' + item.issue : '')
243
- }
244
- }),
210
+ product_list: targetProducts
211
+ .reduce((acc, item) => {
212
+ acc.push(
213
+ ...inboundInventories
214
+ .filter(
215
+ ih =>
216
+ ih.productId == item.product.id &&
217
+ ih.batchId == item.batchId &&
218
+ ih.packingType == item.packingType &&
219
+ ih.uom == item.uom
220
+ )
221
+ .map(unloadInvHistory => {
222
+ return {
223
+ product_sku: `${item.product.sku}`,
224
+ product_brand_sku: `${item.product.brandSku}`,
225
+ product_name: `${item.product.name}(${item.product.description})`,
226
+ product_desc: item.product.description,
227
+ product_nameOnly: item.product.name,
228
+ product_type: item.packingType,
229
+ product_size: item.packingSize,
230
+ product_batch: item.batchId,
231
+ batch_id_ref: item?.batchIdRef ? item.batchIdRef : '',
232
+ pallet_qty: item.actualPalletQty,
233
+ product_qty: unloadInvHistory.qty || item.actualPackQty,
234
+ product_unit_uom_value: `${Math.round(item.uomValue * 100) / 100}`,
235
+ product_total_uom_value: `${
236
+ Math.round((unloadInvHistory.uomValue || item.uomValue * item.actualPackQty) * 100) / 100
237
+ }`,
238
+ product_uom: `${unloadInvHistory.uom || item.uom}`,
239
+ product_gross_weight: item.product.grossWeight || null,
240
+ unit_price: item.unitPrice || null,
241
+ expiry_date:
242
+ unloadInvHistory.expiryDate && unloadInvHistory.expiryDate != ''
243
+ ? new Date(unloadInvHistory.expiryDate).toISOString().split('T')[0]
244
+ : '',
245
+ manufacture_date: item.manufactureDate,
246
+ reusable_pallet_id: unloadInvHistory.reusablePalletId || '',
247
+ remark: (item.remark ? item.remark : '') + (item.issue ? ' [Issue]: ' + item.issue : '')
248
+ }
249
+ })
250
+ )
251
+ return acc
252
+ }, [])
253
+ .map((item, idx) => ({ list_no: idx + 1, ...item })),
245
254
  serialNumber: foundInventoryItem
246
255
  }
247
256
 
@@ -6,6 +6,7 @@ import { Attachment, STORAGE } from '@things-factory/attachment-base'
6
6
  import { config } from '@things-factory/env'
7
7
  import { Manifest, ReleaseGood } from '@things-factory/sales-base'
8
8
  import { Domain } from '@things-factory/shell'
9
+ import { Bizplace, getCompanyBizplace } from '@things-factory/biz-base'
9
10
 
10
11
  import { TEMPLATE_TYPE } from '../constants'
11
12
  import { DateTimeConverter } from '../utils/datetime-util'
@@ -25,8 +26,9 @@ export async function renderManifest({ manifestNo }, context: any) {
25
26
  })
26
27
 
27
28
  // find release good
28
- const releaseGoods: ReleaseGood[] = await getRepository(ReleaseGood).find({
29
- where: { domain, manifest }
29
+ let releaseGoods: ReleaseGood[] = await getRepository(ReleaseGood).find({
30
+ where: { domain, manifest },
31
+ relations: ['bizplace']
30
32
  })
31
33
 
32
34
  // 7. find grn template based on category
@@ -41,7 +43,9 @@ export async function renderManifest({ manifestNo }, context: any) {
41
43
  manifest_no: manifest?.name,
42
44
  manifest_date: DateTimeConverter.date(manifest?.createdAt).toString(),
43
45
  total_list: releaseGoods?.length || 0,
44
- product_list: releaseGoods.map((item, idx) => {
46
+ product_list: await Promise.all (releaseGoods.map(async(item, idx) => {
47
+ const customerBizplaceId: string = item.bizplace.id
48
+ const custCompanyBizplace: Bizplace = await getCompanyBizplace(null, null, customerBizplaceId)
45
49
  return {
46
50
  list_no: idx + 1,
47
51
  order_no: item?.refNo,
@@ -50,9 +54,12 @@ export async function renderManifest({ manifestNo }, context: any) {
50
54
  delivery_date: DateTimeConverter.date(manifest?.dispatchedAt).toString(),
51
55
  attention_to: item?.attentionTo,
52
56
  delivery_address: item?.deliveryAddress1,
53
- postal_code_city: `${item?.postalCode}, ${item?.city}`
57
+ postal_code_city: `${item?.postalCode}, ${item?.city}`,
58
+ remark: item?.remark,
59
+ status: item?.status,
60
+ company_domain_name: custCompanyBizplace.domain.name
54
61
  }
55
- })
62
+ }))
56
63
  }
57
64
 
58
65
  const formData = new FormData()
@@ -300,7 +300,7 @@ export class WorksheetController {
300
300
 
301
301
  /**
302
302
  * @summary find worksheet detail by passed condition
303
- * @description find worksheey based on passed condition
303
+ * @description find worksheet detail based on passed condition
304
304
  * If you want to get additional relations you need to define reltaions
305
305
  * ex) findWorksheetDetail(condition, ['worksheet'])
306
306
  */
@@ -390,6 +390,19 @@ export class WorksheetController {
390
390
  let refOrderType: string = await this.getRefOrderField(refOrder)
391
391
  const bizplace: Bizplace = await this.extractBizplaceFromRefOrder(refOrder)
392
392
 
393
+ let existingWorksheet: Worksheet
394
+ try {
395
+ existingWorksheet = await this.findWorksheetByRefOrder(refOrder, type)
396
+ } catch (e) {}
397
+
398
+ if (existingWorksheet)
399
+ throw new Error(
400
+ this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY(
401
+ `create ${type.toLocaleLowerCase()} worksheet`,
402
+ 'existing worksheet is found'
403
+ )
404
+ )
405
+
393
406
  const worksheet: Partial<Worksheet> = {
394
407
  domain: this.domain,
395
408
  bizplace,
@@ -1,7 +1,8 @@
1
1
  import { Worksheet } from './worksheet'
2
2
  import { WorksheetDetail } from './worksheet-detail'
3
3
  import { WorksheetMovement } from './worksheet-movement'
4
+ import { WarehouseBizplaceOnhandInventory } from './warehouse-bizplace-onhand-inventory'
4
5
 
5
- export const entities = [Worksheet, WorksheetDetail, WorksheetMovement]
6
+ export const entities = [Worksheet, WorksheetDetail, WorksheetMovement, WarehouseBizplaceOnhandInventory]
6
7
 
7
8
  export { Worksheet, WorksheetDetail, WorksheetMovement }
@@ -0,0 +1,147 @@
1
+ import { ViewColumn, ViewEntity } from 'typeorm'
2
+
3
+ @ViewEntity({
4
+ expression: `
5
+ select d.name as "domainName", b.name as "bizplaceName", src.* from (
6
+ WITH oi as (
7
+ select
8
+ oi.domain_id,
9
+ oi.bizplace_id,
10
+ SUM(oi.release_qty) AS release_qty,
11
+ SUM(oi.release_uom_value) AS release_uom_value,
12
+ oi.batch_id,
13
+ oi.batch_id_ref,
14
+ oi.product_id,
15
+ oi.packing_type,
16
+ oi.packing_size,
17
+ oi.uom
18
+ FROM
19
+ order_inventories oi
20
+ WHERE
21
+ (oi.status = 'PENDING' or oi.status = 'PENDING_RECEIVE' or oi.status = 'PENDING_WORKSHEET' or oi.status = 'PENDING_SPLIT')
22
+ AND oi.batch_id NOTNULL
23
+ AND oi.product_id NOTNULL
24
+ AND oi.packing_type NOTNULL
25
+ AND oi.packing_size NOTNULL
26
+ AND oi.inventory_id IS NULL
27
+ GROUP BY
28
+ oi.domain_id,
29
+ oi.bizplace_id,
30
+ oi.batch_id,
31
+ oi.batch_id_ref,
32
+ oi.product_id,
33
+ oi.packing_type,
34
+ oi.packing_size,
35
+ oi.uom
36
+ )
37
+ -- SINGLE ITEM INVENTORY QUERY
38
+ select
39
+ i.domain_id as "domainId",
40
+ i.bizplace_id as "bizplaceId",
41
+ i.packing_type as "packingType",
42
+ i.packing_size as "packingSize",
43
+ i.uom,
44
+ i.product_id as "productId",
45
+ null as "productBundleId",
46
+ COALESCE(SUM(COALESCE(i.qty, 0)) - SUM(COALESCE(i.locked_qty, 0)) - MAX(COALESCE(oi.release_qty, 0))) AS "remainQty",
47
+ COALESCE(SUM(COALESCE(i.uom_value, 0)) - SUM(COALESCE(i.locked_uom_value, 0)) - MAX(COALESCE(oi.release_uom_value, 0)), 0) AS "remainUomValue",
48
+ COALESCE(sum(COALESCE(i.qty, 0::double precision))) AS "qty",
49
+ COALESCE(sum(COALESCE(i.uom_value, 0::double precision))) AS "uomValue",
50
+ 'SINGLE' AS "groupType"
51
+ FROM inventories i
52
+ INNER JOIN locations l2 ON i.location_id = l2.id AND i.domain_id = l2.domain_id AND l2.type NOT IN ('QUARANTINE', 'RESERVE')
53
+ LEFT JOIN oi ON i.batch_id = oi.batch_id AND i.product_id = oi.product_id AND i.packing_type = oi.packing_type AND i.packing_size = oi.packing_size AND i.uom = oi.uom
54
+ WHERE i.status = 'STORED'
55
+ GROUP by
56
+ i.domain_id,
57
+ i.bizplace_id,
58
+ i.product_id,
59
+ i.packing_type,
60
+ i.packing_size,
61
+ i.uom
62
+ union all
63
+ -- BUNDLE ITEM INVENTORY QUERY
64
+ SELECT
65
+ pbs.domain_id as "domainId",
66
+ pbs.bizplace_id as "bizplaceId",
67
+ pb.packing_type as "packingType",
68
+ pb.packing_size as "packingSize",
69
+ 'UNIT' AS "uom",
70
+ null as "productId",
71
+ pb.id AS "productBundleId",
72
+ COALESCE(MIN(FLOOR(pbs."availableQty")),0) AS "remainQty",
73
+ COALESCE(MIN(FLOOR(pbs."availableUomValue")),0) AS "remainUomValue",
74
+ COALESCE(MIN(FLOOR(pbs."qty")), 0::double precision) AS "qty",
75
+ COALESCE(MIN(FLOOR(pbs."uomValue")), 0::double precision) AS "uomValue",
76
+ 'BUNDLE' AS "groupType"
77
+ FROM product_bundles pb
78
+ INNER JOIN (
79
+ SELECT i.domain_id, i.bizplace_id, pbs.product_id, pbs.product_bundle_id, min(pbs.bundle_qty),
80
+ (SUM(COALESCE(i.qty, 0)) - SUM(COALESCE(i.locked_qty, 0)) - MAX(COALESCE(oi.release_qty, 0))) / min(pbs.bundle_qty) AS "availableQty",
81
+ (SUM(COALESCE(i.uom_value, 0)) - SUM(COALESCE(i.locked_uom_value, 0)) - MAX(COALESCE(oi.release_uom_value, 0))) / min(pbs.bundle_qty) AS "availableUomValue",
82
+ (sum(COALESCE(i.qty, 0::double precision))) / min(pbs.bundle_qty)::double precision AS "qty",
83
+ (sum(COALESCE(i.uom_value, 0::double precision))) / min(pbs.bundle_qty)::double precision AS "uomValue"
84
+ FROM product_bundle_settings pbs
85
+ LEFT JOIN inventories i ON i.product_id = pbs.product_id AND i.status = 'STORED'
86
+ INNER JOIN locations l ON i.location_id = l.id AND i.domain_id = l.domain_id AND l.type NOT IN ('QUARANTINE', 'RESERVE')
87
+ LEFT JOIN oi ON oi.product_id = i.product_id
88
+ GROUP by
89
+ i.domain_id,
90
+ i.bizplace_id,
91
+ pbs.product_id,
92
+ pbs.product_bundle_id
93
+ ) pbs ON pbs.product_bundle_id = pb.id
94
+ GROUP BY
95
+ pbs.domain_id,
96
+ pbs.bizplace_id,
97
+ pb.packing_type,
98
+ pb.packing_size,
99
+ pb.name,
100
+ pb.sku,
101
+ pb.id
102
+ )
103
+ AS src
104
+ inner join domains d on d.id = src."domainId"
105
+ inner join bizplaces b on b.id = src."bizplaceId"
106
+ where src."remainQty" > 0
107
+ order by src."domainId"
108
+ `
109
+ })
110
+
111
+ export class WarehouseBizplaceOnhandInventory {
112
+ @ViewColumn()
113
+ domainName: string
114
+
115
+ @ViewColumn()
116
+ bizplaceName: string
117
+
118
+ @ViewColumn()
119
+ domainId: string
120
+
121
+ @ViewColumn()
122
+ bizplaceId: string
123
+
124
+ @ViewColumn()
125
+ packingType: string
126
+
127
+ @ViewColumn()
128
+ packingSize: number
129
+
130
+ @ViewColumn()
131
+ uom: string
132
+
133
+ @ViewColumn()
134
+ productId: string
135
+
136
+ @ViewColumn()
137
+ productBundleId: string
138
+
139
+ @ViewColumn()
140
+ remainQty: number
141
+
142
+ @ViewColumn()
143
+ remainUomValue: number
144
+
145
+ @ViewColumn()
146
+ groupType: string
147
+ }
@@ -3,6 +3,7 @@ import { getRepository, SelectQueryBuilder } from 'typeorm'
3
3
  import { ORDER_INVENTORY_STATUS } from '@things-factory/sales-base'
4
4
  import { WORKSHEET_STATUS, WORKSHEET_TYPE } from '../../../constants'
5
5
  import { Worksheet, WorksheetDetail } from '../../../entities'
6
+ import { InventoryChange } from '@things-factory/warehouse-base'
6
7
 
7
8
  export const batchPickingWorksheetResolver = {
8
9
  async batchPickingWorksheet(_: any, { taskNo, locationSortingRules }, context: any) {
@@ -42,6 +43,7 @@ export const batchPickingWorksheetResolver = {
42
43
  .addSelect('LOC.column', 'column')
43
44
  .addSelect('LOC.shelf', 'shelf')
44
45
  .addSelect('BIN_LOC.name', 'binLocationName')
46
+ .addSelect('WSD.status', 'status')
45
47
  .leftJoin('WSD.targetInventory', 'T_INV')
46
48
  .leftJoin('T_INV.inventory', 'INV')
47
49
  .leftJoin('T_INV.product', 'PROD')
@@ -70,6 +72,7 @@ export const batchPickingWorksheetResolver = {
70
72
  .addGroupBy('LOC.column')
71
73
  .addGroupBy('LOC.row')
72
74
  .addGroupBy('LOC.shelf')
75
+ .addGroupBy('WSD.status')
73
76
 
74
77
  if (locationSortingRules?.length > 0) {
75
78
  locationSortingRules.forEach((rule: { name: string; desc: boolean }) => {
@@ -86,6 +89,15 @@ export const batchPickingWorksheetResolver = {
86
89
  partnerDomainId: worksheet.bizplace?.domain.id
87
90
  },
88
91
  worksheetDetailInfos: items.map(async (item: any) => {
92
+ const inventoryChangesCount: number = await getRepository(InventoryChange).count({
93
+ where: {
94
+ inventory: item.inventoryId,
95
+ status: 'PENDING',
96
+ transactionType: 'MISSING'
97
+ },
98
+ relations: ['inventory', 'product']
99
+ })
100
+
89
101
  return {
90
102
  palletId: item?.palletId,
91
103
  cartonId: item?.cartonId,
@@ -98,6 +110,8 @@ export const batchPickingWorksheetResolver = {
98
110
  },
99
111
  qty: item?.qty,
100
112
  releaseQty: item.releaseQty,
113
+ hasMissingInventoryChanges: inventoryChangesCount > 0 ? true : false,
114
+ status: item.status,
101
115
  pickedQty: item.pickedQty,
102
116
  packingType: item?.packingType,
103
117
  packingSize: item?.packingSize,