/**
* 金额分摊
* @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);
}
}