@things-factory/worksheet-base 4.3.770 → 4.3.772

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 (28) hide show
  1. package/dist-server/controllers/inbound/putaway-returning-worksheet-controller.js +10 -5
  2. package/dist-server/controllers/inbound/putaway-returning-worksheet-controller.js.map +1 -1
  3. package/dist-server/controllers/inbound/putaway-worksheet-controller.js +10 -5
  4. package/dist-server/controllers/inbound/putaway-worksheet-controller.js.map +1 -1
  5. package/dist-server/controllers/inbound/unloading-worksheet-controller.js +45 -19
  6. package/dist-server/controllers/inbound/unloading-worksheet-controller.js.map +1 -1
  7. package/dist-server/controllers/outbound/packing-worksheet-controller.js +2 -2
  8. package/dist-server/controllers/outbound/packing-worksheet-controller.js.map +1 -1
  9. package/dist-server/controllers/outbound/picking-worksheet-controller.js +169 -44
  10. package/dist-server/controllers/outbound/picking-worksheet-controller.js.map +1 -1
  11. package/dist-server/controllers/outbound/returning-worksheet-controller.js +36 -3
  12. package/dist-server/controllers/outbound/returning-worksheet-controller.js.map +1 -1
  13. package/dist-server/controllers/outbound/sorting-worksheet-controller.js +2 -2
  14. package/dist-server/controllers/outbound/sorting-worksheet-controller.js.map +1 -1
  15. package/dist-server/controllers/replenishment/replenishment-worksheet-controller.js +1 -1
  16. package/dist-server/controllers/replenishment/replenishment-worksheet-controller.js.map +1 -1
  17. package/dist-server/graphql/resolvers/worksheet/generate-worksheet/generate-release-good-worksheet.js +12 -8
  18. package/dist-server/graphql/resolvers/worksheet/generate-worksheet/generate-release-good-worksheet.js.map +1 -1
  19. package/package.json +4 -4
  20. package/server/controllers/inbound/putaway-returning-worksheet-controller.ts +26 -5
  21. package/server/controllers/inbound/putaway-worksheet-controller.ts +26 -5
  22. package/server/controllers/inbound/unloading-worksheet-controller.ts +66 -23
  23. package/server/controllers/outbound/packing-worksheet-controller.ts +3 -2
  24. package/server/controllers/outbound/picking-worksheet-controller.ts +211 -45
  25. package/server/controllers/outbound/returning-worksheet-controller.ts +41 -16
  26. package/server/controllers/outbound/sorting-worksheet-controller.ts +3 -2
  27. package/server/controllers/replenishment/replenishment-worksheet-controller.ts +1 -7
  28. package/server/graphql/resolvers/worksheet/generate-worksheet/generate-release-good-worksheet.ts +14 -16
@@ -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`));
@@ -1048,10 +1088,18 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1048
1088
  if (!toLocation)
1049
1089
  throw new Error(this.ERROR_MSG.FIND.NO_RESULT(locationName));
1050
1090
  if (fromLocation.id !== toLocation.id) {
1091
+ await this.trxMgr
1092
+ .getRepository(warehouse_base_1.Inventory)
1093
+ .update({ id: inventory.id }, {
1094
+ location: toLocation,
1095
+ warehouse: toLocation.warehouse,
1096
+ zone: toLocation.zone,
1097
+ updater: this.user
1098
+ });
1051
1099
  inventory.location = toLocation;
1052
1100
  inventory.warehouse = toLocation.warehouse;
1053
1101
  inventory.zone = toLocation.zone;
1054
- inventory = await this.transactionInventory(inventory, releaseGood, 0, 0, warehouse_base_1.INVENTORY_TRANSACTION_TYPE.RELOCATE);
1102
+ await (0, warehouse_base_1.generateInventoryHistory)(inventory, releaseGood, warehouse_base_1.INVENTORY_TRANSACTION_TYPE.RELOCATE, 0, 0, this.user, this.trxMgr);
1055
1103
  }
1056
1104
  }
1057
1105
  }
@@ -1089,6 +1137,15 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1089
1137
  .reduce((a, b) => a + b, 0);
1090
1138
  if (sumOfReleaseQty != releaseQty)
1091
1139
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `insufficient picking quantity`));
1140
+ // validation to prevent decimal quantities for non-decimal products
1141
+ if (targetInventories.length > 0) {
1142
+ const batchPickProduct = await this.trxMgr.getRepository(product_base_1.Product).findOne({
1143
+ where: { id: targetInventories[0].productId }
1144
+ });
1145
+ if (releaseQty % 1 !== 0 && !(batchPickProduct === null || batchPickProduct === void 0 ? void 0 : batchPickProduct.isInventoryDecimal)) {
1146
+ throw new Error('Decimal quantities are not allowed for this product');
1147
+ }
1148
+ }
1092
1149
  for (var i = 0; i < targetInventories.length; i++) {
1093
1150
  let targetInventory = targetInventories[i];
1094
1151
  let inventory = await this.trxMgr.getRepository(warehouse_base_1.Inventory).findOne({
@@ -1131,10 +1188,11 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1131
1188
  targetInventory.status = sales_base_1.ORDER_INVENTORY_STATUS.PICKED;
1132
1189
  await this.updateOrderTargets([targetInventory]);
1133
1190
  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}`,
