@things-factory/worksheet-base 4.3.137 → 4.3.138

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 (70) hide show
  1. package/dist-server/controllers/inbound/unloading-worksheet-controller.js +59 -73
  2. package/dist-server/controllers/inbound/unloading-worksheet-controller.js.map +1 -1
  3. package/dist-server/controllers/inspect/cycle-count-worksheet-controller.js +2 -4
  4. package/dist-server/controllers/inspect/cycle-count-worksheet-controller.js.map +1 -1
  5. package/dist-server/controllers/outbound/loading-worksheet-controller.js +5 -4
  6. package/dist-server/controllers/outbound/loading-worksheet-controller.js.map +1 -1
  7. package/dist-server/controllers/outbound/packing-worksheet-controller.js +23 -23
  8. package/dist-server/controllers/outbound/packing-worksheet-controller.js.map +1 -1
  9. package/dist-server/controllers/outbound/picking-worksheet-controller.js +78 -45
  10. package/dist-server/controllers/outbound/picking-worksheet-controller.js.map +1 -1
  11. package/dist-server/controllers/outbound/sorting-worksheet-controller.js +14 -14
  12. package/dist-server/controllers/outbound/sorting-worksheet-controller.js.map +1 -1
  13. package/dist-server/controllers/vas/vas-worksheet-controller.js +1 -2
  14. package/dist-server/controllers/vas/vas-worksheet-controller.js.map +1 -1
  15. package/dist-server/controllers/worksheet-controller.js +7 -7
  16. package/dist-server/controllers/worksheet-controller.js.map +1 -1
  17. package/dist-server/entities/index.js +3 -2
  18. package/dist-server/entities/index.js.map +1 -1
  19. package/dist-server/entities/warehouse-bizplace-onhand-inventory.js +29 -62
  20. package/dist-server/entities/warehouse-bizplace-onhand-inventory.js.map +1 -1
  21. package/dist-server/graphql/resolvers/worksheet/batch-picking-worksheet.js +6 -0
  22. package/dist-server/graphql/resolvers/worksheet/batch-picking-worksheet.js.map +1 -1
  23. package/dist-server/graphql/resolvers/worksheet/confirm-cancellation-release-order.js +1 -2
  24. package/dist-server/graphql/resolvers/worksheet/confirm-cancellation-release-order.js.map +1 -1
  25. package/dist-server/graphql/resolvers/worksheet/cycle-count-adjustment.js +6 -6
  26. package/dist-server/graphql/resolvers/worksheet/cycle-count-adjustment.js.map +1 -1
  27. package/dist-server/graphql/resolvers/worksheet/find-sorting-release-orders-by-task-no.js +2 -2
  28. package/dist-server/graphql/resolvers/worksheet/find-sorting-release-orders-by-task-no.js.map +1 -1
  29. package/dist-server/graphql/resolvers/worksheet/inventories-by-pallet.js +2 -1
  30. package/dist-server/graphql/resolvers/worksheet/inventories-by-pallet.js.map +1 -1
  31. package/dist-server/graphql/resolvers/worksheet/packing-worksheet.js +4 -1
  32. package/dist-server/graphql/resolvers/worksheet/packing-worksheet.js.map +1 -1
  33. package/dist-server/graphql/resolvers/worksheet/picking-worksheet.js +3 -2
  34. package/dist-server/graphql/resolvers/worksheet/picking-worksheet.js.map +1 -1
  35. package/dist-server/graphql/resolvers/worksheet/transfer.js +9 -9
  36. package/dist-server/graphql/resolvers/worksheet/transfer.js.map +1 -1
  37. package/dist-server/graphql/resolvers/worksheet/unloaded-inventories.js +1 -1
  38. package/dist-server/graphql/resolvers/worksheet/unloaded-inventories.js.map +1 -1
  39. package/dist-server/graphql/resolvers/worksheet/vas-transactions/common-utils.js +17 -17
  40. package/dist-server/graphql/resolvers/worksheet/vas-transactions/common-utils.js.map +1 -1
  41. package/dist-server/graphql/resolvers/worksheet-detail/regenerate-release-good-worksheet-details.js +4 -4
  42. package/dist-server/graphql/resolvers/worksheet-detail/regenerate-release-good-worksheet-details.js.map +1 -1
  43. package/dist-server/graphql/types/worksheet-detail/index.js +1 -0
  44. package/dist-server/graphql/types/worksheet-detail/index.js.map +1 -1
  45. package/dist-server/utils/inventory-util.js +1 -98
  46. package/dist-server/utils/inventory-util.js.map +1 -1
  47. package/package.json +16 -16
  48. package/server/controllers/inbound/unloading-worksheet-controller.ts +74 -86
  49. package/server/controllers/inspect/cycle-count-worksheet-controller.ts +2 -4
  50. package/server/controllers/outbound/loading-worksheet-controller.ts +13 -3
  51. package/server/controllers/outbound/packing-worksheet-controller.ts +32 -37
  52. package/server/controllers/outbound/picking-worksheet-controller.ts +94 -59
  53. package/server/controllers/outbound/sorting-worksheet-controller.ts +14 -21
  54. package/server/controllers/vas/vas-worksheet-controller.ts +2 -2
  55. package/server/controllers/worksheet-controller.ts +15 -10
  56. package/server/entities/index.ts +2 -2
  57. package/server/entities/warehouse-bizplace-onhand-inventory.ts +29 -63
  58. package/server/graphql/resolvers/worksheet/batch-picking-worksheet.ts +6 -0
  59. package/server/graphql/resolvers/worksheet/confirm-cancellation-release-order.ts +1 -2
  60. package/server/graphql/resolvers/worksheet/cycle-count-adjustment.ts +2 -2
  61. package/server/graphql/resolvers/worksheet/find-sorting-release-orders-by-task-no.ts +2 -2
  62. package/server/graphql/resolvers/worksheet/inventories-by-pallet.ts +3 -1
  63. package/server/graphql/resolvers/worksheet/packing-worksheet.ts +4 -2
  64. package/server/graphql/resolvers/worksheet/picking-worksheet.ts +3 -2
  65. package/server/graphql/resolvers/worksheet/transfer.ts +18 -16
  66. package/server/graphql/resolvers/worksheet/unloaded-inventories.ts +1 -1
  67. package/server/graphql/resolvers/worksheet/vas-transactions/common-utils.ts +3 -2
  68. package/server/graphql/resolvers/worksheet-detail/regenerate-release-good-worksheet-details.ts +4 -1
  69. package/server/graphql/types/worksheet-detail/index.ts +1 -0
  70. package/server/utils/inventory-util.ts +1 -126
