@things-factory/worksheet-base 4.3.367 → 4.3.369

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 (25) hide show
  1. package/dist-server/controllers/outbound/picking-worksheet-controller.js +111 -140
  2. package/dist-server/controllers/outbound/picking-worksheet-controller.js.map +1 -1
  3. package/dist-server/entities/active-worksheet-picking-view.js +141 -0
  4. package/dist-server/entities/active-worksheet-picking-view.js.map +1 -0
  5. package/dist-server/entities/index.js +4 -1
  6. package/dist-server/entities/index.js.map +1 -1
  7. package/dist-server/graphql/resolvers/worksheet/picking/activate-picking.js +64 -55
  8. package/dist-server/graphql/resolvers/worksheet/picking/activate-picking.js.map +1 -1
  9. package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js +3 -0
  10. package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js.map +1 -1
  11. package/dist-server/graphql/resolvers/worksheet/picking/fetch-and-assign-picking-task.js +2 -1
  12. package/dist-server/graphql/resolvers/worksheet/picking/fetch-and-assign-picking-task.js.map +1 -1
  13. package/dist-server/graphql/resolvers/worksheet/picking-worksheet.js +73 -71
  14. package/dist-server/graphql/resolvers/worksheet/picking-worksheet.js.map +1 -1
  15. package/dist-server/graphql/resolvers/worksheet/worksheet.js +0 -3
  16. package/dist-server/graphql/resolvers/worksheet/worksheet.js.map +1 -1
  17. package/package.json +4 -4
  18. package/server/controllers/outbound/picking-worksheet-controller.ts +134 -167
  19. package/server/entities/active-worksheet-picking-view.ts +118 -0
  20. package/server/entities/index.ts +4 -0
  21. package/server/graphql/resolvers/worksheet/picking/activate-picking.ts +73 -67
  22. package/server/graphql/resolvers/worksheet/picking/complete-picking.ts +4 -1
  23. package/server/graphql/resolvers/worksheet/picking/fetch-and-assign-picking-task.ts +3 -2
  24. package/server/graphql/resolvers/worksheet/picking-worksheet.ts +82 -80
  25. package/server/graphql/resolvers/worksheet/worksheet.ts +0 -3
@@ -298,6 +298,9 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
298
298
  catch (error) {
299
299
  throw error;
300
300
  }
301
+ finally {
302
+ entities_1.ActiveWorksheetPickingView.refreshView();
303
+ }
301
304
  return worksheets;
302
305
  }
303
306
  async activateBatchPicking(worksheetNo) {
@@ -498,111 +501,88 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
498
501
  }, { status: sales_base_1.ORDER_INVENTORY_STATUS.PENDING_SPLIT, updater: this.user, updatedAt: new Date() });
499
502
  }
