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