我是靠谱客的博主 拉长御姐,这篇文章主要介绍三级订单上的奖学金分摊错误,最后算出负数,现在分享给大家,希望可以做个参考。

问题复现:

 //总支付金额(不包含奖学金)
        BigDecimal sumPayedAmountNotScholarship = new BigDecimal(orderItems.stream().mapToInt(OrderAmountUtil::getOrderItemPayAmountNotScholarship).sum());

        //记录已经使用的奖学金
        BigDecimal useItemScholarShip = new BigDecimal("0");

        for (int i = 0; i < orderItems.size(); i++) {
            OrderItem orderItem = orderItems.get(i);

            //三级订单支付金额(不包含奖学金)
            BigDecimal itemPayedAmountNotScholarship = new BigDecimal(String.valueOf(OrderAmountUtil.getOrderItemPayAmountNotScholarship(orderItem)));

            if (itemPayedAmountNotScholarship.compareTo(BigDecimal.ZERO) < 0) {
                log.error("奖学金优惠后分摊金额小于0,{}", JsonUtil.toString(orderItem));
                return PlatformReturn.failure("优惠后分摊金额不能小于0,请重新下单");
            }

            //奖学金平摊金额 注意:这里必须先乘再除 否则除了之后直接变为0
            BigDecimal itemScholarShip = itemPayedAmountNotScholarship.multiply(sumScholarship).divide(sumPayedAmountNotScholarship, RoundingMode.HALF_UP);
            if (i == orderItems.size() - 1) {
                itemScholarShip = sumScholarship.subtract(useItemScholarShip);
            }

            orderItem.setScholarship(itemScholarShip.intValue());
            useItemScholarShip = useItemScholarShip.add(itemScholarShip);
        }

问题分析:

1.这里注意,BigDecimal 的 除法 和成法运算 顺序必须是 先乘后除,否则先除小数点都会直接变为0

2.这里数据库金额存的是分为单位的int类型,所以这里分摊不用BigDecaimal 参数来承接也可以,但是运算需要用BigDecimal 来进行乘除

3.由于四舍五入,itemSchlarShip 算出来的金额 可能比 useItemScholarShip 大,这也是最终算出负数的原因

4.注意这里的itemPayedAmountNotScholarship必须大于0,否则最后一笔0元订单可能分摊部分奖学金

解决方案:

//总支付金额(不包含奖学金)
        BigDecimal sumPayedAmountNotScholarship = new BigDecimal(orderItems.stream().mapToInt(OrderAmountUtil::getOrderItemPayAmountNotScholarship).sum());

        //记录已经使用的奖学金
        int useItemScholarShip = 0;

        for (int i = 0; i < orderItems.size(); i++) {
            OrderItem orderItem = orderItems.get(i);

            //三级订单支付金额(不包含奖学金)
            BigDecimal itemPayedAmountNotScholarship = new BigDecimal(String.valueOf(OrderAmountUtil.getOrderItemPayAmountNotScholarship(orderItem)));

            if (itemPayedAmountNotScholarship.compareTo(BigDecimal.ZERO) < 0) {
                log.error("奖学金优惠后分摊金额小于0,{}", JsonUtil.toString(orderItem));
                return PlatformReturn.failure("优惠后分摊金额不能小于0,请重新下单");
            }

            int itemScholarShip = 0;
            //最后一个三级订单
            if (i == orderItems.size() - 1) {
                itemScholarShip = sumScholarship.intValue() - useItemScholarShip;
            } else {
                //奖学金平摊金额 注意:这里必须先乘再除 否则除了之后直接变为0
                itemScholarShip = itemPayedAmountNotScholarship.multiply(sumScholarship).divide(sumPayedAmountNotScholarship, RoundingMode.HALF_UP).intValue();

                //判断当前三级订单平摊的奖学金,是否超出了总奖学金
                if (itemScholarShip > sumScholarship.intValue()) {
                    itemScholarShip = sumScholarship.intValue();
                }

                //判断所有三级订单合计平摊的奖学金,是否超出了总奖学金
                if (useItemScholarShip + itemScholarShip > sumScholarship.intValue()) {
                    itemScholarShip = sumScholarship.intValue() - useItemScholarShip;
                }
            }

            if (itemScholarShip < 0) {
                log.error("奖学金分摊异常,itemScholarShip < 0,context:{},orderItems:{},sumScholarship:{}",
                        JsonUtil.toString(context), JsonUtil.toString(orderItems), sumScholarship);
                return PlatformReturn.failure("网络异常,请稍候重试");
            }

            useItemScholarShip += itemScholarShip;
            orderItem.setScholarship(itemScholarShip);
        }


        //奖学金都为0,设置最后一个三级订单为奖学金总额
        if (orderItems.stream().noneMatch(a -> a.getScholarship() > 0)) {
            orderItems.get(orderItems.size() - 1).setScholarship(sumScholarship.intValue());
        }

最后

以上就是拉长御姐最近收集整理的关于三级订单上的奖学金分摊错误,最后算出负数的全部内容,更多相关三级订单上内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(170)

评论列表共有 0 条评论

立即
投稿
返回
顶部