金额按比例分摊

/**
 * 金额分摊
 * @author 
 */
public class BizSplitAmountUtil {
    /**
     * 分摊金额
     * @param shareBig 分摊的金额
     * @param list 分摊的对象
     * @param getParam 指定计算分摊比例的金额属性
     * @param setParam 指定分摊后的金额属性
     * @param <R>
     */
    public static <R> void share(BigDecimal shareBig, List<R> list, Function<R, BigDecimal> getParam, BiFunction<R,BigDecimal,R> setParam) {
        //累计可理算金额
        BigDecimal sum = BigDecimal.ZERO;
        for (R entry : list) {
            BigDecimal amount = getParam.apply(entry);
            sum = BigDecimalUtil.add(sum,amount);
        }

        //累计可理算金额为0,则跳过分摊
        if (sum.equals(BigDecimal.ZERO)) {
            return;
        }

        //剩余分摊金额
        BigDecimal surplusBig = shareBig;
        for (int i = 0; i < list.size(); i++) {
            R entry = list.get(i);
            BigDecimal amount = getParam.apply(entry);
            //可理算金额为0时,跳过
            if (amount.equals(BigDecimal.ZERO)) {
                continue;
            }

            //分摊后的钱
            BigDecimal shareAmount;
            if (list.size() - 1 == i) {
                //最后一条明细,分摊金额为剩余分摊金额
                shareAmount = surplusBig;
            } else {
                //计算分摊比例:可理算金额/总可理算金额
                BigDecimal ratio = BigDecimalUtil.divideProcess(amount, sum);
                //计算分摊金额:分摊金额*分摊比例
                shareAmount = BigDecimalUtil.multiplyMoney(shareBig, ratio);
                //分摊金额大于剩余分摊金额  剩余金额给它
                if (shareAmount.compareTo(surplusBig) > 0) {
                    shareAmount = surplusBig;
                }
                //计算剩余分摊金额
                surplusBig = BigDecimalUtil.subZero(surplusBig, shareAmount);
            }
            //把分摊后的钱放到对象中
            setParam.apply(entry, shareAmount);
        }
        
        
    }

    /**
     * 演示
     * @param args
     */
    public static void main(String[] args) {

        List<TreatmentInfo> list = new ArrayList<>();
        TreatmentInfo t1 =  new TreatmentInfo();
        t1.setCalcAdjustedAmount(new BigDecimal("20"));
        TreatmentInfo t2 =  new TreatmentInfo();
        t2.setCalcAdjustedAmount(new BigDecimal("30"));
        TreatmentInfo t3 =  new TreatmentInfo();
        t3.setCalcAdjustedAmount(new BigDecimal("60"));
        list.add(t1);
        list.add(t2);
        list.add(t3);
        BigDecimal sum = new BigDecimal("100");
        share(sum,list,TreatmentInfo::getCalcAdjustedAmount,(treatmentInfo, shareAmount)->{
            treatmentInfo.setCalcPreviousDutyAmount(shareAmount);
            return treatmentInfo;
        });
        for (TreatmentInfo treatmentInfo : list) {
            System.out.println(treatmentInfo.getCalcPreviousDutyAmount());
        }
    }
}
public class BigDecimalUtil {
    /**
     * BigDecimal空指针处理
     *
     * @param bigDecimal
     * @return
     */
    public static BigDecimal notNull(BigDecimal bigDecimal) {
        return ObjectUtil.defaultIfNull(bigDecimal, new BigDecimal(0));
    }

    /**
     * BigDecimal转str
     *
     * @param bigDecimal
     * @return
     */
    public static String toStr(BigDecimal bigDecimal) {
        return Objects.isNull(bigDecimal) ? "" : bigDecimal.toString();
    }

    /**
     * 字符转数字
     *
     * @param str
     * @return
     */
    public static BigDecimal strToBigDecimal(String str) {
        if (StringUtils.isBlank(str)) {
            return null;
        }
        if (NumberUtil.isNumber(str)) {
            return new BigDecimal(str);
        }
        return null;
    }

    /**
     * 带逗号数据处理
     *
     * @param str
     * @return
     */
    public static BigDecimal createBigDecimalFromString(String str) {
        try {
            if (StringUtils.isBlank(str)) {
                return null;
            }
            str = str.replace(",", "");
            if (NumberUtil.isNumber(str)) {
                return new BigDecimal(str);
            }
        } catch (NumberFormatException e) {

        }
        return null;
    }

    public static BigDecimal add(BigDecimal... bigDecimals) {
        BigDecimal sum = BigDecimal.ZERO;
        for (BigDecimal decimal : bigDecimals) {
            sum = sum.add(decimal == null ? BigDecimal.ZERO : decimal);
        }
        return sum;
    }

    public static BigDecimal sub(BigDecimal subBigDecimal, BigDecimal... bigDecimals) {
        subBigDecimal = notNull(subBigDecimal);
        for (BigDecimal decimal : bigDecimals) {
            subBigDecimal = subBigDecimal.subtract(decimal == null ? BigDecimal.ZERO : decimal);
        }
        return subBigDecimal;
    }

    /**
     * 减值处理,负数当做0处理
     *
     * @param subBigDecimal
     * @param bigDecimals
     * @return
     */
    public static BigDecimal subZero(BigDecimal subBigDecimal, BigDecimal... bigDecimals) {
        subBigDecimal = notNull(subBigDecimal);
        for (BigDecimal decimal : bigDecimals) {
            subBigDecimal = subBigDecimal.subtract(decimal == null ? BigDecimal.ZERO : decimal);
        }
        return subBigDecimal.compareTo(BigDecimal.ZERO) > 0 ? subBigDecimal : BigDecimal.ZERO;
    }

    /**
     * 百分比转换为小数
     *
     * @param originalRatio
     * @return
     */
    public static BigDecimal ratio(BigDecimal originalRatio) {
        originalRatio = notNull(originalRatio);
        return originalRatio.divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
    }

    /**
     * 百分比还原
     *
     * @param originalRatio
     * @return
     */
    public static BigDecimal ratioReturn(BigDecimal originalRatio) {
        originalRatio = notNull(originalRatio);
        return originalRatio.multiply(new BigDecimal(100));
    }

    /**
     * 金额处理,保留2位小数,默认四舍五入
     *
     * @param originalMoney
     * @return
     */
    public static BigDecimal money(BigDecimal originalMoney) {
        originalMoney = notNull(originalMoney);
        return originalMoney.setScale(2, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 乘法
     *
     * @param multiplyDecimal 被乘数
     * @param bigDecimals     乘数
     * @return BigDecimal
     */
    public static BigDecimal multiplyMoney(BigDecimal multiplyDecimal, BigDecimal... bigDecimals) {
        multiplyDecimal = notNull(multiplyDecimal);
        for (BigDecimal bigDecimal : bigDecimals) {
            multiplyDecimal = multiplyDecimal.multiply(notNull(bigDecimal));
        }
        return money(multiplyDecimal);
    }

    /**
     * 除值,计算过程中,精确6位小数
     * @param divideBigDecimal
     * @param bigDecimal
     * @return
     */
    public static BigDecimal divideProcess(BigDecimal divideBigDecimal, BigDecimal bigDecimal) {
        divideBigDecimal = notNull(divideBigDecimal);
        if (bigDecimal == null) {
            bigDecimal = BigDecimal.ONE;
        }
        return divideBigDecimal.divide(bigDecimal, 6, BigDecimal.ROUND_HALF_UP);
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值