@things-factory/sales-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.
@@ -476,14 +476,19 @@ export async function deleteReleaseGood(tx: EntityManager, name: string, user: U
476
476
  await Promise.all(
477
477
  foundOIs.map(async (oi: OrderInventory) => {
478
478
  if (oi?.inventory?.id) {
479
- oi.inventory = await tx.getRepository(Inventory).findOne(oi.inventory.id)
480
-
481
- await tx.getRepository(Inventory).save({
482
- ...oi.inventory,
483
- lockedQty: safeDecimalOperation(oi.inventory.lockedQty, oi.releaseQty, 'subtract'),
484
- lockedUomValue: safeDecimalOperation(oi.inventory.lockedUomValue, oi.releaseUomValue, 'subtract'),
485
- updater: user
486
- })
479
+ await tx
480
+ .getRepository(Inventory)
481
+ .createQueryBuilder()
482
+ .update(Inventory)
483
+ .set({
484
+ lockedQty: () => `GREATEST(COALESCE("locked_qty", 0) - :releaseQty::numeric, 0)`,
485
+ lockedUomValue: () => `GREATEST(COALESCE("locked_uom_value", 0) - :releaseUomValue::numeric, 0)`,
486
+ updater: user
487
+ })
488
+ .setParameter('releaseQty', oi.releaseQty)
489
+ .setParameter('releaseUomValue', oi.releaseUomValue)
490
+ .where('id = :id', { id: oi.inventory.id })
491
+ .execute()
487
492
  }
488
493
 
489
494
  await tx.getRepository(OrderInventory).delete({ id: oi.id })
@@ -505,9 +510,11 @@ export async function deleteReleaseGood(tx: EntityManager, name: string, user: U
505
510
  .createQueryBuilder()
506
511
  .update(ProductDetailStock)
507
512
  .set({
508
- unassignedQty: () => `"unassigned_qty" - ${op.releaseQty}`,
509
- unassignedUomValue: () => `"unassigned_uom_value" - ${op.releaseUomValue}`
513
+ unassignedQty: () => `GREATEST("unassigned_qty" - :releaseQty::numeric, 0)`,
514
+ unassignedUomValue: () => `GREATEST("unassigned_uom_value" - :releaseUomValue::numeric, 0)`
510
515
  })
516
+ .setParameter('releaseQty', op.releaseQty)
517
+ .setParameter('releaseUomValue', op.releaseUomValue)
511
518
  .where({ productDetail: op.productDetail.id })
512
519
  .execute()
513
520
 
@@ -1131,20 +1138,37 @@ export async function generateReleaseGoodFunction(
1131
1138
  if (worksheetPickingAssignment?.value !== 'true' || oi.inventory?.id) {
1132
1139
  await tx.getRepository(OrderInventory).save({ ...oi, name: OrderNoGenerator.orderInventory() })
1133
1140
 
1134
- await tx.getRepository(Inventory).update(oi.inventory.id, {
1135
- lockedQty: (oi.inventory?.lockedQty || 0) + oi.releaseQty,
1136
- lockedUomValue: (oi.inventory?.lockedUomValue || 0) + oi.releaseUomValue,
1137
- updater: user
1138
- })
1141
+ const lockResult = await tx
1142
+ .getRepository(Inventory)
1143
+ .createQueryBuilder()
1144
+ .update(Inventory)
1145
+ .set({
1146
+ lockedQty: () => `COALESCE("locked_qty", 0) + :releaseQty::numeric`,
1147
+ lockedUomValue: () => `COALESCE("locked_uom_value", 0) + :releaseUomValue::numeric`,
1148
+ updater: user
1149
+ })
1150
+ .setParameter('releaseQty', oi.releaseQty)
1151
+ .setParameter('releaseUomValue', oi.releaseUomValue)
1152
+ .where('id = :id AND qty >= COALESCE(locked_qty, 0) + :newQty', {
1153
+ id: oi.inventory.id,
1154
+ newQty: oi.releaseQty
1155
+ })
1156
+ .execute()
1157
+
1158
+ if (lockResult.affected === 0) {
1159
+ throw new Error(`Insufficient inventory for ${oi.product?.sku || 'unknown product'}`)
1160
+ }
1139
1161
  } else {
1140
1162
  await tx
1141
1163
  .getRepository(ProductDetailStock)
1142
1164
  .createQueryBuilder()
1143
1165
  .update(ProductDetailStock)
1144
1166
  .set({
1145
- unassignedQty: () => `"unassigned_qty" + ${oi.releaseQty}`,
1146
- unassignedUomValue: () => `"unassigned_uom_value" + ${oi.releaseUomValue}`
1167
+ unassignedQty: () => `"unassigned_qty" + :releaseQty::numeric`,
1168
+ unassignedUomValue: () => `"unassigned_uom_value" + :releaseUomValue::numeric`
1147
1169
  })
1170
+ .setParameter('releaseQty', oi.releaseQty)
1171
+ .setParameter('releaseUomValue', oi.releaseUomValue)
1148
1172
  .where({ productDetail: oi.productDetail.id })
1149
1173
  .execute()
1150
1174
  }
@@ -1971,10 +1995,12 @@ export async function bulkGenerateReleaseGood(
1971
1995
  .createQueryBuilder()
1972
1996
  .update(Inventory)
1973
1997
  .set({
1974
- lockedQty: () => `COALESCE("locked_qty",0) + ${generatedOI.releaseQty}`,
1975
- lockedUomValue: () => `COALESCE("locked_uom_value",0) + ${generatedOI.releaseUomValue}`,
1998
+ lockedQty: () => `COALESCE("locked_qty",0) + :releaseQty::numeric`,
1999
+ lockedUomValue: () => `COALESCE("locked_uom_value",0) + :releaseUomValue::numeric`,
1976
2000
  updater: user
1977
2001
  })
2002
+ .setParameter('releaseQty', generatedOI.releaseQty)
2003
+ .setParameter('releaseUomValue', generatedOI.releaseUomValue)
1978
2004
  .where(`id = :id AND qty >= COALESCE(locked_qty,0) + :newQty`, {
1979
2005
  id: oi.inventory.id,
1980
2006
  newQty: generatedOI.releaseQty
@@ -1990,9 +2016,11 @@ export async function bulkGenerateReleaseGood(
1990
2016
  .createQueryBuilder()
1991
2017
  .update(ProductDetailStock)
1992
2018
  .set({
1993
- unassignedQty: () => `"unassigned_qty" + ${generatedOI.releaseQty}`,
1994
- unassignedUomValue: () => `"unassigned_uom_value" + ${generatedOI.releaseUomValue}`
2019
+ unassignedQty: () => `"unassigned_qty" + :releaseQty::numeric`,
2020
+ unassignedUomValue: () => `"unassigned_uom_value" + :releaseUomValue::numeric`
1995
2021
  })
2022
+ .setParameter('releaseQty', generatedOI.releaseQty)
2023
+ .setParameter('releaseUomValue', generatedOI.releaseUomValue)
1996
2024
  .where({ productDetail: oi.productDetail ? oi.productDetail.id : oi.productDetailId })
1997
2025
  .execute()
1998
2026
  }
@@ -1133,7 +1133,7 @@ export async function bulkReleaseGoodsAvailableItemsFunction(
1133
1133
  AND i.uom = foo.uom
1134
1134
  AND i.domain_id = $1
1135
1135
  AND i.bizplace_id = $2
1136
- WHERE l.type NOT IN ($3, $4)
1136
+ WHERE l.type NOT IN ($3, $4, $8)
1137
1137
  AND i.status = 'STORED'
1138
1138
  AND i.obsolete = false
1139
1139
  AND i.transfer_qty <= 0
@@ -1166,7 +1166,8 @@ export async function bulkReleaseGoodsAvailableItemsFunction(
1166
1166
  LOCATION_TYPE.RESERVE,
1167
1167
  uniqueWarehouseCodes.length === 1 ? uniqueWarehouseCodes[0] : null,
1168
1168
  uniqueBatchIds.length === 1 ? uniqueBatchIds[0] : null,
1169
- releaseShelfLifeOverride
1169
+ releaseShelfLifeOverride,
1170
+ LOCATION_TYPE.DAMAGE
1170
1171
  ]
1171
1172
  )
1172
1173
 
@@ -949,7 +949,7 @@ export const InventoryUtil = {
949
949
 
950
950
  let locationTypes = [LOCATION_TYPE.QUARANTINE, LOCATION_TYPE.RESERVE]
951
951
 
952
- if (recall === false) {
952
+ if (recall !== true) {
953
953
  locationTypes.push(LOCATION_TYPE.DAMAGE)
954
954
  }
955
955
 
@@ -1413,7 +1413,8 @@ export function _composeTargetInventories(
1413
1413
 
1414
1414
  let orderInventories: Partial<OrderInventory[]> = []
1415
1415
  let idx = 0
1416
- while (compReleaseQty < record.releaseQty) {
1416
+ const EPSILON = 1e-6
1417
+ while (compReleaseQty + EPSILON < record.releaseQty && idx < inventories.length) {
1417
1418
  const inventory = inventories[idx]
1418
1419
  const {
1419
1420
  packingType,
@@ -1466,5 +1467,9 @@ export function _composeTargetInventories(
1466
1467
  idx++
1467
1468
  }
1468
1469
 
1470
+ if (orderInventories.length === 0) {
1471
+ throw new Error(`no inventories could be allocated for ${product?.sku}`)
1472
+ }
1473
+
1469
1474
  return orderInventories
1470
1475
  }