@RequestMapping(
     value = "/summary/reorder",
     method = {RequestMethod.PUT, RequestMethod.POST})
 @RequireHardLogIn
 public String reorder(
     @RequestParam(value = "orderCode") final String orderCode,
     final RedirectAttributes redirectModel)
     throws CMSItemNotFoundException, InvalidCartException, ParseException,
         CommerceCartModificationException {
   // create a cart from the order and set it as session cart.
   getB2BCheckoutFacade().createCartFromOrder(orderCode);
   // validate for stock and availability
   final List<CartModificationData> cartModifications = doNotUsecartFacade.validateCartData();
   for (final CartModificationData cartModification : cartModifications) {
     if (CommerceCartModificationStatus.NO_STOCK.equals(cartModification.getStatusCode())) {
       GlobalMessages.addFlashMessage(
           redirectModel,
           GlobalMessages.ERROR_MESSAGES_HOLDER,
           "basket.page.message.update.reducedNumberOfItemsAdded.noStock",
           new Object[] {cartModification.getEntry().getProduct().getName()});
       break;
     } else if (cartModification.getQuantity() != cartModification.getQuantityAdded()) {
       // item has been modified to match available stock levels
       GlobalMessages.addFlashMessage(
           redirectModel,
           GlobalMessages.ERROR_MESSAGES_HOLDER,
           "basket.information.quantity.adjusted");
       break;
     }
     // TODO: handle more specific messaging, i.e. out of stock, product not available
   }
   return REDIRECT_PREFIX + "/checkout/single/summary"; // checkoutSummary(model);
 }
 @Test
 public void testAddToCart() {
   final CartModificationData modification = classUnderTest.addToCart(productId, quantity);
   assertNotNull(modification);
   assertTrue(modification.getQuantity() == quantity);
   assertTrue(modification.getQuantityAdded() == quantity);
 }
 @Test
 public void testAddToCartEntry() {
   final CartModificationData modification = classUnderTest.addToCart(productId, quantity);
   assertNotNull(modification);
   final OrderEntryData entry = modification.getEntry();
   assertNotNull(entry);
   assertEquals(productId, entry.getProduct().getCode());
   assertEquals(new Long(quantity), entry.getQuantity());
 }
  @RequestMapping(
      value = "/cart/update",
      method = RequestMethod.POST,
      produces = "application/json")
  public String updateCartQuantities(
      @RequestParam("storeNamePost") final String storeId,
      @RequestParam("entryNumber") final long entryNumber,
      @RequestParam("hiddenPickupQty") final long quantity,
      final RedirectAttributes redirectModel)
      throws CommerceCartModificationException {
    final CartModificationData cartModificationData =
        cartFacade.updateCartEntry(entryNumber, storeId);

    if (entryNumber == cartModificationData.getEntry().getEntryNumber().intValue()) {
      final CartModificationData cartModification =
          cartFacade.updateCartEntry(entryNumber, quantity);
      if (cartModification.getQuantity() == quantity) {
        // Success
        if (cartModification.getQuantity() == 0) {
          // Success in removing entry
          GlobalMessages.addFlashMessage(
              redirectModel, GlobalMessages.CONF_MESSAGES_HOLDER, "basket.page.message.remove");
        } else {
          // Success in update quantity
          GlobalMessages.addFlashMessage(
              redirectModel,
              GlobalMessages.CONF_MESSAGES_HOLDER,
              "basket.page.message.update.pickupinstoreitem");
        }
      } else {
        // Less than successful
        GlobalMessages.addFlashMessage(
            redirectModel,
            GlobalMessages.ERROR_MESSAGES_HOLDER,
            "basket.information.quantity.reducedNumberOfItemsAdded."
                + cartModification.getStatusCode());
      }
    } else if (!CommerceCartModificationStatus.SUCCESS.equals(
        cartModificationData.getStatusCode())) {
      // When update pickupInStore happens to be same as existing entry with POS and SKU and that
      // merged POS has lower stock
      GlobalMessages.addFlashMessage(
          redirectModel,
          GlobalMessages.ERROR_MESSAGES_HOLDER,
          "basket.information.quantity.reducedNumberOfItemsAdded."
              + cartModificationData.getStatusCode());
    }

    return REDIRECT_PREFIX + "/cart";
  }
  @RequestMapping(
      value = "/cart/update/delivery",
      method = {RequestMethod.GET, RequestMethod.POST})
  public String updateToDelivery(
      @RequestParam("entryNumber") final long entryNumber, final RedirectAttributes redirectModel)
      throws CommerceCartModificationException {
    final CartModificationData cartModificationData = cartFacade.updateCartEntry(entryNumber, null);
    if (CommerceCartModificationStatus.SUCCESS.equals(cartModificationData.getStatusCode())) {
      // Success in update quantity
      GlobalMessages.addFlashMessage(
          redirectModel,
          GlobalMessages.CONF_MESSAGES_HOLDER,
          "basket.page.message.update.pickupinstoreitem.toship");
    } else {
      // Less than successful
      GlobalMessages.addFlashMessage(
          redirectModel,
          GlobalMessages.ERROR_MESSAGES_HOLDER,
          "basket.information.quantity.reducedNumberOfItemsAdded."
              + cartModificationData.getStatusCode());
    }

    return REDIRECT_PREFIX + "/cart";
  }
  @RequestMapping(value = "/cart/add", method = RequestMethod.POST, produces = "application/json")
  public String addToCartPickup(
      @RequestParam("productCodePost") final String code,
      @RequestParam("storeNamePost") final String storeId,
      final Model model,
      @Valid final PickupInStoreForm form,
      final BindingResult bindingErrors) {
    if (bindingErrors.hasErrors()) {
      return getViewWithBindingErrorMessages(model, bindingErrors);
    }

    final long qty = form.getHiddenPickupQty();

    if (qty <= 0) {
      model.addAttribute("errorMsg", "basket.error.quantity.invalid");
      return ControllerConstants.Views.Fragments.Cart.AddToCartPopup;
    }

    try {
      final CartModificationData cartModification = cartFacade.addToCart(code, qty, storeId);
      model.addAttribute("quantity", Long.valueOf(cartModification.getQuantityAdded()));
      model.addAttribute("entry", cartModification.getEntry());

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

      // Put in the cart again after it has been modified
      model.addAttribute("cartData", cartFacade.getSessionCart());
    } catch (final CommerceCartModificationException ex) {
      model.addAttribute("errorMsg", "basket.error.occurred");
      model.addAttribute("quantity", Long.valueOf(0L));
      LOG.warn("Couldn't add product of code " + code + " to cart.", ex);
    }

    final ProductData productData =
        productFacade.getProductForCodeAndOptions(
            code, Arrays.asList(ProductOption.BASIC, ProductOption.PRICE));
    model.addAttribute("product", productData);

    model.addAttribute("cartData", cartFacade.getSessionCart());

    return ControllerConstants.Views.Fragments.Cart.AddToCartPopup;
  }
  @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) {
    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", Long.valueOf(0L));
    } else {
      try {
        final CartModificationData cartModification = cartFacade.addToCart(code, qty);
        model.addAttribute("quantity", 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());
        }
      } catch (final CommerceCartModificationException ex) {
        model.addAttribute(ERROR_MSG_TYPE, "basket.error.occurred");
        model.addAttribute("quantity", Long.valueOf(0L));
      }
    }

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

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