0001: /*
0002: * $Id: ShoppingCart.java,v 1.39 2004/03/05 19:45:54 ajzeneski Exp $
0003: *
0004: * Copyright (c) 2001, 2002 The Open For Business Project - www.ofbiz.org
0005: *
0006: * Permission is hereby granted, free of charge, to any person obtaining a
0007: * copy of this software and associated documentation files (the "Software"),
0008: * to deal in the Software without restriction, including without limitation
0009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0010: * and/or sell copies of the Software, and to permit persons to whom the
0011: * Software is furnished to do so, subject to the following conditions:
0012: *
0013: * The above copyright notice and this permission notice shall be included
0014: * in all copies or substantial portions of the Software.
0015: *
0016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
0019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
0020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
0021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
0022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0023: */
0024: package org.ofbiz.order.shoppingcart;
0025:
0026: import java.text.NumberFormat;
0027: import java.util.*;
0028: import java.sql.Timestamp;
0029:
0030: import org.ofbiz.base.util.*;
0031: import org.ofbiz.entity.GenericDelegator;
0032: import org.ofbiz.entity.GenericEntityException;
0033: import org.ofbiz.entity.GenericPK;
0034: import org.ofbiz.entity.GenericValue;
0035: import org.ofbiz.order.order.OrderReadHelper;
0036: import org.ofbiz.order.shoppingcart.product.ProductPromoWorker;
0037: import org.ofbiz.service.LocalDispatcher;
0038: import org.ofbiz.product.store.ProductStoreWorker;
0039:
0040: /**
0041: * <p><b>Title:</b> ShoppingCart.java
0042: * <p><b>Description:</b> Shopping Cart Object.
0043: *
0044: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
0045: * @author <a href="mailto:cnelson@einnovation.com">Chris Nelson</a>
0046: * @author <a href="mailto:jonesde@ofbiz.org">David E. Jones</a>
0047: * @version $Revision: 1.39 $
0048: * @since 2.0
0049: */
0050: public class ShoppingCart implements java.io.Serializable {
0051: public static final String module = ShoppingCart.class.getName();
0052:
0053: private List paymentMethodIds = new LinkedList();
0054: private List singleUsePaymentIds = new LinkedList();
0055: private Map paymentMethodAmounts = new HashMap();
0056: private List paymentMethodTypeIds = new LinkedList();
0057: private Map paymentMethodTypeAmounts = new HashMap();
0058: private String orderType = "SALES_ORDER"; // default orderType
0059: private String poNumber = null;
0060: private String orderId = null;
0061: private String firstAttemptOrderId = null;
0062: private String billingAccountId = null;
0063: private double billingAccountAmt = 0.00;
0064: private String currencyUom = null;
0065:
0066: private GenericValue orderShipmentPreference = null;
0067: private String orderAdditionalEmails = null;
0068: private boolean viewCartOnAdd = false;
0069:
0070: /** Holds value of order adjustments. */
0071: private List adjustments = new LinkedList();
0072: private List cartLines = new ArrayList();
0073: private Map contactMechIdsMap = new HashMap();
0074:
0075: public static class ProductPromoUseInfo {
0076: public String productPromoId;
0077: public String productPromoCodeId;
0078: public double totalDiscountAmount = 0;
0079: public double quantityLeftInActions = 0;
0080:
0081: public ProductPromoUseInfo(String productPromoId,
0082: String productPromoCodeId, double totalDiscountAmount,
0083: double quantityLeftInActions) {
0084: this .productPromoId = productPromoId;
0085: this .productPromoCodeId = productPromoCodeId;
0086: this .totalDiscountAmount = totalDiscountAmount;
0087: this .quantityLeftInActions = quantityLeftInActions;
0088: }
0089:
0090: public String getProductPromoId() {
0091: return this .productPromoId;
0092: }
0093:
0094: public String getProductPromoCodeId() {
0095: return this .productPromoCodeId;
0096: }
0097:
0098: public double getTotalDiscountAmount() {
0099: return this .totalDiscountAmount;
0100: }
0101:
0102: public double getQuantityLeftInActions() {
0103: return this .quantityLeftInActions;
0104: }
0105: }
0106:
0107: /** Contains a List for each productPromoId (key) containing a productPromoCodeId (or empty string for no code) for each use of the productPromoId */
0108: private List productPromoUseInfoList = new LinkedList();
0109: /** Contains the promo codes entered */
0110: private Set productPromoCodes = new HashSet();
0111: private List freeShippingProductPromoActions = new ArrayList();
0112:
0113: private transient GenericDelegator delegator = null;
0114: private String delegatorName = null;
0115: private String productStoreId = null;
0116: private String webSiteId = null;
0117:
0118: private GenericValue userLogin = null;
0119: private GenericValue autoUserLogin = null;
0120:
0121: private Locale locale; // holds the locale from the user session
0122:
0123: /** don't allow empty constructor */
0124: protected ShoppingCart() {
0125: }
0126:
0127: /** Creates a new cloned ShoppingCart Object. */
0128: public ShoppingCart(ShoppingCart cart) {
0129: this .delegator = cart.getDelegator();
0130: this .delegatorName = delegator.getDelegatorName();
0131: this .productStoreId = cart.getProductStoreId();
0132: this .paymentMethodIds = cart.getPaymentMethodIds();
0133: this .paymentMethodTypeIds = cart.getPaymentMethodTypeIds();
0134: this .poNumber = cart.getPoNumber();
0135: this .orderId = cart.getOrderId();
0136: this .firstAttemptOrderId = cart.getFirstAttemptOrderId();
0137: this .billingAccountId = cart.getBillingAccountId();
0138: this .orderShipmentPreference = cart
0139: .getOrderShipmentPreference();
0140: this .orderAdditionalEmails = cart.getOrderAdditionalEmails();
0141: this .adjustments = new LinkedList(cart.getAdjustments());
0142: this .contactMechIdsMap = new HashMap(cart
0143: .getOrderContactMechIds());
0144: this .freeShippingProductPromoActions = new ArrayList(cart
0145: .getFreeShippingProductPromoActions());
0146: this .productPromoUseInfoList = new LinkedList(
0147: cart.productPromoUseInfoList);
0148: this .productPromoCodes = new HashSet(cart.productPromoCodes);
0149: this .locale = cart.getLocale();
0150: this .currencyUom = cart.getCurrency();
0151: this .viewCartOnAdd = cart.viewCartOnAdd();
0152:
0153: // clone the items
0154: List items = cart.items();
0155: Iterator itIt = items.iterator();
0156: while (itIt.hasNext()) {
0157: cartLines.add(new ShoppingCartItem((ShoppingCartItem) itIt
0158: .next()));
0159: }
0160: }
0161:
0162: /** Creates new empty ShoppingCart object. */
0163: public ShoppingCart(GenericDelegator delegator,
0164: String productStoreId, String webSiteId, String currencyUom) {
0165: this .delegator = delegator;
0166: this .delegatorName = delegator.getDelegatorName();
0167: this .productStoreId = productStoreId;
0168: this .webSiteId = webSiteId;
0169: this .currencyUom = currencyUom;
0170: this .orderShipmentPreference = delegator.makeValue(
0171: "OrderShipmentPreference", null);
0172: // make sure locale is initialized if nothing other than from jvm
0173: // for a web shopping cart this would be set later by the webShoppingCart methods
0174: this .locale = Locale.getDefault();
0175:
0176: // set the default view cart on add for this store
0177: GenericValue productStore = ProductStoreWorker.getProductStore(
0178: productStoreId, delegator);
0179: String storeViewCartOnAdd = productStore
0180: .getString("viewCartOnAdd");
0181: if (storeViewCartOnAdd != null
0182: && "Y".equalsIgnoreCase(storeViewCartOnAdd)) {
0183: this .viewCartOnAdd = true;
0184: }
0185: }
0186:
0187: public GenericDelegator getDelegator() {
0188: if (delegator == null) {
0189: delegator = GenericDelegator
0190: .getGenericDelegator(delegatorName);
0191: }
0192: return delegator;
0193: }
0194:
0195: public String getProductStoreId() {
0196: return this .productStoreId;
0197: }
0198:
0199: public void setProductStoreId(String productStoreId) {
0200: this .productStoreId = productStoreId;
0201: }
0202:
0203: public Locale getLocale() {
0204: return locale;
0205: }
0206:
0207: public void setLocale(Locale locale) {
0208: this .locale = locale;
0209: }
0210:
0211: // =======================================================================
0212: // Methods for cart items
0213: // =======================================================================
0214:
0215: /** Add an item to the shopping cart, or if already there, increase the quantity.
0216: * @return the new/increased item index
0217: * @throws CartItemModifyException
0218: */
0219: public int addOrIncreaseItem(String productId,
0220: double selectedAmount, double quantity, Map features,
0221: Map attributes, String prodCatalogId,
0222: LocalDispatcher dispatcher) throws CartItemModifyException {
0223: // public int addOrIncreaseItem(GenericValue product, double quantity, HashMap features) {
0224:
0225: // Check for existing cart item.
0226: for (int i = 0; i < this .cartLines.size(); i++) {
0227: ShoppingCartItem sci = (ShoppingCartItem) cartLines.get(i);
0228:
0229: if (sci.equals(productId, features, attributes,
0230: prodCatalogId, selectedAmount)) {
0231: double newQuantity = sci.getQuantity() + quantity;
0232:
0233: if (Debug.verboseOn())
0234: Debug.logVerbose("Found a match for id "
0235: + productId + " on line " + i
0236: + ", updating quantity to " + newQuantity,
0237: module);
0238: sci.setQuantity(newQuantity, dispatcher, this );
0239: return i;
0240: }
0241: }
0242:
0243: // Add the new item to the shopping cart if it wasn't found.
0244: return this .addItem(0, ShoppingCartItem.makeItem(
0245: new Integer(0), productId, selectedAmount, quantity,
0246: features, attributes, prodCatalogId, dispatcher, this ));
0247: }
0248:
0249: public int addOrIncreaseItem(String productId, double quantity,
0250: Map features, Map attributes, String prodCatalogId,
0251: LocalDispatcher dispatcher) throws CartItemModifyException {
0252: return addOrIncreaseItem(productId, 0.00, quantity, features,
0253: attributes, prodCatalogId, dispatcher);
0254: }
0255:
0256: /** Add a non-product item to the shopping cart.
0257: * @return the new item index
0258: * @throws CartItemModifyException
0259: */
0260: public int addNonProductItem(String itemType, String description,
0261: String categoryId, double price, double quantity,
0262: Map attributes, String prodCatalogId,
0263: LocalDispatcher dispatcher) throws CartItemModifyException {
0264: return this .addItem(0, ShoppingCartItem.makeItem(
0265: new Integer(0), itemType, description, categoryId,
0266: price, 0.00, quantity, attributes, prodCatalogId,
0267: dispatcher, this , true));
0268: }
0269:
0270: /** Add an item to the shopping cart. */
0271: public int addItem(int index, ShoppingCartItem item) {
0272: if (!cartLines.contains(item)) {
0273: cartLines.add(index, item);
0274: return index;
0275: } else {
0276: return this .getItemIndex(item);
0277: }
0278: }
0279:
0280: /** Add an item to the shopping cart. */
0281: public int addItemToEnd(String productId, double amount,
0282: double quantity, HashMap features, HashMap attributes,
0283: String prodCatalogId, LocalDispatcher dispatcher)
0284: throws CartItemModifyException {
0285: return addItemToEnd(ShoppingCartItem.makeItem(null, productId,
0286: amount, quantity, features, attributes, prodCatalogId,
0287: dispatcher, this ));
0288: }
0289:
0290: /** Add an item to the shopping cart. */
0291: public int addItemToEnd(ShoppingCartItem item) {
0292: if (!cartLines.contains(item)) {
0293: cartLines.add(item);
0294: return cartLines.size() - 1;
0295: } else {
0296: return this .getItemIndex(item);
0297: }
0298: }
0299:
0300: /** Get a ShoppingCartItem from the cart object. */
0301: public ShoppingCartItem findCartItem(String productId,
0302: Map features, Map attributes, String prodCatalogId,
0303: double selectedAmount) {
0304: // Check for existing cart item.
0305: for (int i = 0; i < this .cartLines.size(); i++) {
0306: ShoppingCartItem cartItem = (ShoppingCartItem) cartLines
0307: .get(i);
0308:
0309: if (cartItem.equals(productId, features, attributes,
0310: prodCatalogId, selectedAmount)) {
0311: return cartItem;
0312: }
0313: }
0314: return null;
0315: }
0316:
0317: /** Get all ShoppingCartItems from the cart object with the given productId. */
0318: public List findAllCartItems(String productId) {
0319: if (productId == null)
0320: return new LinkedList(this .cartLines);
0321: List itemsToReturn = new LinkedList();
0322:
0323: // Check for existing cart item.
0324: for (int i = 0; i < this .cartLines.size(); i++) {
0325: ShoppingCartItem cartItem = (ShoppingCartItem) cartLines
0326: .get(i);
0327:
0328: if (productId.equals(cartItem.getProductId())) {
0329: itemsToReturn.add(cartItem);
0330: }
0331: }
0332: return itemsToReturn;
0333: }
0334:
0335: /** Remove quantity 0 ShoppingCartItems from the cart object. */
0336: public void removeEmptyCartItems() {
0337: // Check for existing cart item.
0338: for (int i = 0; i < this .cartLines.size();) {
0339: ShoppingCartItem cartItem = (ShoppingCartItem) cartLines
0340: .get(i);
0341:
0342: if (cartItem.getQuantity() == 0.0) {
0343: cartLines.remove(i);
0344: } else {
0345: i++;
0346: }
0347: }
0348: }
0349:
0350: /** Returns this item's index. */
0351: public int getItemIndex(ShoppingCartItem item) {
0352: return cartLines.indexOf(item);
0353: }
0354:
0355: /** Get a ShoppingCartItem from the cart object. */
0356: public ShoppingCartItem findCartItem(int index) {
0357: if (cartLines.size() <= index)
0358: return null;
0359: return (ShoppingCartItem) cartLines.get(index);
0360: }
0361:
0362: /** Remove an item from the cart object. */
0363: public void removeCartItem(int index, LocalDispatcher dispatcher)
0364: throws CartItemModifyException {
0365: if (index < 0)
0366: return;
0367: if (cartLines.size() <= index)
0368: return;
0369: ShoppingCartItem item = (ShoppingCartItem) cartLines
0370: .remove(index);
0371:
0372: // set quantity to 0 to trigger necessary events
0373: item.setQuantity(0.0, dispatcher, this );
0374: }
0375:
0376: /** Moves a line item to a differnt index. */
0377: public void moveCartItem(int fromIndex, int toIndex) {
0378: if (toIndex < fromIndex) {
0379: cartLines.add(toIndex, cartLines.remove(fromIndex));
0380: } else if (toIndex > fromIndex) {
0381: cartLines.add(toIndex - 1, cartLines.remove(fromIndex));
0382: }
0383: }
0384:
0385: /** Returns the number of items in the cart object. */
0386: public int size() {
0387: return cartLines.size();
0388: }
0389:
0390: /** Returns a Collection of items in the cart object. */
0391: public List items() {
0392: return cartLines;
0393: }
0394:
0395: /** Returns an iterator of cart items. */
0396: public Iterator iterator() {
0397: return cartLines.iterator();
0398: }
0399:
0400: /** Gets the userLogin associated with the cart; may be null */
0401: public GenericValue getUserLogin() {
0402: return this .userLogin;
0403: }
0404:
0405: public void setUserLogin(GenericValue userLogin,
0406: LocalDispatcher dispatcher) throws CartItemModifyException {
0407: this .userLogin = userLogin;
0408: this .handleNewUser(dispatcher);
0409: }
0410:
0411: public GenericValue getAutoUserLogin() {
0412: return this .autoUserLogin;
0413: }
0414:
0415: public void setAutoUserLogin(GenericValue autoUserLogin,
0416: LocalDispatcher dispatcher) throws CartItemModifyException {
0417: this .autoUserLogin = autoUserLogin;
0418: if (getUserLogin() == null) {
0419: this .handleNewUser(dispatcher);
0420: }
0421: }
0422:
0423: public void handleNewUser(LocalDispatcher dispatcher)
0424: throws CartItemModifyException {
0425: String partyId = this .getPartyId();
0426: if (UtilValidate.isNotEmpty(partyId)) {
0427: // recalculate all prices
0428: Iterator cartItemIter = this .iterator();
0429: while (cartItemIter.hasNext()) {
0430: ShoppingCartItem cartItem = (ShoppingCartItem) cartItemIter
0431: .next();
0432: cartItem.updatePrice(dispatcher, this );
0433: }
0434:
0435: // check all promo codes, remove on failed check
0436: Iterator promoCodeIter = this .productPromoCodes.iterator();
0437: while (promoCodeIter.hasNext()) {
0438: String promoCode = (String) promoCodeIter.next();
0439: String checkResult = ProductPromoWorker
0440: .checkCanUsePromoCode(promoCode, partyId, this
0441: .getDelegator());
0442: if (checkResult != null) {
0443: promoCodeIter.remove();
0444: Debug.logWarning(
0445: "On user change promo code was removed because: "
0446: + checkResult, module);
0447: }
0448: }
0449:
0450: // rerun promotions
0451: ProductPromoWorker.doPromotions(this , dispatcher);
0452: }
0453: }
0454:
0455: public String getWebSiteId() {
0456: return this .webSiteId;
0457: }
0458:
0459: public void setWebSiteId(String webSiteId) {
0460: this .webSiteId = webSiteId;
0461: }
0462:
0463: public String getPartyId() {
0464: String partyId = null;
0465:
0466: if (partyId == null && getUserLogin() != null) {
0467: partyId = getUserLogin().getString("partyId");
0468: }
0469: if (partyId == null && getAutoUserLogin() != null) {
0470: partyId = getAutoUserLogin().getString("partyId");
0471: }
0472: return partyId;
0473: }
0474:
0475: public Double getPartyDaysSinceCreated(Timestamp nowTimestamp) {
0476: String partyId = this .getPartyId();
0477: if (UtilValidate.isEmpty(partyId)) {
0478: return null;
0479: }
0480: try {
0481: GenericValue party = this .getDelegator()
0482: .findByPrimaryKeyCache("Party",
0483: UtilMisc.toMap("partyId", partyId));
0484: if (party == null) {
0485: return null;
0486: }
0487: Timestamp createdDate = party.getTimestamp("createdDate");
0488: if (createdDate == null) {
0489: return null;
0490: }
0491: double diffMillis = nowTimestamp.getTime()
0492: - createdDate.getTime();
0493: // millis per day: 1000.0 * 60.0 * 60.0 * 24.0 = 86400000.0
0494: return new Double((diffMillis) / 86400000.0);
0495: } catch (GenericEntityException e) {
0496: Debug.logError(e,
0497: "Error looking up party when getting createdDate",
0498: module);
0499: return null;
0500: }
0501: }
0502:
0503: // =======================================================================
0504: // Methods for cart fields
0505: // =======================================================================
0506:
0507: /** Clears out the cart. */
0508: public void clear() {
0509: this .firstAttemptOrderId = null;
0510: this .poNumber = null;
0511: this .orderId = null;
0512:
0513: this .orderShipmentPreference.remove("shippingInstructions");
0514: this .orderShipmentPreference.remove("maySplit");
0515: this .orderShipmentPreference.remove("giftMessage");
0516: this .orderShipmentPreference.remove("isGift");
0517:
0518: this .orderAdditionalEmails = null;
0519: this .freeShippingProductPromoActions.clear();
0520: this .productPromoUseInfoList.clear();
0521: this .productPromoCodes.clear();
0522:
0523: this .clearPaymentMethodIds();
0524: this .clearPaymentMethodTypeIds();
0525:
0526: this .adjustments.clear();
0527: this .expireSingleUsePayments();
0528: this .cartLines.clear();
0529: }
0530:
0531: private void expireSingleUsePayments() {
0532: Iterator i = singleUsePaymentIds.iterator();
0533: Timestamp now = UtilDateTime.nowTimestamp();
0534: while (i.hasNext()) {
0535: String paymentMethodId = (String) i.next();
0536: GenericValue paymentMethod = null;
0537: try {
0538: paymentMethod = delegator.findByPrimaryKey(
0539: "PaymentMethod", UtilMisc.toMap(
0540: "paymentMethodId", paymentMethodId));
0541: } catch (GenericEntityException e) {
0542: Debug.logError(e,
0543: "ERROR: Unable to get payment method record to expire : "
0544: + paymentMethodId, module);
0545: }
0546: if (paymentMethod != null) {
0547: paymentMethod.set("thruDate", now);
0548: try {
0549: paymentMethod.store();
0550: } catch (GenericEntityException e) {
0551: Debug.logError(e,
0552: "Unable to store single use PaymentMethod record : "
0553: + paymentMethod, module);
0554: }
0555: } else {
0556: Debug.logError(
0557: "ERROR: Received back a null payment method record for expired ID : "
0558: + paymentMethodId, module);
0559: }
0560: }
0561: }
0562:
0563: /** Sets the order type. */
0564: public void setOrderType(String orderType) {
0565: this .orderType = orderType;
0566: }
0567:
0568: /** Returns the order type. */
0569: public String getOrderType() {
0570: return this .orderType;
0571: }
0572:
0573: /** Sets the PO Number in the cart. */
0574: public void setPoNumber(String poNumber) {
0575: this .poNumber = poNumber;
0576: }
0577:
0578: /** Returns the po number. */
0579: public String getPoNumber() {
0580: return poNumber;
0581: }
0582:
0583: /** Checks to see if a Payment Method is selected. */
0584: public boolean isPaymentMethodSelected(String paymentMethodId) {
0585: if (paymentMethodId != null) {
0586: return this .paymentMethodIds.contains(paymentMethodId);
0587: } else {
0588: return false;
0589: }
0590: }
0591:
0592: /** Sets the amount of a Payment Method. */
0593: public void setPaymentMethodAmount(String paymentMethodId,
0594: Double amount, boolean isSingleUse) {
0595: if (paymentMethodId != null) {
0596: if (!this .paymentMethodIds.contains(paymentMethodId)) {
0597: this .paymentMethodIds.add(paymentMethodId);
0598: }
0599: this .paymentMethodAmounts.put(paymentMethodId, amount);
0600: }
0601: if (isSingleUse) {
0602: this .singleUsePaymentIds.add(paymentMethodId);
0603: }
0604: }
0605:
0606: public void setPaymentMethodAmount(String paymentMethodId,
0607: Double amount) {
0608: setPaymentMethodAmount(paymentMethodId, amount, false);
0609: }
0610:
0611: /** Returns the Payment Method Ids. */
0612: public List getPaymentMethodIds() {
0613: return paymentMethodIds;
0614: }
0615:
0616: /** Clears the list of Payment Method Ids. */
0617: public void clearPaymentMethodIds() {
0618: this .paymentMethodIds.clear();
0619: this .paymentMethodAmounts.clear();
0620: }
0621:
0622: /** Clears a specific Payment Method Id. */
0623: public void clearPaymentMethodId(String paymentMethodId) {
0624: this .paymentMethodIds.remove(paymentMethodId);
0625: this .paymentMethodAmounts.remove(paymentMethodId);
0626: }
0627:
0628: /** Add the Payment Method Type Id to the cart. */
0629: public void addPaymentMethodTypeId(String paymentMethodTypeId) {
0630: addPaymentMethodTypeId(paymentMethodTypeId, null);
0631: }
0632:
0633: /** Add the Payment Method Type Id with amount to the cart. */
0634: public void addPaymentMethodTypeId(String paymentMethodTypeId,
0635: Double amount) {
0636: if (paymentMethodTypeId != null) {
0637: this .paymentMethodTypeIds.add(paymentMethodTypeId);
0638: this .paymentMethodTypeAmounts.put(paymentMethodTypeId,
0639: amount);
0640: }
0641: }
0642:
0643: /** Returns set amount of the Payment Method. */
0644: public Double getPaymentMethodAmount(String paymentMethodId) {
0645: if (this .paymentMethodAmounts.get(paymentMethodId) != null) {
0646: return (Double) this .paymentMethodAmounts
0647: .get(paymentMethodId);
0648: } else {
0649: return new Double(0.00);
0650: }
0651: }
0652:
0653: /** Returns the total amount of the selected Payment Method(s). */
0654: public double getSelectedPaymentMethodsTotal() {
0655: double paymentMethodsTotal = 0.00;
0656: Iterator i = this .getPaymentMethodIds().iterator();
0657: while (i.hasNext()) {
0658: String paymentMethodId = (String) i.next();
0659: Double paymentTotal = (Double) this .paymentMethodAmounts
0660: .get(paymentMethodId);
0661: if (paymentTotal != null) {
0662: paymentMethodsTotal += paymentTotal.doubleValue();
0663: }
0664: }
0665: return paymentMethodsTotal;
0666: }
0667:
0668: /** Returns a list of PaymentMethod value objects selected in the cart. */
0669: public List getSelectedPaymentMethods() {
0670: List ids = getPaymentMethodIds();
0671: List methods = new ArrayList();
0672: try {
0673: Iterator i = ids.iterator();
0674: while (i.hasNext()) {
0675: String id = (String) i.next();
0676: GenericValue paymentMethod = this .getDelegator()
0677: .findByPrimaryKeyCache("PaymentMethod",
0678: UtilMisc.toMap("paymentMethodId", id));
0679: methods.add(paymentMethod);
0680: }
0681: } catch (GenericEntityException e) {
0682: Debug
0683: .logError(
0684: e,
0685: "Unable to get selected payment methods from the database",
0686: module);
0687: return null;
0688: }
0689: return methods;
0690: }
0691:
0692: /** Returns the Payment Method Ids. */
0693: public List getPaymentMethodTypeIds() {
0694: return paymentMethodTypeIds;
0695: }
0696:
0697: /** Clears the list of Payment Method Type Ids. */
0698: public void clearPaymentMethodTypeIds() {
0699: this .paymentMethodTypeIds.clear();
0700: this .paymentMethodTypeAmounts.clear();
0701: }
0702:
0703: /** Sets the billing account id string. */
0704: public void setBillingAccount(String billingAccountId, double amount) {
0705: this .billingAccountId = billingAccountId;
0706: this .billingAccountAmt = amount;
0707: }
0708:
0709: /** Returns the billing message string. */
0710: public String getBillingAccountId() {
0711: return this .billingAccountId;
0712: }
0713:
0714: /** Returns the amount to be billed to the billing account.*/
0715: public double getBillingAccountAmount() {
0716: return this .billingAccountAmt;
0717: }
0718:
0719: /** Sets the shipping contact mech id. */
0720: public void setShippingContactMechId(String shippingContactMechId) {
0721: // set the shipping address
0722: this .addContactMech("SHIPPING_LOCATION", shippingContactMechId);
0723: }
0724:
0725: /** Returns the shipping message string. */
0726: public String getShippingContactMechId() {
0727: return this .getContactMech("SHIPPING_LOCATION");
0728: }
0729:
0730: /** Returns the order level shipping amount */
0731: public double getOrderShipping() {
0732: return OrderReadHelper.calcOrderAdjustments(this
0733: .getAdjustments(), this .getSubTotal(), false, false,
0734: true);
0735: }
0736:
0737: /** Sets the shipment method type. */
0738: public void setShipmentMethodTypeId(String shipmentMethodTypeId) {
0739: orderShipmentPreference.set("shipmentMethodTypeId",
0740: shipmentMethodTypeId);
0741: }
0742:
0743: /** Returns the shipment method type */
0744: public String getShipmentMethodTypeId() {
0745: return orderShipmentPreference
0746: .getString("shipmentMethodTypeId");
0747: }
0748:
0749: /** Sets the shipping instructions. */
0750: public void setShippingInstructions(String shippingInstructions) {
0751: orderShipmentPreference.set("shippingInstructions",
0752: shippingInstructions);
0753: }
0754:
0755: /** Returns the shipping instructions. */
0756: public String getShippingInstructions() {
0757: return orderShipmentPreference
0758: .getString("shippingInstructions");
0759: }
0760:
0761: public void setMaySplit(Boolean maySplit) {
0762: orderShipmentPreference.set("maySplit", maySplit);
0763: }
0764:
0765: /** Returns Boolean.TRUE if the order may be split (null if unspecified) */
0766: public Boolean getMaySplit() {
0767: return orderShipmentPreference.getBoolean("maySplit");
0768: }
0769:
0770: public void setGiftMessage(String giftMessage) {
0771: orderShipmentPreference.set("giftMessage", giftMessage);
0772: }
0773:
0774: public String getGiftMessage() {
0775: return orderShipmentPreference.getString("giftMessage");
0776: }
0777:
0778: public void setIsGift(Boolean isGift) {
0779: orderShipmentPreference.set("isGift", isGift);
0780: }
0781:
0782: public Boolean getIsGift() {
0783: return orderShipmentPreference.getBoolean("isGift");
0784: }
0785:
0786: public GenericValue getOrderShipmentPreference() {
0787: return this .orderShipmentPreference;
0788: }
0789:
0790: public void setCarrierPartyId(String carrierPartyId) {
0791: orderShipmentPreference.set("carrierPartyId", carrierPartyId);
0792: }
0793:
0794: public String getCarrierPartyId() {
0795: return orderShipmentPreference.getString("carrierPartyId");
0796: }
0797:
0798: public void setOrderAdditionalEmails(String orderAdditionalEmails) {
0799: this .orderAdditionalEmails = orderAdditionalEmails;
0800: }
0801:
0802: public String getOrderAdditionalEmails() {
0803: return orderAdditionalEmails;
0804: }
0805:
0806: public List getPaymentMethods() {
0807: List paymentMethods = new LinkedList();
0808:
0809: if (paymentMethodIds != null && paymentMethodIds.size() > 0) {
0810: Iterator pmIdsIter = paymentMethodIds.iterator();
0811:
0812: while (pmIdsIter.hasNext()) {
0813: String paymentMethodId = (String) pmIdsIter.next();
0814:
0815: try {
0816: paymentMethods.add(getDelegator().findByPrimaryKey(
0817: "PaymentMethod",
0818: UtilMisc.toMap("paymentMethodId",
0819: paymentMethodId)));
0820: } catch (GenericEntityException e) {
0821: Debug.logError(e, module);
0822: }
0823: }
0824: }
0825: return paymentMethods;
0826: }
0827:
0828: public List getGiftCards() {
0829: List paymentMethods = this .getPaymentMethods();
0830: List giftCards = new LinkedList();
0831: if (paymentMethods != null) {
0832: Iterator i = paymentMethods.iterator();
0833: while (i.hasNext()) {
0834: GenericValue pm = (GenericValue) i.next();
0835: if ("GIFT_CARD".equals(pm
0836: .getString("paymentMethodTypeId"))) {
0837: try {
0838: GenericValue gc = pm.getRelatedOne("GiftCard");
0839: giftCards.add(gc);
0840: } catch (GenericEntityException e) {
0841: Debug.logError(e,
0842: "Unable to get gift card record from payment method : "
0843: + pm, module);
0844: }
0845: }
0846: }
0847: }
0848: return giftCards;
0849: }
0850:
0851: public GenericValue getShippingAddress() {
0852: if (this .getShippingContactMechId() != null) {
0853: try {
0854: return getDelegator().findByPrimaryKey(
0855: "PostalAddress",
0856: UtilMisc.toMap("contactMechId", this
0857: .getShippingContactMechId()));
0858: } catch (GenericEntityException e) {
0859: Debug.logWarning(e.toString(), module);
0860: return null;
0861: }
0862: } else {
0863: return null;
0864: }
0865: }
0866:
0867: /** Returns the tax amount from the cart object. */
0868: public double getTotalSalesTax() {
0869: double tempTax = 0.0;
0870: Iterator i = iterator();
0871:
0872: while (i.hasNext()) {
0873: tempTax += ((ShoppingCartItem) i.next()).getItemTax();
0874: }
0875:
0876: tempTax += OrderReadHelper.calcOrderAdjustments(this
0877: .getAdjustments(), getSubTotal(), false, true, false);
0878:
0879: return tempTax;
0880: }
0881:
0882: /** Returns the shipping amount from the cart object. */
0883: public double getTotalShipping() {
0884: double tempShipping = 0.0;
0885: Iterator i = iterator();
0886:
0887: while (i.hasNext()) {
0888: tempShipping += ((ShoppingCartItem) i.next())
0889: .getItemShipping();
0890: }
0891:
0892: tempShipping += OrderReadHelper.calcOrderAdjustments(this
0893: .getAdjustments(), getSubTotal(), false, false, true);
0894:
0895: return tempShipping;
0896: }
0897:
0898: /** Returns the item-total in the cart (not including discount/tax/shipping). */
0899: public double getItemTotal() {
0900: double itemTotal = 0.00;
0901: Iterator i = iterator();
0902:
0903: while (i.hasNext()) {
0904: itemTotal += ((ShoppingCartItem) i.next()).getBasePrice();
0905: }
0906: return itemTotal;
0907: }
0908:
0909: /** Returns the sub-total in the cart (item-total - discount). */
0910: public double getSubTotal() {
0911: double itemsTotal = 0.00;
0912: Iterator i = iterator();
0913:
0914: while (i.hasNext()) {
0915: itemsTotal += ((ShoppingCartItem) i.next())
0916: .getItemSubTotal();
0917: }
0918: return itemsTotal;
0919: }
0920:
0921: /** Returns the sub-total in the cart (item-total - discount). */
0922: public double getSubTotalForPromotions() {
0923: double itemsTotal = 0.00;
0924: Iterator i = iterator();
0925:
0926: while (i.hasNext()) {
0927: ShoppingCartItem cartItem = (ShoppingCartItem) i.next();
0928: GenericValue product = cartItem.getProduct();
0929: if (product != null
0930: && "N".equals(product
0931: .getString("includeInPromotions"))) {
0932: // don't include in total if this is the case...
0933: continue;
0934: }
0935: itemsTotal += cartItem.getItemSubTotal();
0936: }
0937: return itemsTotal;
0938: }
0939:
0940: /** Add a contact mech to this purpose; the contactMechPurposeTypeId is required */
0941: public void addContactMech(String contactMechPurposeTypeId,
0942: String contactMechId) {
0943: if (contactMechPurposeTypeId == null)
0944: throw new IllegalArgumentException(
0945: "You must specify a contactMechPurposeTypeId to add a ContactMech");
0946: contactMechIdsMap.put(contactMechPurposeTypeId, contactMechId);
0947: }
0948:
0949: /** Get the contactMechId for this cart given the contactMechPurposeTypeId */
0950: public String getContactMech(String contactMechPurposeTypeId) {
0951: return (String) contactMechIdsMap.get(contactMechPurposeTypeId);
0952: }
0953:
0954: /** Remove the contactMechId from this cart given the contactMechPurposeTypeId */
0955: public String removeContactMech(String contactMechPurposeTypeId) {
0956: return (String) contactMechIdsMap
0957: .remove(contactMechPurposeTypeId);
0958: }
0959:
0960: public Map getOrderContactMechIds() {
0961: return this .contactMechIdsMap;
0962: }
0963:
0964: /** Get a List of adjustments on the order (ie cart) */
0965: public List getAdjustments() {
0966: return adjustments;
0967: }
0968:
0969: /** 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 */
0970: public void addAdjustment(GenericValue adjustment) {
0971: adjustments.add(adjustment);
0972: }
0973:
0974: public void removeAdjustment(int index) {
0975: adjustments.remove(index);
0976: }
0977:
0978: /** go through the order adjustments and remove all adjustments with the given type */
0979: public void removeAdjustmentByType(String orderAdjustmentTypeId) {
0980: if (orderAdjustmentTypeId == null)
0981: return;
0982:
0983: // make a list of adjustment lists including the cart adjustments and the cartItem adjustments for each item
0984: List adjsLists = new LinkedList();
0985:
0986: if (this .getAdjustments() != null) {
0987: adjsLists.add(this .getAdjustments());
0988: }
0989: Iterator cartIterator = this .iterator();
0990:
0991: while (cartIterator.hasNext()) {
0992: ShoppingCartItem item = (ShoppingCartItem) cartIterator
0993: .next();
0994:
0995: if (item.getAdjustments() != null) {
0996: adjsLists.add(item.getAdjustments());
0997: }
0998: }
0999:
1000: Iterator adjsListsIter = adjsLists.iterator();
1001:
1002: while (adjsListsIter.hasNext()) {
1003: List adjs = (List) adjsListsIter.next();
1004:
1005: if (adjs != null) {
1006: for (int i = 0; i < adjs.size();) {
1007: GenericValue orderAdjustment = (GenericValue) adjs
1008: .get(i);
1009:
1010: if (orderAdjustmentTypeId.equals(orderAdjustment
1011: .getString("orderAdjustmentTypeId"))) {
1012: adjs.remove(i);
1013: } else {
1014: i++;
1015: }
1016: }
1017: }
1018: }
1019: }
1020:
1021: public double getOrderOtherAdjustmentTotal() {
1022: return OrderReadHelper.calcOrderAdjustments(this
1023: .getAdjustments(), getSubTotal(), true, false, false);
1024: }
1025:
1026: /** Returns the total from the cart, including tax/shipping. */
1027: public double getGrandTotal() {
1028: List orderAdjustments = this .makeAllAdjustments();
1029: List orderItems = this .makeOrderItems();
1030: return OrderReadHelper.getOrderGrandTotal(orderItems,
1031: orderAdjustments);
1032: }
1033:
1034: /** Returns the SHIPPABLE item-total in the cart. */
1035: public double getShippableTotal() {
1036: double itemTotal = 0.0;
1037: Iterator i = iterator();
1038:
1039: while (i.hasNext()) {
1040: ShoppingCartItem item = (ShoppingCartItem) i.next();
1041:
1042: if (item.shippingApplies())
1043: itemTotal += item.getItemSubTotal();
1044: }
1045: return itemTotal;
1046: }
1047:
1048: /** Returns the total quantity in the cart. */
1049: public double getTotalQuantity() {
1050: double count = 0.0;
1051: Iterator i = iterator();
1052:
1053: while (i.hasNext()) {
1054: count += ((ShoppingCartItem) i.next()).getQuantity();
1055: }
1056: return count;
1057: }
1058:
1059: /** Returns the total SHIPPABLE quantity in the cart. */
1060: public double getShippableQuantity() {
1061: double count = 0.0;
1062: Iterator i = iterator();
1063:
1064: while (i.hasNext()) {
1065: ShoppingCartItem item = (ShoppingCartItem) i.next();
1066:
1067: if (item.shippingApplies()) {
1068: count += item.getQuantity();
1069: }
1070: }
1071: return count;
1072: }
1073:
1074: /** Returns the total SHIPPABLE weight in the cart. */
1075: public double getShippableWeight() {
1076: double weight = 0.0;
1077: Iterator i = iterator();
1078:
1079: while (i.hasNext()) {
1080: ShoppingCartItem item = (ShoppingCartItem) i.next();
1081:
1082: if (item.shippingApplies()) {
1083: weight += (item.getWeight() * item.getQuantity());
1084: }
1085: }
1086: return weight;
1087: }
1088:
1089: /** Returns a List of shippable item's size. */
1090: public List getShippableSizes() {
1091: List shippableSizes = new LinkedList();
1092: Iterator i = iterator();
1093:
1094: while (i.hasNext()) {
1095: ShoppingCartItem item = (ShoppingCartItem) i.next();
1096:
1097: if (item.shippingApplies()) {
1098: shippableSizes.add(new Double(item.getSize()));
1099: }
1100: }
1101: return shippableSizes;
1102: }
1103:
1104: /** Returns the total weight in the cart. */
1105: public double getTotalWeight() {
1106: double weight = 0.0;
1107: Iterator i = iterator();
1108:
1109: while (i.hasNext()) {
1110: ShoppingCartItem item = (ShoppingCartItem) i.next();
1111:
1112: weight += (item.getWeight() * item.getQuantity());
1113: }
1114: return weight;
1115: }
1116:
1117: /** Returns a Map of all features applied to products in the cart with quantities. */
1118: public Map getFeatureIdQtyMap() {
1119: Map featureMap = new HashMap();
1120: Iterator i = iterator();
1121: while (i.hasNext()) {
1122: ShoppingCartItem item = (ShoppingCartItem) i.next();
1123: featureMap.putAll(item.getFeatureIdQtyMap());
1124: }
1125: return featureMap;
1126: }
1127:
1128: /** Returns true if the user wishes to view the cart everytime an item is added. */
1129: public boolean viewCartOnAdd() {
1130: return viewCartOnAdd;
1131: }
1132:
1133: /** Returns true if the user wishes to view the cart everytime an item is added. */
1134: public void setViewCartOnAdd(boolean viewCartOnAdd) {
1135: this .viewCartOnAdd = viewCartOnAdd;
1136: }
1137:
1138: /** Returns the order ID associated with this cart or null if no order has been created yet. */
1139: public String getOrderId() {
1140: return this .orderId;
1141: }
1142:
1143: /** Returns the first attempt order ID associated with this cart or null if no order has been created yet. */
1144: public String getFirstAttemptOrderId() {
1145: return this .firstAttemptOrderId;
1146: }
1147:
1148: /** Sets the orderId associated with this cart. */
1149: public void setOrderId(String orderId) {
1150: this .orderId = orderId;
1151: }
1152:
1153: /** Sets the first attempt orderId for this cart. */
1154: public void setFirstAttemptOrderId(String orderId) {
1155: this .firstAttemptOrderId = orderId;
1156: }
1157:
1158: /** Sets the currency for the cart. */
1159: public void setCurrency(LocalDispatcher dispatcher,
1160: String currencyUom) throws CartItemModifyException {
1161: String previousCurrency = this .currencyUom;
1162: this .currencyUom = currencyUom;
1163: if (!previousCurrency.equals(this .currencyUom)) {
1164: Iterator itemIterator = this .iterator();
1165: while (itemIterator.hasNext()) {
1166: ShoppingCartItem item = (ShoppingCartItem) itemIterator
1167: .next();
1168: item.updatePrice(dispatcher, this );
1169: }
1170: }
1171: }
1172:
1173: /** Get the current currency setting. */
1174: public String getCurrency() {
1175: if (this .currencyUom != null) {
1176: return this .currencyUom;
1177: } else {
1178: return UtilProperties.getPropertyValue(
1179: "general.properties", "currency.uom.id.default",
1180: "USD");
1181: }
1182: }
1183:
1184: public void removeAllFreeShippingProductPromoActions() {
1185: this .freeShippingProductPromoActions.clear();
1186: }
1187:
1188: /** Removes a free shipping ProductPromoAction by trying to find one in the list with the same primary key. */
1189: public void removeFreeShippingProductPromoAction(
1190: GenericPK productPromoActionPK) {
1191: if (productPromoActionPK == null)
1192: return;
1193:
1194: Iterator fsppas = this .freeShippingProductPromoActions
1195: .iterator();
1196: while (fsppas.hasNext()) {
1197: if (productPromoActionPK.equals(((GenericValue) fsppas
1198: .next()).getPrimaryKey())) {
1199: fsppas.remove();
1200: }
1201: }
1202: }
1203:
1204: /** Adds a ProductPromoAction to be used for free shipping (must be of type free shipping, or nothing will be done). */
1205: public void addFreeShippingProductPromoAction(
1206: GenericValue productPromoAction) {
1207: if (productPromoAction == null)
1208: return;
1209: // is this a free shipping action?
1210: if (!"PROMO_FREE_SHIPPING".equals(productPromoAction
1211: .getString("productPromoActionEnumId")))
1212: return; // Changed 1-5-04 by Si Chen
1213:
1214: // to easily make sure that no duplicate exists, do a remove first
1215: this .removeFreeShippingProductPromoAction(productPromoAction
1216: .getPrimaryKey());
1217: this .freeShippingProductPromoActions.add(productPromoAction);
1218: }
1219:
1220: public List getFreeShippingProductPromoActions() {
1221: return this .freeShippingProductPromoActions;
1222: }
1223:
1224: public void addProductPromoUse(String productPromoId,
1225: String productPromoCodeId, double totalDiscountAmount,
1226: double quantityLeftInActions) {
1227: if (UtilValidate.isNotEmpty(productPromoCodeId)
1228: && !this .productPromoCodes.contains(productPromoCodeId)) {
1229: throw new IllegalStateException(
1230: "Cannot add a use to a promo code use for a code that has not been entered.");
1231: }
1232: if (Debug.verboseOn())
1233: Debug.logVerbose("Used promotion [" + productPromoId
1234: + "] with code [" + productPromoCodeId
1235: + "] for total discount [" + totalDiscountAmount
1236: + "] and quantity left in actions ["
1237: + quantityLeftInActions + "]", module);
1238: this .productPromoUseInfoList.add(new ProductPromoUseInfo(
1239: productPromoId, productPromoCodeId,
1240: totalDiscountAmount, quantityLeftInActions));
1241: }
1242:
1243: public void clearProductPromoUseInfo() {
1244: // clear out info for general promo use
1245: this .productPromoUseInfoList.clear();
1246: }
1247:
1248: public void clearCartItemUseInPromoInfo() {
1249: // clear out info about which cart items have been used in promos
1250: Iterator cartLineIter = this .iterator();
1251: while (cartLineIter.hasNext()) {
1252: ShoppingCartItem cartLine = (ShoppingCartItem) cartLineIter
1253: .next();
1254: cartLine.clearPromoRuleUseInfo();
1255: }
1256: }
1257:
1258: public Iterator getProductPromoUseInfoIter() {
1259: return productPromoUseInfoList.iterator();
1260: }
1261:
1262: public double getProductPromoUseTotalDiscount(String productPromoId) {
1263: if (productPromoId == null)
1264: return 0;
1265: double totalDiscount = 0;
1266: Iterator productPromoUseInfoIter = this .productPromoUseInfoList
1267: .iterator();
1268: while (productPromoUseInfoIter.hasNext()) {
1269: ProductPromoUseInfo productPromoUseInfo = (ProductPromoUseInfo) productPromoUseInfoIter
1270: .next();
1271: if (productPromoId
1272: .equals(productPromoUseInfo.productPromoId)) {
1273: totalDiscount += productPromoUseInfo
1274: .getTotalDiscountAmount();
1275: }
1276: }
1277: return totalDiscount;
1278: }
1279:
1280: public int getProductPromoUseCount(String productPromoId) {
1281: if (productPromoId == null)
1282: return 0;
1283: int useCount = 0;
1284: Iterator productPromoUseInfoIter = this .productPromoUseInfoList
1285: .iterator();
1286: while (productPromoUseInfoIter.hasNext()) {
1287: ProductPromoUseInfo productPromoUseInfo = (ProductPromoUseInfo) productPromoUseInfoIter
1288: .next();
1289: if (productPromoId
1290: .equals(productPromoUseInfo.productPromoId)) {
1291: useCount++;
1292: }
1293: }
1294: return useCount;
1295: }
1296:
1297: public int getProductPromoCodeUse(String productPromoCodeId) {
1298: if (productPromoCodeId == null)
1299: return 0;
1300: int useCount = 0;
1301: Iterator productPromoUseInfoIter = this .productPromoUseInfoList
1302: .iterator();
1303: while (productPromoUseInfoIter.hasNext()) {
1304: ProductPromoUseInfo productPromoUseInfo = (ProductPromoUseInfo) productPromoUseInfoIter
1305: .next();
1306: if (productPromoCodeId
1307: .equals(productPromoUseInfo.productPromoCodeId)) {
1308: useCount++;
1309: }
1310: }
1311: return useCount;
1312: }
1313:
1314: public void clearAllPromotionInformation() {
1315: this .clearAllPromotionAdjustments();
1316:
1317: // remove all free shipping promo actions
1318: this .removeAllFreeShippingProductPromoActions();
1319:
1320: // clear promo uses & reset promo code uses, and reset info about cart items used for promos (ie qualifiers and benefiters)
1321: this .clearProductPromoUseInfo();
1322: this .clearCartItemUseInPromoInfo();
1323: }
1324:
1325: public void clearAllPromotionAdjustments() {
1326: // remove cart adjustments from promo actions
1327: List cartAdjustments = this .getAdjustments();
1328: if (cartAdjustments != null) {
1329: Iterator cartAdjustmentIter = cartAdjustments.iterator();
1330: while (cartAdjustmentIter.hasNext()) {
1331: GenericValue checkOrderAdjustment = (GenericValue) cartAdjustmentIter
1332: .next();
1333: if (UtilValidate.isNotEmpty(checkOrderAdjustment
1334: .getString("productPromoId"))
1335: && UtilValidate.isNotEmpty(checkOrderAdjustment
1336: .getString("productPromoRuleId"))
1337: && UtilValidate.isNotEmpty(checkOrderAdjustment
1338: .getString("productPromoActionSeqId"))) {
1339: cartAdjustmentIter.remove();
1340: }
1341: }
1342: }
1343:
1344: // remove cart lines that are promos (ie GWPs) and cart line adjustments from promo actions
1345: Iterator cartItemIter = this .iterator();
1346: while (cartItemIter.hasNext()) {
1347: ShoppingCartItem checkItem = (ShoppingCartItem) cartItemIter
1348: .next();
1349: if (checkItem.getIsPromo()) {
1350: cartItemIter.remove();
1351: } else {
1352: // found a promo item with the productId, see if it has a matching adjustment on it
1353: Iterator checkOrderAdjustments = UtilMisc
1354: .toIterator(checkItem.getAdjustments());
1355: while (checkOrderAdjustments != null
1356: && checkOrderAdjustments.hasNext()) {
1357: GenericValue checkOrderAdjustment = (GenericValue) checkOrderAdjustments
1358: .next();
1359: if (UtilValidate.isNotEmpty(checkOrderAdjustment
1360: .getString("productPromoId"))
1361: && UtilValidate
1362: .isNotEmpty(checkOrderAdjustment
1363: .getString("productPromoRuleId"))
1364: && UtilValidate
1365: .isNotEmpty(checkOrderAdjustment
1366: .getString("productPromoActionSeqId"))) {
1367: checkOrderAdjustments.remove();
1368: }
1369: }
1370: }
1371: }
1372: }
1373:
1374: /** 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
1375: * @param productPromoCodeId The promotion code to check and add
1376: * @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.
1377: */
1378: public String addProductPromoCode(String productPromoCodeId,
1379: LocalDispatcher dispatcher) {
1380: if (this .productPromoCodes.contains(productPromoCodeId)) {
1381: return "The promotion code [" + productPromoCodeId
1382: + "] has already been entered.";
1383: }
1384: // if the promo code requires it make sure the code is valid
1385: String checkResult = ProductPromoWorker.checkCanUsePromoCode(
1386: productPromoCodeId, this .getPartyId(), this
1387: .getDelegator());
1388: if (checkResult == null) {
1389: this .productPromoCodes.add(productPromoCodeId);
1390: // new promo code, re-evaluate promos
1391: ProductPromoWorker.doPromotions(this , dispatcher);
1392: return null;
1393: } else {
1394: return checkResult;
1395: }
1396: }
1397:
1398: public Set getProductPromoCodesEntered() {
1399: return this .productPromoCodes;
1400: }
1401:
1402: public synchronized void resetPromoRuleUse(String productPromoId,
1403: String productPromoRuleId) {
1404: Iterator lineIter = this .iterator();
1405: while (lineIter.hasNext()) {
1406: ShoppingCartItem cartItem = (ShoppingCartItem) lineIter
1407: .next();
1408: cartItem.resetPromoRuleUse(productPromoId,
1409: productPromoRuleId);
1410: }
1411: }
1412:
1413: public synchronized void confirmPromoRuleUse(String productPromoId,
1414: String productPromoRuleId) {
1415: Iterator lineIter = this .iterator();
1416: while (lineIter.hasNext()) {
1417: ShoppingCartItem cartItem = (ShoppingCartItem) lineIter
1418: .next();
1419: cartItem.confirmPromoRuleUse(productPromoId,
1420: productPromoRuleId);
1421: }
1422: }
1423:
1424: // =======================================================================
1425: // Methods used for order creation
1426: // =======================================================================
1427:
1428: private void explodeItems(LocalDispatcher dispatcher) {
1429: synchronized (cartLines) {
1430: if (dispatcher != null) {
1431: List cartLineItems = new LinkedList(cartLines);
1432: Iterator itemIter = cartLineItems.iterator();
1433:
1434: while (itemIter.hasNext()) {
1435: ShoppingCartItem item = (ShoppingCartItem) itemIter
1436: .next();
1437:
1438: Debug.logInfo("Item qty: " + item.getQuantity(),
1439: module);
1440: try {
1441: item.explodeItem(this , dispatcher);
1442: } catch (CartItemModifyException e) {
1443: Debug
1444: .logError(
1445: e,
1446: "Problem exploding item! Item not exploded.",
1447: module);
1448: }
1449: }
1450: }
1451: }
1452: }
1453:
1454: public List makeOrderItems() {
1455: return makeOrderItems(false, null);
1456: }
1457:
1458: public List makeOrderItems(boolean explodeItems,
1459: LocalDispatcher dispatcher) {
1460: // do the explosion
1461: if (explodeItems && dispatcher != null)
1462: explodeItems(dispatcher);
1463:
1464: // now build the lines
1465: synchronized (cartLines) {
1466: List result = new LinkedList();
1467: long cartLineSize = cartLines.size();
1468: long seqId = 1;
1469: Iterator itemIter = cartLines.iterator();
1470:
1471: while (itemIter.hasNext()) {
1472: ShoppingCartItem item = (ShoppingCartItem) itemIter
1473: .next();
1474:
1475: // format the string with enough leading zeroes for the number of cartLines
1476: NumberFormat nf = NumberFormat.getNumberInstance();
1477:
1478: if (cartLineSize > 9) {
1479: nf.setMinimumIntegerDigits(2);
1480: } else if (cartLineSize > 99) {
1481: nf.setMinimumIntegerDigits(3);
1482: } else if (cartLineSize > 999) {
1483: nf.setMinimumIntegerDigits(4);
1484: } else if (cartLineSize > 9999) {
1485: // if it's more than 9999, something's up... hit the sky
1486: nf.setMinimumIntegerDigits(18);
1487: }
1488:
1489: String orderItemSeqId = nf.format(seqId);
1490:
1491: seqId++;
1492: item.setOrderItemSeqId(orderItemSeqId);
1493:
1494: // the initial status for all item types
1495: String initialStatus = "ITEM_CREATED";
1496:
1497: GenericValue orderItem = getDelegator().makeValue(
1498: "OrderItem", null);
1499: orderItem.set("orderItemSeqId", orderItemSeqId);
1500: orderItem.set("orderItemTypeId", item.getItemType());
1501: orderItem.set("productId", item.getProductId());
1502: orderItem.set("prodCatalogId", item.getProdCatalogId());
1503: orderItem.set("productCategoryId", item
1504: .getProductCategoryId());
1505: orderItem.set("quantity",
1506: new Double(item.getQuantity()));
1507: orderItem.set("unitPrice", new Double(item
1508: .getBasePrice()));
1509: orderItem.set("unitListPrice", new Double(item
1510: .getListPrice()));
1511:
1512: orderItem.set("shoppingListId", item
1513: .getShoppingListId());
1514: orderItem.set("shoppingListItemSeqId", item
1515: .getShoppingListItemSeqId());
1516:
1517: orderItem.set("itemDescription", item.getName());
1518: orderItem.set("comments", item.getItemComment());
1519: orderItem.set("correspondingPoId", this .getPoNumber());
1520: orderItem.set("statusId", initialStatus);
1521: result.add(orderItem);
1522: // don't do anything with adjustments here, those will be added below in makeAllAdjustments
1523: }
1524: return result;
1525: }
1526: }
1527:
1528: /** make a list of all adjustments including order adjustments, order line adjustments, and special adjustments (shipping and tax if applicable) */
1529: public List makeAllAdjustments() {
1530: List allAdjs = new LinkedList();
1531:
1532: // before returning adjustments, go through them to find all that need counter adjustments (for instance: free shipping)
1533: Iterator allAdjsIter = this .getAdjustments().iterator();
1534:
1535: while (allAdjsIter.hasNext()) {
1536: GenericValue orderAdjustment = (GenericValue) allAdjsIter
1537: .next();
1538:
1539: allAdjs.add(orderAdjustment);
1540:
1541: if ("SHIPPING_CHARGES".equals(orderAdjustment
1542: .get("orderAdjustmentTypeId"))) {
1543: Iterator fsppas = this .freeShippingProductPromoActions
1544: .iterator();
1545:
1546: while (fsppas.hasNext()) {
1547: GenericValue productPromoAction = (GenericValue) fsppas
1548: .next();
1549:
1550: if ((productPromoAction.get("productId") == null || productPromoAction
1551: .getString("productId").equals(
1552: this .getShipmentMethodTypeId()))
1553: && (productPromoAction.get("partyId") == null || productPromoAction
1554: .getString("partyId").equals(
1555: this .getCarrierPartyId()))) {
1556: Double shippingAmount = new Double(
1557: -OrderReadHelper.calcOrderAdjustment(
1558: orderAdjustment, getSubTotal()));
1559: // always set orderAdjustmentTypeId to SHIPPING_CHARGES for free shipping adjustments
1560: GenericValue fsOrderAdjustment = getDelegator()
1561: .makeValue(
1562: "OrderAdjustment",
1563: UtilMisc
1564: .toMap(
1565: "orderItemSeqId",
1566: orderAdjustment
1567: .get("orderItemSeqId"),
1568: "orderAdjustmentTypeId",
1569: "SHIPPING_CHARGES",
1570: "amount",
1571: shippingAmount,
1572: "productPromoId",
1573: productPromoAction
1574: .get("productPromoId"),
1575: "productPromoRuleId",
1576: productPromoAction
1577: .get("productPromoRuleId"),
1578: "productPromoActionSeqId",
1579: productPromoAction
1580: .get("productPromoActionSeqId")));
1581:
1582: allAdjs.add(fsOrderAdjustment);
1583:
1584: // if free shipping IS applied to this orderAdjustment, break
1585: // out of the loop so that even if there are multiple free
1586: // shipping adjustments that apply to this orderAdjustment it
1587: // will only be compensated for once
1588: break;
1589: }
1590: }
1591: }
1592: }
1593:
1594: // add all of the item adjustments to this list too
1595: Iterator itemIter = cartLines.iterator();
1596:
1597: while (itemIter.hasNext()) {
1598: ShoppingCartItem item = (ShoppingCartItem) itemIter.next();
1599: Collection adjs = item.getAdjustments();
1600:
1601: if (adjs != null) {
1602: Iterator adjIter = adjs.iterator();
1603:
1604: while (adjIter.hasNext()) {
1605: GenericValue orderAdjustment = (GenericValue) adjIter
1606: .next();
1607:
1608: orderAdjustment.set("orderItemSeqId", item
1609: .getOrderItemSeqId());
1610: allAdjs.add(orderAdjustment);
1611:
1612: if ("SHIPPING_CHARGES".equals(orderAdjustment
1613: .get("orderAdjustmentTypeId"))) {
1614: Iterator fsppas = this .freeShippingProductPromoActions
1615: .iterator();
1616:
1617: while (fsppas.hasNext()) {
1618: GenericValue productPromoAction = (GenericValue) fsppas
1619: .next();
1620:
1621: if ((productPromoAction.get("productId") == null || productPromoAction
1622: .getString("productId")
1623: .equals(
1624: item
1625: .getShipmentMethodTypeId()))
1626: && (productPromoAction
1627: .get("partyId") == null || productPromoAction
1628: .getString("partyId")
1629: .equals(
1630: item
1631: .getCarrierPartyId()))) {
1632: Double shippingAmount = new Double(
1633: -OrderReadHelper
1634: .calcItemAdjustment(
1635: orderAdjustment,
1636: new Double(
1637: item
1638: .getQuantity()),
1639: new Double(
1640: item
1641: .getItemSubTotal())));
1642: // always set orderAdjustmentTypeId to SHIPPING_CHARGES for free shipping adjustments
1643: GenericValue fsOrderAdjustment = getDelegator()
1644: .makeValue(
1645: "OrderAdjustment",
1646: UtilMisc
1647: .toMap(
1648: "orderItemSeqId",
1649: orderAdjustment
1650: .get("orderItemSeqId"),
1651: "orderAdjustmentTypeId",
1652: "SHIPPING_CHARGES",
1653: "amount",
1654: shippingAmount,
1655: "productPromoId",
1656: productPromoAction
1657: .get("productPromoId"),
1658: "productPromoRuleId",
1659: productPromoAction
1660: .get("productPromoRuleId"),
1661: "productPromoActionSeqId",
1662: productPromoAction
1663: .get("productPromoActionSeqId")));
1664:
1665: allAdjs.add(fsOrderAdjustment);
1666:
1667: // if free shipping IS applied to this orderAdjustment, break
1668: // out of the loop so that even if there are multiple free
1669: // shipping adjustments that apply to this orderAdjustment it
1670: // will only be compensated for once
1671: break;
1672: }
1673: }
1674: }
1675: }
1676: }
1677: }
1678:
1679: return allAdjs;
1680: }
1681:
1682: /** make a list of all OrderPaymentPreferences including all payment methods and types */
1683: public List makeAllOrderPaymentPreferences() {
1684: List allOpPrefs = new LinkedList();
1685:
1686: // first create the payment methods (online payments?)
1687: List paymentMethods = this .getPaymentMethods();
1688: Iterator pmi = paymentMethods.iterator();
1689: while (pmi.hasNext()) {
1690: GenericValue paymentMethod = (GenericValue) pmi.next();
1691: GenericValue p = delegator.makeValue(
1692: "OrderPaymentPreference", new HashMap());
1693: p.set("paymentMethodTypeId", paymentMethod
1694: .get("paymentMethodTypeId"));
1695: p.set("paymentMethodId", paymentMethod
1696: .get("paymentMethodId"));
1697: p.set("statusId", "PAYMENT_NOT_AUTH");
1698: if (this .paymentMethodAmounts.get(paymentMethod
1699: .getString("paymentMethodId")) != null) {
1700: p.set("maxAmount",
1701: this .paymentMethodAmounts.get(paymentMethod
1702: .getString("paymentMethodId")));
1703: }
1704: allOpPrefs.add(p);
1705: }
1706:
1707: // next create the payment types (offline payments?)
1708: Iterator pti = this .getPaymentMethodTypeIds().iterator();
1709: while (pti.hasNext()) {
1710: String paymentMethodTypeId = (String) pti.next();
1711: GenericValue p = delegator.makeValue(
1712: "OrderPaymentPreference", new HashMap());
1713: p.set("paymentMethodTypeId", paymentMethodTypeId);
1714: p.set("statusId", "PAYMENT_NOT_RECEIVED");
1715: if (this .paymentMethodTypeAmounts.get(paymentMethodTypeId) != null) {
1716: p.set("maxAmount", this .paymentMethodTypeAmounts
1717: .get(paymentMethodTypeId));
1718: }
1719: allOpPrefs.add(p);
1720: }
1721:
1722: return allOpPrefs;
1723: }
1724:
1725: /** make a list of all OrderShipmentPreferences including ones for the order and order lines */
1726: public List makeAllOrderShipmentPreferences() {
1727: List allOshPrefs = new LinkedList();
1728:
1729: // if nothing has been put into the value, don't set it; must at least have a carrierPartyId and a shipmentMethodTypeId
1730: if (this .orderShipmentPreference.size() > 1) {
1731: allOshPrefs.add(this .orderShipmentPreference);
1732: }
1733:
1734: // add all of the item adjustments to this list too
1735: Iterator itemIter = cartLines.iterator();
1736:
1737: while (itemIter.hasNext()) {
1738: ShoppingCartItem item = (ShoppingCartItem) itemIter.next();
1739: // if nothing has been put into the value, don't set it; must at least have a carrierPartyId and a shipmentMethodTypeId
1740: GenericValue itemOrderShipmentPreference = item
1741: .getOrderShipmentPreference();
1742:
1743: if (itemOrderShipmentPreference != null
1744: && itemOrderShipmentPreference.size() > 1) {
1745: itemOrderShipmentPreference.set("orderItemSeqId", item
1746: .getOrderItemSeqId());
1747: allOshPrefs.add(item.getOrderShipmentPreference());
1748: }
1749: }
1750:
1751: return allOshPrefs;
1752: }
1753:
1754: /** make a list of OrderItemPriceInfos from the ShoppingCartItems */
1755: public List makeAllOrderItemPriceInfos() {
1756: List allInfos = new LinkedList();
1757:
1758: // add all of the item adjustments to this list too
1759: Iterator itemIter = cartLines.iterator();
1760:
1761: while (itemIter.hasNext()) {
1762: ShoppingCartItem item = (ShoppingCartItem) itemIter.next();
1763: Collection infos = item.getOrderItemPriceInfos();
1764:
1765: if (infos != null) {
1766: Iterator infosIter = infos.iterator();
1767:
1768: while (infosIter.hasNext()) {
1769: GenericValue orderItemPriceInfo = (GenericValue) infosIter
1770: .next();
1771:
1772: orderItemPriceInfo.set("orderItemSeqId", item
1773: .getOrderItemSeqId());
1774: allInfos.add(orderItemPriceInfo);
1775: }
1776: }
1777: }
1778:
1779: return allInfos;
1780: }
1781:
1782: public List makeProductPromoUses() {
1783: List productPromoUses = new ArrayList(
1784: this .productPromoUseInfoList.size());
1785: String partyId = this .getPartyId();
1786: int sequenceValue = 0;
1787: Iterator productPromoUseInfoIter = this .productPromoUseInfoList
1788: .iterator();
1789: while (productPromoUseInfoIter.hasNext()) {
1790: ProductPromoUseInfo productPromoUseInfo = (ProductPromoUseInfo) productPromoUseInfoIter
1791: .next();
1792: GenericValue productPromoUse = this .getDelegator()
1793: .makeValue("ProductPromoUse", null);
1794: productPromoUse.set("promoSequenceId", UtilFormatOut
1795: .formatPaddedNumber(sequenceValue, 5));
1796: productPromoUse.set("productPromoId", productPromoUseInfo
1797: .getProductPromoId());
1798: productPromoUse.set("productPromoCodeId",
1799: productPromoUseInfo.getProductPromoCodeId());
1800: productPromoUse.set("totalDiscountAmount", new Double(
1801: productPromoUseInfo.getTotalDiscountAmount()));
1802: productPromoUse.set("quantityLeftInActions", new Double(
1803: productPromoUseInfo.getQuantityLeftInActions()));
1804: productPromoUse.set("partyId", partyId);
1805: productPromoUses.add(productPromoUse);
1806: sequenceValue++;
1807: }
1808: return productPromoUses;
1809: }
1810:
1811: /** make a list of SurveyResponse object to update with order information set */
1812: public List makeAllOrderItemSurveyResponses() {
1813: List allInfos = new LinkedList();
1814: Iterator itemIter = this .iterator();
1815: while (itemIter.hasNext()) {
1816: ShoppingCartItem item = (ShoppingCartItem) itemIter.next();
1817: List responses = (List) item
1818: .getAttribute("surveyResponses");
1819: if (responses != null) {
1820: Iterator ri = responses.iterator();
1821: while (ri.hasNext()) {
1822: String responseId = (String) ri.next();
1823: GenericValue response = null;
1824: try {
1825: response = delegator
1826: .findByPrimaryKey("SurveyResponse",
1827: UtilMisc.toMap(
1828: "surveyResponseId",
1829: responseId));
1830: } catch (GenericEntityException e) {
1831: Debug.logError(e,
1832: "Unable to obtain SurveyResponse record for ID : "
1833: + responseId, module);
1834: }
1835: if (response != null) {
1836: response.set("orderItemSeqId", item
1837: .getOrderItemSeqId());
1838: allInfos.add(response);
1839: }
1840: }
1841: }
1842: }
1843: return allInfos;
1844: }
1845:
1846: /** make a list of OrderContactMechs from the ShoppingCart and the ShoppingCartItems */
1847: public List makeAllOrderContactMechs() {
1848: List allOrderContactMechs = new LinkedList();
1849:
1850: Map contactMechIds = this .getOrderContactMechIds();
1851:
1852: if (contactMechIds != null) {
1853: Iterator cMechIdsIter = contactMechIds.entrySet()
1854: .iterator();
1855:
1856: while (cMechIdsIter.hasNext()) {
1857: Map.Entry entry = (Map.Entry) cMechIdsIter.next();
1858: GenericValue orderContactMech = getDelegator()
1859: .makeValue("OrderContactMech", null);
1860:
1861: orderContactMech.set("contactMechPurposeTypeId", entry
1862: .getKey());
1863: orderContactMech.set("contactMechId", entry.getValue());
1864: allOrderContactMechs.add(orderContactMech);
1865: }
1866: }
1867:
1868: return allOrderContactMechs;
1869: }
1870:
1871: /** make a list of OrderContactMechs from the ShoppingCart and the ShoppingCartItems */
1872: public List makeAllOrderItemContactMechs() {
1873: List allOrderContactMechs = new LinkedList();
1874:
1875: Iterator itemIter = cartLines.iterator();
1876:
1877: while (itemIter.hasNext()) {
1878: ShoppingCartItem item = (ShoppingCartItem) itemIter.next();
1879: Map itemContactMechIds = item.getOrderItemContactMechIds();
1880:
1881: if (itemContactMechIds != null) {
1882: Iterator cMechIdsIter = itemContactMechIds.entrySet()
1883: .iterator();
1884:
1885: while (cMechIdsIter.hasNext()) {
1886: Map.Entry entry = (Map.Entry) cMechIdsIter.next();
1887: GenericValue orderContactMech = getDelegator()
1888: .makeValue("OrderItemContactMech", null);
1889:
1890: orderContactMech.set("contactMechPurposeTypeId",
1891: entry.getKey());
1892: orderContactMech.set("contactMechId", entry
1893: .getValue());
1894: orderContactMech.set("orderItemSeqId", item
1895: .getOrderItemSeqId());
1896: allOrderContactMechs.add(orderContactMech);
1897: }
1898: }
1899: }
1900:
1901: return allOrderContactMechs;
1902: }
1903:
1904: /** Returns a Map of cart values to pass to the storeOrder service */
1905: public Map makeCartMap(LocalDispatcher dispatcher,
1906: boolean explodeItems) {
1907: Map result = new HashMap();
1908:
1909: result.put("orderTypeId", this .getOrderType());
1910: result.put("orderItems", this .makeOrderItems(explodeItems,
1911: dispatcher));
1912: result.put("orderAdjustments", this .makeAllAdjustments());
1913: result.put("orderItemPriceInfos", this
1914: .makeAllOrderItemPriceInfos());
1915: result
1916: .put("orderProductPromoUses", this
1917: .makeProductPromoUses());
1918:
1919: result
1920: .put("orderContactMechs", this
1921: .makeAllOrderContactMechs());
1922: result.put("orderItemContactMechs", this
1923: .makeAllOrderItemContactMechs());
1924: result.put("orderPaymentPreferences", this
1925: .makeAllOrderPaymentPreferences());
1926: result.put("orderShipmentPreferences", this
1927: .makeAllOrderShipmentPreferences());
1928: result.put("orderItemSurveyResponses", this
1929: .makeAllOrderItemSurveyResponses());
1930:
1931: result
1932: .put("firstAttemptOrderId", this
1933: .getFirstAttemptOrderId());
1934: result.put("currencyUom", this .getCurrency());
1935: result.put("billingAccountId", this .getBillingAccountId());
1936: return result;
1937: }
1938:
1939: protected void finalize() throws Throwable {
1940: this .clear();
1941: super .finalize();
1942: }
1943:
1944: public List getLineListOrderedByBasePrice(boolean ascending) {
1945: List result = new ArrayList(this .cartLines);
1946: Collections.sort(result,
1947: new BasePriceOrderComparator(ascending));
1948: return result;
1949: }
1950:
1951: static class BasePriceOrderComparator implements Comparator {
1952:
1953: private boolean ascending = false;
1954:
1955: BasePriceOrderComparator(boolean ascending) {
1956: this .ascending = ascending;
1957: }
1958:
1959: public int compare(java.lang.Object obj, java.lang.Object obj1) {
1960: ShoppingCartItem cartItem = (ShoppingCartItem) obj;
1961: ShoppingCartItem cartItem1 = (ShoppingCartItem) obj1;
1962:
1963: int compareValue = new Double(cartItem.getBasePrice())
1964: .compareTo(new Double(cartItem1.getBasePrice()));
1965: if (this .ascending) {
1966: return compareValue;
1967: } else {
1968: return -compareValue;
1969: }
1970: }
1971:
1972: public boolean equals(java.lang.Object obj) {
1973: if (obj instanceof BasePriceOrderComparator) {
1974: return this .ascending == ((BasePriceOrderComparator) obj).ascending;
1975: } else {
1976: return false;
1977: }
1978: }
1979: }
1980: }
|