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