protected int applyLegacyAdjustments( int appliedItemOffersCount, PromotableCandidateItemOffer itemOffer, int beforeCount, PromotableOrderItem orderItem) { // legacy promotion if (!orderItem.isNotCombinableOfferApplied()) { if ((itemOffer.getOffer().isCombinableWithOtherOffers() && itemOffer.getOffer().isStackable()) || !orderItem.isHasOrderItemAdjustments()) { applyOrderItemAdjustment(itemOffer, orderItem); appliedItemOffersCount++; } } // check if not combinable offer is better than sale price; if no, remove the not combinable // offer so // that another offer may be applied to the item if (!itemOffer.getOffer().isCombinableWithOtherOffers() && appliedItemOffersCount > beforeCount) { Money adjustmentTotal = new Money(0D); Money saleTotal = new Money(0D); adjustmentTotal = adjustmentTotal.add(orderItem.getCurrentPrice().multiply(orderItem.getQuantity())); saleTotal = saleTotal.add( orderItem.getPriceBeforeAdjustments(true).multiply(orderItem.getQuantity())); if (adjustmentTotal.greaterThanOrEqual(saleTotal)) { // adjustment price is not best price, remove adjustments for this item orderItem.removeAllAdjustments(); appliedItemOffersCount--; } } return appliedItemOffersCount; }
/** * Private method used by applyAllItemOffers to create an OrderItemAdjustment from a * CandidateItemOffer and associates the OrderItemAdjustment to the OrderItem. * * @param itemOffer a CandidateItemOffer to apply to an OrderItem */ protected void applyOrderItemAdjustment( PromotableCandidateItemOffer itemOffer, PromotableOrderItem orderItem) { OrderItemAdjustment itemAdjustment = offerDao.createOrderItemAdjustment(); itemAdjustment.init( orderItem.getDelegate(), itemOffer.getOffer(), itemOffer.getOffer().getName()); // add to adjustment PromotableOrderItemAdjustment promotableOrderItemAdjustment = promotableItemFactory.createPromotableOrderItemAdjustment(itemAdjustment, orderItem); orderItem.addOrderItemAdjustment( promotableOrderItemAdjustment); // This is how we can tell if an item has been discounted }
protected void applyItemQualifiersAndTargets( PromotableCandidateItemOffer itemOffer, PromotableOrder order) { Offer promotion = itemOffer.getOffer(); OrderItemPriceComparator priceComparator = new OrderItemPriceComparator(promotion.getApplyDiscountToSalePrice()); boolean matchFound = false; do { matchFound = false; int totalQualifiersNeeded = 0; for (OfferItemCriteria itemCriteria : itemOffer.getCandidateQualifiersMap().keySet()) { totalQualifiersNeeded += itemCriteria.getQuantity(); } int receiveQtyNeeded = promotion.getTargetItemCriteria().getQuantity(); checkAll: { for (OfferItemCriteria itemCriteria : itemOffer.getCandidateQualifiersMap().keySet()) { List<PromotableOrderItem> chargeableItems = itemOffer.getCandidateQualifiersMap().get(itemCriteria); // Sort the items so that the highest priced ones are at the top Collections.sort(chargeableItems, priceComparator); // Calculate the number of qualifiers needed that will not receive the promotion. // These will be reserved first before the target is assigned. int qualifierQtyNeeded = itemCriteria.getQuantity(); for (PromotableOrderItem chargeableItem : chargeableItems) { // Mark Qualifiers if (qualifierQtyNeeded > 0) { int itemQtyAvailableToBeUsedAsQualifier = chargeableItem.getQuantityAvailableToBeUsedAsQualifier(promotion); if (itemQtyAvailableToBeUsedAsQualifier > 0) { int qtyToMarkAsQualifier = Math.min(qualifierQtyNeeded, itemQtyAvailableToBeUsedAsQualifier); qualifierQtyNeeded -= qtyToMarkAsQualifier; chargeableItem.addPromotionQualifier(itemOffer, itemCriteria, qtyToMarkAsQualifier); } } if (qualifierQtyNeeded == 0) { totalQualifiersNeeded -= itemCriteria.getQuantity(); break; } } if (qualifierQtyNeeded != 0) { break checkAll; } } checkTargets: { List<PromotableOrderItem> chargeableItems = itemOffer.getCandidateTargets(); Collections.sort(chargeableItems, priceComparator); for (PromotableOrderItem chargeableItem : chargeableItems) { // Mark Targets if (receiveQtyNeeded > 0) { int itemQtyAvailableToBeUsedAsTarget = chargeableItem.getQuantityAvailableToBeUsedAsTarget(promotion); if (itemQtyAvailableToBeUsedAsTarget > 0) { if (promotion.getMaxUses() == 0 || itemOffer.getUses() < promotion.getMaxUses()) { int qtyToMarkAsTarget = Math.min(receiveQtyNeeded, itemQtyAvailableToBeUsedAsTarget); receiveQtyNeeded -= qtyToMarkAsTarget; // atLeastOneCriteriaMatched = true; chargeableItem.addPromotionDiscount( itemOffer, itemOffer.getOffer().getTargetItemCriteria(), qtyToMarkAsTarget); } } } if (receiveQtyNeeded == 0) { break checkTargets; } } } } boolean criteriaMatched = true; if (receiveQtyNeeded != 0 || totalQualifiersNeeded != 0) { // This ItemCriteria did not match. Therefore, we need to clear all non-finalized // quantities. for (OfferItemCriteria itemCriteria : itemOffer.getCandidateQualifiersMap().keySet()) { List<PromotableOrderItem> chargeableItems = itemOffer.getCandidateQualifiersMap().get(itemCriteria); clearAllNonFinalizedQuantities(chargeableItems); } clearAllNonFinalizedQuantities(itemOffer.getCandidateTargets()); criteriaMatched = false; } if (criteriaMatched) { matchFound = true; finalizeQuantities(order.getDiscountableDiscreteOrderItems()); } // This promotion may be able to be applied multiple times if there is enough // product quantity in the order. Continue to loop through the order until // there are no more matches } while (matchFound); if (order.getSplitItems().size() == 0) { initializeSplitItems(order, order.getDiscountableDiscreteOrderItems()); } List<PromotableOrderItem> allSplitItems = order.getAllSplitItems(); for (PromotableOrderItem chargeableItem : allSplitItems) { if (itemOffer.getCandidateTargets().contains(chargeableItem)) { List<PromotableOrderItem> splitItems = chargeableItem.split(); if (splitItems != null && splitItems.size() > 0) { // Remove this item from the list List<PromotableOrderItem> temp = order.searchSplitItems(chargeableItem); if (!CollectionUtils.isEmpty(temp)) { temp.remove(chargeableItem); temp.addAll(splitItems); } } } } }
protected int applyAdjustments( PromotableOrder order, int appliedItemOffersCount, PromotableCandidateItemOffer itemOffer, int beforeCount) { boolean notCombinableOfferApplied = false; boolean offerApplied = false; List<PromotableOrderItem> allSplitItems = order.getAllSplitItems(); for (PromotableOrderItem targetItem : allSplitItems) { notCombinableOfferApplied = targetItem.isNotCombinableOfferApplied(); if (!offerApplied) { offerApplied = targetItem.isHasOrderItemAdjustments(); } if (notCombinableOfferApplied) { break; } } if (!notCombinableOfferApplied && (((itemOffer.getOffer().isCombinableWithOtherOffers() || itemOffer.getOffer().isTotalitarianOffer() == null || !itemOffer.getOffer().isTotalitarianOffer()) // && itemOffer.getOffer().isStackable() ) || !offerApplied)) { // At this point, we should not have any official adjustment on the order // for this item. applyItemQualifiersAndTargets(itemOffer, order); allSplitItems = order.getAllSplitItems(); for (PromotableOrderItem splitItem : allSplitItems) { for (PromotionDiscount discount : splitItem.getPromotionDiscounts()) { if (discount.getPromotion().equals(itemOffer.getOffer())) { applyOrderItemAdjustment(itemOffer, splitItem); appliedItemOffersCount++; break; } } } } // check if not combinable offer is better than sale price; if no, remove the not combinable // offer so // that another offer may be applied to the item if ((!itemOffer.getOffer().isCombinableWithOtherOffers() || (itemOffer.getOffer().isTotalitarianOffer() != null && itemOffer.getOffer().isTotalitarianOffer())) && appliedItemOffersCount > beforeCount) { Money adjustmentTotal = new Money(0D); Money saleTotal = new Money(0D); for (PromotableOrderItem splitItem : allSplitItems) { adjustmentTotal = adjustmentTotal.add(splitItem.getCurrentPrice().multiply(splitItem.getQuantity())); saleTotal = saleTotal.add( splitItem.getPriceBeforeAdjustments(true).multiply(splitItem.getQuantity())); } if (adjustmentTotal.greaterThanOrEqual(saleTotal)) { // adjustment price is not best price, remove adjustments for this item for (PromotableOrderItem splitItem : allSplitItems) { if (splitItem.isHasOrderItemAdjustments()) { appliedItemOffersCount--; } } order.getSplitItems().clear(); } } return appliedItemOffersCount; }