use of org.broadleafcommerce.core.order.domain.DiscreteOrderItem 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;
}
use of org.broadleafcommerce.core.order.domain.DiscreteOrderItem in project BroadleafCommerce by BroadleafCommerce.
the class CheckUpdateAvailabilityActivity method execute.
@Override
public ProcessContext<CartOperationRequest> execute(ProcessContext<CartOperationRequest> context) throws Exception {
CartOperationRequest request = context.getSeedData();
OrderItemRequestDTO orderItemRequestDTO = request.getItemRequest();
if (orderItemRequestDTO instanceof NonDiscreteOrderItemRequestDTO) {
return context;
}
Sku sku;
Long orderItemId = request.getItemRequest().getOrderItemId();
OrderItem orderItem = orderItemService.readOrderItemById(orderItemId);
if (orderItem instanceof DiscreteOrderItem) {
sku = ((DiscreteOrderItem) orderItem).getSku();
} else if (orderItem instanceof BundleOrderItem) {
sku = ((BundleOrderItem) orderItem).getSku();
} else {
LOG.warn("Could not check availability; did not recognize passed-in item " + orderItem.getClass().getName());
return context;
}
Order order = context.getSeedData().getOrder();
Integer requestedQuantity = request.getItemRequest().getQuantity();
checkSkuAvailability(order, sku, requestedQuantity);
Integer previousQty = orderItem.getQuantity();
for (OrderItem child : orderItem.getChildOrderItems()) {
Sku childSku = ((DiscreteOrderItem) child).getSku();
Integer childQuantity = child.getQuantity();
childQuantity = childQuantity / previousQty;
checkSkuAvailability(order, childSku, childQuantity * requestedQuantity);
}
return context;
}
use of org.broadleafcommerce.core.order.domain.DiscreteOrderItem in project BroadleafCommerce by BroadleafCommerce.
the class UpdateOrderItemActivity method execute.
@Override
public ProcessContext<CartOperationRequest> execute(ProcessContext<CartOperationRequest> context) throws Exception {
CartOperationRequest request = context.getSeedData();
OrderItemRequestDTO orderItemRequestDTO = request.getItemRequest();
Order order = request.getOrder();
OrderItem orderItem = null;
for (OrderItem oi : order.getOrderItems()) {
if (oi.getId().equals(orderItemRequestDTO.getOrderItemId())) {
orderItem = oi;
}
}
if (orderItem == null || !order.getOrderItems().contains(orderItem)) {
throw new ItemNotFoundException("Order Item (" + orderItemRequestDTO.getOrderItemId() + ") not found in Order (" + order.getId() + ")");
}
OrderItem itemFromOrder = order.getOrderItems().get(order.getOrderItems().indexOf(orderItem));
if (orderItemRequestDTO.getQuantity() >= 0) {
int previousQty = itemFromOrder.getQuantity();
request.setOrderItemQuantityDelta(orderItemRequestDTO.getQuantity() - itemFromOrder.getQuantity());
itemFromOrder.setQuantity(orderItemRequestDTO.getQuantity());
for (OrderItem child : itemFromOrder.getChildOrderItems()) {
int childQuantity = child.getQuantity();
childQuantity = childQuantity / previousQty;
child.setQuantity(childQuantity * orderItemRequestDTO.getQuantity());
}
// Update any additional attributes of the passed in request
if (itemFromOrder instanceof DiscreteOrderItem) {
DiscreteOrderItem discreteOrderItem = (DiscreteOrderItem) itemFromOrder;
discreteOrderItem.getAdditionalAttributes().putAll(orderItemRequestDTO.getAdditionalAttributes());
}
request.setOrderItem(itemFromOrder);
}
return context;
}
use of org.broadleafcommerce.core.order.domain.DiscreteOrderItem in project BroadleafCommerce by BroadleafCommerce.
the class PricingTest method testPricing.
@Test(groups = { "testPricing" }, dependsOnGroups = { "testShippingInsert", "createCustomerIdGeneration" })
@Transactional
public void testPricing() throws Exception {
Order order = orderService.createNewCartForCustomer(createCustomer());
customerService.saveCustomer(order.getCustomer());
Country country = new CountryImpl();
country.setAbbreviation("US");
country.setName("United States");
country = countryService.save(country);
ISOCountry isoCountry = new ISOCountryImpl();
isoCountry.setAlpha2("US");
isoCountry.setName("UNITED STATES");
isoCountry = isoService.save(isoCountry);
State state = new StateImpl();
state.setAbbreviation("TX");
state.setName("Texas");
state.setCountry(country);
state = stateService.save(state);
Address address = new AddressImpl();
address.setAddressLine1("123 Test Rd");
address.setCity("Dallas");
address.setFirstName("Jeff");
address.setLastName("Fischer");
address.setPostalCode("75240");
address.setPrimaryPhone("972-978-9067");
address.setState(state);
address.setCountry(country);
address.setIsoCountrySubdivision("US-TX");
address.setIsoCountryAlpha2(isoCountry);
FulfillmentGroup group = new FulfillmentGroupImpl();
group.setAddress(address);
List<FulfillmentGroup> groups = new ArrayList<>();
group.setMethod("standard");
group.setService(ShippingServiceType.BANDED_SHIPPING.getType());
group.setOrder(order);
groups.add(group);
order.setFulfillmentGroups(groups);
Money total = new Money(8.5D);
group.setShippingPrice(total);
{
DiscreteOrderItem item = new DiscreteOrderItemImpl();
Sku sku = new SkuImpl();
sku.setName("Test Sku");
sku.setRetailPrice(new Money(10D));
sku.setDiscountable(true);
SkuFee fee = new SkuFeeImpl();
fee.setFeeType(SkuFeeType.FULFILLMENT);
fee.setName("fee test");
fee.setAmount(new Money(10D));
fee = catalogService.saveSkuFee(fee);
List<SkuFee> fees = new ArrayList<>();
fees.add(fee);
sku.setFees(fees);
sku = catalogService.saveSku(sku);
item.setSku(sku);
item.setQuantity(2);
item.setOrder(order);
item = (DiscreteOrderItem) orderItemService.saveOrderItem(item);
order.addOrderItem(item);
FulfillmentGroupItem fgItem = new FulfillmentGroupItemImpl();
fgItem.setFulfillmentGroup(group);
fgItem.setOrderItem(item);
fgItem.setQuantity(2);
// fgItem.setPrice(new Money(0D));
group.addFulfillmentGroupItem(fgItem);
}
{
DiscreteOrderItem item = new DiscreteOrderItemImpl();
Sku sku = new SkuImpl();
sku.setName("Test Product 2");
sku.setRetailPrice(new Money(20D));
sku.setDiscountable(true);
sku = catalogService.saveSku(sku);
item.setSku(sku);
item.setQuantity(1);
item.setOrder(order);
item = (DiscreteOrderItem) orderItemService.saveOrderItem(item);
order.addOrderItem(item);
FulfillmentGroupItem fgItem = new FulfillmentGroupItemImpl();
fgItem.setFulfillmentGroup(group);
fgItem.setOrderItem(item);
fgItem.setQuantity(1);
// fgItem.setPrice(new Money(0D));
group.addFulfillmentGroupItem(fgItem);
}
order.addOfferCode(createOfferCode("20 Percent Off Item Offer", OfferType.ORDER_ITEM, OfferDiscountType.PERCENT_OFF, 20, null, "discreteOrderItem.sku.name==\"Test Sku\""));
order.addOfferCode(createOfferCode("3 Dollars Off Item Offer", OfferType.ORDER_ITEM, OfferDiscountType.AMOUNT_OFF, 3, null, "discreteOrderItem.sku.name!=\"Test Sku\""));
order.addOfferCode(createOfferCode("1.20 Dollars Off Order Offer", OfferType.ORDER, OfferDiscountType.AMOUNT_OFF, 1.20, null, null));
order.setTotalShipping(new Money(0D));
orderService.save(order, true);
assert order.getSubTotal().subtract(order.getOrderAdjustmentsValue()).equals(new Money(31.80D));
assert (order.getTotal().greaterThan(order.getSubTotal()));
// Shipping is not taxable
assert (order.getTotalTax().equals(order.getSubTotal().subtract(order.getOrderAdjustmentsValue()).multiply(0.05D)));
// determine the total cost of the fulfillment group fees
Money fulfillmentGroupFeeTotal = getFulfillmentGroupFeeTotal(order);
assert (order.getTotal().equals(order.getSubTotal().add(order.getTotalTax()).add(order.getTotalShipping()).add(fulfillmentGroupFeeTotal).subtract(order.getOrderAdjustmentsValue())));
}
use of org.broadleafcommerce.core.order.domain.DiscreteOrderItem in project BroadleafCommerce by BroadleafCommerce.
the class PricingTest method testShipping.
@Test(groups = { "testShipping" }, dependsOnGroups = { "testShippingInsert", "createCustomerIdGeneration" })
@Transactional
public void testShipping() throws Exception {
Order order = orderService.createNewCartForCustomer(createCustomer());
customerService.saveCustomer(order.getCustomer());
FulfillmentGroup group1 = new FulfillmentGroupImpl();
FulfillmentGroup group2 = new FulfillmentGroupImpl();
// setup group1 - standard
group1.setMethod("standard");
group1.setService(ShippingServiceType.BANDED_SHIPPING.getType());
Country country = new CountryImpl();
country.setAbbreviation("US");
country.setName("United States");
country = countryService.save(country);
ISOCountry isoCountry = new ISOCountryImpl();
isoCountry.setAlpha2("US");
isoCountry.setName("UNITED STATES");
isoCountry = isoService.save(isoCountry);
State state = new StateImpl();
state.setAbbreviation("TX");
state.setName("Texas");
state.setCountry(country);
state = stateService.save(state);
Address address = new AddressImpl();
address.setAddressLine1("123 Test Rd");
address.setCity("Dallas");
address.setFirstName("Jeff");
address.setLastName("Fischer");
address.setPostalCode("75240");
address.setPrimaryPhone("972-978-9067");
address.setState(state);
address.setCountry(country);
address.setIsoCountrySubdivision("US-TX");
address.setIsoCountryAlpha2(isoCountry);
group1.setAddress(address);
group1.setOrder(order);
// setup group2 - truck
group2.setMethod("truck");
group2.setService(ShippingServiceType.BANDED_SHIPPING.getType());
group2.setOrder(order);
List<FulfillmentGroup> groups = new ArrayList<>();
groups.add(group1);
// groups.add(group2);
order.setFulfillmentGroups(groups);
Money total = new Money(8.5D);
group1.setShippingPrice(total);
group2.setShippingPrice(total);
// group1.setTotalTax(new Money(1D));
// group2.setTotalTax(new Money(1D));
order.setSubTotal(total);
order.setTotal(total);
DiscreteOrderItem item = new DiscreteOrderItemImpl();
Sku sku = new SkuImpl();
sku.setRetailPrice(new Money(15D));
sku.setDiscountable(true);
sku.setName("Test Sku");
sku = catalogService.saveSku(sku);
item.setSku(sku);
item.setQuantity(1);
item.setOrder(order);
item = (DiscreteOrderItem) orderItemService.saveOrderItem(item);
List<OrderItem> items = new ArrayList<>();
items.add(item);
order.setOrderItems(items);
for (OrderItem orderItem : items) {
FulfillmentGroupItem fgi = new FulfillmentGroupItemImpl();
fgi.setOrderItem(orderItem);
fgi.setQuantity(orderItem.getQuantity());
fgi.setFulfillmentGroup(group1);
// fgi.setRetailPrice(new Money(15D));
group1.addFulfillmentGroupItem(fgi);
}
order.setTotalShipping(new Money(0D));
orderService.save(order, true);
assert (order.getTotal().greaterThan(order.getSubTotal()));
// Shipping price is not taxable
assert (order.getTotalTax().equals(order.getSubTotal().multiply(0.05D)));
assert (order.getTotal().equals(order.getSubTotal().add(order.getTotalTax().add(order.getTotalShipping()))));
}
Aggregations