use of org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateItemOffer in project BroadleafCommerce by BroadleafCommerce.
the class ItemOfferProcessorTest method testApplyAllItemOffers.
public void testApplyAllItemOffers() throws Exception {
replay();
Order order = dataProvider.createBasicOrder();
Offer offer1 = dataProvider.createItemBasedOfferWithItemCriteria("order.subTotal.getAmount()>20", OfferDiscountType.PERCENT_OFF, "([MVEL.eval(\"toUpperCase()\",\"test1\"), MVEL.eval(\"toUpperCase()\",\"test2\")] contains MVEL.eval(\"toUpperCase()\", discreteOrderItem.category.name))", "([MVEL.eval(\"toUpperCase()\",\"test1\"), MVEL.eval(\"toUpperCase()\",\"test2\")] contains MVEL.eval(\"toUpperCase()\", discreteOrderItem.category.name))").get(0);
offer1.setId(1L);
List<Offer> offers = new ArrayList<Offer>();
offers.add(offer1);
List<PromotableCandidateItemOffer> qualifiedOffers = new ArrayList<PromotableCandidateItemOffer>();
order.updatePrices();
offerService.applyAndSaveOffersToOrder(offers, order);
assertTrue(order.getTotalAdjustmentsValue().getAmount().doubleValue() > 0);
order = dataProvider.createBasicOrder();
qualifiedOffers = new ArrayList<PromotableCandidateItemOffer>();
offer1.setApplyDiscountToSalePrice(false);
((DiscreteOrderItem) order.getOrderItems().get(0)).getSku().setSalePrice(new Money(1D));
((DiscreteOrderItem) order.getOrderItems().get(1)).getSku().setSalePrice(new Money(1D));
order.updatePrices();
offerService.applyAndSaveOffersToOrder(offers, order);
assertTrue(order.getTotalAdjustmentsValue().getAmount().doubleValue() == 0);
verify();
}
use of org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateItemOffer in project BroadleafCommerce by BroadleafCommerce.
the class ItemOfferProcessorImpl method calculatePotentialSavings.
/**
* This method determines the potential savings for each item offer as if it was the only item offer being applied.
* @param itemOffers
* @param order
*/
protected void calculatePotentialSavings(List<PromotableCandidateItemOffer> itemOffers, PromotableOrder order) {
if (itemOffers.size() > 1) {
for (PromotableCandidateItemOffer itemOffer : itemOffers) {
Money potentialSavings = new Money(order.getOrderCurrency());
Offer offer = itemOffer.getOffer();
BigDecimal calculatedWeightedPercent = new BigDecimal(0);
markQualifiersAndTargets(order, itemOffer);
for (PromotableOrderItemPriceDetail detail : order.getAllPromotableOrderItemPriceDetails()) {
PromotableOrderItem item = detail.getPromotableOrderItem();
for (PromotionDiscount discount : detail.getPromotionDiscounts()) {
Money itemSavings = calculatePotentialSavingsForOrderItem(itemOffer, item, discount.getQuantity());
potentialSavings = potentialSavings.add(itemSavings);
if (useCalculatePercent(offer)) {
BigDecimal discountPercent = calculatePercent(item.calculateTotalWithoutAdjustments(), itemSavings);
calculatedWeightedPercent = calculatedWeightedPercent.add(discountPercent);
} else if (hasQualifierAndQualifierRestricted(offer)) {
BigDecimal discountPercent = calculateWeightedPercent(discount, item, itemSavings);
calculatedWeightedPercent = calculatedWeightedPercent.add(discountPercent);
}
}
// Reset state back for next offer
detail.getPromotionDiscounts().clear();
detail.getPromotionQualifiers().clear();
}
itemOffer.setPotentialSavings(potentialSavings);
if (usePercentOffValue(offer)) {
itemOffer.setWeightedPercentSaved(offer.getValue());
} else if (useCalculatePercent(offer) || hasQualifierAndQualifierRestricted(offer)) {
itemOffer.setWeightedPercentSaved(calculatedWeightedPercent);
}
if (itemOffer.getUses() == 0) {
itemOffer.setPotentialSavingsQtyOne(potentialSavings);
} else {
itemOffer.setPotentialSavingsQtyOne(potentialSavings.divide(itemOffer.getUses()));
}
}
}
}
use of org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateItemOffer in project BroadleafCommerce by BroadleafCommerce.
the class ItemOfferProcessorImpl method removeTotalitarianAndNonCombinableOffers.
protected void removeTotalitarianAndNonCombinableOffers(List<PromotableCandidateItemOffer> offers, List<List<PromotableCandidateItemOffer>> listOfOfferLists) {
List<PromotableCandidateItemOffer> listWithoutTotalitarianOrNonCombinables = new ArrayList<PromotableCandidateItemOffer>(offers);
Iterator<PromotableCandidateItemOffer> offerIterator = listWithoutTotalitarianOrNonCombinables.iterator();
while (offerIterator.hasNext()) {
PromotableCandidateItemOffer offer = offerIterator.next();
if (offer.getOffer().isTotalitarianOffer() || !offer.getOffer().isCombinableWithOtherOffers()) {
offerIterator.remove();
}
}
if (listWithoutTotalitarianOrNonCombinables.size() > 0) {
listOfOfferLists.add(listWithoutTotalitarianOrNonCombinables);
}
}
use of org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateItemOffer in project BroadleafCommerce by BroadleafCommerce.
the class ItemOfferProcessorImpl method applyAndCompareOrderAndItemOffers.
@Override
@SuppressWarnings("unchecked")
public void applyAndCompareOrderAndItemOffers(PromotableOrder order, List<PromotableCandidateOrderOffer> qualifiedOrderOffers, List<PromotableCandidateItemOffer> qualifiedItemOffers) {
if (!qualifiedItemOffers.isEmpty()) {
calculatePotentialSavings(qualifiedItemOffers, order);
// the actual application of those offers. Thus the uses for each item offer needs to be reset
for (PromotableCandidateItemOffer itemOffer : qualifiedItemOffers) {
itemOffer.resetUses();
}
// Sort order item offers by priority and potential total discount
Collections.sort(qualifiedItemOffers, ItemOfferComparator.INSTANCE);
if (qualifiedItemOffers.size() > 1) {
qualifiedItemOffers = determineBestPermutation(qualifiedItemOffers, order);
}
applyAllItemOffers(qualifiedItemOffers, order);
}
chooseSaleOrRetailAdjustments(order);
if (extensionManager != null) {
extensionManager.chooseSaleOrRetailAdjustments(order);
}
order.setOrderSubTotalToPriceWithAdjustments();
if (!qualifiedOrderOffers.isEmpty()) {
// Sort order offers by priority and discount
Collections.sort(qualifiedOrderOffers, OrderOfferComparator.INSTANCE);
applyAllOrderOffers(qualifiedOrderOffers, order);
}
order.setOrderSubTotalToPriceWithAdjustments();
// pull it out and reapply.
if (!qualifiedOrderOffers.isEmpty() && !qualifiedItemOffers.isEmpty()) {
List<PromotableCandidateOrderOffer> finalQualifiedOrderOffers = new ArrayList<PromotableCandidateOrderOffer>();
order.removeAllCandidateOrderOfferAdjustments();
for (PromotableCandidateOrderOffer candidateOrderOffer : qualifiedOrderOffers) {
/*
* Note - there is an edge case possibility where this logic would miss an order promotion
* that had a subtotal requirement that was missed because of item deductions, but without
* the item deductions, the order promotion would have been included and ended up giving the
* customer a better deal than the item deductions.
*/
if (couldOfferApplyToOrder(candidateOrderOffer.getOffer(), order)) {
finalQualifiedOrderOffers.add(candidateOrderOffer);
}
}
// Sort order offers by priority and discount
Collections.sort(finalQualifiedOrderOffers, OrderOfferComparator.INSTANCE);
if (!finalQualifiedOrderOffers.isEmpty()) {
applyAllOrderOffers(finalQualifiedOrderOffers, order);
order.setOrderSubTotalToPriceWithAdjustments();
}
}
}
use of org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateItemOffer in project BroadleafCommerce by BroadleafCommerce.
the class ItemOfferProcessorImpl method filterItemLevelOffer.
/* (non-Javadoc)
* @see org.broadleafcommerce.core.offer.service.processor.ItemOfferProcessor#filterItemLevelOffer(org.broadleafcommerce.core.order.domain.Order, java.util.List, java.util.List, org.broadleafcommerce.core.offer.domain.Offer)
*/
@Override
public void filterItemLevelOffer(PromotableOrder order, List<PromotableCandidateItemOffer> qualifiedItemOffers, Offer offer) {
boolean isNewFormat = CollectionUtils.isNotEmpty(offer.getQualifyingItemCriteriaXref()) || CollectionUtils.isNotEmpty(offer.getTargetItemCriteriaXref());
boolean itemLevelQualification = false;
boolean offerCreated = false;
for (PromotableOrderItem promotableOrderItem : order.getDiscountableOrderItems()) {
if (couldOfferApplyToOrder(offer, order, promotableOrderItem)) {
if (!isNewFormat) {
// support legacy offers
PromotableCandidateItemOffer candidate = createCandidateItemOffer(qualifiedItemOffers, offer, order);
if (!candidate.getLegacyCandidateTargets().contains(promotableOrderItem)) {
candidate.getLegacyCandidateTargets().add(promotableOrderItem);
}
offerCreated = true;
continue;
}
itemLevelQualification = true;
break;
}
for (PromotableFulfillmentGroup fulfillmentGroup : order.getFulfillmentGroups()) {
if (couldOfferApplyToOrder(offer, order, promotableOrderItem, fulfillmentGroup)) {
if (!isNewFormat) {
// support legacy offers
PromotableCandidateItemOffer candidate = createCandidateItemOffer(qualifiedItemOffers, offer, order);
if (!candidate.getLegacyCandidateTargets().contains(promotableOrderItem)) {
candidate.getLegacyCandidateTargets().add(promotableOrderItem);
}
offerCreated = true;
continue;
}
itemLevelQualification = true;
break;
}
}
}
// Item Qualification - new for 1.5!
if (itemLevelQualification && !offerCreated) {
CandidatePromotionItems candidates = couldOfferApplyToOrderItems(offer, order.getDiscountableOrderItems(offer.getApplyDiscountToSalePrice()));
PromotableCandidateItemOffer candidateOffer = null;
if (candidates.isMatchedQualifier()) {
// we don't know the final target yet, so put null for the order item for now
candidateOffer = createCandidateItemOffer(qualifiedItemOffers, offer, order);
candidateOffer.getCandidateQualifiersMap().putAll(candidates.getCandidateQualifiersMap());
}
if (candidates.isMatchedTarget() && candidates.isMatchedQualifier()) {
if (candidateOffer == null) {
// we don't know the final target yet, so put null for the order item for now
candidateOffer = createCandidateItemOffer(qualifiedItemOffers, offer, order);
}
candidateOffer.getCandidateTargetsMap().putAll(candidates.getCandidateTargetsMap());
}
}
}
Aggregations