use of org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateOrderOffer in project BroadleafCommerce by BroadleafCommerce.
the class OrderOfferProcessorImpl method applyAllOrderOffers.
@Override
public void applyAllOrderOffers(List<PromotableCandidateOrderOffer> orderOffers, PromotableOrder promotableOrder) {
// If order offer is not combinable, first verify order adjustment is zero, if zero, compare item discount total vs this offer's total
Iterator<PromotableCandidateOrderOffer> orderOfferIterator = orderOffers.iterator();
while (orderOfferIterator.hasNext()) {
PromotableCandidateOrderOffer orderOffer = orderOfferIterator.next();
if (promotableOrder.canApplyOrderOffer(orderOffer)) {
if (orderMeetsQualifyingSubtotalRequirements(promotableOrder, orderOffer) && orderMeetsSubtotalRequirements(promotableOrder, orderOffer)) {
applyOrderOffer(promotableOrder, orderOffer);
if (orderOffer.isTotalitarian() || promotableOrder.isTotalitarianItemOfferApplied()) {
if (LOG.isTraceEnabled()) {
LOG.trace("Totalitarian Order Offer Applied. Comparing order and item offers for best outcome.");
}
compareAndAdjustOrderAndItemOffers(promotableOrder);
// item offer. There could be other order offers that are not totalitarian that also qualify.
continue;
}
if (!orderOffer.isCombinable()) {
if (LOG.isTraceEnabled()) {
LOG.trace("Non-Combinable Order Offer Applied with id=[" + orderOffer.getOffer().getId() + "]. No other order offers can be applied");
}
break;
}
}
}
}
promotableOrder.getOrder().setSubTotal(promotableOrder.calculateSubtotalWithAdjustments());
}
use of org.broadleafcommerce.core.offer.service.discount.domain.PromotableCandidateOrderOffer in project BroadleafCommerce by BroadleafCommerce.
the class OfferServiceImpl method applyAndSaveOffersToOrder.
/*
*
* Offers Logic:
* 1) Remove all existing offers in the Order (order, item, and fulfillment)
* 2) Check and remove offers
* a) Remove out of date offers
* b) Remove offers that do not apply to this customer
* 3) Loop through offers
* a) Verifies type of offer (order, order item, fulfillment)
* b) Verifies if offer can be applies
* c) Assign offer to type (order, order item, or fulfillment)
* 4) Sorts the order and item offers list by priority and then discount
* 5) Identify the best offers to apply to order item and create adjustments for each item offer
* 6) Compare order item adjustment price to sales price, and remove adjustments if sale price is better
* 7) Identify the best offers to apply to the order and create adjustments for each order offer
* 8) If item contains non-combinable offers remove either the item or order adjustments based on discount value
* 9) Set final order item prices and reapply order offers
*
* Assumptions:
* 1) % off all items will be created as an item offer with no expression
* 2) $ off order will be created as an order offer
* 3) Order offers applies to the best price for each item (not just retail price)
* 4) Fulfillment offers apply to best price for each item (not just retail price)
* 5) Stackable only applies to the same offer type (i.e. a not stackable order offer can be used with item offers)
* 6) Fulfillment offers cannot be not combinable
* 7) Order offers cannot be FIXED_PRICE
* 8) FIXED_PRICE offers cannot be stackable
* 9) Non-combinable offers only apply to the order and order items, fulfillment group offers will always apply
*
*/
@Override
@Transactional("blTransactionManager")
public Order applyAndSaveOffersToOrder(List<Offer> offers, Order order) throws PricingException {
/*
TODO rather than a threadlocal, we should update the "shouldPrice" boolean on the service API to
use a richer object to describe the parameters of the pricing call. This object would include
the pricing boolean, but would also include a list of activities to include or exclude in the
call - see http://jira.broadleafcommerce.org/browse/BLC-664
*/
OfferContext offerContext = OfferContext.getOfferContext();
if (offerContext == null || offerContext.executePromotionCalculation) {
PromotableOrder promotableOrder = promotableItemFactory.createPromotableOrder(order, false);
List<Offer> filteredOffers = orderOfferProcessor.filterOffers(offers, order.getCustomer());
if ((filteredOffers == null) || (filteredOffers.isEmpty())) {
if (LOG.isTraceEnabled()) {
LOG.trace("No offers applicable to this order.");
}
} else {
List<PromotableCandidateOrderOffer> qualifiedOrderOffers = new ArrayList<PromotableCandidateOrderOffer>();
List<PromotableCandidateItemOffer> qualifiedItemOffers = new ArrayList<PromotableCandidateItemOffer>();
itemOfferProcessor.filterOffers(promotableOrder, filteredOffers, qualifiedOrderOffers, qualifiedItemOffers);
if (!(qualifiedItemOffers.isEmpty() && qualifiedOrderOffers.isEmpty())) {
// At this point, we should have a PromotableOrder that contains PromotableItems each of which
// has a list of candidatePromotions that might be applied.
// We also have a list of orderOffers that might apply and a list of itemOffers that might apply.
itemOfferProcessor.applyAndCompareOrderAndItemOffers(promotableOrder, qualifiedOrderOffers, qualifiedItemOffers);
}
}
orderOfferProcessor.synchronizeAdjustmentsAndPrices(promotableOrder);
verifyAdjustments(order, true);
order.setSubTotal(order.calculateSubTotal());
order.finalizeItemPrices();
order = orderService.save(order, false);
boolean madeChange = verifyAdjustments(order, false);
if (madeChange) {
order = orderService.save(order, false);
}
}
return order;
}
Aggregations