Fixed: In packing, only use reservations with stock on hand
During packing, OFBiz looks for reservations (OrderItemShipGrpInvRes)
for the order item. Some reservations are for back ordered items not on hand.
These reservations should not be used during packing, but they are.
@@ -144,8 +144,12 @@ public class PackingSession implements java.io.Serializable {
// find the inventoryItemId to use
if (reservations.size() == 1) {
GenericValue res = EntityUtil.getFirst(reservations);
+ BigDecimal resQty = numAvailableItems(res);
+
+ if (resQty.compareTo(quantity) > 0) {
int checkCode = this.checkLineForAdd(res, orderId, orderItemSeqId, shipGroupSeqId, productId, quantity, packageSeqId, update);
this.createPackLineItem(checkCode, res, orderId, orderItemSeqId, shipGroupSeqId, productId, quantity, weight, packageSeqId);
+ }
} else {
// more than one reservation found
Map<GenericValue, BigDecimal> toCreateMap = new HashMap<GenericValue, BigDecimal>();
@@ -160,7 +164,9 @@ public class PackingSession implements java.io.Serializable {
continue;
}
- BigDecimal resQty = res.getBigDecimal("quantity");
+ BigDecimal resQty = numAvailableItems(res);
+
+ if (resQty.compareTo(BigDecimal.ZERO) > 0) {
BigDecimal resPackedQty = this.getPackedQuantity(orderId, orderItemSeqId, shipGroupSeqId, productId, res.getString("inventoryItemId"), -1);
if (resPackedQty.compareTo(resQty) >= 0) {
continue;
@@ -189,6 +195,7 @@ public class PackingSession implements java.io.Serializable {
break;
}
}
+ }
if (qtyRemain.compareTo(BigDecimal.ZERO) == 0) {
for (Map.Entry<GenericValue, BigDecimal> entry: toCreateMap.entrySet()) {
@@ -205,6 +212,20 @@ public class PackingSession implements java.io.Serializable {
this.runEvents(PackingEvent.EVENT_CODE_ADD);
}
+ private BigDecimal numAvailableItems(GenericValue res) {
+ // In simple situations, the reserved quantity will match the quantity from the order item.
+ // If there is a back order, quantity from order may exceed quantity currently reserved and on hand.
+ // resQty should never exceed the quantity from the order item, because that quantity was the quantity reserved in the first place.
+ BigDecimal notAvailable = res.getBigDecimal("quantityNotAvailable");
+ BigDecimal resQty = res.getBigDecimal("quantity");
+
+ if (notAvailable != null) {
+ resQty = resQty.subtract(notAvailable);
+ }
+
+ return resQty;
+ }
+
public void addOrIncreaseLine(String orderId, String orderItemSeqId, String shipGroupSeqId, BigDecimal quantity, int packageSeqId) throws GeneralException {
this.addOrIncreaseLine(orderId, orderItemSeqId, shipGroupSeqId, null, quantity, packageSeqId, BigDecimal.ZERO, false);
}
