Class SplitTotalRounder


  • public class SplitTotalRounder
    extends Object
    Can be used for handling rounding of amounts which need to add up to different totals.

    This tracks targeted totals in two different directions to allow rounding component amounts while still summing to those totals.

    For example, when splitting items between multiple fulfillments, this rounding method ensures that:

    1. The split versions of a particular item still sum to the original item price after rounding
    2. All the items in a particular split fulfillment sum to that split fulfillment's designated item subtotal
    • Constructor Detail

      • SplitTotalRounder

        public SplitTotalRounder​(List<List<javax.money.MonetaryAmount>> amountsOfSplits,
                                 List<javax.money.MonetaryAmount> splitTargetTotals,
                                 javax.money.MonetaryAmount unitAmount,
                                 @Nullable
                                 com.broadleafcommerce.order.client.domain.OrderFulfillment originalFulfillment)
        Create a new SplitTotalRounder to round amounts which have been split.
        Parameters:
        amountsOfSplits - a list where each element represents one part of a split, each of which contains a list of amounts containing the split portion of the original amount which was assigned to that part
        splitTargetTotals - the target total for each split part
        unitAmount - the smallest unit of the currency
        originalFulfillment - the original fulfillment which was split, if splitting a fulfillment
    • Method Detail

      • roundAmounts

        public void roundAmounts()
        Rounds the contained amounts so that each split side sums to the target totals, and each split amount sums to its original value.

        All amounts are first rounded to floor, and then units are distributed for each side of the split.

      • distributeAmountUnits

        protected void distributeAmountUnits​(int splitIndex)
        Distributes units to one split part, indicated by the given splitIndex into one of the parts of each element of amounts.
        Parameters:
        splitIndex - the index into the SplitTotalRounder.SplitAmount.splitAmounts, indicating which part of the split to distribute units to
      • distributeUnitsForAmounts

        protected void distributeUnitsForAmounts​(Function<SplitTotalRounder.SplitAmount,​javax.money.MonetaryAmount> getAmount,
                                                 Function<SplitTotalRounder.SplitAmount,​javax.money.MonetaryAmount> getRemainder,
                                                 Consumer<SplitTotalRounder.SplitAmount> incrementAmount,
                                                 javax.money.MonetaryAmount targetTotal)
        Distributes units to amounts on one part of the split until the given targetTotal is reached. An amount will only be incremented if it has not already reached the correct total across that amount.

        This implementation only handles unit-rounding, and will never distribute more than one unit to each amount. This should always be sufficient to reach the target total. If some erroneous case occurs where the target total cannot be reached, extra units will not be distributed, and the amounts will not add up to the target total.

        Parameters:
        getAmount - getter for the amount on this side of the split
        getRemainder - getter for the remainder on this side of the split
        incrementAmount - method to increment the amount on this side of the split
        targetTotal - the total which the amounts on this side of the split should sum to
      • getAmountsForSplit

        public List<javax.money.MonetaryAmount> getAmountsForSplit​(int splitIndex)
        Retrieve the amounts for one split part.
        Parameters:
        splitIndex - the index of the part which was split to retrieve
        Returns:
        a list of all the amounts for a specific split part
      • getOriginalFulfillment

        @Nullable
        protected com.broadleafcommerce.order.client.domain.OrderFulfillment getOriginalFulfillment()
        The original fulfillment which was split.
      • getSplitTargetTotals

        protected List<javax.money.MonetaryAmount> getSplitTargetTotals()
        The amounts which all of the amounts for a specific split part should sum to.
      • getUnitAmount

        protected javax.money.MonetaryAmount getUnitAmount()
        The smallest unit of the currency.
      • setSplitTargetTotals

        protected void setSplitTargetTotals​(List<javax.money.MonetaryAmount> splitTargetTotals)
        The amounts which all of the amounts for a specific split part should sum to.
      • setUnitAmount

        protected void setUnitAmount​(javax.money.MonetaryAmount unitAmount)
        The smallest unit of the currency.