@@ -2,7 +2,7 @@ import { EntityManager, Equal, getConnection, In, IsNull, Not } from 'typeorm'
2
2
 
3
3
  import { Bizplace } from '@things-factory/biz-base'
4
4
  import { generateId } from '@things-factory/id-rule-base'
5
- import { Product, ProductDetail } from '@things-factory/product-base'
5
+ import { Product, ProductDetail, ProductBarcode } from '@things-factory/product-base'
6
6
  import {
7
7
  GenerateBatchPickInfo,
8
8
  ORDER_INVENTORY_STATUS,
@@ -28,12 +28,13 @@ import {
28
28
  Location,
29
29
  LOCATION_TYPE,
30
30
  Tote,
31
- TOTE_STATUS
31
+ TOTE_STATUS,
32
+ generateInventoryHistory
32
33
  } from '@things-factory/warehouse-base'
33
34
 
34
35
  import { TASK_NUMBER_RULE_TYPE, TASK_NUMBER_SETTING_KEY, WORKSHEET_STATUS, WORKSHEET_TYPE } from '../../constants'
35
36
  import { Worksheet, WorksheetDetail } from '../../entities'
36
- import { generateInventoryHistory, WorksheetNoGenerator } from '../../utils'
37
+ import { WorksheetNoGenerator } from '../../utils'
37
38
  import { VasWorksheetController } from '../vas/vas-worksheet-controller'
38
39
 
39
40
  export class PickingWorksheetController extends VasWorksheetController {
@@ -213,7 +214,7 @@ export class PickingWorksheetController extends VasWorksheetController {
213
214
  if (vasWorksheet) {
214
215
  await this.activateVAS(vasWorksheet.name, vasWorksheet.worksheetDetails)
215
216
  }
216
- } catch (e) { }
217
+ } catch (e) {}
217
218
 
218
219
  const pendingSplitOIs: OrderInventory[] = await this.trxMgr.getRepository(OrderInventory).find({
219
220
  where: { domain: this.domain, releaseGood, status: ORDER_INVENTORY_STATUS.PENDING_SPLIT }
@@ -428,11 +429,8 @@ export class PickingWorksheetController extends VasWorksheetController {
428
429
  .innerJoinAndSelect('oi.inventory', 'inv')
429
430
  .leftJoinAndSelect('oi.orderProduct', 'op')
430
431
  .innerJoinAndSelect('oi.product', 'prd')
431
- .leftJoinAndSelect(
432
- 'prd.productDetails',
433
- 'pd',
434
- 'pd.product_id = oi.product_id AND pd.deleted_at is null AND pd.packing_type = oi.packing_type AND pd.packing_size = oi.packing_size AND pd.uom = oi.uom'
435
- )
432
+ .innerJoinAndSelect('oi.productDetail', 'pd')
433
+ .innerJoinAndSelect('pd.productBarcodes', 'pb')
436
434
  .where('wd.name = :name', { name: worksheetDetailName })
437
435
  .andWhere('wd.domain_id = :domainId', { domainId: this.domain.id })
438
436
  .andWhere('wd.type = :type', { type: worksheetType })
@@ -441,17 +439,35 @@ export class PickingWorksheetController extends VasWorksheetController {
441
439
  .getOne()
442
440
 
443
441
  //validation to check matching worksheet detail based on name
444
- if (!worksheetDetail || !worksheetDetail.targetInventory)
445
- throw new Error(this.ERROR_MSG.FIND.NO_RESULT(worksheetDetailName))
442
+ if (!worksheetDetail) throw new Error(this.ERROR_MSG.FIND.NO_RESULT(worksheetDetailName))
443
+
444
+ const releaseGood: ReleaseGood = worksheetDetail.targetInventory.releaseGood
445
+ let targetInventory: OrderInventory = worksheetDetail.targetInventory
446
+ let targetProduct: OrderProduct = targetInventory.orderProduct
447
+ const product: Product = targetInventory.product
448
+ const matchProductBarcode: ProductBarcode = await this.trxMgr.getRepository(ProductBarcode).findOne({
449
+ where: { gtin: productBarcode },
450
+ relations: ['productDetail']
451
+ })
452
+ const productDetail: ProductDetail = targetInventory.productDetail
453
+ const productBarcodes: [ProductBarcode] = productDetail.productBarcodes
454
+ let inventory: Inventory = targetInventory.inventory
455
+ let bizplace: Bizplace = worksheetDetail.worksheet.bizplace
456
+ let pickedUomValue = pickedQty * productDetail.uomValue
457
+ let matchingProduct
446
458
 
447
459
  //validation to prevent duplicated picking
448
- if (worksheetDetail?.targetInventory?.status != ORDER_INVENTORY_STATUS.PICKING)
460
+ if (targetInventory?.status != ORDER_INVENTORY_STATUS.PICKING)
449
461
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `is done`))
450
462
 
451
- let matchingProduct = await this.getDirectQty(
463
+ if (!productBarcodes.find(itm => itm.gtin == productBarcode) && product?.isRequireSerialNumberScanningOutbound) {
464
+ throw new Error(this.ERROR_MSG.FIND.NO_RESULT(productBarcode))
465
+ }
466
+
467
+ matchingProduct = await this.getDirectQty(
452
468
  {
453
- ...worksheetDetail?.targetInventory?.product?.productDetails[0],
454
- product: worksheetDetail?.targetInventory?.product
469
+ ...productDetail,
470
+ product: targetInventory?.product
455
471
  },
456
472
  productBarcode,
457
473
  pickedQty
@@ -461,7 +477,7 @@ export class PickingWorksheetController extends VasWorksheetController {
461
477
  if (!matchingProduct) throw new Error(this.ERROR_MSG.FIND.NO_RESULT(productBarcode))
462
478
 
463
479
  pickedQty = matchingProduct.qty
464
- let pickedUomValue = matchingProduct.uomValue
480
+ pickedUomValue = matchingProduct.uomValue
465
481
 
466
482
  //validation to prevent over release
467
483
  if (
@@ -471,15 +487,24 @@ export class PickingWorksheetController extends VasWorksheetController {
471
487
  )
472
488
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `over release`))
473
489
 
474
- const releaseGood: ReleaseGood = worksheetDetail.targetInventory.releaseGood
490
+ targetInventory = await this.checkAndSetBinPicking(targetInventory, binLocation)
475
491
 
476
- let targetInventory: OrderInventory = worksheetDetail.targetInventory
477
- let targetProduct: OrderProduct = targetInventory.orderProduct
478
- let inventory: Inventory = targetInventory.inventory
479
- let bizplace: Bizplace = worksheetDetail.worksheet.bizplace
480
- const product: Product = targetInventory.product
492
+ // // search for matching product barcode
493
+ // const productDetails: ProductDetail[] = product?.productDetails.filter(detail => !detail.deletedAt)
494
+ // // scannedProductDetail can be child or gtin
495
+ // const scannedProductDetail: ProductDetail = productDetails.find(detail => detail.gtin == productBarcode)
496
+ // if (!scannedProductDetail) throw new Error(this.ERROR_MSG.FIND.NO_RESULT(productBarcode))
481
497
 
482
- targetInventory = await this.checkAndSetBinPicking(targetInventory, binLocation)
498
+ // // case for scanning parent packing type, packing size
499
+ // // when scannedProductDetail id is not the same as productDetail id, then it's not child gtin, proceed to get child qty
500
+ // if (scannedProductDetail.id !== productDetail.id && !product?.isRequireSerialNumberScanningOutbound) {
501
+ // let childQty = await this.getChildQty(productDetails, productBarcode, productDetail, scannedProductDetail)
502
+ // pickedQty *= childQty
503
+ // }
504
+
505
+ // if (pickedQty + targetInventory.pickedQty > releaseQty) {
506
+ // throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `over release`))
507
+ // }
483
508
 
484
509
  // for required outbound serial number scanning
485
510
  if (product?.isRequireSerialNumberScanningOutbound) {
@@ -527,6 +552,7 @@ export class PickingWorksheetController extends VasWorksheetController {
527
552
  inventoryItem.outboundOrderId = releaseGood.id
528
553
  inventoryItem.source = INVENTORY_ITEM_SOURCE.OUTBOUND
529
554
  inventoryItem.product = product
555
+ inventoryItem.productDetail = productDetail
530
556
  inventoryItem.inventory = inventory
531
557
  inventoryItem.domain = this.domain
532
558
 
@@ -692,13 +718,15 @@ export class PickingWorksheetController extends VasWorksheetController {
692
718
  'targetInventory.orderProduct',
693
719
  'targetInventory.inventory',
694
720
  'targetInventory.inventory.location',
695
- 'targetInventory.product'
721
+ 'targetInventory.product',
722
+ 'targetInventory.productDetail'
696
723
  ]
697
724
  )
698
725
 
699
726
  const releaseGood: ReleaseGood = worksheetDetail.targetInventory.releaseGood
700
727
  let targetInventory: OrderInventory = worksheetDetail.targetInventory
701
728
  const product: Product = targetInventory.product
729
+ const productDetail: ProductDetail = targetInventory.productDetail
702
730
  let inventory: Inventory = targetInventory.inventory
703
731
  let targetProduct: OrderProduct = targetInventory.orderProduct
704
732
  let bizplace: Bizplace = worksheetDetail.worksheet.bizplace
@@ -728,13 +756,13 @@ export class PickingWorksheetController extends VasWorksheetController {
728
756
  })
729
757
 
730
758
  let foundSerialNumber: InventoryItem = await this.trxMgr.getRepository(InventoryItem).findOne({
731
- where: { domain: this.domain, serialNumber: serialNumber, product },
732
- relations: ['product', 'inventory']
759
+ where: { domain: this.domain, serialNumber: serialNumber, productDetail },
760
+ relations: ['product', 'productDetail', 'inventory']
733
761
  })
734
762
 
735
763
  let scannedPalletIdInventory: Inventory = await this.trxMgr
736
764
  .getRepository(Inventory)
737
- .findOne({ where: { domain: this.domain, palletId }, relations: ['product'] })
765
+ .findOne({ where: { domain: this.domain, palletId }, relations: ['productDetail'] })
738
766
 
739
767
  if (foundSerialNumber) {
740
768
  if (foundSerialNumber.outboundOrderId) {
@@ -761,6 +789,7 @@ export class PickingWorksheetController extends VasWorksheetController {
761
789
  inventoryItem.source = INVENTORY_ITEM_SOURCE.OUTBOUND
762
790
  inventoryItem.outboundOrderId = releaseGood.id
763
791
  inventoryItem.product = product
792
+ inventoryItem.productDetail = productDetail
764
793
  inventoryItem.inventory = scannedPalletIdInventory
765
794
  inventoryItem.domain = this.domain
766
795
 
@@ -786,8 +815,7 @@ export class PickingWorksheetController extends VasWorksheetController {
786
815
  )
787
816
  } else if (
788
817
  scannedPalletIdInventory.batchId == inventory.batchId &&
789
- scannedPalletIdInventory.product.id == product.id &&
790
- scannedPalletIdInventory.product.packingType == product.packingType
818
+ scannedPalletIdInventory.productDetail.id == productDetail.id
791
819
  ) {
792
820
  //if replacement order inventory does not exist
793
821
  await this.serialNumberReplacement(
@@ -795,6 +823,7 @@ export class PickingWorksheetController extends VasWorksheetController {
795
823
  scannedPalletIdInventory,
796
824
  releaseGood,
797
825
  product,
826
+ productDetail,
798
827
  worksheetDetail,
799
828
  foundSerialNumber
800
829
  )
@@ -970,6 +999,8 @@ export class PickingWorksheetController extends VasWorksheetController {
970
999
  'worksheetDetails.targetInventory.releaseGood',
971
1000
  'worksheetDetails.targetInventory.inventory',
972
1001
  'worksheetDetails.targetInventory.inventory.location',
1002
+ 'worksheetDetails.targetInventory.productDetail',
1003
+ 'worksheetDetails.targetInventory.productDetail.product',
973
1004
  'worksheetDetails.targetInventory.product',
974
1005
  'worksheetDetails.targetInventory.product.productDetails',
975
1006
  'worksheetDetails.targetInventory.product.productDetails.childProductDetail'
@@ -977,49 +1008,51 @@ export class PickingWorksheetController extends VasWorksheetController {
977
1008
  })
978
1009
 
979
1010
  const worksheetDetails: WorksheetDetail[] = worksheet.worksheetDetails
980
- const product: Product = worksheetDetails
981
- .map((wsd: WorksheetDetail) => wsd.targetInventory.product)
982
- .find((product: Product) => product.id === inventory.product.id)
1011
+ const productDetail: ProductDetail = worksheetDetails
1012
+ .map(wsd => wsd.targetInventory.productDetail)
1013
+ .find(productDetail => productDetail.id === inventory.productDetail.id)
1014
+
1015
+ const product: Product = productDetail.product
983
1016
 
984
1017
  const batchId: string = inventory.batchId
985
- const packingType: string = inventory.packingType
986
- const packingSize: number = inventory.packingSize
987
1018
  let pickedQty: number = pickingQty ? pickingQty : 1
1019
+ let matchingProduct
988
1020
 
989
1021
  const targetInventories: OrderInventory[] = worksheetDetails
990
1022
  .map((wsd: WorksheetDetail) => wsd.targetInventory)
991
1023
  .filter(
992
1024
  (targetInventory: OrderInventory) =>
993
1025
  targetInventory.batchId === batchId &&
994
- targetInventory.packingType === packingType &&
995
1026
  targetInventory.inventory.cartonId === cartonId &&
996
- targetInventory.product.id === product.id
1027
+ targetInventory.productDetail.id === productDetail.id
997
1028
  )
998
1029
 
999
- // search for matching product barcode
1000
- const productDetails: ProductDetail[] = product?.productDetails.filter(detail => !detail.deletedAt)
1001
- const isMatchingBarcode: boolean = productDetails.map(detail => detail.gtin).includes(productBarcode)
1002
- if (!isMatchingBarcode) throw new Error(this.ERROR_MSG.FIND.NO_RESULT(`GTIN (${productBarcode})`))
1003
-
1004
- // case for scanning parent packing type, packing size
1005
- const foundProductDetail: ProductDetail = productDetails.find(
1006
- (detail: ProductDetail) =>
1007
- detail.gtin === productBarcode && detail.packingType === packingType && detail.packingSize == packingSize
1030
+ matchingProduct = await this.getDirectQty(
1031
+ {
1032
+ ...productDetail,
1033
+ product
1034
+ },
1035
+ productBarcode,
1036
+ pickedQty
1008
1037
  )
1009
1038
 
1010
- if (!foundProductDetail) {
1011
- const roProductDetail: ProductDetail = productDetails.find(
1012
- (parentDetail: ProductDetail) =>
1013
- parentDetail.packingType === packingType && parentDetail.packingSize == packingSize
1014
- )
1015
- if (!roProductDetail)
1016
- throw new Error(
1017
- this.ERROR_MSG.FIND.NO_RESULT(`Packing Type ( ${packingType}) or Packing Size (${packingSize})`)
1018
- )
1039
+ //validate matching product details based on scanned barcode
1040
+ if (!matchingProduct) throw new Error(this.ERROR_MSG.FIND.NO_RESULT(productBarcode))
1019
1041
 
1020
- let childQty = await this.getChildQty(productDetails, productBarcode, roProductDetail)
1021
- pickedQty *= childQty
1022
- }
1042
+ pickedQty = matchingProduct.qty
1043
+
1044
+ // // search for matching product barcode
1045
+ // const productDetails: ProductDetail[] = product?.productDetails.filter(detail => !detail.deletedAt)
1046
+ // // scannedProductDetail can be child or gtin
1047
+ // const scannedProductDetail: ProductDetail = productDetails.find(detail => detail.gtin == productBarcode)
1048
+ // if (!scannedProductDetail) throw new Error(this.ERROR_MSG.FIND.NO_RESULT(productBarcode))
1049
+
1050
+ // // case for scanning parent packing type, packing size
1051
+ // // when scannedProductDetail id is not the same as productDetail id, then it's not child gtin, proceed to get child qty
1052
+ // if (scannedProductDetail.id !== productDetail.id) {
1053
+ // let childQty = await this.getChildQty(productDetails, productBarcode, productDetail, scannedProductDetail)
1054
+ // pickedQty *= childQty
1055
+ // }
1023
1056
 
1024
1057
  const sumOfReleaseQty: number = targetInventories
1025
1058
  .map((oi: OrderInventory) => oi.releaseQty)
@@ -1404,7 +1437,7 @@ export class PickingWorksheetController extends VasWorksheetController {
1404
1437
  await this.trxMgr.getRepository(WorksheetDetail).delete(worksheetDetail.ild)
1405
1438
  await this.trxMgr.getRepository(OrderInventory).delete(targetInventory.id)
1406
1439
  }
1407
- } catch (e) { }
1440
+ } catch (e) {}
1408
1441
  }
1409
1442
 
1410
1443
  private async serialNumberReplacement(
@@ -1412,6 +1445,7 @@ export class PickingWorksheetController extends VasWorksheetController {
1412
1445
  scannedPalletIdInventory,
1413
1446
  releaseGood,
1414
1447
  product,
1448
+ productDetail,
1415
1449
  worksheetDetail,
1416
1450
  foundSerialNumber
1417
1451
  ) {
@@ -1476,6 +1510,7 @@ export class PickingWorksheetController extends VasWorksheetController {
1476
1510
  releaseUomValue: newOrderInventoryReleaseUomValue,
1477
1511
  pickedQty: 1,
1478
1512
  product,
1513
+ productDetail,
1479
1514
  inventory: scannedPalletIdInventory,
1480
1515
  creator: this.user,
1481
1516
  updater: this.user
@@ -1519,7 +1554,7 @@ export class PickingWorksheetController extends VasWorksheetController {
1519
1554
  await this.trxMgr.getRepository(WorksheetDetail).delete(worksheetDetail.id)
1520
1555
  await this.trxMgr.getRepository(OrderInventory).delete(targetInventory.id)
1521
1556
  }
1522
- } catch (e) { }
1557
+ } catch (e) {}
1523
1558
  }
1524
1559
 
1525
1560
  private async toteScanning(toteNo, targetProduct, targetInventory, pickedQty, releaseGood, bizplace) {
@@ -1,6 +1,6 @@
1
1
  import { In, IsNull } from 'typeorm'
2
2
 
3
- import { Product, ProductDetail } from '@things-factory/product-base'
3
+ import { Product, ProductDetail, ProductBarcode } from '@things-factory/product-base'
4
4
  import {
5
5
  ORDER_INVENTORY_STATUS,
6
6
  ORDER_STATUS,
@@ -85,9 +85,8 @@ export class SortingWorksheetController extends VasWorksheetController {
85
85
  .innerJoinAndSelect('worksheet.worksheetDetails', 'worksheetDetails')
86
86
  .innerJoinAndSelect('worksheetDetails.targetInventory', 'targetInventory')
87
87
  .innerJoinAndSelect('targetInventory.product', 'product')
88
- .innerJoinAndSelect('product.productDetails', 'productDetails')
89
- .leftJoinAndSelect('productDetails.childProductDetail', 'childProductDetail')
90
88
  .leftJoinAndSelect('targetInventory.orderProduct', 'orderProduct')
89
+ .leftJoinAndSelect('targetInventory.productDetail', 'productDetail')
91
90
  .leftJoinAndSelect('targetInventory.bizplace', 'bizplace')
92
91
  .leftJoinAndSelect('targetInventory.inventory', 'inventory')
93
92
  .leftJoinAndSelect('targetInventory.releaseGood', 'releaseGood')
@@ -96,7 +95,6 @@ export class SortingWorksheetController extends VasWorksheetController {
96
95
  .andWhere('worksheet.type = :type', { type: WORKSHEET_TYPE.SORTING })
97
96
  .andWhere('worksheet.status = :status', { status: WORKSHEET_STATUS.EXECUTING })
98
97
  .andWhere('releaseGood.name = :rg', { rg: releaseGoodNo })
99
- .andWhere('productDetails.gtin = :gtin', { gtin: productBarcode })
100
98
  .getOne()
101
99
 
102
100
  if (!worksheet) {
@@ -105,17 +103,15 @@ export class SortingWorksheetController extends VasWorksheetController {
105
103
 
106
104
  const worksheetDetails = worksheet.worksheetDetails
107
105
  const orderInventories: OrderInventory[] = worksheetDetails.map((wsd: WorksheetDetail) => wsd.targetInventory)
108
- const productDetails: ProductDetail[] = orderInventories[0].product.productDetails
109
- const scannedProductDetail: ProductDetail = productDetails.find(itm => itm.gtin == productBarcode)
106
+ const scanProductBarcode: ProductBarcode = await this.trxMgr.getRepository(ProductBarcode).findOne({
107
+ where: { gtin: productBarcode },
108
+ relations: ['productDetail', 'productDetail.childProductDetail']
109
+ })
110
+ const scannedProductDetail: ProductDetail = scanProductBarcode.productDetail
110
111
  const scannedChildProductDetail: ProductDetail = scannedProductDetail.childProductDetail
111
112
 
112
113
  //find matching order inventories based on scanned product detail
113
- let matchingOIs = orderInventories.filter(
114
- oi =>
115
- oi.packingType == scannedProductDetail.packingType &&
116
- oi.packingSize == scannedProductDetail.packingSize &&
117
- oi.uom == scannedProductDetail.uom
118
- )
114
+ let matchingOIs = orderInventories.filter(oi => oi.productDetail.id == scannedProductDetail.id)
119
115
 
120
116
  let productDetail = scannedProductDetail
121
117
 
@@ -125,12 +121,7 @@ export class SortingWorksheetController extends VasWorksheetController {
125
121
  if (!scannedChildProductDetail) {
126
122
  throw new Error(this.ERROR_MSG.FIND.NO_RESULT(productBarcode))
127
123
  }
128
- matchingOIs = orderInventories.filter(
129
- oi =>
130
- oi.packingType == scannedChildProductDetail.packingType &&
131
- oi.packingSize == scannedChildProductDetail.packingSize &&
132
- oi.uom == scannedChildProductDetail.uom
133
- )
124
+ matchingOIs = orderInventories.filter(oi => oi.productDetail.id == scannedChildProductDetail.id)
134
125
 
135
126
  productDetail = scannedChildProductDetail
136
127
 
@@ -295,7 +286,8 @@ export class SortingWorksheetController extends VasWorksheetController {
295
286
  'worksheetDetails.targetInventory.inventory.product',
296
287
  'worksheetDetails.targetInventory.inventory.product.productDetails',
297
288
  'worksheetDetails.targetInventory.inventory.product.productDetails.product',
298
- 'worksheetDetails.targetInventory.releaseGood'
289
+ 'worksheetDetails.targetInventory.releaseGood',
290
+ 'worksheetDetails.targetInventory.productDetail'
299
291
  ]
300
292
  })
301
293
 
@@ -315,6 +307,7 @@ export class SortingWorksheetController extends VasWorksheetController {
315
307
  const inventory: Inventory = matchingOI.inventory
316
308
  const releaseGood: ReleaseGood = matchingOI.releaseGood
317
309
  const product: Product = matchingOI.inventory.product
310
+ const productDetail: ProductDetail = matchingOI.productDetail
318
311
  const packingType: string = matchingOI.packingType
319
312
  const packingSize: number = matchingOI.packingSize
320
313
 
@@ -324,8 +317,7 @@ export class SortingWorksheetController extends VasWorksheetController {
324
317
  }
325
318
 
326
319
  let foundSerialNumber: InventoryItem = await this.trxMgr.getRepository(InventoryItem).findOne({
327
- where: { domain: this.domain, serialNumber: serialNumber, product },
328
- relations: ['product', 'inventory']
320
+ where: { domain: this.domain, serialNumber: serialNumber, productDetail }
329
321
  })
330
322
 
331
323
  if (foundSerialNumber) {
@@ -349,6 +341,7 @@ export class SortingWorksheetController extends VasWorksheetController {
349
341
  inventoryItem.source = INVENTORY_ITEM_SOURCE.OUTBOUND
350
342
  inventoryItem.outboundOrderId = releaseGood.id
351
343
  inventoryItem.product = product
344
+ inventoryItem.productDetail = productDetail
352
345
  inventoryItem.inventory = inventory
353
346
  inventoryItem.domain = this.domain
354
347
 
@@ -22,7 +22,8 @@ import {
22
22
  InventoryNoGenerator,
23
23
  Location,
24
24
  LOCATION_TYPE,
25
- Warehouse
25
+ Warehouse,
26
+ generateInventoryHistory
26
27
  } from '@things-factory/warehouse-base'
27
28
 
28
29
  import { WORKSHEET_STATUS, WORKSHEET_TYPE } from '../../constants'
@@ -36,7 +37,6 @@ import {
36
37
  RefOrderType
37
38
  } from '../../graphql/resolvers/worksheet/vas-transactions'
38
39
  import { PackingUnits } from '../../graphql/resolvers/worksheet/vas-transactions/interfaces/repackaging'
39
- import { generateInventoryHistory } from '../../utils'
40
40
  import { ReferenceOrderType, WorksheetController } from '../worksheet-controller'
41
41
 
42
42
  type CompleteTransactionType = (trxMgr: EntityManager, orderVas: OrderVas, user: User) => Promise<void>
@@ -19,11 +19,17 @@ import {
19
19
  VasOrder
20
20
  } from '@things-factory/sales-base'
21
21
  import { Domain } from '@things-factory/shell'
22
- import { Inventory, INVENTORY_STATUS, InventoryItem, Pallet } from '@things-factory/warehouse-base'
22
+ import {
23
+ Inventory,
24
+ INVENTORY_STATUS,
25
+ InventoryItem,
26
+ Pallet,
27
+ generateInventoryHistory
28
+ } from '@things-factory/warehouse-base'
23
29
 
24
30
  import { WORKSHEET_STATUS, WORKSHEET_TYPE } from '../constants'
25
31
  import { Worksheet, WorksheetDetail } from '../entities'
26
- import { generateInventoryHistory, WorksheetNoGenerator } from '../utils'
32
+ import { WorksheetNoGenerator } from '../utils'
27
33
 
28
34
  export type ReferenceOrderType = ArrivalNotice | ReleaseGood | VasOrder | InventoryCheck | DeliveryOrder | ReturnOrder
29
35
  export type OrderTargetTypes = OrderProduct | OrderInventory | OrderVas
@@ -590,8 +596,7 @@ export class WorksheetController {
590
596
  return worksheet
591
597
  }
592
598
 
593
- // @chernhaoee I think the naming of this function is not proper. Seems like it should be something like "updateLoadingWorksheet" since the logic targets only Loading Order Target
594
- async updateWorksheet(
599
+ async updateLoadWorksheet(
595
600
  worksheetType: string,
596
601
  refOrder: ReferenceOrderType,
597
602
  worksheet: Worksheet,
@@ -1006,11 +1011,9 @@ export class WorksheetController {
1006
1011
  async getChildQty(
1007
1012
  productDetails: ProductDetail[],
1008
1013
  productBarcode: string,
1009
- orderProductDetail: ProductDetail
1014
+ orderProductDetail: ProductDetail,
1015
+ scannedProductDetail: ProductDetail
1010
1016
  ): Promise<number> {
1011
- const scannedProductDetail: ProductDetail = productDetails.find(
1012
- (productDetail: ProductDetail) => productDetail.gtin === productBarcode
1013
- )
1014
1017
  let hasChildRelation: boolean = Boolean(scannedProductDetail?.childProductDetail)
1015
1018
  let hasMatchingChild: boolean
1016
1019
  let childQty: number
@@ -1061,16 +1064,18 @@ export class WorksheetController {
1061
1064
  WITH RECURSIVE cte as (
1062
1065
  select * from (
1063
1066
  select pd2.product_id as "productId", pd2.id, pd2.packing_size as "packingSize",
1064
- pd2.packing_type as "packingType", pd2.uom as "uom", (pd2.uom_value * $2::float) as "uomValue", $2::float as "qty", pd2.gtin
1067
+ pd2.packing_type as "packingType", pd2.uom as "uom", (pd2.uom_value * $2::float) as "uomValue", $2::float as "qty", pb.gtin
1065
1068
  from product_details pd
1066
1069
  inner join product_details pd2 on pd.product_id = pd2.product_id and pd.packing_type = pd2.packing_type and pd.packing_size = pd2.packing_size and pd.uom = pd2.uom
1070
+ inner join product_barcodes pb on pb.product_detail_id = pd2.id
1067
1071
  where pd.id = $1
1068
1072
  ) as dt
1069
1073
  union all
1070
1074
  select pd.product_id as "productId", pd.id, pd.packing_size as "packingSize",
1071
1075
  pd.packing_type as "packingType", pd.uom,
1072
- dt1.qty * pd.packing_size * pd.uom_value as "uomValue", dt1.qty * pd.packing_size as "qty", pd.gtin
1076
+ dt1.qty * pd.packing_size * pd.uom_value as "uomValue", dt1.qty * pd.packing_size as "qty", pb.gtin
1073
1077
  from product_details pd
1078
+ inner join product_barcodes pb on pb.product_detail_id = pd.id
1074
1079
  inner join cte dt1 on dt1.id = pd.child_product_detail_id
1075
1080
  where pd.deleted_at is null
1076
1081
  )
@@ -1,8 +1,8 @@
1
+ import { WarehouseBizplaceOnhandInventory } from './warehouse-bizplace-onhand-inventory'
1
2
  import { Worksheet } from './worksheet'
2
3
  import { WorksheetDetail } from './worksheet-detail'
3
4
  import { WorksheetMovement } from './worksheet-movement'
4
- import { WarehouseBizplaceOnhandInventory } from './warehouse-bizplace-onhand-inventory'
5
5
 
6
6
  export const entities = [Worksheet, WorksheetDetail, WorksheetMovement, WarehouseBizplaceOnhandInventory]
7
7
 
8
- export { Worksheet, WorksheetDetail, WorksheetMovement }
8
+ export { WarehouseBizplaceOnhandInventory, Worksheet, WorksheetDetail, WorksheetMovement }
@@ -2,55 +2,23 @@ import { ViewColumn, ViewEntity } from 'typeorm'
2
2
 
3
3
  @ViewEntity({
4
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
- )
5
+ select d.name as "domain_name", b.name as "bizplace_name", src.* from (
37
6
  -- SINGLE ITEM INVENTORY QUERY
38
7
  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",
8
+ i.domain_id as "domain_id",
9
+ i.bizplace_id as "bizplace_id",
10
+ i.packing_type as "packing_type",
11
+ i.packing_size as "packing_size",
43
12
  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",
13
+ i.product_id as "product_id",
14
+ null as "product_bundle_id",
15
+ COALESCE(SUM(COALESCE(i.qty, 0)) - SUM(COALESCE(i.locked_qty, 0))) AS "remain_qty",
16
+ COALESCE(SUM(COALESCE(i.uom_value, 0)) - SUM(COALESCE(i.locked_uom_value, 0))) AS "remain_uom_value",
48
17
  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"
18
+ COALESCE(sum(COALESCE(i.uom_value, 0::double precision))) AS "uom_value",
19
+ 'SINGLE' AS "group_type"
51
20
  FROM inventories i
52
21
  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
22
  WHERE i.status = 'STORED'
55
23
  GROUP by
56
24
  i.domain_id,
@@ -62,29 +30,28 @@ import { ViewColumn, ViewEntity } from 'typeorm'
62
30
  union all
63
31
  -- BUNDLE ITEM INVENTORY QUERY
64
32
  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",
33
+ pbs.domain_id as "domain_id",
34
+ pbs.bizplace_id as "bizplace_id",
35
+ pb.packing_type as "packing_type",
36
+ pb.packing_size as "packing_size",
69
37
  '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",
38
+ null as "product_id",
39
+ pb.id AS "product_bundle_id",
40
+ COALESCE(MIN(FLOOR(pbs."available_qty")),0) AS "remain_qty",
41
+ COALESCE(MIN(FLOOR(pbs."available_uom_value")),0) AS "remain_uom_value",
74
42
  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"
43
+ COALESCE(MIN(FLOOR(pbs."uom_value")), 0::double precision) AS "uom_value",
44
+ 'BUNDLE' AS "group_type"
77
45
  FROM product_bundles pb
78
46
  INNER JOIN (
79
47
  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",
48
+ (SUM(COALESCE(i.qty, 0)) - SUM(COALESCE(i.locked_qty, 0))) / min(pbs.bundle_qty) AS "available_qty",
49
+ (SUM(COALESCE(i.uom_value, 0)) - SUM(COALESCE(i.locked_uom_value, 0))) / min(pbs.bundle_qty) AS "available_uom_value",
82
50
  (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"
51
+ (sum(COALESCE(i.uom_value, 0::double precision))) / min(pbs.bundle_qty)::double precision AS "uom_value"
84
52
  FROM product_bundle_settings pbs
85
53
  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
54
+ INNER JOIN locations l ON i.location_id = l.id AND i.domain_id = l.domain_id AND l.type NOT IN ('QUARANTINE', 'RESERVE')
88
55
  GROUP by
89
56
  i.domain_id,
90
57
  i.bizplace_id,
@@ -101,14 +68,13 @@ import { ViewColumn, ViewEntity } from 'typeorm'
101
68
  pb.id
102
69
  )
103
70
  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
71
+ inner join domains d on d.id = src."domain_id"
72
+ inner join bizplaces b on b.id = src."bizplace_id"
73
+ where src."remain_qty" >= 0
107
74
  and src."qty" > 0
108
- order by src."domainId"
75
+ order by src."domain_id"
109
76
  `
110
77
  })
111
-
112
78
  export class WarehouseBizplaceOnhandInventory {
113
79
  @ViewColumn()
114
80
  domainName: string