@Override
 @Transactional(
     value = "blTransactionManager",
     rollbackFor = {AddToCartException.class})
 public Order addItemWithPriceOverrides(
     Long orderId, OrderItemRequestDTO orderItemRequestDTO, boolean priceOrder)
     throws AddToCartException {
   Order order = findOrderById(orderId);
   if (automaticallyMergeLikeItems) {
     OrderItem item = findMatchingItem(order, orderItemRequestDTO);
     if (item != null) {
       orderItemRequestDTO.setQuantity(item.getQuantity() + orderItemRequestDTO.getQuantity());
       orderItemRequestDTO.setOrderItemId(item.getId());
       try {
         return updateItemQuantity(orderId, orderItemRequestDTO, priceOrder);
       } catch (RemoveFromCartException e) {
         throw new AddToCartException(
             "Unexpected error - system tried to remove item while adding to cart", e);
       } catch (UpdateCartException e) {
         throw new AddToCartException("Could not update quantity for matched item", e);
       }
     }
   }
   try {
     CartOperationRequest cartOpRequest =
         new CartOperationRequest(findOrderById(orderId), orderItemRequestDTO, priceOrder);
     CartOperationContext context =
         (CartOperationContext) addItemWorkflow.doActivities(cartOpRequest);
     return context.getSeedData().getOrder();
   } catch (WorkflowException e) {
     throw new AddToCartException("Could not add to cart", getCartOperationExceptionRootCause(e));
   }
 }
  @Override
  @Transactional("blTransactionManager")
  public Order addAllItemsFromNamedOrder(Order namedOrder, boolean priceOrder)
      throws RemoveFromCartException, AddToCartException {
    Order cartOrder = orderDao.readCartForCustomer(namedOrder.getCustomer());
    if (cartOrder == null) {
      cartOrder = createNewCartForCustomer(namedOrder.getCustomer());
    }
    List<OrderItem> items = new ArrayList<OrderItem>(namedOrder.getOrderItems());
    for (OrderItem item : items) {
      if (moveNamedOrderItems) {
        removeItem(namedOrder.getId(), item.getId(), false);
      }

      OrderItemRequestDTO orderItemRequest =
          orderItemService.buildOrderItemRequestDTOFromOrderItem(item);
      cartOrder = addItem(cartOrder.getId(), orderItemRequest, priceOrder);
    }

    if (deleteEmptyNamedOrders) {
      cancelOrder(namedOrder);
    }

    return cartOrder;
  }
  @Override
  @Transactional("blTransactionManager")
  public Order addItemFromNamedOrder(
      Order namedOrder, OrderItem item, int quantity, boolean priceOrder)
      throws RemoveFromCartException, AddToCartException, UpdateCartException {
    // Validate that the quantity requested makes sense
    if (quantity < 1 || quantity > item.getQuantity()) {
      throw new IllegalArgumentException("Cannot move 0 or less quantity");
    } else if (quantity == item.getQuantity()) {
      return addItemFromNamedOrder(namedOrder, item, priceOrder);
    }

    Order cartOrder = orderDao.readCartForCustomer(namedOrder.getCustomer());
    if (cartOrder == null) {
      cartOrder = createNewCartForCustomer(namedOrder.getCustomer());
    }

    if (moveNamedOrderItems) {
      // Update the old item to its new quantity only if we're moving items
      OrderItemRequestDTO orderItemRequestDTO = new OrderItemRequestDTO();
      orderItemRequestDTO.setOrderItemId(item.getId());
      orderItemRequestDTO.setQuantity(item.getQuantity() - quantity);
      updateItemQuantity(namedOrder.getId(), orderItemRequestDTO, false);
    }

    OrderItemRequestDTO orderItemRequest =
        orderItemService.buildOrderItemRequestDTOFromOrderItem(item);
    orderItemRequest.setQuantity(quantity);
    cartOrder = addItem(cartOrder.getId(), orderItemRequest, priceOrder);

    return cartOrder;
  }
  public Order setUpAnonymousCartWithBundleGiftWrap() throws PricingException {
    Customer customer = customerService.saveCustomer(createNamedCustomer());

    Order order = cartService.createNewCartForCustomer(customer);

    BundleOrderItemRequest itemRequest = createBundleOrderItemRequestWithGiftWrap();

    BundleOrderItem newBundle =
        (BundleOrderItem) orderService.addBundleItemToOrder(order, itemRequest);
    List<OrderItem> addedItems = new ArrayList<OrderItem>();
    GiftWrapOrderItem giftItem = null;
    for (DiscreteOrderItem addedItem : newBundle.getDiscreteOrderItems()) {
      if (addedItem instanceof GiftWrapOrderItem) {
        giftItem = (GiftWrapOrderItem) addedItem;
      } else {
        addedItems.add(addedItem);
      }
    }
    for (OrderItem addedItem : addedItems) {
      addedItem.setGiftWrapOrderItem(giftItem);
    }
    giftItem.getWrappedItems().addAll(addedItems);
    order = orderService.save(order, false);

    return order;
  }
 public Money calculateOrderItemsPriceWithoutAdjustments() {
   Money calculatedSubTotal = new Money();
   for (OrderItem orderItem : delegate.getOrderItems()) {
     Money price = orderItem.getPriceBeforeAdjustments(true);
     calculatedSubTotal = calculatedSubTotal.add(price.multiply(orderItem.getQuantity()));
   }
   return calculatedSubTotal;
 }
  public void removeAllCandidateOffers() {
    removeAllCandidateOrderOffers();
    for (OrderItem orderItem : getDelegate().getOrderItems()) {
      orderItem.removeAllCandidateItemOffers();
    }

    removeAllCandidateFulfillmentGroupOffers();
  }
 public void assignOrderItemsFinalPrice() {
   for (PromotableOrderItem orderItem : getDiscountableDiscreteOrderItems()) {
     orderItem.assignFinalPrice();
   }
   for (OrderItem orderItem : getDelegate().getOrderItems()) {
     if (orderItem instanceof BundleOrderItem) {
       orderItem.assignFinalPrice();
     }
   }
 }
 public void resetTotalitarianOfferApplied() {
   totalitarianOfferApplied = false;
   notCombinableOfferAppliedAtAnyLevel = false;
   for (OrderAdjustment adjustment : delegate.getOrderAdjustments()) {
     if (adjustment.getOffer().isTotalitarianOffer() != null
         && adjustment.getOffer().isTotalitarianOffer()) {
       totalitarianOfferApplied = true;
       break;
     }
     if (!adjustment.getOffer().isCombinableWithOtherOffers()) {
       notCombinableOfferAppliedAtAnyLevel = true;
       break;
     }
   }
   if (!totalitarianOfferApplied || !notCombinableOfferAppliedAtAnyLevel) {
     check:
     {
       for (OrderItem orderItem : delegate.getOrderItems()) {
         for (OrderItemAdjustment adjustment : orderItem.getOrderItemAdjustments()) {
           if (adjustment.getOffer().isTotalitarianOffer() != null
               && adjustment.getOffer().isTotalitarianOffer()) {
             totalitarianOfferApplied = true;
             break check;
           }
           if (!adjustment.getOffer().isCombinableWithOtherOffers()) {
             notCombinableOfferAppliedAtAnyLevel = true;
             break check;
           }
         }
       }
     }
   }
   if (!totalitarianOfferApplied || !notCombinableOfferAppliedAtAnyLevel) {
     check:
     {
       for (FulfillmentGroup fg : delegate.getFulfillmentGroups()) {
         for (FulfillmentGroupAdjustment adjustment : fg.getFulfillmentGroupAdjustments()) {
           if (adjustment.getOffer().isTotalitarianOffer() != null
               && adjustment.getOffer().isTotalitarianOffer()) {
             totalitarianOfferApplied = true;
             break check;
           }
           if (!adjustment.getOffer().isCombinableWithOtherOffers()) {
             notCombinableOfferAppliedAtAnyLevel = true;
             break check;
           }
         }
       }
     }
   }
 }
 @RequestMapping(
     value = "/viewCart.htm",
     params = "updateItemQuantity",
     method = RequestMethod.POST)
 public String updateItemQuantity(
     @ModelAttribute(value = "cartSummary") CartSummary cartSummary,
     Errors errors,
     ModelMap model,
     HttpServletRequest request)
     throws PricingException {
   if (errors.hasErrors()) {
     model.addAttribute("cartSummary", cartSummary);
     return cartView;
   }
   Order currentCartOrder = retrieveCartOrder(request, model);
   List<OrderItem> orderItems = currentCartOrder.getOrderItems();
   List<CartOrderItem> items = new ArrayList<CartOrderItem>(cartSummary.getRows());
   for (CartOrderItem cartOrderItem : items) {
     OrderItem orderItem =
         (OrderItem)
             CollectionUtils.find(
                 orderItems,
                 new BeanPropertyValueEqualsPredicate("id", cartOrderItem.getOrderItem().getId()));
     // in case the item was removed from the cart from another browser tab
     if (orderItem != null) {
       if (cartOrderItem.getQuantity() > 0) {
         orderItem.setQuantity(cartOrderItem.getQuantity());
         try {
           cartService.updateItemQuantity(currentCartOrder, orderItem);
         } catch (ItemNotFoundException e) {
           LOG.error("Item not found in order: (" + orderItem.getId() + ")", e);
         } catch (PricingException e) {
           LOG.error("Unable to price the order: (" + currentCartOrder.getId() + ")", e);
         }
       } else {
         try {
           cartService.removeItemFromOrder(currentCartOrder, orderItem);
           cartSummary.getRows().remove(cartOrderItem);
         } catch (Exception e) {
           // TODO: handle exception gracefully
           LOG.error("Unable to remove item from the order: (" + currentCartOrder.getId() + ")");
         }
       }
     }
   }
   cartSummary.setOrderDiscounts(currentCartOrder.getTotalAdjustmentsValue().getAmount());
   return cartView;
 }
 public void removeAllItemAdjustments() {
   for (OrderItem orderItem : getDelegate().getOrderItems()) {
     orderItem.removeAllAdjustments();
     adjustmentPrice = null;
     resetTotalitarianOfferApplied();
     if (orderItem instanceof BundleOrderItem) {
       for (DiscreteOrderItem discreteOrderItem :
           ((BundleOrderItem) orderItem).getDiscreteOrderItems()) {
         discreteOrderItem.setPrice(null);
       }
     }
     orderItem.setPrice(null);
     orderItem.assignFinalPrice();
   }
   splitItems.clear();
 }
  @Override
  @Transactional(
      value = "blTransactionManager",
      rollbackFor = {RemoveFromCartException.class})
  public Order removeInactiveItems(Long orderId, boolean priceOrder)
      throws RemoveFromCartException {
    Order order = findOrderById(orderId);
    try {

      for (OrderItem currentItem : new ArrayList<OrderItem>(order.getOrderItems())) {
        if (!currentItem.isSkuActive()) {
          removeItem(orderId, currentItem.getId(), priceOrder);
        }
      }

    } catch (Exception e) {
      throw new RemoveFromCartException("Could not remove from cart", e.getCause());
    }
    return findOrderById(orderId);
  }
  public Order setUpAnonymousCartWithInactiveBundleGiftWrap() throws PricingException {
    Customer customer = customerService.saveCustomer(createNamedCustomer());

    Order order = cartService.createNewCartForCustomer(customer);

    Sku newSku = addTestSku("Small Plastic Crate", "Plastic Crate", "Crates");
    Sku newInactiveSku = addTestSku("Small Red Plastic Crate", "Plastic Crate", "Crates", false);
    Sku giftWrapSku = addTestSku("Gift Box", "Gift Box", "Gift Wraps");
    Category category = newSku.getAllParentProducts().get(0).getDefaultCategory();

    List<DiscreteOrderItemRequest> discreteOrderItems = new ArrayList<DiscreteOrderItemRequest>();
    discreteOrderItems.add(createDiscreteOrderItemRequest(newSku, 1));
    discreteOrderItems.add(createDiscreteOrderItemRequest(newInactiveSku, 1));
    discreteOrderItems.add(
        createGiftWrapOrderItemRequest(giftWrapSku, 1, new ArrayList<OrderItem>()));

    BundleOrderItemRequest itemRequest = new BundleOrderItemRequest();
    itemRequest.setCategory(category);
    itemRequest.setName("test bundle " + bundleCount++);
    itemRequest.setQuantity(1);
    itemRequest.setDiscreteOrderItems(discreteOrderItems);

    BundleOrderItem newBundle =
        (BundleOrderItem) orderService.addBundleItemToOrder(order, itemRequest);
    List<OrderItem> addedItems = new ArrayList<OrderItem>();
    GiftWrapOrderItem giftItem = null;
    for (DiscreteOrderItem addedItem : newBundle.getDiscreteOrderItems()) {
      if (addedItem instanceof GiftWrapOrderItem) {
        giftItem = (GiftWrapOrderItem) addedItem;
      } else {
        addedItems.add(addedItem);
      }
    }
    for (OrderItem addedItem : addedItems) {
      addedItem.setGiftWrapOrderItem(giftItem);
    }
    giftItem.getWrappedItems().addAll(addedItems);
    order = orderService.save(order, false);

    return order;
  }
  public Order setUpAnonymousCartWithBundleGiftWrapReferringToRootItems() throws PricingException {
    Customer customer = customerService.saveCustomer(createNamedCustomer());

    Order order = cartService.createNewCartForCustomer(customer);

    Sku newSku = addTestSku("Small Plastic Bowl", "Plastic Bowl", "Bowls");
    Sku newActiveSku = addTestSku("Small Red Plastic Bowl", "Plastic Bowl", "Bowls");

    Product newProduct = newSku.getAllParentProducts().get(0);
    Category newCategory = newProduct.getDefaultCategory();

    List<OrderItem> addedItems = new ArrayList<OrderItem>();
    addedItems.add(
        orderService.addSkuToOrder(
            order.getId(), newSku.getId(), newProduct.getId(), newCategory.getId(), 2));
    addedItems.add(
        orderService.addSkuToOrder(
            order.getId(), newActiveSku.getId(), newProduct.getId(), newCategory.getId(), 2));

    BundleOrderItem newBundle =
        (BundleOrderItem)
            orderService.addBundleItemToOrder(order, createBundleOrderItemRequestWithGiftWrap());
    GiftWrapOrderItem giftItem = null;
    for (DiscreteOrderItem addedItem : newBundle.getDiscreteOrderItems()) {
      if (addedItem instanceof GiftWrapOrderItem) {
        giftItem = (GiftWrapOrderItem) addedItem;
      }
    }
    for (OrderItem addedItem : addedItems) {
      addedItem.setGiftWrapOrderItem(giftItem);
    }
    giftItem.getWrappedItems().addAll(addedItems);
    order = orderService.save(order, false);

    return order;
  }
  @Override
  public void printOrder(Order order, Log log) {
    if (!log.isDebugEnabled()) {
      return;
    }

    TableCreator tc =
        new TableCreator(
            new TableCreator.Col[] {
              new TableCreator.Col("Order Item", 30),
              new TableCreator.Col("Qty"),
              new TableCreator.Col("Unit Price"),
              new TableCreator.Col("Avg Adj"),
              new TableCreator.Col("Total Adj"),
              new TableCreator.Col("Total Price")
            });

    for (OrderItem oi : order.getOrderItems()) {
      tc.addRow(
          new String[] {
            oi.getName(),
            String.valueOf(oi.getQuantity()),
            String.valueOf(oi.getPriceBeforeAdjustments(true)),
            String.valueOf(oi.getAverageAdjustmentValue()),
            String.valueOf(oi.getTotalAdjustmentValue()),
            String.valueOf(oi.getTotalPrice())
          });
    }

    tc.addSeparator()
        .withGlobalRowHeaderWidth(15)
        .addRow("Subtotal", order.getSubTotal())
        .addRow("Order Adj.", order.getOrderAdjustmentsValue())
        .addRow("Tax", order.getTotalTax())
        .addRow("Shipping", order.getTotalShipping())
        .addRow("Total", order.getTotal())
        .addSeparator();

    log.debug(tc.toString());
  }
  @RequestMapping(value = "/viewCart.htm", method = RequestMethod.GET)
  public String viewCart(ModelMap model, HttpServletRequest request) throws PricingException {
    Order cart = retrieveCartOrder(request, model);
    CartSummary cartSummary = new CartSummary();

    if (cart.getOrderItems() != null) {
      for (OrderItem orderItem : cart.getOrderItems()) {
        if (orderItem instanceof DiscreteOrderItem) {
          Sku sku = catalogService.findSkuById(((DiscreteOrderItem) orderItem).getSku().getId());
          if (!(sku.getSalePrice().equals(((DiscreteOrderItem) orderItem).getSalePrice()))) {
            orderItem.setSalePrice(sku.getSalePrice());
          }
          if (!(sku.getRetailPrice().equals(((DiscreteOrderItem) orderItem).getRetailPrice()))) {
            orderItem.setRetailPrice(sku.getRetailPrice());
          }

          if (orderItem.getSalePrice() != orderItem.getRetailPrice()) {
            orderItem.setPrice(orderItem.getSalePrice());
          } else {
            orderItem.setPrice(orderItem.getRetailPrice());
          }

          orderItem.getPrice();
        }
      }
    }

    if (cart.getOrderItems() != null) {
      for (OrderItem orderItem : cart.getOrderItems()) {
        CartOrderItem cartOrderItem = new CartOrderItem();
        cartOrderItem.setOrderItem(orderItem);
        cartOrderItem.setQuantity(orderItem.getQuantity());
        cartSummary.getRows().add(cartOrderItem);
      }
    }

    if ((cart.getFulfillmentGroups() != null) && (cart.getFulfillmentGroups().isEmpty() == false)) {
      String cartShippingMethod = cart.getFulfillmentGroups().get(0).getMethod();
      String cartShippingService = cart.getFulfillmentGroups().get(0).getService();

      if (cartShippingMethod != null) {
        if (cartShippingMethod.equals("standard")) {
          cartSummary = createFulfillmentGroup(cartSummary, "standard", cartShippingService, cart);
        } else if (cartShippingMethod.equals("expedited")) {
          cartSummary = createFulfillmentGroup(cartSummary, "expedited", cartShippingService, cart);
        }
      }
    }

    updateFulfillmentGroups(cartSummary, cart);
    cartSummary.setOrderDiscounts(cart.getTotalAdjustmentsValue().getAmount());
    model.addAttribute("cartSummary", cartSummary);
    return cartViewRedirect ? "redirect:" + cartView : cartView;
  }
  public List<PromotableOrderItem> getDiscreteOrderItems() {
    if (discreteOrderItems == null) {
      discreteOrderItems = new ArrayList<PromotableOrderItem>();
      OrderItemVisitor visitor =
          new OrderItemVisitorAdapter() {

            @Override
            public void visit(BundleOrderItem bundleOrderItem) throws PricingException {
              for (DiscreteOrderItem discreteOrderItem : bundleOrderItem.getDiscreteOrderItems()) {
                addDiscreteItem(discreteOrderItem);
              }
            }

            @Override
            public void visit(DiscreteOrderItem discreteOrderItem) throws PricingException {
              addDiscreteItem(discreteOrderItem);
            }

            @Override
            public void visit(DynamicPriceDiscreteOrderItem dynamicPriceDiscreteOrderItem)
                throws PricingException {
              addDiscreteItem(dynamicPriceDiscreteOrderItem);
            }

            @Override
            public void visit(GiftWrapOrderItem giftWrapOrderItem) throws PricingException {
              addDiscreteItem(giftWrapOrderItem);
            }

            private void addDiscreteItem(DiscreteOrderItem discreteOrderItem) {
              PromotableOrderItem item =
                  itemFactory.createPromotableOrderItem(
                      discreteOrderItem, PromotableOrderImpl.this);
              item.computeAdjustmentPrice();
              discreteOrderItems.add(item);
            }
          };
      // filter out the original bundle order items and replace with the split bundles
      List<OrderItem> basicOrderItems = new ArrayList<OrderItem>();
      basicOrderItems.addAll(delegate.getOrderItems());
      Iterator<OrderItem> itr = basicOrderItems.iterator();
      while (itr.hasNext()) {
        OrderItem temp = itr.next();
        if (temp instanceof BundleOrderItem) {
          itr.remove();
        }
      }
      for (BundleOrderItemSplitContainer container : bundleSplitItems) {
        basicOrderItems.addAll(container.getSplitItems());
      }
      try {
        for (OrderItem temp : basicOrderItems) {
          temp.accept(visitor);
        }
      } catch (PricingException e) {
        throw new RuntimeException(e);
      }
    }

    return discreteOrderItems;
  }