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.MathUtil;
026    import com.liferay.portal.kernel.util.OrderByComparator;
027    import com.liferay.portal.kernel.util.StringBundler;
028    import com.liferay.portal.kernel.util.StringPool;
029    import com.liferay.portal.kernel.util.StringUtil;
030    import com.liferay.portal.theme.ThemeDisplay;
031    import com.liferay.portal.util.WebKeys;
032    import com.liferay.portlet.shopping.NoSuchCartException;
033    import com.liferay.portlet.shopping.model.ShoppingCart;
034    import com.liferay.portlet.shopping.model.ShoppingCartItem;
035    import com.liferay.portlet.shopping.model.ShoppingCategory;
036    import com.liferay.portlet.shopping.model.ShoppingCoupon;
037    import com.liferay.portlet.shopping.model.ShoppingCouponConstants;
038    import com.liferay.portlet.shopping.model.ShoppingItem;
039    import com.liferay.portlet.shopping.model.ShoppingItemField;
040    import com.liferay.portlet.shopping.model.ShoppingItemPrice;
041    import com.liferay.portlet.shopping.model.ShoppingItemPriceConstants;
042    import com.liferay.portlet.shopping.model.ShoppingOrder;
043    import com.liferay.portlet.shopping.model.ShoppingOrderConstants;
044    import com.liferay.portlet.shopping.model.ShoppingOrderItem;
045    import com.liferay.portlet.shopping.model.impl.ShoppingCartImpl;
046    import com.liferay.portlet.shopping.service.ShoppingCartLocalServiceUtil;
047    import com.liferay.portlet.shopping.service.ShoppingCategoryLocalServiceUtil;
048    import com.liferay.portlet.shopping.service.ShoppingOrderItemLocalServiceUtil;
049    import com.liferay.portlet.shopping.service.persistence.ShoppingItemPriceUtil;
050    import com.liferay.portlet.shopping.util.comparator.ItemMinQuantityComparator;
051    import com.liferay.portlet.shopping.util.comparator.ItemNameComparator;
052    import com.liferay.portlet.shopping.util.comparator.ItemPriceComparator;
053    import com.liferay.portlet.shopping.util.comparator.ItemSKUComparator;
054    import com.liferay.portlet.shopping.util.comparator.OrderDateComparator;
055    
056    import java.text.NumberFormat;
057    
058    import java.util.ArrayList;
059    import java.util.HashMap;
060    import java.util.HashSet;
061    import java.util.List;
062    import java.util.Locale;
063    import java.util.Map;
064    import java.util.Set;
065    
066    import javax.portlet.PortletRequest;
067    import javax.portlet.PortletSession;
068    import javax.portlet.PortletURL;
069    import javax.portlet.RenderRequest;
070    import javax.portlet.RenderResponse;
071    import javax.portlet.WindowState;
072    
073    import javax.servlet.jsp.PageContext;
074    
075    /**
076     * @author Brian Wing Shun Chan
077     */
078    public class ShoppingUtil {
079    
080            public static double calculateActualPrice(ShoppingItem item) {
081                    return item.getPrice() - calculateDiscountPrice(item);
082            }
083    
084            public static double calculateActualPrice(ShoppingItem item, int count)
085                    throws PortalException, SystemException {
086    
087                    return calculatePrice(item, count) -
088                            calculateDiscountPrice(item, count);
089            }
090    
091            public static double calculateActualPrice(ShoppingItemPrice itemPrice) {
092                    return itemPrice.getPrice() - calculateDiscountPrice(itemPrice);
093            }
094    
095            public static double calculateActualSubtotal(
096                    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                            double insuranceRate = 0.0;
328    
329                            double[] range = ShoppingPreferences.INSURANCE_RANGE;
330    
331                            for (int i = 0; i < range.length - 1; i++) {
332                                    if ((subtotal > range[i]) && (subtotal <= range[i + 1])) {
333                                            int rangeId = i / 2;
334    
335                                            if (MathUtil.isOdd(i)) {
336                                                    rangeId = (i + 1) / 2;
337                                            }
338    
339                                            insuranceRate = GetterUtil.getDouble(
340                                                    preferences.getInsurance()[rangeId]);
341                                    }
342                            }
343    
344                            String formula = preferences.getInsuranceFormula();
345    
346                            if (formula.equals("flat")) {
347                                    insurance += insuranceRate;
348                            }
349                            else if (formula.equals("percentage")) {
350                                    insurance += subtotal * insuranceRate;
351                            }
352                    }
353    
354                    return insurance;
355            }
356    
357            public static double calculatePrice(ShoppingItem item, int count)
358                    throws PortalException, SystemException {
359    
360                    ShoppingItemPrice itemPrice = _getItemPrice(item, count);
361    
362                    return itemPrice.getPrice() * count;
363            }
364    
365            public static double calculateShipping(Map<ShoppingCartItem, Integer> items)
366                    throws PortalException, SystemException {
367    
368                    double shipping = 0.0;
369                    double subtotal = 0.0;
370    
371                    ShoppingPreferences preferences = null;
372    
373                    for (Map.Entry<ShoppingCartItem, Integer> entry : items.entrySet()) {
374                            ShoppingCartItem cartItem = entry.getKey();
375                            Integer count = entry.getValue();
376    
377                            ShoppingItem item = cartItem.getItem();
378    
379                            if (preferences == null) {
380                                    ShoppingCategory category = item.getCategory();
381    
382                                    preferences = ShoppingPreferences.getInstance(
383                                            category.getCompanyId(), category.getGroupId());
384                            }
385    
386                            if (item.isRequiresShipping()) {
387                                    ShoppingItemPrice itemPrice = _getItemPrice(
388                                            item, count.intValue());
389    
390                                    if (itemPrice.isUseShippingFormula()) {
391                                            subtotal +=
392                                                    calculateActualPrice(itemPrice) * count.intValue();
393                                    }
394                                    else {
395                                            shipping += itemPrice.getShipping() * count.intValue();
396                                    }
397                            }
398                    }
399    
400                    if ((preferences != null) && (subtotal > 0)) {
401                            double shippingRate = 0.0;
402    
403                            double[] range = ShoppingPreferences.SHIPPING_RANGE;
404    
405                            for (int i = 0; i < range.length - 1; i++) {
406                                    if ((subtotal > range[i]) && (subtotal <= range[i + 1])) {
407                                            int rangeId = i / 2;
408    
409                                            if (MathUtil.isOdd(i)) {
410                                                    rangeId = (i + 1) / 2;
411                                            }
412    
413                                            shippingRate = GetterUtil.getDouble(
414                                                    preferences.getShipping()[rangeId]);
415                                    }
416                            }
417    
418                            String formula = preferences.getShippingFormula();
419    
420                            if (formula.equals("flat")) {
421                                    shipping += shippingRate;
422                            }
423                            else if (formula.equals("percentage")) {
424                                    shipping += subtotal * shippingRate;
425                            }
426                    }
427    
428                    return shipping;
429            }
430    
431            public static double calculateSubtotal(Map<ShoppingCartItem, Integer> items)
432                    throws PortalException, SystemException {
433    
434                    double subtotal = 0.0;
435    
436                    for (Map.Entry<ShoppingCartItem, Integer> entry : items.entrySet()) {
437                            ShoppingCartItem cartItem = entry.getKey();
438                            Integer count = entry.getValue();
439    
440                            ShoppingItem item = cartItem.getItem();
441    
442                            subtotal += calculatePrice(item, count.intValue());
443                    }
444    
445                    return subtotal;
446            }
447    
448            public static double calculateTax(
449                            Map<ShoppingCartItem, Integer> items, String stateId)
450                    throws PortalException, SystemException {
451    
452                    double tax = 0.0;
453    
454                    ShoppingPreferences preferences = null;
455    
456                    for (Map.Entry<ShoppingCartItem, Integer> entry : items.entrySet()) {
457                            ShoppingCartItem cartItem = entry.getKey();
458    
459                            ShoppingItem item = cartItem.getItem();
460    
461                            if (preferences == null) {
462                                    ShoppingCategory category = item.getCategory();
463    
464                                    preferences = ShoppingPreferences.getInstance(
465                                            category.getCompanyId(), category.getGroupId());
466    
467                                    break;
468                            }
469                    }
470    
471                    if ((preferences != null) &&
472                            preferences.getTaxState().equals(stateId)) {
473    
474                            double subtotal = 0.0;
475    
476                            for (Map.Entry<ShoppingCartItem, Integer> entry :
477                                            items.entrySet()) {
478    
479                                    ShoppingCartItem cartItem = entry.getKey();
480                                    Integer count = entry.getValue();
481    
482                                    ShoppingItem item = cartItem.getItem();
483    
484                                    if (item.isTaxable()) {
485                                            subtotal += calculatePrice(item, count.intValue());
486                                    }
487                            }
488    
489                            tax = preferences.getTaxRate() * subtotal;
490                    }
491    
492                    return tax;
493            }
494    
495            public static double calculateTotal(
496                            Map<ShoppingCartItem, Integer> items, String stateId,
497                            ShoppingCoupon coupon, int altShipping, boolean insure)
498                    throws PortalException, SystemException {
499    
500                    double actualSubtotal = calculateActualSubtotal(items);
501                    double tax = calculateTax(items, stateId);
502                    double shipping = calculateAlternativeShipping(items, altShipping);
503    
504                    double insurance = 0.0;
505    
506                    if (insure) {
507                            insurance = calculateInsurance(items);
508                    }
509    
510                    double couponDiscount = calculateCouponDiscount(items, stateId, coupon);
511    
512                    double total =
513                            actualSubtotal + tax + shipping + insurance - couponDiscount;
514    
515                    if (total < 0) {
516                            total = 0.0;
517                    }
518    
519                    return total;
520            }
521    
522            public static double calculateTotal(ShoppingOrder order)
523                    throws SystemException {
524    
525                    List<ShoppingOrderItem> orderItems =
526                            ShoppingOrderItemLocalServiceUtil.getOrderItems(order.getOrderId());
527    
528                    double total =
529                            calculateActualSubtotal(orderItems) + order.getTax() +
530                                    order.getShipping() + order.getInsurance() -
531                                            order.getCouponDiscount();
532    
533                    if (total < 0) {
534                            total = 0.0;
535                    }
536    
537                    return total;
538            }
539    
540            public static String getBreadcrumbs(
541                            long categoryId, PageContext pageContext,
542                            RenderRequest renderRequest, RenderResponse renderResponse)
543                    throws Exception {
544    
545                    ShoppingCategory category = null;
546    
547                    try {
548                            category = ShoppingCategoryLocalServiceUtil.getCategory(categoryId);
549                    }
550                    catch (Exception e) {
551                    }
552    
553                    return getBreadcrumbs(
554                            category, pageContext, renderRequest, renderResponse);
555            }
556    
557            public static String getBreadcrumbs(
558                            ShoppingCategory category, PageContext pageContext,
559                            RenderRequest renderRequest, RenderResponse renderResponse)
560                    throws Exception {
561    
562                    PortletURL categoriesURL = renderResponse.createRenderURL();
563    
564                    WindowState windowState = renderRequest.getWindowState();
565    
566                    if (windowState.equals(LiferayWindowState.POP_UP)) {
567                            categoriesURL.setParameter(
568                                    "struts_action", "/shopping/select_category");
569                            categoriesURL.setWindowState(LiferayWindowState.POP_UP);
570                    }
571                    else {
572                            categoriesURL.setParameter("struts_action", "/shopping/view");
573                            categoriesURL.setParameter("tabs1", "categories");
574                            //categoriesURL.setWindowState(WindowState.MAXIMIZED);
575                    }
576    
577                    String categoriesLink =
578                            "<a href=\"" + categoriesURL.toString() + "\">" +
579                                    LanguageUtil.get(pageContext, "categories") + "</a>";
580    
581                    if (category == null) {
582                            return "<span class=\"first last\">" + categoriesLink + "</span>";
583                    }
584    
585                    String breadcrumbs = StringPool.BLANK;
586    
587                    if (category != null) {
588                            for (int i = 0;; i++) {
589                                    category = category.toEscapedModel();
590    
591                                    PortletURL portletURL = renderResponse.createRenderURL();
592    
593                                    if (windowState.equals(LiferayWindowState.POP_UP)) {
594                                            portletURL.setParameter(
595                                                    "struts_action", "/shopping/select_category");
596                                            portletURL.setParameter(
597                                                    "categoryId", String.valueOf(category.getCategoryId()));
598                                            portletURL.setWindowState(LiferayWindowState.POP_UP);
599                                    }
600                                    else {
601                                            portletURL.setParameter("struts_action", "/shopping/view");
602                                            portletURL.setParameter("tabs1", "categories");
603                                            portletURL.setParameter(
604                                                    "categoryId", String.valueOf(category.getCategoryId()));
605                                            //portletURL.setWindowState(WindowState.MAXIMIZED);
606                                    }
607    
608                                    String categoryLink =
609                                            "<a href=\"" + portletURL.toString() + "\">" +
610                                                    category.getName() + "</a>";
611    
612                                    if (i == 0) {
613                                            breadcrumbs =
614                                                    "<span class=\"last\">" + categoryLink + "</span>";
615                                    }
616                                    else {
617                                            breadcrumbs = categoryLink + " &raquo; " + breadcrumbs;
618                                    }
619    
620                                    if (category.isRoot()) {
621                                            break;
622                                    }
623    
624                                    category = ShoppingCategoryLocalServiceUtil.getCategory(
625                                            category.getParentCategoryId());
626                            }
627                    }
628    
629                    breadcrumbs =
630                            "<span class=\"first\">" + categoriesLink + " &raquo; </span>" +
631                                    breadcrumbs;
632    
633                    return breadcrumbs;
634            }
635    
636            public static ShoppingCart getCart(PortletRequest portletRequest)
637                    throws PortalException, SystemException {
638    
639                    PortletSession portletSession = portletRequest.getPortletSession();
640    
641                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
642                            WebKeys.THEME_DISPLAY);
643    
644                    String sessionCartId =
645                            ShoppingCart.class.getName() + themeDisplay.getScopeGroupId();
646    
647                    if (themeDisplay.isSignedIn()) {
648                            ShoppingCart cart = (ShoppingCart)portletSession.getAttribute(
649                                    sessionCartId);
650    
651                            if (cart != null) {
652                                    portletSession.removeAttribute(sessionCartId);
653                            }
654    
655                            if ((cart != null) && (cart.getItemsSize() > 0)) {
656                                    cart = ShoppingCartLocalServiceUtil.updateCart(
657                                            themeDisplay.getUserId(), themeDisplay.getScopeGroupId(),
658                                            cart.getItemIds(), cart.getCouponCodes(),
659                                            cart.getAltShipping(), cart.isInsure());
660                            }
661                            else {
662                                    try {
663                                            cart = ShoppingCartLocalServiceUtil.getCart(
664                                                    themeDisplay.getUserId(),
665                                                    themeDisplay.getScopeGroupId());
666                                    }
667                                    catch (NoSuchCartException nsce) {
668                                            cart = getCart(themeDisplay);
669    
670                                            cart = ShoppingCartLocalServiceUtil.updateCart(
671                                                    themeDisplay.getUserId(),
672                                                    themeDisplay.getScopeGroupId(), cart.getItemIds(),
673                                                    cart.getCouponCodes(), cart.getAltShipping(),
674                                                    cart.isInsure());
675                                    }
676                            }
677    
678                            return cart;
679                    }
680                    else {
681                            ShoppingCart cart = (ShoppingCart)portletSession.getAttribute(
682                                    sessionCartId);
683    
684                            if (cart == null) {
685                                    cart = getCart(themeDisplay);
686    
687                                    portletSession.setAttribute(sessionCartId, cart);
688                            }
689    
690                            return cart;
691                    }
692            }
693    
694            public static ShoppingCart getCart(ThemeDisplay themeDisplay) {
695                    ShoppingCart cart = new ShoppingCartImpl();
696    
697                    cart.setGroupId(themeDisplay.getScopeGroupId());
698                    cart.setCompanyId(themeDisplay.getCompanyId());
699                    cart.setUserId(themeDisplay.getUserId());
700                    cart.setItemIds(StringPool.BLANK);
701                    cart.setCouponCodes(StringPool.BLANK);
702                    cart.setAltShipping(0);
703                    cart.setInsure(false);
704    
705                    return cart;
706            }
707    
708            public static int getFieldsQuantitiesPos(
709                    ShoppingItem item, ShoppingItemField[] itemFields,
710                    String[] fieldsArray) {
711    
712                    Set<String> fieldsValues = new HashSet<String>();
713    
714                    for (String fields : fieldsArray) {
715                            int pos = fields.indexOf("=");
716    
717                            String fieldValue = fields.substring(
718                                    pos + 1, fields.length()).trim();
719    
720                            fieldsValues.add(fieldValue);
721                    }
722    
723                    List<String> names = new ArrayList<String>();
724                    List<String[]> values = new ArrayList<String[]>();
725    
726                    for (int i = 0; i < itemFields.length; i++) {
727                            names.add(itemFields[i].getName());
728                            values.add(StringUtil.split(itemFields[i].getValues()));
729                    }
730    
731                    int numOfRows = 1;
732    
733                    for (String[] vArray : values) {
734                            numOfRows = numOfRows * vArray.length;
735                    }
736    
737                    int rowPos = 0;
738    
739                    for (int i = 0; i < numOfRows; i++) {
740                            boolean match = true;
741    
742                            for (int j = 0; j < names.size(); j++) {
743                                    int numOfRepeats = 1;
744    
745                                    for (int k = j + 1; k < values.size(); k++) {
746                                            String[] vArray = values.get(k);
747    
748                                            numOfRepeats = numOfRepeats * vArray.length;
749                                    }
750    
751                                    String[] vArray = values.get(j);
752    
753                                    int arrayPos;
754    
755                                    for (arrayPos = i / numOfRepeats;
756                                            arrayPos >= vArray.length;
757                                            arrayPos = arrayPos - vArray.length) {
758                                    }
759    
760                                    if (!fieldsValues.contains(vArray[arrayPos].trim())) {
761                                            match = false;
762    
763                                            break;
764                                    }
765                            }
766    
767                            if (match) {
768                                    rowPos = i;
769    
770                                    break;
771                            }
772                    }
773    
774                    return rowPos;
775            }
776    
777            public static String getItemFields(String itemId) {
778                    int pos = itemId.indexOf(CharPool.PIPE);
779    
780                    if (pos == -1) {
781                            return StringPool.BLANK;
782                    }
783                    else {
784                            return itemId.substring(pos + 1);
785                    }
786            }
787    
788            public static long getItemId(String itemId) {
789                    int pos = itemId.indexOf(CharPool.PIPE);
790    
791                    if (pos != -1) {
792                            itemId = itemId.substring(0, pos);
793                    }
794    
795                    return GetterUtil.getLong(itemId);
796            }
797    
798            public static OrderByComparator getItemOrderByComparator(
799                    String orderByCol, String orderByType) {
800    
801                    boolean orderByAsc = false;
802    
803                    if (orderByType.equals("asc")) {
804                            orderByAsc = true;
805                    }
806    
807                    OrderByComparator orderByComparator = null;
808    
809                    if (orderByCol.equals("min-qty")) {
810                            orderByComparator = new ItemMinQuantityComparator(orderByAsc);
811                    }
812                    else if (orderByCol.equals("name")) {
813                            orderByComparator = new ItemNameComparator(orderByAsc);
814                    }
815                    else if (orderByCol.equals("price")) {
816                            orderByComparator = new ItemPriceComparator(orderByAsc);
817                    }
818                    else if (orderByCol.equals("sku")) {
819                            orderByComparator = new ItemSKUComparator(orderByAsc);
820                    }
821                    else if (orderByCol.equals("order-date")) {
822                            orderByComparator = new OrderDateComparator(orderByAsc);
823                    }
824    
825                    return orderByComparator;
826            }
827    
828            public static int getMinQuantity(ShoppingItem item)
829                    throws PortalException, SystemException {
830    
831                    int minQuantity = item.getMinQuantity();
832    
833                    List<ShoppingItemPrice> itemPrices = item.getItemPrices();
834    
835                    for (ShoppingItemPrice itemPrice : itemPrices) {
836                            if (minQuantity > itemPrice.getMinQuantity()) {
837                                    minQuantity = itemPrice.getMinQuantity();
838                            }
839                    }
840    
841                    return minQuantity;
842            }
843    
844            public static String getPayPalNotifyURL(ThemeDisplay themeDisplay) {
845                    return themeDisplay.getPortalURL() + themeDisplay.getPathMain() +
846                            "/shopping/notify";
847            }
848    
849            public static String getPayPalRedirectURL(
850                    ShoppingPreferences preferences, ShoppingOrder order, double total,
851                    String returnURL, String notifyURL) {
852    
853                    String payPalEmailAddress = HttpUtil.encodeURL(
854                            preferences.getPayPalEmailAddress());
855    
856                    NumberFormat doubleFormat = NumberFormat.getNumberInstance(
857                            Locale.ENGLISH);
858    
859                    doubleFormat.setMaximumFractionDigits(2);
860                    doubleFormat.setMinimumFractionDigits(2);
861    
862                    String amount = doubleFormat.format(total);
863    
864                    returnURL = HttpUtil.encodeURL(returnURL);
865                    notifyURL = HttpUtil.encodeURL(notifyURL);
866    
867                    String firstName = HttpUtil.encodeURL(order.getBillingFirstName());
868                    String lastName = HttpUtil.encodeURL(order.getBillingLastName());
869                    String address1 = HttpUtil.encodeURL(order.getBillingStreet());
870                    String city = HttpUtil.encodeURL(order.getBillingCity());
871                    String state = HttpUtil.encodeURL(order.getBillingState());
872                    String zip = HttpUtil.encodeURL(order.getBillingZip());
873    
874                    String currencyCode = preferences.getCurrencyId();
875    
876                    StringBundler sb = new StringBundler(45);
877    
878                    sb.append("https://www.paypal.com/cgi-bin/webscr?");
879                    sb.append("cmd=_xclick&");
880                    sb.append("business=").append(payPalEmailAddress).append("&");
881                    sb.append("item_name=").append(order.getNumber()).append("&");
882                    sb.append("item_number=").append(order.getNumber()).append("&");
883                    sb.append("invoice=").append(order.getNumber()).append("&");
884                    sb.append("amount=").append(amount).append("&");
885                    sb.append("return=").append(returnURL).append("&");
886                    sb.append("notify_url=").append(notifyURL).append("&");
887                    sb.append("first_name=").append(firstName).append("&");
888                    sb.append("last_name=").append(lastName).append("&");
889                    sb.append("address1=").append(address1).append("&");
890                    sb.append("city=").append(city).append("&");
891                    sb.append("state=").append(state).append("&");
892                    sb.append("zip=").append(zip).append("&");
893                    sb.append("no_note=1&");
894                    sb.append("currency_code=").append(currencyCode).append("");
895    
896                    return sb.toString();
897            }
898    
899            public static String getPayPalReturnURL(
900                    PortletURL portletURL, ShoppingOrder order) {
901    
902                    portletURL.setParameter("struts_action", "/shopping/checkout");
903                    portletURL.setParameter(Constants.CMD, Constants.VIEW);
904                    portletURL.setParameter("orderId", String.valueOf(order.getOrderId()));
905    
906                    return portletURL.toString();
907            }
908    
909            public static String getPpPaymentStatus(
910                    ShoppingOrder order, PageContext pageContext) {
911    
912                    String ppPaymentStatus = order.getPpPaymentStatus();
913    
914                    if (ppPaymentStatus.equals(ShoppingOrderConstants.STATUS_CHECKOUT)) {
915                            ppPaymentStatus = "checkout";
916                    }
917                    else {
918                            ppPaymentStatus = ppPaymentStatus.toLowerCase();
919                    }
920    
921                    return LanguageUtil.get(pageContext, ppPaymentStatus);
922            }
923    
924            public static String getPpPaymentStatus(String ppPaymentStatus) {
925                    if ((ppPaymentStatus == null) || (ppPaymentStatus.length() < 2) ||
926                            ppPaymentStatus.equals("checkout")) {
927    
928                            return ShoppingOrderConstants.STATUS_CHECKOUT;
929                    }
930                    else {
931                            return Character.toUpperCase(ppPaymentStatus.charAt(0)) +
932                                    ppPaymentStatus.substring(1);
933                    }
934            }
935    
936            public static boolean isInStock(ShoppingItem item) {
937                    if (!item.isFields()) {
938                            if (item.getStockQuantity() > 0) {
939                                    return true;
940                            }
941                            else {
942                                    return false;
943                            }
944                    }
945                    else {
946                            String[] fieldsQuantities = item.getFieldsQuantitiesArray();
947    
948                            for (int i = 0; i < fieldsQuantities.length; i++) {
949                                    if (GetterUtil.getInteger(fieldsQuantities[i]) > 0) {
950                                            return true;
951                                    }
952                            }
953    
954                            return false;
955                    }
956            }
957    
958            public static boolean isInStock(
959                    ShoppingItem item, ShoppingItemField[] itemFields, String[] fieldsArray,
960                    Integer orderedQuantity) {
961    
962                    if (!item.isFields()) {
963                            int stockQuantity = item.getStockQuantity();
964    
965                            if ((stockQuantity > 0) &&
966                                    (stockQuantity >= orderedQuantity.intValue())) {
967    
968                                    return true;
969                            }
970                            else {
971                                    return false;
972                            }
973                    }
974                    else {
975                            String[] fieldsQuantities = item.getFieldsQuantitiesArray();
976    
977                            int stockQuantity = 0;
978    
979                            if (fieldsQuantities.length > 0) {
980                                    int rowPos = getFieldsQuantitiesPos(
981                                            item, itemFields, fieldsArray);
982    
983                                    stockQuantity = GetterUtil.getInteger(fieldsQuantities[rowPos]);
984                            }
985    
986                            try {
987                                    if ((stockQuantity > 0) &&
988                                            (stockQuantity >= orderedQuantity.intValue())) {
989    
990                                            return true;
991                                    }
992                            }
993                            catch (Exception e) {
994                            }
995    
996                            return false;
997                    }
998            }
999    
1000            public static boolean meetsMinOrder(
1001                            ShoppingPreferences preferences,
1002                            Map<ShoppingCartItem, Integer> items)
1003                    throws PortalException, SystemException {
1004    
1005                    if ((preferences.getMinOrder() > 0) &&
1006                            (calculateSubtotal(items) < preferences.getMinOrder())) {
1007    
1008                            return false;
1009                    }
1010                    else {
1011                            return true;
1012                    }
1013            }
1014    
1015            private static ShoppingItemPrice _getItemPrice(ShoppingItem item, int count)
1016                    throws PortalException, SystemException {
1017    
1018                    ShoppingItemPrice itemPrice = null;
1019    
1020                    List<ShoppingItemPrice> itemPrices = item.getItemPrices();
1021    
1022                    for (ShoppingItemPrice temp : itemPrices) {
1023                            int minQty = temp.getMinQuantity();
1024                            int maxQty = temp.getMaxQuantity();
1025    
1026                            if (temp.getStatus() !=
1027                                            ShoppingItemPriceConstants.STATUS_INACTIVE) {
1028    
1029                                    if ((count >= minQty) && ((count <= maxQty) || (maxQty == 0))) {
1030                                            return temp;
1031                                    }
1032    
1033                                    if ((count > maxQty) &&
1034                                            ((itemPrice == null) ||
1035                                             (itemPrice.getMaxQuantity() < maxQty))) {
1036    
1037                                            itemPrice = temp;
1038                                    }
1039                            }
1040                    }
1041    
1042                    if (itemPrice == null) {
1043                            return ShoppingItemPriceUtil.create(0);
1044                    }
1045    
1046                    return itemPrice;
1047            }
1048    
1049    }