@Override public Money calculateSubTotal() { Money calculatedSubTotal = BroadleafCurrencyUtils.getMoney(getCurrency()); for (OrderItem orderItem : orderItems) { calculatedSubTotal = calculatedSubTotal.add(orderItem.getTotalPrice()); } return calculatedSubTotal; }
/** * Because an item may have multiple price details that don't round cleanly, we may have pennies * left over that need to be distributed. * * This method may not be needed because the sum of the item amounts is derived from a double price (OrderItem's total) * being multiplied and divided by whole numbers of which guarantees that each item amount is a clean multiple * of the price of a single unit of that item. This behavior being enforced in populateItemTotalAmount. So we will * never get a fraction of a cent that could cause totalItemAmount and totalFGItemAmount to be different values. * * @param order * @param partialOrderItemMap */ protected void fixItemTotalRoundingIssues(Order order, Map<OrderItem, List<FulfillmentGroupItem>> partialOrderItemMap) { for (OrderItem orderItem : partialOrderItemMap.keySet()) { Money totalItemAmount = orderItem.getTotalPrice(); Money totalFGItemAmount = sumItemAmount(partialOrderItemMap.get(orderItem), order); Money amountDiff = totalItemAmount.subtract(totalFGItemAmount); if (!(amountDiff.getAmount().compareTo(BigDecimal.ZERO) == 0)) { long numApplicationsNeeded = countNumberOfUnits(amountDiff); Money unitAmount = getUnitAmount(amountDiff); for (FulfillmentGroupItem fgItem : partialOrderItemMap.get(orderItem)) { numApplicationsNeeded = numApplicationsNeeded - applyDifferenceToAmount(fgItem, numApplicationsNeeded, unitAmount); if (numApplicationsNeeded == 0) { break; } } } } }
/** * Sets the fulfillment amount which includes the relative portion of the total price for * the corresponding order item. * * @param order * @param partialOrderItemMap */ protected void populateItemTotalAmount(Order order, Map<OrderItem, List<FulfillmentGroupItem>> partialOrderItemMap) { for (FulfillmentGroup fulfillmentGroup : order.getFulfillmentGroups()) { for (FulfillmentGroupItem fgItem : fulfillmentGroup.getFulfillmentGroupItems()) { OrderItem orderItem = fgItem.getOrderItem(); int fgItemQty = fgItem.getQuantity(); int orderItemQty = orderItem.getQuantity(); Money totalItemAmount = orderItem.getTotalPrice(); if (fgItemQty != orderItemQty) { // We need to keep track of all of these items in case we need to distribute a remainder // to one or more of the items. List<FulfillmentGroupItem> fgItemList = partialOrderItemMap.get(orderItem); if (fgItemList == null) { fgItemList = new ArrayList<>(); partialOrderItemMap.put(orderItem, fgItemList); } fgItemList.add(fgItem); fgItem.setTotalItemAmount(totalItemAmount.multiply(fgItemQty).divide(orderItemQty)); } else { fgItem.setTotalItemAmount(totalItemAmount); } } } }
@Override public Money getTotalPrice() { Money returnValue = convertToMoney(BigDecimal.ZERO); if (shouldSumItems()) { for (OrderItem containedItem : getOrderItems()) { returnValue = returnValue.add(containedItem.getTotalPrice()); } returnValue = returnValue.multiply(quantity); } else { returnValue = super.getTotalPrice(); } return returnValue; }
@Override public Money getTotalPrice(boolean includeChildren) { Money returnValue = convertToMoney(BigDecimal.ZERO); if (orderItemPriceDetails != null && orderItemPriceDetails.size() > 0) { for (OrderItemPriceDetail oipd : orderItemPriceDetails) { returnValue = returnValue.add(oipd.getTotalAdjustedPrice()); } } else { if (price != null) { returnValue = convertToMoney(price).multiply(quantity); } else { returnValue = getSalePrice().multiply(quantity); } } if (includeChildren) { for (OrderItem child : getChildOrderItems()) { Money childPrice = child.getTotalPrice();//.multiply(quantity); returnValue = returnValue.add(childPrice); } } return returnValue; }
@Override public ProcessContext<Order> execute(ProcessContext<Order> context) throws Exception { Order order = context.getSeedData(); for(FulfillmentGroup fulfillmentGroup : order.getFulfillmentGroups()) { Money merchandiseTotal = BroadleafCurrencyUtils.getMoney(BigDecimal.ZERO, fulfillmentGroup.getOrder().getCurrency()); for(FulfillmentGroupItem fulfillmentGroupItem : fulfillmentGroup.getFulfillmentGroupItems()) { OrderItem item = fulfillmentGroupItem.getOrderItem(); merchandiseTotal = merchandiseTotal.add(item.getTotalPrice()); } fulfillmentGroup.setMerchandiseTotal(merchandiseTotal); } context.setSeedData(order); return context; }
String.valueOf(oi.getAverageAdjustmentValue()), String.valueOf(oi.getTotalAdjustmentValue()), String.valueOf(oi.getTotalPrice()) });
public void testBundleDistribution() throws Exception { Order order = dataProvider.createOrderWithBundle(); Money subTotal = new Money(order.getCurrency()); for (OrderItem orderItem : order.getOrderItems()) { subTotal = subTotal.add(orderItem.getTotalPrice()); } order.setSubTotal(subTotal); OrderAdjustment adjustment = new OrderAdjustmentImpl(); adjustment.setValue(new Money(new BigDecimal("1"), order.getCurrency())); adjustment.setOrder(order); order.getOrderAdjustments().add(adjustment); ProcessContext<Order> context = new DefaultProcessContextImpl<Order>(); context.setSeedData(order); fulfillmentItemPricingActivity.execute(context); assertTrue(sumProratedOfferAdjustments(order).equals( new Money(new BigDecimal("1"), order.getCurrency()))); }
public void testRoundingRequired() throws Exception { Order order = dataProvider.createBasicOrder(); Money subTotal = new Money(order.getCurrency()); for (OrderItem orderItem : order.getOrderItems()) { orderItem.getOrderItemPriceDetails().clear(); orderItem.setQuantity(2); orderItem.setSalePrice(new Money(10D)); subTotal = subTotal.add(orderItem.getTotalPrice()); } order.setSubTotal(subTotal); OrderAdjustment adjustment = new OrderAdjustmentImpl(); adjustment.setValue(new Money(new BigDecimal(".05"), order.getCurrency())); adjustment.setOrder(order); order.getOrderAdjustments().add(adjustment); ProcessContext<Order> context = new DefaultProcessContextImpl<Order>(); context.setSeedData(order); fulfillmentItemPricingActivity.execute(context); assertTrue(sumProratedOfferAdjustments(order).equals( new Money(new BigDecimal(".05"), order.getCurrency()))); }
public void testBundleDistributionWithoutItemSum() throws Exception { Order order = dataProvider.createOrderWithBundle(); Money subTotal = new Money(order.getCurrency()); for (OrderItem orderItem : order.getOrderItems()) { if (orderItem instanceof BundleOrderItem) { BundleOrderItem bItem = (BundleOrderItem) orderItem; bItem.getProductBundle().setPricingModel(ProductBundlePricingModelType.BUNDLE); } subTotal = subTotal.add(orderItem.getTotalPrice()); } order.setSubTotal(subTotal); OrderAdjustment adjustment = new OrderAdjustmentImpl(); adjustment.setValue(new Money(new BigDecimal("1"), order.getCurrency())); adjustment.setOrder(order); order.getOrderAdjustments().add(adjustment); ProcessContext<Order> context = new DefaultProcessContextImpl<Order>(); context.setSeedData(order); fulfillmentItemPricingActivity.execute(context); assertTrue(sumProratedOfferAdjustments(order).equals( new Money(new BigDecimal("1"), order.getCurrency()))); } }
public void testDistributeOneDollarAcrossFiveEqualItems() throws Exception { Order order = dataProvider.createBasicOrder(); Money subTotal = new Money(order.getCurrency()); for (OrderItem orderItem : order.getOrderItems()) { orderItem.setSalePrice(new Money(10D)); orderItem.getOrderItemPriceDetails().clear(); subTotal = subTotal.add(orderItem.getTotalPrice()); } OrderAdjustment adjustment = new OrderAdjustmentImpl(); adjustment.setValue(new Money(new BigDecimal("1"), order.getCurrency())); order.getOrderAdjustments().add(adjustment); adjustment.setOrder(order); order.setSubTotal(subTotal); ProcessContext<Order> context = new DefaultProcessContextImpl<Order>(); context.setSeedData(order); fulfillmentItemPricingActivity.execute(context); // Each item is equally priced, so the adjustment should be .20 per item. Money proratedAdjustment = new Money(".20"); for (FulfillmentGroup fulfillmentGroup : order.getFulfillmentGroups()) { for (FulfillmentGroupItem fulfillmentGroupItem : fulfillmentGroup.getFulfillmentGroupItems()) { assertTrue(fulfillmentGroupItem.getProratedOrderAdjustmentAmount().compareTo( proratedAdjustment.multiply(fulfillmentGroupItem.getQuantity())) == 0); } } }