blob: c7eb53e9a17d580bd81bdc5aef00c16805430cdf [file] [log] [blame]
/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*******************************************************************************/
package org.apache.ofbiz.shipment.packing;
import java.math.BigDecimal;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.GeneralException;
import org.apache.ofbiz.base.util.UtilFormatOut;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.base.util.UtilValidate;
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.util.EntityQuery;
import org.apache.ofbiz.entity.util.EntityUtil;
import org.apache.ofbiz.product.product.ProductWorker;
import org.apache.ofbiz.service.GenericServiceException;
import org.apache.ofbiz.service.LocalDispatcher;
import org.apache.ofbiz.service.ServiceContainer;
import org.apache.ofbiz.service.ServiceUtil;
@SuppressWarnings("serial")
public class PackingSession implements java.io.Serializable {
public static final String module = PackingSession.class.getName();
protected GenericValue userLogin = null;
protected String pickerPartyId = null;
protected String primaryOrderId = null;
protected String primaryShipGrp = null;
protected String dispatcherName = null;
protected String delegatorName = null;
protected String picklistBinId = null;
protected String facilityId = null;
protected String shipmentId = null;
protected String instructions = null;
protected String weightUomId = null;
protected String shipmentBoxTypeId = null;
protected BigDecimal additionalShippingCharge = null;
protected Map<Integer, BigDecimal> packageWeights = null;
protected List<PackingEvent> packEvents = null;
protected List<PackingSessionLine> packLines = null;
protected List<ItemDisplay> itemInfos = null;
protected int packageSeq = -1;
protected int status = 1;
protected Map<Integer, String> shipmentBoxTypes = null;
private transient Delegator _delegator = null;
private transient LocalDispatcher _dispatcher = null;
public PackingSession(LocalDispatcher dispatcher, GenericValue userLogin, String facilityId, String binId, String orderId, String shipGrp) {
this._dispatcher = dispatcher;
this.dispatcherName = dispatcher.getName();
this._delegator = _dispatcher.getDelegator();
this.delegatorName = _delegator.getDelegatorName();
this.primaryOrderId = orderId;
this.primaryShipGrp = shipGrp;
this.picklistBinId = binId;
this.userLogin = userLogin;
this.facilityId = facilityId;
this.packLines = new LinkedList<PackingSessionLine>();
this.packEvents = new LinkedList<PackingEvent>();
this.itemInfos = new LinkedList<PackingSession.ItemDisplay>();
this.packageSeq = 1;
this.packageWeights = new HashMap<Integer, BigDecimal>();
this.shipmentBoxTypes = new HashMap<Integer, String>();
}
public PackingSession(LocalDispatcher dispatcher, GenericValue userLogin, String facilityId) {
this(dispatcher, userLogin, facilityId, null, null, null);
}
public PackingSession(LocalDispatcher dispatcher, GenericValue userLogin) {
this(dispatcher, userLogin, null, null, null, null);
}
public void addOrIncreaseLine(String orderId, String orderItemSeqId, String shipGroupSeqId, String productId, BigDecimal quantity, int packageSeqId, BigDecimal weight, boolean update) throws GeneralException {
// reset the session if we just completed
if (status == 0) {
throw new GeneralException("Packing session has been completed; be sure to CLEAR before packing a new order! [000]");
}
// do nothing if we are trying to add a quantity of 0
if (!update && quantity.compareTo(BigDecimal.ZERO) == 0) {
return;
}
// find the actual product ID
productId = ProductWorker.findProductId(this.getDelegator(), productId);
// set the default null values - primary is the assumed first item
if (orderId == null) {
orderId = primaryOrderId;
}
if (shipGroupSeqId == null) {
shipGroupSeqId = primaryShipGrp;
}
if (orderItemSeqId == null && productId != null) {
orderItemSeqId = this.findOrderItemSeqId(productId, orderId, shipGroupSeqId, quantity);
}
// 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);
List<GenericValue> reservations = this.getDelegator().findByAnd("OrderItemShipGrpInvRes", invLookup, UtilMisc.toList("quantity DESC"), false);
// no reservations we cannot add this item
if (UtilValidate.isEmpty(reservations)) {
throw new GeneralException("No inventory reservations available; cannot pack this item! [101]");
}
// find the inventoryItemId to use
if (reservations.size() == 1) {
GenericValue res = EntityUtil.getFirst(reservations);
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>();
Iterator<GenericValue> i = reservations.iterator();
BigDecimal qtyRemain = quantity;
while (i.hasNext() && qtyRemain.compareTo(BigDecimal.ZERO) > 0) {
GenericValue res = i.next();
// Check that the inventory item product match with the current product to pack
if (!productId.equals(res.getRelatedOne("InventoryItem", false).getString("productId"))) {
continue;
}
BigDecimal resQty = res.getBigDecimal("quantity");
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 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;
}
}
if (qtyRemain.compareTo(BigDecimal.ZERO) == 0) {
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);
}
} else {
throw new GeneralException("Not enough inventory reservation available; cannot pack the item! [103]");
}
}
// run the add events
this.runEvents(PackingEvent.EVENT_CODE_ADD);
}
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);
}
public void addOrIncreaseLine(String productId, BigDecimal quantity, int packageSeqId) throws GeneralException {
this.addOrIncreaseLine(null, null, null, productId, quantity, packageSeqId, BigDecimal.ZERO, false);
}
public PackingSessionLine findLine(String orderId, String orderItemSeqId, String shipGroupSeqId, String productId, String inventoryItemId, int packageSeq) {
for (PackingSessionLine line: this.getLines()) {
if (orderId.equals(line.getOrderId()) &&
orderItemSeqId.equals(line.getOrderItemSeqId()) &&
shipGroupSeqId.equals(line.getShipGroupSeqId()) &&
productId.equals(line.getProductId()) &&
inventoryItemId.equals(line.getInventoryItemId()) &&
packageSeq == line.getPackageSeq()) {
return line;
}
}
return null;
}
protected void createPackLineItem(int checkCode, GenericValue res, String orderId, String orderItemSeqId, String shipGroupSeqId, String productId, BigDecimal quantity, BigDecimal weight, int packageSeqId) throws GeneralException {
// process the result; add new item if necessary
switch (checkCode) {
case 0:
// not enough reserved
throw new GeneralException("Not enough inventory reservation available; cannot pack the item! [201]");
case 1:
// we're all good to go; quantity already updated
break;
case 2:
// need to create a new item
String invItemId = res.getString("inventoryItemId");
packLines.add(new PackingSessionLine(orderId, orderItemSeqId, shipGroupSeqId, productId, invItemId, quantity, weight, packageSeqId));
break;
}
// Add the line weight to the package weight
if (weight.compareTo(BigDecimal.ZERO) > 0) this.addToPackageWeight(packageSeqId, weight);
// update the package sequence
if (packageSeqId > packageSeq) {
this.packageSeq = packageSeqId;
}
}
protected String findOrderItemSeqId(String productId, String orderId, String shipGroupSeqId, BigDecimal quantity) throws GeneralException {
Map<String, Object> lookupMap = new HashMap<String, Object>();
lookupMap.put("orderId", orderId);
lookupMap.put("productId", productId);
lookupMap.put("statusId", "ITEM_APPROVED");
lookupMap.put("shipGroupSeqId", shipGroupSeqId);
List<String> sort = UtilMisc.toList("-quantity");
List<GenericValue> orderItems = this.getDelegator().findByAnd("OrderItemAndShipGroupAssoc", lookupMap, sort, false);
String orderItemSeqId = null;
if (orderItems != null) {
for (GenericValue item: orderItems) {
// get the reservations for the item
Map<String, Object> invLookup = new HashMap<String, Object>();
invLookup.put("orderId", orderId);
invLookup.put("orderItemSeqId", item.getString("orderItemSeqId"));
invLookup.put("shipGroupSeqId", shipGroupSeqId);
List<GenericValue> reservations = this.getDelegator().findByAnd("OrderItemShipGrpInvRes", invLookup, null, false);
for (GenericValue res: reservations) {
BigDecimal qty = res.getBigDecimal("quantity");
if (quantity.compareTo(qty) <= 0) {
orderItemSeqId = item.getString("orderItemSeqId");
break;
}
}
}
}
if (orderItemSeqId != null) {
return orderItemSeqId;
} else {
throw new GeneralException("No valid order item found for product [" + productId + "] with quantity: " + quantity);
}
}
protected int checkLineForAdd(GenericValue res, String orderId, String orderItemSeqId, String shipGroupSeqId, String productId, BigDecimal quantity, int packageSeqId, boolean update) {
// check to see if the reservation can hold the requested quantity amount
String invItemId = res.getString("inventoryItemId");
BigDecimal resQty = res.getBigDecimal("quantity");
PackingSessionLine line = this.findLine(orderId, orderItemSeqId, shipGroupSeqId, productId, invItemId, packageSeqId);
BigDecimal packedQty = this.getPackedQuantity(orderId, orderItemSeqId, shipGroupSeqId, productId);
Debug.logInfo("Packed quantity [" + packedQty + "] + [" + quantity + "]", module);
if (line == null) {
Debug.logInfo("No current line found testing [" + invItemId + "] R: " + resQty + " / Q: " + quantity, module);
if (resQty.compareTo(quantity) < 0) {
return 0;
} else {
return 2;
}
} else {
BigDecimal newQty = update ? quantity : (line.getQuantity().add(quantity));
Debug.logInfo("Existing line found testing [" + invItemId + "] R: " + resQty + " / Q: " + newQty, module);
if (resQty.compareTo(newQty) < 0) {
return 0;
} else {
line.setQuantity(newQty);
return 1;
}
}
}
public void addItemInfo(List<GenericValue> infos) {
for (GenericValue v: infos) {
ItemDisplay newItem = new ItemDisplay(v);
int currentIdx = itemInfos.indexOf(newItem);
if (currentIdx != -1) {
ItemDisplay existingItem = itemInfos.get(currentIdx);
existingItem.quantity = existingItem.quantity.add(newItem.quantity);
} else {
itemInfos.add(newItem);
}
}
}
public List<ItemDisplay> getItemInfos() {
return itemInfos;
}
/**
* <p>Delivers all the packing lines grouped by package.</p>
* Output map:
* <ul>
* <li>packageMap - a Map of type {@code Map<Integer, List<PackingSessionLine>>}
* that maps package sequence ids to the lines that belong in
* that package</li>
* <li>sortedKeys - a List of type List&lt;Integer&gt; with the sorted package
* sequence numbers to index the packageMap</li>
* </ul>
* @return result Map with packageMap and sortedKeys
*/
public Map<Object, Object> getPackingSessionLinesByPackage() {
Map<Integer, List<PackingSessionLine>> packageMap = new HashMap<Integer, List<PackingSessionLine>>();
for (PackingSessionLine line : packLines) {
int pSeq = line.getPackageSeq();
List<PackingSessionLine> packageLineList = packageMap.get(pSeq);
if (packageLineList == null) {
packageLineList = new LinkedList<PackingSessionLine>();
packageMap.put(pSeq, packageLineList);
}
packageLineList.add(line);
}
Object[] keys = packageMap.keySet().toArray();
java.util.Arrays.sort(keys);
List<Object> sortedKeys = new LinkedList<Object>();
for (Object key : keys) {
sortedKeys.add(key);
}
Map<Object, Object> result = new HashMap<Object, Object>();
result.put("packageMap", packageMap);
result.put("sortedKeys", sortedKeys);
return result;
}
public void clearItemInfos() {
itemInfos.clear();
}
public String getShipmentId() {
return this.shipmentId;
}
public List<PackingSessionLine> getLines() {
return this.packLines;
}
public int nextPackageSeq() {
return ++packageSeq;
}
public int getCurrentPackageSeq() {
return packageSeq;
}
public BigDecimal getPackedQuantity(String orderId, String orderItemSeqId, String shipGroupSeqId, String productId) {
return getPackedQuantity(orderId, orderItemSeqId, shipGroupSeqId, productId, null, -1);
}
public BigDecimal getPackedQuantity(String orderId, String orderItemSeqId, String shipGroupSeqId, String productId, int packageSeq) {
return getPackedQuantity(orderId, orderItemSeqId, shipGroupSeqId, productId, null, packageSeq);
}
public BigDecimal getPackedQuantity(String orderId, String orderItemSeqId, String shipGroupSeqId, String productId, String inventoryItemId, int packageSeq) {
BigDecimal total = BigDecimal.ZERO;
for (PackingSessionLine line: this.getLines()) {
if (orderId.equals(line.getOrderId()) && orderItemSeqId.equals(line.getOrderItemSeqId()) &&
shipGroupSeqId.equals(line.getShipGroupSeqId()) && productId.equals(line.getProductId())) {
if (inventoryItemId == null || inventoryItemId.equals(line.getInventoryItemId())) {
if (packageSeq == -1 || packageSeq == line.getPackageSeq()) {
total = total.add(line.getQuantity());
}
}
}
}
return total;
}
public BigDecimal getPackedQuantity(String productId, int packageSeq) {
if (productId != null) {
try {
productId = ProductWorker.findProductId(this.getDelegator(), productId);
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
}
BigDecimal total = BigDecimal.ZERO;
if (productId != null) {
for (PackingSessionLine line: this.getLines()) {
if (productId.equals(line.getProductId())) {
if (packageSeq == -1 || packageSeq == line.getPackageSeq()) {
total = total.add(line.getQuantity());
}
}
}
}
return total;
}
public BigDecimal getPackedQuantity(int packageSeq) {
BigDecimal total = BigDecimal.ZERO;
for (PackingSessionLine line: this.getLines()) {
if (packageSeq == -1 || packageSeq == line.getPackageSeq()) {
total = total.add(line.getQuantity());
}
}
return total;
}
public BigDecimal getPackedQuantity(String productId) {
return getPackedQuantity(productId, -1);
}
public BigDecimal getCurrentReservedQuantity(String orderId, String orderItemSeqId, String shipGroupSeqId, String productId) {
BigDecimal reserved = BigDecimal.ONE.negate();
try {
GenericValue res = EntityUtil.getFirst(this.getDelegator().findByAnd("OrderItemAndShipGrpInvResAndItemSum", UtilMisc.toMap("orderId", orderId,
"orderItemSeqId", orderItemSeqId, "shipGroupSeqId", shipGroupSeqId, "inventoryProductId", productId), null, false));
reserved = res.getBigDecimal("totQuantityAvailable");
if (reserved == null) {
reserved = BigDecimal.ONE.negate();
}
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
return reserved;
}
public BigDecimal getCurrentShippedQuantity(String orderId, String orderItemSeqId, String shipGroupSeqId) {
BigDecimal shipped = BigDecimal.ZERO;
List<GenericValue> issues = this.getItemIssuances(orderId, orderItemSeqId, shipGroupSeqId);
if (issues != null) {
for (GenericValue v: issues) {
BigDecimal qty = v.getBigDecimal("quantity");
if (qty == null) qty = BigDecimal.ZERO;
shipped = shipped.add(qty);
}
}
return shipped;
}
public List<String> getCurrentShipmentIds(String orderId, String orderItemSeqId, String shipGroupSeqId) {
Set<String> shipmentIds = new HashSet<String>();
List<GenericValue> issues = this.getItemIssuances(orderId, orderItemSeqId, shipGroupSeqId);
if (issues != null) {
for (GenericValue v: issues) {
shipmentIds.add(v.getString("shipmentId"));
}
}
List<String> retList = new LinkedList<String>();
retList.addAll(shipmentIds);
return retList;
}
public List<String> getCurrentShipmentIds(String orderId, String shipGroupSeqId) {
return this.getCurrentShipmentIds(orderId, null, shipGroupSeqId);
}
public void registerEvent(PackingEvent event) {
this.packEvents.add(event);
this.runEvents(PackingEvent.EVENT_CODE_EREG);
}
public LocalDispatcher getDispatcher() {
if (_dispatcher == null) {
_dispatcher = ServiceContainer.getLocalDispatcher(dispatcherName, this.getDelegator());
}
return _dispatcher;
}
public Delegator getDelegator() {
if (_delegator == null) {
_delegator = DelegatorFactory.getDelegator(delegatorName);
}
return _delegator;
}
public GenericValue getUserLogin() {
return this.userLogin;
}
public int getStatus() {
return this.status;
}
public String getFacilityId() {
return this.facilityId;
}
public void setFacilityId(String facilityId) {
this.facilityId = facilityId;
}
public String getPrimaryOrderId() {
return this.primaryOrderId;
}
public void setPrimaryOrderId(String orderId) {
this.primaryOrderId = orderId;
}
public String getPrimaryShipGroupSeqId() {
return this.primaryShipGrp;
}
public void setPrimaryShipGroupSeqId(String shipGroupSeqId) {
this.primaryShipGrp = shipGroupSeqId;
}
public void setPicklistBinId(String binId) {
this.picklistBinId = binId;
}
public String getPicklistBinId() {
return this.picklistBinId;
}
public String getHandlingInstructions() {
return this.instructions;
}
public void setHandlingInstructions(String instructions) {
this.instructions = instructions;
}
public void setPickerPartyId(String partyId) {
this.pickerPartyId = partyId;
}
public String getPickerPartyId() {
return this.pickerPartyId;
}
public int clearLastPackage() {
if (packageSeq == 1) {
this.clear();
return packageSeq;
}
List<PackingSessionLine> currentLines = UtilMisc.makeListWritable(this.packLines);
for (PackingSessionLine line: currentLines) {
if (line.getPackageSeq() == packageSeq) {
this.clearLine(line);
}
}
//return --packageSeq;
return packageSeq;
}
public void clearLine(PackingSessionLine line) {
this.packLines.remove(line);
BigDecimal packageWeight = this.packageWeights.get(line.packageSeq);
if (packageWeight != null) {
packageWeight = packageWeight.subtract(line.weight);
if (packageWeight.compareTo(BigDecimal.ZERO) < 0) {
packageWeight = BigDecimal.ZERO;
}
this.packageWeights.put(line.packageSeq, packageWeight);
}
if (line.packageSeq == packageSeq && packageSeq > 1) {
packageSeq--;
}
}
public void clearAllLines() {
this.packLines.clear();
this.packageWeights.clear();
this.shipmentBoxTypes.clear();
this.packageSeq = 1;
}
public void clear() {
this.packLines.clear();
this.instructions = null;
this.pickerPartyId = null;
this.picklistBinId = null;
this.primaryOrderId = null;
this.primaryShipGrp = null;
this.additionalShippingCharge = null;
if (this.packageWeights != null) this.packageWeights.clear();
if (this.shipmentBoxTypes != null) this.shipmentBoxTypes.clear();
this.weightUomId = null;
this.packageSeq = 1;
this.status = 1;
this.runEvents(PackingEvent.EVENT_CODE_CLEAR);
}
public String complete(boolean force) throws GeneralException {
// check to see if there is anything to process
if (this.getLines().size() == 0) {
return "EMPTY";
}
// check for errors
this.checkReservations(force);
// set the status to 0
this.status = 0;
// create the shipment
this.createShipment();
// create the packages
this.createPackages();
// issue the items
this.issueItemsToShipment();
// assign items to packages
this.applyItemsToPackages();
// update ShipmentRouteSegments with total weight and weightUomId
this.updateShipmentRouteSegments();
// set the shipment to packed
this.setShipmentToPacked();
// set role on picklist
this.setPickerOnPicklist();
// run the complete events
this.runEvents(PackingEvent.EVENT_CODE_COMPLETE);
return this.shipmentId;
}
protected void checkReservations(boolean ignore) throws GeneralException {
List<String> errors = new LinkedList<String>();
for (PackingSessionLine line: this.getLines()) {
BigDecimal reservedQty = this.getCurrentReservedQuantity(line.getOrderId(), line.getOrderItemSeqId(), line.getShipGroupSeqId(), line.getProductId());
BigDecimal packedQty = this.getPackedQuantity(line.getOrderId(), line.getOrderItemSeqId(), line.getShipGroupSeqId(), line.getProductId());
if (packedQty.compareTo(reservedQty) != 0) {
errors.add("Packed amount does not match reserved amount for item (" + line.getProductId() + ") [" + packedQty + " / " + reservedQty + "]");
}
}
if (errors.size() > 0) {
if (!ignore) {
throw new GeneralException("Attempt to pack order failed.", errors);
} else {
Debug.logWarning("Packing warnings: " + errors, module);
}
}
}
protected void checkEmptyLines() throws GeneralException {
List<PackingSessionLine> lines = new LinkedList<PackingSessionLine>();
lines.addAll(this.getLines());
for (PackingSessionLine l: lines) {
if (l.getQuantity().compareTo(BigDecimal.ZERO) == 0) {
this.packLines.remove(l);
}
}
}
protected void runEvents(int eventCode) {
if (this.packEvents.size() > 0) {
for (PackingEvent event: this.packEvents) {
event.runEvent(this, eventCode);
}
}
}
protected List<GenericValue> getItemIssuances(String orderId, String orderItemSeqId, String shipGroupSeqId) {
List<GenericValue> issues = null;
if (orderId == null) {
throw new IllegalArgumentException("Value for orderId is null");
}
Map<String, Object> lookupMap = new HashMap<String, Object>();
lookupMap.put("orderId", orderId);
if (UtilValidate.isNotEmpty(orderItemSeqId)) {
lookupMap.put("orderItemSeqId", orderItemSeqId);
}
if (UtilValidate.isNotEmpty(shipGroupSeqId)) {
lookupMap.put("shipGroupSeqId", shipGroupSeqId);
}
try {
issues = this.getDelegator().findByAnd("ItemIssuance", lookupMap, null, false);
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
return issues;
}
protected void createShipment() throws GeneralException {
// first create the shipment
Delegator delegator = this.getDelegator();
Map<String, Object> newShipment = new HashMap<String, Object>();
newShipment.put("originFacilityId", this.facilityId);
newShipment.put("primaryShipGroupSeqId", primaryShipGrp);
newShipment.put("primaryOrderId", primaryOrderId);
newShipment.put("shipmentTypeId", "OUTGOING_SHIPMENT");
newShipment.put("statusId", "SHIPMENT_INPUT");
newShipment.put("handlingInstructions", instructions);
newShipment.put("picklistBinId", picklistBinId);
newShipment.put("additionalShippingCharge", additionalShippingCharge);
newShipment.put("userLogin", userLogin);
GenericValue orderRoleShipTo = EntityQuery.use(delegator).from("OrderRole").where("orderId", primaryOrderId, "roleTypeId", "SHIP_TO_CUSTOMER").queryFirst();
if (UtilValidate.isNotEmpty(orderRoleShipTo)) {
newShipment.put("partyIdTo", orderRoleShipTo.getString("partyId"));
}
String partyIdFrom = null;
if (primaryOrderId != null) {
GenericValue orderItemShipGroup = EntityQuery.use(delegator).from("OrderItemShipGroup").where("orderId", primaryOrderId, "shipGroupSeqId", primaryShipGrp).queryFirst();
if (UtilValidate.isNotEmpty(orderItemShipGroup.getString("vendorPartyId"))) {
partyIdFrom = orderItemShipGroup.getString("vendorPartyId");
} else if (UtilValidate.isNotEmpty(orderItemShipGroup.getString("facilityId"))) {
GenericValue facility = EntityQuery.use(delegator).from("Facility").where("facilityId", orderItemShipGroup.getString("facilityId")).queryOne();
if (UtilValidate.isNotEmpty(facility.getString("ownerPartyId"))) {
partyIdFrom = facility.getString("ownerPartyId");
}
}
if (UtilValidate.isEmpty(partyIdFrom)) {
GenericValue orderRoleShipFrom = EntityQuery.use(delegator).from("OrderRole").where("orderId", primaryOrderId, "roleTypeId", "SHIP_FROM_VENDOR").queryFirst();
if (UtilValidate.isNotEmpty(orderRoleShipFrom)) {
partyIdFrom = orderRoleShipFrom.getString("partyId");
} else {
orderRoleShipFrom = EntityQuery.use(delegator).from("OrderRole").where("orderId", primaryOrderId, "roleTypeId", "BILL_FROM_VENDOR").queryFirst();
partyIdFrom = orderRoleShipFrom.getString("partyId");
}
}
} else if (this.facilityId != null) {
GenericValue facility = EntityQuery.use(delegator).from("Facility").where("facilityId", this.facilityId).queryOne();
if (UtilValidate.isNotEmpty(facility.getString("ownerPartyId"))) {
partyIdFrom = facility.getString("ownerPartyId");
}
}
newShipment.put("partyIdFrom", partyIdFrom);
Debug.logInfo("Creating new shipment with context: " + newShipment, module);
Map<String, Object> newShipResp = this.getDispatcher().runSync("createShipment", newShipment);
if (ServiceUtil.isError(newShipResp)) {
throw new GeneralException(ServiceUtil.getErrorMessage(newShipResp));
}
this.shipmentId = (String) newShipResp.get("shipmentId");
}
protected void issueItemsToShipment() throws GeneralException {
List<PackingSessionLine> processedLines = new LinkedList<PackingSessionLine>();
for (PackingSessionLine line: this.getLines()) {
if (this.checkLine(processedLines, line)) {
BigDecimal totalPacked = this.getPackedQuantity(line.getOrderId(), line.getOrderItemSeqId(),
line.getShipGroupSeqId(), line.getProductId(), line.getInventoryItemId(), -1);
line.issueItemToShipment(shipmentId, picklistBinId, userLogin, totalPacked, getDispatcher());
processedLines.add(line);
}
}
}
protected boolean checkLine(List<PackingSessionLine> processedLines, PackingSessionLine line) {
for (PackingSessionLine l: processedLines) {
if (line.isSameItem(l)) {
line.setShipmentItemSeqId(l.getShipmentItemSeqId());
return false;
}
}
return true;
}
protected void createPackages() throws GeneralException {
for (int i = 0; i < packageSeq; i++) {
String shipmentPackageSeqId = UtilFormatOut.formatPaddedNumber(i+1, 5);
Map<String, Object> pkgCtx = new HashMap<String, Object>();
pkgCtx.put("shipmentId", shipmentId);
pkgCtx.put("shipmentPackageSeqId", shipmentPackageSeqId);
pkgCtx.put("shipmentBoxTypeId", getShipmentBoxType(i+1));
pkgCtx.put("weight", getPackageWeight(i+1));
pkgCtx.put("weightUomId", getWeightUomId());
pkgCtx.put("userLogin", userLogin);
Map<String, Object> newPkgResp = this.getDispatcher().runSync("createShipmentPackage", pkgCtx);
if (ServiceUtil.isError(newPkgResp)) {
throw new GeneralException(ServiceUtil.getErrorMessage(newPkgResp));
}
}
}
protected void applyItemsToPackages() throws GeneralException {
for (PackingSessionLine line: this.getLines()) {
line.applyLineToPackage(shipmentId, userLogin, getDispatcher());
}
}
protected void updateShipmentRouteSegments() throws GeneralException {
BigDecimal shipmentWeight = getTotalWeight();
if (shipmentWeight.compareTo(BigDecimal.ZERO) <= 0) return;
List<GenericValue> shipmentRouteSegments = getDelegator().findByAnd("ShipmentRouteSegment", UtilMisc.toMap("shipmentId", this.getShipmentId()), null, false);
if (! UtilValidate.isEmpty(shipmentRouteSegments)) {
for (GenericValue shipmentRouteSegment: shipmentRouteSegments) {
shipmentRouteSegment.set("billingWeight", shipmentWeight);
shipmentRouteSegment.set("billingWeightUomId", getWeightUomId());
}
getDelegator().storeAll(shipmentRouteSegments);
}
}
protected void setShipmentToPacked() throws GeneralException {
Map<String, Object> packedCtx = UtilMisc.toMap("shipmentId", shipmentId, "statusId", "SHIPMENT_PACKED", "userLogin", userLogin);
Map<String, Object> packedResp = this.getDispatcher().runSync("updateShipment", packedCtx);
if (packedResp != null && ServiceUtil.isError(packedResp)) {
throw new GeneralException(ServiceUtil.getErrorMessage(packedResp));
}
}
protected void setPickerOnPicklist() throws GeneralException {
if (picklistBinId != null) {
// first find the picklist id
GenericValue bin = this.getDelegator().findOne("PicklistBin", UtilMisc.toMap("picklistBinId", picklistBinId), false);
if (bin != null) {
Map<String, Object> ctx = new HashMap<String, Object>();
ctx.put("picklistId", bin.getString("picklistId"));
ctx.put("partyId", pickerPartyId);
ctx.put("roleTypeId", "PICKER");
// check if the role already exists and is valid
List<GenericValue> currentRoles = this.getDelegator().findByAnd("PicklistRole", ctx, null, false);
currentRoles = EntityUtil.filterByDate(currentRoles);
// if not; create the role
if (UtilValidate.isNotEmpty(currentRoles)) {
ctx.put("userLogin", userLogin);
Map<String, Object> addRole = this.getDispatcher().runSync("createPicklistRole", ctx);
if (ServiceUtil.isError(addRole)) {
throw new GeneralException(ServiceUtil.getErrorMessage(addRole));
}
}
}
}
}
public BigDecimal getAdditionalShippingCharge() {
return additionalShippingCharge;
}
public void setAdditionalShippingCharge(BigDecimal additionalShippingCharge) {
this.additionalShippingCharge = additionalShippingCharge;
}
public BigDecimal getTotalWeight() {
BigDecimal total = BigDecimal.ZERO;
for (int i = 0; i < packageSeq; i++) {
BigDecimal packageWeight = getPackageWeight(i);
if (! UtilValidate.isEmpty(packageWeight)) {
total = total.add(packageWeight);
}
}
return total;
}
public BigDecimal getShipmentCostEstimate(GenericValue orderItemShipGroup, String productStoreId, List<GenericValue> shippableItemInfo, BigDecimal shippableTotal, BigDecimal shippableWeight, BigDecimal shippableQuantity) {
return getShipmentCostEstimate(orderItemShipGroup.getString("contactMechId"), orderItemShipGroup.getString("shipmentMethodTypeId"),
orderItemShipGroup.getString("carrierPartyId"), orderItemShipGroup.getString("carrierRoleTypeId"),
productStoreId, shippableItemInfo, shippableTotal, shippableWeight, shippableQuantity);
}
public BigDecimal getShipmentCostEstimate(GenericValue orderItemShipGroup, String productStoreId) {
return getShipmentCostEstimate(orderItemShipGroup.getString("contactMechId"), orderItemShipGroup.getString("shipmentMethodTypeId"),
orderItemShipGroup.getString("carrierPartyId"), orderItemShipGroup.getString("carrierRoleTypeId"),
productStoreId, null, null, null, null);
}
public BigDecimal getShipmentCostEstimate(String shippingContactMechId, String shipmentMethodTypeId, String carrierPartyId, String carrierRoleTypeId, String productStoreId, List<GenericValue> shippableItemInfo, BigDecimal shippableTotal, BigDecimal shippableWeight, BigDecimal shippableQuantity) {
BigDecimal shipmentCostEstimate = null;
Map<String, Object> serviceResult = null;
try {
Map<String, Object> serviceContext = new HashMap<String, Object>();
serviceContext.put("shippingContactMechId", shippingContactMechId);
serviceContext.put("shipmentMethodTypeId", shipmentMethodTypeId);
serviceContext.put("carrierPartyId", carrierPartyId);
serviceContext.put("carrierRoleTypeId", carrierRoleTypeId);
serviceContext.put("productStoreId", productStoreId);
if (UtilValidate.isEmpty(shippableItemInfo)) {
shippableItemInfo = new LinkedList<GenericValue>();
for (PackingSessionLine line: getLines()) {
List<GenericValue> oiasgas = getDelegator().findByAnd("OrderItemAndShipGroupAssoc", UtilMisc.toMap("orderId", line.getOrderId(), "orderItemSeqId", line.getOrderItemSeqId(), "shipGroupSeqId", line.getShipGroupSeqId()), null, false);
shippableItemInfo.addAll(oiasgas);
}
}
serviceContext.put("shippableItemInfo", shippableItemInfo);
if (UtilValidate.isEmpty(shippableWeight)) {
shippableWeight = getTotalWeight();
}
serviceContext.put("shippableWeight", shippableWeight);
if (UtilValidate.isEmpty(shippableQuantity)) {
shippableQuantity = getPackedQuantity(-1);
}
serviceContext.put("shippableQuantity", shippableQuantity);
if (UtilValidate.isEmpty(shippableTotal)) {
shippableTotal = BigDecimal.ZERO;
}
serviceContext.put("shippableTotal", shippableTotal);
serviceResult = getDispatcher().runSync("calcShipmentCostEstimate", serviceContext);
} catch (GenericEntityException e) {
Debug.logError(e, module);
} catch (GenericServiceException e) {
Debug.logError(e, module);
}
if (UtilValidate.isNotEmpty(serviceResult)) {
shipmentCostEstimate = (BigDecimal) serviceResult.get("shippingEstimateAmount");
}
return shipmentCostEstimate;
}
public String getWeightUomId() {
return weightUomId;
}
public void setWeightUomId(String weightUomId) {
this.weightUomId = weightUomId;
}
public void setShipmentBoxTypeId(String shipmentBoxTypeId) {
this.shipmentBoxTypeId = shipmentBoxTypeId;
}
public List<Integer> getPackageSeqIds() {
Set<Integer> packageSeqIds = new TreeSet<Integer>();
if (! UtilValidate.isEmpty(this.getLines())) {
for (PackingSessionLine line: this.getLines()) {
packageSeqIds.add(Integer.valueOf(line.getPackageSeq()));
}
}
return UtilMisc.makeListWritable(packageSeqIds);
}
public void setPackageWeight(int packageSeqId, BigDecimal packageWeight) {
if (UtilValidate.isEmpty(packageWeight)) {
packageWeights.remove(Integer.valueOf(packageSeqId));
} else {
packageWeights.put(Integer.valueOf(packageSeqId), packageWeight);
}
}
public BigDecimal getPackageWeight(int packageSeqId) {
if (this.packageWeights == null) return null;
BigDecimal packageWeight = null;
Object p = packageWeights.get(packageSeqId);
if (p != null) {
packageWeight = (BigDecimal) p;
}
return packageWeight;
}
public void addToPackageWeight(int packageSeqId, BigDecimal weight) {
if (UtilValidate.isEmpty(weight)) return;
BigDecimal packageWeight = getPackageWeight(packageSeqId);
BigDecimal newPackageWeight = UtilValidate.isEmpty(packageWeight) ? weight : weight.add(packageWeight);
setPackageWeight(packageSeqId, newPackageWeight);
}
// These methods (setShipmentBoxType and getShipmentBoxType) are added so that each package will have different box type.
public void setShipmentBoxType(int packageSeqId, String shipmentBoxType) {
if (UtilValidate.isEmpty(shipmentBoxType)) {
shipmentBoxTypes.remove(Integer.valueOf(packageSeqId));
} else {
shipmentBoxTypes.put(Integer.valueOf(packageSeqId), shipmentBoxType);
}
}
public String getShipmentBoxType(int packageSeqId) {
if (this.shipmentBoxTypes == null) return null;
String shipmentBoxType = null;
Object p = shipmentBoxTypes.get(packageSeqId);
if (p != null) {
shipmentBoxType = (String) p;
}
return shipmentBoxType;
}
class ItemDisplay extends AbstractMap<Object, Object> {
public GenericValue orderItem;
public BigDecimal quantity;
public String productId;
public ItemDisplay(GenericValue v) {
if ("PicklistItem".equals(v.getEntityName())) {
quantity = v.getBigDecimal("quantity").setScale(2, BigDecimal.ROUND_HALF_UP);
try {
orderItem = v.getRelatedOne("OrderItem", false);
productId = v.getRelatedOne("InventoryItem", false).getString("productId");
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
} else {
// this is an OrderItemAndShipGrpInvResAndItemSum
orderItem = v;
productId = v.getString("inventoryProductId");
quantity = v.getBigDecimal("totQuantityReserved").setScale(2, BigDecimal.ROUND_HALF_UP);
}
Debug.logInfo("created item display object quantity: " + quantity + " (" + productId + ")", module);
}
public GenericValue getOrderItem() {
return orderItem;
}
public BigDecimal getQuantity() {
return quantity;
}
@Override
public Set<Entry<Object, Object>> entrySet() {
return null;
}
@Override
public Object get(Object name) {
if ("orderItem".equals(name.toString())) {
return orderItem;
} else if ("quantity".equals(name.toString())) {
return quantity;
} else if ("productId".equals(name.toString())) {
return productId;
}
return null;
}
@Override
public boolean equals(Object o) {
if (o instanceof ItemDisplay) {
ItemDisplay d = (ItemDisplay) o;
boolean sameOrderItemProduct = true;
if (d.getOrderItem().getString("productId") != null && orderItem.getString("productId") != null) {
sameOrderItemProduct = d.getOrderItem().getString("productId").equals(orderItem.getString("productId"));
} else if (d.getOrderItem().getString("productId") != null || orderItem.getString("productId") != null) {
sameOrderItemProduct = false;
}
return (d.productId.equals(productId) &&
d.getOrderItem().getString("orderItemSeqId").equals(orderItem.getString("orderItemSeqId")) &&
sameOrderItemProduct);
} else {
return false;
}
}
}
}