This is an automated email from the ASF dual-hosted git repository. jleroux pushed a commit to branch release22.01 in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git
The following commit(s) were added to refs/heads/release22.01 by this push: new 31167ae3a6 Fixed: Picklist with same product multiple times (OFBIZ-12707) 31167ae3a6 is described below commit 31167ae3a64597aab9139bf2823fa3e10b413cb9 Author: Jacques Le Roux <jacques.le.r...@les7arts.com> AuthorDate: Thu Oct 20 11:21:06 2022 +0200 Fixed: Picklist with same product multiple times (OFBIZ-12707) Create an order with the same product in different order item lines - for example with different amount, comment. Goto Facility --> Pack shipment --> Enter orderId You will see two lines with the same product. Enter the productId into the input box (leave quantity 1) and click pack item. You will receive an error message saying the quantity is not available for this packing item ... This fixes enables packing with the above setting. That's important if you have the situation that products can't be grouped by orderSeqId (order item comments, amounts ...). jleroux: I formatted to fix checkStyle issues Thanks: Ingo Wolfmayr --- .../ofbiz/shipment/packing/PackingSession.java | 141 ++++++++++++--------- 1 file changed, 80 insertions(+), 61 deletions(-) diff --git a/applications/product/src/main/java/org/apache/ofbiz/shipment/packing/PackingSession.java b/applications/product/src/main/java/org/apache/ofbiz/shipment/packing/PackingSession.java index bd02effbab..4b33107df7 100644 --- a/applications/product/src/main/java/org/apache/ofbiz/shipment/packing/PackingSession.java +++ b/applications/product/src/main/java/org/apache/ofbiz/shipment/packing/PackingSession.java @@ -39,6 +39,9 @@ import org.apache.ofbiz.entity.Delegator; import org.apache.ofbiz.entity.DelegatorFactory; import org.apache.ofbiz.entity.GenericEntityException; import org.apache.ofbiz.entity.GenericValue; +import org.apache.ofbiz.entity.condition.EntityCondition; +import org.apache.ofbiz.entity.condition.EntityConditionList; +import org.apache.ofbiz.entity.condition.EntityOperator; import org.apache.ofbiz.entity.util.EntityQuery; import org.apache.ofbiz.entity.util.EntityUtil; import org.apache.ofbiz.product.product.ProductWorker; @@ -157,16 +160,43 @@ public class PackingSession implements java.io.Serializable { if (shipGroupSeqId == null) { shipGroupSeqId = primaryShipGrp; } + + List<GenericValue> reservations = null; + List<String> orderItemSeqIds = new LinkedList<String>(); + if (orderItemSeqId == null && productId != null) { - orderItemSeqId = this.findOrderItemSeqId(productId, orderId, shipGroupSeqId, quantity); + orderItemSeqIds = this.findOrderItemSeqId(productId, orderId, shipGroupSeqId, quantity); + + if (orderItemSeqIds.size() == 1) { + orderItemSeqId = orderItemSeqIds.get(0); + + // get the reservations for the item + Map<String, Object> invLookup = new HashMap<String, Object>(); + invLookup.put("orderId", orderId); + invLookup.put("orderItemSeqId", orderItemSeqId); + invLookup.put("shipGroupSeqId", shipGroupSeqId); + reservations = this.getDelegator().findByAnd("OrderItemShipGrpInvRes", invLookup, + UtilMisc.toList("quantity DESC"), false); + } else { + List<EntityCondition> exprList = new LinkedList<EntityCondition>(); + exprList.add(EntityCondition.makeCondition("orderId", EntityOperator.EQUALS, orderId)); + exprList.add(EntityCondition.makeCondition("orderItemSeqId", EntityOperator.IN, orderItemSeqIds)); + exprList.add(EntityCondition.makeCondition("shipGroupSeqId", EntityOperator.EQUALS, shipGroupSeqId)); + EntityConditionList<EntityCondition> orderSeqExprList = EntityCondition.makeCondition(exprList, EntityOperator.AND); + reservations = this.getDelegator().findList("OrderItemShipGrpInvRes", orderSeqExprList, null, + UtilMisc.toList("quantity"), null, false); + } } // get the reservations for the item - Map<String, Object> invLookup = new HashMap<>(); - invLookup.put("orderId", orderId); - invLookup.put("orderItemSeqId", orderItemSeqId); - invLookup.put("shipGroupSeqId", shipGroupSeqId); - List<GenericValue> reservations = this.getDelegator().findByAnd("OrderItemShipGrpInvRes", invLookup, UtilMisc.toList("quantity DESC"), false); + if (UtilValidate.isEmpty(reservations)) { + // get the reservations for the item + Map<String, Object> invLookup = new HashMap<String, Object>(); + invLookup.put("orderId", orderId); + invLookup.put("orderItemSeqId", orderItemSeqId); + invLookup.put("shipGroupSeqId", shipGroupSeqId); + reservations = this.getDelegator().findByAnd("OrderItemShipGrpInvRes", invLookup, UtilMisc.toList("quantity DESC"), false); + } // no reservations we cannot add this item if (UtilValidate.isEmpty(reservations)) { @@ -176,13 +206,10 @@ 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 reservation has enough for the quantity required - 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); - } + int checkCode = this.checkLineForAdd(res, res.get("orderId").toString(), + res.get("orderItemSeqId").toString(), res.get("shipGroupSeqId").toString(), productId, quantity, packageSeqId, update); + this.createPackLineItem(checkCode, res, res.get("orderId").toString(), + res.get("orderItemSeqId").toString(), res.get("shipGroupSeqId").toString(), productId, quantity, weight, packageSeqId); } else { // more than one reservation found Map<GenericValue, BigDecimal> toCreateMap = new HashMap<>(); @@ -197,37 +224,41 @@ public class PackingSession implements java.io.Serializable { continue; } - 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; - } else if (!update) { - resQty = resQty.subtract(resPackedQty); - } + BigDecimal resQty = res.getBigDecimal("quantity"); + BigDecimal resPackedQty = this.getPackedQuantity( + res.get("orderId").toString(), + res.get("orderItemSeqId").toString(), + res.get("shipGroupSeqId").toString(), + productId, res.getString("inventoryItemId"), -1); + if (resPackedQty.compareTo(resQty) >= 0) { + continue; + } else if (!update) { + resQty = resQty.subtract(resPackedQty); + } - BigDecimal thisQty = resQty.compareTo(qtyRemain) > 0 ? qtyRemain : resQty; - - int thisCheck = this.checkLineForAdd(res, orderId, orderItemSeqId, shipGroupSeqId, productId, thisQty, packageSeqId, update); - switch (thisCheck) { - case 2: - Debug.logInfo("Packing check returned '2' - new pack line will be created!", MODULE); - toCreateMap.put(res, thisQty); - qtyRemain = qtyRemain.subtract(thisQty); - break; - case 1: - Debug.logInfo("Packing check returned '1' - existing pack line has been updated!", MODULE); - qtyRemain = qtyRemain.subtract(thisQty); - break; - case 0: - Debug.logInfo("Packing check returned '0' - doing nothing.", MODULE); - break; - default: - Debug.logInfo("Packing check returned '> 2' or '< 0'", MODULE); - break; - } + BigDecimal thisQty = resQty.compareTo(qtyRemain) > 0 ? qtyRemain : resQty; + + int thisCheck = this.checkLineForAdd(res, + res.get("orderId").toString(), + res.get("orderItemSeqId").toString(), + res.get("shipGroupSeqId").toString(), + productId, thisQty, packageSeqId, update); + switch (thisCheck) { + case 2: + Debug.logInfo("Packing check returned '2' - new pack line will be created!", MODULE); + toCreateMap.put(res, thisQty); + qtyRemain = qtyRemain.subtract(thisQty); + break; + case 1: + Debug.logInfo("Packing check returned '1' - existing pack line has been updated!", MODULE); + qtyRemain = qtyRemain.subtract(thisQty); + break; + case 0: + Debug.logInfo("Packing check returned '0' - doing nothing.", MODULE); + break; + default: + Debug.logInfo("Packing check returned '> 2' or '< 0'", MODULE); + break; } } @@ -235,7 +266,8 @@ public class PackingSession implements java.io.Serializable { for (Map.Entry<GenericValue, BigDecimal> entry: toCreateMap.entrySet()) { GenericValue res = entry.getKey(); BigDecimal qty = entry.getValue(); - this.createPackLineItem(2, res, orderId, orderItemSeqId, shipGroupSeqId, productId, qty, weight, packageSeqId); + this.createPackLineItem(2, res, res.get("orderId").toString(), res.get("orderItemSeqId").toString(), + res.get("shipGroupSeqId").toString(), productId, qty, weight, packageSeqId); } } else { throw new GeneralException("Not enough inventory reservation available; cannot pack the item! [103]"); @@ -246,20 +278,6 @@ public class PackingSession implements java.io.Serializable { this.runEvents(PackingEvent.EVENT_CODE_ADD); } - private static 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; - } - /** * Add or increase line. * @param orderId the order id @@ -361,7 +379,7 @@ public class PackingSession implements java.io.Serializable { * @return the string * @throws GeneralException the general exception */ - protected String findOrderItemSeqId(String productId, String orderId, String shipGroupSeqId, BigDecimal quantity) throws GeneralException { + protected List<String> findOrderItemSeqId(String productId, String orderId, String shipGroupSeqId, BigDecimal quantity) throws GeneralException { Map<String, Object> lookupMap = new HashMap<>(); lookupMap.put("orderId", orderId); lookupMap.put("productId", productId); @@ -372,6 +390,7 @@ public class PackingSession implements java.io.Serializable { List<GenericValue> orderItems = this.getDelegator().findByAnd("OrderItemAndShipGroupAssoc", lookupMap, sort, false); String orderItemSeqId = null; + List<String> orderItemSeqIds = new LinkedList<String>(); if (orderItems != null) { for (GenericValue item: orderItems) { // get the reservations for the item @@ -384,14 +403,14 @@ public class PackingSession implements java.io.Serializable { BigDecimal qty = res.getBigDecimal("quantity"); if (quantity.compareTo(qty) <= 0) { orderItemSeqId = item.getString("orderItemSeqId"); - break; + orderItemSeqIds.add(orderItemSeqId); } } } } if (orderItemSeqId != null) { - return orderItemSeqId; + return orderItemSeqIds; } else { throw new GeneralException("No valid order item found for product [" + productId + "] with quantity: " + quantity); }