500
503
  async scanProductPicking(worksheetDetailName, worksheetType, productBarcode, cartonId, binLocation, serialNumber, toteNo, pickedQty = 1) {
501
- var _a;
502
504
  try {
503
505
  //find existing worksheet detail
504
- let worksheetDetail = await this.trxMgr
505
- .getRepository(entities_1.WorksheetDetail)
506
- .createQueryBuilder('wd')
507
- .innerJoinAndSelect('wd.worksheet', 'ws')
508
- .innerJoinAndSelect('ws.bizplace', 'bz')
509
- .innerJoinAndSelect('wd.targetInventory', 'oi')
510
- .innerJoinAndSelect('oi.releaseGood', 'rg')
511
- .innerJoinAndSelect('oi.inventory', 'inv')
512
- .leftJoinAndSelect('oi.orderProduct', 'op')
513
- .innerJoinAndSelect('oi.product', 'prd')
514
- .innerJoinAndSelect('oi.productDetail', 'pd')
515
- .innerJoinAndSelect('pd.productBarcodes', 'pb')
516
- .where('wd.name = :name', { name: worksheetDetailName })
517
- .andWhere('wd.domain_id = :domainId', { domainId: this.domain.id })
518
- .andWhere('wd.type = :type', { type: worksheetType })
519
- .andWhere('wd.status = :status', { status: constants_1.WORKSHEET_STATUS.EXECUTING })
520
- .andWhere('inv.carton_id = :cartonId', { cartonId: cartonId })
521
- .getOne();
506
+ let worksheetDetailFilters = [
507
+ { query: 'mawp."worksheetDetailName"', value: worksheetDetailName },
508
+ { query: 'mawp."domainId"', value: this.domain.id },
509
+ { query: 'mawp."inventoryCartonId"', value: cartonId }
510
+ // { query: 'mawp."gtin"', value: productBarcode }
511
+ ];
512
+ let worksheetDetailRaw = await this.trxMgr.query(`
513
+ select * from active_worksheet_picking_views mawp
514
+ where 1 = 1
515
+ and
516
+ ${worksheetDetailFilters.map((data, idx) => {
517
+ return `${data.query} = $${idx + 1}`;
518
+ }).join(' AND ')}
519
+ `, worksheetDetailFilters.map((data, idx) => {
520
+ return data.value;
521
+ }));
522
522
  //validation to check matching worksheet detail based on name
523
- if (!worksheetDetail)
523
+ if ((worksheetDetailRaw.length < 1))
524
524
  throw new Error(this.ERROR_MSG.FIND.NO_RESULT(worksheetDetailName));
525
- const releaseGood = worksheetDetail.targetInventory.releaseGood;
526
- let targetInventory = worksheetDetail.targetInventory;
527
- let targetProduct = targetInventory.orderProduct;
528
- const product = targetInventory.product;
529
- const matchProductBarcode = await this.trxMgr.getRepository(product_base_1.ProductBarcode).findOne({
530
- where: { gtin: productBarcode },
531
- relations: ['productDetail']
532
- });
533
- const productDetail = targetInventory.productDetail;
534
- const productBarcodes = productDetail.productBarcodes;
535
- let inventory = targetInventory.inventory;
536
- let bizplace = worksheetDetail.worksheet.bizplace;
537
- let pickedUomValue = pickedQty * productDetail.uomValue;
538
- let matchingProduct;
539
- // validation to prevent picking if the inventory is involved in cycle count
540
- let inventoryCheckItem = await this.trxMgr.getRepository(sales_base_1.InventoryCheckItem).findOne({
541
- where: {
542
- domain: this.domain,
543
- inventory: inventory.id,
544
- status: (0, typeorm_1.In)([
545
- sales_base_1.INVENTORY_CHECK_ITEM_STATUS.PENDING,
546
- sales_base_1.INVENTORY_CHECK_ITEM_STATUS.INSPECTING,
547
- sales_base_1.INVENTORY_CHECK_ITEM_STATUS.INSPECTED,
548
- sales_base_1.INVENTORY_CHECK_ITEM_STATUS.NOT_TALLY,
549
- sales_base_1.INVENTORY_CHECK_ITEM_STATUS.GROUP_NOT_TALLY,
550
- sales_base_1.INVENTORY_CHECK_ITEM_STATUS.MISSING,
551
- sales_base_1.INVENTORY_CHECK_ITEM_STATUS.ADDED
552
- ])
553
- }
554
- });
555
- if (inventoryCheckItem) {
525
+ let worksheetDetailInfos = worksheetDetailRaw[0];
526
+ let targetInventory = await this.trxMgr.getRepository(sales_base_1.OrderInventory).findOne({ where: { id: worksheetDetailInfos.orderInventoryId } });
527
+ const inventory = await this.trxMgr.getRepository(warehouse_base_1.Inventory).findOne({ where: { id: worksheetDetailInfos.inventoryId } });
528
+ let targetProduct = { id: worksheetDetailInfos.targetProductId };
529
+ let bizplace = { id: worksheetDetailInfos.bizplaceId };
530
+ const releaseGood = { id: worksheetDetailInfos.releaseGoodId };
531
+ let matchingProduct, pickedUomValue;
532
+ // // validation to prevent picking if the inventory is involved in cycle count
533
+ const inventoryCheckStatus = new Set([
534
+ sales_base_1.INVENTORY_CHECK_ITEM_STATUS.PENDING,
535
+ sales_base_1.INVENTORY_CHECK_ITEM_STATUS.INSPECTING,
536
+ sales_base_1.INVENTORY_CHECK_ITEM_STATUS.INSPECTED,
537
+ sales_base_1.INVENTORY_CHECK_ITEM_STATUS.NOT_TALLY,
538
+ sales_base_1.INVENTORY_CHECK_ITEM_STATUS.GROUP_NOT_TALLY,
539
+ sales_base_1.INVENTORY_CHECK_ITEM_STATUS.MISSING,
540
+ sales_base_1.INVENTORY_CHECK_ITEM_STATUS.ADDED
541
+ ]);
542
+ if (inventoryCheckStatus.has(worksheetDetailInfos.inventoryCheckItemStatus)) {
556
543
  throw new Error(`Inventory currently involved in an ongoing cycle count. Please complete the cycle count to proceed with picking.`);
557
544
  }
558
545
  //validation to prevent duplicated picking
559
- if ((targetInventory === null || targetInventory === void 0 ? void 0 : targetInventory.status) != sales_base_1.ORDER_INVENTORY_STATUS.PICKING)
546
+ if (targetInventory.status != sales_base_1.ORDER_INVENTORY_STATUS.PICKING)
560
547
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `is done`));
561
- if (!productBarcodes.find(itm => itm.gtin == productBarcode) && (product === null || product === void 0 ? void 0 : product.isRequireSerialNumberScanningOutbound)) {
562
- throw new Error(this.ERROR_MSG.FIND.NO_RESULT(productBarcode));
548
+ // if (!productBarcodes.find(itm => itm.gtin == productBarcode) && product?.isRequireSerialNumberScanningOutbound) {
549
+ // throw new Error(this.ERROR_MSG.FIND.NO_RESULT(productBarcode))
550
+ // }
551
+ matchingProduct = worksheetDetailRaw.find(x => x.gtin === productBarcode);
552
+ if (matchingProduct) {
553
+ pickedUomValue = pickedQty * (matchingProduct.uomValue || 1);
563
554
  }
564
- matchingProduct = await this.getDirectQty(Object.assign(Object.assign({}, productDetail), { product: targetInventory === null || targetInventory === void 0 ? void 0 : targetInventory.product }), productBarcode, pickedQty);
565
- //validate matching product details based on scanned barcode
566
- if (!matchingProduct)
567
- throw new Error(this.ERROR_MSG.FIND.NO_RESULT(productBarcode));
568
- pickedQty = matchingProduct.qty;
569
- pickedUomValue = matchingProduct.uomValue;
570
- //validation to prevent over release
571
- if (!(worksheetDetail === null || worksheetDetail === void 0 ? void 0 : worksheetDetail.targetInventory) ||
572
- (worksheetDetail === null || worksheetDetail === void 0 ? void 0 : worksheetDetail.targetInventory.inventory.qty) < 1 ||
573
- pickedQty + (((_a = worksheetDetail.targetInventory) === null || _a === void 0 ? void 0 : _a.pickedQty) || 0) > worksheetDetail.targetInventory.releaseQty)
555
+ else {
556
+ matchingProduct = await this.getDirectQty({ id: worksheetDetailInfos.productDetailId }, productBarcode, pickedQty);
557
+ //validate matching product details based on scanned barcode
558
+ if (!matchingProduct)
559
+ throw new Error(this.ERROR_MSG.FIND.NO_RESULT(productBarcode));
560
+ pickedQty = matchingProduct.qty;
561
+ pickedUomValue = matchingProduct.uomValue;
562
+ }
563
+ // //validation to prevent over release
564
+ if (!targetInventory)
565
+ throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `inventory not assigned`));
566
+ // //validation to prevent over release
567
+ if (inventory.qty < 1 || pickedQty + ((targetInventory === null || targetInventory === void 0 ? void 0 : targetInventory.pickedQty) || 0) > targetInventory.releaseQty)
574
568
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `over release`));
575
569
  targetInventory = await this.checkAndSetBinPicking(targetInventory, binLocation);
