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;
823                                            arrayPos >= vArray.length;
824                                            arrayPos = arrayPos - vArray.length) {
825                                    }
826    
827                                    if (!fieldsValues.contains(vArray[arrayPos].trim())) {
828                                            match = false;
829    
830                                            break;
831                                    }
832                            }
833    
834                            if (match) {
835                                    rowPos = i;
836    
837                                    break;
838                            }
839                    }
840    
841                    return rowPos;
842            }
843    
844            public static String getItemFields(String itemId) {
845                    int pos = itemId.indexOf(CharPool.PIPE);
846    
847                    if (pos == -1) {
848                            return StringPool.BLANK;
849                    }
850                    else {
851                            return itemId.substring(pos + 1);
852                    }
853            }
854    
855            public static long getItemId(String itemId) {
856                    int pos = itemId.indexOf(CharPool.PIPE);
857    
858                    if (pos != -1) {
859                            itemId = itemId.substring(0, pos);
860                    }
861    
862                    return GetterUtil.getLong(itemId);
863            }
864    
865            public static OrderByComparator<ShoppingItem> getItemOrderByComparator(
866                    String orderByCol, String orderByType) {
867    
868                    boolean orderByAsc = false;
869    
870                    if (orderByType.equals("asc")) {
871                            orderByAsc = true;
872                    }
873    
874                    OrderByComparator<ShoppingItem> orderByComparator = null;
875    
876                    if (orderByCol.equals("min-qty")) {
877                            orderByComparator = new ItemMinQuantityComparator(orderByAsc);
878                    }
879                    else if (orderByCol.equals("name")) {
880                            orderByComparator = new ItemNameComparator(orderByAsc);
881                    }
882                    else if (orderByCol.equals("price")) {
883                            orderByComparator = new ItemPriceComparator(orderByAsc);
884                    }
885                    else if (orderByCol.equals("sku")) {
886                            orderByComparator = new ItemSKUComparator(orderByAsc);
887                    }
888    
889                    return orderByComparator;
890            }
891    
892            public static int getMinQuantity(ShoppingItem item) throws PortalException {
893                    int minQuantity = item.getMinQuantity();
894    
895                    List<ShoppingItemPrice> itemPrices = item.getItemPrices();
896    
897                    for (ShoppingItemPrice itemPrice : itemPrices) {
898                            if (minQuantity > itemPrice.getMinQuantity()) {
899                                    minQuantity = itemPrice.getMinQuantity();
900                            }
901                    }
902    
903                    return minQuantity;
904            }
905    
906            public static String getPayPalNotifyURL(ThemeDisplay themeDisplay) {
907                    return themeDisplay.getPortalURL() + themeDisplay.getPathMain() +
908                            "/shopping/notify";
909            }
910    
911            public static String getPayPalRedirectURL(
912                    ShoppingSettings shoppingSettings, ShoppingOrder order, double total,
913                    String returnURL, String notifyURL) {
914    
915                    String payPalEmailAddress = HttpUtil.encodeURL(
916                            shoppingSettings.getPayPalEmailAddress());
917    
918                    NumberFormat doubleFormat = NumberFormat.getNumberInstance(
919                            LocaleUtil.ENGLISH);
920    
921                    doubleFormat.setMaximumFractionDigits(2);
922                    doubleFormat.setMinimumFractionDigits(2);
923    
924                    String amount = doubleFormat.format(total);
925    
926                    returnURL = HttpUtil.encodeURL(returnURL);
927                    notifyURL = HttpUtil.encodeURL(notifyURL);
928    
929                    String firstName = HttpUtil.encodeURL(order.getBillingFirstName());
930                    String lastName = HttpUtil.encodeURL(order.getBillingLastName());
931                    String address1 = HttpUtil.encodeURL(order.getBillingStreet());
932                    String city = HttpUtil.encodeURL(order.getBillingCity());
933                    String state = HttpUtil.encodeURL(order.getBillingState());
934                    String zip = HttpUtil.encodeURL(order.getBillingZip());
935    
936                    String currencyCode = shoppingSettings.getCurrencyId();
937    
938                    StringBundler sb = new StringBundler(45);
939    
940                    sb.append("https://www.paypal.com/cgi-bin/webscr?");
941                    sb.append("cmd=_xclick&");
942                    sb.append("business=").append(payPalEmailAddress).append("&");
943                    sb.append("item_name=").append(order.getNumber()).append("&");
944                    sb.append("item_number=").append(order.getNumber()).append("&");
945                    sb.append("invoice=").append(order.getNumber()).append("&");
946                    sb.append("amount=").append(amount).append("&");
947                    sb.append("return=").append(returnURL).append("&");
948                    sb.append("notify_url=").append(notifyURL).append("&");
949                    sb.append("first_name=").append(firstName).append("&");
950                    sb.append("last_name=").append(lastName).append("&");
951                    sb.append("address1=").append(address1).append("&");
952                    sb.append("city=").append(city).append("&");
953                    sb.append("state=").append(state).append("&");
954                    sb.append("zip=").append(zip).append("&");
955                    sb.append("no_note=1&");
956                    sb.append("currency_code=").append(currencyCode).append("");
957    
958                    return sb.toString();
959            }
960    
961            public static String getPayPalReturnURL(
962                    PortletURL portletURL, ShoppingOrder order) {
963    
964                    portletURL.setParameter("struts_action", "/shopping/checkout");
965                    portletURL.setParameter(Constants.CMD, Constants.VIEW);
966                    portletURL.setParameter("orderId", String.valueOf(order.getOrderId()));
967    
968                    return portletURL.toString();
969            }
970    
971            public static String getPpPaymentStatus(
972                    ShoppingOrder order, HttpServletRequest request) {
973    
974                    String ppPaymentStatus = order.getPpPaymentStatus();
975    
976                    if (ppPaymentStatus.equals(ShoppingOrderConstants.STATUS_CHECKOUT)) {
977                            ppPaymentStatus = "checkout";
978                    }
979                    else {
980                            ppPaymentStatus = StringUtil.toLowerCase(ppPaymentStatus);
981                    }
982    
983                    return LanguageUtil.get(request, HtmlUtil.escape(ppPaymentStatus));
984            }
985    
986            public static String getPpPaymentStatus(String ppPaymentStatus) {
987                    if ((ppPaymentStatus == null) || (ppPaymentStatus.length() < 2) ||
988                            ppPaymentStatus.equals("checkout")) {
989    
990                            return ShoppingOrderConstants.STATUS_CHECKOUT;
991                    }
992                    else {
993                            return Character.toUpperCase(ppPaymentStatus.charAt(0)) +
994                                    ppPaymentStatus.substring(1);
995                    }
996            }
997    
998            public static boolean isInStock(ShoppingItem item) {
999                    if (item.isInfiniteStock()) {
1000                            return true;
1001                    }
1002    
1003                    if (!item.isFields()) {
1004                            if (item.getStockQuantity() > 0) {
1005                                    return true;
1006                            }
1007                            else {
1008                                    return false;
1009                            }
1010                    }
1011                    else {
1012                            String[] fieldsQuantities = item.getFieldsQuantitiesArray();
1013    
1014                            for (int i = 0; i < fieldsQuantities.length; i++) {
1015                                    if (GetterUtil.getInteger(fieldsQuantities[i]) > 0) {
1016                                            return true;
1017                                    }
1018                            }
1019    
1020                            return false;
1021                    }
1022            }
1023    
1024            public static boolean isInStock(
1025                    ShoppingItem item, ShoppingItemField[] itemFields, String[] fieldsArray,
1026                    Integer orderedQuantity) {
1027    
1028                    if (item.isInfiniteStock()) {
1029                            return true;
1030                    }
1031    
1032                    if (!item.isFields()) {
1033                            int stockQuantity = item.getStockQuantity();
1034    
1035                            if ((stockQuantity > 0) &&
1036                                    (stockQuantity >= orderedQuantity.intValue())) {
1037    
1038                                    return true;
1039                            }
1040                            else {
1041                                    return false;
1042                            }
1043                    }
1044                    else {
1045                            String[] fieldsQuantities = item.getFieldsQuantitiesArray();
1046    
1047                            int stockQuantity = 0;
1048    
1049                            if (fieldsQuantities.length > 0) {
1050                                    int rowPos = getFieldsQuantitiesPos(
1051                                            item, itemFields, fieldsArray);
1052    
1053                                    stockQuantity = GetterUtil.getInteger(fieldsQuantities[rowPos]);
1054                            }
1055    
1056                            try {
1057                                    if ((stockQuantity > 0) &&
1058                                            (stockQuantity >= orderedQuantity.intValue())) {
1059    
1060                                            return true;
1061                                    }
1062                            }
1063                            catch (Exception e) {
1064                            }
1065    
1066                            return false;
1067                    }
1068            }
1069    
1070            public static boolean meetsMinOrder(
1071                            ShoppingSettings shoppingSettings,
1072                            Map<ShoppingCartItem, Integer> items)
1073                    throws PortalException {
1074    
1075                    if ((shoppingSettings.getMinOrder() > 0) &&
1076                            (calculateSubtotal(items) < shoppingSettings.getMinOrder())) {
1077    
1078                            return false;
1079                    }
1080                    else {
1081                            return true;
1082                    }
1083            }
1084    
1085            private static ShoppingItemPrice _getItemPrice(ShoppingItem item, int count)
1086                    throws PortalException {
1087    
1088                    ShoppingItemPrice itemPrice = null;
1089    
1090                    List<ShoppingItemPrice> itemPrices = item.getItemPrices();
1091    
1092                    for (ShoppingItemPrice temp : itemPrices) {
1093                            int minQty = temp.getMinQuantity();
1094                            int maxQty = temp.getMaxQuantity();
1095    
1096                            if (temp.getStatus() !=
1097                                            ShoppingItemPriceConstants.STATUS_INACTIVE) {
1098    
1099                                    if ((count >= minQty) && ((count <= maxQty) || (maxQty == 0))) {
1100                                            return temp;
1101                                    }
1102    
1103                                    if ((count > maxQty) &&
1104                                            ((itemPrice == null) ||
1105                                             (itemPrice.getMaxQuantity() < maxQty))) {
1106    
1107                                            itemPrice = temp;
1108                                    }
1109                            }
1110                    }
1111    
1112                    if (itemPrice == null) {
1113                            return ShoppingItemPriceUtil.create(0);
1114                    }
1115    
1116                    return itemPrice;
1117            }
1118    
1119    }