public List<PromotableOrderItem> getDiscountableDiscreteOrderItems(
      boolean applyDiscountToSalePrice) {
    if (discountableDiscreteOrderItems == null) {
      discountableDiscreteOrderItems = new ArrayList<PromotableOrderItem>();
      for (PromotableOrderItem orderItem : getDiscreteOrderItems()) {
        if (orderItem.getSku().isDiscountable() == null || orderItem.getSku().isDiscountable()) {
          discountableDiscreteOrderItems.add((PromotableOrderItem) orderItem);
        }
      }

      OrderItemPriceComparator priceComparator =
          new OrderItemPriceComparator(applyDiscountToSalePrice);
      // Sort the items so that the highest priced ones are at the top
      Collections.sort(discountableDiscreteOrderItems, priceComparator);

      currentSortParam = applyDiscountToSalePrice;
    }

    if (currentSortParam != applyDiscountToSalePrice) {
      OrderItemPriceComparator priceComparator =
          new OrderItemPriceComparator(applyDiscountToSalePrice);
      // Sort the items so that the highest priced ones are at the top
      Collections.sort(discountableDiscreteOrderItems, priceComparator);

      currentSortParam = applyDiscountToSalePrice;
    }

    return discountableDiscreteOrderItems;
  }
 public Money calculateOrderItemsCurrentPrice() {
   Money calculatedSubTotal = new Money();
   for (PromotableOrderItem orderItem : getDiscountableDiscreteOrderItems()) {
     Money currentPrice = orderItem.getCurrentPrice();
     calculatedSubTotal = calculatedSubTotal.add(currentPrice.multiply(orderItem.getQuantity()));
   }
   return calculatedSubTotal;
 }
 public void assignOrderItemsFinalPrice() {
   for (PromotableOrderItem orderItem : getDiscountableDiscreteOrderItems()) {
     orderItem.assignFinalPrice();
   }
   for (OrderItem orderItem : getDelegate().getOrderItems()) {
     if (orderItem instanceof BundleOrderItem) {
       orderItem.assignFinalPrice();
     }
   }
 }
  public int calculateMaxUsesForItemCriteria(OfferItemCriteria itemCriteria, Offer promotion) {
    int numberOfTargets = 0;
    int numberOfUsesForThisItemCriteria = 9999;

    if (candidateTargets != null && itemCriteria != null) {
      for (PromotableOrderItem potentialTarget : candidateTargets) {
        numberOfTargets += potentialTarget.getQuantityAvailableToBeUsedAsTarget(promotion);
      }
      numberOfUsesForThisItemCriteria = numberOfTargets / itemCriteria.getQuantity();
    }

    return numberOfUsesForThisItemCriteria;
  }
 public void resetDiscreteOrderItems() {
   if (discreteOrderItems != null) {
     for (PromotableOrderItem orderItem : discreteOrderItems) {
       orderItem.reset();
     }
     discreteOrderItems = null;
   }
   if (discountableDiscreteOrderItems != null) {
     for (PromotableOrderItem orderItem : discountableDiscreteOrderItems) {
       orderItem.reset();
     }
     discountableDiscreteOrderItems = null;
   }
 }
  /**
   * This method determines how much the customer might save using this promotion for the purpose of
   * sorting promotions with the same priority. The assumption is that any possible target specified
   * for BOGO style offers are of equal or lesser value. We are using a calculation based on the
   * qualifiers here strictly for rough comparative purposes.
   *
   * <p>If two promotions have the same priority, the one with the highest potential savings will be
   * used as the tie-breaker to determine the order to apply promotions.
   *
   * <p>This method makes a good approximation of the promotion value as determining the exact value
   * would require all permutations of promotions to be run resulting in a costly operation.
   *
   * @return
   */
  public Money calculatePotentialSavings() {
    Money savings = new Money(0);
    int maxUses = calculateMaximumNumberOfUses();
    int appliedCount = 0;

    for (PromotableOrderItem chgItem : candidateTargets) {
      int qtyToReceiveSavings = Math.min(chgItem.getQuantity(), maxUses);
      savings = calculateSavingsForOrderItem(chgItem, qtyToReceiveSavings);

      appliedCount = appliedCount + qtyToReceiveSavings;
      if (appliedCount >= maxUses) {
        return savings;
      }
    }

    return savings;
  }
 public List<PromotableOrderItem> searchSplitItems(PromotableOrderItem key) {
   for (OrderItemSplitContainer container : splitItems) {
     if (container.getKey().equals(key.getDelegate())) {
       return container.getSplitItems();
     }
   }
   return null;
 }
 public Money calculateSavingsForOrderItem(
     PromotableOrderItem orderItem, int qtyToReceiveSavings) {
   Money savings = new Money(0);
   Money salesPrice =
       orderItem.getPriceBeforeAdjustments(getOffer().getApplyDiscountToSalePrice());
   if (getOffer().getDiscountType().equals(OfferDiscountType.AMOUNT_OFF)) {
     // Price reduction by a fixed amount
     savings = savings.add(new Money(getOffer().getValue()).multiply(qtyToReceiveSavings));
   } else if (getOffer().getDiscountType().equals(OfferDiscountType.PERCENT_OFF)) {
     // Price reduction by a percent off
     BigDecimal savingsPercent = getOffer().getValue().divide(new BigDecimal(100));
     savings = savings.add(salesPrice.multiply(savingsPercent).multiply(qtyToReceiveSavings));
   } else {
     // Different price (presumably less than the normal price)
     savings =
         savings.add(
             salesPrice
                 .multiply(qtyToReceiveSavings)
                 .subtract(new Money(getOffer().getValue()).multiply(qtyToReceiveSavings)));
   }
   return savings;
 }