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