Search in sources :

Example 1 with FulfillmentOption

use of org.broadleafcommerce.core.order.domain.FulfillmentOption in project BroadleafCommerce by BroadleafCommerce.

the class FulfillmentPricingServiceImpl method estimateCostForFulfillmentGroup.

@Override
public FulfillmentEstimationResponse estimateCostForFulfillmentGroup(FulfillmentGroup fulfillmentGroup, Set<FulfillmentOption> options) throws FulfillmentPriceException {
    FulfillmentEstimationResponse response = new FulfillmentEstimationResponse();
    HashMap<FulfillmentOption, Money> prices = new HashMap<FulfillmentOption, Money>();
    response.setFulfillmentOptionPrices(prices);
    for (FulfillmentPricingProvider provider : providers) {
        // to, then the response from the pricing provider should not include the options that it could not respond to.
        try {
            FulfillmentEstimationResponse processorResponse = provider.estimateCostForFulfillmentGroup(fulfillmentGroup, options);
            if (processorResponse != null && processorResponse.getFulfillmentOptionPrices() != null && processorResponse.getFulfillmentOptionPrices().size() > 0) {
                prices.putAll(processorResponse.getFulfillmentOptionPrices());
            }
        } catch (FulfillmentPriceException e) {
            // Shouldn't completely fail the rest of the estimation on a pricing exception. Another provider might still
            // be able to respond
            String errorMessage = "FulfillmentPriceException thrown when trying to estimate fulfillment costs from ";
            errorMessage += provider.getClass().getName();
            errorMessage += ". Underlying message was: " + e.getMessage();
            LOG.error(errorMessage);
        }
    }
    return response;
}
Also used : Money(org.broadleafcommerce.common.money.Money) FulfillmentPricingProvider(org.broadleafcommerce.core.pricing.service.fulfillment.provider.FulfillmentPricingProvider) HashMap(java.util.HashMap) FulfillmentPriceException(org.broadleafcommerce.common.vendor.service.exception.FulfillmentPriceException) FulfillmentEstimationResponse(org.broadleafcommerce.core.pricing.service.fulfillment.provider.FulfillmentEstimationResponse) FulfillmentOption(org.broadleafcommerce.core.order.domain.FulfillmentOption)

Example 2 with FulfillmentOption

use of org.broadleafcommerce.core.order.domain.FulfillmentOption in project BroadleafCommerce by BroadleafCommerce.

the class FixedPriceFulfillmentPricingProvider method estimateCostForFulfillmentGroup.

@Override
public FulfillmentEstimationResponse estimateCostForFulfillmentGroup(FulfillmentGroup fulfillmentGroup, Set<FulfillmentOption> options) throws FulfillmentPriceException {
    FulfillmentEstimationResponse response = new FulfillmentEstimationResponse();
    HashMap<FulfillmentOption, Money> shippingPrices = new HashMap<FulfillmentOption, Money>();
    response.setFulfillmentOptionPrices(shippingPrices);
    for (FulfillmentOption option : options) {
        if (canCalculateCostForFulfillmentGroup(fulfillmentGroup, option)) {
            Money price = ((FixedPriceFulfillmentOption) option).getPrice();
            shippingPrices.put(option, price);
        }
    }
    return response;
}
Also used : Money(org.broadleafcommerce.common.money.Money) HashMap(java.util.HashMap) FixedPriceFulfillmentOption(org.broadleafcommerce.core.order.fulfillment.domain.FixedPriceFulfillmentOption) FixedPriceFulfillmentOption(org.broadleafcommerce.core.order.fulfillment.domain.FixedPriceFulfillmentOption) FulfillmentOption(org.broadleafcommerce.core.order.domain.FulfillmentOption)

Example 3 with FulfillmentOption

use of org.broadleafcommerce.core.order.domain.FulfillmentOption in project BroadleafCommerce by BroadleafCommerce.

the class OnePageCheckoutProcessor method populateFulfillmentOptionsAndEstimationOnModel.

/**
 * A helper method to retrieve all fulfillment options for the cart and estimate the cost of applying
 * fulfillment options on the first shippable fulfillment group.
 */
