1   /**
2    * Copyright (c) 2000-2008 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.OrderByComparator;
33  import com.liferay.portal.kernel.util.StringMaker;
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  import com.liferay.util.MathUtil;
62  
63  import java.text.NumberFormat;
64  
65  import java.util.ArrayList;
66  import java.util.HashMap;
67  import java.util.HashSet;
68  import java.util.Iterator;
69  import java.util.List;
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 prefs = 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 (prefs == null) {
144                 ShoppingCategory category = item.getCategory();
145 
146                 prefs = 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 ((prefs != null) &&
157             (prefs.useAlternativeShipping()) && (shipping > 0)) {
158 
159             double altShippingDelta = 0.0;
160 
161             try {
162                 altShippingDelta = GetterUtil.getDouble(
163                     prefs.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 prefs = 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 (prefs == null) {
342                 ShoppingCategory category = item.getCategory();
343 
344                 prefs = 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 ((prefs != 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                         prefs.getInsurance()[rangeId]);
368                 }
369             }
370 
371             String formula = prefs.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 prefs = 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 (prefs == null) {
412                 ShoppingCategory category = item.getCategory();
413 
414                 prefs = 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 ((prefs != 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                         prefs.getShipping()[rangeId]);
446                 }
447             }
448 
449             String formula = prefs.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 prefs = 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 (prefs == null) {
503                 ShoppingCategory category = item.getCategory();
504 
505                 prefs = ShoppingPreferences.getInstance(
506                     category.getCompanyId(), category.getGroupId());
507 
508                 break;
509             }
510         }
511 
512         if ((prefs != null) &&
513             (prefs.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 = prefs.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 PortalException, 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, RenderRequest req,
584             RenderResponse res)
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(category, pageContext, req, res);
596     }
597 
598     public static String getBreadcrumbs(
599             ShoppingCategory category, PageContext pageContext,
600             RenderRequest req, RenderResponse res)
601         throws Exception {
602 
603         PortletURL categoriesURL = res.createRenderURL();
604 
605         WindowState windowState = req.getWindowState();
606 
607         if (windowState.equals(LiferayWindowState.POP_UP)) {
608             categoriesURL.setWindowState(LiferayWindowState.POP_UP);
609 
610             categoriesURL.setParameter(
611                 "struts_action", "/shopping/select_category");
612         }
613         else {
614             categoriesURL.setWindowState(WindowState.MAXIMIZED);
615 
616             categoriesURL.setParameter("struts_action", "/shopping/view");
617             categoriesURL.setParameter("tabs1", "categories");
618         }
619 
620         String categoriesLink =
621             "<a href=\"" + categoriesURL.toString() + "\">" +
622                 LanguageUtil.get(pageContext, "categories") + "</a>";
623 
624         if (category == null) {
625             return categoriesLink;
626         }
627 
628         String breadcrumbs = StringPool.BLANK;
629 
630         if (category != null) {
631             for (int i = 0;; i++) {
632                 category = category.toEscapedModel();
633 
634                 PortletURL portletURL = res.createRenderURL();
635 
636                 if (windowState.equals(LiferayWindowState.POP_UP)) {
637                     portletURL.setWindowState(LiferayWindowState.POP_UP);
638 
639                     portletURL.setParameter(
640                         "struts_action", "/shopping/select_category");
641                     portletURL.setParameter(
642                         "categoryId", String.valueOf(category.getCategoryId()));
643                 }
644                 else {
645                     portletURL.setWindowState(WindowState.MAXIMIZED);
646 
647                     portletURL.setParameter("struts_action", "/shopping/view");
648                     portletURL.setParameter("tabs1", "categories");
649                     portletURL.setParameter(
650                         "categoryId", String.valueOf(category.getCategoryId()));
651                 }
652 
653                 String categoryLink =
654                     "<a href=\"" + portletURL.toString() + "\">" +
655                         category.getName() + "</a>";
656 
657                 if (i == 0) {
658                     breadcrumbs = categoryLink;
659                 }
660                 else {
661                     breadcrumbs = categoryLink + " &raquo; " + breadcrumbs;
662                 }
663 
664                 if (category.isRoot()) {
665                     break;
666                 }
667 
668                 category = ShoppingCategoryLocalServiceUtil.getCategory(
669                     category.getParentCategoryId());
670             }
671         }
672 
673         breadcrumbs = categoriesLink + " &raquo; " + breadcrumbs;
674 
675         return breadcrumbs;
676     }
677 
678     public static ShoppingCart getCart(ThemeDisplay themeDisplay) {
679         ShoppingCart cart = new ShoppingCartImpl();
680 
681         cart.setGroupId(themeDisplay.getPortletGroupId());
682         cart.setCompanyId(themeDisplay.getCompanyId());
683         cart.setUserId(themeDisplay.getUserId());
684         cart.setItemIds(StringPool.BLANK);
685         cart.setCouponCodes(StringPool.BLANK);
686         cart.setAltShipping(0);
687         cart.setInsure(false);
688 
689         return cart;
690     }
691 
692     public static ShoppingCart getCart(PortletRequest req)
693         throws PortalException, SystemException {
694 
695         PortletSession ses = req.getPortletSession();
696 
697         ThemeDisplay themeDisplay =
698             (ThemeDisplay)req.getAttribute(WebKeys.THEME_DISPLAY);
699 
700         String sesCartId =
701             ShoppingCart.class.getName() + themeDisplay.getPortletGroupId();
702 
703         if (themeDisplay.isSignedIn()) {
704             ShoppingCart cart = (ShoppingCart)ses.getAttribute(sesCartId);
705 
706             if (cart != null) {
707                 ses.removeAttribute(sesCartId);
708             }
709 
710             if ((cart != null) && (cart.getItemsSize() > 0)) {
711                 cart = ShoppingCartLocalServiceUtil.updateCart(
712                     themeDisplay.getUserId(), themeDisplay.getPortletGroupId(),
713                     cart.getItemIds(), cart.getCouponCodes(),
714                     cart.getAltShipping(), cart.isInsure());
715             }
716             else {
717                 try {
718                     cart = ShoppingCartLocalServiceUtil.getCart(
719                         themeDisplay.getUserId(),
720                         themeDisplay.getPortletGroupId());
721                 }
722                 catch (NoSuchCartException nsce) {
723                     cart = getCart(themeDisplay);
724 
725                     cart = ShoppingCartLocalServiceUtil.updateCart(
726                         themeDisplay.getUserId(),
727                         themeDisplay.getPortletGroupId(), cart.getItemIds(),
728                         cart.getCouponCodes(), cart.getAltShipping(),
729                         cart.isInsure());
730                 }
731             }
732 
733             return cart;
734         }
735         else {
736             ShoppingCart cart = (ShoppingCart)ses.getAttribute(sesCartId);
737 
738             if (cart == null) {
739                 cart = getCart(themeDisplay);
740 
741                 ses.setAttribute(sesCartId, cart);
742             }
743 
744             return cart;
745         }
746     }
747 
748     public static int getFieldsQuantitiesPos(
749         ShoppingItem item, ShoppingItemField[] itemFields,
750         String[] fieldsArray) {
751 
752         Set<String> fieldsValues = new HashSet<String>();
753 
754         for (String fields : fieldsArray) {
755             int pos = fields.indexOf("=");
756 
757             String fieldValue = fields.substring(
758                 pos + 1, fields.length()).trim();
759 
760             fieldsValues.add(fieldValue);
761         }
762 
763         List<String> names = new ArrayList<String>();
764         List<String[]> values = new ArrayList<String[]>();
765 
766         for (int i = 0; i < itemFields.length; i++) {
767             names.add(itemFields[i].getName());
768             values.add(StringUtil.split(itemFields[i].getValues()));
769         }
770 
771         int numOfRows = 1;
772 
773         for (String[] vArray : values) {
774             numOfRows = numOfRows * vArray.length;
775         }
776 
777         int rowPos = 0;
778 
779         for (int i = 0; i < numOfRows; i++) {
780             boolean match = true;
781 
782             for (int j = 0; j < names.size(); j++) {
783                 int numOfRepeats = 1;
784 
785                 for (int k = j + 1; k < values.size(); k++) {
786                     String[] vArray = values.get(k);
787 
788                     numOfRepeats = numOfRepeats * vArray.length;
789                 }
790 
791                 String[] vArray = values.get(j);
792 
793                 int arrayPos;
794                 for (arrayPos = i / numOfRepeats;
795                      arrayPos >= vArray.length;
796                      arrayPos = arrayPos - vArray.length) {
797                 }
798 
799                 if (!fieldsValues.contains(vArray[arrayPos].trim())) {
800                     match = false;
801 
802                     break;
803                 }
804             }
805 
806             if (match) {
807                 rowPos = i;
808 
809                 break;
810             }
811         }
812 
813         return rowPos;
814     }
815 
816     public static long getItemId(String itemId) {
817         int pos = itemId.indexOf(StringPool.PIPE);
818 
819         if (pos != -1) {
820             itemId = itemId.substring(0, pos);
821         }
822 
823         return GetterUtil.getLong(itemId);
824     }
825 
826     public static String getItemFields(String itemId) {
827         int pos = itemId.indexOf(StringPool.PIPE);
828 
829         if (pos == -1) {
830             return StringPool.BLANK;
831         }
832         else {
833             return itemId.substring(pos + 1, itemId.length());
834         }
835     }
836 
837     public static OrderByComparator getItemOrderByComparator(
838         String orderByCol, String orderByType) {
839 
840         boolean orderByAsc = false;
841 
842         if (orderByType.equals("asc")) {
843             orderByAsc = true;
844         }
845 
846         OrderByComparator orderByComparator = null;
847 
848         if (orderByCol.equals("min-qty")) {
849             orderByComparator = new ItemMinQuantityComparator(orderByAsc);
850         }
851         else if (orderByCol.equals("name")) {
852             orderByComparator = new ItemNameComparator(orderByAsc);
853         }
854         else if (orderByCol.equals("price")) {
855             orderByComparator = new ItemPriceComparator(orderByAsc);
856         }
857         else if (orderByCol.equals("sku")) {
858             orderByComparator = new ItemSKUComparator(orderByAsc);
859         }
860         else if (orderByCol.equals("order-date")) {
861             orderByComparator = new OrderDateComparator(orderByAsc);
862         }
863 
864         return orderByComparator;
865     }
866 
867     public static int getMinQuantity(ShoppingItem item)
868         throws PortalException, SystemException {
869 
870         int minQuantity = item.getMinQuantity();
871 
872         List<ShoppingItemPrice> itemPrices = item.getItemPrices();
873 
874         for (ShoppingItemPrice itemPrice : itemPrices) {
875             if (minQuantity > itemPrice.getMinQuantity()) {
876                 minQuantity = itemPrice.getMinQuantity();
877             }
878         }
879 
880         return minQuantity;
881     }
882 
883     public static String getPayPalNotifyURL(ThemeDisplay themeDisplay) {
884         return themeDisplay.getURLPortal() + themeDisplay.getPathMain() +
885             "/shopping/notify";
886     }
887 
888     public static String getPayPalRedirectURL(
889             ShoppingPreferences prefs, ShoppingOrder order, double total,
890             String returnURL, String notifyURL)
891         throws PortalException, SystemException {
892 
893         String payPalEmailAddress = HttpUtil.encodeURL(
894             prefs.getPayPalEmailAddress());
895 
896         NumberFormat doubleFormat = NumberFormat.getNumberInstance();
897 
898         doubleFormat.setMaximumFractionDigits(2);
899         doubleFormat.setMinimumFractionDigits(2);
900 
901         String amount = doubleFormat.format(total);
902 
903         returnURL = HttpUtil.encodeURL(returnURL);
904         notifyURL = HttpUtil.encodeURL(notifyURL);
905 
906         String firstName = HttpUtil.encodeURL(order.getBillingFirstName());
907         String lastName = HttpUtil.encodeURL(order.getBillingLastName());
908         String address1 = HttpUtil.encodeURL(order.getBillingStreet());
909         String city = HttpUtil.encodeURL(order.getBillingCity());
910         String state = HttpUtil.encodeURL(order.getBillingState());
911         String zip = HttpUtil.encodeURL(order.getBillingZip());
912 
913         String currencyCode = prefs.getCurrencyId();
914 
915         StringMaker sm = new StringMaker();
916 
917         sm.append("https://www.paypal.com/cgi-bin/webscr?");
918         sm.append("cmd=_xclick&");
919         sm.append("business=").append(payPalEmailAddress).append("&");
920         sm.append("item_name=").append(order.getOrderId()).append("&");
921         sm.append("item_number=").append(order.getOrderId()).append("&");
922         sm.append("invoice=").append(order.getOrderId()).append("&");
923         sm.append("amount=").append(amount).append("&");
924         sm.append("return=").append(returnURL).append("&");
925         sm.append("notify_url=").append(notifyURL).append("&");
926         sm.append("first_name=").append(firstName).append("&");
927         sm.append("last_name=").append(lastName).append("&");
928         sm.append("address1=").append(address1).append("&");
929         sm.append("city=").append(city).append("&");
930         sm.append("state=").append(state).append("&");
931         sm.append("zip=").append(zip).append("&");
932         sm.append("no_note=1&");
933         sm.append("currency_code=").append(currencyCode).append("");
934 
935         return sm.toString();
936     }
937 
938     public static String getPayPalReturnURL(
939         PortletURL portletURL, ShoppingOrder order) {
940 
941         portletURL.setParameter(
942             "struts_action", "/shopping/checkout");
943         portletURL.setParameter(Constants.CMD, Constants.VIEW);
944         portletURL.setParameter("orderId", String.valueOf(order.getOrderId()));
945 
946         return portletURL.toString();
947     }
948 
949     public static String getPpPaymentStatus(String ppPaymentStatus) {
950         if ((ppPaymentStatus == null) || (ppPaymentStatus.length() < 2) ||
951             (ppPaymentStatus.equals("checkout"))) {
952 
953             return ShoppingOrderImpl.STATUS_CHECKOUT;
954         }
955         else {
956             return Character.toUpperCase(ppPaymentStatus.charAt(0)) +
957                 ppPaymentStatus.substring(1, ppPaymentStatus.length());
958         }
959     }
960 
961     public static String getPpPaymentStatus(
962             ShoppingOrder order, PageContext pageContext)
963         throws PortalException {
964 
965         String ppPaymentStatus = order.getPpPaymentStatus();
966 
967         if (ppPaymentStatus.equals(ShoppingOrderImpl.STATUS_CHECKOUT)) {
968             ppPaymentStatus = "checkout";
969         }
970         else {
971             ppPaymentStatus = ppPaymentStatus.toLowerCase();
972         }
973 
974         return LanguageUtil.get(pageContext, ppPaymentStatus);
975     }
976 
977     public static boolean isInStock(ShoppingItem item) {
978         if (!item.isFields()) {
979             if (item.getStockQuantity() > 0) {
980                 return true;
981             }
982             else {
983                 return false;
984             }
985         }
986         else {
987             String[] fieldsQuantities = item.getFieldsQuantitiesArray();
988 
989             for (int i = 0; i < fieldsQuantities.length; i++) {
990                 if (GetterUtil.getInteger(fieldsQuantities[i]) > 0) {
991                     return true;
992                 }
993             }
994 
995             return false;
996         }
997     }
998 
999     public static boolean isInStock(
1000        ShoppingItem item, ShoppingItemField[] itemFields,
1001        String[] fieldsArray, Integer orderedQuantity) {
1002
1003        if (!item.isFields()) {
1004            int stockQuantity = item.getStockQuantity();
1005
1006            if ((stockQuantity > 0)  &&
1007                (stockQuantity >= orderedQuantity.intValue())) {
1008
1009                return true;
1010            }
1011            else {
1012                return false;
1013            }
1014        }
1015        else {
1016            int rowPos = getFieldsQuantitiesPos(item, itemFields, fieldsArray);
1017
1018            String[] fieldsQuantities = item.getFieldsQuantitiesArray();
1019
1020            int stockQuantity = GetterUtil.getInteger(fieldsQuantities[rowPos]);
1021
1022            try {
1023                if ((stockQuantity > 0) &&
1024                    (stockQuantity >= orderedQuantity.intValue())) {
1025
1026                    return true;
1027                }
1028            }
1029            catch (Exception e) {
1030            }
1031
1032            return false;
1033        }
1034    }
1035
1036    public static boolean meetsMinOrder(
1037            ShoppingPreferences prefs, Map<ShoppingCartItem, Integer> items)
1038        throws PortalException, SystemException {
1039
1040        if ((prefs.getMinOrder() > 0) &&
1041            (calculateSubtotal(items) < prefs.getMinOrder())) {
1042
1043            return false;
1044        }
1045        else {
1046            return true;
1047        }
1048    }
1049
1050    private static ShoppingItemPrice _getItemPrice(ShoppingItem item, int count)
1051        throws PortalException, SystemException {
1052
1053        ShoppingItemPrice itemPrice = null;
1054
1055        List<ShoppingItemPrice> itemPrices = item.getItemPrices();
1056
1057        for (ShoppingItemPrice temp : itemPrices) {
1058            int minQty = temp.getMinQuantity();
1059            int maxQty = temp.getMaxQuantity();
1060
1061            if ((temp.getStatus() !=
1062                    ShoppingItemPriceImpl.STATUS_INACTIVE) &&
1063                (count >= minQty) && (count < maxQty || maxQty == 0))  {
1064
1065                itemPrice = temp;
1066            }
1067        }
1068
1069        if (itemPrice == null) {
1070            return ShoppingItemPriceUtil.create(0);
1071        }
1072
1073        return itemPrice;
1074    }
1075
1076}