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