protected void populateFulfillmentOptionsAndEstimationOnModel(Map<String, Object> localVars) {
    List<FulfillmentOption> fulfillmentOptions = fulfillmentOptionService.readAllFulfillmentOptions();
    Order cart = CartState.getCart();
    if (!(cart instanceof NullOrderImpl) && cart.getFulfillmentGroups().size() > 0 && hasPopulatedShippingAddress(cart)) {
        Set<FulfillmentOption> options = new HashSet<>();
        options.addAll(fulfillmentOptions);
        FulfillmentEstimationResponse estimateResponse = null;
        try {
            estimateResponse = fulfillmentPricingService.estimateCostForFulfillmentGroup(fulfillmentGroupService.getFirstShippableFulfillmentGroup(cart), options);
        } catch (FulfillmentPriceException e) {
        }
        localVars.put("estimateResponse", estimateResponse);
    }
    localVars.put("fulfillmentOptions", fulfillmentOptions);
}
Also used : Order(org.broadleafcommerce.core.order.domain.Order) FulfillmentPriceException(org.broadleafcommerce.common.vendor.service.exception.FulfillmentPriceException) FulfillmentEstimationResponse(org.broadleafcommerce.core.pricing.service.fulfillment.provider.FulfillmentEstimationResponse) FulfillmentOption(org.broadleafcommerce.core.order.domain.FulfillmentOption) NullOrderImpl(org.broadleafcommerce.core.order.domain.NullOrderImpl) HashSet(java.util.HashSet)

Example 4 with FulfillmentOption

use of org.broadleafcommerce.core.order.domain.FulfillmentOption in project BroadleafCommerce by BroadleafCommerce.

the class SkuImpl method createOrRetrieveCopyInstance.

@Override
public <G extends Sku> CreateResponse<G> createOrRetrieveCopyInstance(MultiTenantCopyContext context) throws CloneNotSupportedException {
    CreateResponse<G> createResponse = context.createOrRetrieveCopyInstance(this);
    if (createResponse.isAlreadyPopulated()) {
        return createResponse;
    }
    Sku cloned = createResponse.getClone();
    cloned.setRetailPrice(getRetailPrice());
    cloned.setSalePrice(getSalePrice());
    cloned.setName(name);
    cloned.setActiveEndDate(activeEndDate);
    cloned.setActiveStartDate(activeStartDate);
    cloned.setCurrency(currency);
    cloned.setQuantityAvailable(quantityAvailable);
    cloned.setDescription(description);
    cloned.setDimension(dimension);
    cloned.setDiscountable(isDiscountable());
    cloned.setDisplayTemplate(displayTemplate);
    cloned.setExternalId(externalId);
    cloned.setTaxable(isTaxable());
    cloned.setTaxCode(taxCode);
    cloned.setUrlKey(urlKey);
    cloned.setInventoryType(getInventoryType());
    cloned.setFulfillmentType(getFulfillmentType());
    cloned.setIsMachineSortable(isMachineSortable);
    cloned.setLongDescription(longDescription);
    cloned.setUpc(upc);
    if (product != null) {
        cloned.setDefaultProduct(product.createOrRetrieveCopyInstance(context).getClone());
    }
    if (product != null) {
        cloned.setProduct(product.createOrRetrieveCopyInstance(context).getClone());
    }
    for (Map.Entry<String, SkuAttribute> entry : getSkuAttributes().entrySet()) {
        SkuAttribute clonedEntry = entry.getValue().createOrRetrieveCopyInstance(context).getClone();
        cloned.getSkuAttributes().put(entry.getKey(), clonedEntry);
    }
    for (SkuProductOptionValueXref entry : productOptionValueXrefs) {
        SkuProductOptionValueXref clonedEntry = entry.createOrRetrieveCopyInstance(context).getClone();
        cloned.getProductOptionValueXrefs().add(clonedEntry);
    }
    for (Map.Entry<String, SkuMediaXref> entry : skuMedia.entrySet()) {
        SkuMediaXrefImpl clonedEntry = ((SkuMediaXrefImpl) entry.getValue()).createOrRetrieveCopyInstance(context).getClone();
        cloned.getSkuMediaXrefIgnoreDefaultSku().put(entry.getKey(), clonedEntry);
    }
    for (FulfillmentOption entry : excludedFulfillmentOptions) {
        FulfillmentOption clonedEntry = entry.createOrRetrieveCopyInstance(context).getClone();
        cloned.getExcludedFulfillmentOptions().add(clonedEntry);
    }
    for (Map.Entry<FulfillmentOption, BigDecimal> entry : fulfillmentFlatRates.entrySet()) {
        FulfillmentOption clonedEntry = entry.getKey().createOrRetrieveCopyInstance(context).getClone();
        cloned.getFulfillmentFlatRates().put(clonedEntry, entry.getValue());
    }
    return createResponse;
}
Also used : FulfillmentOption(org.broadleafcommerce.core.order.domain.FulfillmentOption) BigDecimal(java.math.BigDecimal) MultiValueMap(org.apache.commons.collections.map.MultiValueMap) Map(java.util.Map) HashMap(java.util.HashMap) AdminPresentationMap(org.broadleafcommerce.common.presentation.AdminPresentationMap) ClonePolicyCollectionOverride(org.broadleafcommerce.common.extensibility.jpa.clone.ClonePolicyCollectionOverride)

