use of org.broadleafcommerce.core.offer.service.discount.domain.PromotableOrder in project BroadleafCommerce by BroadleafCommerce.
the class OrderOfferProcessorImpl method synchronizeOrderAdjustments.
protected void synchronizeOrderAdjustments(PromotableOrder promotableOrder) {
Order order = promotableOrder.getOrder();
if (order.getOrderAdjustments().isEmpty() && promotableOrder.getCandidateOrderAdjustments().isEmpty()) {
return;
}
Map<Long, PromotableOrderAdjustment> newAdjustmentsMap = buildPromotableOrderAdjustmentsMap(promotableOrder);
Iterator<OrderAdjustment> orderAdjIterator = order.getOrderAdjustments().iterator();
while (orderAdjIterator.hasNext()) {
OrderAdjustment adjustment = orderAdjIterator.next();
if (adjustment.getOffer() != null) {
Long offerId = adjustment.getOffer().getId();
PromotableOrderAdjustment promotableAdjustment = newAdjustmentsMap.remove(offerId);
if (promotableAdjustment != null) {
if (!adjustment.getValue().equals(promotableAdjustment.getAdjustmentValue())) {
if (LOG.isDebugEnabled()) {
LOG.debug("Updating value for order adjustment with offer Id " + offerId + " to " + promotableAdjustment.getAdjustmentValue());
}
adjustment.setValue(promotableAdjustment.getAdjustmentValue());
}
} else {
// No longer using this order adjustment, remove it.
orderAdjIterator.remove();
}
}
}
for (PromotableOrderAdjustment promotableOrderAdjustment : newAdjustmentsMap.values()) {
// Add the newly introduced adjustments.
Offer offer = promotableOrderAdjustment.getOffer();
OrderAdjustment orderAdjustment = offerDao.createOrderAdjustment();
orderAdjustment.init(order, offer, offer.getName());
orderAdjustment.setValue(promotableOrderAdjustment.getAdjustmentValue());
order.getOrderAdjustments().add(orderAdjustment);
}
}
use of org.broadleafcommerce.core.offer.service.discount.domain.PromotableOrder in project BroadleafCommerce by BroadleafCommerce.
the class OrderOfferProcessorImpl method synchronizeFulfillmentGroups.
protected void synchronizeFulfillmentGroups(PromotableOrder promotableOrder) {
Order order = promotableOrder.getOrder();
Map<Long, PromotableFulfillmentGroup> fgMap = buildPromotableFulfillmentGroupMap(promotableOrder);
for (FulfillmentGroup fg : order.getFulfillmentGroups()) {
synchronizeFulfillmentGroupAdjustments(fg, fgMap.get(fg.getId()));
}
}
use of org.broadleafcommerce.core.offer.service.discount.domain.PromotableOrder 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;
}
use of org.broadleafcommerce.core.offer.service.discount.domain.PromotableOrder in project BroadleafCommerce by BroadleafCommerce.
the class OfferServiceImpl method applyAndSaveFulfillmentGroupOffersToOrder.
@Override
@Transactional("blTransactionManager")
public Order applyAndSaveFulfillmentGroupOffersToOrder(List<Offer> offers, Order order) throws PricingException {
OfferContext offerContext = OfferContext.getOfferContext();
if (offerContext == null || offerContext.executePromotionCalculation) {
PromotableOrder promotableOrder = promotableItemFactory.createPromotableOrder(order, true);
List<Offer> possibleFGOffers = new ArrayList<Offer>();
for (Offer offer : offers) {
if (offer.getType().getType().equals(OfferType.FULFILLMENT_GROUP.getType())) {
possibleFGOffers.add(offer);
}
}
List<Offer> filteredOffers = orderOfferProcessor.filterOffers(possibleFGOffers, order.getCustomer());
List<PromotableCandidateFulfillmentGroupOffer> qualifiedFGOffers = new ArrayList<PromotableCandidateFulfillmentGroupOffer>();
for (Offer offer : filteredOffers) {
fulfillmentGroupOfferProcessor.filterFulfillmentGroupLevelOffer(promotableOrder, qualifiedFGOffers, offer);
}
if (!qualifiedFGOffers.isEmpty()) {
fulfillmentGroupOfferProcessor.applyAllFulfillmentGroupOffers(qualifiedFGOffers, promotableOrder);
fulfillmentGroupOfferProcessor.calculateFulfillmentGroupTotal(promotableOrder);
orderOfferProcessor.synchronizeAdjustmentsAndPrices(promotableOrder);
}
return orderService.save(order, false);
}
return order;
}
use of org.broadleafcommerce.core.offer.service.discount.domain.PromotableOrder in project BroadleafCommerce by BroadleafCommerce.
the class OfferDataItemProvider method createBasicPromotableOrder.
public PromotableOrder createBasicPromotableOrder() {
Order order = createBasicOrder();
PromotableOrder promotableOrder = new PromotableOrderImpl(order, new PromotableItemFactoryImpl(), false);
return promotableOrder;
}
Aggregations