@things-factory/worksheet-base 4.3.769 → 4.3.771

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 (52) hide show
  1. package/dist-server/constants/template.js +2 -1
  2. package/dist-server/constants/template.js.map +1 -1
  3. package/dist-server/controllers/inbound/unloading-worksheet-controller.js +17 -0
  4. package/dist-server/controllers/inbound/unloading-worksheet-controller.js.map +1 -1
  5. package/dist-server/controllers/index.js +1 -0
  6. package/dist-server/controllers/index.js.map +1 -1
  7. package/dist-server/controllers/outbound/loading-worksheet-controller.js +53 -0
  8. package/dist-server/controllers/outbound/loading-worksheet-controller.js.map +1 -1
  9. package/dist-server/controllers/outbound/picking-worksheet-controller.js +151 -42
  10. package/dist-server/controllers/outbound/picking-worksheet-controller.js.map +1 -1
  11. package/dist-server/controllers/render-packing-label.js +160 -0
  12. package/dist-server/controllers/render-packing-label.js.map +1 -0
  13. package/dist-server/graphql/resolvers/worksheet/loading/create-group-loading-packages.js +20 -0
  14. package/dist-server/graphql/resolvers/worksheet/loading/create-group-loading-packages.js.map +1 -0
  15. package/dist-server/graphql/resolvers/worksheet/loading/index.js +2 -1
  16. package/dist-server/graphql/resolvers/worksheet/loading/index.js.map +1 -1
  17. package/dist-server/graphql/resolvers/worksheet/picking-worksheet.js +6 -1
  18. package/dist-server/graphql/resolvers/worksheet/picking-worksheet.js.map +1 -1
  19. package/dist-server/graphql/resolvers/worksheet/putaway-replenishment-worksheet.js +2 -1
  20. package/dist-server/graphql/resolvers/worksheet/putaway-replenishment-worksheet.js.map +1 -1
  21. package/dist-server/graphql/resolvers/worksheet/putaway-returning-worksheet.js +2 -1
  22. package/dist-server/graphql/resolvers/worksheet/putaway-returning-worksheet.js.map +1 -1
  23. package/dist-server/graphql/resolvers/worksheet/putaway-worksheet.js +1 -0
  24. package/dist-server/graphql/resolvers/worksheet/putaway-worksheet.js.map +1 -1
  25. package/dist-server/graphql/resolvers/worksheet/return-worksheet.js +2 -1
  26. package/dist-server/graphql/resolvers/worksheet/return-worksheet.js.map +1 -1
  27. package/dist-server/graphql/types/worksheet/group-loading-package-item.js +11 -0
  28. package/dist-server/graphql/types/worksheet/group-loading-package-item.js.map +1 -0
  29. package/dist-server/graphql/types/worksheet/index.js +8 -1
  30. package/dist-server/graphql/types/worksheet/index.js.map +1 -1
  31. package/dist-server/graphql/types/worksheet/worksheet-detail-info.js +1 -0
  32. package/dist-server/graphql/types/worksheet/worksheet-detail-info.js.map +1 -1
  33. package/dist-server/routes.js +11 -0
  34. package/dist-server/routes.js.map +1 -1
  35. package/package.json +13 -13
  36. package/server/constants/template.ts +2 -1
  37. package/server/controllers/inbound/unloading-worksheet-controller.ts +20 -0
  38. package/server/controllers/index.ts +1 -0
  39. package/server/controllers/outbound/loading-worksheet-controller.ts +67 -0
  40. package/server/controllers/outbound/picking-worksheet-controller.ts +167 -43
  41. package/server/controllers/render-packing-label.ts +199 -0
  42. package/server/graphql/resolvers/worksheet/loading/create-group-loading-packages.ts +32 -0
  43. package/server/graphql/resolvers/worksheet/loading/index.ts +3 -1
  44. package/server/graphql/resolvers/worksheet/picking-worksheet.ts +5 -1
  45. package/server/graphql/resolvers/worksheet/putaway-replenishment-worksheet.ts +2 -1
  46. package/server/graphql/resolvers/worksheet/putaway-returning-worksheet.ts +2 -1
  47. package/server/graphql/resolvers/worksheet/putaway-worksheet.ts +1 -0
  48. package/server/graphql/resolvers/worksheet/return-worksheet.ts +2 -1
  49. package/server/graphql/types/worksheet/group-loading-package-item.ts +8 -0
  50. package/server/graphql/types/worksheet/index.ts +8 -1
  51. package/server/graphql/types/worksheet/worksheet-detail-info.ts +1 -0
  52. package/server/routes.ts +11 -0
