Search in sources :

Example 1 with PromotableCandidateItemOffer

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();
}
Also used : PromotableOrder(org.broadleafcommerce.core.offer.service.discount.domain.PromotableOrder) Order(org.broadleafcommerce.core.order.domain.Order) Money(org.broadleafcommerce.common.money.Money) PromotableCandidateItemOffer(org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateItemOffer) CandidateItemOffer(org.broadleafcommerce.core.offer.domain.CandidateItemOffer) Offer(org.broadleafcommerce.core.offer.domain.Offer) PromotableCandidateItemOffer(org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateItemOffer) ArrayList(java.util.ArrayList)

Example 2 with PromotableCandidateItemOffer

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()));
            }
        }
    }
}
Also used : Money(org.broadleafcommerce.common.money.Money) PromotableCandidateItemOffer(org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateItemOffer) PromotableCandidateItemOffer(org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateItemOffer) PromotableCandidateOrderOffer(org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateOrderOffer) Offer(org.broadleafcommerce.core.offer.domain.Offer) BigDecimal(java.math.BigDecimal) PromotableOrderItem(org.broadleafcommerce.core.offer.service.discount.domain.PromotableOrderItem) PromotionDiscount(org.broadleafcommerce.core.offer.service.discount.PromotionDiscount) PromotableOrderItemPriceDetail(org.broadleafcommerce.core.offer.service.discount.domain.PromotableOrderItemPriceDetail)

Example 3 with PromotableCandidateItemOffer

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);
    }
}
Also used : PromotableCandidateItemOffer(org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateItemOffer) ArrayList(java.util.ArrayList)

Example 4 with PromotableCandidateItemOffer

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();
        }
    }
}
Also used : PromotableCandidateItemOffer(org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateItemOffer) PromotableCandidateOrderOffer(org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateOrderOffer) ArrayList(java.util.ArrayList)

Example 5 with PromotableCandidateItemOffer

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());
        }
    }
}
Also used : PromotableCandidateItemOffer(org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateItemOffer) CandidatePromotionItems(org.broadleafcommerce.core.offer.service.discount.CandidatePromotionItems) PromotableFulfillmentGroup(org.broadleafcommerce.core.offer.service.discount.domain.PromotableFulfillmentGroup) PromotableOrderItem(org.broadleafcommerce.core.offer.service.discount.domain.PromotableOrderItem)

Aggregations

PromotableCandidateItemOffer (org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateItemOffer)11 ArrayList (java.util.ArrayList)7 Offer (org.broadleafcommerce.core.offer.domain.Offer)6 Money (org.broadleafcommerce.common.money.Money)4 PromotableCandidateOrderOffer (org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateOrderOffer)4 PromotableOrder (org.broadleafcommerce.core.offer.service.discount.domain.PromotableOrder)4 PromotableOrderItem (org.broadleafcommerce.core.offer.service.discount.domain.PromotableOrderItem)4 CandidateItemOffer (org.broadleafcommerce.core.offer.domain.CandidateItemOffer)3 PromotableOrderItemPriceDetail (org.broadleafcommerce.core.offer.service.discount.domain.PromotableOrderItemPriceDetail)2 Order (org.broadleafcommerce.core.order.domain.Order)2 BigDecimal (java.math.BigDecimal)1 List (java.util.List)1 CustomerOffer (org.broadleafcommerce.core.offer.domain.CustomerOffer)1 OfferItemCriteria (org.broadleafcommerce.core.offer.domain.OfferItemCriteria)1 OfferTargetCriteriaXref (org.broadleafcommerce.core.offer.domain.OfferTargetCriteriaXref)1 CandidatePromotionItems (org.broadleafcommerce.core.offer.service.discount.CandidatePromotionItems)1 PromotionDiscount (org.broadleafcommerce.core.offer.service.discount.PromotionDiscount)1 PromotableCandidateFulfillmentGroupOffer (org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateFulfillmentGroupOffer)1 PromotableFulfillmentGroup (org.broadleafcommerce.core.offer.service.discount.domain.PromotableFulfillmentGroup)1 OrderItem (org.broadleafcommerce.core.order.domain.OrderItem)1