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