@@ -616,10 +616,27 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
616
616
  newTargetInventory.creator = this.user;
617
617
  newTargetInventory.updater = this.user;
618
618
  newTargetInventory = await this.trxMgr.getRepository(sales_base_1.OrderInventory).save(newTargetInventory);
619
- // Update locked qty and uomValue of inventory
620
- inventory.lockedQty = targetInventory.releaseQty + (inventory.lockedQty || 0);
621
- inventory.lockedUomValue = targetInventory.releaseUomValue + (inventory.lockedUomValue || 0);
622
- await this.updateInventory(inventory);
619
+ // Atomic update of locked qty and uomValue of inventory
620
+ const lockResult = await this.trxMgr
621
+ .getRepository(warehouse_base_1.Inventory)
622
+ .createQueryBuilder()
623
+ .update(warehouse_base_1.Inventory)
624
+ .set({
625
+ lockedQty: () => `COALESCE("locked_qty", 0) + :releaseQty::numeric`,
626
+ lockedUomValue: () => `COALESCE("locked_uom_value", 0) + :releaseUomValue::numeric`,
627
+ updater: this.user,
628
+ updatedAt: new Date()
629
+ })
630
+ .setParameter('releaseQty', targetInventory.releaseQty)
631
+ .setParameter('releaseUomValue', targetInventory.releaseUomValue)
632
+ .where('id = :id AND qty >= COALESCE(locked_qty, 0) + :newQty', {
633
+ id: inventory.id,
634
+ newQty: targetInventory.releaseQty
635
+ })
636
+ .execute();
637
+ if (lockResult.affected === 0) {
638
+ throw new Error(`Insufficient inventory for picking assignment`);
639
+ }
623
640
  // Create worksheet details
624
641
  await this.createWorksheetDetails(worksheet, constants_1.WORKSHEET_TYPE.PICKING, [newTargetInventory]);
625
642
  }
@@ -639,12 +656,21 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
639
656
  worksheetDetailIds.push(worksheetDetail.id);
640
657
  const targetInventory = worksheetDetail.targetInventory;
641
658
  targetInventoryIds.push(targetInventory.id);
642
- let inventory = await this.trxMgr
659
+ // Atomic update of locked qty and uomValue of inventory
660
+ await this.trxMgr
643
661
  .getRepository(warehouse_base_1.Inventory)
644
- .findOne({ where: { id: worksheetDetail.targetInventory.inventory.id } });
645
- inventory.lockedQty = inventory.lockedQty - targetInventory.releaseQty;
646
- inventory.lockedUomValue = inventory.lockedUomValue - targetInventory.releaseUomValue;
647
- await this.updateInventory(inventory);
662
+ .createQueryBuilder()
663
+ .update(warehouse_base_1.Inventory)
664
+ .set({
665
+ lockedQty: () => `GREATEST(COALESCE("locked_qty", 0) - :releaseQty::numeric, 0)`,
666
+ lockedUomValue: () => `GREATEST(COALESCE("locked_uom_value", 0) - :releaseUomValue::numeric, 0)`,
667
+ updater: this.user,
668
+ updatedAt: new Date()
669
+ })
670
+ .setParameter('releaseQty', targetInventory.releaseQty)
671
+ .setParameter('releaseUomValue', targetInventory.releaseUomValue)
672
+ .where('id = :id', { id: worksheetDetail.targetInventory.inventory.id })
673
+ .execute();
648
674
  await this.trxMgr
649
675
  .getRepository(sales_base_1.OrderProduct)