1191
+ qty: () => `"qty" - :deductQty::numeric`,
1192
+ lockedQty: () => `GREATEST("locked_qty" - :deductQty::numeric, 0)`,
1193
+ uomValue: () => `"uom_value" - :deductUomValue::numeric`,
1194
+ lockedUomValue: () => `GREATEST("locked_uom_value" - :deductUomValue::numeric, 0)`,
1195
+ status: () => `case when "qty" - :deductQty::numeric <= 0 then '${warehouse_base_1.INVENTORY_STATUS.TERMINATED}' else status end`,
1138
1196
  updater: this.user,
1139
1197
  updatedAt: new Date()
1140
1198
  };
@@ -1143,6 +1201,8 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1143
1201
  .createQueryBuilder()
1144
1202
  .update(warehouse_base_1.Inventory)
1145
1203
  .set(updateInvObj)
1204
+ .setParameter('deductQty', targetInventory.releaseQty)
1205
+ .setParameter('deductUomValue', targetInventory.releaseUomValue)
1146
1206
  .where('id = :id', { id: targetInventory.inventory.id })
1147
1207
  .returning(['qty'])
1148
1208
  .execute();
@@ -1159,10 +1219,18 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1159
1219
  if (!toLocation)
1160
1220
  throw new Error(this.ERROR_MSG.FIND.NO_RESULT(locationName));
1161
1221
  if (fromLocation.id !== toLocation.id) {
1222
+ await this.trxMgr
1223
+ .getRepository(warehouse_base_1.Inventory)
1224
+ .update({ id: inventory.id }, {
1225
+ location: toLocation,
1226
+ warehouse: toLocation.warehouse,
1227
+ zone: toLocation.zone,
1228
+ updater: this.user
1229
+ });
1162
1230
  inventory.location = toLocation;
1163
1231
  inventory.warehouse = toLocation.warehouse;
1164
1232
  inventory.zone = toLocation.zone;
1165
- await this.transactionInventory(inventory, releaseGood, 0, 0, warehouse_base_1.INVENTORY_TRANSACTION_TYPE.RELOCATE);
1233
+ await (0, warehouse_base_1.generateInventoryHistory)(inventory, releaseGood, warehouse_base_1.INVENTORY_TRANSACTION_TYPE.RELOCATE, 0, 0, this.user, this.trxMgr);
1166
1234
  }
1167
1235
  }
1168
1236
  }
@@ -1207,6 +1275,10 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1207
1275
  if (!matchingProduct)
1208
1276
  throw new Error(this.ERROR_MSG.FIND.NO_RESULT(productBarcode));
1209
1277
  pickedQty = matchingProduct.qty;