576
- // // search for matching product barcode
577
- // const productDetails: ProductDetail[] = product?.productDetails.filter(detail => !detail.deletedAt)
578
- // // scannedProductDetail can be child or gtin
579
- // const scannedProductDetail: ProductDetail = productDetails.find(detail => detail.gtin == productBarcode)
580
- // if (!scannedProductDetail) throw new Error(this.ERROR_MSG.FIND.NO_RESULT(productBarcode))
581
- // // case for scanning parent packing type, packing size
582
- // // when scannedProductDetail id is not the same as productDetail id, then it's not child gtin, proceed to get child qty
583
- // if (scannedProductDetail.id !== productDetail.id && !product?.isRequireSerialNumberScanningOutbound) {
584
- // let childQty = await this.getChildQty(productDetails, productBarcode, productDetail, scannedProductDetail)
585
- // pickedQty *= childQty
586
- // }
587
- // if (pickedQty + targetInventory.pickedQty > releaseQty) {
588
- // throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `over release`))
589
- // }
590
570
  // for required outbound serial number scanning
591
- if (product === null || product === void 0 ? void 0 : product.isRequireSerialNumberScanningOutbound) {
571
+ if (worksheetDetailInfos === null || worksheetDetailInfos === void 0 ? void 0 : worksheetDetailInfos.productIsRequireSerialNumberScanningOutbound) {
592
572
  if (!serialNumber || serialNumber == '') {
593
573
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `require serial number`));
594
574
  }
