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(pos + 1, fields.length());
721    
722                            fieldsValues.add(fieldValue.trim());
723                    }
724    
725                    List<String> names = new ArrayList<String>();
726                    List<String[]> values = new ArrayList<String[]>();
727    
728                    for (int i = 0; i < itemFields.length; i++) {
729                            names.add(itemFields[i].getName());
730                            values.add(StringUtil.split(itemFields[i].getValues()));
731                    }
732    
733                    int numOfRows = 1;
734    
735                    for (String[] vArray : values) {
736                            numOfRows = numOfRows * vArray.length;
737                    }
738    
739                    int rowPos = 0;
740    
741                    for (int i = 0; i < numOfRows; i++) {
742                            boolean match = true;
743    
744                            for (int j = 0; j < names.size(); j++) {
745                                    int numOfRepeats = 1;
746    
747                                    for (int k = j + 1; k < values.size(); k++) {
748                                            String[] vArray = values.get(k);
749    
750                                            numOfRepeats = numOfRepeats * vArray.length;
751                                    }
752    
753                                    String[] vArray = values.get(j);
754    
755                                    int arrayPos;
756    
757                                    for (arrayPos = i / numOfRepeats;
758                                            arrayPos >= vArray.length;
759                                            arrayPos = arrayPos - vArray.length) {
760                                    }
761    
762                                    if (!fieldsValues.contains(vArray[arrayPos].trim())) {
763                                            match = false;
764    
765                                            break;
766                                    }
767                            }
768    
769                            if (match) {
770                                    rowPos = i;
771    
772                                    break;
773                            }
774                    }
775    
776                    return rowPos;
777            }
778    
779            public static String getItemFields(String itemId) {
780                    int pos = itemId.indexOf(CharPool.PIPE);
781    
782                    if (pos == -1) {
783                            return StringPool.BLANK;
784                    }
785                    else {
786                            return itemId.substring(pos + 1);
787                    }
788            }
789    
790            public static long getItemId(String itemId) {
791                    int pos = itemId.indexOf(CharPool.PIPE);
792    
793                    if (pos != -1) {
794                            itemId = itemId.substring(0, pos);
795                    }
796    
797                    return GetterUtil.getLong(itemId);
798            }
799    
800            public static OrderByComparator getItemOrderByComparator(
801                    String orderByCol, String orderByType) {
802    
803                    boolean orderByAsc = false;
804    
805                    if (orderByType.equals("asc")) {
806                            orderByAsc = true;
807                    }
808    
809                    OrderByComparator orderByComparator = null;
810    
811                    if (orderByCol.equals("min-qty")) {
812                            orderByComparator = new ItemMinQuantityComparator(orderByAsc);
813                    }
814                    else if (orderByCol.equals("name")) {
815                            orderByComparator = new ItemNameComparator(orderByAsc);
816                    }
817                    else if (orderByCol.equals("price")) {
818                            orderByComparator = new ItemPriceComparator(orderByAsc);
819                    }
820                    else if (orderByCol.equals("sku")) {
821                            orderByComparator = new ItemSKUComparator(orderByAsc);
822                    }
823                    else if (orderByCol.equals("order-date")) {
824                            orderByComparator = new OrderDateComparator(orderByAsc);
825                    }
826    
827                    return orderByComparator;
828            }
829    
830            public static int getMinQuantity(ShoppingItem item)
831                    throws PortalException, SystemException {
832    
833                    int minQuantity = item.getMinQuantity();
834    
835                    List<ShoppingItemPrice> itemPrices = item.getItemPrices();
836    
837                    for (ShoppingItemPrice itemPrice : itemPrices) {
838                            if (minQuantity > itemPrice.getMinQuantity()) {
839                                    minQuantity = itemPrice.getMinQuantity();
840                            }
841                    }
842    
843                    return minQuantity;
844            }
845    
846            public static String getPayPalNotifyURL(ThemeDisplay themeDisplay) {
847                    return themeDisplay.getPortalURL() + themeDisplay.getPathMain() +
848                            "/shopping/notify";
849            }
850    
851            public static String getPayPalRedirectURL(
852                    ShoppingPreferences preferences, ShoppingOrder order, double total,
853                    String returnURL, String notifyURL) {
854    
855                    String payPalEmailAddress = HttpUtil.encodeURL(
856                            preferences.getPayPalEmailAddress());
857    
858                    NumberFormat doubleFormat = NumberFormat.getNumberInstance(
859                            LocaleUtil.ENGLISH);
860    
861                    doubleFormat.setMaximumFractionDigits(2);
862                    doubleFormat.setMinimumFractionDigits(2);
863    
864                    String amount = doubleFormat.format(total);
865    
866                    returnURL = HttpUtil.encodeURL(returnURL);
867                    notifyURL = HttpUtil.encodeURL(notifyURL);
868    
869                    String firstName = HttpUtil.encodeURL(order.getBillingFirstName());
870                    String lastName = HttpUtil.encodeURL(order.getBillingLastName());
871                    String address1 = HttpUtil.encodeURL(order.getBillingStreet());
872                    String city = HttpUtil.encodeURL(order.getBillingCity());
873                    String state = HttpUtil.encodeURL(order.getBillingState());
874                    String zip = HttpUtil.encodeURL(order.getBillingZip());
875    
876                    String currencyCode = preferences.getCurrencyId();
877    
878                    StringBundler sb = new StringBundler(45);
879    
880                    sb.append("https://www.paypal.com/cgi-bin/webscr?");
881                    sb.append("cmd=_xclick&");
882                    sb.append("business=").append(payPalEmailAddress).append("&");
883                    sb.append("item_name=").append(order.getNumber()).append("&");
884                    sb.append("item_number=").append(order.getNumber()).append("&");
885                    sb.append("invoice=").append(order.getNumber()).append("&");
886                    sb.append("amount=").append(amount).append("&");
887                    sb.append("return=").append(returnURL).append("&");
888                    sb.append("notify_url=").append(notifyURL).append("&");
889                    sb.append("first_name=").append(firstName).append("&");
890                    sb.append("last_name=").append(lastName).append("&");
891                    sb.append("address1=").append(address1).append("&");
892                    sb.append("city=").append(city).append("&");
893                    sb.append("state=").append(state).append("&");
894                    sb.append("zip=").append(zip).append("&");
895                    sb.append("no_note=1&");
896                    sb.append("currency_code=").append(currencyCode).append("");
897    
898                    return sb.toString();
899            }
900    
901            public static String getPayPalReturnURL(
902                    PortletURL portletURL, ShoppingOrder order) {
903    
904                    portletURL.setParameter("struts_action", "/shopping/checkout");
905                    portletURL.setParameter(Constants.CMD, Constants.VIEW);
906                    portletURL.setParameter("orderId", String.valueOf(order.getOrderId()));
907    
908                    return portletURL.toString();
909            }
910    
911            public static String getPpPaymentStatus(
912                    ShoppingOrder order, PageContext pageContext) {
913    
914                    String ppPaymentStatus = order.getPpPaymentStatus();
915    
916                    if (ppPaymentStatus.equals(ShoppingOrderConstants.STATUS_CHECKOUT)) {
917                            ppPaymentStatus = "checkout";
918                    }
919                    else {
920                            ppPaymentStatus = StringUtil.toLowerCase(ppPaymentStatus);
921                    }
922    
923                    return LanguageUtil.get(pageContext, ppPaymentStatus);
924            }
925    
926            public static String getPpPaymentStatus(String ppPaymentStatus) {
927                    if ((ppPaymentStatus == null) || (ppPaymentStatus.length() < 2) ||
928                            ppPaymentStatus.equals("checkout")) {
929    
930                            return ShoppingOrderConstants.STATUS_CHECKOUT;
931                    }
932                    else {
933                            return Character.toUpperCase(ppPaymentStatus.charAt(0)) +
934                                    ppPaymentStatus.substring(1);
935                    }
936            }
937    
938            public static boolean isInStock(ShoppingItem item) {
939                    if (!item.isFields()) {
940                            if (item.getStockQuantity() > 0) {
941                                    return true;
942                            }
943                            else {
944                                    return false;
945                            }
946                    }
947                    else {
948                            String[] fieldsQuantities = item.getFieldsQuantitiesArray();
949    
950                            for (int i = 0; i < fieldsQuantities.length; i++) {
951                                    if (GetterUtil.getInteger(fieldsQuantities[i]) > 0) {
952                                            return true;
953                                    }
954                            }
955    
956                            return false;
957                    }
958            }
959    
960            public static boolean isInStock(
961                    ShoppingItem item, ShoppingItemField[] itemFields, String[] fieldsArray,
962                    Integer orderedQuantity) {
963    
964                    if (!item.isFields()) {
965                            int stockQuantity = item.getStockQuantity();
966    
967                            if ((stockQuantity > 0) &&
968                                    (stockQuantity >= orderedQuantity.intValue())) {
969    
970                                    return true;
971                            }
972                            else {
973                                    return false;
974                            }
975                    }
976                    else {
977                            String[] fieldsQuantities = item.getFieldsQuantitiesArray();
978    
979                            int stockQuantity = 0;
980    
981                            if (fieldsQuantities.length > 0) {
982                                    int rowPos = getFieldsQuantitiesPos(
983                                            item, itemFields, fieldsArray);
984    
985                                    stockQuantity = GetterUtil.getInteger(fieldsQuantities[rowPos]);
986                            }
987    
988                            try {
989                                    if ((stockQuantity > 0) &&
990                                            (stockQuantity >= orderedQuantity.intValue())) {
991    
992                                            return true;
993                                    }
994                            }
995                            catch (Exception e) {
996                            }
997    
998                            return false;
999                    }
1000            }
1001    
1002            public static boolean meetsMinOrder(
1003                            ShoppingPreferences preferences,
1004                            Map<ShoppingCartItem, Integer> items)
1005                    throws PortalException, SystemException {
1006    
1007                    if ((preferences.getMinOrder() > 0) &&
1008                            (calculateSubtotal(items) < preferences.getMinOrder())) {
1009    
1010                            return false;
1011                    }
1012                    else {
1013                            return true;
1014                    }
1015            }
1016    
1017            private static ShoppingItemPrice _getItemPrice(ShoppingItem item, int count)
1018                    throws PortalException, SystemException {
1019    
1020                    ShoppingItemPrice itemPrice = null;
1021    
1022                    List<ShoppingItemPrice> itemPrices = item.getItemPrices();
1023    
1024                    for (ShoppingItemPrice temp : itemPrices) {
1025                            int minQty = temp.getMinQuantity();
1026                            int maxQty = temp.getMaxQuantity();
1027    
1028                            if (temp.getStatus() !=
1029                                            ShoppingItemPriceConstants.STATUS_INACTIVE) {
1030    
1031                                    if ((count >= minQty) && ((count <= maxQty) || (maxQty == 0))) {
1032                                            return temp;
1033                                    }
1034    
1035                                    if ((count > maxQty) &&
1036                                            ((itemPrice == null) ||
1037                                             (itemPrice.getMaxQuantity() < maxQty))) {
1038    
1039                                            itemPrice = temp;
1040                                    }
1041                            }
1042                    }
1043    
1044                    if (itemPrice == null) {
1045                            return ShoppingItemPriceUtil.create(0);
1046                    }
1047    
1048                    return itemPrice;
1049            }
1050    
1051    }