Example 5 with FulfillmentOption

use of org.broadleafcommerce.core.order.domain.FulfillmentOption in project BroadleafCommerce by BroadleafCommerce.

the class BandedFulfillmentPricingProvider method estimateCostForFulfillmentGroup.

@Override
public FulfillmentEstimationResponse estimateCostForFulfillmentGroup(FulfillmentGroup fulfillmentGroup, Set<FulfillmentOption> options) throws FulfillmentPriceException {
    // Set up the response object
    FulfillmentEstimationResponse res = new FulfillmentEstimationResponse();
    HashMap<FulfillmentOption, Money> shippingPrices = new HashMap<FulfillmentOption, Money>();
    res.setFulfillmentOptionPrices(shippingPrices);
    for (FulfillmentOption option : options) {
        if (canCalculateCostForFulfillmentGroup(fulfillmentGroup, option)) {
            List<? extends FulfillmentBand> bands = null;
            if (option instanceof BandedPriceFulfillmentOption) {
                bands = ((BandedPriceFulfillmentOption) option).getBands();
            } else if (option instanceof BandedWeightFulfillmentOption) {
                bands = ((BandedWeightFulfillmentOption) option).getBands();
            }
            if (bands == null || bands.isEmpty()) {
                // Something is misconfigured. There are no bands associated with this fulfillment option
                throw new IllegalStateException("There were no Fulfillment Price Bands configured for a BandedPriceFulfillmentOption with ID: " + option.getId());
            }
            // Calculate the amount that the band will be applied to
            BigDecimal retailTotal = BigDecimal.ZERO;
            BigDecimal flatTotal = BigDecimal.ZERO;
            BigDecimal weightTotal = BigDecimal.ZERO;
            boolean foundCandidateForBand = false;
            for (FulfillmentGroupItem fulfillmentGroupItem : fulfillmentGroup.getFulfillmentGroupItems()) {
                // If this item has a Sku associated with it which also has a flat rate for this fulfillment option, don't add it to the price
                // or weight total but instead tack it onto the final rate
                boolean addToTotal = true;
                Sku sku = null;
                if (fulfillmentGroupItem.getOrderItem() instanceof DiscreteOrderItem) {
                    sku = ((DiscreteOrderItem) fulfillmentGroupItem.getOrderItem()).getSku();
                } else if (fulfillmentGroupItem.getOrderItem() instanceof BundleOrderItem) {
                    sku = ((BundleOrderItem) fulfillmentGroupItem.getOrderItem()).getSku();
                }
                if (sku != null && option.getUseFlatRates()) {
                    BigDecimal rate = sku.getFulfillmentFlatRates().get(option);
                    if (rate != null) {
                        addToTotal = false;
                        flatTotal = flatTotal.add(rate);
                    }
                }
                if (addToTotal) {
                    foundCandidateForBand = true;
                    BigDecimal price = (fulfillmentGroupItem.getTotalItemAmount() != null) ? fulfillmentGroupItem.getTotalItemAmount().getAmount() : null;
                    if (price == null) {
                        price = fulfillmentGroupItem.getOrderItem().getAveragePrice().getAmount().multiply(BigDecimal.valueOf(fulfillmentGroupItem.getQuantity()));
                    }
                    retailTotal = retailTotal.add(price);
                    if (sku != null && sku.getWeight() != null && sku.getWeight().getWeight() != null) {
                        BigDecimal convertedWeight = convertWeight(sku.getWeight().getWeight(), sku.getWeight().getWeightUnitOfMeasure()).multiply(BigDecimal.valueOf(fulfillmentGroupItem.getQuantity()));
                        weightTotal = weightTotal.add(convertedWeight);
                    }
                }
            }
            // Used to keep track of the lowest price when there is are bands that have the same
            // minimum amount
            BigDecimal lowestBandFulfillmentPrice = null;
            // Used to keep track of the amount for the lowest band fulfillment price. Used to compare
            // if 2 bands are configured for the same minimum amount
            BigDecimal lowestBandFulfillmentPriceMinimumAmount = BigDecimal.ZERO;
            if (foundCandidateForBand) {
                for (FulfillmentBand band : bands) {
                    BigDecimal bandMinimumAmount = BigDecimal.ZERO;
                    boolean foundMatch = false;
                    if (band instanceof FulfillmentPriceBand) {
                        bandMinimumAmount = ((FulfillmentPriceBand) band).getRetailPriceMinimumAmount();
                        foundMatch = retailTotal.compareTo(bandMinimumAmount) >= 0;
                    } else if (band instanceof FulfillmentWeightBand) {
                        bandMinimumAmount = ((FulfillmentWeightBand) band).getMinimumWeight();
                        foundMatch = weightTotal.compareTo(bandMinimumAmount) >= 0;
                    }
                    if (foundMatch) {
                        // So far, we've found a potential match
                        // Now, determine if this is a percentage or actual amount
                        FulfillmentBandResultAmountType resultAmountType = band.getResultAmountType();
                        BigDecimal bandFulfillmentPrice = null;
                        if (FulfillmentBandResultAmountType.RATE.equals(resultAmountType)) {
                            bandFulfillmentPrice = band.getResultAmount();
                        } else if (FulfillmentBandResultAmountType.PERCENTAGE.equals(resultAmountType)) {
                            // Since this is a percentage, we calculate the result amount based on retailTotal and the band percentage
                            bandFulfillmentPrice = retailTotal.multiply(band.getResultAmount());
                        } else {
                            LOG.warn("Unknown FulfillmentBandResultAmountType: " + resultAmountType.getType() + " Should be RATE or PERCENTAGE. Ignoring.");
                        }
                        if (bandFulfillmentPrice != null) {
                            // haven't initialized the lowest price yet so just take on this one
                            if (lowestBandFulfillmentPrice == null) {
                                lowestBandFulfillmentPrice = bandFulfillmentPrice;
                                lowestBandFulfillmentPriceMinimumAmount = bandMinimumAmount;
                            }
                            // is cheaper
                            if (lowestBandFulfillmentPriceMinimumAmount.compareTo(bandMinimumAmount) == 0) {
                                if (bandFulfillmentPrice.compareTo(lowestBandFulfillmentPrice) <= 0) {
                                    lowestBandFulfillmentPrice = bandFulfillmentPrice;
                                    lowestBandFulfillmentPriceMinimumAmount = bandMinimumAmount;
                                }
                            } else if (bandMinimumAmount.compareTo(lowestBandFulfillmentPriceMinimumAmount) > 0) {
                                lowestBandFulfillmentPrice = bandFulfillmentPrice;
                                lowestBandFulfillmentPriceMinimumAmount = bandMinimumAmount;
                            }
                        } else {
                            throw new IllegalStateException("Bands must have a non-null fulfillment price");
                        }
                    }
                }
            }
            // If I didn't find a valid band, initialize the fulfillment price to zero
            if (lowestBandFulfillmentPrice == null) {
                lowestBandFulfillmentPrice = BigDecimal.ZERO;
            }
            // add the flat rate amount calculated on the Sku
            lowestBandFulfillmentPrice = lowestBandFulfillmentPrice.add(flatTotal);
            shippingPrices.put(option, BroadleafCurrencyUtils.getMoney(lowestBandFulfillmentPrice, fulfillmentGroup.getOrder().getCurrency()));
        }
    }
    return res;
}
Also used : DiscreteOrderItem(org.broadleafcommerce.core.order.domain.DiscreteOrderItem) HashMap(java.util.HashMap) BandedPriceFulfillmentOption(org.broadleafcommerce.core.order.fulfillment.domain.BandedPriceFulfillmentOption) BandedWeightFulfillmentOption(org.broadleafcommerce.core.order.fulfillment.domain.BandedWeightFulfillmentOption) FulfillmentOption(org.broadleafcommerce.core.order.domain.FulfillmentOption) BandedPriceFulfillmentOption(org.broadleafcommerce.core.order.fulfillment.domain.BandedPriceFulfillmentOption) FulfillmentBand(org.broadleafcommerce.core.order.fulfillment.domain.FulfillmentBand) BigDecimal(java.math.BigDecimal) FulfillmentPriceBand(org.broadleafcommerce.core.order.fulfillment.domain.FulfillmentPriceBand) Money(org.broadleafcommerce.common.money.Money) BundleOrderItem(org.broadleafcommerce.core.order.domain.BundleOrderItem) FulfillmentGroupItem(org.broadleafcommerce.core.order.domain.FulfillmentGroupItem) FulfillmentBandResultAmountType(org.broadleafcommerce.core.order.service.type.FulfillmentBandResultAmountType) Sku(org.broadleafcommerce.core.catalog.domain.Sku) BandedWeightFulfillmentOption(org.broadleafcommerce.core.order.fulfillment.domain.BandedWeightFulfillmentOption) FulfillmentWeightBand(org.broadleafcommerce.core.order.fulfillment.domain.FulfillmentWeightBand)

