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