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