in applications/manufacturing/src/main/java/org/apache/ofbiz/manufacturing/bom/BOMServices.java [496:770]
public static Map<String, Object> createShipmentPackages(DispatchContext dctx, Map<String, ? extends Object> context) {
Map<String, Object> result = new HashMap<>();
Delegator delegator = dctx.getDelegator();
LocalDispatcher dispatcher = dctx.getDispatcher();
Locale locale = (Locale) context.get("locale");
GenericValue userLogin = (GenericValue) context.get("userLogin");
String shipmentId = (String) context.get("shipmentId");
try {
List<GenericValue> packages = EntityQuery.use(delegator).from("ShipmentPackage").where("shipmentId", shipmentId).queryList();
if (UtilValidate.isNotEmpty(packages)) {
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingBomPackageAlreadyFound", locale));
}
} catch (GenericEntityException gee) {
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingBomErrorLoadingShipmentPackages", locale));
}
// ShipmentItems are loaded
List<GenericValue> shipmentItems = null;
try {
shipmentItems = EntityQuery.use(delegator).from("ShipmentItem").where("shipmentId", shipmentId).queryList();
} catch (GenericEntityException gee) {
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingBomErrorLoadingShipmentItems", locale));
}
Map<String, Object> orderReadHelpers = new HashMap<>();
Map<String, Object> partyOrderShipments = new HashMap<>();
for (GenericValue shipmentItem : shipmentItems) {
// Get the OrderShipments
GenericValue orderShipment = null;
try {
orderShipment = EntityQuery.use(delegator).from("OrderShipment")
.where("shipmentId", shipmentId,
"shipmentItemSeqId", shipmentItem.get("shipmentItemSeqId"))
.queryFirst();
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingPackageConfiguratorError", locale));
}
if (orderShipment != null && !orderReadHelpers.containsKey(orderShipment.getString("orderId"))) {
orderReadHelpers.put(orderShipment.getString("orderId"), new OrderReadHelper(delegator, orderShipment.getString("orderId")));
}
OrderReadHelper orderReadHelper = null;
if (orderShipment != null) {
orderReadHelper = (OrderReadHelper) orderReadHelpers.get(orderShipment.getString("orderId"));
}
if (orderReadHelper != null) {
Map<String, Object> orderShipmentReadMap = UtilMisc.toMap("orderShipment", orderShipment, "orderReadHelper", orderReadHelper);
String partyId = (orderReadHelper.getPlacingParty() != null ? orderReadHelper.getPlacingParty().getString("partyId") : null);
// FIXME: is it the customer?
if (partyId != null) {
if (!partyOrderShipments.containsKey(partyId)) {
List<Map<String, Object>> orderShipmentReadMapList = new LinkedList<>();
partyOrderShipments.put(partyId, orderShipmentReadMapList);
}
List<Map<String, Object>> orderShipmentReadMapList = UtilGenerics.cast(partyOrderShipments.get(partyId));
orderShipmentReadMapList.add(orderShipmentReadMap);
}
}
}
// For each party: try to expand the shipment item products
// (search for components that needs to be packaged).
for (Map.Entry<String, Object> partyOrderShipment : partyOrderShipments.entrySet()) {
List<Map<String, Object>> orderShipmentReadMapList = UtilGenerics.cast(partyOrderShipment.getValue());
for (Map<String, Object> stringObjectMap : orderShipmentReadMapList) {
Map<String, Object> orderShipmentReadMap = UtilGenerics.cast(stringObjectMap);
GenericValue orderShipment = (GenericValue) orderShipmentReadMap.get("orderShipment");
OrderReadHelper orderReadHelper = (OrderReadHelper) orderShipmentReadMap.get("orderReadHelper");
GenericValue orderItem = orderReadHelper.getOrderItem(orderShipment.getString("orderItemSeqId"));
// getProductsInPackages
Map<String, Object> serviceContext = new HashMap<>();
serviceContext.put("productId", orderItem.getString("productId"));
serviceContext.put("quantity", orderShipment.getBigDecimal("quantity"));
Map<String, Object> serviceResult = null;
try {
serviceResult = dispatcher.runSync("getProductsInPackages", serviceContext);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingPackageConfiguratorError", locale));
}
} catch (GenericServiceException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingPackageConfiguratorError", locale));
}
List<BOMNode> productsInPackages = UtilGenerics.cast(serviceResult.get("productsInPackages"));
if (productsInPackages.size() == 1) {
BOMNode root = productsInPackages.get(0);
String rootProductId = (root.getSubstitutedNode() != null ? root.getSubstitutedNode().getProduct().getString("productId")
: root.getProduct().getString("productId"));
if (orderItem.getString("productId").equals(rootProductId)) {
productsInPackages = null;
}
}
if (productsInPackages != null && productsInPackages.isEmpty()) {
productsInPackages = null;
}
if (UtilValidate.isNotEmpty(productsInPackages)) {
orderShipmentReadMap.put("productsInPackages", productsInPackages);
}
}
}
// Group together products and components
// of the same box type.
Map<String, GenericValue> boxTypes = new HashMap<>();
for (Map.Entry<String, Object> partyOrderShipment : partyOrderShipments.entrySet()) {
Map<String, List<Map<String, Object>>> boxTypeContent = new HashMap<>();
List<Map<String, Object>> orderShipmentReadMapList = UtilGenerics.cast(partyOrderShipment.getValue());
for (Map<String, Object> objectMap : orderShipmentReadMapList) {
Map<String, Object> orderShipmentReadMap = UtilGenerics.cast(objectMap);
GenericValue orderShipment = (GenericValue) orderShipmentReadMap.get("orderShipment");
OrderReadHelper orderReadHelper = (OrderReadHelper) orderShipmentReadMap.get("orderReadHelper");
List<BOMNode> productsInPackages = UtilGenerics.cast(orderShipmentReadMap.get("productsInPackages"));
if (productsInPackages != null) {
// there are subcomponents:
// this is a multi package shipment item
for (int j = 0; j < productsInPackages.size(); j++) {
BOMNode component = productsInPackages.get(j);
Map<String, Object> boxTypeContentMap = new HashMap<>();
boxTypeContentMap.put("content", orderShipmentReadMap);
boxTypeContentMap.put("componentIndex", j);
GenericValue product = component.getProduct();
String boxTypeId = product.getString("shipmentBoxTypeId");
if (boxTypeId != null) {
if (!boxTypes.containsKey(boxTypeId)) {
GenericValue boxType = null;
try {
boxType = EntityQuery.use(delegator).from("ShipmentBoxType").where("shipmentBoxTypeId", boxTypeId).queryOne();
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingPackageConfiguratorError",
locale));
}
boxTypes.put(boxTypeId, boxType);
List<Map<String, Object>> box = new LinkedList<>();
boxTypeContent.put(boxTypeId, box);
}
List<Map<String, Object>> boxTypeContentList = UtilGenerics.cast(boxTypeContent.get(boxTypeId));
boxTypeContentList.add(boxTypeContentMap);
}
}
} else {
// no subcomponents, the product has its own package:
// this is a single package shipment item
Map<String, Object> boxTypeContentMap = new HashMap<>();
boxTypeContentMap.put("content", orderShipmentReadMap);
GenericValue orderItem = orderReadHelper.getOrderItem(orderShipment.getString("orderItemSeqId"));
GenericValue product = null;
try {
product = orderItem.getRelatedOne("Product", false);
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingPackageConfiguratorError", locale));
}
String boxTypeId = product.getString("shipmentBoxTypeId");
if (boxTypeId != null) {
if (!boxTypes.containsKey(boxTypeId)) {
GenericValue boxType = null;
try {
boxType = EntityQuery.use(delegator).from("ShipmentBoxType").where("shipmentBoxTypeId", boxTypeId).queryOne();
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingPackageConfiguratorError", locale));
}
boxTypes.put(boxTypeId, boxType);
List<Map<String, Object>> box = new LinkedList<>();
boxTypeContent.put(boxTypeId, box);
}
List<Map<String, Object>> boxTypeContentList = UtilGenerics.cast(boxTypeContent.get(boxTypeId));
boxTypeContentList.add(boxTypeContentMap);
}
}
}
// The packages and package contents are created.
for (Map.Entry<String, List<Map<String, Object>>> boxTypeContentEntry : boxTypeContent.entrySet()) {
String boxTypeId = boxTypeContentEntry.getKey();
List<Map<String, Object>> contentList = UtilGenerics.cast(boxTypeContentEntry.getValue());
GenericValue boxType = boxTypes.get(boxTypeId);
BigDecimal boxWidth = boxType.getBigDecimal("boxLength");
BigDecimal totalWidth = BigDecimal.ZERO;
if (boxWidth == null) {
boxWidth = BigDecimal.ZERO;
}
String shipmentPackageSeqId = null;
for (Map<String, Object> stringObjectMap : contentList) {
Map<String, Object> contentMap = UtilGenerics.cast(stringObjectMap);
Map<String, Object> content = UtilGenerics.cast(contentMap.get("content"));
OrderReadHelper orderReadHelper = (OrderReadHelper) content.get("orderReadHelper");
List<BOMNode> productsInPackages = UtilGenerics.cast(content.get("productsInPackages"));
GenericValue orderShipment = (GenericValue) content.get("orderShipment");
GenericValue product = null;
BigDecimal quantity = BigDecimal.ZERO;
boolean subProduct = contentMap.containsKey("componentIndex");
if (subProduct) {
// multi package
Integer index = (Integer) contentMap.get("componentIndex");
BOMNode component = productsInPackages.get(index);
product = component.getProduct();
quantity = component.getQuantity();
} else {
// single package
GenericValue orderItem = orderReadHelper.getOrderItem(orderShipment.getString("orderItemSeqId"));
try {
product = orderItem.getRelatedOne("Product", false);
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingPackageConfiguratorError", locale));
}
quantity = orderShipment.getBigDecimal("quantity");
}
BigDecimal productDepth = product.getBigDecimal("shippingDepth");
if (productDepth == null) {
productDepth = product.getBigDecimal("productDepth");
}
if (productDepth == null) {
productDepth = BigDecimal.ONE;
}
BigDecimal firstMaxNumOfProducts = boxWidth.subtract(totalWidth).divide(productDepth, 0, RoundingMode.FLOOR);
if (firstMaxNumOfProducts.compareTo(BigDecimal.ZERO) == 0) firstMaxNumOfProducts = BigDecimal.ONE;
//
BigDecimal maxNumOfProducts = boxWidth.divide(productDepth, 0, RoundingMode.FLOOR);
if (maxNumOfProducts.compareTo(BigDecimal.ZERO) == 0) maxNumOfProducts = BigDecimal.ONE;
BigDecimal remQuantity = quantity;
boolean isFirst = true;
while (remQuantity.compareTo(BigDecimal.ZERO) > 0) {
BigDecimal maxQuantity = BigDecimal.ZERO;
if (isFirst) {
maxQuantity = firstMaxNumOfProducts;
isFirst = false;
} else {
maxQuantity = maxNumOfProducts;
}
BigDecimal qty = (remQuantity.compareTo(maxQuantity) < 0 ? remQuantity : maxQuantity);
// If needed, create the package
if (shipmentPackageSeqId == null) {
try {
Map<String, Object> serviceResult = dispatcher.runSync("createShipmentPackage",
UtilMisc.<String, Object>toMap("shipmentId", orderShipment.getString("shipmentId"), "shipmentBoxTypeId",
boxTypeId, "userLogin", userLogin));
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
}
shipmentPackageSeqId = (String) serviceResult.get("shipmentPackageSeqId");
} catch (GenericServiceException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingPackageConfiguratorError", locale));
}
totalWidth = BigDecimal.ZERO;
}
try {
Map<String, Object> inputMap = null;
if (subProduct) {
inputMap = UtilMisc.toMap("shipmentId", orderShipment.getString("shipmentId"),
"shipmentPackageSeqId", shipmentPackageSeqId,
"shipmentItemSeqId", orderShipment.getString("shipmentItemSeqId"),
"subProductId", product.getString("productId"),
"userLogin", userLogin,
"subProductQuantity", qty);
} else {
inputMap = UtilMisc.toMap("shipmentId", orderShipment.getString("shipmentId"),
"shipmentPackageSeqId", shipmentPackageSeqId,
"shipmentItemSeqId", orderShipment.getString("shipmentItemSeqId"),
"userLogin", userLogin,
"quantity", qty);
}
Map<String, Object> serviceResult = dispatcher.runSync("createShipmentPackageContent", inputMap);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingPackageConfiguratorError", locale));
}
} catch (GenericServiceException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingPackageConfiguratorError", locale));
}
totalWidth = totalWidth.add(qty.multiply(productDepth));
if (qty.compareTo(maxQuantity) == 0) shipmentPackageSeqId = null;
remQuantity = remQuantity.subtract(qty);
}
}
}
}
return result;
}