This commit is contained in:
磷叶 2025-04-17 09:56:49 +08:00
parent 47a2ced150
commit 81260e34c9
3 changed files with 81 additions and 79 deletions

View File

@ -70,7 +70,7 @@ public class BonusConverterImpl implements BonusConverter {
// 设置分成金额
Order order = bo.getOrder();
BatUtil.partAmount(result, order.getPayAmount());
BonusUtil.partAmount(result, order.getPayAmount());
// 设置其他基础数据
String reason = "订单收入:" + order.getNo();

View File

@ -155,4 +155,84 @@ public class BonusUtil {
return refundList;
}
/**
* 分成金额
* @param bonusList 分成列表
* @param totalAmount 总金额
*/
public static void partAmount(List<Bonus> bonusList, BigDecimal totalAmount) {
if (totalAmount == null || totalAmount.compareTo(BigDecimal.ZERO) < 0) {
throw new ServiceException("分成总金额不允许小于0");
}
BigDecimal decimal100 = new BigDecimal("100");
// 循环遍历构造分成金额
for (Bonus bonus : bonusList) {
if (bonus != null && bonus.getPoint() != null) {
BigDecimal amount = totalAmount.multiply(bonus.getPoint()).divide(decimal100, 2, RoundingMode.HALF_UP);
setAmount(bonus, amount);
}
}
// 处理误差
BigDecimal dividedAmount = CollectionUtils.sumDecimal(bonusList, Bonus::getAmount);
handlePartDiff(bonusList, totalAmount.subtract(dividedAmount));
// 处理误差后的分配金额
dividedAmount = CollectionUtils.sumDecimal(bonusList, Bonus::getAmount);
ServiceUtil.assertion(dividedAmount.compareTo(totalAmount) != 0, "分成金额分配出错");
}
/**
* 处理分成的误差
*/
public static void handlePartDiff(List<? extends Bonus> bonusList, BigDecimal diff) {
// 若误差金额为0则不处理
if (diff == null || diff.compareTo(BigDecimal.ZERO) == 0) {
return;
}
// 若误差金额为正数则交给第一个分成方处理
if (diff.compareTo(BigDecimal.ZERO) > 0) {
Bonus bonus = bonusList.get(0);
setAmount(bonus, bonus.getAmount().add(diff));
}
// 否则若为负数则多个分成方处理
else {
// 多个分成方共同承担误差
BigDecimal remainingDiff = diff;
for (Bonus bonus : bonusList) {
if (bonus == null || bonus.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
continue;
}
// 计算当前分成方可以承担的误差金额确保不会导致金额为负
BigDecimal maxDeductible = bonus.getAmount(); // 最大可扣除金额
BigDecimal adjustAmount = maxDeductible.min(remainingDiff.abs());
// 直接调整金额
setAmount(bonus, bonus.getAmount().subtract(adjustAmount));
remainingDiff = remainingDiff.add(adjustAmount);
// 如果误差已经分配完毕则退出
if (remainingDiff.compareTo(BigDecimal.ZERO) == 0) {
return;
}
}
// 如果所有分成方都处理完了还有剩余误差抛出异常
if (remainingDiff.compareTo(BigDecimal.ZERO) != 0) {
throw new ServiceException("分成金额误差处理失败:无法完全分配误差金额,剩余误差:" + remainingDiff);
}
}
}
private static void setAmount(Bonus bonus, BigDecimal amount) {
ServiceUtil.assertion(amount.compareTo(BigDecimal.ZERO) < 0, "分成金额不允许小于0");
bonus.setAmount(amount);
}
}

View File

@ -90,82 +90,4 @@ public class BatUtil {
}
}
/**
* 分成金额
* @param result 分成列表
* @param amount 总金额
*/
public static void partAmount(List<Bonus> bonusList, BigDecimal totalAmount) {
if (totalAmount == null || totalAmount.compareTo(BigDecimal.ZERO) < 0) {
throw new ServiceException("分成总金额不允许小于0");
}
BigDecimal decimal100 = new BigDecimal("100");
// 循环遍历构造分成金额
for (Bonus bonus : bonusList) {
if (bonus != null && bonus.getPoint() != null) {
BigDecimal amount = totalAmount.multiply(bonus.getPoint()).divide(decimal100, 2, RoundingMode.HALF_UP);
setAmount(bonus, amount);
}
}
// 处理误差
BigDecimal dividedAmount = CollectionUtils.sumDecimal(bonusList, Bonus::getAmount);
handlePartDiff(bonusList, totalAmount.subtract(dividedAmount));
// 处理误差后的分配金额
dividedAmount = CollectionUtils.sumDecimal(bonusList, Bonus::getAmount);
ServiceUtil.assertion(dividedAmount.compareTo(totalAmount) != 0, "分成金额分配出错");
}
/**
* 处理分成的误差
*/
public static void handlePartDiff(List<? extends Bonus> bonusList, BigDecimal diff) {
// 若误差金额为0则不处理
if (diff == null || diff.compareTo(BigDecimal.ZERO) == 0) {
return;
}
// 若误差金额为正数则交给第一个分成方处理
if (diff.compareTo(BigDecimal.ZERO) > 0) {
Bonus bonus = bonusList.get(0);
setAmount(bonus, bonus.getAmount().add(diff));
}
// 否则若为负数则多个分成方处理
else {
// 多个分成方共同承担误差
BigDecimal remainingDiff = diff;
for (Bonus bonus : bonusList) {
if (bonus == null || bonus.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
continue;
}
// 计算当前分成方可以承担的误差金额确保不会导致金额为负
BigDecimal maxDeductible = bonus.getAmount(); // 最大可扣除金额
BigDecimal adjustAmount = maxDeductible.min(remainingDiff.abs());
// 直接调整金额
setAmount(bonus, bonus.getAmount().subtract(adjustAmount));
remainingDiff = remainingDiff.add(adjustAmount);
// 如果误差已经分配完毕则退出
if (remainingDiff.compareTo(BigDecimal.ZERO) == 0) {
return;
}
}
// 如果所有分成方都处理完了还有剩余误差抛出异常
if (remainingDiff.compareTo(BigDecimal.ZERO) != 0) {
throw new ServiceException("分成金额误差处理失败:无法完全分配误差金额,剩余误差:" + remainingDiff);
}
}
}
private static void setAmount(Bonus bonus, BigDecimal amount) {
ServiceUtil.assertion(amount.compareTo(BigDecimal.ZERO) < 0, "分成金额不允许小于0");
bonus.setAmount(amount);
}
}