|
|
|
@@ -4062,17 +4062,9 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto |
|
|
|
message = "Cannot resolve new inventory lot line", errorPosition = null |
|
|
|
) |
|
|
|
|
|
|
|
if (newIll.status == InventoryLotLineStatus.UNAVAILABLE) { |
|
|
|
return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Lot line unavailable", |
|
|
|
code = "LOT_UNAVAILABLE", |
|
|
|
type = "pickorder", |
|
|
|
message = "Cannot switch to unavailable inventory lot line", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
val targetUnavailable = newIll.status == InventoryLotLineStatus.UNAVAILABLE |
|
|
|
|
|
|
|
|
|
|
|
// Item consistency check |
|
|
|
val newItemId = newIll.inventoryLot?.item?.id |
|
|
|
if (newItemId == null || newItemId != polItemId) { |
|
|
|
@@ -4108,21 +4100,48 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
// Availability check on newIll BEFORE updates |
|
|
|
val inQty = newIll.inQty ?: zero |
|
|
|
val outQty = newIll.outQty ?: zero |
|
|
|
val holdQty = newIll.holdQty ?: zero |
|
|
|
val issueQty = newIll.issueQty ?: zero |
|
|
|
val available = inQty.subtract(outQty).subtract(holdQty).subtract(issueQty) |
|
|
|
if (!targetUnavailable) { |
|
|
|
// Availability check on newIll BEFORE updates |
|
|
|
val inQty = newIll.inQty ?: zero |
|
|
|
val outQty = newIll.outQty ?: zero |
|
|
|
val holdQty = newIll.holdQty ?: zero |
|
|
|
//val issueQty = newIll.issueQty ?: zero |
|
|
|
val available = inQty.subtract(outQty).subtract(holdQty)//.subtract(issueQty) |
|
|
|
|
|
|
|
if (available.compareTo(qtyToHold) < 0) { |
|
|
|
return MessageResponse( |
|
|
|
id = null, name = "Insufficient lot qty", code = "REJECT", type = "pickorder", |
|
|
|
message = "Reject switch lot: available=$available < required=$qtyToHold", errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (available.compareTo(qtyToHold) < 0) { |
|
|
|
val oldIll = spl.suggestedLotLine |
|
|
|
|
|
|
|
// Allow switch to UNAVAILABLE lot, but do NOT move hold/onHold and do NOT alter SOL status. |
|
|
|
if (targetUnavailable) { |
|
|
|
spl.suggestedLotLine = newIll |
|
|
|
suggestPickLotRepository.saveAndFlush(spl) |
|
|
|
|
|
|
|
if (req.stockOutLineId != null && req.stockOutLineId > 0) { |
|
|
|
val sol = stockOutLIneRepository.findById(req.stockOutLineId).orElse(null) |
|
|
|
if (sol != null) { |
|
|
|
sol.inventoryLotLine = newIll |
|
|
|
sol.item = pol.item |
|
|
|
stockOutLIneRepository.saveAndFlush(sol) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
val newLotNo = newIll.inventoryLot?.lotNo ?: req.newInventoryLotNo |
|
|
|
return MessageResponse( |
|
|
|
id = null, name = "Insufficient lot qty", code = "REJECT", type = "pickorder", |
|
|
|
message = "Reject switch lot: available=$available < required=$qtyToHold", errorPosition = null |
|
|
|
id = null, |
|
|
|
name = "Lot substitution confirmed (unavailable lot bound)", |
|
|
|
code = "SUCCESS_UNAVAILABLE", |
|
|
|
type = "pickorder", |
|
|
|
message = "Switched to unavailable lot '$newLotNo' without hold movement and without stock out status update", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
val oldIll = spl.suggestedLotLine |
|
|
|
|
|
|
|
// Load stock out line (if provided) to decide "bind vs split" |
|
|
|
val existingSol = if (req.stockOutLineId != null && req.stockOutLineId > 0) { |
|
|
|
|