595
575
  let totalInventoryItems = await this.trxMgr.getRepository(warehouse_base_1.InventoryItem).count({
596
576
  where: {
597
- inventory,
577
+ inventory: { id: worksheetDetailInfos.inventoryId },
598
578
  status: (0, typeorm_1.Not)((0, typeorm_1.In)([warehouse_base_1.INVENTORY_STATUS.TERMINATED, warehouse_base_1.INVENTORY_STATUS.PICKED]))
599
579
  }
600
580
  });
601
581
  let foundSerialNumber = await this.trxMgr
602
582
  .getRepository(warehouse_base_1.InventoryItem)
603
- .findOne({ where: { domain: this.domain, serialNumber: serialNumber, product } });
583
+ .findOne({ where: { domain: this.domain, serialNumber: serialNumber, product: { id: worksheetDetailInfos.productId } } });
604
584
  if (foundSerialNumber) {
605
- if (foundSerialNumber.inventoryId !== inventory.id) {
585
+ if (foundSerialNumber.inventoryId !== worksheetDetailInfos.inventoryId) {
606
586
  throw new Error('Serial Number scanned is in another inventory');
607
587
  }
608
588
  if (foundSerialNumber.outboundOrderId) {
@@ -615,7 +595,7 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
615
595
  }
616
596
  foundSerialNumber.status = warehouse_base_1.INVENTORY_STATUS.PICKING;
617
597
  foundSerialNumber.updater = this.user;
618
- foundSerialNumber.outboundOrderId = releaseGood.id;
598
+ foundSerialNumber.outboundOrderId = worksheetDetailInfos.releaseGoodId;
619
599
  await this.trxMgr.getRepository(warehouse_base_1.InventoryItem).save(foundSerialNumber);
620
600
  }
621
601
  else {
@@ -626,11 +606,11 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
626
606
  inventoryItem.name = warehouse_base_1.InventoryNoGenerator.inventoryItemName();
627
607
  inventoryItem.serialNumber = serialNumber;
628
608
  inventoryItem.status = warehouse_base_1.INVENTORY_STATUS.PICKING;
629
- inventoryItem.outboundOrderId = releaseGood.id;
609
+ inventoryItem.outboundOrderId = worksheetDetailInfos.releaseGoodId;
630
610
  inventoryItem.source = warehouse_base_1.INVENTORY_ITEM_SOURCE.OUTBOUND;
631
- inventoryItem.product = product;
632
- inventoryItem.productDetail = productDetail;
633
- inventoryItem.inventory = inventory;
611
+ inventoryItem.product = { id: worksheetDetailInfos.productId };
612
+ inventoryItem.productDetail = { id: worksheetDetailInfos.productDetailId };
613
+ inventoryItem.inventory = { id: worksheetDetailInfos.inventoryId };
634
614
  inventoryItem.domain = this.domain;
635
615
  await this.trxMgr.getRepository(warehouse_base_1.InventoryItem).save(inventoryItem);
636
616
  }
@@ -649,11 +629,9 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
649
629
  updater: this.user,
650
630
  pickedBy: this.user.name,
651
631
  pickedByUser: this.user,
652
- pickedAt: new Date()
632
+ pickedAt: new Date(),
633
+ status: () => `case when release_qty = "picked_qty" + ${pickedQty} then '${sales_base_1.ORDER_INVENTORY_STATUS.PICKED}' else status end`
653
634
  };