650
676
  .update({ id: targetInventory.orderProduct.id }, { status: sales_base_1.ORDER_PRODUCT_STATUS.PENDING_ASSIGN, updater: this.user });
@@ -770,6 +796,13 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
770
796
  pickedQty = matchingProduct.qty;
771
797
  pickedUomValue = matchingProduct.uomValue;
772
798
  }
799
+ // validation to prevent decimal quantities for non-decimal products
800
+ const scanPickProduct = await this.trxMgr.getRepository(product_base_1.Product).findOne({
801
+ where: { id: worksheetDetailInfos.productId }
802
+ });
803
+ if (pickedQty % 1 !== 0 && !(scanPickProduct === null || scanPickProduct === void 0 ? void 0 : scanPickProduct.isInventoryDecimal)) {
804
+ throw new Error('Decimal quantities are not allowed for this product');
805
+ }
773
806
  // //validation to prevent over release
774
807
  if (!targetInventory)
775
808
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `inventory not assigned`));
@@ -834,13 +867,13 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
834
867
  const releaseQty = targetInventory.releaseQty;
835
868
  targetInventory.pickedQty = ((targetInventory === null || targetInventory === void 0 ? void 0 : targetInventory.pickedQty) || 0) + pickedQty;
836
869
  let updateOiObj = {
837
- pickedQty: () => `"picked_qty" + ${pickedQty}`,
870
+ pickedQty: () => `"picked_qty" + :pickedQty`,
838
871
  updatedAt: new Date(),
839
872
  updater: this.user,
840
873
  pickedBy: this.user.name,
841
874
  pickedByUser: this.user,
842
875
  pickedAt: new Date(),
843
- status: () => `case when release_qty = "picked_qty" + ${pickedQty} then '${sales_base_1.ORDER_INVENTORY_STATUS.PICKED}' else status end`
876
+ status: () => `case when release_qty = "picked_qty" + :pickedQty then '${sales_base_1.ORDER_INVENTORY_STATUS.PICKED}' else status end`
844
877
  };
845
878
  if (targetInventory.binLocation) {
846
879
  updateOiObj['binLocation'] = targetInventory.binLocation;
@@ -850,6 +883,7 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
850
883
  .createQueryBuilder()
851
884
  .update(sales_base_1.OrderInventory)
852
885
  .set(updateOiObj)
886
+ .setParameter('pickedQty', pickedQty)
853
887
  .where({ id: targetInventory.id })
854
888
  .andWhere(`picked_qty + :pickedQty <= release_qty`, { pickedQty })
855
889
  .execute();
@@ -870,11 +904,11 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
870
904
  .execute();
871
905
  let releaseUomValue = Math.trunc((pickedUomValue / pickedQty) * releaseQty * 1000) / 1000;
872
906
  let updateInvObj = {
873
- qty: () => `"qty" - ${releaseQty}`,
874
- lockedQty: () => `"locked_qty" - ${releaseQty}`,
875
- uomValue: () => `"uom_value" - ${releaseUomValue}`,
876
- lockedUomValue: () => `"locked_uom_value" - ${releaseUomValue}`,
877
- status: () => `case when "qty" - ${releaseQty} <= 0 then '${warehouse_base_1.INVENTORY_STATUS.TERMINATED}' else status end`,
907
+ qty: () => `"qty" - :deductQty::numeric`,
908
+ lockedQty: () => `GREATEST("locked_qty" - :deductQty::numeric, 0)`,
909
+ uomValue: () => `"uom_value" - :deductUomValue::numeric`,
910
+ lockedUomValue: () => `GREATEST("locked_uom_value" - :deductUomValue::numeric, 0)`,
911
+ status: () => `case when "qty" - :deductQty::numeric <= 0 then '${warehouse_base_1.INVENTORY_STATUS.TERMINATED}' else status end`,
878
912
  updater: this.user,
879
913
  updatedAt: new Date()
880
914
  };
@@ -883,6 +917,8 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
883
917
  .createQueryBuilder()
884
918
  .update(warehouse_base_1.Inventory)
885
919
  .set(updateInvObj)
920
+ .setParameter('deductQty', releaseQty)
921
+ .setParameter('deductUomValue', releaseUomValue)
886
922
  .where('id = :id', { id: worksheetDetailInfos.inventoryId })
887
923
  .returning(['qty'])
888
924
  .execute();
@@ -960,6 +996,10 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
960
996
  });
