| | |
| | | import java.util.concurrent.*; |
| | | import java.util.concurrent.locks.ReentrantLock; |
| | | import java.util.stream.Collectors; |
| | | import java.util.stream.IntStream; |
| | | import java.util.stream.Stream; |
| | | import javax.annotation.Resource; |
| | | import javax.servlet.http.HttpServletRequest; |
| | |
| | | } |
| | | |
| | | if(StringUtil.isNotBlank(lycdzjhmxj) && lycdzjhmxj.equalsIgnoreCase("N")){ |
| | | BigDecimal paidIn = tjFlowingWater.getPaidIn(); |
| | | BigDecimal difference = zongjia.subtract(paidIn); |
| | | if (difference.compareTo(BigDecimal.ZERO) > 0) { |
| | | log.info("金额多出了:{}",difference); |
| | | log.info("-----------------------原明细-------------------------"); |
| | | calculateTotalPrice(array,false); |
| | | log.info("-----------------------新明细-------------------------"); |
| | | adjustPrice(array,paidIn); |
| | | zongjia = calculateTotalPrice(array,true); |
| | | } else if (difference.compareTo(BigDecimal.ZERO) < 0) { |
| | | log.info("金额缺少了:{}", difference.abs()); |
| | | log.info("-----------------------原明细-------------------------"); |
| | | calculateTotalPrice(array,false); |
| | | log.info("-----------------------新明细-------------------------"); |
| | | adjustPrice(array,paidIn); |
| | | zongjia = calculateTotalPrice(array,true); |
| | | } |
| | | map.put("feiYongInfoList", array); |
| | | }else { |
| | | zongjia = tjFlowingWater.getPaidIn(); |
| | |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 判断总价是否一致 是否进行价格补减 |
| | | * - 保证所有单价不为负数 |
| | | * - 差额分摊策略为:平均分摊 + 误差补最后一项 |
| | | * |
| | | * @param items his传递的明细项目 |
| | | * @param targetTotal 总价 |
| | | */ |
| | | public static void adjustPrice(JSONArray items, BigDecimal targetTotal) { |
| | | BigDecimal actualTotal = BigDecimal.ZERO; |
| | | int size = items.size(); |
| | | |
| | | // 计算目前明细集合总价 |
| | | for (int i = 0; i < size; i++) { |
| | | JSONObject item = items.getJSONObject(i); |
| | | BigDecimal danJia = item.getBigDecimal("danJia"); |
| | | BigDecimal shuliang = item.getBigDecimal("shuliang"); |
| | | BigDecimal jieSuanJe = danJia.multiply(shuliang).setScale(2, RoundingMode.HALF_UP); |
| | | item.set("jieSuanJe", jieSuanJe); |
| | | actualTotal = actualTotal.add(jieSuanJe); |
| | | } |
| | | BigDecimal diff = targetTotal.subtract(actualTotal).setScale(2, RoundingMode.HALF_UP); |
| | | // 无需调整 |
| | | if (diff.compareTo(BigDecimal.ZERO) == 0 || size == 0) { |
| | | return; |
| | | } |
| | | |
| | | // 剩余待分摊差额 |
| | | BigDecimal remainingDiff = diff; |
| | | for (int i = 0; i < size; i++) { |
| | | JSONObject item = items.getJSONObject(i); |
| | | BigDecimal danJia = item.getBigDecimal("danJia"); |
| | | BigDecimal shuliang = item.getBigDecimal("shuliang"); |
| | | |
| | | if (shuliang.compareTo(BigDecimal.ZERO) == 0) continue; |
| | | |
| | | // 分摊比例(平均分) |
| | | // 示例:若剩余差额 remainingDiff = 1.50,剩余 3 项,当前 portion = 1.50 ÷ 3 = 0.50 |
| | | BigDecimal portion = remainingDiff.divide(new BigDecimal(size - i), 10, RoundingMode.HALF_UP); |
| | | |
| | | // 分摊到单价上 |
| | | // 示例:portion = 0.50,shuliang = 2,deltaPerUnit = 0.25 |
| | | BigDecimal deltaPerUnit = portion.divide(shuliang, 10, RoundingMode.HALF_UP); |
| | | |
| | | // 调整单价:新单价 = 原单价 + 单位差额 |
| | | BigDecimal adjustedDanJia = danJia.add(deltaPerUnit).setScale(2, RoundingMode.HALF_UP); |
| | | |
| | | // 防止负数价格 |
| | | if (adjustedDanJia.compareTo(BigDecimal.ZERO) < 0) { |
| | | adjustedDanJia = BigDecimal.ZERO; |
| | | } |
| | | |
| | | item.set("danJia", adjustedDanJia); |
| | | BigDecimal adjustedJieSuan = adjustedDanJia.multiply(shuliang).setScale(2, RoundingMode.HALF_UP); |
| | | item.set("jieSuanJe", adjustedJieSuan); |
| | | |
| | | // 计算本次实际调整的差额,继续分摊剩余部分 |
| | | BigDecimal oldJieSuan = danJia.multiply(shuliang).setScale(2, RoundingMode.HALF_UP); |
| | | remainingDiff = remainingDiff.subtract(adjustedJieSuan.subtract(oldJieSuan)); |
| | | } |
| | | |
| | | // 若仍存在小额差额(如由于四舍五入导致),尝试把差额补到最后一项 |
| | | if (remainingDiff.abs().compareTo(new BigDecimal("0.01")) > 0) { |
| | | JSONObject lastItem = items.getJSONObject(size - 1); |
| | | BigDecimal danJia = lastItem.getBigDecimal("danJia"); |
| | | BigDecimal shuliang = lastItem.getBigDecimal("shuliang"); |
| | | if (shuliang.compareTo(BigDecimal.ZERO) != 0) { |
| | | BigDecimal delta = remainingDiff.divide(shuliang, 10, RoundingMode.HALF_UP); |
| | | BigDecimal newDanJia = danJia.add(delta).setScale(2, RoundingMode.HALF_UP); |
| | | if (newDanJia.compareTo(BigDecimal.ZERO) < 0) { |
| | | newDanJia = BigDecimal.ZERO; |
| | | } |
| | | lastItem.set("danJia", newDanJia); |
| | | BigDecimal newJieSuan = newDanJia.multiply(shuliang).setScale(2, RoundingMode.HALF_UP); |
| | | lastItem.set("jieSuanJe", newJieSuan); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 明细价格日志输出 |
| | | * @param array |
| | | */ |
| | | public static BigDecimal calculateTotalPrice(JSONArray array,Boolean isOverride) { |
| | | BigDecimal total = BigDecimal.ZERO; |
| | | for (int i = 0; i < array.size(); i++) { |
| | | JSONObject obj = array.getJSONObject(i); |
| | | BigDecimal danJia = new BigDecimal(obj.getStr("danJia", "0")).setScale(2, RoundingMode.HALF_UP); |
| | | BigDecimal shuliang = new BigDecimal(obj.getStr("shuliang", "0")).setScale(2, RoundingMode.HALF_UP); |
| | | BigDecimal jieSuanJe = danJia.multiply(shuliang).setScale(2, RoundingMode.HALF_UP); |
| | | obj.set("danJia", danJia); |
| | | obj.set("shuliang", shuliang); |
| | | obj.set("jieSuanJe", jieSuanJe); |
| | | total = total.add(jieSuanJe); |
| | | log.info(String.format("第%d项 -> 单价: %s, 数量: %s, 结算金额: %s", i + 1, danJia, shuliang, jieSuanJe)); |
| | | } |
| | | log.info("总价为: {}", total.setScale(2, RoundingMode.HALF_UP)); |
| | | if (isOverride) return total.setScale(2, RoundingMode.HALF_UP); |
| | | return null; |
| | | } |
| | | |
| | | public void addCaiYangDengJi(List<TjOrderDetail> detailList, boolean detailList1, TjOrder order, SysUser sysUser, String jxbz) { |
| | | String lis_tmh_prefix = configService.selectConfigByKey("make_lis_tmh_prefix"); |
| | | String config = configService.selectConfigByKey("sfkqdyhis"); |