001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.shopping.util;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.language.LanguageUtil;
020    import com.liferay.portal.kernel.portlet.LiferayWindowState;
021    import com.liferay.portal.kernel.util.Constants;
022    import com.liferay.portal.kernel.util.GetterUtil;
023    import com.liferay.portal.kernel.util.HttpUtil;
024    import com.liferay.portal.kernel.util.MathUtil;
025    import com.liferay.portal.kernel.util.OrderByComparator;
026    import com.liferay.portal.kernel.util.StringBundler;
027    import com.liferay.portal.kernel.util.StringPool;
028    import com.liferay.portal.kernel.util.StringUtil;
029    import com.liferay.portal.theme.ThemeDisplay;
030    import com.liferay.portal.util.WebKeys;
031    import com.liferay.portlet.shopping.NoSuchCartException;
032    import com.liferay.portlet.shopping.model.ShoppingCart;
033    import com.liferay.portlet.shopping.model.ShoppingCartItem;
034    import com.liferay.portlet.shopping.model.ShoppingCategory;
035    import com.liferay.portlet.shopping.model.ShoppingCoupon;
036    import com.liferay.portlet.shopping.model.ShoppingCouponConstants;
037    import com.liferay.portlet.shopping.model.ShoppingItem;
038    import com.liferay.portlet.shopping.model.ShoppingItemField;
039    import com.liferay.portlet.shopping.model.ShoppingItemPrice;
040    import com.liferay.portlet.shopping.model.ShoppingItemPriceConstants;
041    import com.liferay.portlet.shopping.model.ShoppingOrder;
042    import com.liferay.portlet.shopping.model.ShoppingOrderConstants;
043    import com.liferay.portlet.shopping.model.ShoppingOrderItem;
044    import com.liferay.portlet.shopping.model.impl.ShoppingCartImpl;
045    import com.liferay.portlet.shopping.service.ShoppingCartLocalServiceUtil;
046    import com.liferay.portlet.shopping.service.ShoppingCategoryLocalServiceUtil;
047    import com.liferay.portlet.shopping.service.ShoppingOrderItemLocalServiceUtil;
048    import com.liferay.portlet.shopping.service.persistence.ShoppingItemPriceUtil;
049    import com.liferay.portlet.shopping.util.comparator.ItemMinQuantityComparator;
050    import com.liferay.portlet.shopping.util.comparator.ItemNameComparator;
051    import com.liferay.portlet.shopping.util.comparator.ItemPriceComparator;
052    import com.liferay.portlet.shopping.util.comparator.ItemSKUComparator;
053    import com.liferay.portlet.shopping.util.comparator.OrderDateComparator;
054    
055    import java.text.NumberFormat;
056    
057    import java.util.ArrayList;
058    import java.util.HashMap;
059    import java.util.HashSet;
060    import java.util.Iterator;
061    import java.util.List;
062    import java.util.Locale;
063    import java.util.Map;
064    import java.util.Set;
065    
066    import javax.portlet.PortletRequest;
067    import javax.portlet.PortletSession;
068    import javax.portlet.PortletURL;
069    import javax.portlet.RenderRequest;
070    import javax.portlet.RenderResponse;
071    import javax.portlet.WindowState;
072    
073    import javax.servlet.jsp.PageContext;
074    
075    /**
076     * @author Brian Wing Shun Chan
077     */
078    public class ShoppingUtil {
079    
080            public static double calculateActualPrice(ShoppingItem item) {
081                    return item.getPrice() - calculateDiscountPrice(item);
082            }
083    
084            public static double calculateActualPrice(ShoppingItem item, int count)
085                    throws PortalException, SystemException {
086    
087                    return calculatePrice(item, count) -
088                            calculateDiscountPrice(item, count);
089            }
090    
091            public static double calculateActualPrice(ShoppingItemPrice itemPrice) {
092                    return itemPrice.getPrice() - calculateDiscountPrice(itemPrice);
093            }
094    
095            public static double calculateActualSubtotal(
096                            Map<ShoppingCartItem, Integer> items)
097                    throws PortalException, SystemException {
098    
099                    return calculateSubtotal(items) - calculateDiscountSubtotal(items);
100            }
101    
102            public static double calculateActualSubtotal(
103                    List<ShoppingOrderItem> orderItems) {
104    
105                    double subtotal = 0.0;
106    
107                    for (ShoppingOrderItem orderItem : orderItems) {
108                            subtotal += orderItem.getPrice() * orderItem.getQuantity();
109                    }
110    
111                    return subtotal;
112            }
113    
114            public static double calculateAlternativeShipping(
115                            Map<ShoppingCartItem, Integer> items, int altShipping)
116                    throws PortalException, SystemException {
117    
118                    double shipping = calculateShipping(items);
119                    double alternativeShipping = shipping;
120    
121                    ShoppingPreferences preferences = null;
122    
123                    Iterator<Map.Entry<ShoppingCartItem, Integer>> itr =
124                            items.entrySet().iterator();
125    
126                    while (itr.hasNext()) {
127                            Map.Entry<ShoppingCartItem, Integer> entry = itr.next();
128    
129                            ShoppingCartItem cartItem = entry.getKey();
130    
131                            ShoppingItem item = cartItem.getItem();
132    
133                            if (preferences == null) {
134                                    ShoppingCategory category = item.getCategory();
135    
136                                    preferences = ShoppingPreferences.getInstance(
137                                            category.getCompanyId(), category.getGroupId());
138    
139                                    break;
140                            }
141                    }
142    
143                    // Calculate alternative shipping if shopping is configured to use
144                    // alternative shipping and shipping price is greater than 0
145    
146                    if ((preferences != null) &&
147                            (preferences.useAlternativeShipping()) && (shipping > 0)) {
148    
149                            double altShippingDelta = 0.0;
150    
151                            try {
152                                    altShippingDelta = GetterUtil.getDouble(
153                                            preferences.getAlternativeShipping()[1][altShipping]);
154                            }
155                            catch (Exception e) {
156                                    return alternativeShipping;
157                            }
158    
159                            if (altShippingDelta > 0) {
160                                    alternativeShipping = shipping * altShippingDelta;
161                            }
162                    }
163    
164                    return alternativeShipping;
165            }
166    
167            public static double calculateCouponDiscount(
168                            Map<ShoppingCartItem, Integer> items, ShoppingCoupon coupon)
169                    throws PortalException, SystemException {
170    
171                    return calculateCouponDiscount(items, null, coupon);
172            }
173    
174            public static double calculateCouponDiscount(
175                            Map<ShoppingCartItem, Integer> items, String stateId,
176                            ShoppingCoupon coupon)
177                    throws PortalException, SystemException {
178    
179                    double discount = 0.0;
180    
181                    if ((coupon == null) || !coupon.isActive() ||
182                            !coupon.hasValidDateRange()) {
183    
184                            return discount;
185                    }
186    
187                    String[] categoryIds = StringUtil.split(coupon.getLimitCategories());
188                    String[] skus = StringUtil.split(coupon.getLimitSkus());
189    
190                    if ((categoryIds.length > 0) || (skus.length > 0)) {
191                            Set<String> categoryIdsSet = new HashSet<String>();
192    
193                            for (String categoryId : categoryIds) {
194                                    categoryIdsSet.add(categoryId);
195                            }
196    
197                            Set<String> skusSet = new HashSet<String>();
198    
199                            for (String sku : skus) {
200                                    skusSet.add(sku);
201                            }
202    
203                            Map<ShoppingCartItem, Integer> newItems =
204                                    new HashMap<ShoppingCartItem, Integer>();
205    
206                            Iterator<Map.Entry<ShoppingCartItem, Integer>> itr =
207                                    items.entrySet().iterator();
208    
209                            while (itr.hasNext()) {
210                                    Map.Entry<ShoppingCartItem, Integer> entry = itr.next();
211    
212                                    ShoppingCartItem cartItem = entry.getKey();
213                                    Integer count = entry.getValue();
214    
215                                    ShoppingItem item = cartItem.getItem();
216    
217                                    if (((categoryIdsSet.size() > 0) &&
218                                             (categoryIdsSet.contains(
219                                                    String.valueOf(item.getCategoryId())))) ||
220                                            ((skusSet.size() > 0) &&
221                                             (skusSet.contains(item.getSku())))) {
222    
223                                            newItems.put(cartItem, count);
224                                    }
225                            }
226    
227                            items = newItems;
228                    }
229    
230                    double actualSubtotal = calculateActualSubtotal(items);
231    
232                    if ((coupon.getMinOrder() > 0) &&
233                            (coupon.getMinOrder() > actualSubtotal)) {
234    
235                            return discount;
236                    }
237    
238                    String type = coupon.getDiscountType();
239    
240                    if (type.equals(ShoppingCouponConstants.DISCOUNT_TYPE_PERCENTAGE)) {
241                            discount = actualSubtotal * coupon.getDiscount();
242                    }
243                    else if (type.equals(ShoppingCouponConstants.DISCOUNT_TYPE_ACTUAL)) {
244                            discount = coupon.getDiscount();
245                    }
246                    else if (type.equals(
247                                            ShoppingCouponConstants.DISCOUNT_TYPE_FREE_SHIPPING)) {
248    
249                            discount = calculateShipping(items);
250                    }
251                    else if (type.equals(ShoppingCouponConstants.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 preferences = 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 (preferences == null) {
334                                    ShoppingCategory category = item.getCategory();
335    
336                                    preferences = 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 ((preferences != 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                                                    preferences.getInsurance()[rangeId]);
360                                    }
361                            }
362    
363                            String formula = preferences.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 preferences = 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 (preferences == null) {
404                                    ShoppingCategory category = item.getCategory();
405    
406                                    preferences = 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 ((preferences != 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                                                    preferences.getShipping()[rangeId]);
438                                    }
439                            }
440    
441                            String formula = preferences.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 preferences = 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 (preferences == null) {
495                                    ShoppingCategory category = item.getCategory();
496    
497                                    preferences = ShoppingPreferences.getInstance(
498                                            category.getCompanyId(), category.getGroupId());
499    
500                                    break;
501                            }
502                    }
503    
504                    if ((preferences != null) &&
505                            (preferences.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 = preferences.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 preferences, ShoppingOrder order, double total,
888                    String returnURL, String notifyURL) {
889    
890                    String payPalEmailAddress = HttpUtil.encodeURL(
891                            preferences.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 = preferences.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 ShoppingOrderConstants.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(ShoppingOrderConstants.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 preferences,
1035                            Map<ShoppingCartItem, Integer> items)
1036                    throws PortalException, SystemException {
1037    
1038                    if ((preferences.getMinOrder() > 0) &&
1039                            (calculateSubtotal(items) < preferences.getMinOrder())) {
1040    
1041                            return false;
1042                    }
1043                    else {
1044                            return true;
1045                    }
1046            }
1047    
1048            private static ShoppingItemPrice _getItemPrice(ShoppingItem item, int count)
1049                    throws PortalException, SystemException {
1050    
1051                    ShoppingItemPrice itemPrice = null;
1052    
1053                    List<ShoppingItemPrice> itemPrices = item.getItemPrices();
1054    
1055                    for (ShoppingItemPrice temp : itemPrices) {
1056                            int minQty = temp.getMinQuantity();
1057                            int maxQty = temp.getMaxQuantity();
1058    
1059                            if ((temp.getStatus() !=
1060                                            ShoppingItemPriceConstants.STATUS_INACTIVE)) {
1061    
1062                                    if ((count >= minQty) && ((count <= maxQty) || (maxQty == 0))) {
1063                                            return temp;
1064                                    }
1065    
1066                                    if ((count > maxQty) &&
1067                                            ((itemPrice == null) ||
1068                                             (itemPrice.getMaxQuantity() < maxQty))) {
1069    
1070                                            itemPrice = temp;
1071                                    }
1072                            }
1073                    }
1074    
1075                    if (itemPrice == null) {
1076                            return ShoppingItemPriceUtil.create(0);
1077                    }
1078    
1079                    return itemPrice;
1080            }
1081    
1082    }