KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > order > shoppingcart > ShoppingCartItem


1 /*
2  * $Id: ShoppingCartItem.java 7275 2006-04-11 08:59:24Z jonesde $
3  *
4  * Copyright (c) 2001-2005 The Open For Business Project - www.ofbiz.org
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */

24 package org.ofbiz.order.shoppingcart;
25
26 import java.math.BigDecimal JavaDoc;
27 import java.sql.Timestamp JavaDoc;
28 import java.util.ArrayList JavaDoc;
29 import java.util.Arrays JavaDoc;
30 import java.util.HashMap JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.LinkedList JavaDoc;
33 import java.util.List JavaDoc;
34 import java.util.Locale JavaDoc;
35 import java.util.Map JavaDoc;
36 import java.util.Set JavaDoc;
37
38 import org.apache.commons.collections.set.ListOrderedSet;
39 import org.ofbiz.base.util.Debug;
40 import org.ofbiz.base.util.GeneralException;
41 import org.ofbiz.base.util.UtilDateTime;
42 import org.ofbiz.base.util.UtilFormatOut;
43 import org.ofbiz.base.util.UtilMisc;
44 import org.ofbiz.base.util.UtilProperties;
45 import org.ofbiz.base.util.UtilValidate;
46 import org.ofbiz.entity.GenericDelegator;
47 import org.ofbiz.entity.GenericEntityException;
48 import org.ofbiz.entity.GenericPK;
49 import org.ofbiz.entity.GenericValue;
50 import org.ofbiz.entity.condition.EntityExpr;
51 import org.ofbiz.entity.condition.EntityOperator;
52 import org.ofbiz.entity.util.EntityUtil;
53 import org.ofbiz.order.order.OrderReadHelper;
54 import org.ofbiz.order.shoppingcart.product.ProductPromoWorker;
55 import org.ofbiz.order.shoppinglist.ShoppingListEvents;
56 import org.ofbiz.product.catalog.CatalogWorker;
57 import org.ofbiz.product.category.CategoryWorker;
58 import org.ofbiz.product.config.ProductConfigWrapper;
59 import org.ofbiz.product.product.ProductContentWrapper;
60 import org.ofbiz.product.product.ProductWorker;
61 import org.ofbiz.product.store.ProductStoreWorker;
62 import org.ofbiz.service.GenericServiceException;
63 import org.ofbiz.service.LocalDispatcher;
64 import org.ofbiz.service.ModelService;
65 import org.ofbiz.service.ServiceUtil;
66 import javolution.util.FastMap;
67
68 /**
69  * <p><b>Title:</b> ShoppingCartItem.java
70  * <p><b>Description:</b> Shopping cart item object.
71  *
72  * @author <a HREF="mailto:jaz@ofbiz.org.com">Andy Zeneski</a>
73  * @author <a HREF="mailto:jonesde@ofbiz.org">David E. Jones</a>
74  * @version $Rev: 7275 $
75  * @since 2.0
76  */

