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