blob: c81a0ae2c7a83e27813a0a4fe83ff808332d5979 [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.order.shoppingcart;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.MathContext;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.GeneralException;
import org.apache.ofbiz.base.util.GeneralRuntimeException;
import org.apache.ofbiz.base.util.UtilDateTime;
import org.apache.ofbiz.base.util.UtilFormatOut;
import org.apache.ofbiz.base.util.UtilGenerics;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.base.util.UtilNumber;
import org.apache.ofbiz.base.util.UtilProperties;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.common.DataModelConstants;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.DelegatorFactory;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericPK;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.entity.util.EntityUtil;
import org.apache.ofbiz.entity.util.EntityUtilProperties;
import org.apache.ofbiz.order.finaccount.FinAccountHelper;
import org.apache.ofbiz.order.order.OrderReadHelper;
import org.apache.ofbiz.order.shoppingcart.product.ProductPromoWorker;
import org.apache.ofbiz.order.shoppingcart.shipping.ShippingEstimateWrapper;
import org.apache.ofbiz.order.shoppinglist.ShoppingListEvents;
import org.apache.ofbiz.party.contact.ContactHelper;
import org.apache.ofbiz.party.contact.ContactMechWorker;
import org.apache.ofbiz.product.category.CategoryWorker;
import org.apache.ofbiz.product.config.ProductConfigWrapper;
import org.apache.ofbiz.product.product.ProductWorker;
import org.apache.ofbiz.product.store.ProductStoreWorker;
import org.apache.ofbiz.service.GenericServiceException;
import org.apache.ofbiz.service.LocalDispatcher;
import org.apache.ofbiz.service.ServiceUtil;
/**
* Shopping Cart Object
*/
@SuppressWarnings("serial")
public class ShoppingCart implements Iterable<ShoppingCartItem>, Serializable {
public static final String module = ShoppingCart.class.getName();
public static final String resource_error = "OrderErrorUiLabels";
// modes for getting OrderItemAttributes
public static final int ALL = 1;
public static final int EMPTY_ONLY = 2;
public static final int FILLED_ONLY = 3;
// scales and rounding modes for BigDecimal math
public static final int scale = UtilNumber.getBigDecimalScale("order.decimals");
public static final int rounding = UtilNumber.getBigDecimalRoundingMode("order.rounding");
public static final int taxCalcScale = UtilNumber.getBigDecimalScale("salestax.calc.decimals");
public static final int taxFinalScale = UtilNumber.getBigDecimalScale("salestax.final.decimals");
public static final int taxRounding = UtilNumber.getBigDecimalRoundingMode("salestax.rounding");
public static final BigDecimal ZERO = BigDecimal.ZERO;
public static final MathContext generalRounding = new MathContext(10);
private String orderType = "SALES_ORDER"; // default orderType
private String channel = "UNKNWN_SALES_CHANNEL"; // default channel enum
private String poNumber = null;
private String orderId = null;
private String orderName = null;
private String orderStatusId = null;
private String orderStatusString = null;
private String firstAttemptOrderId = null;
private String externalId = null;
private String internalCode = null;
private String billingAccountId = null;
private BigDecimal billingAccountAmt = BigDecimal.ZERO;
private String agreementId = null;
private String quoteId = null;
private String workEffortId = null;
private long nextItemSeq = 1;
private String defaultItemDeliveryDate = null;
private String defaultItemComment = null;
private String orderAdditionalEmails = null;
private boolean viewCartOnAdd = false;
private boolean readOnlyCart = false;
private Timestamp lastListRestore = null;
private String autoSaveListId = null;
/** Holds value of order adjustments. */
private List<GenericValue> adjustments = new LinkedList<GenericValue>();
// OrderTerms
private boolean orderTermSet = false;
private List<GenericValue> orderTerms = new LinkedList<GenericValue>();
private List<ShoppingCartItem> cartLines = new LinkedList<ShoppingCartItem>();
private Map<String, ShoppingCartItemGroup> itemGroupByNumberMap = new HashMap<String, ShoppingCartItemGroup>();
protected long nextGroupNumber = 1;
private List<CartPaymentInfo> paymentInfo = new LinkedList<ShoppingCart.CartPaymentInfo>();
private List<CartShipInfo> shipInfo = new LinkedList<ShoppingCart.CartShipInfo>();
private Map<String, String> contactMechIdsMap = new HashMap<String, String>();
private Map<String, String> orderAttributes = new HashMap<String, String>();
private Map<String, Object> attributes = new HashMap<String, Object>(); // user defined attributes
// Lists of internal/public notes: when the order is stored they are transformed into OrderHeaderNotes
private List<String> internalOrderNotes = new LinkedList<String>(); // internal notes
private List<String> orderNotes = new LinkedList<String>(); // public notes (printed on documents etc.)
/** contains a list of partyId for each roleTypeId (key) */
private Map<String, List<String>> additionalPartyRole = new HashMap<String, List<String>>();
/** these are defaults for all ship groups */
private Timestamp defaultShipAfterDate = null;
private Timestamp defaultShipBeforeDate = null;
/** Contains a List for each productPromoId (key) containing a productPromoCodeId (or empty string for no code) for each use of the productPromoId */
private List<ProductPromoUseInfo> productPromoUseInfoList = new LinkedList<ShoppingCart.ProductPromoUseInfo>();
/** Contains the promo codes entered */
private Set<String> productPromoCodes = new HashSet<String>();
private List<GenericValue> freeShippingProductPromoActions = new ArrayList<GenericValue>();
/** Note that even though this is promotion info, it should NOT be cleared when the promos are cleared, it is a preference that will be used in the next promo calculation */
private Map<GenericPK, String> desiredAlternateGiftByAction = new HashMap<GenericPK, String>();
private Timestamp cartCreatedTs = UtilDateTime.nowTimestamp();
private transient Delegator delegator = null;
private String delegatorName = null;
protected String productStoreId = null;
protected boolean doPromotions = true;
protected String transactionId = null;
protected String facilityId = null;
protected String webSiteId = null;
protected String terminalId = null;
protected String autoOrderShoppingListId = null;
/** General partyId for the Order, all other IDs default to this one if not specified explicitly */
protected String orderPartyId = null;
// sales order parties
protected String placingCustomerPartyId = null;
protected String billToCustomerPartyId = null;
protected String shipToCustomerPartyId = null;
protected String endUserCustomerPartyId = null;
// purchase order parties
protected String billFromVendorPartyId = null;
protected String shipFromVendorPartyId = null;
protected String supplierAgentPartyId = null;
protected GenericValue userLogin = null;
protected GenericValue autoUserLogin = null;
protected Locale locale; // holds the locale from the user session
protected String currencyUom = null;
protected boolean holdOrder = false;
protected Timestamp orderDate = null;
protected Timestamp cancelBackOrderDate = null;
/** don't allow empty constructor */
protected ShoppingCart() {}
/** Creates a new cloned ShoppingCart Object. */
public ShoppingCart(ShoppingCart cart) {
this.delegator = cart.getDelegator();
this.delegatorName = delegator.getDelegatorName();
this.productStoreId = cart.getProductStoreId();
this.doPromotions = cart.getDoPromotions();
this.poNumber = cart.getPoNumber();
this.orderId = cart.getOrderId();
this.orderName = "Copy of " + cart.getOrderName();
this.workEffortId = cart.getWorkEffortId();
this.firstAttemptOrderId = cart.getFirstAttemptOrderId();
this.billingAccountId = cart.getBillingAccountId();
this.agreementId = cart.getAgreementId();
this.quoteId = cart.getQuoteId();
this.orderAdditionalEmails = cart.getOrderAdditionalEmails();
this.adjustments.addAll(cart.getAdjustments());
this.contactMechIdsMap = new HashMap<String, String>(cart.getOrderContactMechIds());
this.freeShippingProductPromoActions = new ArrayList<GenericValue>(cart.getFreeShippingProductPromoActions());
this.desiredAlternateGiftByAction = cart.getAllDesiredAlternateGiftByActionCopy();
this.productPromoUseInfoList.addAll(cart.productPromoUseInfoList);
this.productPromoCodes = new HashSet<String>(cart.productPromoCodes);
this.locale = cart.getLocale();
this.currencyUom = cart.getCurrency();
this.externalId = cart.getExternalId();
this.internalCode = cart.getInternalCode();
this.viewCartOnAdd = cart.viewCartOnAdd();
this.defaultShipAfterDate = cart.getDefaultShipAfterDate();
this.defaultShipBeforeDate = cart.getDefaultShipBeforeDate();
this.cancelBackOrderDate = cart.getCancelBackOrderDate();
this.terminalId = cart.getTerminalId();
this.transactionId = cart.getTransactionId();
this.autoOrderShoppingListId = cart.getAutoOrderShoppingListId();
// clone the additionalPartyRoleMap
this.additionalPartyRole = new HashMap<String, List<String>>();
for (Map.Entry<String, List<String>> me : cart.additionalPartyRole.entrySet()) {
this.additionalPartyRole.put(me.getKey(), new LinkedList<String>(me.getValue()));
}
// clone the groups
for (ShoppingCartItemGroup itemGroup : cart.itemGroupByNumberMap.values()) {
// get the new parent group by number from the existing set; as before the parent must come before all children to work...
ShoppingCartItemGroup parentGroup = null;
if (itemGroup.getParentGroup() != null) parentGroup = this.getItemGroupByNumber(itemGroup.getParentGroup().getGroupNumber());
ShoppingCartItemGroup newGroup = new ShoppingCartItemGroup(itemGroup, parentGroup);
itemGroupByNumberMap.put(newGroup.getGroupNumber(), newGroup);
}
// clone the items
for (ShoppingCartItem item : cart.items()) {
cartLines.add(new ShoppingCartItem(item));
}
this.facilityId = cart.facilityId;
this.webSiteId = cart.webSiteId;
}
/** Creates new empty ShoppingCart object. */
public ShoppingCart(Delegator delegator, String productStoreId, String webSiteId, Locale locale, String currencyUom, String billToCustomerPartyId, String billFromVendorPartyId) {
this.delegator = delegator;
this.delegatorName = delegator.getDelegatorName();
this.productStoreId = productStoreId;
this.webSiteId = webSiteId;
this.locale = (locale != null) ? locale : Locale.getDefault();
this.currencyUom = (currencyUom != null) ? currencyUom : EntityUtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD", delegator);
this.billToCustomerPartyId = billToCustomerPartyId;
this.billFromVendorPartyId = billFromVendorPartyId;
if (productStoreId != null) {
// set the default view cart on add for this store
GenericValue productStore = ProductStoreWorker.getProductStore(productStoreId, delegator);
if (productStore == null) {
throw new IllegalArgumentException("Unable to locate ProductStore by ID [" + productStoreId + "]");
}
String storeViewCartOnAdd = productStore.getString("viewCartOnAdd");
if (storeViewCartOnAdd != null && "Y".equalsIgnoreCase(storeViewCartOnAdd)) {
this.viewCartOnAdd = true;
}
if (billFromVendorPartyId == null) {
// since default cart is of type SALES_ORDER, set to store's payToPartyId
this.billFromVendorPartyId = productStore.getString("payToPartyId");
}
this.facilityId = productStore.getString("inventoryFacilityId");
}
}
/** Creates new empty ShoppingCart object. */
public ShoppingCart(Delegator delegator, String productStoreId, String webSiteId, Locale locale, String currencyUom) {
this(delegator, productStoreId, webSiteId, locale, currencyUom, null, null);
}
/** Creates a new empty ShoppingCart object. */
public ShoppingCart(Delegator delegator, String productStoreId, Locale locale, String currencyUom) {
this(delegator, productStoreId, null, locale, currencyUom);
}
public Delegator getDelegator() {
if (delegator == null) {
delegator = DelegatorFactory.getDelegator(delegatorName);
}
return delegator;
}
public String getProductStoreId() {
return this.productStoreId;
}
public boolean getDoPromotions() {
return this.doPromotions;
}
public void setDoPromotions(boolean doPromotions) {
this.doPromotions = doPromotions;
}
/**
* This is somewhat of a dangerous method, changing the productStoreId changes a lot of stuff including:
* - some items in the cart may not be valid in any catalog in the new store
* - promotions need to be recalculated for the products that remain
* - what else? lots of settings on the ProductStore...
*
* So for now this can only be called if the cart is empty... otherwise it wil throw an exception
*
*/
public void setProductStoreId(String productStoreId) {
if ((productStoreId == null && this.productStoreId == null) || (productStoreId != null && productStoreId.equals(this.productStoreId))) {
return;
}
if (this.size() == 0) {
this.productStoreId = productStoreId;
} else {
throw new IllegalArgumentException("Cannot set productStoreId when the cart is not empty; cart size is " + this.size());
}
}
public String getTransactionId() {
return this.transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getTerminalId() {
return this.terminalId;
}
public void setTerminalId(String terminalId) {
this.terminalId = terminalId;
}
public String getAutoOrderShoppingListId() {
return this.autoOrderShoppingListId;
}
public void setAutoOrderShoppingListId(String autoOrderShoppingListId) {
this.autoOrderShoppingListId = autoOrderShoppingListId;
}
public String getFacilityId() {
return this.facilityId;
}
public void setFacilityId(String facilityId) {
this.facilityId = facilityId;
}
public Locale getLocale() {
return locale;
}
public void setLocale(Locale locale) {
this.locale = locale;
for (ShoppingCartItem cartItem : cartLines) {
cartItem.setLocale(locale);
}
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
public String getOrderName() {
return orderName;
}
public void setWorkEffortId(String workEffortId) {
this.workEffortId = workEffortId;
}
public String getWorkEffortId() {
return workEffortId;
}
public void setAttribute(String name, Object value) {
this.attributes.put(name, value);
}
public void removeAttribute(String name) {
this.attributes.remove(name);
}
@SuppressWarnings("unchecked")
public <T> T getAttribute(String name) {
return (T) this.attributes.get(name);
}
public void removeOrderAttribute(String name) {
this.orderAttributes.remove(name);
}
public void setOrderAttribute(String name, String value) {
this.orderAttributes.put(name, value);
}
public String getOrderAttribute(String name) {
return this.orderAttributes.get(name);
}
public void setHoldOrder(boolean b) {
this.holdOrder = b;
}
public boolean getHoldOrder() {
return this.holdOrder;
}
public void setOrderDate(Timestamp t) {
this.orderDate = t;
}
public Timestamp getOrderDate() {
return this.orderDate;
}
/** Sets the currency for the cart. */
public void setCurrency(LocalDispatcher dispatcher, String currencyUom) throws CartItemModifyException {
if (isReadOnlyCart()) {
throw new CartItemModifyException("Cart items cannot be changed");
}
String previousCurrency = this.currencyUom;
this.currencyUom = currencyUom;
if (!previousCurrency.equals(this.currencyUom)) {
for (ShoppingCartItem item : this) {
item.updatePrice(dispatcher, this);
}
}
}
/** Get the current currency setting. */
public String getCurrency() {
if (this.currencyUom != null) {
return this.currencyUom;
} else {
// uh oh, not good, should always be passed in on init, we can't really do anything without it, so throw an exception
throw new IllegalStateException("The Currency UOM is not set in the shopping cart, this is not a valid state, it should always be passed in when the cart is created.");
}
}
public Timestamp getCartCreatedTime() {
return this.cartCreatedTs;
}
public GenericValue getSupplierProduct(String productId, BigDecimal quantity, LocalDispatcher dispatcher) {
GenericValue supplierProduct = null;
Map<String, Object> params = UtilMisc.<String, Object>toMap("productId", productId,
"partyId", this.getPartyId(),
"currencyUomId", this.getCurrency(),
"quantity", quantity);
try {
Map<String, Object> result = dispatcher.runSync("getSuppliersForProduct", params);
List<GenericValue> productSuppliers = UtilGenerics.checkList(result.get("supplierProducts"));
if ((productSuppliers != null) && (productSuppliers.size() > 0)) {
supplierProduct = productSuppliers.get(0);
}
} catch (GenericServiceException e) {
Debug.logWarning(UtilProperties.getMessage(resource_error,"OrderRunServiceGetSuppliersForProductError", locale) + e.getMessage(), module);
} catch (Exception e) {
Debug.logWarning(UtilProperties.getMessage(resource_error,"OrderRunServiceGetSuppliersForProductError", locale) + e.getMessage(), module);
}
return supplierProduct;
}
// =======================================================================
// Methods for cart items
// =======================================================================
/** Add an item to the shopping cart, or if already there, increase the quantity.
* @return the new/increased item index
* @throws CartItemModifyException
*/
public int addOrIncreaseItem(String productId, BigDecimal selectedAmount, BigDecimal quantity, Timestamp reservStart, BigDecimal reservLength, BigDecimal reservPersons,
Timestamp shipBeforeDate, Timestamp shipAfterDate, Map<String, GenericValue> features, Map<String, Object> attributes, String prodCatalogId,
ProductConfigWrapper configWrapper, String itemType, String itemGroupNumber, String parentProductId, LocalDispatcher dispatcher) throws CartItemModifyException, ItemNotFoundException {
return addOrIncreaseItem(productId,selectedAmount,quantity,reservStart,reservLength,reservPersons, null,null,shipBeforeDate,shipAfterDate,features,attributes,prodCatalogId,
configWrapper,itemType,itemGroupNumber,parentProductId,dispatcher);
}
/** add rental (with accommodation) item to cart */
public int addOrIncreaseItem(String productId, BigDecimal selectedAmount, BigDecimal quantity, Timestamp reservStart, BigDecimal reservLength, BigDecimal reservPersons,
String accommodationMapId, String accommodationSpotId, Timestamp shipBeforeDate, Timestamp shipAfterDate, Map<String, GenericValue> features, Map<String, Object> attributes,
String prodCatalogId, ProductConfigWrapper configWrapper, String itemType, String itemGroupNumber, String parentProductId, LocalDispatcher dispatcher) throws CartItemModifyException, ItemNotFoundException {
return addOrIncreaseItem(productId, selectedAmount, quantity, reservStart, reservLength, reservPersons, accommodationMapId, accommodationSpotId, shipBeforeDate, shipAfterDate, features, attributes, null, prodCatalogId, configWrapper, itemType, itemGroupNumber, parentProductId, dispatcher);
}
/** add rental (with accommodation) item to cart and order item attributes*/
// TODO change method signature, this one is really scary, above are not bad too :/ !
public int addOrIncreaseItem(String productId, BigDecimal selectedAmount, BigDecimal quantity, Timestamp reservStart, BigDecimal reservLength, BigDecimal reservPersons,
String accommodationMapId, String accommodationSpotId, Timestamp shipBeforeDate, Timestamp shipAfterDate, Map<String, GenericValue> features, Map<String,
Object> attributes, Map<String, String> orderItemAttributes, String prodCatalogId, ProductConfigWrapper configWrapper, String itemType, String itemGroupNumber,
String parentProductId, LocalDispatcher dispatcher) throws CartItemModifyException, ItemNotFoundException {
if (isReadOnlyCart()) {
throw new CartItemModifyException("Cart items cannot be changed");
}
selectedAmount = selectedAmount == null ? BigDecimal.ZERO : selectedAmount;
reservLength = reservLength == null ? BigDecimal.ZERO : reservLength;
reservPersons = reservPersons == null ? BigDecimal.ZERO : reservPersons;
ShoppingCart.ShoppingCartItemGroup itemGroup = this.getItemGroupByNumber(itemGroupNumber);
GenericValue supplierProduct = null;
// Check for existing cart item.
for (int i = 0; i < this.cartLines.size(); i++) {
ShoppingCartItem sci = cartLines.get(i);
if (sci.equals(productId, reservStart, reservLength, reservPersons, accommodationMapId, accommodationSpotId, features, attributes, orderItemAttributes, prodCatalogId,selectedAmount, configWrapper, itemType, itemGroup, false)) {
BigDecimal newQuantity = sci.getQuantity().add(quantity);
try {
BigDecimal minQuantity = getMinimumOrderQuantity(getDelegator(),sci.getBasePrice(), productId);
if(newQuantity.compareTo(minQuantity) < 0) {
newQuantity = minQuantity;
}
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
if (sci.getItemType().equals("RENTAL_ORDER_ITEM")) {
// check to see if the related fixed asset is available for the new quantity
String isAvailable = ShoppingCartItem.checkAvailability(productId, newQuantity, reservStart, reservLength, this);
if (isAvailable.compareTo("OK") != 0) {
Map<String, Object> messageMap = UtilMisc.<String, Object>toMap("productId", productId, "availableMessage", isAvailable);
String excMsg = UtilProperties.getMessage(ShoppingCartItem.resource, "item.product_not_available", messageMap, this.getLocale());
Debug.logInfo(excMsg, module);
throw new CartItemModifyException(isAvailable);
}
}
if (Debug.verboseOn()) Debug.logVerbose("Found a match for id " + productId + " on line " + i + ", updating quantity to " + newQuantity, module);
sci.setQuantity(newQuantity, dispatcher, this);
if (getOrderType().equals("PURCHASE_ORDER")) {
supplierProduct = getSupplierProduct(productId, newQuantity, dispatcher);
if (supplierProduct != null && supplierProduct.getBigDecimal("lastPrice") != null) {
sci.setSupplierProductId(supplierProduct.getString("supplierProductId"));
sci.setBasePrice(supplierProduct.getBigDecimal("lastPrice"));
sci.setName(ShoppingCartItem.getPurchaseOrderItemDescription(sci.getProduct(), supplierProduct, this.getLocale(), dispatcher));
} else {
throw new CartItemModifyException("SupplierProduct not found");
}
}
return i;
}
}
// Add the new item to the shopping cart if it wasn't found.
ShoppingCartItem item = null;
if (getOrderType().equals("PURCHASE_ORDER")) {
supplierProduct = getSupplierProduct(productId, quantity, dispatcher);
if (supplierProduct != null || "_NA_".equals(this.getPartyId())) {
item = ShoppingCartItem.makePurchaseOrderItem(Integer.valueOf(0), productId, selectedAmount, quantity, features, attributes, prodCatalogId, configWrapper, itemType, itemGroup, dispatcher, this, supplierProduct, shipBeforeDate, shipAfterDate, cancelBackOrderDate);
} else {
throw new CartItemModifyException("SupplierProduct not found");
}
} else {
try {
BigDecimal minQuantity = getMinimumOrderQuantity(getDelegator(),null, productId);
if(quantity.compareTo(minQuantity) < 0) {
quantity = minQuantity;
}
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
item = ShoppingCartItem.makeItem(Integer.valueOf(0), productId, selectedAmount, quantity, null,
reservStart, reservLength, reservPersons, accommodationMapId, accommodationSpotId, shipBeforeDate, shipAfterDate,
features, attributes, prodCatalogId, configWrapper, itemType, itemGroup, dispatcher,
this, Boolean.TRUE, Boolean.TRUE, parentProductId, Boolean.FALSE, Boolean.FALSE);
}
// add order item attributes
if (UtilValidate.isNotEmpty(orderItemAttributes)) {
for (Entry<String, String> entry : orderItemAttributes.entrySet()) {
item.setOrderItemAttribute(entry.getKey(), entry.getValue());
}
}
return this.addItem(0, item);
}
/** Add a non-product item to the shopping cart.
* @return the new item index
* @throws CartItemModifyException
*/
public int addNonProductItem(String itemType, String description, String categoryId, BigDecimal price, BigDecimal quantity,
Map<String, Object> attributes, String prodCatalogId, String itemGroupNumber, LocalDispatcher dispatcher) throws CartItemModifyException {
ShoppingCart.ShoppingCartItemGroup itemGroup = this.getItemGroupByNumber(itemGroupNumber);
return this.addItem(0, ShoppingCartItem.makeItem(Integer.valueOf(0), itemType, description, categoryId, price, null, quantity, attributes, prodCatalogId, itemGroup, dispatcher, this, Boolean.TRUE));
}
/** Add an item to the shopping cart. */
public int addItem(int index, ShoppingCartItem item) throws CartItemModifyException {
if (isReadOnlyCart()) {
throw new CartItemModifyException("Cart items cannot be changed");
}
if (!cartLines.contains(item)) {
// If the billing address is already set, verify if the new product
// is available in the address' geo
GenericValue product = item.getProduct();
if (product != null && isSalesOrder()) {
GenericValue billingAddress = this.getBillingAddress();
if (billingAddress != null) {
if (!ProductWorker.isBillableToAddress(product, billingAddress)) {
throw new CartItemModifyException("The billing address is not compatible with ProductGeos rules of this product.");
}
}
}
cartLines.add(index, item);
return index;
} else {
return this.getItemIndex(item);
}
}
/** Add an item to the shopping cart. */
public int addItemToEnd(String productId, BigDecimal amount, BigDecimal quantity, BigDecimal unitPrice, HashMap<String, GenericValue> features, HashMap<String, Object> attributes, String prodCatalogId, String itemType, ProductConfigWrapper configWrapper, LocalDispatcher dispatcher, Boolean triggerExternalOps, Boolean triggerPriceRules) throws CartItemModifyException, ItemNotFoundException {
return addItemToEnd(ShoppingCartItem.makeItem(null, productId, amount, quantity, unitPrice, null, null, null, null, null, features, attributes, prodCatalogId, configWrapper, itemType, null, dispatcher, this, triggerExternalOps, triggerPriceRules, null, Boolean.FALSE, Boolean.FALSE));
}
/** Add an item to the shopping cart. */
public int addItemToEnd(String productId, BigDecimal amount, BigDecimal quantity, BigDecimal unitPrice, HashMap<String, GenericValue> features, HashMap<String, Object> attributes, String prodCatalogId, String itemType, LocalDispatcher dispatcher, Boolean triggerExternalOps, Boolean triggerPriceRules) throws CartItemModifyException, ItemNotFoundException {
return addItemToEnd(productId, amount, quantity, unitPrice, features, attributes, prodCatalogId, itemType, dispatcher, triggerExternalOps, triggerPriceRules, Boolean.FALSE, Boolean.FALSE);
}
/** Add an (rental)item to the shopping cart. */
public int addItemToEnd(String productId, BigDecimal amount, BigDecimal quantity, BigDecimal unitPrice, Timestamp reservStart, BigDecimal reservLength, BigDecimal reservPersons, HashMap<String, GenericValue> features, HashMap<String, Object> attributes, String prodCatalogId, String itemType, LocalDispatcher dispatcher, Boolean triggerExternalOps, Boolean triggerPriceRules) throws CartItemModifyException, ItemNotFoundException {
return addItemToEnd(ShoppingCartItem.makeItem(null, productId, amount, quantity, unitPrice, reservStart, reservLength, reservPersons, null, null, features, attributes, prodCatalogId, null, itemType, null, dispatcher, this, triggerExternalOps, triggerPriceRules, null, Boolean.FALSE, Boolean.FALSE));
}
/** Add an (rental)item to the shopping cart. */
public int addItemToEnd(String productId, BigDecimal amount, BigDecimal quantity, BigDecimal unitPrice, Timestamp reservStart, BigDecimal reservLength, BigDecimal reservPersons, HashMap<String, GenericValue> features, HashMap<String, Object> attributes, String prodCatalogId, String itemType, LocalDispatcher dispatcher, Boolean triggerExternalOps, Boolean triggerPriceRules, Boolean skipInventoryChecks, Boolean skipProductChecks) throws CartItemModifyException, ItemNotFoundException {
return addItemToEnd(ShoppingCartItem.makeItem(null, productId, amount, quantity, unitPrice, reservStart, reservLength, reservPersons, null, null, features, attributes, prodCatalogId, null, itemType, null, dispatcher, this, triggerExternalOps, triggerPriceRules, null, skipInventoryChecks, skipProductChecks));
}
/** Add an (rental/aggregated)item to the shopping cart. */
public int addItemToEnd(String productId, BigDecimal amount, BigDecimal quantity, BigDecimal unitPrice, Timestamp reservStart, BigDecimal reservLength, BigDecimal reservPersons, HashMap<String, GenericValue> features, HashMap<String, Object> attributes, String prodCatalogId, ProductConfigWrapper configWrapper, String itemType, LocalDispatcher dispatcher, Boolean triggerExternalOps, Boolean triggerPriceRules, Boolean skipInventoryChecks, Boolean skipProductChecks) throws CartItemModifyException, ItemNotFoundException {
return addItemToEnd(ShoppingCartItem.makeItem(null, productId, amount, quantity, unitPrice, reservStart, reservLength, reservPersons, null, null, features, attributes, prodCatalogId, configWrapper, itemType, null, dispatcher, this, triggerExternalOps, triggerPriceRules, null, skipInventoryChecks, skipProductChecks));
}
/** Add an accommodation(rental)item to the shopping cart. */
public int addItemToEnd(String productId, BigDecimal amount, BigDecimal quantity, BigDecimal unitPrice, Timestamp reservStart, BigDecimal reservLength, BigDecimal reservPersons, String accommodationMapId, String accommodationSpotId, HashMap<String, GenericValue> features, HashMap<String, Object> attributes, String prodCatalogId, String itemType, LocalDispatcher dispatcher, Boolean triggerExternalOps, Boolean triggerPriceRules) throws CartItemModifyException, ItemNotFoundException {
return addItemToEnd(ShoppingCartItem.makeItem(null, productId, amount, quantity, unitPrice, reservStart, reservLength, reservPersons, accommodationMapId, accommodationSpotId, null, null, features, attributes, prodCatalogId, null, itemType, null, dispatcher, this, triggerExternalOps, triggerPriceRules, null, Boolean.FALSE, Boolean.FALSE));
}
/** Add an accommodation(rental)item to the shopping cart. */
public int addItemToEnd(String productId, BigDecimal amount, BigDecimal quantity, BigDecimal unitPrice, Timestamp reservStart, BigDecimal reservLength, BigDecimal reservPersons, String accommodationMapId, String accommodationSpotId, HashMap<String, GenericValue> features, HashMap<String, Object> attributes, String prodCatalogId, String itemType, LocalDispatcher dispatcher, Boolean triggerExternalOps, Boolean triggerPriceRules, Boolean skipInventoryChecks, Boolean skipProductChecks) throws CartItemModifyException, ItemNotFoundException {
return addItemToEnd(ShoppingCartItem.makeItem(null, productId, amount, quantity, unitPrice, reservStart, reservLength, reservPersons, accommodationMapId, accommodationSpotId, null, null, features, attributes, prodCatalogId, null, itemType, null, dispatcher, this, triggerExternalOps, triggerPriceRules, null, skipInventoryChecks, skipProductChecks));
}
/** Add an accommodation(rental/aggregated)item to the shopping cart. */
public int addItemToEnd(String productId, BigDecimal amount, BigDecimal quantity, BigDecimal unitPrice, Timestamp reservStart, BigDecimal reservLength, BigDecimal reservPersonsDbl,String accommodationMapId, String accommodationSpotId, HashMap<String, GenericValue> features, HashMap<String, Object> attributes, String prodCatalogId, ProductConfigWrapper configWrapper, String itemType, LocalDispatcher dispatcher, Boolean triggerExternalOps, Boolean triggerPriceRules, Boolean skipInventoryChecks, Boolean skipProductChecks) throws CartItemModifyException, ItemNotFoundException {
return addItemToEnd(ShoppingCartItem.makeItem(null, productId, amount, quantity, unitPrice, reservStart, reservLength, reservPersonsDbl, accommodationMapId, accommodationSpotId, null, null, features, attributes, prodCatalogId, configWrapper, itemType, null, dispatcher, this, triggerExternalOps, triggerPriceRules, null, skipInventoryChecks, skipProductChecks));
}
/** Add an item to the shopping cart. */
public int addItemToEnd(String productId, BigDecimal amount, BigDecimal quantity, BigDecimal unitPrice, HashMap<String, GenericValue> features, HashMap<String, Object> attributes, String prodCatalogId, String itemType, LocalDispatcher dispatcher, Boolean triggerExternalOps, Boolean triggerPriceRules, Boolean skipInventoryChecks, Boolean skipProductChecks) throws CartItemModifyException, ItemNotFoundException {
return addItemToEnd(ShoppingCartItem.makeItem(null, productId, amount, quantity, unitPrice, null, null, null, null, null, features, attributes, prodCatalogId, null, itemType, null, dispatcher, this, triggerExternalOps, triggerPriceRules, null, skipInventoryChecks, skipProductChecks));
}
/** Add an item to the shopping cart. */
public int addItemToEnd(ShoppingCartItem item) throws CartItemModifyException {
return addItem(cartLines.size(), item);
}
/** Get a ShoppingCartItem from the cart object. */
public ShoppingCartItem findCartItem(String productId, Map<String, GenericValue> features, Map<String, Object> attributes, String prodCatalogId, BigDecimal selectedAmount) {
// Check for existing cart item.
for (int i = 0; i < this.cartLines.size(); i++) {
ShoppingCartItem cartItem = cartLines.get(i);
if (cartItem.equals(productId, features, attributes, prodCatalogId, selectedAmount)) {
return cartItem;
}
}
return null;
}
/** Get all ShoppingCartItems from the cart object with the given productId. */
public List<ShoppingCartItem> findAllCartItems(String productId) {
return this.findAllCartItems(productId, null);
}
/** Get all ShoppingCartItems from the cart object with the given productId and optional groupNumber to limit it to a specific item group */
public List<ShoppingCartItem> findAllCartItems(String productId, String groupNumber) {
if (productId == null) return this.items();
List<ShoppingCartItem> itemsToReturn = new LinkedList<ShoppingCartItem>();
// Check for existing cart item.
for (ShoppingCartItem cartItem : cartLines) {
if (UtilValidate.isNotEmpty(groupNumber) && !cartItem.isInItemGroup(groupNumber)) {
continue;
}
if (productId.equals(cartItem.getProductId())) {
itemsToReturn.add(cartItem);
}
}
return itemsToReturn;
}
/** Get all ShoppingCartItems from the cart object with the given productCategoryId and optional groupNumber to limit it to a specific item group */
public List<ShoppingCartItem> findAllCartItemsInCategory(String productCategoryId, String groupNumber) {
if (productCategoryId == null) return this.items();
Delegator delegator = this.getDelegator();
List<ShoppingCartItem> itemsToReturn = new LinkedList<ShoppingCartItem>();
try {
// Check for existing cart item
for (ShoppingCartItem cartItem : cartLines) {
if (UtilValidate.isNotEmpty(groupNumber) && !cartItem.isInItemGroup(groupNumber)) {
continue;
}
if (CategoryWorker.isProductInCategory(delegator, cartItem.getProductId(), productCategoryId)) {
itemsToReturn.add(cartItem);
} else {
}
}
} catch (GenericEntityException e) {
Debug.logError(e, "Error getting cart items that are in a category: " + e.toString(), module);
}
return itemsToReturn;
}
/** Remove quantity 0 ShoppingCartItems from the cart object. */
public void removeEmptyCartItems() {
// Check for existing cart item.
for (int i = 0; i < this.cartLines.size();) {
ShoppingCartItem cartItem = cartLines.get(i);
if (cartItem.getQuantity().compareTo(BigDecimal.ZERO) == 0) {
this.clearItemShipInfo(cartItem);
cartLines.remove(i);
} else {
i++;
}
}
}
// =============== some misc utility methods, mostly for dealing with lists of items =================
public void removeExtraItems(List<ShoppingCartItem> multipleItems, LocalDispatcher dispatcher, int maxItems) throws CartItemModifyException {
// if 1 or 0 items, do nothing
if (multipleItems.size() <= maxItems) return;
// remove all except first <maxItems> in list from the cart, first because new cart items are added to the beginning...
List<ShoppingCartItem> localList = new LinkedList<ShoppingCartItem>();
localList.addAll(multipleItems);
// the ones to keep...
for (int i=0; i<maxItems; i++) localList.remove(0);
for (ShoppingCartItem item : localList) {
this.removeCartItem(item, dispatcher);
}
}
public static BigDecimal getItemsTotalQuantity(List<ShoppingCartItem> cartItems) {
BigDecimal totalQuantity = BigDecimal.ZERO;
for (ShoppingCartItem item : cartItems) {
totalQuantity = totalQuantity.add(item.getQuantity());
}
return totalQuantity;
}
public static List<GenericValue> getItemsProducts(List<ShoppingCartItem> cartItems) {
List<GenericValue> productList = new LinkedList<GenericValue>();
for (ShoppingCartItem item : cartItems) {
GenericValue product = item.getProduct();
if (product != null) {
productList.add(product);
}
}
return productList;
}
public void ensureItemsQuantity(List<ShoppingCartItem> cartItems, LocalDispatcher dispatcher, BigDecimal quantity) throws CartItemModifyException {
for (ShoppingCartItem item : cartItems) {
if (item.getQuantity() != quantity) {
item.setQuantity(quantity, dispatcher, this);
}
}
}
public BigDecimal ensureItemsTotalQuantity(List<ShoppingCartItem> cartItems, LocalDispatcher dispatcher, BigDecimal quantity) throws CartItemModifyException {
BigDecimal quantityRemoved = BigDecimal.ZERO;
// go through the items and reduce quantityToKeep by the item quantities until it is 0, then remove the remaining...
BigDecimal quantityToKeep = quantity;
for (ShoppingCartItem item : cartItems) {
if (quantityToKeep.compareTo(item.getQuantity()) >= 0) {
// quantityToKeep sufficient to keep it all... just reduce quantityToKeep and move on
quantityToKeep = quantityToKeep.subtract(item.getQuantity());
} else {
// there is more in this than we want to keep, so reduce the quantity, or remove altogether...
if (quantityToKeep.compareTo(BigDecimal.ZERO) == 0) {
// nothing left to keep, just remove it...
quantityRemoved = quantityRemoved.add(item.getQuantity());
this.removeCartItem(item, dispatcher);
} else {
// there is some to keep, so reduce quantity to quantityToKeep, at this point we know we'll take up all of the rest of the quantityToKeep
quantityRemoved = quantityRemoved.add(item.getQuantity().subtract(quantityToKeep));
item.setQuantity(quantityToKeep, dispatcher, this);
quantityToKeep = BigDecimal.ZERO;
}
}
}
return quantityRemoved;
}
// ============== WorkEffort related methods ===============
public boolean containAnyWorkEffortCartItems() {
// Check for existing cart item.
for (ShoppingCartItem cartItem : this.cartLines) {
if (cartItem.getItemType().equals("RENTAL_ORDER_ITEM")) { // create workeffort items?
return true;
}
}
return false;
}
public boolean containAllWorkEffortCartItems() {
// Check for existing cart item.
for (ShoppingCartItem cartItem : this.cartLines) {
if (!cartItem.getItemType().equals("RENTAL_ORDER_ITEM")) { // not a item to create workefforts?
return false;
}
}
return true;
}
/**
* Check to see if the cart contains only Digital Goods, ie no Finished Goods and no Finished/Digital Goods, et cetera.
* This is determined by making sure no Product has a type where ProductType.isPhysical!=N.
*/
public boolean containOnlyDigitalGoods() {
for (ShoppingCartItem cartItem : this.cartLines) {
GenericValue product = cartItem.getProduct();
try {
GenericValue productType = product.getRelatedOne("ProductType", true);
if (productType == null || !"N".equals(productType.getString("isPhysical"))) {
return false;
}
} catch (GenericEntityException e) {
Debug.logError(e, "Error looking up ProductType: " + e.toString(), module);
// consider this not a digital good if we don't have "proof"
return false;
}
}
return true;
}
/**
* Check to see if the ship group contains only Digital Goods, ie no Finished Goods and no Finished/Digital Goods, et cetera.
* This is determined by making sure no Product has a type where ProductType.isPhysical!=N.
*/
public boolean containOnlyDigitalGoods(int shipGroupIdx) {
CartShipInfo shipInfo = getShipInfo(shipGroupIdx);
for (ShoppingCartItem cartItem: shipInfo.getShipItems()) {
GenericValue product = cartItem.getProduct();
try {
GenericValue productType = product.getRelatedOne("ProductType", true);
if (productType == null || !"N".equals(productType.getString("isPhysical"))) {
return false;
}
} catch (GenericEntityException e) {
Debug.logError(e, "Error looking up ProductType: " + e.toString(), module);
// consider this not a digital good if we don't have "proof"
return false;
}
}
return true;
}
/** Returns this item's index. */
public int getItemIndex(ShoppingCartItem item) {
return cartLines.indexOf(item);
}
/** Get a ShoppingCartItem from the cart object. */
public ShoppingCartItem findCartItem(int index) {
if (cartLines.size() <= index) {
return null;
}
return cartLines.get(index);
}
public ShoppingCartItem findCartItem(String orderItemSeqId) {
if (orderItemSeqId != null) {
for (int i = 0; i < this.cartLines.size(); i++) {
ShoppingCartItem cartItem = cartLines.get(i);
String itemSeqId = cartItem.getOrderItemSeqId();
if (itemSeqId != null && orderItemSeqId.equals(itemSeqId)) {
return cartItem;
}
}
}
return null;
}
public void removeCartItem(ShoppingCartItem item, LocalDispatcher dispatcher) throws CartItemModifyException {
if (item == null) return;
this.removeCartItem(this.getItemIndex(item), dispatcher);
}
/** Remove an item from the cart object. */
public void removeCartItem(int index, LocalDispatcher dispatcher) throws CartItemModifyException {
if (isReadOnlyCart()) {
throw new CartItemModifyException("Cart items cannot be changed");
}
if (index < 0) return;
if (cartLines.size() <= index) return;
ShoppingCartItem item = cartLines.remove(index);
// set quantity to 0 to trigger necessary events, but skip price calc and inventory checks
item.setQuantity(BigDecimal.ZERO, dispatcher, this, true, true, false, true);
}
/** Moves a line item to a different index. */
public void moveCartItem(int fromIndex, int toIndex) {
if (toIndex < fromIndex) {
cartLines.add(toIndex, cartLines.remove(fromIndex));
} else if (toIndex > fromIndex) {
cartLines.add(toIndex - 1, cartLines.remove(fromIndex));
}
}
/** Returns the number of items in the cart object. */
public int size() {
return cartLines.size();
}
/** Returns a Collection of items in the cart object. */
public List<ShoppingCartItem> items() {
List<ShoppingCartItem> result = new LinkedList<ShoppingCartItem>();
result.addAll(cartLines);
return result;
}
/** Returns an iterator of cart items. */
@Override
public Iterator<ShoppingCartItem> iterator() {
return cartLines.iterator();
}
public ShoppingCart.ShoppingCartItemGroup getItemGroupByNumber(String groupNumber) {
if (UtilValidate.isEmpty(groupNumber)) return null;
return this.itemGroupByNumberMap.get(groupNumber);
}
/** Creates a new Item Group and returns the groupNumber that represents it */
public String addItemGroup(String groupName, String parentGroupNumber) {
ShoppingCart.ShoppingCartItemGroup parentGroup = this.getItemGroupByNumber(parentGroupNumber);
ShoppingCart.ShoppingCartItemGroup newGroup = new ShoppingCart.ShoppingCartItemGroup(this.nextGroupNumber, groupName, parentGroup);
this.nextGroupNumber++;
this.itemGroupByNumberMap.put(newGroup.getGroupNumber(), newGroup);
return newGroup.getGroupNumber();
}
public ShoppingCartItemGroup addItemGroup(GenericValue itemGroupValue) throws GenericEntityException {
if (itemGroupValue == null) {
return null;
}
String itemGroupNumber = itemGroupValue.getString("orderItemGroupSeqId");
ShoppingCartItemGroup itemGroup = this.getItemGroupByNumber(itemGroupNumber);
if (itemGroup == null) {
ShoppingCartItemGroup parentGroup = addItemGroup(itemGroupValue.getRelatedOne("ParentOrderItemGroup", true));
itemGroup = new ShoppingCartItemGroup(itemGroupNumber, itemGroupValue.getString("groupName"), parentGroup);
int parsedGroupNumber = Integer.parseInt(itemGroupNumber);
if (parsedGroupNumber > this.nextGroupNumber) {
this.nextGroupNumber = parsedGroupNumber + 1;
}
this.itemGroupByNumberMap.put(itemGroupNumber, itemGroup);
}
return itemGroup;
}
public List<ShoppingCartItem> getCartItemsInNoGroup() {
List<ShoppingCartItem> cartItemList = new LinkedList<ShoppingCartItem>();
for (ShoppingCartItem cartItem : cartLines) {
if (cartItem.getItemGroup() == null) {
cartItemList.add(cartItem);
}
}
return cartItemList;
}
public List<ShoppingCartItem> getCartItemsInGroup(String groupNumber) {
List<ShoppingCartItem> cartItemList = new LinkedList<ShoppingCartItem>();
ShoppingCart.ShoppingCartItemGroup itemGroup = this.getItemGroupByNumber(groupNumber);
if (itemGroup != null) {
for (ShoppingCartItem cartItem : cartLines) {
if (itemGroup.equals(cartItem.getItemGroup())) {
cartItemList.add(cartItem);
}
}
}
return cartItemList;
}
public void deleteItemGroup(String groupNumber) {
ShoppingCartItemGroup itemGroup = this.getItemGroupByNumber(groupNumber);
if (itemGroup != null) {
// go through all cart items and remove from group if they are in it
List<ShoppingCartItem> cartItemList = this.getCartItemsInGroup(groupNumber);
for (ShoppingCartItem cartItem : cartItemList) {
cartItem.setItemGroup(null);
}
// if this is a parent of any set them to this group's parent (or null)
for (ShoppingCartItemGroup otherItemGroup : this.itemGroupByNumberMap.values()) {
if (itemGroup.equals(otherItemGroup.getParentGroup())) {
otherItemGroup.inheritParentsParent();
}
}
// finally, remove the itemGroup...
this.itemGroupByNumberMap.remove(groupNumber);
}
}
//=======================================================
// Other General Info Maintenance Methods
//=======================================================
/** Gets the userLogin associated with the cart; may be null */
public GenericValue getUserLogin() {
return this.userLogin;
}
public void setUserLogin(GenericValue userLogin, LocalDispatcher dispatcher) throws CartItemModifyException {
this.userLogin = userLogin;
this.handleNewUser(dispatcher);
}
protected void setUserLogin(GenericValue userLogin) {
if (this.userLogin == null) {
this.userLogin = userLogin;
} else {
throw new IllegalArgumentException("Cannot change UserLogin object with this method");
}
}
public GenericValue getAutoUserLogin() {
return this.autoUserLogin;
}
public void setAutoUserLogin(GenericValue autoUserLogin, LocalDispatcher dispatcher) throws CartItemModifyException {
this.autoUserLogin = autoUserLogin;
if (getUserLogin() == null) {
this.handleNewUser(dispatcher);
}
}
protected void setAutoUserLogin(GenericValue autoUserLogin) {
if (this.autoUserLogin == null) {
this.autoUserLogin = autoUserLogin;
} else {
throw new IllegalArgumentException("Cannot change AutoUserLogin object with this method");
}
}
public void handleNewUser(LocalDispatcher dispatcher) throws CartItemModifyException {
String partyId = this.getPartyId();
if (UtilValidate.isNotEmpty(partyId)) {
// recalculate all prices
for (ShoppingCartItem cartItem : this) {
cartItem.updatePrice(dispatcher, this);
}
// check all promo codes, remove on failed check
Iterator<String> promoCodeIter = this.productPromoCodes.iterator();
while (promoCodeIter.hasNext()) {
String promoCode = promoCodeIter.next();
String checkResult = ProductPromoWorker.checkCanUsePromoCode(promoCode, partyId, this.getDelegator(), locale);
if (checkResult != null) {
promoCodeIter.remove();
Debug.logWarning(UtilProperties.getMessage(resource_error,"OrderOnUserChangePromoCodeWasRemovedBecause", UtilMisc.toMap("checkResult",checkResult), locale), module);
}
}
// rerun promotions
ProductPromoWorker.doPromotions(this, dispatcher);
}
}
public String getExternalId() {
return this.externalId;
}
public void setExternalId(String externalId) {
this.externalId = externalId;
}
public String getInternalCode() {
return this.internalCode;
}
public void setInternalCode(String internalCode) {
this.internalCode = internalCode;
}
public String getWebSiteId() {
return this.webSiteId;
}
public void setWebSiteId(String webSiteId) {
this.webSiteId = webSiteId;
}
/**
* Set ship before date for a particular ship group
* @param idx
* @param shipBeforeDate
*/
public void setShipBeforeDate(int idx, Timestamp shipBeforeDate) {
CartShipInfo csi = this.getShipInfo(idx);
csi.shipBeforeDate = shipBeforeDate;
}
/**
* Set ship before date for ship group 0
* @param shipBeforeDate
*/
public void setShipBeforeDate(Timestamp shipBeforeDate) {
this.setShipBeforeDate(0, shipBeforeDate);
}
/**
* Get ship before date for a particular ship group
* @param idx the ship group number
* @return ship before date for a given ship group
*/
public Timestamp getShipBeforeDate(int idx) {
CartShipInfo csi = this.getShipInfo(idx);
return csi.shipBeforeDate;
}
/**
* Get ship before date for ship group 0
* @return ship before date for the first ship group
*/
public Timestamp getShipBeforeDate() {
return this.getShipBeforeDate(0);
}
/**
* Set ship after date for a particular ship group
* @param idx the ship group number
* @param shipAfterDate the ship after date to be set for the given ship group
*/
public void setShipAfterDate(int idx, Timestamp shipAfterDate) {
CartShipInfo csi = this.getShipInfo(idx);
csi.shipAfterDate = shipAfterDate;
}
/**
* Set ship after date for a particular ship group
* @param shipAfterDate the ship after date to be set for the first ship group
*/
public void setShipAfterDate(Timestamp shipAfterDate) {
this.setShipAfterDate(0, shipAfterDate);
}
/**
* Get ship after date for a particular ship group
* @param idx the ship group number
* @return return the ship after date for the given ship group
*/
public Timestamp getShipAfterDate(int idx) {
CartShipInfo csi = this.getShipInfo(idx);
return csi.shipAfterDate;
}
/**
* Get ship after date for ship group 0
* @return return the ship after date for the first ship group
*/
public Timestamp getShipAfterDate() {
return this.getShipAfterDate(0);
}
public void setDefaultShipBeforeDate(Timestamp defaultShipBeforeDate) {
this.defaultShipBeforeDate = defaultShipBeforeDate;
}
public Timestamp getDefaultShipBeforeDate() {
return this.defaultShipBeforeDate;
}
public void setDefaultShipAfterDate(Timestamp defaultShipAfterDate) {
this.defaultShipAfterDate = defaultShipAfterDate;
}
public void setCancelBackOrderDate(Timestamp cancelBackOrderDate) {
this.cancelBackOrderDate = cancelBackOrderDate;
}
public Timestamp getCancelBackOrderDate() {
return this.cancelBackOrderDate;
}
public Timestamp getDefaultShipAfterDate() {
return this.defaultShipAfterDate;
}
public String getOrderPartyId() {
return this.orderPartyId != null ? this.orderPartyId : this.getPartyId();
}
public void setOrderPartyId(String orderPartyId) {
this.orderPartyId = orderPartyId;
}
public String getPlacingCustomerPartyId() {
return this.placingCustomerPartyId != null ? this.placingCustomerPartyId : this.getPartyId();
}
public void setPlacingCustomerPartyId(String placingCustomerPartyId) {
this.placingCustomerPartyId = placingCustomerPartyId;
if (UtilValidate.isEmpty(this.orderPartyId)) this.orderPartyId = placingCustomerPartyId;
}
public String getBillToCustomerPartyId() {
return this.billToCustomerPartyId != null ? this.billToCustomerPartyId : this.getPartyId();
}
public void setBillToCustomerPartyId(String billToCustomerPartyId) {
this.billToCustomerPartyId = billToCustomerPartyId;
if ((UtilValidate.isEmpty(this.orderPartyId)) && !(orderType.equals("PURCHASE_ORDER"))) {
this.orderPartyId = billToCustomerPartyId; // orderPartyId should be bill-to-customer when it is not a purchase order
}
}
public String getShipToCustomerPartyId() {
return this.shipToCustomerPartyId != null ? this.shipToCustomerPartyId : this.getPartyId();
}
public void setShipToCustomerPartyId(String shipToCustomerPartyId) {
this.shipToCustomerPartyId = shipToCustomerPartyId;
if (UtilValidate.isEmpty(this.orderPartyId)) this.orderPartyId = shipToCustomerPartyId;
}
public String getEndUserCustomerPartyId() {
return this.endUserCustomerPartyId != null ? this.endUserCustomerPartyId : this.getPartyId();
}
public void setEndUserCustomerPartyId(String endUserCustomerPartyId) {
this.endUserCustomerPartyId = endUserCustomerPartyId;
if (UtilValidate.isEmpty(this.orderPartyId)) this.orderPartyId = endUserCustomerPartyId;
}
public String getBillFromVendorPartyId() {
return this.billFromVendorPartyId != null ? this.billFromVendorPartyId : this.getPartyId();
}
public void setBillFromVendorPartyId(String billFromVendorPartyId) {
this.billFromVendorPartyId = billFromVendorPartyId;
if ((UtilValidate.isEmpty(this.orderPartyId)) && (orderType.equals("PURCHASE_ORDER"))) {
this.orderPartyId = billFromVendorPartyId; // orderPartyId should be bill-from-vendor when it is a purchase order
}
}
public String getShipFromVendorPartyId() {
return this.shipFromVendorPartyId != null ? this.shipFromVendorPartyId : this.getPartyId();
}
public void setShipFromVendorPartyId(String shipFromVendorPartyId) {
this.shipFromVendorPartyId = shipFromVendorPartyId;
if (UtilValidate.isEmpty(this.orderPartyId)) this.orderPartyId = shipFromVendorPartyId;
}
public String getSupplierAgentPartyId() {
return this.supplierAgentPartyId != null ? this.supplierAgentPartyId : this.getPartyId();
}
public void setSupplierAgentPartyId(String supplierAgentPartyId) {
this.supplierAgentPartyId = supplierAgentPartyId;
if (UtilValidate.isEmpty(this.orderPartyId)) this.orderPartyId = supplierAgentPartyId;
}
public String getPartyId() {
String partyId = this.orderPartyId;
if (partyId == null && getUserLogin() != null) {
partyId = getUserLogin().getString("partyId");
}
if (partyId == null && getAutoUserLogin() != null) {
partyId = getAutoUserLogin().getString("partyId");
}
return partyId;
}
public void setAutoSaveListId(String id) {
this.autoSaveListId = id;
}
public String getAutoSaveListId() {
return this.autoSaveListId;
}
public void setLastListRestore(Timestamp time) {
this.lastListRestore = time;
}
public Timestamp getLastListRestore() {
return this.lastListRestore;
}
public BigDecimal getPartyDaysSinceCreated(Timestamp nowTimestamp) {
String partyId = this.getPartyId();
if (UtilValidate.isEmpty(partyId)) {
return null;
}
try {
GenericValue party = this.getDelegator().findOne("Party", UtilMisc.toMap("partyId", partyId), true);
if (party == null) {
return null;
}
Timestamp createdDate = party.getTimestamp("createdDate");
if (createdDate == null) {
return null;
}
BigDecimal diffMillis = new BigDecimal(nowTimestamp.getTime() - createdDate.getTime());
// millis per day: 1000.0 * 60.0 * 60.0 * 24.0 = 86400000.0
return (diffMillis).divide(new BigDecimal("86400000"), generalRounding);
} catch (GenericEntityException e) {
Debug.logError(e, "Error looking up party when getting createdDate", module);
return null;
}
}
// =======================================================================
// Methods for cart fields
// =======================================================================
/** Clears out the cart. */
public void clear() {
this.poNumber = null;
this.orderId = null;
this.firstAttemptOrderId = null;
this.billingAccountId = null;
this.billingAccountAmt = BigDecimal.ZERO;
this.nextItemSeq = 1;
this.agreementId = null;
this.quoteId = null;
this.defaultItemDeliveryDate = null;
this.defaultItemComment = null;
this.orderAdditionalEmails = null;
this.readOnlyCart = false;
this.lastListRestore = null;
this.orderTermSet = false;
this.orderTerms.clear();
this.adjustments.clear();
this.expireSingleUsePayments();
this.cartLines.clear();
this.itemGroupByNumberMap.clear();
this.clearPayments();
this.shipInfo.clear();
this.contactMechIdsMap.clear();
this.internalOrderNotes.clear();
this.orderNotes.clear();
this.attributes.clear();
this.orderAttributes.clear();
// clear the additionalPartyRole Map
for (Map.Entry<String, List<String>> me : this.additionalPartyRole.entrySet()) {
((LinkedList<String>) me.getValue()).clear();
}
this.additionalPartyRole.clear();
this.freeShippingProductPromoActions.clear();
this.desiredAlternateGiftByAction.clear();
this.productPromoUseInfoList.clear();
this.productPromoCodes.clear();
// clear the auto-save info
if (ProductStoreWorker.autoSaveCart(this.getDelegator(), this.getProductStoreId())) {
GenericValue ul = this.getUserLogin();
if (ul == null) {
ul = this.getAutoUserLogin();
}
// autoSaveListId shouldn't be set to null for anonymous user until the list is not cleared from the database
if (ul != null && !"anonymous".equals(ul.getString("userLoginId"))) {
this.autoSaveListId = null;
}
// load the auto-save list ID
if (autoSaveListId == null) {
try {
autoSaveListId = ShoppingListEvents.getAutoSaveListId(this.getDelegator(), null, null, ul, this.getProductStoreId());
} catch (GeneralException e) {
Debug.logError(e, module);
}
}
// clear the list
if (autoSaveListId != null) {
try {
org.apache.ofbiz.order.shoppinglist.ShoppingListEvents.clearListInfo(this.getDelegator(), autoSaveListId);
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
}
this.lastListRestore = null;
this.autoSaveListId = null;
}
}
/** Sets the order type. */
public void setOrderType(String orderType) {
this.orderType = orderType;
}
/** Returns the order type. */
public String getOrderType() {
return this.orderType;
}
public void setChannelType(String channelType) {
this.channel = channelType;
}
public String getChannelType() {
return this.channel;
}
public boolean isPurchaseOrder() {
return "PURCHASE_ORDER".equals(this.orderType);
}
public boolean isSalesOrder() {
return "SALES_ORDER".equals(this.orderType);
}
/** Sets the PO Number in the cart. */
public void setPoNumber(String poNumber) {
this.poNumber = poNumber;
}
/** Returns the po number. */
public String getPoNumber() {
return poNumber;
}
public void setDefaultItemDeliveryDate(String date) {
this.defaultItemDeliveryDate = date;
}
public String getDefaultItemDeliveryDate() {
return this.defaultItemDeliveryDate;
}
public void setDefaultItemComment(String comment) {
this.defaultItemComment = comment;
}
public String getDefaultItemComment() {
return this.defaultItemComment;
}
public void setAgreementId(String agreementId) {
this.agreementId = agreementId;
}
public String getAgreementId() {
return this.agreementId;
}
public void setQuoteId(String quoteId) {
this.quoteId = quoteId;
}
public String getQuoteId() {
return this.quoteId;
}
// =======================================================================
// Payment Method
// =======================================================================
public String getPaymentMethodTypeId(String paymentMethodId) {
try {
GenericValue pm = this.getDelegator().findOne("PaymentMethod", UtilMisc.toMap("paymentMethodId", paymentMethodId), false);
if (pm != null) {
return pm.getString("paymentMethodTypeId");
}
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
return null;
}
/** Creates a CartPaymentInfo object */
public CartPaymentInfo makePaymentInfo(String id, String refNum, BigDecimal amount) {
CartPaymentInfo inf = new CartPaymentInfo();
inf.refNum[0] = refNum;
inf.amount = amount;
if (!isPaymentMethodType(id)) {
inf.paymentMethodTypeId = this.getPaymentMethodTypeId(id);
inf.paymentMethodId = id;
} else {
inf.paymentMethodTypeId = id;
}
return inf;
}
/** Creates a CartPaymentInfo object with a possible authCode (may be null) */
public CartPaymentInfo makePaymentInfo(String id, String refNum, String authCode, BigDecimal amount) {
CartPaymentInfo inf = new CartPaymentInfo();
inf.refNum[0] = refNum;
inf.refNum[1] = authCode;
inf.amount = amount;
if (!isPaymentMethodType(id)) {
inf.paymentMethodTypeId = this.getPaymentMethodTypeId(id);
inf.paymentMethodId = id;
} else {
inf.paymentMethodTypeId = id;
}
return inf;
}
/** Locates the index of an existing CartPaymentInfo object or -1 if none found */
public int getPaymentInfoIndex(String id, String refNum) {
CartPaymentInfo thisInf = this.makePaymentInfo(id, refNum, null);
for (int i = 0; i < paymentInfo.size(); i++) {
CartPaymentInfo inf = paymentInfo.get(i);
if (inf.compareTo(thisInf) == 0) {
return i;
}
}
return -1;
}
/** Returns the CartPaymentInfo objects which have matching fields */
public List<CartPaymentInfo> getPaymentInfos(boolean isPaymentMethod, boolean isPaymentMethodType, boolean hasRefNum) {
List<CartPaymentInfo> foundRecords = new LinkedList<CartPaymentInfo>();
for (CartPaymentInfo inf : paymentInfo) {
if (isPaymentMethod && inf.paymentMethodId != null) {
if (hasRefNum && inf.refNum != null) {
foundRecords.add(inf);
} else if (!hasRefNum && inf.refNum == null) {
foundRecords.add(inf);
}
} else if (isPaymentMethodType && inf.paymentMethodTypeId != null) {
if (hasRefNum && inf.refNum != null) {
foundRecords.add(inf);
} else if (!hasRefNum && inf.refNum == null) {
foundRecords.add(inf);
}
}
}
return foundRecords;
}
/** Locates an existing CartPaymentInfo object by index */
public CartPaymentInfo getPaymentInfo(int index) {
return paymentInfo.get(index);
}
/** Locates an existing (or creates a new) CartPaymentInfo object */
public CartPaymentInfo getPaymentInfo(String id, String refNum, String authCode, BigDecimal amount, boolean update) {
CartPaymentInfo thisInf = this.makePaymentInfo(id, refNum, authCode, amount);
for (CartPaymentInfo inf : paymentInfo) {
if (inf.compareTo(thisInf) == 0) {
// update the info
if (update) {
inf.refNum[0] = refNum;
inf.refNum[1] = authCode;
inf.amount = amount;
}
Debug.logInfo("Returned existing PaymentInfo - " + inf.toString(), module);
return inf;
}
}
Debug.logInfo("Returned new PaymentInfo - " + thisInf.toString(), module);
return thisInf;
}
/** Locates an existing (or creates a new) CartPaymentInfo object */
public CartPaymentInfo getPaymentInfo(String id, String refNum, String authCode, BigDecimal amount) {
return this.getPaymentInfo(id, refNum, authCode, amount, false);
}
/** Locates an existing (or creates a new) CartPaymentInfo object */
public CartPaymentInfo getPaymentInfo(String id) {
return this.getPaymentInfo(id, null, null, null, false);
}
/** adds a payment method/payment method type */
public CartPaymentInfo addPaymentAmount(String id, BigDecimal amount, String refNum, String authCode, boolean isSingleUse, boolean isPresent, boolean replace) {
CartPaymentInfo inf = this.getPaymentInfo(id, refNum, authCode, amount, replace);
if (isSalesOrder()) {
GenericValue billingAddress = inf.getBillingAddress(this.getDelegator());
if (billingAddress != null) {
// this payment method will set the billing address for the order;
// before it is set we have to verify if the billing address is
// compatible with the ProductGeos
for (GenericValue product : ShoppingCart.getItemsProducts(this.cartLines)) {
if (!ProductWorker.isBillableToAddress(product, billingAddress)) {
throw new IllegalArgumentException("The billing address is not compatible with ProductGeos rules.");
}
}
}
}
inf.singleUse = isSingleUse;
inf.isPresent = isPresent;
if (replace) {
paymentInfo.remove(inf);
}
paymentInfo.add(inf);
return inf;
}
/** adds a payment method/payment method type */
public CartPaymentInfo addPaymentAmount(String id, BigDecimal amount, boolean isSingleUse) {
return this.addPaymentAmount(id, amount, null, null, isSingleUse, false, true);
}
/** adds a payment method/payment method type */
public CartPaymentInfo addPaymentAmount(String id, BigDecimal amount) {
return this.addPaymentAmount(id, amount, false);
}
/** adds a payment method/payment method type */
public CartPaymentInfo addPayment(String id) {
return this.addPaymentAmount(id, null, false);
}
/** returns the payment method/payment method type amount */
public BigDecimal getPaymentAmount(String id) {
return this.getPaymentInfo(id).amount;
}
public void addPaymentRef(String id, String ref, String authCode) {
this.getPaymentInfo(id).refNum[0] = ref;
this.getPaymentInfo(id).refNum[1] = authCode;
}
public String getPaymentRef(String id) {
for (CartPaymentInfo inf : paymentInfo) {
if (inf.paymentMethodId.equals(id) || inf.paymentMethodTypeId.equals(id)) {
return inf.refNum[0];
}
}
return null;
}
/** returns the total payment amounts */
public BigDecimal getPaymentTotal() {
BigDecimal total = BigDecimal.ZERO;
for (CartPaymentInfo inf : paymentInfo) {
if (inf.amount != null) {
total = total.add(inf.amount);
}
}
return total;
}
public int selectedPayments() {
return paymentInfo.size();
}
public boolean isPaymentSelected(String id) {
CartPaymentInfo inf = this.getPaymentInfo(id);
return paymentInfo.contains(inf);
}
/** removes a specific payment method/payment method type */
public void clearPayment(String id) {
CartPaymentInfo inf = this.getPaymentInfo(id);
paymentInfo.remove(inf);
}
/** removes a specific payment info from the list */
public void clearPayment(int index) {
paymentInfo.remove(index);
}
/** clears all payment method/payment method types */
public void clearPayments() {
this.expireSingleUsePayments();
paymentInfo.clear();
}
/** remove all the paymentMethods based on the paymentMethodIds */
public void clearPaymentMethodsById(List<String> paymentMethodIdsToRemove) {
if (UtilValidate.isEmpty(paymentMethodIdsToRemove)) return;
for (Iterator<CartPaymentInfo> iter = paymentInfo.iterator(); iter.hasNext();) {
CartPaymentInfo info = iter.next();
if (paymentMethodIdsToRemove.contains(info.paymentMethodId)) {
iter.remove();
}
}
}
/** remove declined payment methods for an order from cart. The idea is to call this after an attempted order is rejected */
public void clearDeclinedPaymentMethods(Delegator delegator) {
String orderId = this.getOrderId();
if (UtilValidate.isNotEmpty(orderId)) {
try {
List<GenericValue> declinedPaymentMethods = EntityQuery.use(delegator).from("OrderPaymentPreference").where("orderId", orderId, "statusId", "PAYMENT_DECLINED").queryList();
if (UtilValidate.isNotEmpty(declinedPaymentMethods)) {
List<String> paymentMethodIdsToRemove = new ArrayList<String>();
for (GenericValue opp : declinedPaymentMethods) {
paymentMethodIdsToRemove.add(opp.getString("paymentMethodId"));
}
clearPaymentMethodsById(paymentMethodIdsToRemove);
}
} catch (GenericEntityException ex) {
Debug.logError("Unable to remove declined payment methods from cart due to " + ex.getMessage(), module);
return;
}
}
}
private void expireSingleUsePayments() {
Timestamp now = UtilDateTime.nowTimestamp();
for (CartPaymentInfo inf : paymentInfo) {
if (inf.paymentMethodId == null || !inf.singleUse) {
continue;
}
GenericValue paymentMethod = null;
try {
paymentMethod = this.getDelegator().findOne("PaymentMethod", UtilMisc.toMap("paymentMethodId", inf.paymentMethodId), false);
} catch (GenericEntityException e) {
Debug.logError(e, "ERROR: Unable to get payment method record to expire : " + inf.paymentMethodId, module);
}
if (paymentMethod != null) {
paymentMethod.set("thruDate", now);
try {
paymentMethod.store();
} catch (GenericEntityException e) {
Debug.logError(e, "Unable to store single use PaymentMethod record : " + paymentMethod, module);
}
} else {
Debug.logError("ERROR: Received back a null payment method record for expired ID : " + inf.paymentMethodId, module);
}
}
}
/** Returns the Payment Method Ids */
public List<String> getPaymentMethodIds() {
List<String> pmi = new LinkedList<String>();
for (CartPaymentInfo inf : paymentInfo) {
if (inf.paymentMethodId != null) {
pmi.add(inf.paymentMethodId);
}
}
return pmi;
}
/** Returns the Payment Method Ids */
public List<String> getPaymentMethodTypeIds() {
List<String> pmt = new LinkedList<String>();
for (CartPaymentInfo inf : paymentInfo) {
if (inf.paymentMethodTypeId != null) {
pmt.add(inf.paymentMethodTypeId);
}
}
return pmt;
}
/** Returns a list of PaymentMethod value objects selected in the cart */
public List<GenericValue> getPaymentMethods() {
List<GenericValue> methods = new LinkedList<GenericValue>();
if (UtilValidate.isNotEmpty(paymentInfo)) {
for (String paymentMethodId : getPaymentMethodIds()) {
try {
GenericValue paymentMethod = this.getDelegator().findOne("PaymentMethod", UtilMisc.toMap("paymentMethodId", paymentMethodId), true);
if (paymentMethod != null) {
methods.add(paymentMethod);
} else {
Debug.logError("Error getting cart payment methods, the paymentMethodId [" + paymentMethodId +"] is not valid", module);
}
} catch (GenericEntityException e) {
Debug.logError(e, "Unable to get payment method from the database", module);
}
}
}
return methods;
}
/** Returns a list of PaymentMethodType value objects selected in the cart */
public List<GenericValue> getPaymentMethodTypes() {
List<GenericValue> types = new LinkedList<GenericValue>();
if (UtilValidate.isNotEmpty(paymentInfo)) {
for (String id : getPaymentMethodIds()) {
try {
types.add(this.getDelegator().findOne("PaymentMethodType", UtilMisc.toMap("paymentMethodTypeId", id), true));
} catch (GenericEntityException e) {
Debug.logError(e, "Unable to get payment method type from the database", module);
}
}
}
return types;
}
public List<GenericValue> getCreditCards() {
List<GenericValue> paymentMethods = this.getPaymentMethods();
List<GenericValue> creditCards = new LinkedList<GenericValue>();
if (paymentMethods != null) {
for (GenericValue pm : paymentMethods) {
if ("CREDIT_CARD".equals(pm.getString("paymentMethodTypeId"))) {
try {
GenericValue cc = pm.getRelatedOne("CreditCard", false);
creditCards.add(cc);
} catch (GenericEntityException e) {
Debug.logError(e, "Unable to get credit card record from payment method : " + pm, module);
}
}
}
}
return creditCards;
}
public List<GenericValue> getGiftCards() {
List<GenericValue> paymentMethods = this.getPaymentMethods();
List<GenericValue> giftCards = new LinkedList<GenericValue>();
if (paymentMethods != null) {
for (GenericValue pm : paymentMethods) {
if ("GIFT_CARD".equals(pm.getString("paymentMethodTypeId"))) {
try {
GenericValue gc = pm.getRelatedOne("GiftCard", false);
giftCards.add(gc);
} catch (GenericEntityException e) {
Debug.logError(e, "Unable to get gift card record from payment method : " + pm, module);
}
}
}
}
return giftCards;
}
/* determines if the id supplied is a payment method or not by searching in the entity engine */
public boolean isPaymentMethodType(String id) {
GenericValue paymentMethodType = null;
try {
paymentMethodType = this.getDelegator().findOne("PaymentMethodType", UtilMisc.toMap("paymentMethodTypeId", id), true);
} catch (GenericEntityException e) {
Debug.logInfo(e, "Problems getting PaymentMethodType", module);
}
if (paymentMethodType == null) {
return false;
} else {
return true;
}
}
public GenericValue getBillingAddress() {
GenericValue billingAddress = null;
for (CartPaymentInfo inf : paymentInfo) {
billingAddress = inf.getBillingAddress(this.getDelegator());
if (billingAddress != null) {
break;
}
}
return billingAddress;
}
/**
* Returns ProductStoreFinActSetting based on cart's productStoreId and FinAccountHelper's defined giftCertFinAcctTypeId
* @param delegator the delegator
* @return returns ProductStoreFinActSetting based on cart's productStoreId
* @throws GenericEntityException
*/
public GenericValue getGiftCertSettingFromStore(Delegator delegator) throws GenericEntityException {
return EntityQuery.use(delegator).from("ProductStoreFinActSetting").where("productStoreId", getProductStoreId(), "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId).cache().queryOne();
}
/**
* Determines whether pin numbers are required for gift cards, based on ProductStoreFinActSetting. Default to true.
* @param delegator the delegator
* @return returns true whether pin numbers are required for gift card
*/
public boolean isPinRequiredForGC(Delegator delegator) {
try {
GenericValue giftCertSettings = getGiftCertSettingFromStore(delegator);
if (giftCertSettings != null) {
if ("Y".equals(giftCertSettings.getString("requirePinCode"))) {
return true;
} else {
return false;
}
} else {
Debug.logWarning("No product store gift certificate settings found for store [" + getProductStoreId() + "]", module);
return true;
}
} catch (GenericEntityException ex) {
Debug.logError("Error checking if store requires pin number for GC: " + ex.getMessage(), module);
return true;
}
}
/**
* Returns whether the cart should validate gift cards against FinAccount (ie, internal gift certificates). Defaults to false.
* @param delegator the delegator
* @return returns true whether the cart should validate gift cards against FinAccount
*/
public boolean isValidateGCFinAccount(Delegator delegator) {
try {
GenericValue giftCertSettings = getGiftCertSettingFromStore(delegator);
if (giftCertSettings != null) {
if ("Y".equals(giftCertSettings.getString("validateGCFinAcct"))) {
return true;
} else {
return false;
}
} else {
Debug.logWarning("No product store gift certificate settings found for store [" + getProductStoreId() + "]", module);
return false;
}
} catch (GenericEntityException ex) {
Debug.logError("Error checking if store requires pin number for GC: " + ex.getMessage(), module);
return false;
}
}
// =======================================================================
// Billing Accounts
// =======================================================================
/** Sets the billing account id string. */
public void setBillingAccount(String billingAccountId, BigDecimal amount) {
this.billingAccountId = billingAccountId;
this.billingAccountAmt = amount;
}
/** Returns the billing message string. */
public String getBillingAccountId() {
return this.billingAccountId;
}
/** Returns the amount to be billed to the billing account.*/
public BigDecimal getBillingAccountAmount() {
return this.billingAccountAmt;
}
// =======================================================================
// Shipping Charges
// =======================================================================
/** Returns the order level shipping amount */
public BigDecimal getOrderShipping() {
return OrderReadHelper.calcOrderAdjustments(this.getAdjustments(), this.getSubTotal(), false, false, true);
}
// ----------------------------------------
// Ship Group Methods
// ----------------------------------------
public int addShipInfo() {
CartShipInfo csi = new CartShipInfo();
csi.orderTypeId = getOrderType();
shipInfo.add(csi);
return (shipInfo.size() - 1);
}
public List<CartShipInfo> getShipGroups() {
return this.shipInfo;
}
public Map<Integer, BigDecimal> getShipGroups(ShoppingCartItem item) {
Map<Integer, BigDecimal> shipGroups = new LinkedHashMap<Integer, BigDecimal>();
if (item != null) {
for (int i = 0; i < this.shipInfo.size(); i++) {
CartShipInfo csi = shipInfo.get(i);
CartShipInfo.CartShipItemInfo csii = csi.shipItemInfo.get(item);
if (csii != null) {
if (this.checkShipItemInfo(csi, csii)) {
shipGroups.put(i, csii.quantity);
}
}
}
}
return shipGroups;
}
public Map<Integer, BigDecimal> getShipGroups(int itemIndex) {
return this.getShipGroups(this.findCartItem(itemIndex));
}
public CartShipInfo getShipInfo(int idx) {
if (idx == -1) {
return null;
}
if (shipInfo.size() == idx) {
CartShipInfo csi = new CartShipInfo();
csi.orderTypeId = getOrderType();
shipInfo.add(csi);
}
return shipInfo.get(idx);
}
public int getShipGroupSize() {
return this.shipInfo.size();
}
/** Returns the ShoppingCartItem (key) and quantity (value) associated with the ship group */
public Map<ShoppingCartItem, BigDecimal> getShipGroupItems(int idx) {
CartShipInfo csi = this.getShipInfo(idx);
Map<ShoppingCartItem, BigDecimal> qtyMap = new HashMap<ShoppingCartItem, BigDecimal>();
for (ShoppingCartItem item : csi.shipItemInfo.keySet()) {
CartShipInfo.CartShipItemInfo csii = csi.shipItemInfo.get(item);
qtyMap.put(item, csii.quantity);
}
return qtyMap;
}
public void clearItemShipInfo(ShoppingCartItem item) {
for (int i = 0; i < shipInfo.size(); i++) {
CartShipInfo csi = this.getShipInfo(i);
csi.shipItemInfo.remove(item);
}
// DEJ20100107: commenting this out because we do NOT want to clear out ship group info since there is information there that will be lost; good enough to clear the item/group association which can be restored later (though questionable, the whole processes using this should be rewritten to not destroy information!
// this.cleanUpShipGroups();
}
public void setItemShipGroupEstimate(BigDecimal amount, int idx) {
CartShipInfo csi = this.getShipInfo(idx);
csi.shipEstimate = amount;
}
/**
* Updates the shipBefore and shipAfterDates of all ship groups that the item belongs to, re-setting
* ship group ship before date if item ship before date is before it and ship group ship after date if
* item ship after date is before it.
* @param item
*/
public void setShipGroupShipDatesFromItem(ShoppingCartItem item) {
Map<Integer, BigDecimal> shipGroups = this.getShipGroups(item);
if ((shipGroups != null) && (shipGroups.keySet() != null)) {
for (Integer shipGroup : shipGroups.keySet()) {
CartShipInfo cartShipInfo = this.getShipInfo(shipGroup.intValue());
cartShipInfo.resetShipAfterDateIfBefore(item.getShipAfterDate());
cartShipInfo.resetShipBeforeDateIfAfter(item.getShipBeforeDate());
}
}
}
public BigDecimal getItemShipGroupEstimate(int idx) {
CartShipInfo csi = this.getShipInfo(idx);
return csi.shipEstimate;
}
public void setItemShipGroupQty(int itemIndex, BigDecimal quantity, int idx) {
ShoppingCartItem itemIdx = this.findCartItem(itemIndex);
if(itemIdx != null) {
this.setItemShipGroupQty(itemIdx, itemIndex, quantity, idx);
}
}
public void setItemShipGroupQty(ShoppingCartItem item, BigDecimal quantity, int idx) {
this.setItemShipGroupQty(item, this.getItemIndex(item), quantity, idx);
}
public void setItemShipGroupQty(ShoppingCartItem item, int itemIndex, BigDecimal quantity, int idx) {
if (itemIndex > -1) {
CartShipInfo csi = this.getShipInfo(idx);
// never set less than zero
if (quantity.compareTo(BigDecimal.ZERO) < 0) {
quantity = BigDecimal.ZERO;
}
// never set more than quantity ordered
if (item != null) {
if (quantity.compareTo(item.getQuantity()) > 0) {
quantity = item.getQuantity();
}
// re-set the ship group's before and after dates based on the item's
csi.resetShipBeforeDateIfAfter(item.getShipBeforeDate());
csi.resetShipAfterDateIfBefore(item.getShipAfterDate());
CartShipInfo.CartShipItemInfo csii = csi.setItemInfo(item, quantity);
this.checkShipItemInfo(csi, csii);
}
}
}
public BigDecimal getItemShipGroupQty(ShoppingCartItem item, int idx) {
if (item != null) {
CartShipInfo csi = this.getShipInfo(idx);
CartShipInfo.CartShipItemInfo csii = csi.shipItemInfo.get(item);
if (csii != null) {
return csii.quantity;
}
}
return BigDecimal.ZERO;
}
public BigDecimal getItemShipGroupQty(int itemIndex, int idx) {
return this.getItemShipGroupQty(this.findCartItem(itemIndex), idx);
}
public void positionItemToGroup(int itemIndex, BigDecimal quantity, int fromIndex, int toIndex, boolean clearEmptyGroups) {
this.positionItemToGroup(this.findCartItem(itemIndex), quantity, fromIndex, toIndex, clearEmptyGroups);
}
public void positionItemToGroup(ShoppingCartItem item, BigDecimal quantity, int fromIndex, int toIndex, boolean clearEmptyGroups) {
if (fromIndex == toIndex || quantity.compareTo(BigDecimal.ZERO) <= 0) {
// do nothing
return;
}
// get the ship groups; create the TO group if needed
CartShipInfo fromGroup = this.getShipInfo(fromIndex);
CartShipInfo toGroup = null;
if (toIndex == -1) {
toGroup = new CartShipInfo();
toGroup.orderTypeId = getOrderType();
this.shipInfo.add(toGroup);
toIndex = this.shipInfo.size() - 1;
} else {
toGroup = this.getShipInfo(toIndex);
}
// adjust the quantities
if (fromGroup != null && toGroup != null) {
BigDecimal fromQty = this.getItemShipGroupQty(item, fromIndex);
BigDecimal toQty = this.getItemShipGroupQty(item, toIndex);
if (fromQty.compareTo(BigDecimal.ZERO) > 0) {
if (quantity.compareTo(fromQty) > 0) {
quantity = fromQty;
}
fromQty = fromQty.subtract(quantity);
toQty = toQty.add(quantity);
this.setItemShipGroupQty(item, fromQty, fromIndex);
this.setItemShipGroupQty(item, toQty, toIndex);
}
if (clearEmptyGroups) {
// remove any empty ship groups
this.cleanUpShipGroups();
}
}
}
// removes 0 quantity items
protected boolean checkShipItemInfo(CartShipInfo csi, CartShipInfo.CartShipItemInfo csii) {
if (csii.quantity.compareTo(BigDecimal.ZERO) == 0 || csii.item.getQuantity().compareTo(BigDecimal.ZERO) == 0) {
csi.shipItemInfo.remove(csii.item);
return false;
}
return true;
}
public void cleanUpShipGroups() {
for (CartShipInfo csi : this.shipInfo) {
Iterator<ShoppingCartItem> si = csi.shipItemInfo.keySet().iterator();
while (si.hasNext()) {
ShoppingCartItem item = si.next();
if (item.getQuantity().compareTo(BigDecimal.ZERO) == 0) {
si.remove();
}
}
if (csi.shipItemInfo.size() == 0) {
this.shipInfo.remove(csi);
}
}
}
public int getShipInfoIndex (String shipGroupSeqId) {
int idx = -1;
for (int i=0; i<shipInfo.size(); i++) {
CartShipInfo csi = shipInfo.get(i);
if (shipGroupSeqId.equals(csi.shipGroupSeqId)) {
idx = i;
break;
}
}
return idx;
}
/**
* Return index of the ship group where the item is located
* @return
*/
public int getItemShipGroupIndex(int itemId) {
int shipGroupIndex = this.getShipGroupSize() - 1;
ShoppingCartItem item = this.findCartItem(itemId);
int result=0;
for (int i = 0; i <(shipGroupIndex + 1); i++) {
CartShipInfo csi = this.getShipInfo(i);
Iterator<ShoppingCartItem> it = csi.shipItemInfo.keySet().iterator();
while (it.hasNext()) {
ShoppingCartItem item2 = it.next();
if (item.equals(item2) ) {
result = i;
}
}
}
return result;
}
/** Sets the shipping contact mech id. */
public void setShippingContactMechId(int idx, String shippingContactMechId) {
CartShipInfo csi = this.getShipInfo(idx);
if (isSalesOrder() && UtilValidate.isNotEmpty(shippingContactMechId)) {
// Verify if the new address is compatible with the ProductGeos rules of
// the products already in the cart
GenericValue shippingAddress = null;
try {
shippingAddress = this.getDelegator().findOne("PostalAddress", UtilMisc.toMap("contactMechId", shippingContactMechId), false);
} catch (GenericEntityException gee) {
Debug.logError(gee, "Error retrieving the shipping address for contactMechId [" + shippingContactMechId + "].", module);
}
if (shippingAddress != null) {
Set<ShoppingCartItem> shipItems = csi.getShipItems();
if (UtilValidate.isNotEmpty(shipItems)) {
for (ShoppingCartItem cartItem : shipItems) {
GenericValue product = cartItem.getProduct();
if (product != null) {
if (!ProductWorker.isShippableToAddress(product, shippingAddress)) {
throw new IllegalArgumentException("The shipping address is not compatible with ProductGeos rules.");
}
}
}
}
}
}
csi.setContactMechId(shippingContactMechId);
}
/**
* Sets @param shippingContactMechId in all ShipInfo(ShipGroups) associated
* with this ShoppingCart
* <p>
* @param shippingContactMechId
*/
public void setAllShippingContactMechId(String shippingContactMechId) {
for (int x=0; x < shipInfo.size(); x++) {
this.setShippingContactMechId(x, shippingContactMechId);
}
}
/** Returns the shipping contact mech id. */
public String getShippingContactMechId(int idx) {
CartShipInfo csi = this.getShipInfo(idx);
return csi.getContactMechId();
}
public String getShippingContactMechId() {
return this.getShippingContactMechId(0);
}
/** Sets the shipment method type. */
public void setShipmentMethodTypeId(int idx, String shipmentMethodTypeId) {
CartShipInfo csi = this.getShipInfo(idx);
csi.shipmentMethodTypeId = shipmentMethodTypeId;
}
/**
* Sets @param shipmentMethodTypeId in all ShipInfo(ShipGroups) associated
* with this ShoppingCart
* <p>
* @param shipmentMethodTypeId
*/
public void setAllShipmentMethodTypeId(String shipmentMethodTypeId) {
for (int x=0; x < shipInfo.size(); x++) {
this.setShipmentMethodTypeId(x, shipmentMethodTypeId);
}
}
/** Returns the shipment method type ID */
public String getShipmentMethodTypeId(int idx) {
CartShipInfo csi = this.getShipInfo(idx);
return csi.shipmentMethodTypeId;
}
public String getShipmentMethodTypeId() {
return this.getShipmentMethodTypeId(0);
}
/** Returns the shipment method type. */
public GenericValue getShipmentMethodType(int idx) {
String shipmentMethodTypeId = this.getShipmentMethodTypeId(idx);
if (UtilValidate.isNotEmpty(shipmentMethodTypeId)) {
try {
return this.getDelegator().findOne("ShipmentMethodType",
UtilMisc.toMap("shipmentMethodTypeId", shipmentMethodTypeId), false);
} catch (GenericEntityException e) {
Debug.logWarning(e, module);
}
}
return null;
}
/** Sets the supplier for the given ship group (drop shipment). */
public void setSupplierPartyId(int idx, String supplierPartyId) {
CartShipInfo csi = this.getShipInfo(idx);
// TODO: before we set the value we have to verify if all the products
// already in this ship group are drop shippable from the supplier
csi.supplierPartyId = supplierPartyId;
}
/** Returns the supplier for the given ship group (drop shipment). */
public String getSupplierPartyId(int idx) {
CartShipInfo csi = this.getShipInfo(idx);
return csi.supplierPartyId;
}
/** Sets the shipping instructions. */
public void setShippingInstructions(int idx, String shippingInstructions) {
CartShipInfo csi = this.getShipInfo(idx);
csi.shippingInstructions = shippingInstructions;
}
/**
* Sets @param shippingInstructions in all ShipInfo(ShipGroups) associated
* with this ShoppingCart
* <p>
* @param shippingInstructions
*/
public void setAllShippingInstructions(String shippingInstructions) {
for (int x=0; x < shipInfo.size(); x++) {
this.setShippingInstructions(x, shippingInstructions);
}
}
/** Returns the shipping instructions. */
public String getShippingInstructions(int idx) {
CartShipInfo csi = this.getShipInfo(idx);
return csi.shippingInstructions;
}
public String getShippingInstructions() {
return this.getShippingInstructions(0);
}
public void setMaySplit(int idx, Boolean maySplit) {
CartShipInfo csi = this.getShipInfo(idx);
if (UtilValidate.isNotEmpty(maySplit)) {
csi.setMaySplit(maySplit);
}
}
/**
* Sets @param maySplit in all ShipInfo(ShipGroups) associated
* with this ShoppingCart
* <p>
* @param maySplit
*/
public void setAllMaySplit(Boolean maySplit) {
for (int x=0; x < shipInfo.size(); x++) {
this.setMaySplit(x, maySplit);
}
}
/** Returns Boolean.TRUE if the order may be split (null if unspecified) */
public String getMaySplit(int idx) {
CartShipInfo csi = this.getShipInfo(idx);
return csi.maySplit;
}
public String getMaySplit() {
return this.getMaySplit(0);
}
public void setGiftMessage(int idx, String giftMessage) {
CartShipInfo csi = this.getShipInfo(idx);
csi.giftMessage = giftMessage;
}
/**
* Sets @param giftMessage in all ShipInfo(ShipGroups) associated
* with this ShoppingCart
* <p>
* @param giftMessage
*/
public void setAllGiftMessage(String giftMessage) {
for (int x=0; x < shipInfo.size(); x++) {
this.setGiftMessage(x, giftMessage);
}
}
public String getGiftMessage(int idx) {
CartShipInfo csi = this.getShipInfo(idx);
return csi.giftMessage;
}
public String getGiftMessage() {
return this.getGiftMessage(0);
}
public void setIsGift(int idx, Boolean isGift) {
CartShipInfo csi = this.getShipInfo(idx);
if (UtilValidate.isNotEmpty(isGift)) {
csi.isGift = isGift.booleanValue() ? "Y" : "N";
}
}
/**
* Sets @param isGift in all ShipInfo(ShipGroups) associated
* with this ShoppingCart
* <p>
* @param isGift
*/
public void setAllIsGift(Boolean isGift) {
for (int x=0; x < shipInfo.size(); x++) {
this.setIsGift(x, isGift);
}
}
public String getIsGift(int idx) {
CartShipInfo csi = this.getShipInfo(idx);
return csi.isGift;
}
public String getIsGift() {
return this.getIsGift(0);
}
public void setCarrierPartyId(int idx, String carrierPartyId) {
CartShipInfo csi = this.getShipInfo(idx);
csi.carrierPartyId = carrierPartyId;
}
/**
* Sets @param carrierPartyId in all ShipInfo(ShipGroups) associated
* with this ShoppingCart
* <p>
* @param carrierPartyId
*/
public void setAllCarrierPartyId(String carrierPartyId) {
for (int x=0; x < shipInfo.size(); x++) {
this.setCarrierPartyId(x, carrierPartyId);
}
}
public String getCarrierPartyId(int idx) {
CartShipInfo csi = this.getShipInfo(idx);
return csi.carrierPartyId;
}
public String getCarrierPartyId() {
return this.getCarrierPartyId(0);
}
public String getProductStoreShipMethId(int idx) {
CartShipInfo csi = this.getShipInfo(idx);
return csi.productStoreShipMethId;
}
public String getProductStoreShipMethId() {
return this.getProductStoreShipMethId(0);
}
public void setProductStoreShipMethId(int idx, String productStoreShipMethId) {
CartShipInfo csi = this.getShipInfo(idx);
csi.productStoreShipMethId = productStoreShipMethId;
}
/**
* Sets @param productStoreShipMethId in all ShipInfo(ShipGroups) associated
* with this ShoppingCart
* <p>
* @param productStoreShipMethId
*/
public void setAllProductStoreShipMethId(String productStoreShipMethId) {
for (int x=0; x < shipInfo.size(); x++) {
this.setProductStoreShipMethId(x, productStoreShipMethId);
}
}
public void setShipGroupFacilityId(int idx, String facilityId) {
CartShipInfo csi = this.getShipInfo(idx);
csi.facilityId = facilityId;
}
public String getShipGroupFacilityId(int idx) {
CartShipInfo csi = this.getShipInfo(idx);
return csi.facilityId;
}
public void setShipGroupVendorPartyId(int idx, String vendorPartyId) {
CartShipInfo csi = this.getShipInfo(idx);
csi.vendorPartyId = vendorPartyId;
}
public String getShipGroupVendorPartyId(int idx) {
CartShipInfo csi = this.getShipInfo(idx);
return csi.vendorPartyId;
}
public void setShipGroupSeqId(int idx, String shipGroupSeqId) {
CartShipInfo csi = this.getShipInfo(idx);
csi.shipGroupSeqId = shipGroupSeqId;
}
public String getShipGroupSeqId(int idx) {
CartShipInfo csi = this.getShipInfo(idx);
return csi.shipGroupSeqId;
}
public void setOrderAdditionalEmails(String orderAdditionalEmails) {
this.orderAdditionalEmails = orderAdditionalEmails;
}
public String getOrderAdditionalEmails() {
return orderAdditionalEmails;
}
public GenericValue getShippingAddress(int idx) {
if (this.getShippingContactMechId(idx) != null) {
try {
return getDelegator().findOne("PostalAddress", UtilMisc.toMap("contactMechId", this.getShippingContactMechId(idx)), false);
} catch (GenericEntityException e) {
Debug.logWarning(e.toString(), module);
return null;
}
} else {
return null;
}
}
public GenericValue getShippingAddress() {
return this.getShippingAddress(0);
}
// ----------------------------------------
// internal/public notes
// ----------------------------------------
public List<String> getInternalOrderNotes() {
return this.internalOrderNotes;
}
public List<String> getOrderNotes() {
return this.orderNotes;
}
public void addInternalOrderNote(String note) {
this.internalOrderNotes.add(note);
}
public void clearInternalOrderNotes() {
this.internalOrderNotes.clear();
}
public void clearOrderNotes() {
this.orderNotes.clear();
}
public void addOrderNote(String note) {
this.orderNotes.add(note);
}
// Preset with default values some of the checkout options to get a quicker checkout process.
public void setDefaultCheckoutOptions(LocalDispatcher dispatcher) {
// skip the add party screen
this.setAttribute("addpty", "Y");
if (getOrderType().equals("SALES_ORDER")) {
// checkout options for sales orders
// set as the default shipping location the first from the list of available shipping locations
if (this.getPartyId() != null && !this.getPartyId().equals("_NA_")) {
try {
GenericValue orderParty = this.getDelegator().findOne("Party", UtilMisc.toMap("partyId", this.getPartyId()), false);
Collection<GenericValue> shippingContactMechList = ContactHelper.getContactMech(orderParty, "SHIPPING_LOCATION", "POSTAL_ADDRESS", false);
if (UtilValidate.isNotEmpty(shippingContactMechList)) {
GenericValue shippingContactMech = (shippingContactMechList.iterator()).next();
this.setAllShippingContactMechId(shippingContactMech.getString("contactMechId"));
}
} catch (GenericEntityException e) {
Debug.logError(e, "Error setting shippingContactMechId in setDefaultCheckoutOptions() method.", module);
}
}
// set the default shipment method
ShippingEstimateWrapper shipEstimateWrapper = org.apache.ofbiz.order.shoppingcart.shipping.ShippingEstimateWrapper.getWrapper(dispatcher, this, 0);
GenericValue carrierShipmentMethod = EntityUtil.getFirst(shipEstimateWrapper.getShippingMethods());
if (carrierShipmentMethod != null) {
this.setAllShipmentMethodTypeId(carrierShipmentMethod.getString("shipmentMethodTypeId"));
this.setAllCarrierPartyId(carrierShipmentMethod.getString("partyId"));
}
} else {
// checkout options for purchase orders
// TODO: should we select a default agreement? For now we don't do this.
// skip the order terms selection step
this.setOrderTermSet(true);
// set as the default shipping location the first from the list of available shipping locations
String companyId = this.getBillToCustomerPartyId();
if (companyId != null) {
// the facilityId should be set prior to triggering default options, otherwise we do not set up facility information
String defaultFacilityId = getFacilityId();
if (defaultFacilityId != null) {
GenericValue facilityContactMech = ContactMechWorker.getFacilityContactMechByPurpose(this.getDelegator(), facilityId, UtilMisc.toList("SHIPPING_LOCATION", "PRIMARY_LOCATION"));
if (facilityContactMech != null) {
this.setShippingContactMechId(0, facilityContactMech.getString("contactMechId"));
}
}
}
// shipping options
this.setAllShipmentMethodTypeId("NO_SHIPPING");
this.setAllCarrierPartyId("_NA_");
this.setAllShippingInstructions("");
this.setAllGiftMessage("");
this.setAllMaySplit(Boolean.TRUE);
this.setAllIsGift(Boolean.FALSE);
}
}
// Returns the tax amount for a ship group. */
public BigDecimal getTotalSalesTax(int shipGroup) {
CartShipInfo csi = this.getShipInfo(shipGroup);
return csi.getTotalTax(this);
}
/** Returns the tax amount from the cart object. */
public BigDecimal getTotalSalesTax() {
BigDecimal totalTax = ZERO;
for (int i = 0; i < shipInfo.size(); i++) {
CartShipInfo csi = this.getShipInfo(i);
totalTax = totalTax.add(csi.getTotalTax(this)).setScale(taxCalcScale, taxRounding);
}
return totalTax.setScale(taxFinalScale, taxRounding);
}
/** Returns the shipping amount from the cart object. */
public BigDecimal getTotalShipping() {
BigDecimal tempShipping = BigDecimal.ZERO;
for (CartShipInfo csi : this.shipInfo) {
tempShipping = tempShipping.add(csi.shipEstimate);
}
return tempShipping;
}
/** Returns the item-total in the cart (not including discount/tax/shipping). */
public BigDecimal getItemTotal() {
BigDecimal itemTotal = BigDecimal.ZERO;
for (ShoppingCartItem cartItem : this.cartLines) {
itemTotal = itemTotal.add(cartItem.getBasePrice());
}
return itemTotal;
}
/** Returns the sub-total in the cart (item-total - discount). */
public BigDecimal getSubTotal() {
BigDecimal itemsTotal = BigDecimal.ZERO;
for (ShoppingCartItem cartItem : this.cartLines) {
itemsTotal = itemsTotal.add(cartItem.getItemSubTotal());
}
return itemsTotal;
}
/** Returns the total from the cart, including tax/shipping. */
public BigDecimal getGrandTotal() {
// sales tax and shipping are not stored as adjustments but rather as part of the ship group
return this.getSubTotal().add(this.getTotalShipping()).add(this.getTotalSalesTax()).add(this.getOrderOtherAdjustmentTotal()).add(this.getOrderGlobalAdjustments());
}
public BigDecimal getDisplaySubTotal() {
BigDecimal itemsTotal = BigDecimal.ZERO;
for (ShoppingCartItem cartItem : this.cartLines) {
itemsTotal = itemsTotal.add(cartItem.getDisplayItemSubTotal());
}
return itemsTotal;
}
public BigDecimal getOrderGlobalAdjustments() {
List<GenericValue> cartAdjustments = this.getAdjustments();
List<GenericValue> tempAdjustmentsList = new LinkedList<GenericValue>();
if (cartAdjustments != null) {
Iterator<GenericValue> cartAdjustmentIter = cartAdjustments.iterator();
while (cartAdjustmentIter.hasNext()) {
GenericValue checkOrderAdjustment = (GenericValue) cartAdjustmentIter.next();
if (UtilValidate.isEmpty(checkOrderAdjustment.getString("shipGroupSeqId")) || DataModelConstants.SEQ_ID_NA.equals(checkOrderAdjustment.getString("shipGroupSeqId"))) {
tempAdjustmentsList.add(checkOrderAdjustment);
}
}
}
return OrderReadHelper.calcOrderAdjustments(tempAdjustmentsList, this.getSubTotal(), false, true, true);
}
public BigDecimal getDisplayTaxIncluded() {
BigDecimal taxIncluded = getDisplaySubTotal().subtract(getSubTotal());
return taxIncluded.setScale(taxFinalScale, taxRounding);
}
public BigDecimal getDisplayRecurringSubTotal() {
BigDecimal itemsTotal = BigDecimal.ZERO;
for (ShoppingCartItem cartItem : this.cartLines) {
itemsTotal = itemsTotal.add(cartItem.getDisplayItemRecurringSubTotal());
}
return itemsTotal;
}
/** Returns the total from the cart, including tax/shipping. */
public BigDecimal getDisplayGrandTotal() {
return this.getDisplaySubTotal().add(this.getTotalShipping()).add(this.getTotalSalesTax()).add(this.getOrderOtherAdjustmentTotal()).add(this.getOrderGlobalAdjustments());
}
public BigDecimal getOrderOtherAdjustmentTotal() {
return OrderReadHelper.calcOrderAdjustments(this.getAdjustments(), this.getSubTotal(), true, false, false);
}
/** Returns the sub-total in the cart (item-total - discount). */
public BigDecimal getSubTotalForPromotions() {
BigDecimal itemsTotal = BigDecimal.ZERO;
for (ShoppingCartItem cartItem : this.cartLines) {
GenericValue product = cartItem.getProduct();
if (product != null && "N".equals(product.getString("includeInPromotions"))) {
// don't include in total if this is the case...
continue;
}
itemsTotal = itemsTotal.add(cartItem.getItemSubTotal());
}
return itemsTotal.add(this.getOrderOtherAdjustmentTotal());
}
public BigDecimal getSubTotalForPromotions(Set<String> productIds) {
BigDecimal itemsTotal = BigDecimal.ZERO;
for (ShoppingCartItem cartItem : this.cartLines) {
GenericValue product = cartItem.getProduct();
if (product == null || "N".equals(product.getString("includeInPromotions")) || !productIds.contains(cartItem.getProductId())) {
// don't include in total if this is the case...
continue;
}
itemsTotal = itemsTotal.add(cartItem.getItemSubTotal());
}
return itemsTotal;
}
/**
* Get the total payment amount by payment type. Specify null to get amount
* over all types.
*/
public BigDecimal getOrderPaymentPreferenceTotalByType(String paymentMethodTypeId) {
BigDecimal total = BigDecimal.ZERO;
String thisPaymentMethodTypeId = null;
for (CartPaymentInfo payment : paymentInfo) {
if (payment.amount == null) continue;
if (payment.paymentMethodId != null) {
try {
// need to determine the payment method type from the payment method
GenericValue paymentMethod = this.getDelegator().findOne("PaymentMethod", UtilMisc.toMap("paymentMethodId", payment.paymentMethodId), true);
if (paymentMethod != null) {
thisPaymentMethodTypeId = paymentMethod.getString("paymentMethodTypeId");
}
} catch (GenericEntityException e) {
Debug.logError(e, e.getMessage(), module);
}
} else {
thisPaymentMethodTypeId = payment.paymentMethodTypeId;
}
// add the amount according to paymentMethodType
if (paymentMethodTypeId == null || paymentMethodTypeId.equals(thisPaymentMethodTypeId)) {
total = total.add(payment.amount);
}
}
return total;
}
public BigDecimal getCreditCardPaymentPreferenceTotal() {
return getOrderPaymentPreferenceTotalByType("CREDIT_CARD");
}
public BigDecimal getBillingAccountPaymentPreferenceTotal() {
return getOrderPaymentPreferenceTotalByType("EXT_BILLACT");
}
public BigDecimal getGiftCardPaymentPreferenceTotal() {
return getOrderPaymentPreferenceTotalByType("GIFT_CARD");
}
/** Add a contact mech to this purpose; the contactMechPurposeTypeId is required */
public void addContactMech(String contactMechPurposeTypeId, String contactMechId) {
if (contactMechPurposeTypeId == null) throw new IllegalArgumentException("You must specify a contactMechPurposeTypeId to add a ContactMech");
contactMechIdsMap.put(contactMechPurposeTypeId, contactMechId);
}
/** Get the contactMechId for this cart given the contactMechPurposeTypeId */
public String getContactMech(String contactMechPurposeTypeId) {
return contactMechIdsMap.get(contactMechPurposeTypeId);
}
/** Remove the contactMechId from this cart given the contactMechPurposeTypeId */
public String removeContactMech(String contactMechPurposeTypeId) {
return contactMechIdsMap.remove(contactMechPurposeTypeId);
}
public Map<String, String> getOrderContactMechIds() {
return this.contactMechIdsMap;
}
/** Get a List of adjustments on the order (ie cart) */
public List<GenericValue> getAdjustments() {
return adjustments;
}
public int getAdjustmentPromoIndex(String productPromoId) {
int index = adjustments.size();
while (index > 0) {
index--;
if (adjustments.get(index).getString("productPromoId").equals(productPromoId)) {
return(index);
}
}
return -1;
}
/** Add an adjustment to the order; don't worry about setting the orderId, orderItemSeqId or orderAdjustmentId; they will be set when the order is created */
public int addAdjustment(GenericValue adjustment) {
adjustments.add(adjustment);
return adjustments.indexOf(adjustment);
}
public void removeAdjustment(int index) {
adjustments.remove(index);
}
public GenericValue getAdjustment(int index) {
return adjustments.get(index);
}
/** Get a List of orderTerms on the order (ie cart) */
public List<GenericValue> getOrderTerms() {
return orderTerms;
}
/** Add an orderTerm to the order */
public int addOrderTerm(String termTypeId, BigDecimal termValue, Long termDays) {
return addOrderTerm(termTypeId, termValue, termDays, null);
}
/** Add an orderTerm to the order */
public int addOrderTerm(String termTypeId, BigDecimal termValue, Long termDays, String textValue) {
GenericValue orderTerm = this.getDelegator().makeValue("OrderTerm");
orderTerm.put("termTypeId", termTypeId);
orderTerm.put("termValue", termValue);
orderTerm.put("termDays", termDays);
orderTerm.put("textValue", textValue);
return addOrderTerm(orderTerm);
}
public int addOrderTerm(String termTypeId, String orderItemSeqId,BigDecimal termValue, Long termDays, String textValue, String description) {
GenericValue orderTerm = this.getDelegator().makeValue("OrderTerm");
orderTerm.put("termTypeId", termTypeId);
if (UtilValidate.isEmpty(orderItemSeqId)) {
orderItemSeqId = "_NA_";
}
orderTerm.put("orderItemSeqId", orderItemSeqId);
orderTerm.put("termValue", termValue);
orderTerm.put("termDays", termDays);
orderTerm.put("textValue", textValue);
orderTerm.put("description", description);
return addOrderTerm(orderTerm);
}
/** Add an orderTerm to the order */
public int addOrderTerm(GenericValue orderTerm) {
orderTerms.add(orderTerm);
return orderTerms.indexOf(orderTerm);
}
public void removeOrderTerm(int index) {
orderTerms.remove(index);
}
public void removeOrderTerms() {
orderTerms.clear();
}
public boolean isOrderTermSet() {
return orderTermSet;
}
public void setOrderTermSet(boolean orderTermSet) {
this.orderTermSet = orderTermSet;
}
public boolean hasOrderTerm(String termTypeId) {
if (termTypeId == null) {
return false;
}
for (GenericValue orderTerm : orderTerms) {
if (termTypeId.equals(orderTerm.getString("termTypeId"))) {
return true;
}
}
return false;
}
public boolean isReadOnlyCart() {
return readOnlyCart;
}
public void setReadOnlyCart(boolean readOnlyCart) {
this.readOnlyCart = readOnlyCart;
}
/** go through the order adjustments and remove all adjustments with the given type */
public void removeAdjustmentByType(String orderAdjustmentTypeId) {
if (orderAdjustmentTypeId == null) return;
// make a list of adjustment lists including the cart adjustments and the cartItem adjustments for each item
List<List<GenericValue>> adjsLists = new LinkedList<List<GenericValue>>();
adjsLists.add(this.getAdjustments());
for (ShoppingCartItem item : this) {
if (item.getAdjustments() != null) {
adjsLists.add(item.getAdjustments());
}
}
for (List<GenericValue> adjs: adjsLists) {
if (adjs != null) {
for (int i = 0; i < adjs.size();) {
GenericValue orderAdjustment = adjs.get(i);
if (orderAdjustmentTypeId.equals(orderAdjustment.getString("orderAdjustmentTypeId"))) {
adjs.remove(i);
} else {
i++;
}
}
}
}
}
/** Returns the total weight in the cart. */
public BigDecimal getTotalWeight() {
BigDecimal weight = BigDecimal.ZERO;
for (ShoppingCartItem item : this.cartLines) {
weight = weight.add(item.getWeight().multiply(item.getQuantity()));
}
return weight;
}
/** Returns the total quantity in the cart. */
public BigDecimal getTotalQuantity() {
BigDecimal count = BigDecimal.ZERO;
for (ShoppingCartItem item : this.cartLines) {
count = count.add(item.getQuantity());
}
return count;
}
/** Returns the SHIPPABLE item-total in the cart for a specific ship group. */
public BigDecimal getShippableTotal(int idx) {
CartShipInfo info = this.getShipInfo(idx);
BigDecimal itemTotal = BigDecimal.ZERO;
for (ShoppingCartItem item : info.shipItemInfo.keySet()) {
CartShipInfo.CartShipItemInfo csii = info.shipItemInfo.get(item);
if (csii != null && csii.quantity.compareTo(BigDecimal.ZERO) > 0) {
if (item.shippingApplies()) {
itemTotal = itemTotal.add(item.getItemSubTotal(csii.quantity));
}
}
}
return itemTotal;
}
/** Returns the total SHIPPABLE quantity in the cart for a specific ship group. */
public BigDecimal getShippableQuantity(int idx) {
CartShipInfo info = this.getShipInfo(idx);
BigDecimal count = BigDecimal.ZERO;
for (ShoppingCartItem item : info.shipItemInfo.keySet()) {
CartShipInfo.CartShipItemInfo csii = info.shipItemInfo.get(item);
if (csii != null && csii.quantity.compareTo(BigDecimal.ZERO) > 0) {
if (item.shippingApplies()) {
count = count.add(csii.quantity);
}
}
}
return count;
}
/** Returns the total SHIPPABLE weight in the cart for a specific ship group. */
public BigDecimal getShippableWeight(int idx) {
CartShipInfo info = this.getShipInfo(idx);
BigDecimal weight = BigDecimal.ZERO;
for (ShoppingCartItem item : info.shipItemInfo.keySet()) {
CartShipInfo.CartShipItemInfo csii = info.shipItemInfo.get(item);
if (csii != null && csii.quantity.compareTo(BigDecimal.ZERO) > 0) {
if (item.shippingApplies()) {
weight = weight.add(item.getWeight().multiply(csii.quantity));
}
}
}
return weight;
}
/** Returns a List of shippable item's size for a specific ship group. */
public List<BigDecimal> getShippableSizes(int idx) {
CartShipInfo info = this.getShipInfo(idx);
List<BigDecimal> shippableSizes = new LinkedList<BigDecimal>();
for (ShoppingCartItem item : info.shipItemInfo.keySet()) {
CartShipInfo.CartShipItemInfo csii = info.shipItemInfo.get(item);
if (csii != null && csii.quantity.compareTo(BigDecimal.ZERO) > 0) {
if (item.shippingApplies()) {
shippableSizes.add(item.getSize());
}
}
}
return shippableSizes;
}
/** Returns a List of shippable item info (quantity, size, weight) for a specific ship group */
public List<Map<String, Object>> getShippableItemInfo(int idx) {
CartShipInfo info = this.getShipInfo(idx);
List<Map<String, Object>> itemInfos = new LinkedList<Map<String,Object>>();
for (ShoppingCartItem item : info.shipItemInfo.keySet()) {
CartShipInfo.CartShipItemInfo csii = info.shipItemInfo.get(item);
if (csii != null && csii.quantity.compareTo(BigDecimal.ZERO) > 0) {
if (item.shippingApplies()) {
Map<String, Object> itemInfo = item.getItemProductInfo();
itemInfo.put("quantity", csii.quantity);
itemInfos.add(itemInfo);
}
}
}
return itemInfos;
}
/** Returns true when there are shippable items in the cart */
public boolean shippingApplies() {
boolean shippingApplies = false;
for (ShoppingCartItem item : this) {
if (item.shippingApplies()) {
shippingApplies = true;
break;
}
}
return shippingApplies;
}
/** Returns true when there are taxable items in the cart */
public boolean taxApplies() {
boolean taxApplies = false;
for (ShoppingCartItem item : this) {
if (item.taxApplies()) {
taxApplies = true;
break;
}
}
return taxApplies;
}
/** Returns a Map of all features applied to products in the cart with quantities for a specific ship group. */
public Map<String, BigDecimal> getFeatureIdQtyMap(int idx) {
CartShipInfo info = this.getShipInfo(idx);
Map<String, BigDecimal> featureMap = new HashMap<String, BigDecimal>();
for (ShoppingCartItem item : info.shipItemInfo.keySet()) {
CartShipInfo.CartShipItemInfo csii = info.shipItemInfo.get(item);
if (csii != null && csii.quantity.compareTo(BigDecimal.ZERO) > 0) {
featureMap.putAll(item.getFeatureIdQtyMap(csii.quantity));
}
}
return featureMap;
}
/** Returns true if the user wishes to view the cart everytime an item is added. */
public boolean viewCartOnAdd() {
return viewCartOnAdd;
}
/** Returns true if the user wishes to view the cart everytime an item is added. */
public void setViewCartOnAdd(boolean viewCartOnAdd) {
this.viewCartOnAdd = viewCartOnAdd;
}
/** Returns the order ID associated with this cart or null if no order has been created yet. */
public String getOrderId() {
return this.orderId;
}
/** Returns the first attempt order ID associated with this cart or null if no order has been created yet. */
public String getFirstAttemptOrderId() {
return this.firstAttemptOrderId;
}
/** Sets the orderId associated with this cart. */
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public void setNextItemSeq(long seq) throws GeneralException {
if (this.nextItemSeq != 1) {
throw new GeneralException("Cannot set the item sequence once the sequence has been incremented!");
} else {
this.nextItemSeq = seq;
}
}
/** TODO: Sets the first attempt orderId for this cart. */
public void setFirstAttemptOrderId(String orderId) {
this.firstAttemptOrderId = orderId;
}
public void removeAllFreeShippingProductPromoActions() {
this.freeShippingProductPromoActions.clear();
}
/** Removes a free shipping ProductPromoAction by trying to find one in the list with the same primary key. */
public void removeFreeShippingProductPromoAction(GenericPK productPromoActionPK) {
if (productPromoActionPK == null) return;
Iterator<GenericValue> fsppas = this.freeShippingProductPromoActions.iterator();
while (fsppas.hasNext()) {
if (productPromoActionPK.equals((fsppas.next()).getPrimaryKey())) {
fsppas.remove();
}
}
}
/** Adds a ProductPromoAction to be used for free shipping (must be of type free shipping, or nothing will be done). */
public void addFreeShippingProductPromoAction(GenericValue productPromoAction) {
if (productPromoAction == null) return;
// is this a free shipping action?
if (!"PROMO_FREE_SHIPPING".equals(productPromoAction.getString("productPromoActionEnumId"))) return; // Changed 1-5-04 by Si Chen
// to easily make sure that no duplicate exists, do a remove first
this.removeFreeShippingProductPromoAction(productPromoAction.getPrimaryKey());
this.freeShippingProductPromoActions.add(productPromoAction);
}
public List<GenericValue> getFreeShippingProductPromoActions() {
return this.freeShippingProductPromoActions;
}
public void removeAllDesiredAlternateGiftByActions() {
this.desiredAlternateGiftByAction.clear();
}
public void setDesiredAlternateGiftByAction(GenericPK productPromoActionPK, String productId) {
this.desiredAlternateGiftByAction.put(productPromoActionPK, productId);
}
public String getDesiredAlternateGiftByAction(GenericPK productPromoActionPK) {
return this.desiredAlternateGiftByAction.get(productPromoActionPK);
}
public Map<GenericPK, String> getAllDesiredAlternateGiftByActionCopy() {
return new HashMap<GenericPK, String>(this.desiredAlternateGiftByAction);
}
public void addProductPromoUse(String productPromoId, String productPromoCodeId, BigDecimal totalDiscountAmount, BigDecimal quantityLeftInActions, Map<ShoppingCartItem,BigDecimal> usageInfoMap) {
if (UtilValidate.isNotEmpty(productPromoCodeId) && !this.productPromoCodes.contains(productPromoCodeId)) {
throw new IllegalStateException("Cannot add a use to a promo code use for a code that has not been entered.");
}
if (Debug.verboseOn()) Debug.logVerbose("Used promotion [" + productPromoId + "] with code [" + productPromoCodeId + "] for total discount [" + totalDiscountAmount + "] and quantity left in actions [" + quantityLeftInActions + "]", module);
this.productPromoUseInfoList.add(new ProductPromoUseInfo(productPromoId, productPromoCodeId, totalDiscountAmount, quantityLeftInActions, usageInfoMap));
}
public void removeProductPromoUse(String productPromoId) {
if (!productPromoId.isEmpty()) {
int index = -1;
for (ProductPromoUseInfo productPromoUseInfo : this.productPromoUseInfoList) {
if (productPromoId.equals(productPromoUseInfo.productPromoId)) {
index = this.productPromoUseInfoList.indexOf(productPromoUseInfo);
break;
}
}
if (index != -1) {
this.productPromoUseInfoList.remove(index);
}
}
}
public void clearProductPromoUseInfo() {
// clear out info for general promo use
this.productPromoUseInfoList.clear();
}
public void clearCartItemUseInPromoInfo() {
// clear out info about which cart items have been used in promos
for (ShoppingCartItem cartLine : this) {
cartLine.clearPromoRuleUseInfo();
}
}
public Iterator<ProductPromoUseInfo> getProductPromoUseInfoIter() {
return productPromoUseInfoList.iterator();
}
public BigDecimal getProductPromoTotal() {
BigDecimal totalDiscount = BigDecimal.ZERO;
List<GenericValue> cartAdjustments = this.getAdjustments();
if (cartAdjustments != null) {
for (GenericValue checkOrderAdjustment : cartAdjustments) {
if (UtilValidate.isNotEmpty(checkOrderAdjustment.getString("productPromoId")) &&
UtilValidate.isNotEmpty(checkOrderAdjustment.getString("productPromoRuleId")) &&
UtilValidate.isNotEmpty(checkOrderAdjustment.getString("productPromoActionSeqId"))) {
if (checkOrderAdjustment.get("amount") != null) {
totalDiscount = totalDiscount.add(checkOrderAdjustment.getBigDecimal("amount"));
}
}
}
}
// add cart line adjustments from promo actions
for (ShoppingCartItem checkItem : this) {
Iterator<GenericValue> checkOrderAdjustments = UtilMisc.toIterator(checkItem.getAdjustments());
while (checkOrderAdjustments != null && checkOrderAdjustments.hasNext()) {
GenericValue checkOrderAdjustment = checkOrderAdjustments.next();
if (UtilValidate.isNotEmpty(checkOrderAdjustment.getString("productPromoId")) &&
UtilValidate.isNotEmpty(checkOrderAdjustment.getString("productPromoRuleId")) &&
UtilValidate.isNotEmpty(checkOrderAdjustment.getString("productPromoActionSeqId"))) {
if (checkOrderAdjustment.get("amount") != null) {
totalDiscount = totalDiscount.add(checkOrderAdjustment.getBigDecimal("amount"));
}
}
}
}
return totalDiscount;
}
/** Get total discount for a given ProductPromo, or for ANY ProductPromo if the passed in productPromoId is null. */
public BigDecimal getProductPromoUseTotalDiscount(String productPromoId) {
BigDecimal totalDiscount = BigDecimal.ZERO;
for (ProductPromoUseInfo productPromoUseInfo: this.productPromoUseInfoList) {
if (productPromoId == null || productPromoId.equals(productPromoUseInfo.productPromoId)) {
totalDiscount = totalDiscount.add(productPromoUseInfo.getTotalDiscountAmount());
}
}
return totalDiscount;
}
public int getProductPromoUseCount(String productPromoId) {
if (productPromoId == null) return 0;
int useCount = 0;
for (ProductPromoUseInfo productPromoUseInfo: this.productPromoUseInfoList) {
if (productPromoId.equals(productPromoUseInfo.productPromoId)) {
useCount++;
}
}
return useCount;
}
public int getProductPromoCodeUse(String productPromoCodeId) {
if (productPromoCodeId == null) return 0;
int useCount = 0;
for (ProductPromoUseInfo productPromoUseInfo: this.productPromoUseInfoList) {
if (productPromoCodeId.equals(productPromoUseInfo.productPromoCodeId)) {
useCount++;
}
}
return useCount;
}
public void clearAllPromotionInformation() {
this.clearAllPromotionAdjustments();
// remove all free shipping promo actions
this.removeAllFreeShippingProductPromoActions();
// clear promo uses & reset promo code uses, and reset info about cart items used for promos (ie qualifiers and benefiters)
this.clearProductPromoUseInfo();
this.clearCartItemUseInPromoInfo();
}
public void clearAllPromotionAdjustments() {
// remove cart adjustments from promo actions
List<GenericValue> cartAdjustments = this.getAdjustments();
if (cartAdjustments != null) {
Iterator<GenericValue> cartAdjustmentIter = cartAdjustments.iterator();
while (cartAdjustmentIter.hasNext()) {
GenericValue checkOrderAdjustment = cartAdjustmentIter.next();
if (UtilValidate.isNotEmpty(checkOrderAdjustment.getString("productPromoId")) &&
UtilValidate.isNotEmpty(checkOrderAdjustment.getString("productPromoRuleId")) &&
UtilValidate.isNotEmpty(checkOrderAdjustment.getString("productPromoActionSeqId"))) {
cartAdjustmentIter.remove();
}
}
}
// remove cart lines that are promos (ie GWPs) and cart line adjustments from promo actions
Iterator<ShoppingCartItem> cartItemIter = this.iterator();
while (cartItemIter.hasNext()) {
ShoppingCartItem checkItem = cartItemIter.next();
if (checkItem != null && checkItem.getIsPromo()) {
this.clearItemShipInfo(checkItem);
cartItemIter.remove();
} else {
// found a promo item with the productId, see if it has a matching adjustment on it
Iterator<GenericValue> checkOrderAdjustments = UtilMisc.toIterator(checkItem.getAdjustments());
while (checkOrderAdjustments != null && checkOrderAdjustments.hasNext()) {
GenericValue checkOrderAdjustment = checkOrderAdjustments.next();
if (UtilValidate.isNotEmpty(checkOrderAdjustment.getString("productPromoId")) &&
UtilValidate.isNotEmpty(checkOrderAdjustment.getString("productPromoRuleId")) &&
UtilValidate.isNotEmpty(checkOrderAdjustment.getString("productPromoActionSeqId"))) {
checkOrderAdjustments.remove();
}
}
}
}
}
public void clearAllAdjustments() {
// remove all the promotion information (including adjustments)
clearAllPromotionInformation();
// remove all cart adjustments
this.adjustments.clear();
// remove all cart item adjustments
for (ShoppingCartItem checkItem : this) {
checkItem.getAdjustments().clear();
}
}
public void clearAllItemStatus() {
for (ShoppingCartItem item : this) {
item.setStatusId(null);
}
}
/** Adds a promotion code to the cart, checking if it is valid. If it is valid this will return null, otherwise it will return a message stating why it was not valid
* @param productPromoCodeId The promotion code to check and add
* @return String that is null if valid, and added to cart, or an error message of the code was not valid and not added to the cart.
*/
public String addProductPromoCode(String productPromoCodeId, LocalDispatcher dispatcher) {
if (this.productPromoCodes.contains(productPromoCodeId)) {
return UtilProperties.getMessage(resource_error, "productpromoworker.promotion_code_already_been_entered", UtilMisc.toMap("productPromoCodeId", productPromoCodeId), locale);
}
if (!this.getDoPromotions()) {
this.productPromoCodes.add(productPromoCodeId);
return null;
}
// if the promo code requires it make sure the code is valid
String checkResult = ProductPromoWorker.checkCanUsePromoCode(productPromoCodeId, this.getPartyId(), this.getDelegator(), this, locale);
if (checkResult == null) {
this.productPromoCodes.add(productPromoCodeId);
// new promo code, re-evaluate promos
ProductPromoWorker.doPromotions(this, dispatcher);
return null;
} else {
return checkResult;
}
}
public Set<String> getProductPromoCodesEntered() {
return this.productPromoCodes;
}
public synchronized void resetPromoRuleUse(String productPromoId, String productPromoRuleId) {
for (ShoppingCartItem cartItem : this) {
cartItem.resetPromoRuleUse(productPromoId, productPromoRuleId);
}
}
public synchronized void confirmPromoRuleUse(String productPromoId, String productPromoRuleId) {
for (ShoppingCartItem cartItem : this) {
cartItem.confirmPromoRuleUse(productPromoId, productPromoRuleId);
}
}
/**
* Associates a party with a role to the order.
* @param partyId identifier of the party to associate to order
* @param roleTypeId identifier of the role used in party-order association
*/
public void addAdditionalPartyRole(String partyId, String roleTypeId) {
// search if there is an existing entry
List<String> parties = additionalPartyRole.get(roleTypeId);
if (parties != null) {
for (String pi : parties) {
if (pi.equals(partyId)) {
return;
}
}
} else {
parties = new LinkedList<String>();
additionalPartyRole.put(roleTypeId, parties);
}
parties.add(0, partyId);
}
/**
* Removes a previously associated party to the order.
* @param partyId identifier of the party to associate to order
* @param roleTypeId identifier of the role used in party-order association
*/
public void removeAdditionalPartyRole(String partyId, String roleTypeId) {
List<String> parties = additionalPartyRole.get(roleTypeId);
if (parties != null) {
Iterator<String> it = parties.iterator();
while (it.hasNext()) {
if ((it.next()).equals(partyId)) {
it.remove();
if (parties.isEmpty()) {
additionalPartyRole.remove(roleTypeId);
}
return;
}
}
}
}
public Map<String, List<String>> getAdditionalPartyRoleMap() {
return additionalPartyRole;
}
// =======================================================================
// Methods used for order creation
// =======================================================================
/**
* Returns the Id of an AGGREGATED_CONF product having exact configId.
* If AGGREGATED_CONF product do not exist, creates one, associates it to the AGGREGATED product, and copy its production run template.
* @param item
* @param dispatcher
*/
public String getAggregatedInstanceId (ShoppingCartItem item, LocalDispatcher dispatcher) {
if (UtilValidate.isEmpty(item.getConfigWrapper()) || UtilValidate.isEmpty(item.getConfigWrapper().getConfigId())) {
return null;
}
String newProductId = null;
String configId = item.getConfigWrapper().getConfigId();
try {
//first search for existing productId
newProductId = ProductWorker.getAggregatedInstanceId(getDelegator(), item.getProductId(), configId);
if (newProductId != null) {
return newProductId;
}
Delegator delegator = this.getDelegator();
//create new product and associate it
GenericValue product = item.getProduct();
String productName = product.getString("productName");
String description = product.getString("description");
Map<String, Object> serviceContext = new HashMap<String, Object>();
GenericValue permUserLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
String internalName = item.getProductId() + "_" + configId;
serviceContext.put("internalName", internalName);
serviceContext.put("productName", productName);
serviceContext.put("description", description);
if(ProductWorker.isAggregateService(delegator, item.getProductId())) {
serviceContext.put("productTypeId", "AGGREGATEDSERV_CONF");
}
else {
serviceContext.put("productTypeId", "AGGREGATED_CONF");
}
serviceContext.put("configId", configId);
if (UtilValidate.isNotEmpty(product.getString("requirementMethodEnumId"))) {
serviceContext.put("requirementMethodEnumId", product.getString("requirementMethodEnumId"));
}
serviceContext.put("userLogin", permUserLogin);
Map<String, Object> result = dispatcher.runSync("createProduct", serviceContext);
if (ServiceUtil.isError(result)) {
Debug.logError(ServiceUtil.getErrorMessage(result), module);
return null;
}
serviceContext.clear();
newProductId = (String) result.get("productId");
serviceContext.put("productId", item.getProductId());
serviceContext.put("productIdTo", newProductId);
serviceContext.put("productAssocTypeId", "PRODUCT_CONF");
serviceContext.put("fromDate", UtilDateTime.nowTimestamp());
serviceContext.put("userLogin", permUserLogin);
result = dispatcher.runSync("createProductAssoc", serviceContext);
if (ServiceUtil.isError(result)) {
Debug.logError(ServiceUtil.getErrorMessage(result), module);
return null;
}
//create a new WorkEffortGoodStandard based on existing one of AGGREGATED product .
//Another approach could be to get WorkEffortGoodStandard of the AGGREGATED product while creating production run.
GenericValue productionRunTemplate = EntityQuery.use(delegator).from("WorkEffortGoodStandard").where("productId", item.getProductId(), "workEffortGoodStdTypeId", "ROU_PROD_TEMPLATE", "statusId", "WEGS_CREATED").filterByDate().queryFirst();
if (productionRunTemplate != null) {
serviceContext.clear();
serviceContext.put("workEffortId", productionRunTemplate.getString("workEffortId"));
serviceContext.put("productId", newProductId);
serviceContext.put("workEffortGoodStdTypeId", "ROU_PROD_TEMPLATE");
serviceContext.put("statusId", "WEGS_CREATED");
serviceContext.put("userLogin", permUserLogin);
result = dispatcher.runSync("createWorkEffortGoodStandard", serviceContext);
if (ServiceUtil.isError(result)) {
Debug.logError(ServiceUtil.getErrorMessage(result), module);
return null;
}
}
} catch (GenericEntityException gse) {
Debug.logError(gse, module);
return null;
} catch (GenericServiceException gse) {
Debug.logError(gse, module);
return null;
} catch (Exception e) {
Debug.logError(e, module);
return null;
}
return newProductId;
}
public List<GenericValue> makeOrderItemGroups() {
List<GenericValue> result = new LinkedList<GenericValue>();
for (ShoppingCart.ShoppingCartItemGroup itemGroup : this.itemGroupByNumberMap.values()) {
result.add(itemGroup.makeOrderItemGroup(this.getDelegator()));
}
return result;
}
private void explodeItems(LocalDispatcher dispatcher) {
if (dispatcher == null) return;
synchronized (cartLines) {
List<ShoppingCartItem> cartLineItems = new LinkedList<ShoppingCartItem>(cartLines);
for (ShoppingCartItem item : cartLineItems) {
try {
int thisIndex = items().indexOf(item);
List<ShoppingCartItem> explodedItems = item.explodeItem(this, dispatcher);
// Add exploded items into cart with order item sequence id and item ship group quantity
for (ShoppingCartItem explodedItem : explodedItems) {
String orderItemSeqId = UtilFormatOut.formatPaddedNumber(nextItemSeq, 5);
explodedItem.setOrderItemSeqId(orderItemSeqId);
addItemToEnd(explodedItem);
setItemShipGroupQty(explodedItem, BigDecimal.ONE, thisIndex);
nextItemSeq++;
}
} catch (CartItemModifyException e) {
Debug.logError(e, "Problem exploding item! Item not exploded.", module);
}
}
}
}
/**
* Does an "explode", or "unitize" operation on a list of cart items.
* Resulting state for each item with quantity X is X items of quantity 1.
*
* @param shoppingCartItems
* @param dispatcher
*/
public void explodeItems(List<ShoppingCartItem> shoppingCartItems, LocalDispatcher dispatcher) {
if (dispatcher == null) return;
synchronized (cartLines) {
for (ShoppingCartItem item : shoppingCartItems) {
try {
int thisIndex = items().indexOf(item);
List<ShoppingCartItem> explodedItems = item.explodeItem(this, dispatcher);
// Add exploded items into cart with order item sequence id and item ship group quantity
for (ShoppingCartItem explodedItem : explodedItems) {
String orderItemSeqId = UtilFormatOut.formatPaddedNumber(nextItemSeq, 5);
explodedItem.setOrderItemSeqId(orderItemSeqId);
addItemToEnd(explodedItem);
setItemShipGroupQty(explodedItem, BigDecimal.ONE, thisIndex);
nextItemSeq++;
}
} catch (CartItemModifyException e) {
Debug.logError(e, "Problem exploding (unitizing) item! Item not exploded.", module);
}
}
}
}
public List<GenericValue> makeOrderItems() {
return makeOrderItems(false, false, null);
}
public List<GenericValue> makeOrderItems(boolean explodeItems, boolean replaceAggregatedId, LocalDispatcher dispatcher) {
// do the explosion
if (explodeItems && dispatcher != null) {
explodeItems(dispatcher);
}
// now build the lines
synchronized (cartLines) {
List<GenericValue> result = new LinkedList<GenericValue>();
for (ShoppingCartItem item : cartLines) {
if (UtilValidate.isEmpty(item.getOrderItemSeqId())) {
String orderItemSeqId = UtilFormatOut.formatPaddedNumber(nextItemSeq, 5);
item.setOrderItemSeqId(orderItemSeqId);
nextItemSeq++;
} else {
try {
int thisSeqId = Integer.parseInt(item.getOrderItemSeqId());
if (thisSeqId > nextItemSeq) {
nextItemSeq = thisSeqId + 1;
}
} catch (NumberFormatException e) {
Debug.logError(e, module);
}
}
// the initial status for all item types
String initialStatus = "ITEM_CREATED";
String status = item.getStatusId();
if (status == null) {
status = initialStatus;
}
//check for aggregated products
String aggregatedInstanceId = null;
if (replaceAggregatedId && UtilValidate.isNotEmpty(item.getConfigWrapper())) {
aggregatedInstanceId = getAggregatedInstanceId(item, dispatcher);
}
GenericValue orderItem = getDelegator().makeValue("OrderItem");
orderItem.set("orderItemSeqId", item.getOrderItemSeqId());
orderItem.set("externalId", item.getExternalId());
orderItem.set("orderItemTypeId", item.getItemType());
if (item.getItemGroup() != null) orderItem.set("orderItemGroupSeqId", item.getItemGroup().getGroupNumber());
orderItem.set("productId", UtilValidate.isNotEmpty(aggregatedInstanceId) ? aggregatedInstanceId : item.getProductId());
orderItem.set("supplierProductId", item.getSupplierProductId());
orderItem.set("prodCatalogId", item.getProdCatalogId());
orderItem.set("productCategoryId", item.getProductCategoryId());
orderItem.set("quantity", item.getQuantity());
orderItem.set("selectedAmount", item.getSelectedAmount());
orderItem.set("unitPrice", item.getBasePrice());
orderItem.set("unitListPrice", item.getListPrice());
orderItem.set("isModifiedPrice",item.getIsModifiedPrice() ? "Y" : "N");
orderItem.set("isPromo", item.getIsPromo() ? "Y" : "N");
orderItem.set("shoppingListId", item.getShoppingListId());
orderItem.set("shoppingListItemSeqId", item.getShoppingListItemSeqId());
orderItem.set("itemDescription", item.getName(dispatcher));
orderItem.set("comments", item.getItemComment());
orderItem.set("estimatedDeliveryDate", item.getDesiredDeliveryDate());
orderItem.set("correspondingPoId", this.getPoNumber());
orderItem.set("quoteId", item.getQuoteId());
orderItem.set("quoteItemSeqId", item.getQuoteItemSeqId());
orderItem.set("statusId", status);
orderItem.set("shipBeforeDate", item.getShipBeforeDate());
orderItem.set("shipAfterDate", item.getShipAfterDate());
orderItem.set("estimatedShipDate", item.getEstimatedShipDate());
orderItem.set("cancelBackOrderDate", item.getCancelBackOrderDate());
if (this.getUserLogin() != null) {
orderItem.set("changeByUserLoginId", this.getUserLogin().get("userLoginId"));
}
String fromInventoryItemId = (String) item.getAttribute("fromInventoryItemId");
if (fromInventoryItemId != null) {
orderItem.set("fromInventoryItemId", fromInventoryItemId);
}
result.add(orderItem);
// don't do anything with adjustments here, those will be added below in makeAllAdjustments
}
return result;
}
}
/** create WorkEfforts from the shoppingcart items when itemType = RENTAL_ORDER_ITEM */
public List<GenericValue> makeWorkEfforts() {
List<GenericValue> allWorkEfforts = new LinkedList<GenericValue>();
for (ShoppingCartItem item : cartLines) {
if ("RENTAL_ORDER_ITEM".equals(item.getItemType())) { // prepare workeffort when the order item is a rental item
GenericValue workEffort = getDelegator().makeValue("WorkEffort");
workEffort.set("workEffortId",item.getOrderItemSeqId()); // fill temporary with sequence number
workEffort.set("estimatedStartDate",item.getReservStart());
workEffort.set("estimatedCompletionDate",item.getReservStart(item.getReservLength()));
workEffort.set("reservPersons", item.getReservPersons());
workEffort.set("reserv2ndPPPerc", item.getReserv2ndPPPerc());
workEffort.set("reservNthPPPerc", item.getReservNthPPPerc());
workEffort.set("accommodationMapId", item.getAccommodationMapId());
workEffort.set("accommodationSpotId",item.getAccommodationSpotId());
allWorkEfforts.add(workEffort);
}
}
return allWorkEfforts;
}
/** make a list of all adjustments including order adjustments, order line adjustments, and special adjustments (shipping and tax if applicable) */
public List<GenericValue> makeAllAdjustments() {
List<GenericValue> allAdjs = new LinkedList<GenericValue>();
// before returning adjustments, go through them to find all that need counter adjustments (for instance: free shipping)
for (GenericValue orderAdjustment: this.getAdjustments()) {
allAdjs.add(orderAdjustment);
if ("SHIPPING_CHARGES".equals(orderAdjustment.get("orderAdjustmentTypeId"))) {
Iterator<GenericValue> fsppas = this.freeShippingProductPromoActions.iterator();
while (fsppas.hasNext()) {
// TODO - we need to change the way free shipping promotions work
}
}
}
// add all of the item adjustments to this list too
for (ShoppingCartItem item : cartLines) {
Collection<GenericValue> adjs = item.getAdjustments();
if (adjs != null) {
for (GenericValue orderAdjustment: adjs) {
orderAdjustment.set("orderItemSeqId", item.getOrderItemSeqId());
allAdjs.add(orderAdjustment);
if ("SHIPPING_CHARGES".equals(orderAdjustment.get("orderAdjustmentTypeId"))) {
Iterator<GenericValue> fsppas = this.freeShippingProductPromoActions.iterator();
while (fsppas.hasNext()) {
// TODO - fix the free shipping promotions!!
}
}
}
}
}
return allAdjs;
}
/** make a list of all quote adjustments including header adjustments, line adjustments, and special adjustments (shipping and tax if applicable).
* Internally, the quote adjustments are created from the order adjustments.
*/
public List<GenericValue> makeAllQuoteAdjustments() {
List<GenericValue> quoteAdjs = new LinkedList<GenericValue>();
for (GenericValue orderAdj: makeAllAdjustments()) {
GenericValue quoteAdj = this.getDelegator().makeValue("QuoteAdjustment");
quoteAdj.put("quoteAdjustmentId", orderAdj.get("orderAdjustmentId"));
quoteAdj.put("quoteAdjustmentTypeId", orderAdj.get("orderAdjustmentTypeId"));
quoteAdj.put("quoteItemSeqId", orderAdj.get("orderItemSeqId"));
quoteAdj.put("comments", orderAdj.get("comments"));
quoteAdj.put("description", orderAdj.get("description"));
quoteAdj.put("amount", orderAdj.get("amount"));
quoteAdj.put("productPromoId", orderAdj.get("productPromoId"));
quoteAdj.put("productPromoRuleId", orderAdj.get("productPromoRuleId"));
quoteAdj.put("productPromoActionSeqId", orderAdj.get("productPromoActionSeqId"));
quoteAdj.put("productFeatureId", orderAdj.get("productFeatureId"));
quoteAdj.put("correspondingProductId", orderAdj.get("correspondingProductId"));
quoteAdj.put("sourceReferenceId", orderAdj.get("sourceReferenceId"));
quoteAdj.put("sourcePercentage", orderAdj.get("sourcePercentage"));
quoteAdj.put("customerReferenceId", orderAdj.get("customerReferenceId"));
quoteAdj.put("primaryGeoId", orderAdj.get("primaryGeoId"));
quoteAdj.put("secondaryGeoId", orderAdj.get("secondaryGeoId"));
quoteAdj.put("exemptAmount", orderAdj.get("exemptAmount"));
quoteAdj.put("taxAuthGeoId", orderAdj.get("taxAuthGeoId"));
quoteAdj.put("taxAuthPartyId", orderAdj.get("taxAuthPartyId"));
quoteAdj.put("overrideGlAccountId", orderAdj.get("overrideGlAccountId"));
quoteAdj.put("includeInTax", orderAdj.get("includeInTax"));
quoteAdj.put("includeInShipping", orderAdj.get("includeInShipping"));
quoteAdj.put("createdDate", orderAdj.get("createdDate"));
quoteAdj.put("createdByUserLogin", orderAdj.get("createdByUserLogin"));
quoteAdjs.add(quoteAdj);
}
return quoteAdjs;
}
/** make a list of all OrderPaymentPreferences and Billing info including all payment methods and types */
public List<GenericValue> makeAllOrderPaymentInfos(LocalDispatcher dispatcher) {
Delegator delegator = this.getDelegator();
List<GenericValue> allOpPrefs = new LinkedList<GenericValue>();
BigDecimal remainingAmount = this.getGrandTotal().subtract(this.getPaymentTotal());
remainingAmount = remainingAmount.setScale(2, BigDecimal.ROUND_HALF_UP);
if (getBillingAccountId() != null && this.billingAccountAmt.compareTo(BigDecimal.ZERO) <= 0) {
BigDecimal billingAccountAvailableAmount = CheckOutHelper.availableAccountBalance(getBillingAccountId(), dispatcher);
if (this.billingAccountAmt.compareTo(BigDecimal.ZERO) == 0 && billingAccountAvailableAmount.compareTo(BigDecimal.ZERO) > 0) {
this.billingAccountAmt = billingAccountAvailableAmount;
}
if (remainingAmount.compareTo(getBillingAccountAmount()) < 0) {
this.billingAccountAmt = remainingAmount;
}
if (billingAccountAvailableAmount.compareTo(getBillingAccountAmount()) < 0) {
this.billingAccountAmt = billingAccountAvailableAmount;
}
}
for (CartPaymentInfo inf : paymentInfo) {
if (inf.amount == null) {
inf.amount = remainingAmount;
remainingAmount = BigDecimal.ZERO;
}
allOpPrefs.addAll(inf.makeOrderPaymentInfos(delegator, this));
}
return allOpPrefs;
}
/** make a list of OrderItemPriceInfos from the ShoppingCartItems */
public List<GenericValue> makeAllOrderItemPriceInfos() {
List<GenericValue> allInfos = new LinkedList<GenericValue>();
// add all of the item adjustments to this list too
for (ShoppingCartItem item : cartLines) {
Collection<GenericValue> infos = item.getOrderItemPriceInfos();
if (infos != null) {
for (GenericValue orderItemPriceInfo : infos) {
orderItemPriceInfo.set("orderItemSeqId", item.getOrderItemSeqId());
allInfos.add(orderItemPriceInfo);
}
}
}
return allInfos;
}
public List<GenericValue> makeProductPromoUses() {
List<GenericValue> productPromoUses = new LinkedList<GenericValue>();
String partyId = this.getPartyId();
int sequenceValue = 0;
for (ProductPromoUseInfo productPromoUseInfo: this.productPromoUseInfoList) {
GenericValue productPromoUse = this.getDelegator().makeValue("ProductPromoUse");
productPromoUse.set("promoSequenceId", UtilFormatOut.formatPaddedNumber(sequenceValue, 5));
productPromoUse.set("productPromoId", productPromoUseInfo.getProductPromoId());
productPromoUse.set("productPromoCodeId", productPromoUseInfo.getProductPromoCodeId());
productPromoUse.set("totalDiscountAmount", productPromoUseInfo.getTotalDiscountAmount());
productPromoUse.set("quantityLeftInActions", productPromoUseInfo.getQuantityLeftInActions());
productPromoUse.set("partyId", partyId);
productPromoUses.add(productPromoUse);
sequenceValue++;
}
return productPromoUses;
}
/** make a list of SurveyResponse object to update with order information set */
public List<GenericValue> makeAllOrderItemSurveyResponses() {
List<GenericValue> allInfos = new LinkedList<GenericValue>();
for (ShoppingCartItem item : this) {
List<String> responses = UtilGenerics.checkList(item.getAttribute("surveyResponses"));
GenericValue response = null;
if (responses != null) {
for (String responseId : responses) {
try {
response = this.getDelegator().findOne("SurveyResponse", UtilMisc.toMap("surveyResponseId", responseId), false);
} catch (GenericEntityException e) {
Debug.logError(e, "Unable to obtain SurveyResponse record for ID : " + responseId, module);
}
}
// this case is executed when user selects "Create as new Order" for Gift cards
} else {
String surveyResponseId = (String) item.getAttribute("surveyResponseId");
try {
response = this.getDelegator().findOne("SurveyResponse", UtilMisc.toMap("surveyResponseId", surveyResponseId), false);
} catch (GenericEntityException e) {
Debug.logError(e, "Unable to obtain SurveyResponse record for ID : " + surveyResponseId, module);
}
}
if (response != null) {
response.set("orderItemSeqId", item.getOrderItemSeqId());
allInfos.add(response);
}
}
return allInfos;
}
/** make a list of OrderContactMechs from the ShoppingCart and the ShoppingCartItems */
public List<GenericValue> makeAllOrderContactMechs() {
List<GenericValue> allOrderContactMechs = new LinkedList<GenericValue>();
Map<String, String> contactMechIds = this.getOrderContactMechIds();
if (contactMechIds != null) {
for (Map.Entry<String, String> entry : contactMechIds.entrySet()) {
GenericValue orderContactMech = getDelegator().makeValue("OrderContactMech");
orderContactMech.set("contactMechPurposeTypeId", entry.getKey());
orderContactMech.set("contactMechId", entry.getValue());
allOrderContactMechs.add(orderContactMech);
}
}
return allOrderContactMechs;
}
/** make a list of OrderContactMechs from the ShoppingCart and the ShoppingCartItems */
public List<GenericValue> makeAllOrderItemContactMechs() {
List<GenericValue> allOrderContactMechs = new LinkedList<GenericValue>();
for (ShoppingCartItem item : cartLines) {
Map<String, String> itemContactMechIds = item.getOrderItemContactMechIds();
if (itemContactMechIds != null) {
for (Map.Entry<String, String> entry: itemContactMechIds.entrySet()) {
GenericValue orderContactMech = getDelegator().makeValue("OrderItemContactMech");
orderContactMech.set("contactMechPurposeTypeId", entry.getKey());
orderContactMech.set("contactMechId", entry.getValue());
orderContactMech.set("orderItemSeqId", item.getOrderItemSeqId());
allOrderContactMechs.add(orderContactMech);
}
}
}
return allOrderContactMechs;
}
public List<GenericValue> makeAllShipGroupInfos() {
List<GenericValue> groups = new LinkedList<GenericValue>();
long seqId = 1;
for (CartShipInfo csi : this.shipInfo) {
String shipGroupSeqId = csi.shipGroupSeqId;
if (shipGroupSeqId != null) {
groups.addAll(csi.makeItemShipGroupAndAssoc(this.getDelegator(), this, shipGroupSeqId));
} else {
groups.addAll(csi.makeItemShipGroupAndAssoc(this.getDelegator(), this, UtilFormatOut.formatPaddedNumber(seqId, 5), true));
}
seqId++;
}
return groups;
}
public int getShipInfoSize() {
return this.shipInfo.size();
}
public List<GenericValue> makeAllOrderItemAttributes() {
return makeAllOrderItemAttributes(null, ALL);
}
public List<GenericValue> makeAllOrderItemAttributes(String orderId, int mode) {
// now build order item attributes
synchronized (cartLines) {
List<GenericValue> result = new LinkedList<GenericValue>();
for (ShoppingCartItem item : cartLines) {
Map<String, String> orderItemAttributes = item.getOrderItemAttributes();
for (String key : orderItemAttributes.keySet()) {
String value = orderItemAttributes.get(key);
if (ALL == mode || (FILLED_ONLY == mode && UtilValidate.isNotEmpty(value)) || (EMPTY_ONLY == mode && UtilValidate.isEmpty(value))
|| (mode != ALL && mode != FILLED_ONLY && mode != EMPTY_ONLY)) {
GenericValue orderItemAttribute = getDelegator().makeValue("OrderItemAttribute");
if (UtilValidate.isNotEmpty(orderId)) {
orderItemAttribute.set("orderId", orderId);
}
orderItemAttribute.set("orderItemSeqId", item.getOrderItemSeqId());
orderItemAttribute.set("attrName", key);
orderItemAttribute.set("attrValue", value);
result.add(orderItemAttribute);
}
}
}
return result;
}
}
public List<GenericValue> makeAllOrderAttributes() {
return makeAllOrderAttributes(null, ALL);
}
public List<GenericValue> makeAllOrderAttributes(String orderId, int mode) {
List<GenericValue> allOrderAttributes = new LinkedList<GenericValue>();
for (Map.Entry<String, String> entry: orderAttributes.entrySet()) {
GenericValue orderAtt = this.getDelegator().makeValue("OrderAttribute");
if (UtilValidate.isNotEmpty(orderId)) {
orderAtt.set("orderId", orderId);
}
String key = entry.getKey();
String value = entry.getValue();
orderAtt.put("attrName", key);
orderAtt.put("attrValue", value);
switch (mode) {
case ALL:
allOrderAttributes.add(orderAtt);
break;
case FILLED_ONLY:
if (UtilValidate.isNotEmpty(value)) {
allOrderAttributes.add(orderAtt);
}
break;
case EMPTY_ONLY:
if (UtilValidate.isEmpty(value)) {
allOrderAttributes.add(orderAtt);
}
break;
default:
allOrderAttributes.add(orderAtt);
break;
}
}
return allOrderAttributes;
}
public List<GenericValue> makeAllOrderItemAssociations() {
List<GenericValue> allOrderItemAssociations = new LinkedList<GenericValue>();
for (CartShipInfo csi : shipInfo) {
Set<ShoppingCartItem> items = csi.getShipItems();
for (ShoppingCartItem item : items) {
String requirementId = item.getRequirementId();
if (requirementId != null) {
try {
// TODO: multiple commitments for the same requirement are still not supported
GenericValue commitment = EntityQuery.use(getDelegator())
.from("OrderRequirementCommitment")
.where("requirementId", requirementId)
.queryFirst();
if (commitment != null) {
GenericValue orderItemAssociation = getDelegator().makeValue("OrderItemAssoc");
orderItemAssociation.set("orderId", commitment.getString("orderId"));
orderItemAssociation.set("orderItemSeqId", commitment.getString("orderItemSeqId"));
orderItemAssociation.set("shipGroupSeqId", "_NA_");
orderItemAssociation.set("toOrderItemSeqId", item.getOrderItemSeqId());
orderItemAssociation.set("toShipGroupSeqId", "_NA_");
orderItemAssociation.set("orderItemAssocTypeId", "PURCHASE_ORDER");
allOrderItemAssociations.add(orderItemAssociation);
}
} catch (GenericEntityException e) {
Debug.logError(e, "Unable to load OrderRequirementCommitment records for requirement ID : " + requirementId, module);
}
}
if (item.getAssociatedOrderId() != null && item.getAssociatedOrderItemSeqId() != null) {
GenericValue orderItemAssociation = getDelegator().makeValue("OrderItemAssoc");
orderItemAssociation.set("orderId", item.getAssociatedOrderId());
orderItemAssociation.set("orderItemSeqId", item.getAssociatedOrderItemSeqId());
orderItemAssociation.set("shipGroupSeqId", csi.getAssociatedShipGroupSeqId() != null ? csi.getAssociatedShipGroupSeqId() : "_NA_");
orderItemAssociation.set("toOrderItemSeqId", item.getOrderItemSeqId());
orderItemAssociation.set("toShipGroupSeqId", csi.getShipGroupSeqId() != null ? csi.getShipGroupSeqId() : "_NA_");
orderItemAssociation.set("orderItemAssocTypeId", item.getOrderItemAssocTypeId());
allOrderItemAssociations.add(orderItemAssociation);
}
}
}
return allOrderItemAssociations;
}
/** Returns a Map of cart values to pass to the storeOrder service */
public Map<String, Object> makeCartMap(LocalDispatcher dispatcher, boolean explodeItems) {
Map<String, Object> result = new HashMap<String, Object>();
result.put("orderTypeId", this.getOrderType());
result.put("orderName", this.getOrderName());
result.put("externalId", this.getExternalId());
result.put("orderDate", this.getOrderDate());
result.put("internalCode", this.getInternalCode());
result.put("salesChannelEnumId", this.getChannelType());
result.put("orderItemGroups", this.makeOrderItemGroups());
result.put("orderItems", this.makeOrderItems(explodeItems, Boolean.TRUE, dispatcher));
result.put("workEfforts", this.makeWorkEfforts());
result.put("orderAdjustments", this.makeAllAdjustments());
result.put("orderTerms", this.getOrderTerms());
result.put("orderItemPriceInfos", this.makeAllOrderItemPriceInfos());
result.put("orderProductPromoUses", this.makeProductPromoUses());
result.put("orderProductPromoCodes", this.getProductPromoCodesEntered());
result.put("orderAttributes", this.makeAllOrderAttributes());
result.put("orderItemAttributes", this.makeAllOrderItemAttributes());
result.put("orderContactMechs", this.makeAllOrderContactMechs());
result.put("orderItemContactMechs", this.makeAllOrderItemContactMechs());
result.put("orderPaymentInfo", this.makeAllOrderPaymentInfos(dispatcher));
result.put("orderItemShipGroupInfo", this.makeAllShipGroupInfos());
result.put("orderItemSurveyResponses", this.makeAllOrderItemSurveyResponses());
result.put("orderAdditionalPartyRoleMap", this.getAdditionalPartyRoleMap());
result.put("orderItemAssociations", this.makeAllOrderItemAssociations());
result.put("orderInternalNotes", this.getInternalOrderNotes());
result.put("orderNotes", this.getOrderNotes());
result.put("firstAttemptOrderId", this.getFirstAttemptOrderId());
result.put("currencyUom", this.getCurrency());
result.put("billingAccountId", this.getBillingAccountId());
result.put("partyId", this.getPartyId());
result.put("productStoreId", this.getProductStoreId());
result.put("transactionId", this.getTransactionId());
result.put("originFacilityId", this.getFacilityId());
result.put("terminalId", this.getTerminalId());
result.put("workEffortId", this.getWorkEffortId());
result.put("autoOrderShoppingListId", this.getAutoOrderShoppingListId());
result.put("billToCustomerPartyId", this.getBillToCustomerPartyId());
result.put("billFromVendorPartyId", this.getBillFromVendorPartyId());
if (this.isSalesOrder()) {
result.put("placingCustomerPartyId", this.getPlacingCustomerPartyId());
result.put("shipToCustomerPartyId", this.getShipToCustomerPartyId());
result.put("endUserCustomerPartyId", this.getEndUserCustomerPartyId());
}
if (this.isPurchaseOrder()) {
result.put("shipFromVendorPartyId", this.getShipFromVendorPartyId());
result.put("supplierAgentPartyId", this.getSupplierAgentPartyId());
}
return result;
}
public List<ShoppingCartItem> getLineListOrderedByBasePrice(boolean ascending) {
List<ShoppingCartItem> result = new ArrayList<ShoppingCartItem>(this.cartLines);
Collections.sort(result, new BasePriceOrderComparator(ascending));
return result;
}
public TreeMap<Integer, CartShipInfo> getShipGroupsBySupplier(String supplierPartyId) {
TreeMap<Integer, CartShipInfo> shipGroups = new TreeMap<Integer, CartShipInfo>();
for (int i = 0; i < this.shipInfo.size(); i++) {
CartShipInfo csi = shipInfo.get(i);
if ((csi.supplierPartyId == null && supplierPartyId == null) ||
(UtilValidate.isNotEmpty(csi.supplierPartyId) && csi.supplierPartyId.equals(supplierPartyId))) {
shipGroups.put(Integer.valueOf(i), csi);
}
}
return shipGroups;
}
/**
* Examine each item of each ship group and create new ship groups if the item should be drop shipped
* @param dispatcher
* @throws CartItemModifyException
*/
public void createDropShipGroups(LocalDispatcher dispatcher) throws CartItemModifyException {
// Retrieve the facilityId from the cart's productStoreId because ShoppingCart.setFacilityId() doesn't seem to be used anywhere
String facilityId = null;
if (UtilValidate.isNotEmpty(this.getProductStoreId())) {
try {
GenericValue productStore = this.getDelegator().findOne("ProductStore", UtilMisc.toMap("productStoreId", this.getProductStoreId()), true);
facilityId = productStore.getString("inventoryFacilityId");
} catch (GenericEntityException gee) {
Debug.logError(UtilProperties.getMessage(resource_error,"OrderProblemGettingProductStoreRecords", locale) + gee.getMessage(), module);
return;
} catch (Exception e) {
Debug.logError(UtilProperties.getMessage(resource_error,"OrderProblemGettingProductStoreRecords", locale) + e.getMessage(), module);
return;
}
}
List<CartShipInfo> shipGroups = getShipGroups();
if (shipGroups == null) return;
// Intermediate structure supplierPartyId -> { ShoppingCartItem = { originalShipGroupIndex = dropShipQuantity } } to collect drop-shippable items
Map<String, Map<ShoppingCartItem, Map<Integer, BigDecimal>>> dropShipItems = new HashMap<String, Map<ShoppingCartItem, Map<Integer, BigDecimal>>>();
for (int shipGroupIndex = 0; shipGroupIndex < shipGroups.size(); shipGroupIndex++) {
CartShipInfo shipInfo = shipGroups.get(shipGroupIndex);
// Ignore ship groups that are already drop shipped
String shipGroupSupplierPartyId = shipInfo.getSupplierPartyId();
if (UtilValidate.isNotEmpty(shipGroupSupplierPartyId)) {
continue;
}
// Ignore empty ship groups
Set<ShoppingCartItem> shipItems = shipInfo.getShipItems();
if (UtilValidate.isEmpty(shipItems)) continue;
for (ShoppingCartItem cartItem : shipItems) {
BigDecimal itemQuantity = cartItem.getQuantity();
BigDecimal dropShipQuantity = BigDecimal.ZERO;
GenericValue product = cartItem.getProduct();
if (product == null) {
continue;
}
String productId = product.getString("productId");
String requirementMethodEnumId = product.getString("requirementMethodEnumId");
if ("PRODRQM_DS".equals(requirementMethodEnumId)) {
// Drop ship the full quantity if the product is marked drop-ship only
dropShipQuantity = itemQuantity;
} else if ("PRODRQM_DSATP".equals(requirementMethodEnumId)) {
// Drop ship the quantity not available in inventory if the product is marked drop-ship on low inventory
try {
// Get ATP for the product
Map<String, Object> getProductInventoryAvailableResult = dispatcher.runSync("getInventoryAvailableByFacility", UtilMisc.toMap("productId", productId, "facilityId", facilityId));
BigDecimal availableToPromise = (BigDecimal) getProductInventoryAvailableResult.get("availableToPromiseTotal");
if (itemQuantity.compareTo(availableToPromise) <= 0) {
dropShipQuantity = BigDecimal.ZERO;
} else {
dropShipQuantity = itemQuantity.subtract(availableToPromise);
}
} catch (GenericServiceException gee) {
Debug.logWarning(UtilProperties.getMessage(resource_error,"OrderRunServiceGetInventoryAvailableByFacilityError", locale) + gee.getMessage(), module);
} catch (Exception e) {
Debug.logWarning(UtilProperties.getMessage(resource_error,"OrderRunServiceGetInventoryAvailableByFacilityError", locale) + e.getMessage(), module);
}
} else {
// Don't drop ship anything if the product isn't so marked
dropShipQuantity = BigDecimal.ZERO;
}
if (dropShipQuantity.compareTo(BigDecimal.ZERO) <= 0) continue;
// Find a supplier for the product
String supplierPartyId = null;
try {
Map<String, Object> getSuppliersForProductResult = dispatcher.runSync("getSuppliersForProduct", UtilMisc.<String, Object>toMap("productId", productId, "quantity", dropShipQuantity, "canDropShip", "Y", "currencyUomId", getCurrency()));
List<GenericValue> supplierProducts = UtilGenerics.checkList(getSuppliersForProductResult.get("supplierProducts"));
// Order suppliers by supplierPrefOrderId so that preferred suppliers are used first
supplierProducts = EntityUtil.orderBy(supplierProducts, UtilMisc.toList("supplierPrefOrderId"));
GenericValue supplierProduct = EntityUtil.getFirst(supplierProducts);
if (! UtilValidate.isEmpty(supplierProduct)) {
supplierPartyId = supplierProduct.getString("partyId");
}
} catch (GenericServiceException e) {
Debug.logWarning(UtilProperties.getMessage(resource_error,"OrderRunServiceGetSuppliersForProductError", locale) + e.getMessage(), module);
}
// Leave the items untouched if we couldn't find a supplier
if (UtilValidate.isEmpty(supplierPartyId)) continue;
if (! dropShipItems.containsKey(supplierPartyId)) dropShipItems.put(supplierPartyId, new HashMap<ShoppingCartItem, Map<Integer, BigDecimal>>());
Map<ShoppingCartItem, Map<Integer, BigDecimal>> supplierCartItems = UtilGenerics.checkMap(dropShipItems.get(supplierPartyId));
if (! supplierCartItems.containsKey(cartItem)) supplierCartItems.put(cartItem, new HashMap<Integer, BigDecimal>());
Map<Integer, BigDecimal> cartItemGroupQuantities = UtilGenerics.checkMap(supplierCartItems.get(cartItem));
cartItemGroupQuantities.put(Integer.valueOf(shipGroupIndex), dropShipQuantity);
}
}
// Reassign the drop-shippable item quantities to new or existing drop-ship groups
for (String supplierPartyId : dropShipItems.keySet()) {
CartShipInfo shipInfo = null;
int newShipGroupIndex = -1 ;
// Attempt to get the first ship group for the supplierPartyId
TreeMap<Integer, CartShipInfo> supplierShipGroups = this.getShipGroupsBySupplier(supplierPartyId);
if (! UtilValidate.isEmpty(supplierShipGroups)) {
newShipGroupIndex = (supplierShipGroups.firstKey()).intValue();
shipInfo = supplierShipGroups.get(supplierShipGroups.firstKey());
}
if (newShipGroupIndex == -1) {
newShipGroupIndex = addShipInfo();
shipInfo = this.shipInfo.get(newShipGroupIndex);
}
shipInfo.supplierPartyId = supplierPartyId;
Map<ShoppingCartItem, Map<Integer, BigDecimal>> supplierCartItems = UtilGenerics.checkMap(dropShipItems.get(supplierPartyId));
for (ShoppingCartItem cartItem : supplierCartItems.keySet()) {
Map<Integer, BigDecimal> cartItemGroupQuantities = UtilGenerics.checkMap(supplierCartItems.get(cartItem));
for (Integer previousShipGroupIndex : cartItemGroupQuantities.keySet()) {
BigDecimal dropShipQuantity = cartItemGroupQuantities.get(previousShipGroupIndex);
positionItemToGroup(cartItem, dropShipQuantity, previousShipGroupIndex.intValue(), newShipGroupIndex, true);
}
}
}
}
static class BasePriceOrderComparator implements Comparator<Object>, Serializable {
private boolean ascending = false;
BasePriceOrderComparator(boolean ascending) {
this.ascending = ascending;
}
@Override
public int compare(java.lang.Object obj, java.lang.Object obj1) {
ShoppingCartItem cartItem = (ShoppingCartItem) obj;
ShoppingCartItem cartItem1 = (ShoppingCartItem) obj1;
int compareValue = cartItem.getBasePrice().compareTo(cartItem1.getBasePrice());
if (this.ascending) {
return compareValue;
} else {
return -compareValue;
}
}
@Override
public boolean equals(java.lang.Object obj) {
if (obj instanceof BasePriceOrderComparator) {
return this.ascending == ((BasePriceOrderComparator) obj).ascending;
} else {
return false;
}
}
}
public static class ShoppingCartItemGroup implements Serializable {
private String groupNumber;
private String groupName;
private ShoppingCartItemGroup parentGroup;
// don't allow empty constructor
@SuppressWarnings("unused")
private ShoppingCartItemGroup() {}
protected ShoppingCartItemGroup(long groupNumber, String groupName) {
this(groupNumber, groupName, null);
}
/** Note that to avoid foreign key issues when the groups are created a parentGroup should have a lower number than the child group. */
protected ShoppingCartItemGroup(long groupNumber, String groupName, ShoppingCartItemGroup parentGroup) {
this(UtilFormatOut.formatPaddedNumber(groupNumber, 2), groupName, parentGroup);
}
protected ShoppingCartItemGroup(String groupNumber, String groupName, ShoppingCartItemGroup parentGroup) {
this.groupNumber = groupNumber;
this.groupName = groupName;
this.parentGroup = parentGroup;
}
protected ShoppingCartItemGroup(ShoppingCartItemGroup itemGroup, ShoppingCartItemGroup parentGroup) {
this.groupNumber = itemGroup.groupNumber;
this.groupName = itemGroup.groupName;
this.parentGroup = parentGroup;
}
public String getGroupNumber() {
return this.groupNumber;
}
public String getGroupName() {
return this.groupName;
}
public void setGroupName(String str) {
this.groupName = str;
}
public ShoppingCartItemGroup getParentGroup () {
return this.parentGroup;
}
protected GenericValue makeOrderItemGroup(Delegator delegator) {
GenericValue orderItemGroup = delegator.makeValue("OrderItemGroup");
orderItemGroup.set("orderItemGroupSeqId", this.getGroupNumber());
orderItemGroup.set("groupName", this.getGroupName());
if (this.parentGroup != null) {
orderItemGroup.set("parentGroupSeqId", this.parentGroup.getGroupNumber());
}
return orderItemGroup;
}
public void inheritParentsParent() {
if (this.parentGroup != null) {
this.parentGroup = this.parentGroup.getParentGroup();
}
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
ShoppingCartItemGroup that = (ShoppingCartItemGroup) obj;
if (that.groupNumber.equals(this.groupNumber)) {
return true;
}
return false;
}
}
public static class ProductPromoUseInfo implements Serializable, Comparable<ProductPromoUseInfo> {
public String productPromoId = null;
public String productPromoCodeId = null;
public BigDecimal totalDiscountAmount = BigDecimal.ZERO;
public BigDecimal quantityLeftInActions = BigDecimal.ZERO;
private Map<ShoppingCartItem,BigDecimal> usageInfoMap = null;
public ProductPromoUseInfo(String productPromoId, String productPromoCodeId, BigDecimal totalDiscountAmount, BigDecimal quantityLeftInActions, Map<ShoppingCartItem,BigDecimal> usageInfoMap) {
this.productPromoId = productPromoId;
this.productPromoCodeId = productPromoCodeId;
this.totalDiscountAmount = totalDiscountAmount;
this.quantityLeftInActions = quantityLeftInActions;
this.usageInfoMap = usageInfoMap;
}
public String getProductPromoId() { return this.productPromoId; }
public String getProductPromoCodeId() { return this.productPromoCodeId; }
public BigDecimal getTotalDiscountAmount() { return this.totalDiscountAmount; }
public BigDecimal getQuantityLeftInActions() { return this.quantityLeftInActions; }
public Map<ShoppingCartItem,BigDecimal> getUsageInfoMap() { return this.usageInfoMap; }
public BigDecimal getUsageWeight() {
Iterator<ShoppingCartItem> lineItems = this.usageInfoMap.keySet().iterator();
BigDecimal totalAmount = BigDecimal.ZERO;
while (lineItems.hasNext()) {
ShoppingCartItem lineItem = lineItems.next();
totalAmount = totalAmount.add(lineItem.getBasePrice().multiply(usageInfoMap.get(lineItem)));
}
if (totalAmount.compareTo(BigDecimal.ZERO) == 0) {
return BigDecimal.ZERO;
} else {
return getTotalDiscountAmount().negate().divide(totalAmount, scale, rounding);
}
}
@Override
public int compareTo(ProductPromoUseInfo other) {
return other.getUsageWeight().compareTo(getUsageWeight());
}
}
public static class CartShipInfo implements Serializable {
public Map<ShoppingCartItem, CartShipItemInfo> shipItemInfo = new HashMap<ShoppingCartItem, CartShipItemInfo>();
public List<GenericValue> shipTaxAdj = new LinkedList<GenericValue>();
public String orderTypeId = null;
private String internalContactMechId = null;
public String telecomContactMechId = null;
public String shipmentMethodTypeId = null;
public String supplierPartyId = null;
public String carrierRoleTypeId = null;
public String carrierPartyId = null;
private String facilityId = null;
public String giftMessage = null;
public String shippingInstructions = null;
public String maySplit = "N";
public String isGift = "N";
public BigDecimal shipEstimate = BigDecimal.ZERO;
public Timestamp shipBeforeDate = null;
public Timestamp shipAfterDate = null;
private String shipGroupSeqId = null;
private String associatedShipGroupSeqId = null;
public String vendorPartyId = null;
public String productStoreShipMethId = null;
public Map<String, Object> attributes = new HashMap<String, Object>();
public void setAttribute(String name, Object value) {
this.attributes.put(name, value);
}
public void removeAttribute(String name) {
this.attributes.remove(name);
}
@SuppressWarnings("unchecked")
public <T> T getAttribute(String name) {
return (T) this.attributes.get(name);
}
public String getOrderTypeId() { return orderTypeId; }
public String getContactMechId() { return internalContactMechId; }
public void setContactMechId(String contactMechId) {
this.internalContactMechId = contactMechId;
}
public String getCarrierPartyId() { return carrierPartyId; }
public String getSupplierPartyId() { return supplierPartyId; }
public String getShipmentMethodTypeId() { return shipmentMethodTypeId; }
public BigDecimal getShipEstimate() { return shipEstimate; }
public String getShipGroupSeqId() { return shipGroupSeqId; }
public void setShipGroupSeqId(String shipGroupSeqId) {
this.shipGroupSeqId = shipGroupSeqId;
}
public String getAssociatedShipGroupSeqId() { return associatedShipGroupSeqId; }
public void setAssociatedShipGroupSeqId(String shipGroupSeqId) {
this.associatedShipGroupSeqId = shipGroupSeqId;
}
public String getFacilityId() { return facilityId; }
public void setFacilityId(String facilityId) {
this.facilityId = facilityId;
}
public String getVendorPartyId() { return vendorPartyId;}
public void setVendorPartyId(String vendorPartyId) {
this.vendorPartyId = vendorPartyId;
}
public void setMaySplit(Boolean maySplit) {
if (UtilValidate.isNotEmpty(maySplit)) {
this.maySplit = maySplit.booleanValue() ? "Y" : "N";
}
}
public void clearAllTaxInfo() {
this.shipTaxAdj.clear();
for (CartShipItemInfo itemInfo : shipItemInfo.values()) {
itemInfo.itemTaxAdj.clear();
}
}
public List<GenericValue> makeItemShipGroupAndAssoc(Delegator delegator, ShoppingCart cart, String shipGroupSeqId) {
return makeItemShipGroupAndAssoc(delegator, cart, shipGroupSeqId, false);
}
public List<GenericValue> makeItemShipGroupAndAssoc(Delegator delegator, ShoppingCart cart, String shipGroupSeqId, boolean newShipGroup) {
List<GenericValue> values = new LinkedList<GenericValue>();
// create order contact mech for shipping address
if (this.internalContactMechId != null) {
GenericValue orderCm = delegator.makeValue("OrderContactMech");
orderCm.set("contactMechPurposeTypeId", "SHIPPING_LOCATION");
orderCm.set("contactMechId", this.internalContactMechId);
values.add(orderCm);
}
// create the ship group
GenericValue shipGroup = delegator.makeValue("OrderItemShipGroup");
shipGroup.set("shipmentMethodTypeId", shipmentMethodTypeId);
shipGroup.set("carrierRoleTypeId", carrierRoleTypeId);
shipGroup.set("carrierPartyId", carrierPartyId);
shipGroup.set("supplierPartyId", supplierPartyId);
shipGroup.set("shippingInstructions", shippingInstructions);
shipGroup.set("giftMessage", giftMessage);
shipGroup.set("contactMechId", this.internalContactMechId);
shipGroup.set("telecomContactMechId", this.telecomContactMechId);
shipGroup.set("maySplit", maySplit);
shipGroup.set("isGift", isGift);
shipGroup.set("shipGroupSeqId", shipGroupSeqId);
shipGroup.set("vendorPartyId", vendorPartyId);
shipGroup.set("facilityId", facilityId);
// use the cart's default ship before and after dates here
if ((shipBeforeDate == null) && (cart.getDefaultShipBeforeDate() != null)) {
shipGroup.set("shipByDate", cart.getDefaultShipBeforeDate());
} else {
shipGroup.set("shipByDate", shipBeforeDate);
}
if ((shipAfterDate == null) && (cart.getDefaultShipAfterDate() != null)) {
shipGroup.set("shipAfterDate", cart.getDefaultShipAfterDate());
} else {
shipGroup.set("shipAfterDate", shipAfterDate);
}
values.add(shipGroup);
//set estimated ship dates
LinkedList<Timestamp> estimatedShipDates = new LinkedList<Timestamp>();
for (ShoppingCartItem item : shipItemInfo.keySet()) {
Timestamp estimatedShipDate = item.getEstimatedShipDate();
if (estimatedShipDate != null) {
estimatedShipDates.add(estimatedShipDate);
}
}
if (estimatedShipDates.size() > 0) {
Collections.sort(estimatedShipDates);
Timestamp estimatedShipDate = estimatedShipDates.getLast();
shipGroup.set("estimatedShipDate", estimatedShipDate);
}
//set estimated delivery dates
LinkedList<Timestamp> estimatedDeliveryDates = new LinkedList<Timestamp>();
for (ShoppingCartItem item : shipItemInfo.keySet()) {
Timestamp estimatedDeliveryDate = item.getDesiredDeliveryDate();
if (estimatedDeliveryDate != null) {
estimatedDeliveryDates.add(estimatedDeliveryDate);
}
}
if (UtilValidate.isNotEmpty(estimatedDeliveryDates)) {
Collections.sort(estimatedDeliveryDates);
Timestamp estimatedDeliveryDate = estimatedDeliveryDates.getLast();
shipGroup.set("estimatedDeliveryDate", estimatedDeliveryDate);
}
// create the shipping estimate adjustments
if (shipEstimate.compareTo(BigDecimal.ZERO) != 0) {
GenericValue shipAdj = delegator.makeValue("OrderAdjustment");
shipAdj.set("orderAdjustmentTypeId", "SHIPPING_CHARGES");
shipAdj.set("amount", shipEstimate);
if("PURCHASE_ORDER".equals(cart.getOrderType())) shipAdj.set("isManual", "Y");
shipAdj.set("shipGroupSeqId", shipGroupSeqId);
values.add(shipAdj);
}
// create the top level tax adjustments
for (GenericValue taxAdj : shipTaxAdj) {
taxAdj.set("shipGroupSeqId", shipGroupSeqId);
values.add(taxAdj);
}
// create the ship group item associations
for (ShoppingCartItem item : shipItemInfo.keySet()) {
CartShipItemInfo itemInfo = shipItemInfo.get(item);
GenericValue assoc = delegator.makeValue("OrderItemShipGroupAssoc");
assoc.set("orderItemSeqId", item.getOrderItemSeqId());
assoc.set("shipGroupSeqId", shipGroupSeqId);
assoc.set("quantity", itemInfo.quantity);
values.add(assoc);
// create the item tax adjustment
for (GenericValue taxAdj : itemInfo.itemTaxAdj) {
taxAdj.set("orderItemSeqId", item.getOrderItemSeqId());
taxAdj.set("shipGroupSeqId", shipGroupSeqId);
values.add(taxAdj);
}
}
return values;
}
public CartShipItemInfo setItemInfo(ShoppingCartItem item, BigDecimal quantity, List<GenericValue> taxAdj) {
CartShipItemInfo itemInfo = shipItemInfo.get(item);
if (itemInfo == null) {
if (!isShippableToAddress(item)) {
throw new IllegalArgumentException("The shipping address is not compatible with ProductGeos rules.");
}
itemInfo = new CartShipItemInfo();
itemInfo.item = item;
shipItemInfo.put(item, itemInfo);
}
if (quantity.compareTo(BigDecimal.ZERO) >= 0) {
itemInfo.quantity = quantity;
}
if (taxAdj != null) {
itemInfo.itemTaxAdj.clear();
itemInfo.itemTaxAdj.addAll(taxAdj);
}
return itemInfo;
}
public CartShipItemInfo setItemInfo(ShoppingCartItem item, List<GenericValue> taxAdj) {
return setItemInfo(item, BigDecimal.ONE.negate(), taxAdj);
}
public CartShipItemInfo setItemInfo(ShoppingCartItem item, BigDecimal quantity) {
return setItemInfo(item, quantity, null);
}
public CartShipItemInfo getShipItemInfo(ShoppingCartItem item) {
return shipItemInfo.get(item);
}
public Set<ShoppingCartItem> getShipItems() {
return shipItemInfo.keySet();
}
private boolean isShippableToAddress(ShoppingCartItem item) {
if ("SALES_ORDER".equals(getOrderTypeId())) {
// Verify if the new address is compatible with the ProductGeos rules of
// the products already in the cart
GenericValue shippingAddress = null;
try {
shippingAddress = item.getDelegator().findOne("PostalAddress", UtilMisc.toMap("contactMechId", this.internalContactMechId), false);
} catch (GenericEntityException gee) {
Debug.logError(gee, "Error retrieving the shipping address for contactMechId [" + this.internalContactMechId + "].", module);
}
if (shippingAddress != null) {
GenericValue product = item.getProduct();
if (product != null) {
return ProductWorker.isShippableToAddress(product, shippingAddress);
}
}
}
return true;
}
/**
* Reset the ship group's shipBeforeDate if it is after the parameter
* @param newShipBeforeDate the ship group's shipBeforeDate to be reset
*/
public void resetShipBeforeDateIfAfter(Timestamp newShipBeforeDate) {
if (newShipBeforeDate != null) {
if ((this.shipBeforeDate == null) || (!this.shipBeforeDate.before(newShipBeforeDate))) {
this.shipBeforeDate = newShipBeforeDate;
}
}
}
/**
* Reset the ship group's shipAfterDate if it is before the parameter
* @param newShipAfterDate the ship group's shipAfterDate to be reset
*/
public void resetShipAfterDateIfBefore(Timestamp newShipAfterDate) {
if (newShipAfterDate != null) {
if ((this.shipAfterDate == null) || (!this.shipAfterDate.after(newShipAfterDate))) {
this.shipAfterDate = newShipAfterDate;
}
}
}
public BigDecimal getTotalTax(ShoppingCart cart) {
List<GenericValue> taxAdjustments = new LinkedList<GenericValue>();
taxAdjustments.addAll(shipTaxAdj);
for (CartShipItemInfo info : shipItemInfo.values()) {
taxAdjustments.addAll(info.itemTaxAdj);
}
Map<String, Object> taxByAuthority = OrderReadHelper.getOrderTaxByTaxAuthGeoAndParty(taxAdjustments);
BigDecimal taxTotal = (BigDecimal) taxByAuthority.get("taxGrandTotal");
return taxTotal;
}
public BigDecimal getTotal() {
BigDecimal shipItemTotal = ZERO;
for (CartShipItemInfo info : shipItemInfo.values()) {
shipItemTotal = shipItemTotal.add(info.getItemSubTotal());
}
return shipItemTotal;
}
public static class CartShipItemInfo implements Serializable {
public List<GenericValue> itemTaxAdj = new LinkedList<GenericValue>();
public ShoppingCartItem item = null;
public BigDecimal quantity = BigDecimal.ZERO;
public BigDecimal getItemTax(ShoppingCart cart) {
BigDecimal itemTax = ZERO;
for (int i = 0; i < itemTaxAdj.size(); i++) {
GenericValue v = itemTaxAdj.get(i);
itemTax = itemTax.add(OrderReadHelper.calcItemAdjustment(v, quantity, item.getBasePrice()));
}
return itemTax.setScale(taxCalcScale, taxRounding);
}
public ShoppingCartItem getItem() {
return this.item;
}
public BigDecimal getItemQuantity() {
return this.quantity;
}
public BigDecimal getItemSubTotal() {
return item.getItemSubTotal(quantity);
}
}
}
public static class CartPaymentInfo implements Serializable, Comparable<Object> {
public String paymentMethodTypeId = null;
public String paymentMethodId = null;
public String finAccountId = null;
public String securityCode = null;
public String postalCode = null;
public String[] refNum = new String[2];
public String track2 = null;
public BigDecimal amount = null;
public boolean singleUse = false;
public boolean isPresent = false;
public boolean isSwiped = false;
public boolean overflow = false;
public GenericValue getValueObject(Delegator delegator) {
String entityName = null;
Map<String, String> lookupFields = null;
if (paymentMethodId != null) {
lookupFields = UtilMisc.<String, String>toMap("paymentMethodId", paymentMethodId);
entityName = "PaymentMethod";
} else if (paymentMethodTypeId != null) {
lookupFields = UtilMisc.<String, String>toMap("paymentMethodTypeId", paymentMethodTypeId);
entityName = "PaymentMethodType";
} else {
throw new IllegalArgumentException("Could not create value object because paymentMethodId and paymentMethodTypeId are null");
}
try {
return EntityQuery.use(delegator).from(entityName).where(lookupFields).cache(true).queryOne();
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
return null;
}
public GenericValue getBillingAddress(Delegator delegator) {
GenericValue valueObj = this.getValueObject(delegator);
GenericValue postalAddress = null;
if ("PaymentMethod".equals(valueObj.getEntityName())) {
String paymentMethodTypeId = valueObj.getString("paymentMethodTypeId");
String paymentMethodId = valueObj.getString("paymentMethodId");
// billing account, credit card, gift card, eft account all have postal address
try {
GenericValue pmObj = null;
if ("CREDIT_CARD".equals(paymentMethodTypeId)) {
pmObj = EntityQuery.use(delegator).from("CreditCard").where("paymentMethodId", paymentMethodId).queryOne();
} else if ("GIFT_CARD".equals(paymentMethodTypeId)) {
pmObj = EntityQuery.use(delegator).from("GiftCard").where("paymentMethodId", paymentMethodId).queryOne();
} else if ("EFT_ACCOUNT".equals(paymentMethodTypeId)) {
pmObj = EntityQuery.use(delegator).from("EftAccount").where("paymentMethodId", paymentMethodId).queryOne();
} else if ("EXT_BILLACT".equals(paymentMethodTypeId)) {
pmObj = EntityQuery.use(delegator).from("BillingAccount").where("paymentMethodId", paymentMethodId).queryOne();
} else if ("EXT_PAYPAL".equals(paymentMethodTypeId)) {
pmObj = EntityQuery.use(delegator).from("PayPalPaymentMethod").where("paymentMethodId", paymentMethodId).queryOne();
}
if (pmObj != null) {
postalAddress = pmObj.getRelatedOne("PostalAddress", false);
} else {
Debug.logInfo("No PaymentMethod Object Found - " + paymentMethodId, module);
}
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
}
return postalAddress;
}
public List<GenericValue> makeOrderPaymentInfos(Delegator delegator, ShoppingCart cart) {
BigDecimal maxAmount = ZERO;
GenericValue valueObj = this.getValueObject(delegator);
List<GenericValue> values = new LinkedList<GenericValue>();
if (valueObj != null) {
// first create a BILLING_LOCATION for the payment method address if there is one
if ("PaymentMethod".equals(valueObj.getEntityName())) {
String billingAddressId = null;
GenericValue billingAddress = this.getBillingAddress(delegator);
if (billingAddress != null) {
billingAddressId = billingAddress.getString("contactMechId");
}
if (UtilValidate.isNotEmpty(billingAddressId)) {
GenericValue orderCm = delegator.makeValue("OrderContactMech");
orderCm.set("contactMechPurposeTypeId", "BILLING_LOCATION");
orderCm.set("contactMechId", billingAddressId);
values.add(orderCm);
}
}
GenericValue productStore = null;
String splitPayPrefPerShpGrp = null;
try {
productStore = EntityQuery.use(delegator).from("ProductStore").where("productStoreId", cart.getProductStoreId()).queryOne();
} catch (GenericEntityException e) {
Debug.logError(e.toString(), module);
}
if (productStore != null) {
splitPayPrefPerShpGrp = productStore.getString("splitPayPrefPerShpGrp");
}
if (splitPayPrefPerShpGrp == null) {
splitPayPrefPerShpGrp = "N";
}
if ("Y".equals(splitPayPrefPerShpGrp) && cart.paymentInfo.size() > 1) {
throw new GeneralRuntimeException("Split Payment Preference per Ship Group does not yet support multiple Payment Methods");
}
if ("Y".equals(splitPayPrefPerShpGrp) && cart.paymentInfo.size() == 1) {
for (CartShipInfo csi : cart.getShipGroups()) {
maxAmount = csi.getTotal().add(cart.getOrderOtherAdjustmentTotal().add(cart.getOrderGlobalAdjustments()).divide(new BigDecimal(cart.getShipGroupSize()), generalRounding)).add(csi.getShipEstimate().add(csi.getTotalTax(cart)));
maxAmount = maxAmount.setScale(scale, rounding);
// create the OrderPaymentPreference record
GenericValue opp = delegator.makeValue("OrderPaymentPreference");
opp.set("paymentMethodTypeId", valueObj.getString("paymentMethodTypeId"));
opp.set("presentFlag", isPresent ? "Y" : "N");
opp.set("swipedFlag", isSwiped ? "Y" : "N");
opp.set("overflowFlag", overflow ? "Y" : "N");
opp.set("paymentMethodId", paymentMethodId);
opp.set("finAccountId", finAccountId);
opp.set("billingPostalCode", postalCode);
opp.set("maxAmount", maxAmount);
opp.set("shipGroupSeqId", csi.getShipGroupSeqId());
if (refNum != null) {
opp.set("manualRefNum", refNum[0]);
opp.set("manualAuthCode", refNum[1]);
}
if (securityCode != null) {
opp.set("securityCode", securityCode);
}
if (track2 != null) {
opp.set("track2", track2);
}
if (paymentMethodId != null || "FIN_ACCOUNT".equals(paymentMethodTypeId)) {
opp.set("statusId", "PAYMENT_NOT_AUTH");
} else if (paymentMethodTypeId != null) {
// external payment method types require notification when received
// internal payment method types are assumed to be in-hand
if (paymentMethodTypeId.startsWith("EXT_")) {
opp.set("statusId", "PAYMENT_NOT_RECEIVED");
} else {
opp.set("statusId", "PAYMENT_RECEIVED");
}
}
Debug.logInfo("ShipGroup [" + csi.getShipGroupSeqId() +"]", module);
Debug.logInfo("Creating OrderPaymentPreference - " + opp, module);
values.add(opp);
}
} else if ("N".equals(splitPayPrefPerShpGrp)) {
maxAmount = maxAmount.add(amount);
maxAmount = maxAmount.setScale(scale, rounding);
// create the OrderPaymentPreference record
GenericValue opp = delegator.makeValue("OrderPaymentPreference");
opp.set("paymentMethodTypeId", valueObj.getString("paymentMethodTypeId"));
opp.set("presentFlag", isPresent ? "Y" : "N");
opp.set("swipedFlag", isSwiped ? "Y" : "N");
opp.set("overflowFlag", overflow ? "Y" : "N");
opp.set("paymentMethodId", paymentMethodId);
opp.set("finAccountId", finAccountId);
opp.set("billingPostalCode", postalCode);
opp.set("maxAmount", maxAmount);
if (refNum != null) {
opp.set("manualRefNum", refNum[0]);
opp.set("manualAuthCode", refNum[1]);
}
if (securityCode != null) {
opp.set("securityCode", securityCode);
}
if (track2 != null) {
opp.set("track2", securityCode);
}
if (paymentMethodId != null || "FIN_ACCOUNT".equals(paymentMethodTypeId)) {
opp.set("statusId", "PAYMENT_NOT_AUTH");
} else if (paymentMethodTypeId != null) {
// external payment method types require notification when received
// internal payment method types are assumed to be in-hand
if (paymentMethodTypeId.startsWith("EXT_")) {
opp.set("statusId", "PAYMENT_NOT_RECEIVED");
} else {
opp.set("statusId", "PAYMENT_RECEIVED");
}
}
Debug.logInfo("Creating OrderPaymentPreference - " + opp, module);
values.add(opp);
}
}
return values;
}
@Override
public int compareTo(Object o) {
CartPaymentInfo that = (CartPaymentInfo) o;
Debug.logInfo("Compare [" + this.toString() + "] to [" + that.toString() + "]", module);
if (this.finAccountId == null) {
if (that.finAccountId != null) {
return -1;
}
} else if (!this.finAccountId.equals(that.finAccountId)) {
return -1;
}
if (this.paymentMethodId != null) {
if (that.paymentMethodId == null) {
return 1;
} else {
int pmCmp = this.paymentMethodId.compareTo(that.paymentMethodId);
if (pmCmp == 0) {
if (this.refNum != null && this.refNum[0] != null) {
if (that.refNum != null && that.refNum[0] != null) {
return this.refNum[0].compareTo(that.refNum[0]);
} else {
return 1;
}
} else {
if (that.refNum != null && that.refNum[0] != null) {
return -1;
} else {
return 0;
}
}
} else {
return pmCmp;
}
}
} else {
if (that.paymentMethodId != null) {
return -1;
} else {
int pmtCmp = this.paymentMethodTypeId.compareTo(that.paymentMethodTypeId);
if (pmtCmp == 0) {
if (this.refNum != null && this.refNum[0] != null) {
if (that.refNum != null && that.refNum[0] != null) {
return this.refNum[0].compareTo(that.refNum[0]);
} else {
return 1;
}
} else {
if (that.refNum != null && that.refNum[0] != null) {
return -1;
} else {
return 0;
}
}
} else {
return pmtCmp;
}
}
}
}
@Override
public String toString() {
return "Pm: " + paymentMethodId + " / PmType: " + paymentMethodTypeId + " / Amt: " + amount + " / Ref: " + refNum[0] + "!" + refNum[1];
}
}
@Override
protected void finalize() throws Throwable {
// DEJ20050518 we should not call clear because it kills the auto-save shopping list and is unnecessary given that when this object is GC'ed it will cause everything it points to that isn't referenced anywhere else to be GC'ed too: this.clear();
super.finalize();
}
public Map<String, String> getOrderAttributes() {
return orderAttributes;
}
public void setOrderAttributes(Map<String, String> orderAttributes) {
this.orderAttributes = orderAttributes;
}
public String getOrderStatusId() {
return orderStatusId;
}
public void setOrderStatusId(String orderStatusId) {
this.orderStatusId = orderStatusId;
}
public String getOrderStatusString() {
return orderStatusString;
}
public void setOrderStatusString(String orderStatusString) {
this.orderStatusString = orderStatusString;
}
public static BigDecimal getMinimumOrderQuantity(Delegator delegator, BigDecimal itemBasePrice, String itemProductId) throws GenericEntityException {
BigDecimal minQuantity = BigDecimal.ZERO;
BigDecimal minimumOrderPrice = BigDecimal.ZERO;
List<GenericValue> minimumOrderPriceList = EntityQuery.use(delegator).from("ProductPrice")
.where("productId", itemProductId, "productPriceTypeId", "MINIMUM_ORDER_PRICE")
.filterByDate()
.queryList();
if (itemBasePrice == null) {
List<GenericValue> productPriceList = EntityQuery.use(delegator).from("ProductPrice")
.where("productId", itemProductId)
.filterByDate()
.queryList();
Map<String, BigDecimal> productPriceMap = new HashMap<String, BigDecimal>();
for (GenericValue productPrice : productPriceList) {
productPriceMap.put(productPrice.getString("productPriceTypeId"), productPrice.getBigDecimal("price"));
}
if (UtilValidate.isNotEmpty(productPriceMap.get("SPECIAL_PROMO_PRICE"))) {
itemBasePrice = productPriceMap.get("SPECIAL_PROMO_PRICE");
} else if (UtilValidate.isNotEmpty(productPriceMap.get("PROMO_PRICE"))) {
itemBasePrice = productPriceMap.get("PROMO_PRICE");
} else if (UtilValidate.isNotEmpty(productPriceMap.get("DEFAULT_PRICE"))) {
itemBasePrice = productPriceMap.get("DEFAULT_PRICE");
} else if (UtilValidate.isNotEmpty(productPriceMap.get("LIST_PRICE"))) {
itemBasePrice = productPriceMap.get("LIST_PRICE");
}
}
if (UtilValidate.isNotEmpty(minimumOrderPriceList)) {
minimumOrderPrice = EntityUtil.getFirst(minimumOrderPriceList).getBigDecimal("price");
}
if (itemBasePrice != null && minimumOrderPrice.compareTo(itemBasePrice) > 0) {
minQuantity = minimumOrderPrice.divide(itemBasePrice, 0, BigDecimal.ROUND_UP);
}
return minQuantity;
}
}