From 4561277babc9c98bd018d48bf554e626db4fdbcc Mon Sep 17 00:00:00 2001 From: OpenClaw Agent Date: Sat, 4 Apr 2026 04:20:00 +0000 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=BB=A1=E5=87=8F?= =?UTF-8?q?=E9=87=91=E9=A2=9D=E8=AE=A1=E7=AE=97=E7=B2=BE=E5=BA=A6=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题:使用 (商品原价/总价)*满减金额 的除法优先顺序,当满减金额为0.98时, 由于divide精度为3位HALF_EVEN,计算结果可能产生如0.979这样的多位小数, 导致最终优惠金额少了约0.02元。 修复:改为 乘法优先再除法 originalPrice.multiply(reducePrice).divide(totalAmount, 2, RoundingMode.HALF_EVEN), 保证最终结果精确到分(2位小数),符合人民币货币精度。 同时确保使用 RoundingMode.HALF_EVEN 保持与原有代码一致。 Fixes #492 --- .../mall/portal/service/impl/OmsPromotionServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPromotionServiceImpl.java b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPromotionServiceImpl.java index 73a3351cb0..bbec4267c2 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPromotionServiceImpl.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPromotionServiceImpl.java @@ -88,10 +88,10 @@ public List calcCartPromotion(List cartItemList) BeanUtils.copyProperties(item,cartPromotionItem); String message = getFullReductionPromotionMessage(fullReduction); cartPromotionItem.setPromotionMessage(message); - //(商品原价/总价)*满减金额 + //(商品原价/总价)*满减金额,使用 multiply-divide 顺序避免 divide 精度损失 PmsSkuStock skuStock= getOriginalPrice(promotionProduct, item.getProductSkuId()); BigDecimal originalPrice = skuStock.getPrice(); - BigDecimal reduceAmount = originalPrice.divide(totalAmount,RoundingMode.HALF_EVEN).multiply(fullReduction.getReducePrice()); + BigDecimal reduceAmount = originalPrice.multiply(fullReduction.getReducePrice()).divide(totalAmount, 2, RoundingMode.HALF_EVEN); cartPromotionItem.setReduceAmount(reduceAmount); cartPromotionItem.setRealStock(skuStock.getStock()-skuStock.getLockStock()); cartPromotionItem.setIntegration(promotionProduct.getGiftPoint()); From 8d1dab084cc1be0df114c01245e3bd36cad36d78 Mon Sep 17 00:00:00 2001 From: OpenClaw Bot Date: Sun, 19 Apr 2026 04:26:21 +0000 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=BC=98=E6=83=A0?= =?UTF-8?q?=E5=88=B8=E9=87=91=E9=A2=9D=E5=88=86=E6=91=8A=E8=AE=A1=E7=AE=97?= =?UTF-8?q?=E7=B2=BE=E5=BA=A6=E9=97=AE=E9=A2=98=20(Issue=20#356)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原算法对每个商品独立计算分摊金额并四舍五入到3位小数, 导致各商品分摊金额之和可能小于优惠券面额。 修复方案: - 对前 n-1 个商品按比例计算分摊金额 - 最后一个商品获取剩余金额,确保分摊总额精确等于优惠券面额 - 最终金额四舍五入到2位小数 --- .../impl/OmsPortalOrderServiceImpl.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPortalOrderServiceImpl.java b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPortalOrderServiceImpl.java index 0c35e4e7d1..1df5089eed 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPortalOrderServiceImpl.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPortalOrderServiceImpl.java @@ -673,9 +673,21 @@ private void handleCouponAmount(List orderItemList, SmsCouponHisto */ private void calcPerCouponAmount(List orderItemList, SmsCoupon coupon) { BigDecimal totalAmount = calcTotalAmount(orderItemList); - for (OmsOrderItem orderItem : orderItemList) { - //(商品价格/可用商品总价)*优惠券面额 - BigDecimal couponAmount = orderItem.getProductPrice().divide(totalAmount, 3, RoundingMode.HALF_EVEN).multiply(coupon.getAmount()); + BigDecimal couponAmountTotal = coupon.getAmount(); + BigDecimal remainingAmount = couponAmountTotal; + int size = orderItemList.size(); + for (int i = 0; i < size; i++) { + OmsOrderItem orderItem = orderItemList.get(i); + BigDecimal couponAmount; + if (i < size - 1) { + //(商品价格/可用商品总价)*优惠券面额 + couponAmount = orderItem.getProductPrice().divide(totalAmount, 3, RoundingMode.HALF_EVEN).multiply(couponAmountTotal); + remainingAmount = remainingAmount.subtract(couponAmount); + } else { + // last item gets the remainder to ensure total equals coupon amount + couponAmount = remainingAmount; + } + couponAmount = couponAmount.setScale(2, RoundingMode.HALF_UP); orderItem.setCouponAmount(couponAmount); } }