1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.shopping.util;
24  
25  import com.liferay.portal.PortalException;
26  import com.liferay.portal.SystemException;
27  import com.liferay.portal.kernel.language.LanguageUtil;
28  import com.liferay.portal.kernel.portlet.LiferayWindowState;
29  import com.liferay.portal.kernel.util.Constants;
30  import com.liferay.portal.kernel.util.GetterUtil;
31  import com.liferay.portal.kernel.util.HttpUtil;
32  import com.liferay.portal.kernel.util.MathUtil;
33  import com.liferay.portal.kernel.util.OrderByComparator;
34  import com.liferay.portal.kernel.util.StringPool;
35  import com.liferay.portal.kernel.util.StringUtil;
36  import com.liferay.portal.theme.ThemeDisplay;
37  import com.liferay.portal.util.WebKeys;
38  import com.liferay.portlet.shopping.NoSuchCartException;
39  import com.liferay.portlet.shopping.model.ShoppingCart;
40  import com.liferay.portlet.shopping.model.ShoppingCartItem;
41  import com.liferay.portlet.shopping.model.ShoppingCategory;
42  import com.liferay.portlet.shopping.model.ShoppingCoupon;
43  import com.liferay.portlet.shopping.model.ShoppingItem;
44  import com.liferay.portlet.shopping.model.ShoppingItemField;
45  import com.liferay.portlet.shopping.model.ShoppingItemPrice;
46  import com.liferay.portlet.shopping.model.ShoppingOrder;
47  import com.liferay.portlet.shopping.model.ShoppingOrderItem;
48  import com.liferay.portlet.shopping.model.impl.ShoppingCartImpl;
49  import com.liferay.portlet.shopping.model.impl.ShoppingCouponImpl;
50  import com.liferay.portlet.shopping.model.impl.ShoppingItemPriceImpl;
51  import com.liferay.portlet.shopping.model.impl.ShoppingOrderImpl;
52  import com.liferay.portlet.shopping.service.ShoppingCartLocalServiceUtil;
53  import com.liferay.portlet.shopping.service.ShoppingCategoryLocalServiceUtil;
54  import com.liferay.portlet.shopping.service.ShoppingOrderItemLocalServiceUtil;
55  import com.liferay.portlet.shopping.service.persistence.ShoppingItemPriceUtil;
56  import com.liferay.portlet.shopping.util.comparator.ItemMinQuantityComparator;
57  import com.liferay.portlet.shopping.util.comparator.ItemNameComparator;
58  import com.liferay.portlet.shopping.util.comparator.ItemPriceComparator;
59  import com.liferay.portlet.shopping.util.comparator.ItemSKUComparator;
60  import com.liferay.portlet.shopping.util.comparator.OrderDateComparator;
61  
62  import java.text.NumberFormat;
63  
64  import java.util.ArrayList;
65  import java.util.HashMap;
66  import java.util.HashSet;
67  import java.util.Iterator;
68  import java.util.List;
69  import java.util.Locale;
70  import java.util.Map;
71  import java.util.Set;
72  
73  import javax.portlet.PortletRequest;
74  import javax.portlet.PortletSession;
75  import javax.portlet.PortletURL;
76  import javax.portlet.RenderRequest;
77  import javax.portlet.RenderResponse;
78  import javax.portlet.WindowState;
79  
80  import javax.servlet.jsp.PageContext;
81  
82  /**
83   * <a href="ShoppingUtil.java.html"><b><i>View Source</i></b></a>
84   *
85   * @author Brian Wing Shun Chan
86   *
87   */
88  public class ShoppingUtil {
89  
90      public static double calculateActualPrice(ShoppingItem item) {
91          return item.getPrice() - calculateDiscountPrice(item);
92      }
93  
94      public static double calculateActualPrice(ShoppingItem item, int count)
95          throws PortalException, SystemException {
96  
97          return calculatePrice(item, count) -
98              calculateDiscountPrice(item, count);
99      }
100 
101     public static double calculateActualPrice(ShoppingItemPrice itemPrice) {
102         return itemPrice.getPrice() - calculateDiscountPrice(itemPrice);
103     }
104 
105     public static double calculateActualSubtotal(
106             Map<ShoppingCartItem, Integer> items)
107         throws PortalException, SystemException {
108 
109         return calculateSubtotal(items) - calculateDiscountSubtotal(items);
110     }
111 
112     public static double calculateActualSubtotal(
113         List<ShoppingOrderItem> orderItems) {
114 
115         double subtotal = 0.0;
116 
117         for (ShoppingOrderItem orderItem : orderItems) {
118             subtotal += orderItem.getPrice() * orderItem.getQuantity();
119         }
120 
121         return subtotal;
122     }
123 
124     public static double calculateAlternativeShipping(
125             Map<ShoppingCartItem, Integer> items, int altShipping)
126         throws PortalException, SystemException {
127 
128         double shipping = calculateShipping(items);
129         double alternativeShipping = shipping;
130 
131         ShoppingPreferences preferences = null;
132 
133         Iterator<Map.Entry<ShoppingCartItem, Integer>> itr =
134             items.entrySet().iterator();
135 
136         while (itr.hasNext()) {
137             Map.Entry<ShoppingCartItem, Integer> entry = itr.next();
138 
139             ShoppingCartItem cartItem = entry.getKey();
140 
141             ShoppingItem item = cartItem.getItem();
142 
143             if (preferences == null) {
144                 ShoppingCategory category = item.getCategory();
145 
146                 preferences = ShoppingPreferences.getInstance(
147                     category.getCompanyId(), category.getGroupId());
148 
149                 break;
150             }
151         }
152 
153         // Calculate alternative shipping if shopping is configured to use
154         // alternative shipping and shipping price is greater than 0
155 
156         if ((preferences != null) &&
157             (preferences.useAlternativeShipping()) && (shipping > 0)) {
158 
159             double altShippingDelta = 0.0;
160 
161             try {
162                 altShippingDelta = GetterUtil.getDouble(
163                     preferences.getAlternativeShipping()[1][altShipping]);
164             }
165             catch (Exception e) {
166                 return alternativeShipping;
167             }
168 
169             if (altShippingDelta > 0) {
170                 alternativeShipping = shipping * altShippingDelta;
171             }
172         }
173 
174         return alternativeShipping;
175     }
176 
177     public static double calculateCouponDiscount(
178             Map<ShoppingCartItem, Integer> items, ShoppingCoupon coupon)
179         throws PortalException, SystemException {
180 
181         return calculateCouponDiscount(items, null, coupon);
182     }
183 
184     public static double calculateCouponDiscount(
185             Map<ShoppingCartItem, Integer> items, String stateId,
186             ShoppingCoupon coupon)
187         throws PortalException, SystemException {
188 
189         double discount = 0.0;
190 
191         if ((coupon == null) || !coupon.isActive() ||
192             !coupon.hasValidDateRange()) {
193 
194             return discount;
195         }
196 
197         String[] categoryIds = StringUtil.split(coupon.getLimitCategories());
198         String[] skus = StringUtil.split(coupon.getLimitSkus());
199 
200         if ((categoryIds.length > 0) || (skus.length > 0)) {
201             Set<String> categoryIdsSet = new HashSet<String>();
202 
203             for (String categoryId : categoryIds) {
204                 categoryIdsSet.add(categoryId);
205             }
206 
207             Set<String> skusSet = new HashSet<String>();
208 
209             for (String sku : skus) {
210                 skusSet.add(sku);
211             }
212 
213             Map<ShoppingCartItem, Integer> newItems =
214                 new HashMap<ShoppingCartItem, Integer>();
215 
216             Iterator<Map.Entry<ShoppingCartItem, Integer>> itr =
217                 items.entrySet().iterator();
218 
219             while (itr.hasNext()) {
220                 Map.Entry<ShoppingCartItem, Integer> entry = itr.next();
221 
222                 ShoppingCartItem cartItem = entry.getKey();
223                 Integer count = entry.getValue();
224 
225                 ShoppingItem item = cartItem.getItem();
226 
227                 if (((categoryIdsSet.size() > 0) &&
228                      (categoryIdsSet.contains(
229                         new Long(item.getCategoryId())))) ||
230                     ((skusSet.size() > 0) &&
231                      (skusSet.contains(item.getSku())))) {
232 
233                     newItems.put(cartItem, count);
234                 }
235             }
236 
237             items = newItems;
238         }
239 
240         double actualSubtotal = calculateActualSubtotal(items);
241 
242         if ((coupon.getMinOrder() > 0) &&
243             (coupon.getMinOrder() > actualSubtotal)) {
244 
245             return discount;
246         }
247 
248         String type = coupon.getDiscountType();
249 
250         if (type.equals(ShoppingCouponImpl.DISCOUNT_TYPE_PERCENTAGE)) {
251             discount = actualSubtotal * coupon.getDiscount();
252         }
253         else if (type.equals(ShoppingCouponImpl.DISCOUNT_TYPE_ACTUAL)) {
254             discount = coupon.getDiscount();
255         }
256         else if (type.equals(ShoppingCouponImpl.DISCOUNT_TYPE_FREE_SHIPPING)) {
257             discount = calculateShipping(items);
258         }
259         else if (type.equals(ShoppingCouponImpl.DISCOUNT_TYPE_TAX_FREE)) {
260             if (stateId != null) {
261                 discount = calculateTax(items, stateId);
262             }
263         }
264 
265         return discount;
266     }
267 
268     public static double calculateDiscountPercent(
269             Map<ShoppingCartItem, Integer> items)
270         throws PortalException, SystemException {
271 
272         double discount =
273             calculateDiscountSubtotal(items) / calculateSubtotal(items);
274 
275         if (Double.isNaN(discount) || Double.isInfinite(discount)) {
276             discount = 0.0;
277         }
278 
279         return discount;
280     }
281 
282     public static double calculateDiscountPrice(ShoppingItem item) {
283         return item.getPrice() * item.getDiscount();
284     }
285 
286     public static double calculateDiscountPrice(ShoppingItem item, int count)
287         throws PortalException, SystemException {
288 
289         ShoppingItemPrice itemPrice = _getItemPrice(item, count);
290 
291         return itemPrice.getPrice() * itemPrice.getDiscount() * count;
292     }
293 
294     public static double calculateDiscountPrice(ShoppingItemPrice itemPrice) {
295         return itemPrice.getPrice() * itemPrice.getDiscount();
296     }
297 
298     public static double calculateDiscountSubtotal(
299             Map<ShoppingCartItem, Integer> items)
300         throws PortalException, SystemException {
301 
302         double subtotal = 0.0;
303 
304         Iterator<Map.Entry<ShoppingCartItem, Integer>> itr =
305             items.entrySet().iterator();
306 
307         while (itr.hasNext()) {
308             Map.Entry<ShoppingCartItem, Integer> entry = itr.next();
309 
310             ShoppingCartItem cartItem = entry.getKey();
311             Integer count = entry.getValue();
312 
313             ShoppingItem item = cartItem.getItem();
314 
315             subtotal += calculateDiscountPrice(item, count.intValue());
316         }
317 
318         return subtotal;
319     }
320 
321     public static double calculateInsurance(
322             Map<ShoppingCartItem, Integer> items)
323         throws PortalException, SystemException {
324 
325         double insurance = 0.0;
326         double subtotal = 0.0;
327 
328         ShoppingPreferences preferences = null;
329 
330         Iterator<Map.Entry<ShoppingCartItem, Integer>> itr =
331             items.entrySet().iterator();
332 
333         while (itr.hasNext()) {
334             Map.Entry<ShoppingCartItem, Integer> entry = itr.next();
335 
336             ShoppingCartItem cartItem = entry.getKey();
337             Integer count = entry.getValue();
338 
339             ShoppingItem item = cartItem.getItem();
340 
341             if (preferences == null) {
342                 ShoppingCategory category = item.getCategory();
343 
344                 preferences = ShoppingPreferences.getInstance(
345                     category.getCompanyId(), category.getGroupId());
346             }
347 
348             ShoppingItemPrice itemPrice =
349                 _getItemPrice(item, count.intValue());
350 
351             subtotal += calculateActualPrice(itemPrice) * count.intValue();
352         }
353 
354         if ((preferences != null) && (subtotal > 0)) {
355             double insuranceRate = 0.0;
356 
357             double[] range = ShoppingPreferences.INSURANCE_RANGE;
358 
359             for (int i = 0; i < range.length - 1; i++) {
360                 if (subtotal > range[i] && subtotal <= range[i + 1]) {
361                     int rangeId = i / 2;
362                     if (MathUtil.isOdd(i)) {
363                         rangeId = (i + 1) / 2;
364                     }
365 
366                     insuranceRate = GetterUtil.getDouble(
367                         preferences.getInsurance()[rangeId]);
368                 }
369             }
370 
371             String formula = preferences.getInsuranceFormula();
372 
373             if (formula.equals("flat")) {
374                 insurance += insuranceRate;
375             }
376             else if (formula.equals("percentage")) {
377                 insurance += subtotal * insuranceRate;
378             }
379         }
380 
381         return insurance;
382     }
383 
384     public static double calculatePrice(ShoppingItem item, int count)
385         throws PortalException, SystemException {
386 
387         ShoppingItemPrice itemPrice = _getItemPrice(item, count);
388 
389         return itemPrice.getPrice() * count;
390     }
391 
392     public static double calculateShipping(Map<ShoppingCartItem, Integer> items)
393         throws PortalException, SystemException {
394 
395         double shipping = 0.0;
396         double subtotal = 0.0;
397 
398         ShoppingPreferences preferences = null;
399 
400         Iterator<Map.Entry<ShoppingCartItem, Integer>> itr =
401             items.entrySet().iterator();
402 
403         while (itr.hasNext()) {
404             Map.Entry<ShoppingCartItem, Integer> entry = itr.next();
405 
406             ShoppingCartItem cartItem = entry.getKey();
407             Integer count = entry.getValue();
408 
409             ShoppingItem item = cartItem.getItem();
410 
411             if (preferences == null) {
412                 ShoppingCategory category = item.getCategory();
413 
414                 preferences = ShoppingPreferences.getInstance(
415                     category.getCompanyId(), category.getGroupId());
416             }
417 
418             if (item.isRequiresShipping()) {
419                 ShoppingItemPrice itemPrice =
420                     _getItemPrice(item, count.intValue());
421 
422                 if (itemPrice.isUseShippingFormula()) {
423                     subtotal +=
424                         calculateActualPrice(itemPrice) * count.intValue();
425                 }
426                 else {
427                     shipping += itemPrice.getShipping() * count.intValue();
428                 }
429             }
430         }
431 
432         if ((preferences != null) && (subtotal > 0)) {
433             double shippingRate = 0.0;
434 
435             double[] range = ShoppingPreferences.SHIPPING_RANGE;
436 
437             for (int i = 0; i < range.length - 1; i++) {
438                 if (subtotal > range[i] && subtotal <= range[i + 1]) {
439                     int rangeId = i / 2;
440                     if (MathUtil.isOdd(i)) {
441                         rangeId = (i + 1) / 2;
442                     }
443 
444                     shippingRate = GetterUtil.getDouble(
445                         preferences.getShipping()[rangeId]);
446                 }
447             }
448 
449             String formula = preferences.getShippingFormula();
450 
451             if (formula.equals("flat")) {
452                 shipping += shippingRate;
453             }
454             else if (formula.equals("percentage")) {
455                 shipping += subtotal * shippingRate;
456             }
457         }
458 
459         return shipping;
460     }
461 
462     public static double calculateSubtotal(Map<ShoppingCartItem, Integer> items)
463         throws PortalException, SystemException {
464 
465         double subtotal = 0.0;
466 
467         Iterator<Map.Entry<ShoppingCartItem, Integer>> itr =
468             items.entrySet().iterator();
469 
470         while (itr.hasNext()) {
471             Map.Entry<ShoppingCartItem, Integer> entry = itr.next();
472 
473             ShoppingCartItem cartItem = entry.getKey();
474             Integer count = entry.getValue();
475 
476             ShoppingItem item = cartItem.getItem();
477 
478             subtotal += calculatePrice(item, count.intValue());
479         }
480 
481         return subtotal;
482     }
483 
484     public static double calculateTax(
485             Map<ShoppingCartItem, Integer> items, String stateId)
486         throws PortalException, SystemException {
487 
488         double tax = 0.0;
489 
490         ShoppingPreferences preferences = null;
491 
492         Iterator<Map.Entry<ShoppingCartItem, Integer>> itr =
493             items.entrySet().iterator();
494 
495         while (itr.hasNext()) {
496             Map.Entry<ShoppingCartItem, Integer> entry = itr.next();
497 
498             ShoppingCartItem cartItem = entry.getKey();
499 
500             ShoppingItem item = cartItem.getItem();
501 
502             if (preferences == null) {
503                 ShoppingCategory category = item.getCategory();
504 
505                 preferences = ShoppingPreferences.getInstance(
506                     category.getCompanyId(), category.getGroupId());
507 
508                 break;
509             }
510         }
511 
512         if ((preferences != null) &&
513             (preferences.getTaxState().equals(stateId))) {
514 
515             double subtotal = 0.0;
516 
517             itr = items.entrySet().iterator();
518 
519             while (itr.hasNext()) {
520                 Map.Entry<ShoppingCartItem, Integer> entry = itr.next();
521 
522                 ShoppingCartItem cartItem = entry.getKey();
523                 Integer count = entry.getValue();
524 
525                 ShoppingItem item = cartItem.getItem();
526 
527                 if (item.isTaxable()) {
528                     subtotal += calculatePrice(item, count.intValue());
529                 }
530             }
531 
532             tax = preferences.getTaxRate() * subtotal;
533         }
534 
535         return tax;
536     }
537 
538     public static double calculateTotal(
539             Map<ShoppingCartItem, Integer> items, String stateId,
540             ShoppingCoupon coupon, int altShipping, boolean insure)
541         throws PortalException, SystemException {
542 
543         double actualSubtotal = calculateActualSubtotal(items);
544         double tax = calculateTax(items, stateId);
545         double shipping = calculateAlternativeShipping(items, altShipping);
546 
547         double insurance = 0.0;
548         if (insure) {
549             insurance = calculateInsurance(items);
550         }
551 
552         double couponDiscount = calculateCouponDiscount(items, stateId, coupon);
553 
554         double total =
555             actualSubtotal + tax + shipping + insurance - couponDiscount;
556 
557         if (total < 0) {
558             total = 0.0;
559         }
560 
561         return total;
562     }
563 
564     public static double calculateTotal(ShoppingOrder order)
565         throws SystemException {
566 
567         List<ShoppingOrderItem> orderItems =
568             ShoppingOrderItemLocalServiceUtil.getOrderItems(order.getOrderId());
569 
570         double total =
571             calculateActualSubtotal(orderItems) + order.getTax() +
572                 order.getShipping() + order.getInsurance() -
573                     order.getCouponDiscount();
574 
575         if (total < 0) {
576             total = 0.0;
577         }
578 
579         return total;
580     }
581 
582     public static String getBreadcrumbs(
583             long categoryId, PageContext pageContext,
584             RenderRequest renderRequest, RenderResponse renderResponse)
585         throws Exception {
586 
587         ShoppingCategory category = null;
588 
589         try {
590             category = ShoppingCategoryLocalServiceUtil.getCategory(categoryId);
591         }
592         catch (Exception e) {
593         }
594 
595         return getBreadcrumbs(
596             category, pageContext, renderRequest, renderResponse);
597     }
598 
599     public static String getBreadcrumbs(
600             ShoppingCategory category, PageContext pageContext,
601             RenderRequest renderRequest, RenderResponse renderResponse)
602         throws Exception {
603 
604         PortletURL categoriesURL = renderResponse.createRenderURL();
605 
606         WindowState windowState = renderRequest.getWindowState();
607 
608         if (windowState.equals(LiferayWindowState.POP_UP)) {
609             categoriesURL.setWindowState(LiferayWindowState.POP_UP);
610 
611             categoriesURL.setParameter(
612                 "struts_action", "/shopping/select_category");
613         }
614         else {
615             //categoriesURL.setWindowState(WindowState.MAXIMIZED);
616 
617             categoriesURL.setParameter("struts_action", "/shopping/view");
618             categoriesURL.setParameter("tabs1", "categories");
619         }
620 
621         String categoriesLink =
622             "<a href=\"" + categoriesURL.toString() + "\">" +
623                 LanguageUtil.get(pageContext, "categories") + "</a>";
624 
625         if (category == null) {
626             return "<span class=\"first last\">" + categoriesLink + "</span>";
627         }
628 
629         String breadcrumbs = StringPool.BLANK;
630 
631         if (category != null) {
632             for (int i = 0;; i++) {
633                 category = category.toEscapedModel();
634 
635                 PortletURL portletURL = renderResponse.createRenderURL();
636 
637                 if (windowState.equals(LiferayWindowState.POP_UP)) {
638                     portletURL.setWindowState(LiferayWindowState.POP_UP);
639 
640                     portletURL.setParameter(
641                         "struts_action", "/shopping/select_category");
642                     portletURL.setParameter(
643                         "categoryId", String.valueOf(category.getCategoryId()));
644                 }
645                 else {
646                     //portletURL.setWindowState(WindowState.MAXIMIZED);
647 
648                     portletURL.setParameter("struts_action", "/shopping/view");
649                     portletURL.setParameter("tabs1", "categories");
650                     portletURL.setParameter(
651                         "categoryId", String.valueOf(category.getCategoryId()));
652                 }
653 
654                 String categoryLink =
655                     "<a href=\"" + portletURL.toString() + "\">" +
656                         category.getName() + "</a>";
657 
658                 if (i == 0) {
659                     breadcrumbs =
660                         "<span class=\"last\">" + categoryLink + "</span>";
661                 }
662                 else {
663                     breadcrumbs = categoryLink + " &raquo; " + breadcrumbs;
664                 }
665 
666                 if (category.isRoot()) {
667                     break;
668                 }
669 
670                 category = ShoppingCategoryLocalServiceUtil.getCategory(
671                     category.getParentCategoryId());
672             }
673         }
674 
675         breadcrumbs =
676             "<span class=\"first\">" + categoriesLink + " &raquo; </span>" +
677                 breadcrumbs;
678 
679         return breadcrumbs;
680     }
681 
682     public static ShoppingCart getCart(ThemeDisplay themeDisplay) {
683         ShoppingCart cart = new ShoppingCartImpl();
684 
685         cart.setGroupId(themeDisplay.getScopeGroupId());
686         cart.setCompanyId(themeDisplay.getCompanyId());
687         cart.setUserId(themeDisplay.getUserId());
688         cart.setItemIds(StringPool.BLANK);
689         cart.setCouponCodes(StringPool.BLANK);
690         cart.setAltShipping(0);
691         cart.setInsure(false);
692 
693         return cart;
694     }
695 
696     public static ShoppingCart getCart(PortletRequest portletRequest)
697         throws PortalException, SystemException {
698 
699         PortletSession portletSession = portletRequest.getPortletSession();
700 
701         ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
702             WebKeys.THEME_DISPLAY);
703 
704         String sessionCartId =
705             ShoppingCart.class.getName() + themeDisplay.getScopeGroupId();
706 
707         if (themeDisplay.isSignedIn()) {
708             ShoppingCart cart = (ShoppingCart)portletSession.getAttribute(
709                 sessionCartId);
710 
711             if (cart != null) {
712                 portletSession.removeAttribute(sessionCartId);
713             }
714 
715             if ((cart != null) && (cart.getItemsSize() > 0)) {
716                 cart = ShoppingCartLocalServiceUtil.updateCart(
717                     themeDisplay.getUserId(), themeDisplay.getScopeGroupId(),
718                     cart.getItemIds(), cart.getCouponCodes(),
719                     cart.getAltShipping(), cart.isInsure());
720             }
721             else {
722                 try {
723                     cart = ShoppingCartLocalServiceUtil.getCart(
724                         themeDisplay.getUserId(),
725                         themeDisplay.getScopeGroupId());
726                 }
727                 catch (NoSuchCartException nsce) {
728                     cart = getCart(themeDisplay);
729 
730                     cart = ShoppingCartLocalServiceUtil.updateCart(
731                         themeDisplay.getUserId(),
732                         themeDisplay.getScopeGroupId(), cart.getItemIds(),
733                         cart.getCouponCodes(), cart.getAltShipping(),
734                         cart.isInsure());
735                 }
736             }
737 
738             return cart;
739         }
740         else {
741             ShoppingCart cart = (ShoppingCart)portletSession.getAttribute(
742                 sessionCartId);
743 
744             if (cart == null) {
745                 cart = getCart(themeDisplay);
746 
747                 portletSession.setAttribute(sessionCartId, cart);
748             }
749 
750             return cart;
751         }
752     }
753 
754     public static int getFieldsQuantitiesPos(
755         ShoppingItem item, ShoppingItemField[] itemFields,
756         String[] fieldsArray) {
757 
758         Set<String> fieldsValues = new HashSet<String>();
759 
760         for (String fields : fieldsArray) {
761             int pos = fields.indexOf("=");
762 
763             String fieldValue = fields.substring(
764                 pos + 1, fields.length()).trim();
765 
766             fieldsValues.add(fieldValue);
767         }
768 
769         List<String> names = new ArrayList<String>();
770         List<String[]> values = new ArrayList<String[]>();
771 
772         for (int i = 0; i < itemFields.length; i++) {
773             names.add(itemFields[i].getName());
774             values.add(StringUtil.split(itemFields[i].getValues()));
775         }
776 
777         int numOfRows = 1;
778 
779         for (String[] vArray : values) {
780             numOfRows = numOfRows * vArray.length;
781         }
782 
783         int rowPos = 0;
784 
785         for (int i = 0; i < numOfRows; i++) {
786             boolean match = true;
787 
788             for (int j = 0; j < names.size(); j++) {
789                 int numOfRepeats = 1;
790 
791                 for (int k = j + 1; k < values.size(); k++) {
792                     String[] vArray = values.get(k);
793 
794                     numOfRepeats = numOfRepeats * vArray.length;
795                 }
796 
797                 String[] vArray = values.get(j);
798 
799                 int arrayPos;
800                 for (arrayPos = i / numOfRepeats;
801                      arrayPos >= vArray.length;
802                      arrayPos = arrayPos - vArray.length) {
803                 }
804 
805                 if (!fieldsValues.contains(vArray[arrayPos].trim())) {
806                     match = false;
807 
808                     break;
809                 }
810             }
811 
812             if (match) {
813                 rowPos = i;
814 
815                 break;
816             }
817         }
818 
819         return rowPos;
820     }
821 
822     public static long getItemId(String itemId) {
823         int pos = itemId.indexOf(StringPool.PIPE);
824 
825         if (pos != -1) {
826             itemId = itemId.substring(0, pos);
827         }
828 
829         return GetterUtil.getLong(itemId);
830     }
831 
832     public static String getItemFields(String itemId) {
833         int pos = itemId.indexOf(StringPool.PIPE);
834 
835         if (pos == -1) {
836             return StringPool.BLANK;
837         }
838         else {
839             return itemId.substring(pos + 1, itemId.length());
840         }
841     }
842 
843     public static OrderByComparator getItemOrderByComparator(
844         String orderByCol, String orderByType) {
845 
846         boolean orderByAsc = false;
847 
848         if (orderByType.equals("asc")) {
849             orderByAsc = true;
850         }
851 
852         OrderByComparator orderByComparator = null;
853 
854         if (orderByCol.equals("min-qty")) {
855             orderByComparator = new ItemMinQuantityComparator(orderByAsc);
856         }
857         else if (orderByCol.equals("name")) {
858             orderByComparator = new ItemNameComparator(orderByAsc);
859         }
860         else if (orderByCol.equals("price")) {
861             orderByComparator = new ItemPriceComparator(orderByAsc);
862         }
863         else if (orderByCol.equals("sku")) {
864             orderByComparator = new ItemSKUComparator(orderByAsc);
865         }
866         else if (orderByCol.equals("order-date")) {
867             orderByComparator = new OrderDateComparator(orderByAsc);
868         }
869 
870         return orderByComparator;
871     }
872 
873     public static int getMinQuantity(ShoppingItem item)
874         throws PortalException, SystemException {
875 
876         int minQuantity = item.getMinQuantity();
877 
878         List<ShoppingItemPrice> itemPrices = item.getItemPrices();
879 
880         for (ShoppingItemPrice itemPrice : itemPrices) {
881             if (minQuantity > itemPrice.getMinQuantity()) {
882                 minQuantity = itemPrice.getMinQuantity();
883             }
884         }
885 
886         return minQuantity;
887     }
888 
889     public static String getPayPalNotifyURL(ThemeDisplay themeDisplay) {
890         return themeDisplay.getURLPortal() + themeDisplay.getPathMain() +
891             "/shopping/notify";
892     }
893 
894     public static String getPayPalRedirectURL(
895         ShoppingPreferences preferences, ShoppingOrder order, double total,
896         String returnURL, String notifyURL) {
897 
898         String payPalEmailAddress = HttpUtil.encodeURL(
899             preferences.getPayPalEmailAddress());
900 
901         NumberFormat doubleFormat = NumberFormat.getNumberInstance(
902             Locale.ENGLISH);
903 
904         doubleFormat.setMaximumFractionDigits(2);
905         doubleFormat.setMinimumFractionDigits(2);
906 
907         String amount = doubleFormat.format(total);
908 
909         returnURL = HttpUtil.encodeURL(returnURL);
910         notifyURL = HttpUtil.encodeURL(notifyURL);
911 
912         String firstName = HttpUtil.encodeURL(order.getBillingFirstName());
913         String lastName = HttpUtil.encodeURL(order.getBillingLastName());
914         String address1 = HttpUtil.encodeURL(order.getBillingStreet());
915         String city = HttpUtil.encodeURL(order.getBillingCity());
916         String state = HttpUtil.encodeURL(order.getBillingState());
917         String zip = HttpUtil.encodeURL(order.getBillingZip());
918 
919         String currencyCode = preferences.getCurrencyId();
920 
921         StringBuilder sb = new StringBuilder();
922 
923         sb.append("https://www.paypal.com/cgi-bin/webscr?");
924         sb.append("cmd=_xclick&");
925         sb.append("business=").append(payPalEmailAddress).append("&");
926         sb.append("item_name=").append(order.getNumber()).append("&");
927         sb.append("item_number=").append(order.getNumber()).append("&");
928         sb.append("invoice=").append(order.getNumber()).append("&");
929         sb.append("amount=").append(amount).append("&");
930         sb.append("return=").append(returnURL).append("&");
931         sb.append("notify_url=").append(notifyURL).append("&");
932         sb.append("first_name=").append(firstName).append("&");
933         sb.append("last_name=").append(lastName).append("&");
934         sb.append("address1=").append(address1).append("&");
935         sb.append("city=").append(city).append("&");
936         sb.append("state=").append(state).append("&");
937         sb.append("zip=").append(zip).append("&");
938         sb.append("no_note=1&");
939         sb.append("currency_code=").append(currencyCode).append("");
940 
941         return sb.toString();
942     }
943 
944     public static String getPayPalReturnURL(
945         PortletURL portletURL, ShoppingOrder order) {
946 
947         portletURL.setParameter(
948             "struts_action", "/shopping/checkout");
949         portletURL.setParameter(Constants.CMD, Constants.VIEW);
950         portletURL.setParameter("orderId", String.valueOf(order.getOrderId()));
951 
952         return portletURL.toString();
953     }
954 
955     public static String getPpPaymentStatus(String ppPaymentStatus) {
956         if ((ppPaymentStatus == null) || (ppPaymentStatus.length() < 2) ||
957             (ppPaymentStatus.equals("checkout"))) {
958 
959             return ShoppingOrderImpl.STATUS_CHECKOUT;
960         }
961         else {
962             return Character.toUpperCase(ppPaymentStatus.charAt(0)) +
963                 ppPaymentStatus.substring(1, ppPaymentStatus.length());
964         }
965     }
966 
967     public static String getPpPaymentStatus(
968         ShoppingOrder order, PageContext pageContext) {
969 
970         String ppPaymentStatus = order.getPpPaymentStatus();
971 
972         if (ppPaymentStatus.equals(ShoppingOrderImpl.STATUS_CHECKOUT)) {
973             ppPaymentStatus = "checkout";
974         }
975         else {
976             ppPaymentStatus = ppPaymentStatus.toLowerCase();
977         }
978 
979         return LanguageUtil.get(pageContext, ppPaymentStatus);
980     }
981 
982     public static boolean isInStock(ShoppingItem item) {
983         if (!item.isFields()) {
984             if (item.getStockQuantity() > 0) {
985                 return true;
986             }
987             else {
988                 return false;
989             }
990         }
991         else {
992             String[] fieldsQuantities = item.getFieldsQuantitiesArray();
993 
994             for (int i = 0; i < fieldsQuantities.length; i++) {
995                 if (GetterUtil.getInteger(fieldsQuantities[i]) > 0) {
996                     return true;
997                 }
998             }
999 
1000            return false;
1001        }
1002    }
1003
1004    public static boolean isInStock(
1005        ShoppingItem item, ShoppingItemField[] itemFields,
1006        String[] fieldsArray, Integer orderedQuantity) {
1007
1008        if (!item.isFields()) {
1009            int stockQuantity = item.getStockQuantity();
1010
1011            if ((stockQuantity > 0)  &&
1012                (stockQuantity >= orderedQuantity.intValue())) {
1013
1014                return true;
1015            }
1016            else {
1017                return false;
1018            }
1019        }
1020        else {
1021            int rowPos = getFieldsQuantitiesPos(item, itemFields, fieldsArray);
1022
1023            String[] fieldsQuantities = item.getFieldsQuantitiesArray();
1024
1025            int stockQuantity = GetterUtil.getInteger(fieldsQuantities[rowPos]);
1026
1027            try {
1028                if ((stockQuantity > 0) &&
1029                    (stockQuantity >= orderedQuantity.intValue())) {
1030
1031                    return true;
1032                }
1033            }
1034            catch (Exception e) {
1035            }
1036
1037            return false;
1038        }
1039    }
1040
1041    public static boolean meetsMinOrder(
1042            ShoppingPreferences preferences,
1043            Map<ShoppingCartItem, Integer> items)
1044        throws PortalException, SystemException {
1045
1046        if ((preferences.getMinOrder() > 0) &&
1047            (calculateSubtotal(items) < preferences.getMinOrder())) {
1048
1049            return false;
1050        }
1051        else {
1052            return true;
1053        }
1054    }
1055
1056    private static ShoppingItemPrice _getItemPrice(ShoppingItem item, int count)
1057        throws PortalException, SystemException {
1058
1059        ShoppingItemPrice itemPrice = null;
1060
1061        List<ShoppingItemPrice> itemPrices = item.getItemPrices();
1062
1063        for (ShoppingItemPrice temp : itemPrices) {
1064            int minQty = temp.getMinQuantity();
1065            int maxQty = temp.getMaxQuantity();
1066
1067            if ((temp.getStatus() !=
1068                    ShoppingItemPriceImpl.STATUS_INACTIVE)) {
1069
1070                if ((count >= minQty) && ((count <= maxQty) || (maxQty == 0))) {
1071                    return temp;
1072                }
1073
1074                if ((count > maxQty) &&
1075                    ((itemPrice == null) ||
1076                     (itemPrice.getMaxQuantity() < maxQty))) {
1077
1078                    itemPrice = temp;
1079                }
1080            }
1081        }
1082
1083        if (itemPrice == null) {
1084            return ShoppingItemPriceUtil.create(0);
1085        }
1086
1087        return itemPrice;
1088    }
1089
1090}