1278
+ // validation to prevent decimal quantities for non-decimal products
1279
+ if (pickedQty % 1 !== 0 && !(product === null || product === void 0 ? void 0 : product.isInventoryDecimal)) {
1280
+ throw new Error('Decimal quantities are not allowed for this product');
1281
+ }
1210
1282
  const sumOfReleaseQty = parseFloat(targetInventories
1211
1283
  .map((oi) => oi.releaseQty)
1212
1284
  .reduce((a, b) => a + b, 0)
@@ -1264,10 +1336,11 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1264
1336
  targetInventory.status = sales_base_1.ORDER_INVENTORY_STATUS.PICKED;
1265
1337
  await this.updateOrderTargets([targetInventory]);
1266
1338
  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}`,
1339
+ qty: () => `"qty" - :deductQty::numeric`,
1340
+ lockedQty: () => `GREATEST("locked_qty" - :deductQty::numeric, 0)`,
1341
+ uomValue: () => `"uom_value" - :deductUomValue::numeric`,
1342
+ lockedUomValue: () => `GREATEST("locked_uom_value" - :deductUomValue::numeric, 0)`,
1343
+ status: () => `case when "qty" - :deductQty::numeric <= 0 then '${warehouse_base_1.INVENTORY_STATUS.TERMINATED}' else status end`,
1271
1344
  updater: this.user,
1272
1345
  updatedAt: new Date()
1273
1346
  };
@@ -1276,6 +1349,8 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1276
1349
  .createQueryBuilder()
1277
1350
  .update(warehouse_base_1.Inventory)
1278
1351
  .set(updateInvObj)
1352
+ .setParameter('deductQty', targetInventory.releaseQty)
1353
+ .setParameter('deductUomValue', targetInventory.releaseUomValue)
1279
1354
  .where('id = :id', { id: targetInventory.inventory.id })
1280
1355
  .returning(['qty'])
1281
1356
  .execute();
@@ -1490,6 +1565,13 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1490
1565
  }
1491
1566
  async updatePickingTransaction(releaseGood, orderInventory, worksheetDetail, inventory, pickedQty) {
1492
1567
  var _a;
1568
+ // validation to prevent decimal quantities for non-decimal products
1569
+ const pickTxProduct = await this.trxMgr.getRepository(product_base_1.Product).findOne({
1570
+ where: { id: orderInventory.productId }
1571
+ });
1572
+ if (pickedQty % 1 !== 0 && !(pickTxProduct === null || pickTxProduct === void 0 ? void 0 : pickTxProduct.isInventoryDecimal)) {
1573
+ throw new Error('Decimal quantities are not allowed for this product');
1574
+ }
1493
1575
  const releaseQty = orderInventory.releaseQty;
1494
1576
  orderInventory.pickedQty = ((orderInventory === null || orderInventory === void 0 ? void 0 : orderInventory.pickedQty) || 0) + pickedQty;
1495
1577
  if (orderInventory.pickedQty == releaseQty) {
@@ -1501,11 +1583,28 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1501
1583
  orderInventory.pickedBy = (_a = this.user) === null || _a === void 0 ? void 0 : _a.name;
1502
1584
  orderInventory.pickedByUser = this.user;
1503
1585
  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);
1586
+ // Atomic SQL update instead of stale-read pattern
1587
+ await this.trxMgr
1588
+ .getRepository(warehouse_base_1.Inventory)
1589
+ .createQueryBuilder()
1590
+ .update(warehouse_base_1.Inventory)
1591
+ .set({
1592
+ qty: () => `"qty" - :deductQty::numeric`,
1593
+ uomValue: () => `"uom_value" - :deductUomValue::numeric`,
1594
+ lockedQty: () => `GREATEST("locked_qty" - :deductQty::numeric, 0)`,
1595
+ lockedUomValue: () => `GREATEST("locked_uom_value" - :deductUomValue::numeric, 0)`,
1596
+ status: () => `case when "qty" - :deductQty::numeric <= 0 then '${warehouse_base_1.INVENTORY_STATUS.TERMINATED}' else status end`,
1597
+ updater: this.user,
1598
+ updatedAt: new Date()
1599
+ })
1600
+ .setParameter('deductQty', orderInventory.releaseQty)
1601
+ .setParameter('deductUomValue', orderInventory.releaseUomValue)
1602
+ .where('id = :id', { id: inventory.id })
1603
+ .execute();
1604
+ // Generate inventory history separately
1605
+ await (0, warehouse_base_1.generateInventoryHistory)(inventory, releaseGood, warehouse_base_1.INVENTORY_TRANSACTION_TYPE.PICKING, -orderInventory.releaseQty, -orderInventory.releaseUomValue, this.user, this.trxMgr);
1606
+ // Re-read inventory for downstream use (status check for TERMINATED)
1607
+ inventory = await this.trxMgr.getRepository(warehouse_base_1.Inventory).findOne({ where: { id: inventory.id } });
1509
1608
  worksheetDetail.status = constants_1.WORKSHEET_STATUS.DONE;
1510
1609
  worksheetDetail.updater = this.user;
1511
1610
  await this.trxMgr.getRepository(entities_1.WorksheetDetail).save(worksheetDetail);
@@ -1879,7 +1978,7 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1879
1978
  }
1880
1979
  }
1881
1980
  async assignInventoriesForUnassignedOrder(worksheet, tx) {
1882
- var _a, _b, _c;
1981
+ var _a;
1883
1982
  const releaseGood = worksheet.releaseGood;
1884
1983
  const orderProducts = releaseGood.orderProducts;
1885
1984
  let finalOrderInventories = [];
@@ -1912,19 +2011,35 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1912
2011
  for (let oi of finalOrderInventories) {
1913
2012
  // update inventory locked qty and uom value
1914
2013
  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,
2014
+ const lockResult = await transaction
2015
+ .getRepository(warehouse_base_1.Inventory)
2016
+ .createQueryBuilder()
2017
+ .update(warehouse_base_1.Inventory)
2018
+ .set({
2019
+ lockedQty: () => `COALESCE("locked_qty", 0) + :releaseQty::numeric`,
2020
+ lockedUomValue: () => `COALESCE("locked_uom_value", 0) + :releaseUomValue::numeric`,
1918
2021
  updater: this.user
1919
- });
2022
+ })
2023
+ .setParameter('releaseQty', oi.releaseQty)
2024
+ .setParameter('releaseUomValue', oi.releaseUomValue)
2025
+ .where('id = :id AND qty >= COALESCE(locked_qty, 0) + :newQty', {
2026
+ id: oi.inventory.id,
2027
+ newQty: oi.releaseQty
2028
+ })
2029
+ .execute();
2030
+ if (lockResult.affected === 0) {
2031
+ throw new Error(`Insufficient inventory for picking assignment`);
2032
+ }
1920
2033
  await transaction
1921
2034
  .getRepository(warehouse_base_1.ProductDetailStock)
1922
2035
  .createQueryBuilder()
1923
2036
  .update(warehouse_base_1.ProductDetailStock)
1924
2037
  .set({
1925
- unassignedQty: () => `"unassigned_qty" - ${oi.releaseQty}`,
1926
- unassignedUomValue: () => `"unassigned_uom_value" - ${oi.releaseUomValue}`
2038
+ unassignedQty: () => `GREATEST("unassigned_qty" - :oiReleaseQty::numeric, 0)`,
2039
+ unassignedUomValue: () => `GREATEST("unassigned_uom_value" - :oiReleaseUomValue::numeric, 0)`
1927
2040
  })
2041
+ .setParameter('oiReleaseQty', oi.releaseQty)
2042
+ .setParameter('oiReleaseUomValue', oi.releaseUomValue)
1928
2043
  .where({ productDetail: oi.productDetail.id })
1929
2044
  .execute();
1930
2045
  const worksheetDetail = Object.assign(new entities_1.WorksheetDetail(), {
@@ -1985,25 +2100,35 @@ class PickingWorksheetController extends vas_worksheet_controller_1.VasWorksheet
1985
2100
  releaseQty = releaseQty - allocatedQty;
1986
2101
  releaseUomValue = releaseUomValue - allocatedUomValue;
1987
2102
  //// Update inventory locked quantity
1988
- await this.trxMgr
2103
+ const lockResult = await this.trxMgr
1989
2104
  .getRepository(warehouse_base_1.Inventory)
1990
2105
  .createQueryBuilder('inv')
1991
2106
  .update(warehouse_base_1.Inventory)
1992
2107
  .set({
1993
- lockedUomValue: () => `COALESCE(locked_uom_value,0) + ${allocatedUomValue}`,
1994
- lockedQty: () => `COALESCE(locked_qty,0) + ${allocatedQty}`
2108
+ lockedUomValue: () => `COALESCE(locked_uom_value,0) + :allocatedUomValue::numeric`,
2109
+ lockedQty: () => `COALESCE(locked_qty,0) + :allocatedQty::numeric`
2110
+ })
2111
+ .setParameter('allocatedUomValue', allocatedUomValue)
2112
+ .setParameter('allocatedQty', allocatedQty)
2113
+ .where('id = :id AND qty >= COALESCE(locked_qty, 0) + :newQty', {
2114
+ id: targetInventory.id,
2115
+ newQty: allocatedQty
1995
2116
  })
1996
- .where('id = :id', { id: targetInventory.id })
1997
2117
  .execute();
2118
+ if (lockResult.affected === 0) {
2119
+ throw new Error(`Insufficient inventory for picking assignment`);
2120
+ }
1998
2121
  // update product detail stock deduct unassigned qty and unassigned uom value
1999
2122
  await this.trxMgr
2000
2123
  .getRepository(warehouse_base_1.ProductDetailStock)
2001
2124
  .createQueryBuilder()
2002
2125
  .update(warehouse_base_1.ProductDetailStock)
2003
2126
  .set({
2004
- unassignedQty: () => `"unassigned_qty" - ${allocatedQty}`,
2005
- unassignedUomValue: () => `"unassigned_uom_value" - ${allocatedUomValue}`
2127
+ unassignedQty: () => `GREATEST("unassigned_qty" - :deductQty::numeric, 0)`,
2128
+ unassignedUomValue: () => `GREATEST("unassigned_uom_value" - :deductUomValue::numeric, 0)`
2006
2129
  })
2130
+ .setParameter('deductQty', allocatedQty)
2131
+ .setParameter('deductUomValue', allocatedUomValue)
2007
2132
  .where({ productDetail: orderProducts[i].productDetail.id })
2008
2133
  .execute();
2009
2134
  // update order product status to ASSIGNED