com.ctc.storefront.controllers.misc.AddToCartController.java Source code

Java tutorial

Introduction

Here is the source code for com.ctc.storefront.controllers.misc.AddToCartController.java

Source

/*
 * [y] hybris Platform
 *
 * Copyright (c) 2000-2016 SAP SE or an SAP affiliate company.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of SAP
 * ("Confidential Information"). You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the
 * license agreement you entered into with SAP.
 */
package com.ctc.storefront.controllers.misc;

import de.hybris.platform.acceleratorfacades.product.data.ProductWrapperData;
import de.hybris.platform.acceleratorservices.config.SiteConfigService;
import de.hybris.platform.acceleratorstorefrontcommons.controllers.AbstractController;
import de.hybris.platform.acceleratorstorefrontcommons.forms.AddToCartForm;
import de.hybris.platform.acceleratorstorefrontcommons.forms.AddToCartOrderForm;
import de.hybris.platform.commercefacades.order.CartFacade;
import de.hybris.platform.commercefacades.order.converters.populator.GroupCartModificationListPopulator;
import de.hybris.platform.commercefacades.order.data.CartData;
import de.hybris.platform.commercefacades.order.data.CartModificationData;
import de.hybris.platform.commercefacades.order.data.OrderEntryData;
import de.hybris.platform.commercefacades.product.ProductFacade;
import de.hybris.platform.commercefacades.product.ProductOption;
import de.hybris.platform.commercefacades.product.data.ProductData;
import de.hybris.platform.commerceservices.order.CommerceCartModificationException;
import de.hybris.platform.util.Config;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.ctc.storefront.controllers.ControllerConstants;

/**
 * Controller for Add to Cart functionality which is not specific to a certain page.
 */
@Controller
public class AddToCartController extends AbstractController {
    private static final String QUANTITY_ATTR = "quantity";
    private static final String TYPE_MISMATCH_ERROR_CODE = "typeMismatch";
    private static final String ERROR_MSG_TYPE = "errorMsg";
    private static final String QUANTITY_INVALID_BINDING_MESSAGE_KEY = "basket.error.quantity.invalid.binding";
    private static final String SHOWN_PRODUCT_COUNT = "ctcstorefront.storefront.minicart.shownProductCount";
    private static final String REDIRECT_CART_URL = REDIRECT_PREFIX + "/cart";
    public static final String CART_COUNT_COOKIE_DOMAIN_NAME = "cart.count.cookie.domain.name";

    private static final Logger LOG = Logger.getLogger(AddToCartController.class);

    @Resource(name = "cartFacade")
    private CartFacade cartFacade;

    @Resource(name = "accProductFacade")
    private ProductFacade productFacade;

    @Resource(name = "groupCartModificationListPopulator")
    private GroupCartModificationListPopulator groupCartModificationListPopulator;

    @Resource(name = "siteConfigService")
    private SiteConfigService siteConfigService;

    @RequestMapping(value = "/cart/add", method = RequestMethod.POST, produces = "application/json")
    public String addToCart(@RequestParam("productCodePost") final String code, final Model model,
            @Valid final AddToCartForm form, final BindingResult bindingErrors,
            final HttpServletResponse response) {
        if (bindingErrors.hasErrors()) {
            return getViewWithBindingErrorMessages(model, bindingErrors);
        }

        final long qty = form.getQty();

        if (qty <= 0) {
            model.addAttribute(ERROR_MSG_TYPE, "basket.error.quantity.invalid");
            model.addAttribute(QUANTITY_ATTR, Long.valueOf(0L));
        } else {
            try {
                final CartModificationData cartModification = cartFacade.addToCart(code, qty);
                model.addAttribute(QUANTITY_ATTR, Long.valueOf(cartModification.getQuantityAdded()));
                model.addAttribute("entry", cartModification.getEntry());
                model.addAttribute("cartCode", cartModification.getCartCode());

                if (cartModification.getQuantityAdded() == 0L) {
                    model.addAttribute(ERROR_MSG_TYPE,
                            "basket.information.quantity.noItemsAdded." + cartModification.getStatusCode());
                } else if (cartModification.getQuantityAdded() < qty) {
                    model.addAttribute(ERROR_MSG_TYPE, "basket.information.quantity.reducedNumberOfItemsAdded."
                            + cartModification.getStatusCode());
                }

                setCookie(response, cartFacade.getSessionCart());
            } catch (final CommerceCartModificationException ex) {
                logDebugException(ex);
                model.addAttribute(ERROR_MSG_TYPE, "basket.error.occurred");
                model.addAttribute(QUANTITY_ATTR, Long.valueOf(0L));
            }
        }

        model.addAttribute("product",
                productFacade.getProductForCodeAndOptions(code, Arrays.asList(ProductOption.BASIC)));

        return ControllerConstants.Views.Fragments.Cart.AddToCartPopup;
    }