654
- if (targetInventory.pickedQty == releaseQty) {
655
- updateOiObj['status'] = sales_base_1.ORDER_INVENTORY_STATUS.PICKED;
656
- }
657
635
  if (targetInventory.binLocation) {
658
636
  updateOiObj['binLocation'] = targetInventory.binLocation;
659
637
  }
@@ -666,68 +644,61 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
666
644
  .andWhere(`picked_qty + :pickedQty <= release_qty`, { pickedQty })
667
645
  .execute();
668
646
  if (targetInventory.pickedQty == releaseQty) {
669
- //update worksheet details only when line item picking complete
670
- await this.trxMgr
671
- .getRepository(entities_1.WorksheetDetail)
672
- .createQueryBuilder()
673
- .update(entities_1.WorksheetDetail)
674
- .set({
675
- status: constants_1.WORKSHEET_STATUS.DONE,
676
- updater: this.user,
677
- updatedAt: new Date()
678
- })
679
- .where('id = :id', { id: worksheetDetail.id })
680
- .execute();
681
647
  (0, typeorm_1.getConnection)().transaction(async (tx) => {
682
- let releaseUomValue = Math.round((pickedUomValue / pickedQty) * releaseQty * 100) / 100;
683
- let updateInvObj = {
684
- qty: () => `"qty" - ${releaseQty}`,
685
- lockedQty: () => `"locked_qty" - ${releaseQty}`,
686
- uomValue: () => `"uom_value" - ${releaseUomValue}`,
687
- lockedUomValue: () => `"locked_uom_value" - ${releaseUomValue}`,
688
- updater: this.user,
689
- updatedAt: new Date()
690
- };
691
- let remainingQty = await tx
692
- .getRepository(warehouse_base_1.Inventory)
693
- .createQueryBuilder()
694
- .update(warehouse_base_1.Inventory)
695
- .set(updateInvObj)
696
- .where('id = :id', { id: targetInventory.inventory.id })
697
- .returning(['qty'])
698
- .execute()
699
- .then(dt => {
700
- return dt.raw[0].qty;
701
- });
702
- await (0, warehouse_base_1.generateInventoryHistory)(inventory, releaseGood, warehouse_base_1.INVENTORY_TRANSACTION_TYPE.PICKING, -releaseQty, -releaseUomValue, this.user, tx);
703
- let inventoryItems = await tx
704
- .getRepository(warehouse_base_1.InventoryItem)
705
- .find({ where: { outboundOrderId: releaseGood.id } });
706
- if (inventoryItems.length > 0) {
707
- inventoryItems.forEach((itm) => {
708
- itm.status = warehouse_base_1.INVENTORY_STATUS.PICKED;
709
- itm.updater = this.user;
710
- });
711
- await tx.getRepository(warehouse_base_1.InventoryItem).save(inventoryItems);
712
- }
713
- if (remainingQty === 0) {
648
+ try {
649
+ //update worksheet details only when line item picking complete
650
+ await tx
651
+ .getRepository(entities_1.WorksheetDetail)
652
+ .createQueryBuilder()
653
+ .update(entities_1.WorksheetDetail)
654
+ .set({
655
+ status: constants_1.WORKSHEET_STATUS.DONE,
656
+ updater: this.user,
657
+ updatedAt: new Date()
658
+ })
659
+ .where('id = :id', { id: worksheetDetailInfos.worksheetDetailId })
660
+ .execute();
661
+ let releaseUomValue = Math.round((pickedUomValue / pickedQty) * releaseQty * 100) / 100;
662
+ let updateInvObj = {
663
+ qty: () => `"qty" - ${releaseQty}`,
664
+ lockedQty: () => `"locked_qty" - ${releaseQty}`,
665
+ uomValue: () => `"uom_value" - ${releaseUomValue}`,
666
+ lockedUomValue: () => `"locked_uom_value" - ${releaseUomValue}`,
667
+ status: () => `case when "qty" - ${releaseQty} <= 0 then '${warehouse_base_1.INVENTORY_STATUS.TERMINATED}' else status end`,
668
+ updater: this.user,
669
+ updatedAt: new Date()
670
+ };
714
671
  await tx
715
672
  .getRepository(warehouse_base_1.Inventory)
716
673
  .createQueryBuilder()
717
674
  .update(warehouse_base_1.Inventory)
718
- .set({ status: warehouse_base_1.INVENTORY_STATUS.TERMINATED })
719
- .where('id = :id', { id: targetInventory.inventory.id })
675
+ .set(updateInvObj)
676
+ .where('id = :id', { id: worksheetDetailInfos.inventoryId })
677
+ .returning(['qty'])
720
678
  .execute();
679
+ await (0, warehouse_base_1.generateInventoryHistory)(inventory, releaseGood, warehouse_base_1.INVENTORY_TRANSACTION_TYPE.PICKING, -releaseQty, -releaseUomValue, this.user, tx);
680
+ let inventoryItems = await tx
681
+ .getRepository(warehouse_base_1.InventoryItem)
682
+ .find({ where: { outboundOrderId: worksheetDetailInfos.releaseGoodId } });
683
+ if (inventoryItems.length > 0) {
684
+ inventoryItems.forEach((itm) => {
685
+ itm.status = warehouse_base_1.INVENTORY_STATUS.PICKED;
686
+ itm.updater = this.user;
687
+ });
688
+ await tx.getRepository(warehouse_base_1.InventoryItem).save(inventoryItems);
689
+ }
690
+ }
691
+ catch (error) {
692
+ throw error;
721
693
  }
722
694
  });
723
695
  }
724
- // return worksheet details
725
- worksheetDetail = await this.trxMgr
696
+ let worksheetDetail = await this.trxMgr
726
697
  .getRepository(entities_1.WorksheetDetail)
727
698
  .createQueryBuilder('wd')
728
699
  .innerJoin('wd.targetInventory', 'oi')
729
700
  .innerJoinAndSelect('oi.releaseGood', 'rg')
730
- .where('wd.id = :id', { id: worksheetDetail.id })
701
+ .where('wd.id = :id', { id: worksheetDetailInfos.worksheetDetailId })
731
702
  .getOne();
732
703
  return worksheetDetail;
733
704
  }