Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * #%L
   * BroadleafCommerce Framework
   * %%
   * Copyright (C) 2009 - 2013 Broadleaf Commerce
   * %%
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
  * 
  *       http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * #L%
  */
 package org.broadleafcommerce.core.pricing.service.workflow;
 
 
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
This pricing workflow step will automatically bundle items in the cart. For example, if a ProductBundle exists of two items and the user has one of the items in their cart. If they then add the second item, this activity will replace the two items with the ProductBundle. This only occurs if the ProductBundle is set to "automatically" bundle.
 
 public class AutoBundleActivity extends BaseActivity<ProcessContext<Order>> {
     @Resource(name="blCatalogService")
     protected CatalogService catalogService;
 
     @Resource(name="blOrderService")
     protected OrderService orderService;
 
     @Resource(name="blOrderItemDao")
     protected OrderItemDao orderItemDao;
 
     @Resource(name="blFulfillmentGroupItemDao")
 
     public ProcessContext<Orderexecute(ProcessContext<Ordercontextthrows Exception {
         Order order = context.getSeedData();
         order = handleAutomaticBundling(order);
         context.setSeedData(order);
         return context;
     }
 
         boolean itemsHaveBeenUnbundled = false;
         List<DiscreteOrderItemunbundledItems = null;
 
         List<ProductBundleproductBundles = .findAutomaticProductBundles();
         Set<LongprocessedBundleIds = new HashSet<Long>();
         for (ProductBundle productBundle : productBundles) {
             int existingUses = countExistingUsesOfBundle(orderproductBundle);
             Integer maxApplications = null;
             for (SkuBundleItem skuBundleItem : productBundle.getSkuBundleItems()) {
                 int maxSkuApplications = countMaximumApplications(orderskuBundleItemprocessedBundleIds);
                 if (maxApplications == null || maxApplications > maxSkuApplications) {
                     maxApplications = maxSkuApplications;
                 }
             }
             processedBundleIds.add(productBundle.getId());
 
             if (maxApplications != existingUses) {
                 if (! itemsHaveBeenUnbundled) {
                     // Store the discrete items that were part of automatic bundles
                    unbundledItems = unBundleItems(order);
                    order = removeAutomaticBundles(order);
                    itemsHaveBeenUnbundled = true;
                }
                // Create a new bundle with maxApplication occurrences
                order = bundleItems(orderproductBundlemaxApplicationsunbundledItems);
            }
        }
        return order;
    }

    
Removes all automatic bundles from the order and replaces with DiscreteOrderItems.

    private Order removeAutomaticBundles(Order orderthrows PricingException {
        List<BundleOrderItembundlesToRemove = new ArrayList<BundleOrderItem>();
        for (OrderItem orderItem : order.getOrderItems()) {
            if (orderItem instanceof BundleOrderItem) {
                BundleOrderItem bundleOrderItem = (BundleOrderItemorderItem;
                if (bundleOrderItem.getProductBundle() != null && bundleOrderItem.getProductBundle().getAutoBundle()) {
                    bundlesToRemove.add(bundleOrderItem);
                }
            }
        }
        for (BundleOrderItem bundleOrderItem : bundlesToRemove) {
            try {
                order = .removeItem(order.getId(), bundleOrderItem.getId(), false);
            } catch (RemoveFromCartException e) {
                throw new PricingException("Could not remove item"e);
            }
        }
        return order;
    }

    
Removes all automatic bundles from the order and replaces with DiscreteOrderItems.

Parameters:
order
    private List<DiscreteOrderItemunBundleItems(Order orderthrows PricingException{
        List<DiscreteOrderItemunbundledItems = null;
        for (OrderItem orderItem : order.getOrderItems()) {
            if (orderItem instanceof BundleOrderItem) {
                BundleOrderItem bundleOrderItem = (BundleOrderItemorderItem;
                if (bundleOrderItem.getProductBundle() != null && bundleOrderItem.getProductBundle().getAutoBundle()) {
                    if (unbundledItems == null) {
                        unbundledItems = new ArrayList<DiscreteOrderItem>();
                    }
                    for(DiscreteOrderItem item : bundleOrderItem.getDiscreteOrderItems()) {
                        DiscreteOrderItem newOrderItem = (DiscreteOrderItemitem.clone();
                        newOrderItem.setQuantity(item.getQuantity() * bundleOrderItem.getQuantity());
                        newOrderItem.setSkuBundleItem(null);
                        newOrderItem.setBundleOrderItem(null);   
                        newOrderItem.updateSaleAndRetailPrices();
                        newOrderItem.setOrder(order);
                        unbundledItems.add(newOrderItem);
                    }
                }
            }
        }
        return unbundledItems;
    }

    
Builds a BundleOrderItem based on the passed in productBundle. Creates new DiscreteOrderItems. Removes the existing matching DiscreteOrderItems or modifies the quantity if needed.

    private Order bundleItems(Order orderProductBundle productBundleInteger numApplicationsList<DiscreteOrderItemunbundledItemsthrows PricingExceptionRemoveFromCartException {
        BundleOrderItem bundleOrderItem = (BundleOrderItem.create(.);
        bundleOrderItem.setQuantity(numApplications);
        bundleOrderItem.setCategory(productBundle.getDefaultCategory());
        bundleOrderItem.setSku(productBundle.getDefaultSku());
        bundleOrderItem.setName(productBundle.getName());
        bundleOrderItem.setProductBundle(productBundle);
        bundleOrderItem.setOrder(order);
        // make a copy of the fulfillment group items since they will be deleted when the order items are removed
        Map<LongFulfillmentGroupItemskuIdFulfillmentGroupMap = new HashMap<LongFulfillmentGroupItem>();
        for (FulfillmentGroup fulfillmentGroup : order.getFulfillmentGroups()) {
            for (FulfillmentGroupItem fulfillmentGroupItem : fulfillmentGroup.getFulfillmentGroupItems()) {
                if (fulfillmentGroupItem.getOrderItem() instanceof DiscreteOrderItem) {
                    DiscreteOrderItem discreteOrderItem = (DiscreteOrderItemfulfillmentGroupItem.getOrderItem();
                    skuIdFulfillmentGroupMap.put(discreteOrderItem.getSku().getId(), fulfillmentGroupItem);
                }
            }
        }
        for (SkuBundleItem skuBundleItem : productBundle.getSkuBundleItems()) {
            List<DiscreteOrderItemitemMatches = new ArrayList<DiscreteOrderItem>();
            int skuMatches = populateItemMatchesForSku(itemMatchesorderunbundledItemsskuBundleItem.getSku().getId());
            int skusRequired = skuBundleItem.getQuantity()* numApplications;
            if (skuMatches < skusRequired) {
                throw new IllegalArgumentException("Something went wrong creating automatic bundles.  Not enough skus to fulfill bundle requirements for sku id: " + skuBundleItem.getSku().getId());
            }
            // remove-all-items from order
            // this call also deletes any fulfillment group items that are associated with that order item
            for (DiscreteOrderItem item : itemMatches) {
                order = .removeItem(order.getId(), item.getId(), false);
            }
            DiscreteOrderItem baseItem = null;
            if (itemMatches.size() > 0) {
                baseItem = itemMatches.get(0);
            } else {
                 for (DiscreteOrderItem discreteOrderItem : unbundledItems) {
                     if (discreteOrderItem.getSku().getId().equals(skuBundleItem.getSku().getId())) {
                         baseItem = discreteOrderItem;
                     }
                 }
            }
            // Add item to the skuBundle
            DiscreteOrderItem newSkuBundleItem = (DiscreteOrderItembaseItem.clone();
            newSkuBundleItem.setSkuBundleItem(skuBundleItem);
            newSkuBundleItem.setBundleOrderItem(bundleOrderItem);
            newSkuBundleItem.setQuantity(skuBundleItem.getQuantity());
            newSkuBundleItem.setOrder(null);
            bundleOrderItem.getDiscreteOrderItems().add(newSkuBundleItem);
            if (skuMatches > skusRequired) {
                // Add a non-bundled item to the order with the remaining sku count.
                DiscreteOrderItem newOrderItem = (DiscreteOrderItembaseItem.clone();
                newOrderItem.setBundleOrderItem(null);
                newOrderItem.setSkuBundleItem(null);
                newOrderItem.setQuantity(skuMatches - skusRequired);
                newOrderItem = (DiscreteOrderItem.save(newOrderItem);
                newOrderItem.setOrder(order);
                newOrderItem.updateSaleAndRetailPrices();
                // Re-associate fulfillment group item to newOrderItem
                FulfillmentGroupItem fulfillmentGroupItem = skuIdFulfillmentGroupMap.get(newSkuBundleItem.getSku().getId());
                if (fulfillmentGroupItem != null) {
                    FulfillmentGroupItem newFulfillmentGroupItem = fulfillmentGroupItem.clone();
                    newFulfillmentGroupItem.setOrderItem(newOrderItem);
                    newFulfillmentGroupItem.setQuantity(newOrderItem.getQuantity());
                    newFulfillmentGroupItem = .save(newFulfillmentGroupItem);
                    //In case this activity is run inside a transaction, we need to set the relationships on the order directly
                    //these associations may have not been committed yet. This order is used in other activities and will not be reloaded if in a transaction.
                    for (FulfillmentGroup fg : order.getFulfillmentGroups()) {
                        if (newFulfillmentGroupItem.getFulfillmentGroup() != null && fg.getId().equals(newFulfillmentGroupItem.getFulfillmentGroup().getId())) {
                            fg.addFulfillmentGroupItem(newFulfillmentGroupItem);
                        }
                    }
                }
                order.getOrderItems().add(newOrderItem);
            }
        }
        bundleOrderItem.updateSaleAndRetailPrices();
        order.getOrderItems().add(bundleOrderItem);
        order =  .save(orderfalse);
        for (OrderItem orderItem : order.getOrderItems()) {
            if (orderItem instanceof BundleOrderItem) {
                BundleOrderItem bundleItem = (BundleOrderItemorderItem;
                for (DiscreteOrderItem discreteOrderItem : bundleItem.getDiscreteOrderItems()) {
                    // Re-associate fulfillment group item to newly created skuBundles
                    FulfillmentGroupItem fulfillmentGroupItem = skuIdFulfillmentGroupMap.get(discreteOrderItem.getSku().getId());
                    if (fulfillmentGroupItem != null) {
                        FulfillmentGroupItem newFulfillmentGroupItem = fulfillmentGroupItem.clone();
                        newFulfillmentGroupItem.setOrderItem(discreteOrderItem);
                        newFulfillmentGroupItem.setQuantity(discreteOrderItem.getQuantity());
                        //In case this activity is run inside a transaction, we need to set the relationships on the order directly
                        //these associations may have not been committed yet. This order is used in other activities and will not be reloaded if in a transaction.
                        for (FulfillmentGroup fg : order.getFulfillmentGroups()) {
                            if (newFulfillmentGroupItem.getFulfillmentGroup() != null && fg.getId().equals(newFulfillmentGroupItem.getFulfillmentGroup().getId())) {
                                fg.addFulfillmentGroupItem(newFulfillmentGroupItem);
                            }
                        }
                    }
                }
            }
        }
        //reload order with new fulfillment group items
        order = .save(orderfalse);
        return order;
    }
    protected int countExistingUsesOfBundle(Order orderProductBundle bundle) {
        int existingUses=0;
        for (OrderItem orderItem : order.getOrderItems()) {
            if (orderItem instanceof BundleOrderItem) {
                BundleOrderItem bundleOrderItem = (BundleOrderItemorderItem;
                if (bundleOrderItem.getProductBundle() != null) {
                    if (bundleOrderItem.getProductBundle().getId().equals(bundle.getId())) {
                        existingUses = existingUses+1;
                    }
                }
            }
        }
        return existingUses;
    }
    protected int populateItemMatchesForSku(List<DiscreteOrderItemmatchingItemsOrder orderList<DiscreteOrderItemunbundledItemsLong skuId) {
        int skuMatches = 0;
        for (OrderItem orderItem : order.getOrderItems()) {
            if (orderItem instanceof DiscreteOrderItem) {
                DiscreteOrderItem item = (DiscreteOrderItemorderItem;
                if (skuId.equals(item.getSku().getId())) {
                    matchingItems.add(item);
                    skuMatches = skuMatches + item.getQuantity();
                }
            }
        }
        if (unbundledItems != null) {
            for (DiscreteOrderItem discreteOrderItem : unbundledItems) {
                if (skuId.equals(discreteOrderItem.getSku().getId())) {
                    skuMatches = skuMatches + discreteOrderItem.getQuantity();
                }
            }
        }
        return skuMatches;
    }
    protected int countMaximumApplications(Order orderSkuBundleItem skuBundleItemSet<LongprocessedBundles) {
        int skuMatches = 0;
        Long skuId = skuBundleItem.getSku().getId();
        for (OrderItem orderItem : order.getOrderItems()) {
            if (orderItem instanceof DiscreteOrderItem) {
                DiscreteOrderItem item = (DiscreteOrderItemorderItem;
                if (skuId.equals(item.getSku().getId())) {
                    skuMatches = skuMatches + item.getQuantity();
                }
            } else if (orderItem instanceof BundleOrderItem) {
                BundleOrderItem bundleItem = (BundleOrderItemorderItem;
                if (bundleItem.getProductBundle() != null && bundleItem.getProductBundle().getAutoBundle()) {
                    if (! processedBundles.contains(bundleItem.getId())) {
                        for(DiscreteOrderItem discreteItem : bundleItem.getDiscreteOrderItems()) {
                            if (skuId.equals(discreteItem.getSku().getId())) {
                                skuMatches = skuMatches + (discreteItem.getQuantity() * bundleItem.getQuantity());
                            }
                        }
                    }
                }
            }
        }
        return skuMatches / skuBundleItem.getQuantity();
    }
New to GrepCode? Check out our FAQ X