    protected String getViewWithBindingErrorMessages(final Model model, final BindingResult bindingErrors) {
        for (final ObjectError error : bindingErrors.getAllErrors()) {
            if (isTypeMismatchError(error)) {
                model.addAttribute(ERROR_MSG_TYPE, QUANTITY_INVALID_BINDING_MESSAGE_KEY);
            } else {
                model.addAttribute(ERROR_MSG_TYPE, error.getDefaultMessage());
            }
        }
        return ControllerConstants.Views.Fragments.Cart.AddToCartPopup;
    }

    protected boolean isTypeMismatchError(final ObjectError error) {
        return error.getCode().equals(TYPE_MISMATCH_ERROR_CODE);
    }

    @RequestMapping(value = "/cart/addGrid", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public final String addGridToCart(@RequestBody final AddToCartOrderForm form, final Model model) {
        final Set<String> multidErrorMsgs = new HashSet<String>();
        final List<CartModificationData> modificationDataList = new ArrayList<CartModificationData>();

        for (final OrderEntryData cartEntry : form.getCartEntries()) {
            if (!isValidProductEntry(cartEntry)) {
                LOG.error("Error processing entry");
            } else if (!isValidQuantity(cartEntry)) {
                multidErrorMsgs.add("basket.error.quantity.invalid");
            } else {
                final String errorMsg = addEntryToCart(modificationDataList, cartEntry, true);
                if (StringUtils.isNotEmpty(errorMsg)) {
                    multidErrorMsgs.add(errorMsg);
                }

            }
        }

        if (CollectionUtils.isNotEmpty(modificationDataList)) {
            groupCartModificationListPopulator.populate(null, modificationDataList);

            model.addAttribute("modifications", modificationDataList);
        }

        if (CollectionUtils.isNotEmpty(multidErrorMsgs)) {
            model.addAttribute("multidErrorMsgs", multidErrorMsgs);
        }

        model.addAttribute("numberShowing", Integer.valueOf(Config.getInt(SHOWN_PRODUCT_COUNT, 3)));

        return ControllerConstants.Views.Fragments.Cart.AddToCartPopup;
    }

    @RequestMapping(value = "/cart/addQuickOrder", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public final String addQuickOrderToCart(@RequestBody final AddToCartOrderForm form, final Model model) {
        final List<CartModificationData> modificationDataList = new ArrayList();
        final List<ProductWrapperData> productWrapperDataList = new ArrayList();
        final int maxQuickOrderEntries = Config.getInt("ctcstorefront.quick.order.rows.max", 25);
        final int sizeOfCartEntries = CollectionUtils.size(form.getCartEntries());
        form.getCartEntries().stream().limit(Math.min(sizeOfCartEntries, maxQuickOrderEntries))
                .forEach(cartEntry -> {
                    String errorMsg = StringUtils.EMPTY;
                    final String sku = !isValidProductEntry(cartEntry) ? StringUtils.EMPTY
                            : cartEntry.getProduct().getCode();
                    if (StringUtils.isEmpty(sku)) {
                        errorMsg = "text.quickOrder.product.code.invalid";
                    } else if (!isValidQuantity(cartEntry)) {
                        errorMsg = "text.quickOrder.product.quantity.invalid";
                    } else {
                        errorMsg = addEntryToCart(modificationDataList, cartEntry, false);
                    }

                    if (StringUtils.isNotEmpty(errorMsg)) {
                        productWrapperDataList.add(createProductWrapperData(sku, errorMsg));
                    }
                });

        if (CollectionUtils.isNotEmpty(productWrapperDataList)) {
            model.addAttribute("quickOrderErrorData", productWrapperDataList);
            model.addAttribute("quickOrderErrorMsg", "basket.quick.order.error");
        }

        if (CollectionUtils.isNotEmpty(modificationDataList)) {
            model.addAttribute("modifications", modificationDataList);
        }

        return ControllerConstants.Views.Fragments.Cart.AddToCartPopup;
    }

    protected ProductWrapperData createProductWrapperData(final String sku, final String errorMsg) {
        final ProductWrapperData productWrapperData = new ProductWrapperData();
        final ProductData productData = new ProductData();
        productData.setCode(sku);
        productWrapperData.setProductData(productData);
        productWrapperData.setErrorMsg(errorMsg);
        return productWrapperData;
    }

    protected void logDebugException(final Exception ex) {
        if (LOG.isDebugEnabled()) {
            LOG.debug(ex);
        }
    }

    protected String addEntryToCart(final List<CartModificationData> modificationDataList,
            final OrderEntryData cartEntry, final boolean isReducedQtyError) {
        String errorMsg = StringUtils.EMPTY;
        try {
            final long qty = cartEntry.getQuantity().longValue();
            final CartModificationData cartModificationData = cartFacade.addToCart(cartEntry.getProduct().getCode(),
                    qty);
            if (cartModificationData.getQuantityAdded() == 0L) {
                errorMsg = "basket.information.quantity.noItemsAdded." + cartModificationData.getStatusCode();
            } else if (cartModificationData.getQuantityAdded() < qty && isReducedQtyError) {
                errorMsg = "basket.information.quantity.reducedNumberOfItemsAdded."
                        + cartModificationData.getStatusCode();
            }

            modificationDataList.add(cartModificationData);

        } catch (final CommerceCartModificationException ex) {
            errorMsg = "basket.error.occurred";
            logDebugException(ex);
        }
        return errorMsg;
    }

    protected boolean isValidProductEntry(final OrderEntryData cartEntry) {
        return cartEntry.getProduct() != null && StringUtils.isNotBlank(cartEntry.getProduct().getCode());
    }

    protected boolean isValidQuantity(final OrderEntryData cartEntry) {
        return cartEntry.getQuantity() != null && cartEntry.getQuantity().longValue() >= 1L;
    }

    @RequestMapping(value = "/cart/add", method = RequestMethod.POST, params = { "buyNow" })
    public String buyNow(@RequestParam("productCodePost") final String code, final Model model,
            @Valid final AddToCartForm form, final BindingResult bindingErrors,
            final HttpServletResponse response) {
        if (bindingErrors.hasErrors()) {
            return getViewWithBindingErrorMessages(model, bindingErrors);
        }

        final long qty = form.getQty();

        if (qty <= 0) {
            model.addAttribute(ERROR_MSG_TYPE, "basket.error.quantity.invalid");
            model.addAttribute(QUANTITY_ATTR, Long.valueOf(0L));
        } else {
            try {
                final CartModificationData cartModification = cartFacade.addToCart(code, qty);

                if (cartModification.getQuantityAdded() == 0L) {
                    model.addAttribute(ERROR_MSG_TYPE,
                            "basket.information.quantity.noItemsAdded." + cartModification.getStatusCode());
                } else if (cartModification.getQuantityAdded() < qty) {
                    model.addAttribute(ERROR_MSG_TYPE, "basket.information.quantity.reducedNumberOfItemsAdded."
                            + cartModification.getStatusCode());
                }
                setCookie(response, cartFacade.getSessionCart());
            } catch (final CommerceCartModificationException ex) {
                logDebugException(ex);
                model.addAttribute(ERROR_MSG_TYPE, "basket.error.occurred");
                model.addAttribute(QUANTITY_ATTR, Long.valueOf(0L));
            }
        }
        return REDIRECT_CART_URL;
    }

    private void setCookie(final HttpServletResponse response, final CartData cartData) {
        final Cookie cookie = new Cookie("cartQuantity", String.valueOf(cartData.getTotalUnitCount()));
        cookie.setMaxAge(60 * 60);
        cookie.setPath("/");
        cookie.setDomain(siteConfigService.getString(CART_COUNT_COOKIE_DOMAIN_NAME, ".ctc.com"));
        response.addCookie(cookie);
    }
}