Aggregations

FulfillmentOption (org.broadleafcommerce.core.order.domain.FulfillmentOption)10 HashMap (java.util.HashMap)4 Money (org.broadleafcommerce.common.money.Money)4 FulfillmentGroup (org.broadleafcommerce.core.order.domain.FulfillmentGroup)4 HashSet (java.util.HashSet)3 FulfillmentPriceException (org.broadleafcommerce.common.vendor.service.exception.FulfillmentPriceException)3 Order (org.broadleafcommerce.core.order.domain.Order)3 FulfillmentEstimationResponse (org.broadleafcommerce.core.pricing.service.fulfillment.provider.FulfillmentEstimationResponse)3 BigDecimal (java.math.BigDecimal)2 BandedPriceFulfillmentOption (org.broadleafcommerce.core.order.fulfillment.domain.BandedPriceFulfillmentOption)2 BandedWeightFulfillmentOption (org.broadleafcommerce.core.order.fulfillment.domain.BandedWeightFulfillmentOption)2 FixedPriceFulfillmentOption (org.broadleafcommerce.core.order.fulfillment.domain.FixedPriceFulfillmentOption)2 CustomerAddress (org.broadleafcommerce.profile.core.domain.CustomerAddress)2 Map (java.util.Map)1 MultiValueMap (org.apache.commons.collections.map.MultiValueMap)1 ClonePolicyCollectionOverride (org.broadleafcommerce.common.extensibility.jpa.clone.ClonePolicyCollectionOverride)1 AdminPresentationMap (org.broadleafcommerce.common.presentation.AdminPresentationMap)1 Sku (org.broadleafcommerce.core.catalog.domain.Sku)1 BundleOrderItem (org.broadleafcommerce.core.order.domain.BundleOrderItem)1 DiscreteOrderItem (org.broadleafcommerce.core.order.domain.DiscreteOrderItem)1