77 public class ShoppingCartItem implements java.io.Serializable JavaDoc {
78
79     public static String JavaDoc module = ShoppingCartItem.class.getName();
80     public static final String JavaDoc resource = "OrderUiLabels";
81     public static final String JavaDoc resource_error = "OrderErrorUiLabels";
82     public static String JavaDoc[] attributeNames = { "shoppingListId", "shoppingListItemSeqId", "surveyResponses",
83                                               "itemDesiredDeliveryDate", "itemComment"};
84
85     private transient GenericDelegator delegator = null;
86     private transient GenericValue _product = null; // the actual product
87
private transient GenericValue _parentProduct = null; // the virtual product
88

89     private String JavaDoc delegatorName = null;
90     private String JavaDoc prodCatalogId = null;
91     private String JavaDoc productId = null;
92     private String JavaDoc itemType = null; // ends up in orderItemTypeId
93
private String JavaDoc productCategoryId = null;
94     private String JavaDoc itemDescription = null;
95     private Timestamp JavaDoc reservStart = null; // for reservations: date start
96
private double reservLength = 0; // for reservations: length
97
private double reservPersons = 0; // for reservations: number of persons using
98
private double quantity = 0.0;
99     private double basePrice = 0.0;
100     private Double JavaDoc displayPrice = null;
101     private Double JavaDoc specialPromoPrice = null; // comes from price calc, used for special promo price promotion action
102
private double reserv2ndPPPerc = 0.0; // for reservations: extra % 2nd person
103
private double reservNthPPPerc = 0.0; // for reservations: extra % Nth person
104
private double listPrice = 0.0;
105     private boolean isModifiedPrice = false; // flag to know if the price have been modified
106
private double selectedAmount = 0.0;
107     private String JavaDoc requirementId = null;
108     private String JavaDoc quoteId = null;
109     private String JavaDoc quoteItemSeqId = null;
110     private String JavaDoc statusId = null;
111     private Map JavaDoc orderItemAttributes = null;
112     private Map JavaDoc attributes = null;
113     private String JavaDoc orderItemSeqId = null;
114     private Locale JavaDoc locale = null;
115     private Timestamp JavaDoc shipBeforeDate = null;
116     private Timestamp JavaDoc shipAfterDate = null;
117
118     private Map JavaDoc contactMechIdsMap = FastMap.newInstance();
119     private List JavaDoc orderItemPriceInfos = null;
120     private List JavaDoc itemAdjustments = new LinkedList JavaDoc();
121     private boolean isPromo = false;
122     private double promoQuantityUsed = 0;
123     private Map JavaDoc quantityUsedPerPromoCandidate = new HashMap JavaDoc();
124     private Map JavaDoc quantityUsedPerPromoFailed = new HashMap JavaDoc();
125     private Map JavaDoc quantityUsedPerPromoActual = new HashMap JavaDoc();
126     private Map JavaDoc additionalProductFeatureAndAppls = new HashMap JavaDoc();
127     private List JavaDoc alternativeOptionProductIds = null;
128     private ProductConfigWrapper configWrapper = null;
129     private List JavaDoc featuresForSupplier = new LinkedList JavaDoc();
130
131     /**
132      * Makes a ShoppingCartItem and adds it to the cart.
133      * NOTE: This method will get the product entity and check to make sure it can be purchased.
134      *
135      * @param cartLocation The location to place this item; null will place at the end
136      * @param productId The primary key of the product being added
137      * @param quantity The quantity to add
138      * @param additionalProductFeatureAndAppls Product feature/appls map
139      * @param attributes All unique attributes for this item (NOT features)
140      * @param prodCatalogId The catalog this item was added from
141      * @param dispatcher LocalDispatcher object for doing promotions, etc
142      * @param cart The parent shopping cart object this item will belong to
143      * @return a new ShoppingCartItem object
144      * @throws CartItemModifyException
145      */

146     public static ShoppingCartItem makeItem(Integer JavaDoc cartLocation, String JavaDoc productId, double selectedAmount, double quantity, Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, LocalDispatcher dispatcher, ShoppingCart cart) throws CartItemModifyException, ItemNotFoundException {
147         return ShoppingCartItem.makeItem(cartLocation, productId, selectedAmount, quantity, additionalProductFeatureAndAppls, attributes, prodCatalogId, null, dispatcher, cart);
148     }
149
150     /**
151      * Makes a ShoppingCartItem and adds it to the cart.
152      * NOTE: This method will get the product entity and check to make sure it can be purchased.
153      *
154      * @param cartLocation The location to place this item; null will place at the end
155      * @param productId The primary key of the product being added
156      * @param selectedAmount ?
157      * @param quantity The quantity to add
158      * @param additionalProductFeatureAndAppls Product feature/appls map
159      * @param attributes All unique attributes for this item (NOT features)
160      * @param prodCatalogId The catalog this item was added from
161      * @param configWrapper The product configuration wrapper (null if the product is not configurable)
162      * @param dispatcher LocalDispatcher object for doing promotions, etc
163      * @param cart The parent shopping cart object this item will belong to
164      * @return a new ShoppingCartItem object
165      * @throws CartItemModifyException
166      */

167     public static ShoppingCartItem makeItem(Integer JavaDoc cartLocation, String JavaDoc productId, double selectedAmount, double quantity, Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, ProductConfigWrapper configWrapper, LocalDispatcher dispatcher, ShoppingCart cart) throws CartItemModifyException, ItemNotFoundException {
168         return ShoppingCartItem.makeItem(cartLocation, productId, selectedAmount, quantity, null, 0.00, 0.00, null, null, additionalProductFeatureAndAppls, attributes, prodCatalogId, configWrapper, dispatcher, cart);
169     }
170
171     /**
172      * Makes a ShoppingCartItem and adds it to the cart.
173      * NOTE: This method will get the product entity and check to make sure it can be purchased.
174      *
175      * @param cartLocation The location to place this item; null will place at the end
176      * @param productId The primary key of the product being added
177      * @param selectedAmount ?
178      * @param quantity The quantity to add
179      * @param additionalProductFeatureAndAppls Product feature/appls map
180      * @param attributes All unique attributes for this item (NOT features)
181      * @param prodCatalogId The catalog this item was added from
182      * @param configWrapper The product configuration wrapper (null if the product is not configurable)
183      * @param dispatcher LocalDispatcher object for doing promotions, etc
184      * @param cart The parent shopping cart object this item will belong to
185      * @return a new ShoppingCartItem object
186      * @throws CartItemModifyException
187      */

188     public static ShoppingCartItem makeItem(Integer JavaDoc cartLocation, String JavaDoc productId, double selectedAmount, double quantity, Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, ProductConfigWrapper configWrapper, LocalDispatcher dispatcher, ShoppingCart cart, boolean triggerExternalOps) throws CartItemModifyException, ItemNotFoundException {
189         return ShoppingCartItem.makeItem(cartLocation, productId, selectedAmount, quantity, null, 0.00, 0.00, null, null, additionalProductFeatureAndAppls, attributes, prodCatalogId, configWrapper, dispatcher, cart, triggerExternalOps);
190     }
191
192     /**
193      * Makes a ShoppingCartItem and adds it to the cart.
194      * NOTE: This method will get the product entity and check to make sure it can be purchased.
195      *
196      * @param cartLocation The location to place this item; null will place at the end
197      * @param productId The primary key of the product being added
198      * @param selectedAmount ?
199      * @param quantity The quantity to add
200      * @param reservStart start of the reservation
201      * @param reservLength length of the reservation
202      * @param reservPersons nbr of persons taking advantage of the reservation
203      * @param shipBeforeDate The date to ship the order by
204      * @param shipAfterDate Wait until this date to ship
205      * @param additionalProductFeatureAndAppls Product feature/appls map
206      * @param attributes All unique attributes for this item (NOT features)
207      * @param prodCatalogId The catalog this item was added from
208      * @param configWrapper The product configuration wrapper (null if the product is not configurable)
209      * @param dispatcher LocalDispatcher object for doing promotions, etc
210      * @param cart The parent shopping cart object this item will belong to
211      * @return a new ShoppingCartItem object
212      * @throws CartItemModifyException
213      */

214     public static ShoppingCartItem makeItem(Integer JavaDoc cartLocation, String JavaDoc productId, double selectedAmount, double quantity, Timestamp JavaDoc reservStart, double reservLength, double reservPersons, Timestamp JavaDoc shipBeforeDate, Timestamp JavaDoc shipAfterDate, Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, ProductConfigWrapper configWrapper, LocalDispatcher dispatcher, ShoppingCart cart) throws CartItemModifyException, ItemNotFoundException {
215         return ShoppingCartItem.makeItem(cartLocation, productId, selectedAmount, quantity, reservStart, reservLength, reservPersons, shipBeforeDate, shipAfterDate, additionalProductFeatureAndAppls, attributes, prodCatalogId, configWrapper, dispatcher, cart, true);
216     }
217
218     public static ShoppingCartItem makeItem(Integer JavaDoc cartLocation, String JavaDoc productId, double selectedAmount, double quantity, Timestamp JavaDoc reservStart, double reservLength, double reservPersons, Timestamp JavaDoc shipBeforeDate, Timestamp JavaDoc shipAfterDate, Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, ProductConfigWrapper configWrapper, LocalDispatcher dispatcher, ShoppingCart cart, boolean triggerExternalOps) throws CartItemModifyException, ItemNotFoundException {
219         return ShoppingCartItem.makeItem(cartLocation, productId, selectedAmount, quantity, 0.00, reservStart, reservLength, reservPersons, shipBeforeDate, shipAfterDate, additionalProductFeatureAndAppls, attributes, prodCatalogId, configWrapper, dispatcher, cart, triggerExternalOps, true);
220     }
221     /**
222      * Makes a ShoppingCartItem and adds it to the cart.
223      * NOTE: This method will get the product entity and check to make sure it can be purchased.
224      *
225      * @param cartLocation The location to place this item; null will place at the end
226      * @param productId The primary key of the product being added
227      * @param selectedAmount ?
228      * @param quantity The quantity to add
229      * @param reservStart start of the reservation
230      * @param reservLength length of the reservation
231      * @param reservPersons nbr of persons taking advantage of the reservation
232      * @param shipBeforeDate The date to ship the order by
233      * @param shipAfterDate Wait until this date to ship
234      * @param additionalProductFeatureAndAppls Product feature/appls map
235      * @param attributes All unique attributes for this item (NOT features)
236      * @param prodCatalogId The catalog this item was added from
237      * @param configWrapper The product configuration wrapper (null if the product is not configurable)
238      * @param dispatcher LocalDispatcher object for doing promotions, etc
239      * @param cart The parent shopping cart object this item will belong to
240      * @return a new ShoppingCartItem object
241      * @throws CartItemModifyException
242      */

243     public static ShoppingCartItem makeItem(Integer JavaDoc cartLocation, String JavaDoc productId, double selectedAmount, double quantity, double unitPrice, Timestamp JavaDoc reservStart, double reservLength, double reservPersons, Timestamp JavaDoc shipBeforeDate, Timestamp JavaDoc shipAfterDate, Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, ProductConfigWrapper configWrapper, LocalDispatcher dispatcher, ShoppingCart cart, boolean triggerExternalOps, boolean triggerProductPrice) throws CartItemModifyException, ItemNotFoundException {
244         GenericDelegator delegator = cart.getDelegator();
245         GenericValue product = null;
246     
247         try {
248             product = delegator.findByPrimaryKeyCache("Product", UtilMisc.toMap("productId", productId));
249     
250             // first see if there is a purchase allow category and if this product is in it or not
251
String JavaDoc purchaseProductCategoryId = CatalogWorker.getCatalogPurchaseAllowCategoryId(delegator, prodCatalogId);
252             if (purchaseProductCategoryId != null) {
253                 if (!CategoryWorker.isProductInCategory(delegator, product.getString("productId"), purchaseProductCategoryId)) {
254                     // a Purchase allow productCategoryId was found, but the product is not in the category, axe it...
255
product = null;
256                 }
257             }
258         } catch (GenericEntityException e) {
259             Debug.logWarning(e.toString(), module);
260             product = null;
261         }
262     
263         if (product == null) {
264             Map JavaDoc messageMap = UtilMisc.toMap("productId", productId );
265     
266             String JavaDoc excMsg = UtilProperties.getMessage(resource, "item.product_not_found",
267                                           messageMap , cart.getLocale() );
268     
269             Debug.logWarning(excMsg, module);
270             throw new ItemNotFoundException(excMsg);
271         }
272     
273         return makeItem(cartLocation, product, selectedAmount, quantity, unitPrice, reservStart, reservLength, reservPersons, shipBeforeDate, shipAfterDate, additionalProductFeatureAndAppls, attributes, prodCatalogId, configWrapper, dispatcher, cart, triggerExternalOps, triggerProductPrice);
274     }
275
276     /**
277      * Makes a ShoppingCartItem for a purchase order item and adds it to the cart.
278      * NOTE: This method will get the product entity and check to make sure it can be purchased.
279      *
280      * @param cartLocation The location to place this item; null will place at the end
281      * @param productId The primary key of the product being added
282      * @param quantity The quantity to add
283      * @param additionalProductFeatureAndAppls Product feature/appls map
284      * @param attributes All unique attributes for this item (NOT features)
285      * @param prodCatalogId The catalog this item was added from
286      * @param configWrapper The product configuration wrapper (null if the product is not configurable)
287      * @param dispatcher LocalDispatcher object for doing promotions, etc
288      * @param cart The parent shopping cart object this item will belong to
289      * @param supplierProduct GenericValue of SupplierProduct entity, containing product description and prices
290      * @param shipBeforeDate Request that the shipment be made before this date
291      * @param shipAfterDate Request that the shipment be made after this date
292      * @return a new ShoppingCartItem object
293      * @throws CartItemModifyException
294      */

295     public static ShoppingCartItem makePurchaseOrderItem(Integer JavaDoc cartLocation, String JavaDoc productId, double selectedAmount, double quantity,
296             Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, ProductConfigWrapper configWrapper,
297             LocalDispatcher dispatcher, ShoppingCart cart, GenericValue supplierProduct, Timestamp JavaDoc shipBeforeDate, Timestamp JavaDoc shipAfterDate)
298                 throws CartItemModifyException, ItemNotFoundException {
299         GenericDelegator delegator = cart.getDelegator();
300         GenericValue product = null;
301
302         try {
303             product = delegator.findByPrimaryKeyCache("Product", UtilMisc.toMap("productId", productId));
304         } catch (GenericEntityException e) {
305             Debug.logWarning(e.toString(), module);
306             product = null;
307         }
308
309         if (product == null) {
310             Map JavaDoc messageMap = UtilMisc.toMap("productId", productId );
311
312             String JavaDoc excMsg = UtilProperties.getMessage(resource, "item.product_not_found",
313                                           messageMap , cart.getLocale() );
314
315             Debug.logWarning(excMsg, module);
316             throw new ItemNotFoundException(excMsg);
317         }
318         ShoppingCartItem newItem = new ShoppingCartItem(product, additionalProductFeatureAndAppls, attributes, prodCatalogId, configWrapper, cart.getLocale());
319
320         // check to see if product is virtual
321
if ("Y".equals(product.getString("isVirtual"))) {
322             String JavaDoc excMsg = "Tried to add the Virtual Product " + product.getString("productName") +
323                 " (productId: " + product.getString("productId") + ") to the cart, not adding.";
324
325             Debug.logWarning(excMsg, module);
326             throw new CartItemModifyException(excMsg);
327         }
328
329         // Timestamp nowTimestamp = UtilDateTime.nowTimestamp();
330

331         // check to see if the product is fully configured
332
if ("AGGREGATED".equals(product.getString("productTypeId"))) {
333             if (configWrapper == null || !configWrapper.isCompleted()) {
334                 String JavaDoc excMsg = "Tried to add the Product " + product.getString("productName") +
335                     " (productId: " + product.getString("productId") + ") to the cart, not adding: the product is not configured correctly.";
336
337                 Debug.logWarning(excMsg, module);
338                 throw new CartItemModifyException(excMsg);
339             }
340         }
341
342         // add to cart before setting quantity so that we can get order total, etc
343
if (cartLocation == null) {
344             cart.addItemToEnd(newItem);
345         } else {
346             cart.addItem(cartLocation.intValue(), newItem);
347         }
348
349         if (selectedAmount > 0) {
350             newItem.setSelectedAmount(selectedAmount);
351         }
352         
353         // set the ship before/after dates. this needs to happen before setQuantity because setQuantity causes the ship group's dates to be
354
// checked versus the cart item's
355
newItem.setShipBeforeDate(shipBeforeDate != null ? shipBeforeDate : cart.getDefaultShipBeforeDate());
356         newItem.setShipAfterDate(shipAfterDate != null ? shipAfterDate : cart.getDefaultShipAfterDate());
357
358         try {
359             newItem.setQuantity(quantity, dispatcher, cart, true);
360         } catch (CartItemModifyException e) {
361             cart.removeCartItem(cart.getItemIndex(newItem), dispatcher);
362             cart.clearItemShipInfo(newItem);
363             cart.removeEmptyCartItems();
364             throw e;
365         }
366
367         // specific for purchase orders - description is set to supplierProductId + supplierProductName, price set to lastPrice of SupplierProduct
368
// if supplierProduct has no supplierProductName, use the regular supplierProductId
369
if (supplierProduct != null) {
370             newItem.setName(getPurchaseOrderItemDescription(product, supplierProduct, cart.getLocale()));
371             newItem.setBasePrice(supplierProduct.getDouble("lastPrice").doubleValue());
372         } else {
373             newItem.setName(product.getString("internalName"));
374         }
375         return newItem;
376
377     }
378     /**
379      * Makes a ShoppingCartItem and adds it to the cart.
380      * WARNING: This method does not check if the product is in a purchase category.
381      *
382      * @param cartLocation The location to place this item; null will place at the end
383      * @param product The product entity relating to the product being added
384      * @param quantity The quantity to add
385      * @param additionalProductFeatureAndAppls Product feature/appls map
386      * @param attributes All unique attributes for this item (NOT features)
387      * @param prodCatalogId The catalog this item was added from
388      * @param dispatcher LocalDispatcher object for doing promotions, etc
389      * @param cart The parent shopping cart object this item will belong to
390      * @param triggerExternalOps Indicates if we should run external operations (promotions, auto-save, etc)
391      * @return a new ShoppingCartItem object
392      * @throws CartItemModifyException
393      */

394     public static ShoppingCartItem makeItem(Integer JavaDoc cartLocation, GenericValue product, double selectedAmount, double quantity, Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, LocalDispatcher dispatcher, ShoppingCart cart, boolean triggerExternalOps) throws CartItemModifyException {
395         return ShoppingCartItem.makeItem(cartLocation, product, selectedAmount, quantity, additionalProductFeatureAndAppls, attributes, prodCatalogId, null, dispatcher, cart, triggerExternalOps);
396     }
397
398     /**
399      * Makes a ShoppingCartItem and adds it to the cart.
400      * WARNING: This method does not check if the product is in a purchase category.
401      *
402      * @param cartLocation The location to place this item; null will place at the end
403      * @param product The product entity relating to the product being added
404      * @param quantity The quantity to add
405      * @param additionalProductFeatureAndAppls Product feature/appls map
406      * @param attributes All unique attributes for this item (NOT features)
407      * @param prodCatalogId The catalog this item was added from
408      * @param configWrapper The product configuration wrapper (null if the product is not configurable)
409      * @param dispatcher LocalDispatcher object for doing promotions, etc
410      * @param cart The parent shopping cart object this item will belong to
411      * @param triggerExternalOps Indicates if we should run external operations (promotions, auto-save, etc)
412      * @return a new ShoppingCartItem object
413      * @throws CartItemModifyException
414      */

415     public static ShoppingCartItem makeItem(Integer JavaDoc cartLocation, GenericValue product, double selectedAmount, double quantity, Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, ProductConfigWrapper configWrapper, LocalDispatcher dispatcher, ShoppingCart cart, boolean triggerExternalOps) throws CartItemModifyException {
416         return ShoppingCartItem.makeItem(cartLocation, product, selectedAmount, quantity, null, 0.00, 0.00, additionalProductFeatureAndAppls, attributes, prodCatalogId, configWrapper, dispatcher, cart, triggerExternalOps);
417     }
418
419     /**
420      * Makes a ShoppingCartItem and adds it to the cart.
421      * WARNING: This method does not check if the product is in a purchase category.
422      * rental fields were added.
423      *
424      * @param cartLocation The location to place this item; null will place at the end
425      * @param product The product entity relating to the product being added
426      * @param quantity The quantity to add
427      * @param reservStart the start of the reservation
428      * @param reservLength the reservation length
429      * @param reservPersons the number of persons using the reservation
430      * @param shipBeforeDate The date to ship the order by
431      * @param shipAfterDate Wait until this date to ship
432      * @param additionalProductFeatureAndAppls Product feature/appls map
433      * @param attributes All unique attributes for this item (NOT features)
434      * @param prodCatalogId The catalog this item was added from
435      * @param configWrapper The product configuration wrapper (null if the product is not configurable)
436      * @param dispatcher LocalDispatcher object for doing promotions, etc
437      * @param cart The parent shopping cart object this item will belong to
438      * @param triggerExternalOps Indicates if we should run external operations (promotions, auto-save, etc)
439      * @return a new ShoppingCartItem object
440      * @throws CartItemModifyException
441      */

442     //public static ShoppingCartItem makeItem(Integer cartLocation, GenericValue product, double selectedAmount, double quantity, Timestamp reservStart, double reservLength, double reservPersons, Map additionalProductFeatureAndAppls, Map attributes, String prodCatalogId, ProductConfigWrapper configWrapper, LocalDispatcher dispatcher, ShoppingCart cart, boolean triggerExternalOps) throws CartItemModifyException {
443
public static ShoppingCartItem makeItem(Integer JavaDoc cartLocation, GenericValue product, double selectedAmount, double quantity, double unitPrice, Timestamp JavaDoc reservStart, double reservLength, double reservPersons,
444             Timestamp JavaDoc shipBeforeDate, Timestamp JavaDoc shipAfterDate, Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, ProductConfigWrapper configWrapper, LocalDispatcher dispatcher,
445             ShoppingCart cart, boolean triggerExternalOps, boolean triggerPriceRules) throws CartItemModifyException {
446         ShoppingCartItem newItem = new ShoppingCartItem(product, additionalProductFeatureAndAppls, attributes, prodCatalogId, configWrapper, cart.getLocale());
447         
448         // check to see if product is virtual
449
if ("Y".equals(product.getString("isVirtual"))) {
450             String JavaDoc excMsg = "Tried to add the Virtual Product " + product.getString("productName") +
451                 " (productId: " + product.getString("productId") + ") to the cart, not adding.";
452
453             Debug.logWarning(excMsg, module);
454             throw new CartItemModifyException(excMsg);
455         }
456
457         java.sql.Timestamp JavaDoc nowTimestamp = UtilDateTime.nowTimestamp();
458         
459         // check to see if introductionDate hasn't passed yet
460
if (product.get("introductionDate") != null && nowTimestamp.before(product.getTimestamp("introductionDate"))) {
461             String JavaDoc excMsg = "Tried to add the Product " + product.getString("productName") +
462                 " (productId: " + product.getString("productId") + ") to the cart. This product has not yet been made available for sale, so not adding.";
463
464             Debug.logWarning(excMsg, module);
465             throw new CartItemModifyException(excMsg);
466         }
467         
468         // check to see if salesDiscontinuationDate has passed
469
if (product.get("salesDiscontinuationDate") != null && nowTimestamp.after(product.getTimestamp("salesDiscontinuationDate"))) {
470             String JavaDoc excMsg = "Tried to add the Product " + product.getString("productName") +
471                 " (productId: " + product.getString("productId") + ") to the cart. This product is no longer available for sale, so not adding.";
472
473             Debug.logWarning(excMsg, module);
474             throw new CartItemModifyException(excMsg);
475         }
476
477         // check to see if the product is a rental item
478
if ("ASSET_USAGE".equals(product.getString("productTypeId"))) {
479             if (reservStart == null) {
480                 String JavaDoc excMsg = "The starting date of the reservation is missing....";
481                 throw new CartItemModifyException(excMsg);
482             }
483
484             if (reservStart.before(UtilDateTime.nowTimestamp())) {
485                 String JavaDoc excMsg = "You can only make reservation starting tomorrow....";
486                 throw new CartItemModifyException(excMsg);
487             }
488             newItem.setReservStart(reservStart);
489
490             if (reservLength < 1) {
491                 String JavaDoc excMsg = "Please enter a number of days, 1, or more....";
492                 throw new CartItemModifyException(excMsg);
493             }
494             newItem.setReservLength(reservLength);
495
496             if (product.get("reservMaxPersons") != null) {
497                  double reservMaxPersons = product.getDouble("reservMaxPersons").doubleValue();
498                  if (reservMaxPersons < reservPersons) {
499                      String JavaDoc excMsg = "The maximum number of persons renting this object is " + product.getString("reservMaxPersons") + " however you have requested: " + reservPersons + " !";
500                      Debug.logInfo(excMsg,module);
501                      throw new CartItemModifyException(excMsg);
502                  }
503              }
504              newItem.setReservPersons(reservPersons);
505
506              if (product.get("reserv2ndPPPerc") != null)
507                  newItem.setReserv2ndPPPerc(product.getDouble("reserv2ndPPPerc").doubleValue());
508
509              if (product.get("reservNthPPPerc") != null)
510                  newItem.setReservNthPPPerc(product.getDouble("reservNthPPPerc").doubleValue());
511
512             // check to see if the related fixed asset is available for rent
513
String JavaDoc isAvailable = checkAvailability(product.getString("productId"), quantity, reservStart, reservLength, cart);
514             if(isAvailable.compareTo("OK") != 0) {
515                 String JavaDoc excMsg = "Product not available, ProductId:" + product.getString("productId") + " message:" + isAvailable.toString();
516                 Debug.logInfo(excMsg, module);
517                 throw new CartItemModifyException(isAvailable);
518             }
519         }
520         
521         // check to see if the product is fully configured
522
if ("AGGREGATED".equals(product.getString("productTypeId"))) {
523             if (configWrapper == null || !configWrapper.isCompleted()) {
524                 String JavaDoc excMsg = "Tried to add the Product " + product.getString("productName") +
525                     " (productId: " + product.getString("productId") + ") to the cart, not adding: the product is not configured correctly.";
526
527                 Debug.logWarning(excMsg, module);
528                 throw new CartItemModifyException(excMsg);
529             }
530         }
531         
532         // set the ship before and after dates (defaults to cart ship before/after dates)
533
newItem.setShipBeforeDate(shipBeforeDate != null ? shipBeforeDate : cart.getDefaultShipBeforeDate());
534         newItem.setShipAfterDate(shipAfterDate != null ? shipAfterDate : cart.getDefaultShipAfterDate());
535         
536         // set the product unit price as base price
537
// if triggerPriceRules is true this price will be overriden
538
newItem.setBasePrice(unitPrice);
539
540         // add to cart before setting quantity so that we can get order total, etc
541
if (cartLocation == null) {
542             cart.addItemToEnd(newItem);
543         } else {
544             cart.addItem(cartLocation.intValue(), newItem);
545         }
546
547         // We have to set the selectedAmount before calling setQuantity because
548
// selectedAmount changes the item's base price (used in the updatePrice
549
// method called inside the setQuantity method)
550
if (selectedAmount > 0) {
551             newItem.setSelectedAmount(selectedAmount);
552         }
553
554         try {
555             newItem.setQuantity(quantity, dispatcher, cart, triggerExternalOps, true, triggerPriceRules);
556         } catch (CartItemModifyException e) {
557             Debug.logWarning(e.getMessage(), module);
558             cart.removeCartItem(cart.getItemIndex(newItem), dispatcher);
559             cart.clearItemShipInfo(newItem);
560             cart.removeEmptyCartItems();
561             throw e;
562         }
563
564         return newItem;
565     }
566
567     // Calls makeItem(...) setting a default value, 0.00, for the selectedAmount
568
public static ShoppingCartItem makeItem(Integer JavaDoc cartLocation, GenericValue product, double quantity, Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, LocalDispatcher dispatcher, ShoppingCart cart, boolean triggerExternalOps) throws CartItemModifyException {
569         return makeItem(cartLocation, product, 0.00, quantity, additionalProductFeatureAndAppls, attributes, prodCatalogId, dispatcher, cart, triggerExternalOps);
570     }
571
572     // Calls makeItem(...) setting a default value, 0.00, for unitPrice and setting the triggerProductPrice to true;
573
// in this way, the prices and price rules are automatically set by the updatePrice(...) method
574
public static ShoppingCartItem makeItem(Integer JavaDoc cartLocation, GenericValue product, double selectedAmount, double quantity, Timestamp JavaDoc reservStart, double reservLength, double reservPersons, Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, ProductConfigWrapper configWrapper, LocalDispatcher dispatcher, ShoppingCart cart, boolean triggerExternalOps) throws CartItemModifyException {
575         return makeItem(cartLocation, product, selectedAmount, quantity, 0.0, reservStart, reservLength, reservPersons, null, null, additionalProductFeatureAndAppls, attributes, prodCatalogId, configWrapper, dispatcher, cart, triggerExternalOps, true);
576     }
577     /**
578      * Makes a non-product ShoppingCartItem and adds it to the cart.
579      * NOTE: This is only for non-product items; items without a product entity (work items, bulk items, etc)
580      *
581      * @param cartLocation The location to place this item; null will place at the end
582      * @param itemType The OrderItemTypeId for the item being added
583      * @param itemDescription The optional description of the item
584      * @param productCategoryId The optional category the product *will* go in
585      * @param basePrice The price for this item
586      * @param selectedAmount
587      * @param quantity The quantity to add
588      * @param attributes All unique attributes for this item (NOT features)
589      * @param prodCatalogId The catalog this item was added from
590      * @param dispatcher LocalDispatcher object for doing promotions, etc
591      * @param cart The parent shopping cart object this item will belong to
592      * @param triggerExternalOps Indicates if we should run external operations (promotions, auto-save, etc)
593      * @return a new ShoppingCartItem object
594      * @throws CartItemModifyException
595      */

596     public static ShoppingCartItem makeItem(Integer JavaDoc cartLocation, String JavaDoc itemType, String JavaDoc itemDescription, String JavaDoc productCategoryId, double basePrice, double selectedAmount, double quantity, Map JavaDoc attributes, String JavaDoc prodCatalogId, LocalDispatcher dispatcher, ShoppingCart cart, boolean triggerExternalOps) throws CartItemModifyException {
597         GenericDelegator delegator = cart.getDelegator();
598         ShoppingCartItem newItem = new ShoppingCartItem(delegator, itemType, itemDescription, productCategoryId, basePrice, attributes, prodCatalogId, cart.getLocale());
599
600         // add to cart before setting quantity so that we can get order total, etc
601
if (cartLocation == null) {
602             cart.addItemToEnd(newItem);
603         } else {
604             cart.addItem(cartLocation.intValue(), newItem);
605         }
606
607         try {
608             newItem.setQuantity(quantity, dispatcher, cart, triggerExternalOps);
609         } catch (CartItemModifyException e) {
610             cart.removeEmptyCartItems();
611             throw e;
612         }
613
614         if (selectedAmount > 0) {
615             newItem.setSelectedAmount(selectedAmount);
616         }
617         return newItem;
618     }
619
620     /** Clone an item. */
621     public ShoppingCartItem(ShoppingCartItem item) {
622         try {
623             this._product = item.getProduct();
624         } catch (IllegalStateException JavaDoc e) {
625             this._product = null;
626         }
627         this.delegator = item.getDelegator();
628         this.delegatorName = item.delegatorName;
629         this.prodCatalogId = item.getProdCatalogId();
630         this.productId = item.getProductId();
631         this.itemType = item.getItemType();
632         this.productCategoryId = item.getProductCategoryId();
633         this.quantity = item.getQuantity();
634         this.reservStart = item.getReservStart();
635         this.reservLength = item.getReservLength();
636         this.reservPersons = item.getReservPersons();
637         this.selectedAmount = item.getSelectedAmount();
638         this.setBasePrice(item.getBasePrice());
639         this.setDisplayPrice(item.getDisplayPrice());
640         this.listPrice = item.getListPrice();
641         this.reserv2ndPPPerc = item.getReserv2ndPPPerc();
642         this.reservNthPPPerc = item.getReservNthPPPerc();
643         this.requirementId = item.getRequirementId();
644         this.quoteId = item.getQuoteId();
645         this.quoteItemSeqId = item.getQuoteItemSeqId();
646         this.isPromo = item.getIsPromo();
647         this.promoQuantityUsed = item.promoQuantityUsed;
648         this.locale = item.locale;
649         this.quantityUsedPerPromoCandidate = new HashMap JavaDoc(item.quantityUsedPerPromoCandidate);
650         this.quantityUsedPerPromoFailed = new HashMap JavaDoc(item.quantityUsedPerPromoFailed);
651         this.quantityUsedPerPromoActual = new HashMap JavaDoc(item.quantityUsedPerPromoActual);
652         this.orderItemSeqId = item.getOrderItemSeqId();
653         this.additionalProductFeatureAndAppls = item.getAdditionalProductFeatureAndAppls() == null ?
654                 null : new HashMap JavaDoc(item.getAdditionalProductFeatureAndAppls());
655         this.attributes = item.getAttributes() == null ? new HashMap JavaDoc() : new HashMap JavaDoc(item.getAttributes());
656         this.contactMechIdsMap = item.getOrderItemContactMechIds() == null ? null : new HashMap JavaDoc(item.getOrderItemContactMechIds());
657         this.orderItemPriceInfos = item.getOrderItemPriceInfos() == null ? null : new LinkedList JavaDoc(item.getOrderItemPriceInfos());
658         this.itemAdjustments = item.getAdjustments() == null ? null : new LinkedList JavaDoc(item.getAdjustments());
659         if (this._product == null) {
660             this.itemDescription = item.getName();
661         }
662         if (item.configWrapper != null) {
663             this.configWrapper = new ProductConfigWrapper(item.configWrapper);
664         }
665     }
666
667     /** Cannot create shopping cart item with no parameters */
668     protected ShoppingCartItem() {}
669
670     /** Creates new ShoppingCartItem object. */
671     protected ShoppingCartItem(GenericValue product, Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, Locale JavaDoc locale) {
672         this(product, additionalProductFeatureAndAppls, attributes, prodCatalogId, null, locale);
673          if (product != null) {
674             String JavaDoc productName = ProductContentWrapper.getProductContentAsText(product, "PRODUCT_NAME", this.locale);
675             // if the productName is null or empty, see if there is an associated virtual product and get the productName of that product
676
if (UtilValidate.isEmpty(productName)) {
677                 GenericValue parentProduct = this.getParentProduct();
678                 if (parentProduct != null) {
679                     productName = ProductContentWrapper.getProductContentAsText(parentProduct, "PRODUCT_NAME", this.locale);
680                 }
681             }
682
683             if (productName == null) {
684                 this.itemDescription= "";
685             } else {
686                 this.itemDescription= productName;
687             }
688         }
689     }
690
691     /** Creates new ShoppingCartItem object. */
692     protected ShoppingCartItem(GenericValue product, Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, ProductConfigWrapper configWrapper, Locale JavaDoc locale) {
693         this._product = product;
694         this.productId = _product.getString("productId");
695         if (_product.getString("productTypeId").equals("ASSET_USAGE")) {
696             this.itemType = "RENTAL_ORDER_ITEM"; // will create additional workeffort/asset usage records
697
} else {
698             this.itemType = "PRODUCT_ORDER_ITEM";
699         }
700         this.prodCatalogId = prodCatalogId;
701         this.attributes = (attributes == null? FastMap.newInstance(): attributes);
702         this.delegator = _product.getDelegator();
703         this.delegatorName = _product.getDelegator().getDelegatorName();
704         this.addAllProductFeatureAndAppls(additionalProductFeatureAndAppls);
705         this.locale = locale;
706         this.configWrapper = configWrapper;
707     }
708
709     /** Creates new ShopingCartItem object. */
710     protected ShoppingCartItem(GenericDelegator delegator, String JavaDoc itemTypeId, String JavaDoc description, String JavaDoc categoryId, double basePrice, Map JavaDoc attributes, String JavaDoc prodCatalogId, Locale JavaDoc locale) {
711         this.delegator = delegator;
712         this.itemType = itemTypeId;
713         this.itemDescription = description;
714         this.productCategoryId = categoryId;
715         this.setBasePrice(basePrice);
716         this.setDisplayPrice(basePrice);
717         this.attributes = attributes;
718         this.prodCatalogId = prodCatalogId;
719         this.delegatorName = delegator.getDelegatorName();
720         this.locale = locale;
721        }
722
723     public String JavaDoc getProdCatalogId() {
724         return this.prodCatalogId;
725     }
726
727     /** Sets the user selected amount */
728     public void setSelectedAmount(double selectedAmount) {
729         this.selectedAmount = selectedAmount;
730     }
731
732     /** Returns the user selected amount */
733     public double getSelectedAmount() {
734         return this.selectedAmount;
735     }
736
737     /** Sets the base price for the item; use with caution */
738     public void setBasePrice(double basePrice) {
739         this.basePrice = basePrice;
740     }
741
742     /** Sets the display price for the item; use with caution */
743     public void setDisplayPrice(double displayPrice) {
744         this.displayPrice = new Double JavaDoc(displayPrice);
745     }
746
747     public void setSpecialPromoPrice(Double JavaDoc specialPromoPrice) {
748         this.specialPromoPrice = specialPromoPrice;
749     }
750
751     /** Sets the extra % for second person */
752     public void setReserv2ndPPPerc(double reserv2ndPPPerc) {
753         this.reserv2ndPPPerc = reserv2ndPPPerc;
754     }
755     /** Sets the extra % for third and following person */
756     public void setReservNthPPPerc(double reservNthPPPerc) {
757         this.reservNthPPPerc = reservNthPPPerc;
758     }
759     /** Sets the reservation start date */
760     public void setReservStart(Timestamp JavaDoc reservStart) {
761         this.reservStart = reservStart;
762     }
763     /** Sets the reservation length */
764     public void setReservLength(double reservLength) {
765         this.reservLength = reservLength;
766     }
767     /** Sets number of persons using the reservation */
768     public void setReservPersons(double reservPersons) {
769         this.reservPersons = reservPersons;
770     }
771
772     /** Sets the quantity for the item and validates the change in quantity, etc */
773     public void setQuantity(double quantity, LocalDispatcher dispatcher, ShoppingCart cart) throws CartItemModifyException {
774         this.setQuantity(quantity, dispatcher, cart, true);
775     }
776
777     /** Sets the quantity for the item and validates the change in quantity, etc */
778     public void setQuantity(double quantity, LocalDispatcher dispatcher, ShoppingCart cart, boolean triggerExternalOps) throws CartItemModifyException {
779         this.setQuantity(quantity, dispatcher, cart, triggerExternalOps, true);
780     }
781
782     /** Sets the quantity for the item and validates the change in quantity, etc */
783     public void setQuantity(double quantity, LocalDispatcher dispatcher, ShoppingCart cart, boolean triggerExternalOps, boolean resetShipGroup) throws CartItemModifyException {
784         this.setQuantity((int) quantity, dispatcher, cart, triggerExternalOps, resetShipGroup, true);
785     }
786
787     /** Sets the quantity for the item and validates the change in quantity, etc */
788     public void setQuantity(double quantity, LocalDispatcher dispatcher, ShoppingCart cart, boolean triggerExternalOps, boolean resetShipGroup, boolean updateProductPrice) throws CartItemModifyException {
789         this.setQuantity((int) quantity, dispatcher, cart, triggerExternalOps, resetShipGroup, updateProductPrice);
790     }
791
792     /** returns "OK" when the product can be booked or returns a string with the dates the related fixed Asset is not available */
793     public static String JavaDoc checkAvailability(String JavaDoc productId, double quantity, Timestamp JavaDoc reservStart, double reservLength, ShoppingCart cart) {
794         GenericDelegator delegator = cart.getDelegator();
795         // find related fixedAsset
796
List JavaDoc selFixedAssetProduct = null;
797         GenericValue fixedAssetProduct = null;
798         try {
799             List JavaDoc allFixedAssetProduct = delegator.findByAnd("FixedAssetProduct", UtilMisc.toMap("productId", productId, "fixedAssetProductTypeId", "FAPT_USE"));
800             selFixedAssetProduct = EntityUtil.filterByDate(allFixedAssetProduct, UtilDateTime.nowTimestamp(), "fromDate", "thruDate", true);
801         } catch (GenericEntityException e) {
802             return "Could not find a related Fixed Asset for the product: " + productId;
803         }
804         if (selFixedAssetProduct != null && selFixedAssetProduct.size() > 0) {
805             Iterator JavaDoc firstOne = selFixedAssetProduct.iterator();
806             fixedAssetProduct = (GenericValue) firstOne.next();
807         } else {
808             return "Could not find a related Fixed Asset for the product: " + productId;
809         }
810
811         // find the fixed asset itself
812
GenericValue fixedAsset = null;
813         try {
814             fixedAsset = fixedAssetProduct.getRelatedOne("FixedAsset");
815         } catch (GenericEntityException e) {
816             return "fixed_Asset_not_found. Fixed AssetId: " + fixedAssetProduct.getString("fixedAssetId");
817         }
818         if (fixedAsset == null) {
819             return "fixed_Asset_not_found. Fixed AssetId: " + fixedAssetProduct.getString("fixedAssetId");
820         }
821         //Debug.logInfo("Checking availability for product: " + productId.toString() + " and related FixedAsset: " + fixedAssetProduct.getString("fixedAssetId"),module);
822

823         // see if this fixed asset has a calendar, when no create one and attach to fixed asset
824
// DEJ20050725 this isn't being used anywhere, commenting out for now and not assigning from the getRelatedOne: GenericValue techDataCalendar = null;
825
try {
826             fixedAsset.getRelatedOne("TechDataCalendar");
827         } catch (GenericEntityException e) {
828             // no calendar ok, when not more that total capacity
829
if (fixedAsset.getDouble("productionCapacity").doubleValue() >= quantity) {
830                 return "OK";
831             } else {
832                 return "Quantity requested: " + quantity + " Quantity available: " + fixedAsset.getString("productionCapacity");
833             }
834         }
835         // now find all the dates and check the availabilty for each date
836
// please note that calendarId is the same for (TechData)Calendar, CalendarExcDay and CalendarExWeek
837
long dayCount = 0;
838         String JavaDoc resultMessage = "";
839         while (dayCount < (long) reservLength) {
840             GenericValue techDataCalendarExcDay = null;
841             // find an existing Day exception record
842
Timestamp JavaDoc exceptionDateStartTime = new Timestamp JavaDoc((long) (reservStart.getTime() + (dayCount++ * 86400000)));
843             try {
844                 techDataCalendarExcDay = delegator.findByPrimaryKey("TechDataCalendarExcDay",
845                         UtilMisc.toMap("calendarId", fixedAsset.get("calendarId"), "exceptionDateStartTime", exceptionDateStartTime));
846             } catch (GenericEntityException e) {
847                 if (fixedAsset.get("productionCapacity") != null) {
848                     //Debug.logInfo(" No exception day record found, available: " + fixedAsset.getString("productionCapacity") + " Requested now: " + quantity, module);
849
if (fixedAsset.getDouble("productionCapacity").doubleValue() < quantity)
850                         resultMessage = resultMessage.concat(exceptionDateStartTime.toString().substring(0, 10) + ", ");
851                 }
852             }
853             if (techDataCalendarExcDay != null) {
854                 // see if we can get the number of assets available
855
// first try techDataCalendarExcDay(exceptionCapacity) and then FixedAsset(productionCapacity)
856
// if still zero, do not check availability
857
double exceptionCapacity = 0.00;
858                 if (techDataCalendarExcDay.get("exceptionCapacity") != null)
859                     exceptionCapacity = techDataCalendarExcDay.getDouble("exceptionCapacity").doubleValue();
860                 if (exceptionCapacity == 0.00 && fixedAsset.get("productionCapacity") != null)
861                     exceptionCapacity = fixedAsset.getDouble("productionCapacity").doubleValue();
862                 if (exceptionCapacity != 0.00) {
863                     double usedCapacity = 0.00;
864                     if (techDataCalendarExcDay.get("usedCapacity") != null)
865                         usedCapacity = techDataCalendarExcDay.getDouble("usedCapacity").doubleValue();
866                     if (exceptionCapacity < (quantity + usedCapacity)) {
867                         resultMessage = resultMessage.concat(exceptionDateStartTime.toString().substring(0, 10) + ", ");
868                         Debug.logInfo("No rental fixed Asset available: " + exceptionCapacity +
869                                 " already used: " + usedCapacity +
870                                 " Requested now: " + quantity, module);
871                     }
872                 }
873             }
874         }
875         if (resultMessage.compareTo("") == 0)
876             return "OK";
877         else
878             return "I am sorry, not available at these dates: " + resultMessage + "item not added to the shopping cart.....";
879     }
880
881     protected void setQuantity(int quantity, LocalDispatcher dispatcher, ShoppingCart cart, boolean triggerExternalOps, boolean resetShipGroup, boolean updateProductPrice) throws CartItemModifyException {
882         if (this.quantity == quantity) {
883             return;
884         }
885
886         if (this.isPromo) {
887             throw new CartItemModifyException("Sorry, you can't change the quantity on the promotion item " + this.getName() + " (product ID: " + productId + "), not setting quantity.");
888         }
889
890         // needed for inventory checking and auto-save
891
String JavaDoc productStoreId = cart.getProductStoreId();
892
893         if (!"PURCHASE_ORDER".equals(cart.getOrderType())) {
894             // check inventory if new quantity is greater than old quantity; don't worry about inventory getting pulled out from under, that will be handled at checkout time
895
if (_product != null && quantity > this.quantity) {
896                 try {
897                     Map JavaDoc invReqResult = dispatcher.runSync("isStoreInventoryAvailableOrNotRequired", UtilMisc.toMap("productStoreId", productStoreId, "productId", productId, "product", this.getProduct(), "quantity", new Double JavaDoc(quantity)));
898                     if (ServiceUtil.isError(invReqResult)) {
899                         Debug.logError("Error calling isStoreInventoryAvailableOrNotRequired service, result is: " + invReqResult, module);
900                         throw new CartItemModifyException((String JavaDoc) invReqResult.get(ModelService.ERROR_MESSAGE));
901                     } else if (!"Y".equals((String JavaDoc) invReqResult.get("availableOrNotRequired"))) {
902                         String JavaDoc excMsg = "Sorry, we do not have enough (you tried " + UtilFormatOut.formatQuantity(quantity) + ") of the product " + this.getName() + " (product ID: " + productId + ") in stock, not adding to cart. Please try a lower quantity, try again later, or call customer service for more information.";
903                         Debug.logWarning(excMsg, module);
904                         throw new CartItemModifyException(excMsg);
905                     }
906                 } catch (GenericServiceException e) {
907                     String JavaDoc errMsg = "Fatal error calling inventory checking services: " + e.toString();
908                     Debug.logError(e, errMsg, module);
909                     throw new CartItemModifyException(errMsg);
910                 }
911             }
912         }
913
914         // set quantity before promos so order total, etc will be updated
915
this.quantity = quantity;
916
917         if (updateProductPrice) {
918             this.updatePrice(dispatcher, cart);
919         }
920
921         // apply/unapply promotions
922
if (triggerExternalOps) {
923             ProductPromoWorker.doPromotions(cart, dispatcher);
924         }
925
926         if (!"PURCHASE_ORDER".equals(cart.getOrderType())) {
927             // store the auto-save cart
928
if (triggerExternalOps && ProductStoreWorker.autoSaveCart(delegator, productStoreId)) {
929                 try {
930                     ShoppingListEvents.fillAutoSaveList(cart, dispatcher);
931                 } catch (GeneralException e) {
932                     Debug.logWarning(e, UtilProperties.getMessage(resource_error,"OrderUnableToStoreAutoSaveCart", locale));
933                 }
934             }
935         }
936
937         // set the item ship group
938
if (resetShipGroup) {
939             cart.clearItemShipInfo(this);
940             cart.setItemShipGroupQty(this, quantity, 0);
941         }
942     }
943
944     public void updatePrice(LocalDispatcher dispatcher, ShoppingCart cart) throws CartItemModifyException {
945         // set basePrice using the calculateProductPrice service
946
if (_product != null && isModifiedPrice==false) {
947             try {
948                 Map JavaDoc priceContext = FastMap.newInstance();
949                 priceContext.put("currencyUomId", cart.getCurrency());
950
951                 String JavaDoc partyId = cart.getPartyId();
952                 if (partyId != null) {
953                     priceContext.put("partyId", partyId);
954                 }
955                 priceContext.put("quantity", new Double JavaDoc(this.getQuantity()));
956                 priceContext.put("product", this.getProduct());
957                 if (cart.getOrderType().equals("PURCHASE_ORDER")) {
958                     Map JavaDoc priceResult = dispatcher.runSync("calculatePurchasePrice", priceContext);
959                     if (ServiceUtil.isError(priceResult)) {
960                         throw new CartItemModifyException("There was an error while calculating the price: " + ServiceUtil.getErrorMessage(priceResult));
961                     }
962                     Boolean JavaDoc validPriceFound = (Boolean JavaDoc) priceResult.get("validPriceFound");
963                     if (!validPriceFound.booleanValue()) {
964                         throw new CartItemModifyException("Could not find a valid price for the product with ID [" + this.getProductId() + "] and supplier with ID [" + partyId + "], not adding to cart.");
965                     }
966
967                     this.setBasePrice(((Double JavaDoc) priceResult.get("price")).doubleValue());
968                     this.setDisplayPrice(this.basePrice);
969                     this.orderItemPriceInfos = (List JavaDoc) priceResult.get("orderItemPriceInfos");
970                 } else {
971                     priceContext.put("prodCatalogId", this.getProdCatalogId());
972                     priceContext.put("webSiteId", cart.getWebSiteId());
973                     priceContext.put("productStoreId", cart.getProductStoreId());
974                     Map JavaDoc priceResult = dispatcher.runSync("calculateProductPrice", priceContext);
975                     if (ServiceUtil.isError(priceResult)) {
976                         throw new CartItemModifyException("There was an error while calculating the price: " + ServiceUtil.getErrorMessage(priceResult));
977                     }
978
979                     Boolean JavaDoc validPriceFound = (Boolean JavaDoc) priceResult.get("validPriceFound");
980                     if (!validPriceFound.booleanValue()) {
981                         throw new CartItemModifyException("Could not find a valid price for the product with ID [" + this.getProductId() + "], not adding to cart.");
982                     }
983
984                     if (priceResult.get("listPrice") != null) {
985                         this.listPrice = ((Double JavaDoc) priceResult.get("listPrice")).doubleValue();
986                     }
987
988                     if (priceResult.get("basePrice") != null) {
989                         this.setBasePrice(((Double JavaDoc) priceResult.get("basePrice")).doubleValue());
990                     }
991
992                     if (priceResult.get("price") != null) {
993                         this.setDisplayPrice(((Double JavaDoc) priceResult.get("price")).doubleValue());
994                     }
995
996                     this.setSpecialPromoPrice((Double JavaDoc) priceResult.get("specialPromoPrice"));
997
998                     this.orderItemPriceInfos = (List JavaDoc) priceResult.get("orderItemPriceInfos");
999
1000                    // If product is configurable, the price is taken from the configWrapper.
1001
if (configWrapper != null) {
1002                        // TODO: for configurable products need to do something to make them VAT aware... for now base and display prices are the same
1003
this.setBasePrice(configWrapper.getTotalPrice());
1004                        this.setDisplayPrice(configWrapper.getTotalPrice());
1005                    }
1006                }
1007            } catch (GenericServiceException e) {
1008                throw new CartItemModifyException("There was an error while calculating the price", e);
1009            }
1010        }
1011
1012    }
1013
1014    /** Returns the quantity. */
1015    public double getQuantity() {
1016        return this.quantity;
1017    }
1018
1019    /** Returns the reservation start date. */
1020    public Timestamp JavaDoc getReservStart() {
1021        return this.getReservStart(0);
1022    }
1023    /** Returns the reservation start date with a number of days added. */
1024    public Timestamp JavaDoc getReservStart(double addDays) {
1025        if (addDays == 0)
1026                return this.reservStart;
1027        else {
1028            if(this.reservStart != null)
1029                return new Timestamp JavaDoc((long)(this.reservStart.getTime() + (addDays * 86400000.0)));
1030            else
1031                return null;
1032        }
1033    }
1034    /** Returns the reservation length. */
1035    public double getReservLength() {
1036        return this.reservLength;
1037    }
1038    /** Returns the reservation number of persons. */
1039    public double getReservPersons() {
1040        return this.reservPersons;
1041    }
1042
1043    public double getPromoQuantityUsed() {
1044        if (this.getIsPromo()) {
1045            return this.quantity;
1046        } else {
1047            return this.promoQuantityUsed;
1048        }
1049    }
1050
1051    public double getPromoQuantityAvailable() {
1052        if (this.getIsPromo()) {
1053            return 0;
1054        } else {
1055            return this.quantity - this.promoQuantityUsed;
1056        }
1057    }
1058
1059    public Iterator JavaDoc getQuantityUsedPerPromoActualIter() {
1060        return this.quantityUsedPerPromoActual.entrySet().iterator();
1061    }
1062
1063    public Iterator JavaDoc getQuantityUsedPerPromoCandidateIter() {
1064        return this.quantityUsedPerPromoCandidate.entrySet().iterator();
1065    }
1066
1067    public Iterator JavaDoc getQuantityUsedPerPromoFailedIter() {
1068        return this.quantityUsedPerPromoFailed.entrySet().iterator();
1069    }
1070
1071    public synchronized double addPromoQuantityCandidateUse(double quantityDesired, GenericValue productPromoCondAction, boolean checkAvailableOnly) {
1072        if (quantityDesired == 0) return 0;
1073        double promoQuantityAvailable = this.getPromoQuantityAvailable();
1074        double promoQuantityToUse = quantityDesired;
1075        if (promoQuantityAvailable > 0) {
1076            if (promoQuantityToUse > promoQuantityAvailable) {
1077                promoQuantityToUse = promoQuantityAvailable;
1078            }
1079
1080            if (!checkAvailableOnly) {
1081                // keep track of candidate promo uses on cartItem
1082
GenericPK productPromoCondActionPK = productPromoCondAction.getPrimaryKey();
1083                Double JavaDoc existingValue = (Double JavaDoc) this.quantityUsedPerPromoCandidate.get(productPromoCondActionPK);
1084                if (existingValue == null) {
1085                    this.quantityUsedPerPromoCandidate.put(productPromoCondActionPK, new Double JavaDoc(promoQuantityToUse));
1086                } else {
1087                    this.quantityUsedPerPromoCandidate.put(productPromoCondActionPK, new Double JavaDoc(promoQuantityToUse + existingValue.doubleValue()));
1088                }
1089
1090                this.promoQuantityUsed += promoQuantityToUse;
1091                //Debug.logInfo("promoQuantityToUse=" + promoQuantityToUse + ", quantityDesired=" + quantityDesired + ", for promoCondAction: " + productPromoCondAction, module);
1092
//Debug.logInfo("promoQuantityUsed now=" + promoQuantityUsed, module);
1093
}
1094
1095            return promoQuantityToUse;
1096        } else {
1097            return 0;
1098        }
1099    }
1100
1101    public double getPromoQuantityCandidateUse(GenericValue productPromoCondAction) {
1102        GenericPK productPromoCondActionPK = productPromoCondAction.getPrimaryKey();
1103        Double JavaDoc existingValue = (Double JavaDoc) this.quantityUsedPerPromoCandidate.get(productPromoCondActionPK);
1104        if (existingValue == null) {
1105            return 0;
1106        } else {
1107            return existingValue.doubleValue();
1108        }
1109    }
1110
1111    public double getPromoQuantityCandidateUseActionAndAllConds(GenericValue productPromoAction) {
1112        double totalUse = 0;
1113        String JavaDoc productPromoId = productPromoAction.getString("productPromoId");
1114        String JavaDoc productPromoRuleId = productPromoAction.getString("productPromoRuleId");
1115
1116        GenericPK productPromoActionPK = productPromoAction.getPrimaryKey();
1117        Double JavaDoc existingValue = (Double JavaDoc) this.quantityUsedPerPromoCandidate.get(productPromoActionPK);
1118        if (existingValue != null) {
1119            totalUse = existingValue.doubleValue();
1120        }
1121
1122        Iterator JavaDoc entryIter = this.quantityUsedPerPromoCandidate.entrySet().iterator();
1123        while (entryIter.hasNext()) {
1124            Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entryIter.next();
1125            GenericPK productPromoCondActionPK = (GenericPK) entry.getKey();
1126            Double JavaDoc quantityUsed = (Double JavaDoc) entry.getValue();
1127            if (quantityUsed != null) {
1128                // must be in the same rule and be a condition
1129
if (productPromoId.equals(productPromoCondActionPK.getString("productPromoId")) &&
1130                        productPromoRuleId.equals(productPromoCondActionPK.getString("productPromoRuleId")) &&
1131                        productPromoCondActionPK.containsKey("productPromoCondSeqId")) {
1132                    totalUse += quantityUsed.doubleValue();
1133                }
1134            }
1135        }
1136
1137        return totalUse;
1138    }
1139
1140    public synchronized void resetPromoRuleUse(String JavaDoc productPromoId, String JavaDoc productPromoRuleId) {
1141        Iterator JavaDoc entryIter = this.quantityUsedPerPromoCandidate.entrySet().iterator();
1142        while (entryIter.hasNext()) {
1143            Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entryIter.next();
1144            GenericPK productPromoCondActionPK = (GenericPK) entry.getKey();
1145            Double JavaDoc quantityUsed = (Double JavaDoc) entry.getValue();
1146            if (productPromoId.equals(productPromoCondActionPK.getString("productPromoId")) && productPromoRuleId.equals(productPromoCondActionPK.getString("productPromoRuleId"))) {
1147                entryIter.remove();
1148                Double JavaDoc existingValue = (Double JavaDoc) this.quantityUsedPerPromoFailed.get(productPromoCondActionPK);
1149                if (existingValue == null) {
1150                    this.quantityUsedPerPromoFailed.put(productPromoCondActionPK, quantityUsed);
1151                } else {
1152                    this.quantityUsedPerPromoFailed.put(productPromoCondActionPK, new Double JavaDoc(quantityUsed.doubleValue() + existingValue.doubleValue()));
1153                }
1154                this.promoQuantityUsed -= quantityUsed.doubleValue();
1155            }
1156        }
1157    }
1158
1159    public synchronized void confirmPromoRuleUse(String JavaDoc productPromoId, String JavaDoc productPromoRuleId) {
1160        Iterator JavaDoc entryIter = this.quantityUsedPerPromoCandidate.entrySet().iterator();
1161        while (entryIter.hasNext()) {
1162            Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entryIter.next();
1163            GenericPK productPromoCondActionPK = (GenericPK) entry.getKey();
1164            Double JavaDoc quantityUsed = (Double JavaDoc) entry.getValue();
1165            if (productPromoId.equals(productPromoCondActionPK.getString("productPromoId")) && productPromoRuleId.equals(productPromoCondActionPK.getString("productPromoRuleId"))) {
1166                entryIter.remove();
1167                Double JavaDoc existingValue = (Double JavaDoc) this.quantityUsedPerPromoActual.get(productPromoCondActionPK);
1168                if (existingValue == null) {
1169                    this.quantityUsedPerPromoActual.put(productPromoCondActionPK, quantityUsed);
1170                } else {
1171                    this.quantityUsedPerPromoActual.put(productPromoCondActionPK, new Double JavaDoc(quantityUsed.doubleValue() + existingValue.doubleValue()));
1172                }
1173            }
1174        }
1175    }
1176
1177    public synchronized void clearPromoRuleUseInfo() {
1178        this.quantityUsedPerPromoActual.clear();
1179        this.quantityUsedPerPromoCandidate.clear();
1180        this.quantityUsedPerPromoFailed.clear();
1181        this.promoQuantityUsed = this.getIsPromo() ? this.quantity : 0;
1182    }
1183
1184    /** Sets the item comment. */
1185    public void setItemComment(String JavaDoc itemComment) {
1186        this.setAttribute("itemComment", itemComment);
1187    }
1188
1189    /** Returns the item's comment. */
1190    public String JavaDoc getItemComment() {
1191        return (String JavaDoc) this.getAttribute("itemComment");
1192    }
1193
1194    /** Sets the item's customer desired delivery date. */
1195    public void setDesiredDeliveryDate(Timestamp JavaDoc ddDate) {
1196        if (ddDate != null) {
1197            this.setAttribute("itemDesiredDeliveryDate", ddDate.toString());
1198        }
1199    }
1200
1201    /** Returns the item's customer desired delivery date. */
1202    public Timestamp JavaDoc getDesiredDeliveryDate() {
1203        String JavaDoc ddDate = (String JavaDoc) this.getAttribute("itemDesiredDeliveryDate");
1204
1205        if (ddDate != null) {
1206            try {
1207                return Timestamp.valueOf(ddDate);
1208            } catch (IllegalArgumentException JavaDoc e) {
1209                Debug.logWarning(e, UtilProperties.getMessage(resource_error,"OrderProblemGettingItemDesiredDeliveryDateFor", UtilMisc.toMap("productId",this.getProductId()), locale));
1210                return null;
1211            }
1212        }
1213        return null;
1214    }
1215
1216    /** Sets the date to ship before */
1217    public void setShipBeforeDate(Timestamp JavaDoc date) {
1218        this.shipBeforeDate = date;
1219        
1220    }
1221
1222    /** Returns the date to ship before */
1223    public Timestamp JavaDoc getShipBeforeDate() {
1224        return this.shipBeforeDate;
1225    }
1226
1227    /** Sets the date to ship after */
1228    public void setShipAfterDate(Timestamp JavaDoc date) {
1229        this.shipAfterDate = date;
1230    }
1231
1232    /** Returns the date to ship after */
1233    public Timestamp JavaDoc getShipAfterDate() {
1234        return this.shipAfterDate;
1235    }
1236
1237    /** Sets the item type. */
1238    public void setItemType(String JavaDoc itemType) {
1239        this.itemType = itemType;
1240    }
1241
1242    /** Returns the item type. */
1243    public String JavaDoc getItemType() {
1244        return this.itemType;
1245    }
1246
1247    /** Returns the item type description. */
1248    public String JavaDoc getItemTypeDescription() {
1249        GenericValue orderItemType = null;
1250        try {
1251            orderItemType = this.getDelegator().findByPrimaryKeyCache("OrderItemType", UtilMisc.toMap("orderItemTypeId", this.getItemType()));
1252        } catch (GenericEntityException e) {
1253            Debug.logWarning(e, UtilProperties.getMessage(resource_error,"OrderProblemsGettingOrderItemTypeFor", UtilMisc.toMap("orderItemTypeId",this.getItemType()), locale));
1254        }
1255        if (itemType != null) {
1256            return orderItemType.getString("description");
1257        }
1258        return null;
1259    }
1260
1261    /** Returns the productCategoryId for the item or null if none. */
1262    public String JavaDoc getProductCategoryId() {
1263        return this.productCategoryId;
1264    }
1265
1266    public void setProductCategoryId(String JavaDoc productCategoryId) {
1267        this.productCategoryId = productCategoryId;
1268    }
1269
1270    public void setOrderItemSeqId(String JavaDoc orderItemSeqId) {
1271        Debug.log("Setting orderItemSeqId - " + orderItemSeqId, module);
1272        this.orderItemSeqId = orderItemSeqId;
1273    }
1274
1275    public String JavaDoc getOrderItemSeqId() {
1276        return orderItemSeqId;
1277    }
1278
1279    public void setShoppingList(String JavaDoc shoppingListId, String JavaDoc itemSeqId) {
1280        attributes.put("shoppingListId", shoppingListId);
1281        attributes.put("shoppingListItemSeqId", itemSeqId);
1282    }
1283
1284    public String JavaDoc getShoppingListId() {
1285        return (String JavaDoc) attributes.get("shoppingListId");
1286    }
1287
1288    public String JavaDoc getShoppingListItemSeqId() {
1289        return (String JavaDoc) attributes.get("shoppingListItemSeqId");
1290    }
1291
1292    /** Sets the requirementId. */
1293    public void setRequirementId(String JavaDoc requirementId) {
1294        this.requirementId = requirementId;
1295    }
1296
1297    /** Returns the requirementId. */
1298    public String JavaDoc getRequirementId() {
1299        return this.requirementId;
1300    }
1301
1302    /** Sets the quoteId. */
1303    public void setQuoteId(String JavaDoc quoteId) {
1304        this.quoteId = quoteId;
1305    }
1306
1307    /** Returns the quoteId. */
1308    public String JavaDoc getQuoteId() {
1309        return this.quoteId;
1310    }
1311
1312    /** Sets the quoteItemSeqId. */
1313    public void setQuoteItemSeqId(String JavaDoc quoteItemSeqId) {
1314        this.quoteItemSeqId = quoteItemSeqId;
1315    }
1316
1317    /** Returns the quoteItemSeqId. */
1318    public String JavaDoc getQuoteItemSeqId() {
1319        return this.quoteItemSeqId;
1320    }
1321
1322    public String JavaDoc getStatusId() {
1323        return this.statusId;
1324    }
1325
1326    public void setStatusId(String JavaDoc statusId) {
1327        this.statusId = statusId;
1328    }
1329
1330    /** Returns true if shipping charges apply to this item. */
1331    public boolean shippingApplies() {
1332        GenericValue product = getProduct();
1333        if (product != null) {
1334            return ProductWorker.shippingApplies(product);
1335        } else {
1336            // we don't ship non-product items
1337
return false;
1338        }
1339    }
1340
1341    /** Returns true if tax charges apply to this item. */
1342    public boolean taxApplies() {
1343        GenericValue product = getProduct();
1344        if (product != null) {
1345            return ProductWorker.taxApplies(product);
1346        } else {
1347            // we do tax non-product items
1348
return true;
1349        }
1350    }
1351
1352    /** Returns the item's productId. */
1353    public String JavaDoc getProductId() {
1354        return productId;
1355    }
1356    /** Set the item's description. */
1357    public void setName(String JavaDoc itemName) {
1358        this.itemDescription = itemName;
1359    }
1360    /** Returns the item's description. */
1361    public String JavaDoc getName() {
1362       if (itemDescription != null) {
1363          return itemDescription;
1364       } else {
1365        GenericValue product = getProduct();
1366        if (product != null) {
1367            String JavaDoc productName = ProductContentWrapper.getProductContentAsText(product, "PRODUCT_NAME", this.locale);
1368            // if the productName is null or empty, see if there is an associated virtual product and get the productName of that product
1369
if (UtilValidate.isEmpty(productName)) {
1370                GenericValue parentProduct = this.getParentProduct();
1371                if (parentProduct != null) {
1372                    productName = ProductContentWrapper.getProductContentAsText(parentProduct, "PRODUCT_NAME", this.locale);
1373                }
1374            }
1375            if (productName == null) {
1376                return "";
1377            } else {
1378                return productName;
1379            }
1380        } else {
1381               return "";
1382            }
1383        }
1384    }
1385
1386    /** Returns the item's description. */
1387    public String JavaDoc getDescription() {
1388        GenericValue product = getProduct();
1389
1390        if (product != null) {
1391            String JavaDoc description = ProductContentWrapper.getProductContentAsText(product, "DESCRIPTION", this.locale);
1392
1393            // if the description is null or empty, see if there is an associated virtual product and get the description of that product
1394
if (UtilValidate.isEmpty(description)) {
1395                GenericValue parentProduct = this.getParentProduct();
1396                if (parentProduct != null) {
1397                    description = ProductContentWrapper.getProductContentAsText(parentProduct, "DESCRIPTION", this.locale);
1398                }
1399            }
1400
1401            if (description == null) {
1402                return "";
1403            } else {
1404                return description;
1405            }
1406        } else {
1407            return null;
1408        }
1409    }
1410
1411    public ProductConfigWrapper getConfigWrapper() {
1412        return configWrapper;
1413    }
1414
1415    /** Returns the item's unit weight */
1416    public double getWeight() {
1417        GenericValue product = getProduct();
1418        if (product != null) {
1419            Double JavaDoc weight = product.getDouble("weight");
1420
1421            // if the weight is null, see if there is an associated virtual product and get the weight of that product
1422
if (weight == null) {
1423                GenericValue parentProduct = this.getParentProduct();
1424                if (parentProduct != null) weight = parentProduct.getDouble("weight");
1425            }
1426
1427            if (weight == null) {
1428                return 0;
1429            } else {
1430                return weight.doubleValue();
1431            }
1432        } else {
1433            // non-product items have 0 weight
1434
return 0;
1435        }
1436    }
1437
1438    /** Returns the item's pieces included */
1439    public long getPiecesIncluded() {
1440        GenericValue product = getProduct();
1441        if (product != null) {
1442            Long JavaDoc pieces = product.getLong("piecesIncluded");
1443
1444            // if the piecesIncluded is null, see if there is an associated virtual product and get the piecesIncluded of that product
1445
if (pieces == null) {
1446                GenericValue parentProduct = this.getParentProduct();
1447                if (parentProduct != null) pieces = parentProduct.getLong("piecesIncluded");
1448            }
1449
1450            if (pieces == null) {
1451                return 1;
1452            } else {
1453                return pieces.longValue();
1454            }
1455        } else {
1456            // non-product item assumed 1 piece
1457
return 1;
1458        }
1459    }
1460
1461    /** Returns a Set of the item's features */
1462    public Set JavaDoc getFeatureSet() {
1463        Set JavaDoc featureSet = new ListOrderedSet();
1464        GenericValue product = this.getProduct();
1465        if (product != null) {
1466            List JavaDoc featureAppls = null;
1467            try {
1468                featureAppls = product.getRelated("ProductFeatureAppl");
1469                List JavaDoc filterExprs = UtilMisc.toList(new EntityExpr("productFeatureApplTypeId", EntityOperator.EQUALS, "STANDARD_FEATURE"));
1470                filterExprs.add(new EntityExpr("productFeatureApplTypeId", EntityOperator.EQUALS, "REQUIRED_FEATURE"));
1471                featureAppls = EntityUtil.filterByOr(featureAppls, filterExprs);
1472            } catch (GenericEntityException e) {
1473                Debug.logError(e, "Unable to get features from product : " + product.get("productId"), module);
1474            }
1475            if (featureAppls != null) {
1476                Iterator JavaDoc fai = featureAppls.iterator();
1477                while (fai.hasNext()) {
1478                    GenericValue appl = (GenericValue) fai.next();
1479                    featureSet.add(appl.getString("productFeatureId"));
1480                }
1481            }
1482        }
1483        if (this.additionalProductFeatureAndAppls != null) {
1484            Iterator JavaDoc aapi = this.additionalProductFeatureAndAppls.values().iterator();
1485            while (aapi.hasNext()) {
1486                GenericValue appl = (GenericValue) aapi.next();
1487                featureSet.add(appl.getString("productFeatureId"));
1488            }
1489        }
1490        return featureSet;
1491    }
1492    /** Returns a list of the item's standard features */
1493    public List JavaDoc getStandardFeatureList() {
1494        List JavaDoc features = null;
1495        GenericValue product = this.getProduct();
1496        if (product != null) {
1497            try {
1498                List JavaDoc featureAppls = product.getRelated("ProductFeatureAndAppl");
1499                features=EntityUtil.filterByAnd(featureAppls,UtilMisc.toMap("productFeatureApplTypeId","STANDARD_FEATURE"));
1500            } catch (GenericEntityException e) {
1501                Debug.logError(e, "Unable to get features from product : " + product.get("productId"), module);
1502            }
1503        }
1504        return features;
1505    }
1506
1507    /** Returns a List of the item's features for supplier*/
1508   public List JavaDoc getFeaturesForSupplier(LocalDispatcher dispatcher,String JavaDoc partyId) {
1509       List JavaDoc featureAppls = getStandardFeatureList();
1510       if (featureAppls != null && featureAppls.size() > 0) {
1511           try {
1512              Map JavaDoc result = dispatcher.runSync("convertFeaturesForSupplier", UtilMisc.toMap("partyId", partyId, "productFeatures", featureAppls));
1513              featuresForSupplier = (List JavaDoc) result.get("convertedProductFeatures");
1514           } catch (GenericServiceException e) {
1515               Debug.logError(e, "Unable to get features for supplier from product : " + this.productId, module);
1516           }
1517       }
1518       return featuresForSupplier;
1519   }
1520
1521    /** Returns the item's size (length + girth) */
1522    public double getSize() {
1523        GenericValue product = getProduct();
1524        if (product != null) {
1525            Double JavaDoc height = product.getDouble("shippingHeight");
1526            Double JavaDoc width = product.getDouble("shippingWidth");
1527            Double JavaDoc depth = product.getDouble("shippingDepth");
1528
1529            // if all are null, see if there is an associated virtual product and get the info of that product
1530
if (height == null & width == null && depth == null) {
1531                GenericValue parentProduct = this.getParentProduct();
1532                if (parentProduct != null) {
1533                    height = parentProduct.getDouble("shippingHeight");
1534                    width = product.getDouble("shippingWidth");
1535                    depth = product.getDouble("shippingDepth");
1536                }
1537            }
1538
1539            if (height == null) height = new Double JavaDoc(0);
1540            if (width == null) width = new Double JavaDoc(0);
1541            if (depth == null) depth = new Double JavaDoc(0);
1542
1543            // determine girth (longest field is length)
1544
double[] sizeInfo = { height.doubleValue(), width.doubleValue(), depth.doubleValue() };
1545            Arrays.sort(sizeInfo);
1546
1547            return (sizeInfo[0] * 2) + (sizeInfo[1] * 2) + sizeInfo[2];
1548        } else {
1549            // non-product items have 0 size
1550
return 0;
1551        }
1552    }
1553
1554    public Map JavaDoc getItemProductInfo() {
1555        Map JavaDoc itemInfo = FastMap.newInstance();
1556        itemInfo.put("productId", this.getProductId());
1557        itemInfo.put("weight", new Double JavaDoc(this.getWeight()));
1558        itemInfo.put("size", new Double JavaDoc(this.getSize()));
1559        itemInfo.put("piecesIncluded", new Long JavaDoc(this.getPiecesIncluded()));
1560        itemInfo.put("featureSet", this.getFeatureSet());
1561        return itemInfo;
1562    }
1563
1564    /** Returns the base price. */
1565    public double getBasePrice() {
1566        double curBasePrice;
1567        if (selectedAmount > 0) {
1568            curBasePrice = basePrice * selectedAmount;
1569        } else {
1570            curBasePrice = basePrice;
1571        }
1572        return curBasePrice;
1573    }
1574    
1575    public double getDisplayPrice() {
1576        double curDisplayPrice;
1577        if (this.displayPrice == null) {
1578            curDisplayPrice = this.getBasePrice();
1579        } else {
1580            if (selectedAmount > 0) {
1581                curDisplayPrice = this.displayPrice.doubleValue() * this.selectedAmount;
1582            } else {
1583                curDisplayPrice = this.displayPrice.doubleValue();
1584            }
1585        }
1586        return curDisplayPrice;
1587    }
1588    
1589    public Double JavaDoc getSpecialPromoPrice() {
1590        return this.specialPromoPrice;
1591    }
1592
1593    /** Returns the list price. */
1594    public double getListPrice() {
1595        return listPrice;
1596    }
1597
1598    /** Returns isModifiedPrice */
1599    public boolean getIsModifiedPrice() {
1600        return isModifiedPrice;
1601    }
1602
1603    /** Set isModifiedPrice */
1604    public void setIsModifiedPrice(boolean isModifiedPrice) {
1605        this.isModifiedPrice = isModifiedPrice;
1606    }
1607
1608    /** get the percentage for the second person */
1609    public double getReserv2ndPPPerc() {
1610        return reserv2ndPPPerc;
1611    }
1612
1613    /** get the percentage for the third and following person */
1614    public double getReservNthPPPerc() {
1615        return reservNthPPPerc;
1616    }
1617
1618
1619    /** Returns the "other" adjustments. */
1620    public double getOtherAdjustments() {
1621        return OrderReadHelper.calcItemAdjustments(new Double JavaDoc(quantity), new Double JavaDoc(getBasePrice()), this.getAdjustments(), true, false, false, false, false);
1622    }
1623
1624    /** calculates for a reservation the percentage/100 extra for more than 1 person. */
1625    // similar code at editShoppingList.bsh
1626
public double getRentalAdjustment() {
1627        if (!this.itemType.equals("RENTAL_ORDER_ITEM")) {
1628            // not a rental item?
1629
return 1;
1630        }
1631        double persons = this.getReservPersons();
1632        double rentalValue = 0;
1633        if (persons > 1) {
1634            if (persons > 2 ) {
1635                persons -= 2;
1636                if(getReservNthPPPerc() > 0) {
1637                    rentalValue = persons * getReservNthPPPerc();
1638                } else {
1639                    rentalValue = persons * getReserv2ndPPPerc();
1640                }
1641                persons = 2;
1642            }
1643            if (persons == 2) {
1644                rentalValue += getReserv2ndPPPerc();
1645            }
1646        }
1647        rentalValue += 100; // add final 100 percent for first person
1648
// Debug.log("rental parameters....Nbr of persons:" + getReservPersons() + " extra% 2nd person:" + getReserv2ndPPPerc()+ " extra% Nth person:" + getReservNthPPPerc() + " total rental adjustment:" + rentalValue/100 * getReservLength() );
1649
return rentalValue/100 * getReservLength(); // return total rental adjustment
1650
}
1651
1652    /** Returns the total line price. */
1653    public double getItemSubTotal(double quantity) {
1654// Debug.logInfo("Price" + getBasePrice() + " quantity" + quantity + " Rental adj:" + getRentalAdjustment() + " other adj:" + getOtherAdjustments(), module);
1655
return (getBasePrice() * quantity * getRentalAdjustment()) + getOtherAdjustments();
1656    }
1657
1658    public double getItemSubTotal() {
1659        return this.getItemSubTotal(this.quantity);
1660    }
1661
1662    public double getDisplayItemSubTotal() {
1663        return (getDisplayPrice() * this.quantity * getRentalAdjustment()) + getOtherAdjustments();
1664    }
1665
1666    public void addAllProductFeatureAndAppls(Map JavaDoc productFeatureAndApplsToAdd) {
1667        if (productFeatureAndApplsToAdd == null) return;
1668        Iterator JavaDoc productFeatureAndApplsToAddIter = productFeatureAndApplsToAdd.values().iterator();
1669        while (productFeatureAndApplsToAddIter.hasNext()) {
1670            GenericValue additionalProductFeatureAndAppl = (GenericValue) productFeatureAndApplsToAddIter.next();
1671            this.putAdditionalProductFeatureAndAppl(additionalProductFeatureAndAppl);
1672        }
1673    }
1674
1675    public void putAdditionalProductFeatureAndAppl(GenericValue additionalProductFeatureAndAppl) {
1676        if (additionalProductFeatureAndAppl == null) return;
1677
1678        // if one already exists with the given type, remove it with the corresponding adjustment
1679
removeAdditionalProductFeatureAndAppl(additionalProductFeatureAndAppl.getString("productFeatureTypeId"));
1680
1681        // adds to additional map and creates an adjustment with given price
1682
String JavaDoc featureType = additionalProductFeatureAndAppl.getString("productFeatureTypeId");
1683        this.additionalProductFeatureAndAppls.put(featureType, additionalProductFeatureAndAppl);
1684
1685        GenericValue orderAdjustment = this.getDelegator().makeValue("OrderAdjustment", null);
1686        orderAdjustment.set("orderAdjustmentTypeId", "ADDITIONAL_FEATURE");
1687        orderAdjustment.set("description", additionalProductFeatureAndAppl.get("description"));
1688        orderAdjustment.set("productFeatureId", additionalProductFeatureAndAppl.get("productFeatureId"));
1689        // NOTE: this is a VERY simple pricing scheme for additional features and will likely need to be extended for most real applications
1690
double amount = 0;
1691        Double JavaDoc amountDbl = (Double JavaDoc) additionalProductFeatureAndAppl.get("amount");
1692        if (amountDbl != null) {
1693            amount = amountDbl.doubleValue() * this.getQuantity();
1694        }
1695        orderAdjustment.set("amount", new Double JavaDoc(amount));
1696
1697        this.addAdjustment(orderAdjustment);
1698    }
1699
1700    public GenericValue getAdditionalProductFeatureAndAppl(String JavaDoc productFeatureTypeId) {
1701        if (this.additionalProductFeatureAndAppls == null) return null;
1702        return (GenericValue) this.additionalProductFeatureAndAppls.get(productFeatureTypeId);
1703    }
1704
1705    public GenericValue removeAdditionalProductFeatureAndAppl(String JavaDoc productFeatureTypeId) {
1706        if (this.additionalProductFeatureAndAppls == null) return null;
1707
1708        GenericValue oldAdditionalProductFeatureAndAppl = (GenericValue) this.additionalProductFeatureAndAppls.remove(productFeatureTypeId);
1709
1710        if (oldAdditionalProductFeatureAndAppl != null) {
1711            removeFeatureAdjustment(oldAdditionalProductFeatureAndAppl.getString("productFeatureId"));
1712        }
1713
1714        //if (this.additionalProductFeatureAndAppls.size() == 0) this.additionalProductFeatureAndAppls = null;
1715

1716        return oldAdditionalProductFeatureAndAppl;
1717    }
1718
1719    public Map JavaDoc getAdditionalProductFeatureAndAppls() {
1720        return this.additionalProductFeatureAndAppls;
1721    }
1722
1723    public Map JavaDoc getFeatureIdQtyMap(double quantity) {
1724        Map JavaDoc featureMap = FastMap.newInstance();
1725        GenericValue product = this.getProduct();
1726        if (product != null) {
1727            List JavaDoc featureAppls = null;
1728            try {
1729                featureAppls = product.getRelated("ProductFeatureAppl");
1730                List JavaDoc filterExprs = UtilMisc.toList(new EntityExpr("productFeatureApplTypeId", EntityOperator.EQUALS, "STANDARD_FEATURE"));
1731                filterExprs.add(new EntityExpr("productFeatureApplTypeId", EntityOperator.EQUALS, "REQUIRED_FEATURE"));
1732                featureAppls = EntityUtil.filterByOr(featureAppls, filterExprs);
1733            } catch (GenericEntityException e) {
1734                Debug.logError(e, "Unable to get features from product : " + product.get("productId"), module);
1735            }
1736            if (featureAppls != null) {
1737                Iterator JavaDoc fai = featureAppls.iterator();
1738                while (fai.hasNext()) {
1739                    GenericValue appl = (GenericValue) fai.next();
1740                    Double JavaDoc lastQuantity = (Double JavaDoc) featureMap.get(appl.getString("productFeatureId"));
1741                    if (lastQuantity == null) {
1742                        lastQuantity = new Double JavaDoc(0);
1743                    }
1744                    Double JavaDoc newQuantity = new Double JavaDoc(lastQuantity.doubleValue() + quantity);
1745                    featureMap.put(appl.getString("productFeatureId"), newQuantity);
1746                }
1747            }
1748        }
1749        if (this.additionalProductFeatureAndAppls != null) {
1750            Iterator JavaDoc aapi = this.additionalProductFeatureAndAppls.values().iterator();
1751            while (aapi.hasNext()) {
1752                GenericValue appl = (GenericValue) aapi.next();
1753                Double JavaDoc lastQuantity = (Double JavaDoc) featureMap.get(appl.getString("productFeatureId"));
1754                if (lastQuantity == null) {
1755                    lastQuantity = new Double JavaDoc(0);
1756                }
1757                Double JavaDoc newQuantity = new Double JavaDoc(lastQuantity.doubleValue() + quantity);
1758                featureMap.put(appl.getString("productFeatureId"), newQuantity);
1759            }
1760        }
1761        return featureMap;
1762    }
1763
1764    /** Removes an item attribute. */
1765    public void removeAttribute(String JavaDoc name) {
1766        attributes.remove(name);
1767    }
1768
1769    /** Sets an item attribute. */
1770    public void setAttribute(String JavaDoc name, Object JavaDoc value) {
1771        attributes.put(name, value);
1772    }
1773
1774    /** Return a specific attribute. */
1775    public Object JavaDoc getAttribute(String JavaDoc name) {
1776        return attributes.get(name);
1777    }
1778
1779    /** Returns the attributes for the item. */
1780    public Map JavaDoc getAttributes() {
1781        return attributes;
1782    }
1783
1784    /** Remove an OrderItemAttribute. */
1785    public void removeOrderItemAttribute(String JavaDoc name) {
1786        if (orderItemAttributes != null) {
1787            orderItemAttributes.remove(name);
1788        }
1789    }
1790
1791    /** Creates an OrderItemAttribute entry. */
1792    public void setOrderItemAttribute(String JavaDoc name, String JavaDoc value) {
1793        if (orderItemAttributes == null) orderItemAttributes = FastMap.newInstance();
1794        this.orderItemAttributes.put(name, value);
1795    }
1796
1797    /** Return an OrderItemAttribute. */
1798    public String JavaDoc getOrderItemAttribute(String JavaDoc name) {
1799        if (orderItemAttributes == null) return null;
1800        return (String JavaDoc) this.orderItemAttributes.get(name);
1801    }
1802
1803    public Map JavaDoc getOrderItemAttributes() {
1804        Map JavaDoc attrs = FastMap.newInstance();
1805        if (orderItemAttributes != null) {
1806            attrs.putAll(orderItemAttributes);
1807        }
1808        return attrs;
1809    }
1810
1811    /** Add an adjustment to the order item; don't worry about setting the orderId, orderItemSeqId or orderAdjustmentId; they will be set when the order is created */
1812    public int addAdjustment(GenericValue adjustment) {
1813        itemAdjustments.add(adjustment);
1814        return itemAdjustments.indexOf(adjustment);
1815    }
1816
1817    public void removeAdjustment(GenericValue adjustment) {
1818        itemAdjustments.remove(adjustment);
1819    }
1820
1821    public void removeAdjustment(int index) {
1822        itemAdjustments.remove(index);
1823    }
1824
1825    public List JavaDoc getAdjustments() {
1826        return itemAdjustments;
1827    }
1828
1829    public void removeFeatureAdjustment(String JavaDoc productFeatureId) {
1830        if (productFeatureId == null) return;
1831        Iterator JavaDoc itemAdjustmentsIter = itemAdjustments.iterator();
1832
1833        while (itemAdjustmentsIter.hasNext()) {
1834            GenericValue itemAdjustment = (GenericValue) itemAdjustmentsIter.next();
1835
1836            if (productFeatureId.equals(itemAdjustment.getString("productFeatureId"))) {
1837                itemAdjustmentsIter.remove();
1838            }
1839        }
1840    }
1841
1842    public List JavaDoc getOrderItemPriceInfos() {
1843        return orderItemPriceInfos;
1844    }
1845
1846    /** Add a contact mech to this purpose; the contactMechPurposeTypeId is required */
1847    public void addContactMech(String JavaDoc contactMechPurposeTypeId, String JavaDoc contactMechId) {
1848        if (contactMechPurposeTypeId == null) throw new IllegalArgumentException JavaDoc("You must specify a contactMechPurposeTypeId to add a ContactMech");
1849        contactMechIdsMap.put(contactMechPurposeTypeId, contactMechId);
1850    }
1851
1852    /** Get the contactMechId for this item given the contactMechPurposeTypeId */
1853    public String JavaDoc getContactMech(String JavaDoc contactMechPurposeTypeId) {
1854        return (String JavaDoc) contactMechIdsMap.get(contactMechPurposeTypeId);
1855    }
1856
1857    /** Remove the contactMechId from this item given the contactMechPurposeTypeId */
1858    public String JavaDoc removeContactMech(String JavaDoc contactMechPurposeTypeId) {
1859        return (String JavaDoc) contactMechIdsMap.remove(contactMechPurposeTypeId);
1860    }
1861
1862    public Map JavaDoc getOrderItemContactMechIds() {
1863        return contactMechIdsMap;
1864    }
1865
1866    public void setIsPromo(boolean isPromo) {
1867        this.isPromo = isPromo;
1868    }
1869
1870    public boolean getIsPromo() {
1871        return this.isPromo;
1872    }
1873
1874    public List JavaDoc getAlternativeOptionProductIds() {
1875        return this.alternativeOptionProductIds;
1876    }
1877    public void setAlternativeOptionProductIds(List JavaDoc alternativeOptionProductIds) {
1878        this.alternativeOptionProductIds = alternativeOptionProductIds;
1879    }
1880
1881    /** Compares the specified object with this cart item. */
1882    public boolean equals(ShoppingCartItem item) {
1883        if (item == null) return false;
1884        return this.equals(item.getProductId(), item.additionalProductFeatureAndAppls, item.attributes, item.prodCatalogId, item.selectedAmount, item.getIsPromo());
1885    }
1886
1887    /** Compares the specified object with this cart item. Defaults isPromo to false. */
1888    public boolean equals(String JavaDoc productId, Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, double selectedAmount) {
1889        return equals(productId, additionalProductFeatureAndAppls, attributes, prodCatalogId, selectedAmount, false);
1890    }
1891
1892    /** Compares the specified object with this cart item. Defaults isPromo to false. */
1893    public boolean equals(String JavaDoc productId, Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, ProductConfigWrapper configWrapper, double selectedAmount) {
1894        return equals(productId, null, 0.00, 0.00, additionalProductFeatureAndAppls, attributes, prodCatalogId, selectedAmount, configWrapper, false);
1895    }
1896
1897    /** Compares the specified object with this cart item including rental data. Defaults isPromo to false. */
1898    public boolean equals(String JavaDoc productId, Timestamp JavaDoc reservStart, double reservLength, double reservPersons, Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, ProductConfigWrapper configWrapper, double selectedAmount) {
1899        return equals(productId, reservStart, reservLength, reservPersons, additionalProductFeatureAndAppls, attributes, prodCatalogId, selectedAmount, configWrapper, false);
1900    }
1901
1902    /** Compares the specified object with this cart item. Defaults isPromo to false. */
1903    public boolean equals(String JavaDoc productId, Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, double selectedAmount, boolean isPromo) {
1904        return equals(productId, null, 0.00, 0.00, additionalProductFeatureAndAppls, attributes, prodCatalogId, selectedAmount, null, isPromo);
1905    }
1906
1907    /** Compares the specified object with this cart item. */
1908    public boolean equals(String JavaDoc productId, Timestamp JavaDoc reservStart, double reservLength, double reservPersons, Map JavaDoc additionalProductFeatureAndAppls, Map JavaDoc attributes, String JavaDoc prodCatalogId, double selectedAmount, ProductConfigWrapper configWrapper, boolean isPromo) {
1909        if (this.productId == null || productId == null) {
1910            // all non-product items are unique
1911
return false;
1912        }
1913        if (!this.productId.equals(productId)) {
1914            return false;
1915        }
1916
1917        if ((this.prodCatalogId == null && prodCatalogId != null) || (this.prodCatalogId != null && prodCatalogId == null)) {
1918            return false;
1919        }
1920        if (this.prodCatalogId != null && prodCatalogId != null && !this.prodCatalogId.equals(prodCatalogId)) {
1921            return false;
1922        }
1923
1924        if (this.getSelectedAmount() != selectedAmount) {
1925            return false;
1926        }
1927
1928        if ((this.reservStart == null && reservStart != null) || (this.reservStart != null && reservStart == null)) {
1929            return false;
1930        }
1931        if (this.reservStart != null && reservStart != null && !this.reservStart.equals(reservStart)) {
1932            return false;
1933        }
1934
1935        if (this.reservLength != reservLength) {
1936            return false;
1937        }
1938
1939        if (this.reservPersons != reservPersons) {
1940            return false;
1941        }
1942
1943        if (this.isPromo != isPromo) {
1944            return false;
1945        }
1946
1947        if ((this.additionalProductFeatureAndAppls != null && additionalProductFeatureAndAppls != null) &&
1948                (this.additionalProductFeatureAndAppls.size() != additionalProductFeatureAndAppls.size()) &&
1949                !(this.additionalProductFeatureAndAppls.equals(additionalProductFeatureAndAppls))) {
1950            return false;
1951        }
1952
1953        if ((this.attributes != null && attributes != null) &&
1954                ( (this.attributes.size() != attributes.size()) ||
1955                !(this.attributes.equals(attributes)) )) {
1956            return false;
1957        }
1958
1959        if (configWrapper != null && !configWrapper.equals(this.configWrapper)) {
1960            return false;
1961        }
1962
1963        if (quoteId != null) {
1964            // all items linked to a quote are unique
1965
return false;
1966        }
1967
1968        if (requirementId != null) {
1969            // all items linked to a requirement are unique
1970
return false;
1971        }
1972
1973        return true;
1974    }
1975
1976    /** Gets the Product entity. If it is not already retreived gets it from the delegator */
1977    public GenericValue getProduct() {
1978        if (this._product != null) {
1979            return this._product;
1980        }
1981        if (this.productId != null) {
1982            try {
1983                this._product = this.getDelegator().findByPrimaryKeyCache("Product", UtilMisc.toMap("productId", productId));
1984            } catch (GenericEntityException e) {
1985                throw new RuntimeException JavaDoc("Entity Engine error getting Product (" + e.getMessage() + ")");
1986            }
1987        }
1988        return this._product;
1989    }
1990
1991    public GenericValue getParentProduct() {
1992        if (this._parentProduct != null) {
1993            return this._parentProduct;
1994        }
1995        if (this.productId == null) {
1996            throw new IllegalStateException JavaDoc("Bad product id");
1997        }
1998
1999          this._parentProduct = ProductWorker.getParentProduct(productId, this.getDelegator());
2000
2001        return this._parentProduct;
2002    }
2003
2004    public String JavaDoc getParentProductId() {
2005        GenericValue parentProduct = this.getParentProduct();
2006        if (parentProduct != null) {
2007            return parentProduct.getString("productId");
2008        } else {
2009            return null;
2010        }
2011    }
2012
2013    public Map JavaDoc getOptionalProductFeatures() {
2014        if (_product != null) {
2015            return ProductWorker.getOptionalProductFeatures(getDelegator(), this.productId);
2016        } else {
2017            // non-product items do not have features
2018
return FastMap.newInstance();
2019        }
2020    }
2021
2022    public GenericDelegator getDelegator() {
2023        if (delegator == null) {
2024            if (UtilValidate.isEmpty(delegatorName)) {
2025                throw new IllegalStateException JavaDoc("Bad delegator name");
2026            }
2027            delegator = GenericDelegator.getGenericDelegator(delegatorName);
2028        }
2029        return delegator;
2030    }
2031
2032    public void explodeItem(ShoppingCart cart, LocalDispatcher dispatcher) throws CartItemModifyException {
2033        double baseQuantity = this.getQuantity();
2034        int thisIndex = cart.items().indexOf(this);
2035        List JavaDoc newItems = new ArrayList JavaDoc();
2036
2037        if (baseQuantity > 1) {
2038            for (int i = 1; i < baseQuantity; i++) {
2039                // clone the item
2040
ShoppingCartItem item = new ShoppingCartItem(this);
2041
2042                // set the new item's quantity
2043
item.setQuantity(1, dispatcher, cart, false);
2044
2045                // now copy/calc the adjustments
2046
Debug.logInfo("Clone's adj: " + item.getAdjustments(), module);
2047                if (item.getAdjustments() != null && item.getAdjustments().size() > 0) {
2048                    List JavaDoc adjustments = new LinkedList JavaDoc(item.getAdjustments());
2049                    Iterator JavaDoc adjIterator = adjustments.iterator();
2050
2051                    while (adjIterator.hasNext()) {
2052                        GenericValue adjustment = (GenericValue) adjIterator.next();
2053
2054                        if (adjustment != null) {
2055                            item.removeAdjustment(adjustment);
2056                            GenericValue newAdjustment = GenericValue.create(adjustment);
2057                            Double JavaDoc adjAmount = newAdjustment.getDouble("amount");
2058
2059                            // we use != becuase adjustments can be +/-
2060
if (adjAmount != null && adjAmount.doubleValue() != 0.00)
2061                                newAdjustment.set("amount", new Double JavaDoc(adjAmount.doubleValue() / baseQuantity));
2062                            Debug.logInfo("Cloned adj: " + newAdjustment, module);
2063                            item.addAdjustment(newAdjustment);
2064                        } else {
2065                            Debug.logInfo("Clone Adjustment is null", module);
2066                        }
2067                    }
2068                }
2069                newItems.add(item);
2070            }
2071
2072            // set this item's quantity
2073
this.setQuantity(1, dispatcher, cart, false);
2074
2075            Debug.logInfo("BaseQuantity: " + baseQuantity, module);
2076            Debug.logInfo("Item's Adj: " + this.getAdjustments(), module);
2077
2078            // re-calc this item's adjustments
2079
if (this.getAdjustments() != null && this.getAdjustments().size() > 0) {
2080                List JavaDoc adjustments = new LinkedList JavaDoc(this.getAdjustments());
2081                Iterator JavaDoc adjIterator = adjustments.iterator();
2082
2083                while (adjIterator.hasNext()) {
2084                    GenericValue adjustment = (GenericValue) adjIterator.next();
2085
2086                    if (adjustment != null) {
2087                        this.removeAdjustment(adjustment);
2088                        GenericValue newAdjustment = GenericValue.create(adjustment);
2089                        Double JavaDoc adjAmount = newAdjustment.getDouble("amount");
2090
2091                        // we use != becuase adjustments can be +/-
2092
if (adjAmount != null && adjAmount.doubleValue() != 0.00)
2093                            newAdjustment.set("amount", new Double JavaDoc(adjAmount.doubleValue() / baseQuantity));
2094                        Debug.logInfo("Updated adj: " + newAdjustment, module);
2095                        this.addAdjustment(newAdjustment);
2096                    }
2097                }
2098            }
2099
2100            // add the cloned item(s) to the cart
2101
Iterator JavaDoc newItemsItr = newItems.iterator();
2102
2103            while (newItemsItr.hasNext()) {
2104                cart.addItem(thisIndex, (ShoppingCartItem) newItemsItr.next());
2105            }
2106        }
2107    }
2108    public static String JavaDoc getPurchaseOrderItemDescription(GenericValue product, GenericValue supplierProduct, Locale JavaDoc locale){
2109          String JavaDoc itemDescription = "";
2110          String JavaDoc supplierProductId = supplierProduct.getString("supplierProductId");
2111          if (supplierProductId == null) {
2112               supplierProductId = "";
2113          } else {
2114               supplierProductId += " ";
2115          }
2116          String JavaDoc supplierProductName = supplierProduct.getString("supplierProductName");
2117          if (supplierProductName == null) {
2118            if (supplierProductName == null) {
2119                supplierProductName = ProductContentWrapper.getProductContentAsText(product, "PRODUCT_NAME", locale);
2120             }
2121           }
2122          itemDescription = supplierProductId + supplierProductName;
2123          return itemDescription;
2124    }
2125}
2126
Popular Tags