961
997
  if (!oiValidate)
962
998
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `is done`));
999
+ // validation to prevent decimal quantities for non-decimal products
1000
+ if (pickedQty % 1 !== 0 && !product.isInventoryDecimal) {
1001
+ throw new Error('Decimal quantities are not allowed for this product');
1002
+ }
963
1003
  //validation to prevent over release
964
1004
  if (inventory.qty <= 0)
965
1005
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `over release`));
@@ -1089,6 +1129,15 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1089
1129
  .reduce((a, b) => a + b, 0);
1090
1130
  if (sumOfReleaseQty != releaseQty)
1091
1131
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `insufficient picking quantity`));
1132
+ // validation to prevent decimal quantities for non-decimal products
1133
+ if (targetInventories.length > 0) {
1134
+ const batchPickProduct = await this.trxMgr.getRepository(product_base_1.Product).findOne({
1135
+ where: { id: targetInventories[0].productId }
1136
+ });
1137
+ if (releaseQty % 1 !== 0 && !(batchPickProduct === null || batchPickProduct === void 0 ? void 0 : batchPickProduct.isInventoryDecimal)) {
1138
+ throw new Error('Decimal quantities are not allowed for this product');
1139
+ }
1140
+ }
1092
1141
  for (var i = 0; i < targetInventories.length; i++) {
1093
1142
  let targetInventory = targetInventories[i];
1094
1143
  let inventory = await this.trxMgr.getRepository(warehouse_base_1.Inventory).findOne({
@@ -1131,10 +1180,11 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1131
1180
  targetInventory.status = sales_base_1.ORDER_INVENTORY_STATUS.PICKED;
1132
1181
  await this.updateOrderTargets([targetInventory]);
1133
1182
  let updateInvObj = {
1134
- qty: () => `"qty" - ${targetInventory.releaseQty}`,
1135
- lockedQty: () => `"locked_qty" - ${targetInventory.releaseQty}`,
1136
- uomValue: () => `"uom_value" - ${targetInventory.releaseUomValue}`,
1137
- lockedUomValue: () => `"locked_uom_value" - ${targetInventory.releaseUomValue}`,
1183
+ qty: () => `"qty" - :deductQty::numeric`,
1184
+ lockedQty: () => `GREATEST("locked_qty" - :deductQty::numeric, 0)`,
1185
+ uomValue: () => `"uom_value" - :deductUomValue::numeric`,
1186
+ lockedUomValue: () => `GREATEST("locked_uom_value" - :deductUomValue::numeric, 0)`,
1187
+ status: () => `case when "qty" - :deductQty::numeric <= 0 then '${warehouse_base_1.INVENTORY_STATUS.TERMINATED}' else status end`,
1138
1188
  updater: this.user,
1139
1189
  updatedAt: new Date()
1140
1190
  };
@@ -1143,6 +1193,8 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1143
1193
  .createQueryBuilder()
1144
1194
  .update(warehouse_base_1.Inventory)
1145
1195
  .set(updateInvObj)
1196
+ .setParameter('deductQty', targetInventory.releaseQty)
1197
+ .setParameter('deductUomValue', targetInventory.releaseUomValue)
1146
1198
  .where('id = :id', { id: targetInventory.inventory.id })
1147
1199
  .returning(['qty'])
1148
1200
  .execute();
@@ -1207,6 +1259,10 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1207
1259
  if (!matchingProduct)
1208
1260
  throw new Error(this.ERROR_MSG.FIND.NO_RESULT(productBarcode));
1209
1261
  pickedQty = matchingProduct.qty;
1262
+ // validation to prevent decimal quantities for non-decimal products
1263
+ if (pickedQty % 1 !== 0 && !(product === null || product === void 0 ? void 0 : product.isInventoryDecimal)) {
1264
+ throw new Error('Decimal quantities are not allowed for this product');
1265
+ }
1210
1266
  const sumOfReleaseQty = parseFloat(targetInventories
1211
1267
  .map((oi) => oi.releaseQty)
1212
1268
  .reduce((a, b) => a + b, 0)
@@ -1264,10 +1320,11 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1264
1320
  targetInventory.status = sales_base_1.ORDER_INVENTORY_STATUS.PICKED;
1265
1321
  await this.updateOrderTargets([targetInventory]);
1266
1322
  let updateInvObj = {
1267
- qty: () => `"qty" - ${targetInventory.releaseQty}`,
1268
- lockedQty: () => `"locked_qty" - ${targetInventory.releaseQty}`,
1269
- uomValue: () => `"uom_value" - ${targetInventory.releaseUomValue}`,
1270
- lockedUomValue: () => `"locked_uom_value" - ${targetInventory.releaseUomValue}`,
1323
+ qty: () => `"qty" - :deductQty::numeric`,
1324
+ lockedQty: () => `GREATEST("locked_qty" - :deductQty::numeric, 0)`,
1325
+ uomValue: () => `"uom_value" - :deductUomValue::numeric`,
1326
+ lockedUomValue: () => `GREATEST("locked_uom_value" - :deductUomValue::numeric, 0)`,
1327
+ status: () => `case when "qty" - :deductQty::numeric <= 0 then '${warehouse_base_1.INVENTORY_STATUS.TERMINATED}' else status end`,
1271
1328
  updater: this.user,
1272
1329
  updatedAt: new Date()
1273
1330
  };
@@ -1276,6 +1333,8 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1276
1333
  .createQueryBuilder()
1277
1334
  .update(warehouse_base_1.Inventory)
1278
1335
  .set(updateInvObj)
1336
+ .setParameter('deductQty', targetInventory.releaseQty)
1337
+ .setParameter('deductUomValue', targetInventory.releaseUomValue)
1279
1338
  .where('id = :id', { id: targetInventory.inventory.id })
1280
1339
  .returning(['qty'])
1281
1340
  .execute();
@@ -1490,6 +1549,13 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1490
1549
  }
1491
1550
  async updatePickingTransaction(releaseGood, orderInventory, worksheetDetail, inventory, pickedQty) {
1492
1551
  var _a;
1552
+ // validation to prevent decimal quantities for non-decimal products
1553
+ const pickTxProduct = await this.trxMgr.getRepository(product_base_1.Product).findOne({
1554
+ where: { id: orderInventory.productId }
1555
+ });
1556
+ if (pickedQty % 1 !== 0 && !(pickTxProduct === null || pickTxProduct === void 0 ? void 0 : pickTxProduct.isInventoryDecimal)) {
1557
+ throw new Error('Decimal quantities are not allowed for this product');
1558
+ }
1493
1559
  const releaseQty = orderInventory.releaseQty;
1494
1560
  orderInventory.pickedQty = ((orderInventory === null || orderInventory === void 0 ? void 0 : orderInventory.pickedQty) || 0) + pickedQty;
1495
1561
  if (orderInventory.pickedQty == releaseQty) {
@@ -1501,11 +1567,28 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1501
1567
  orderInventory.pickedBy = (_a = this.user) === null || _a === void 0 ? void 0 : _a.name;
1502
1568
  orderInventory.pickedByUser = this.user;
1503
1569
  orderInventory.pickedAt = new Date();
1504
- inventory.qty -= orderInventory.releaseQty;
1505
- inventory.uomValue = Math.round((inventory.uomValue - orderInventory.releaseUomValue) * 100) / 100;
1506
- inventory.lockedQty = inventory.lockedQty - orderInventory.releaseQty;
1507
- inventory.lockedUomValue = Math.round((inventory.lockedUomValue - orderInventory.releaseUomValue) * 100) / 100;
1508
- inventory = await this.transactionInventory(inventory, releaseGood, -orderInventory.releaseQty, -orderInventory.releaseUomValue, warehouse_base_1.INVENTORY_TRANSACTION_TYPE.PICKING);
1570
+ // Atomic SQL update instead of stale-read pattern
1571
+ await this.trxMgr
1572
+ .getRepository(warehouse_base_1.Inventory)
1573
+ .createQueryBuilder()
1574
+ .update(warehouse_base_1.Inventory)
1575
+ .set({
1576
+ qty: () => `"qty" - :deductQty::numeric`,
1577
+ uomValue: () => `"uom_value" - :deductUomValue::numeric`,
1578
+ lockedQty: () => `GREATEST("locked_qty" - :deductQty::numeric, 0)`,
1579
+ lockedUomValue: () => `GREATEST("locked_uom_value" - :deductUomValue::numeric, 0)`,
1580
+ status: () => `case when "qty" - :deductQty::numeric <= 0 then '${warehouse_base_1.INVENTORY_STATUS.TERMINATED}' else status end`,
1581
+ updater: this.user,
1582
+ updatedAt: new Date()
1583
+ })
1584
+ .setParameter('deductQty', orderInventory.releaseQty)
1585
+ .setParameter('deductUomValue', orderInventory.releaseUomValue)
1586
+ .where('id = :id', { id: inventory.id })
1587
+ .execute();
1588
+ // Generate inventory history separately
1589
+ await (0, warehouse_base_1.generateInventoryHistory)(inventory, releaseGood, warehouse_base_1.INVENTORY_TRANSACTION_TYPE.PICKING, -orderInventory.releaseQty, -orderInventory.releaseUomValue, this.user, this.trxMgr);
1590
+ // Re-read inventory for downstream use (status check for TERMINATED)
1591
+ inventory = await this.trxMgr.getRepository(warehouse_base_1.Inventory).findOne({ where: { id: inventory.id } });
1509
1592
  worksheetDetail.status = constants_1.WORKSHEET_STATUS.DONE;
1510
1593
  worksheetDetail.updater = this.user;
1511
1594
  await this.trxMgr.getRepository(entities_1.WorksheetDetail).save(worksheetDetail);
@@ -1879,7 +1962,7 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1879
1962
  }
1880
1963
  }
1881
1964
  async assignInventoriesForUnassignedOrder(worksheet, tx) {
1882
- var _a, _b, _c;
1965
+ var _a;
1883
1966
  const releaseGood = worksheet.releaseGood;
1884
1967
  const orderProducts = releaseGood.orderProducts;
1885
1968
  let finalOrderInventories = [];
@@ -1912,19 +1995,35 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1912
1995
  for (let oi of finalOrderInventories) {
1913
1996
  // update inventory locked qty and uom value
1914
1997
  oi = await transaction.getRepository(sales_base_1.OrderInventory).save(Object.assign({}, oi));
1915
- await transaction.getRepository(warehouse_base_1.Inventory).update(oi.inventory.id, {
1916
- lockedQty: (((_b = oi.inventory) === null || _b === void 0 ? void 0 : _b.lockedQty) || 0) + oi.releaseQty,
1917
- lockedUomValue: (((_c = oi.inventory) === null || _c === void 0 ? void 0 : _c.lockedUomValue) || 0) + oi.releaseUomValue,
1998
+ const lockResult = await transaction
1999
+ .getRepository(warehouse_base_1.Inventory)
2000
+ .createQueryBuilder()
2001
+ .update(warehouse_base_1.Inventory)
2002
+ .set({
2003
+ lockedQty: () => `COALESCE("locked_qty", 0) + :releaseQty::numeric`,
2004
+ lockedUomValue: () => `COALESCE("locked_uom_value", 0) + :releaseUomValue::numeric`,
1918
2005
  updater: this.user
1919
- });
2006
+ })
2007
+ .setParameter('releaseQty', oi.releaseQty)
2008
+ .setParameter('releaseUomValue', oi.releaseUomValue)
2009
+ .where('id = :id AND qty >= COALESCE(locked_qty, 0) + :newQty', {
2010
+ id: oi.inventory.id,
2011
+ newQty: oi.releaseQty
2012
+ })
2013
+ .execute();
2014
+ if (lockResult.affected === 0) {
2015
+ throw new Error(`Insufficient inventory for picking assignment`);
2016
+ }
1920
2017
  await transaction
1921
2018
  .getRepository(warehouse_base_1.ProductDetailStock)
1922
2019
  .createQueryBuilder()
1923
2020
  .update(warehouse_base_1.ProductDetailStock)
1924
2021
  .set({
1925
- unassignedQty: () => `"unassigned_qty" - ${oi.releaseQty}`,
1926
- unassignedUomValue: () => `"unassigned_uom_value" - ${oi.releaseUomValue}`
2022
+ unassignedQty: () => `GREATEST("unassigned_qty" - :oiReleaseQty::numeric, 0)`,
2023
+ unassignedUomValue: () => `GREATEST("unassigned_uom_value" - :oiReleaseUomValue::numeric, 0)`
1927
2024
  })
2025
+ .setParameter('oiReleaseQty', oi.releaseQty)
2026
+ .setParameter('oiReleaseUomValue', oi.releaseUomValue)
1928
2027
  .where({ productDetail: oi.productDetail.id })
1929
2028
  .execute();
1930
2029
  const worksheetDetail = Object.assign(new entities_1.WorksheetDetail(), {
@@ -1985,25 +2084,35 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1985
2084
  releaseQty = releaseQty - allocatedQty;
1986
2085
  releaseUomValue = releaseUomValue - allocatedUomValue;
1987
2086
  //// Update inventory locked quantity
1988
- await this.trxMgr
2087
+ const lockResult = await this.trxMgr
1989
2088
  .getRepository(warehouse_base_1.Inventory)
1990
2089
  .createQueryBuilder('inv')
1991
2090
  .update(warehouse_base_1.Inventory)
1992
2091
  .set({
1993
- lockedUomValue: () => `COALESCE(locked_uom_value,0) + ${allocatedUomValue}`,
1994
- lockedQty: () => `COALESCE(locked_qty,0) + ${allocatedQty}`
2092
+ lockedUomValue: () => `COALESCE(locked_uom_value,0) + :allocatedUomValue::numeric`,
2093
+ lockedQty: () => `COALESCE(locked_qty,0) + :allocatedQty::numeric`
2094
+ })
2095
+ .setParameter('allocatedUomValue', allocatedUomValue)
2096
+ .setParameter('allocatedQty', allocatedQty)
2097
+ .where('id = :id AND qty >= COALESCE(locked_qty, 0) + :newQty', {
2098
+ id: targetInventory.id,
2099
+ newQty: allocatedQty
1995
2100
  })
1996
- .where('id = :id', { id: targetInventory.id })
1997
2101
  .execute();
2102
+ if (lockResult.affected === 0) {
2103
+ throw new Error(`Insufficient inventory for picking assignment`);
2104
+ }
1998
2105
  // update product detail stock deduct unassigned qty and unassigned uom value
1999
2106
  await this.trxMgr
2000
2107
  .getRepository(warehouse_base_1.ProductDetailStock)
2001
2108
  .createQueryBuilder()
2002
2109
  .update(warehouse_base_1.ProductDetailStock)
2003
2110
  .set({
2004
- unassignedQty: () => `"unassigned_qty" - ${allocatedQty}`,
2005
- unassignedUomValue: () => `"unassigned_uom_value" - ${allocatedUomValue}`
2111
+ unassignedQty: () => `GREATEST("unassigned_qty" - :deductQty::numeric, 0)`,
2112
+ unassignedUomValue: () => `GREATEST("unassigned_uom_value" - :deductUomValue::numeric, 0)`
2006
2113
  })
2114
+ .setParameter('deductQty', allocatedQty)
2115
+ .setParameter('deductUomValue', allocatedUomValue)
2007
2116
  .where({ productDetail: orderProducts[i].productDetail.id })
2008
2117
  .execute();
2009
2118
  // update order product status to ASSIGNED