退款状态问题,全部退款,就取消订单
This commit is contained in:
parent
b13eecbb8d
commit
088d1cb93a
@ -13,6 +13,7 @@ import java.math.RoundingMode;
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class LklSeparateDTO {
|
||||
|
||||
// 基础金额属性
|
||||
private Integer totalSeparateAmount; // 分账总金额(分)
|
||||
private Integer canSeparateAmount; // 可分账金额(分)
|
||||
@ -41,8 +42,8 @@ public class LklSeparateDTO {
|
||||
LklSeparateDTO dto = new LklSeparateDTO();
|
||||
|
||||
// 设置测试参数 - 正常情况
|
||||
dto.setTotalSeparateAmount(800); // 分账总额 1000分
|
||||
dto.setShippingFee(500); // 配送费 100分
|
||||
dto.setTotalSeparateAmount(1000); // 分账总额 1000分
|
||||
dto.setShippingFee(100); // 配送费 100分
|
||||
dto.setLklRatio(new BigDecimal("0.0025")); // 拉卡拉分账比例 0.0025
|
||||
dto.setMchRatio(new BigDecimal("0.94")); // 商家分账比例 0.94
|
||||
dto.setPlatRatio(new BigDecimal("0.06")); // 平台分账比例 0.01
|
||||
@ -60,11 +61,12 @@ public class LklSeparateDTO {
|
||||
// 测试基于可分账金额的分账算法(正常情况)
|
||||
System.out.println("\n=== 基于可分账金额的分账算法测试(正常情况) ===");
|
||||
LklSeparateDTO dto2 = new LklSeparateDTO();
|
||||
dto2.setTotalSeparateAmount(800); // 分账总额 1000分
|
||||
dto2.setTotalSeparateAmount(990); // 分账总额 1000分
|
||||
dto2.setShippingFee(500); // 配送费 100分
|
||||
dto2.setRefCanSeparateAmount(null);
|
||||
dto2.setLklRatio(new BigDecimal("0.0025")); // 拉卡拉分账比例 0.0025
|
||||
dto2.setMchRatio(new BigDecimal("0.94")); // 商家分账比例 0.857 (会产生小数)
|
||||
dto2.setPlatRatio(new BigDecimal("0.06")); // 平台分账比例 0.01
|
||||
dto2.setPlatRatio(new BigDecimal("0.01")); // 平台分账比例 0.01
|
||||
// 不设置一级和二级代理商分账比例,测试不参与分账的情况
|
||||
// dto2.setAgent1stRatio(new BigDecimal("0.01")); // 一级代理商分账比例 0.023 (会产生小数)
|
||||
// dto2.setAgent2ndRatio(new BigDecimal("0.04")); // 二级代理商分账比例 0.031 (会产生小数)
|
||||
@ -77,13 +79,6 @@ public class LklSeparateDTO {
|
||||
}
|
||||
|
||||
// 测试toJSON和toString方法
|
||||
System.out.println("\n=== toJSON和toString方法测试 ===");
|
||||
System.out.println("基于分账总额算法的JSON输出:");
|
||||
System.out.println(dto.toJSON());
|
||||
|
||||
System.out.println("\n基于分账总额算法的toString输出:");
|
||||
System.out.println(dto);
|
||||
|
||||
System.out.println("\n=== toJSON和toString方法测试 ===");
|
||||
System.out.println("基于可分账金额算法的JSON输出:");
|
||||
System.out.println(dto2.toJSON());
|
||||
@ -92,6 +87,22 @@ public class LklSeparateDTO {
|
||||
System.out.println(dto2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算百分比
|
||||
*
|
||||
* @param amount 金额
|
||||
* @param total 总金额
|
||||
* @return 百分比字符串,保留两位小数
|
||||
*/
|
||||
public static String calculatePercentage(Integer amount, Integer total) {
|
||||
if (amount == null || total == null || total == 0) {
|
||||
return "0.00";
|
||||
}
|
||||
BigDecimal percentage = new BigDecimal(amount).multiply(new BigDecimal("100"))
|
||||
.divide(new BigDecimal(total), 2, RoundingMode.HALF_UP);
|
||||
return percentage.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印分账详情
|
||||
*
|
||||
@ -116,238 +127,40 @@ public class LklSeparateDTO {
|
||||
if (dto.getCanSeparateAmount() != null) {
|
||||
System.out.println(" 可分账金额: " + dto.getCanSeparateAmount() + "分");
|
||||
}
|
||||
// 打印平台分账金额(即使为0也要显示)
|
||||
if (dto.getRefCanSeparateAmount() != null) {
|
||||
System.out.println(" 参考可分账金额: " + dto.getRefCanSeparateAmount() + "分");
|
||||
}
|
||||
if (dto.getCanSeparateAmount() != null && dto.getRefCanSeparateAmount() != null) {
|
||||
System.out.println(" 参考可分账差值: " + (dto.getRefCanSeparateAmount() - dto.getCanSeparateAmount()) + "分");
|
||||
}
|
||||
if (dto.getPlatAmount() != null) {
|
||||
System.out.println(" 平台分账金额: " + dto.getPlatAmount() + "分" +
|
||||
(dto.getTotalSeparateAmount() != null
|
||||
? " (总金额占比: " + calculatePercentage(dto.getPlatAmount(), dto.getTotalSeparateAmount())
|
||||
+ "%)"
|
||||
: "")
|
||||
+
|
||||
(dto.getCanSeparateAmount() != null
|
||||
? " (可分账占比: " + calculatePercentage(dto.getPlatAmount(), dto.getCanSeparateAmount()) + "%)"
|
||||
: ""));
|
||||
(dto.getTotalSeparateAmount() != null ?
|
||||
" (总金额占比: " + calculatePercentage(dto.getPlatAmount(), dto.getTotalSeparateAmount()) + "%)" : "") +
|
||||
(dto.getCanSeparateAmount() != null && dto.getCanSeparateAmount() > 0 ?
|
||||
" (可分账占比: " + calculatePercentage(dto.getPlatAmount(), dto.getCanSeparateAmount()) + "%)" : ""));
|
||||
}
|
||||
// 打印一级代理商分账金额(即使为0也要显示)
|
||||
if (dto.getAgent1stAmount() != null) {
|
||||
System.out.println(" 一级代理商分账金额: " + dto.getAgent1stAmount() + "分" +
|
||||
(dto.getTotalSeparateAmount() != null
|
||||
? " (总金额占比: " + calculatePercentage(dto.getAgent1stAmount(), dto.getTotalSeparateAmount())
|
||||
+ "%)"
|
||||
: "")
|
||||
+
|
||||
(dto.getCanSeparateAmount() != null
|
||||
? " (可分账占比: " + calculatePercentage(dto.getAgent1stAmount(), dto.getCanSeparateAmount())
|
||||
+ "%)"
|
||||
: ""));
|
||||
(dto.getTotalSeparateAmount() != null ?
|
||||
" (总金额占比: " + calculatePercentage(dto.getAgent1stAmount(), dto.getTotalSeparateAmount()) + "%)" : "") +
|
||||
(dto.getCanSeparateAmount() != null && dto.getCanSeparateAmount() > 0 ?
|
||||
" (可分账占比: " + calculatePercentage(dto.getAgent1stAmount(), dto.getCanSeparateAmount()) + "%)" : ""));
|
||||
}
|
||||
// 打印二级代理商分账金额(即使为0也要显示)
|
||||
if (dto.getAgent2ndAmount() != null) {
|
||||
System.out.println(" 二级代理商分账金额: " + dto.getAgent2ndAmount() + "分" +
|
||||
(dto.getTotalSeparateAmount() != null
|
||||
? " (总金额占比: " + calculatePercentage(dto.getAgent2ndAmount(), dto.getTotalSeparateAmount())
|
||||
+ "%)"
|
||||
: "")
|
||||
+
|
||||
(dto.getCanSeparateAmount() != null
|
||||
? " (可分账占比: " + calculatePercentage(dto.getAgent2ndAmount(), dto.getCanSeparateAmount())
|
||||
+ "%)"
|
||||
: ""));
|
||||
(dto.getTotalSeparateAmount() != null ?
|
||||
" (总金额占比: " + calculatePercentage(dto.getAgent2ndAmount(), dto.getTotalSeparateAmount()) + "%)" : "") +
|
||||
(dto.getCanSeparateAmount() != null && dto.getCanSeparateAmount() > 0 ?
|
||||
" (可分账占比: " + calculatePercentage(dto.getAgent2ndAmount(), dto.getCanSeparateAmount()) + "%)" : ""));
|
||||
}
|
||||
// 打印商家分账金额
|
||||
if (dto.getMchAmount() != null) {
|
||||
System.out.println(" 商家分账金额: " + dto.getMchAmount() + "分" +
|
||||
(dto.getTotalSeparateAmount() != null
|
||||
? " (总金额占比: " + calculatePercentage(dto.getMchAmount(), dto.getTotalSeparateAmount()) + "%)"
|
||||
: "")
|
||||
+
|
||||
(dto.getCanSeparateAmount() != null
|
||||
? " (可分账占比: " + calculatePercentage(dto.getMchAmount(), dto.getCanSeparateAmount()) + "%)"
|
||||
: ""));
|
||||
(dto.getTotalSeparateAmount() != null ?
|
||||
" (总金额占比: " + calculatePercentage(dto.getMchAmount(), dto.getTotalSeparateAmount()) + "%)" : "") +
|
||||
(dto.getCanSeparateAmount() != null && dto.getCanSeparateAmount() > 0 ?
|
||||
" (可分账占比: " + calculatePercentage(dto.getMchAmount(), dto.getCanSeparateAmount()) + "%)" : ""));
|
||||
}
|
||||
|
||||
// 验证分账是否平衡
|
||||
if (dto.getTotalSeparateAmount() != null) {
|
||||
int totalDistributed = (dto.getLklAmount() != null ? dto.getLklAmount() : 0) +
|
||||
(dto.getShippingFee() != null ? dto.getShippingFee() : 0) +
|
||||
(dto.getPlatAmount() != null ? dto.getPlatAmount() : 0) +
|
||||
(dto.getAgent1stAmount() != null ? dto.getAgent1stAmount() : 0) +
|
||||
(dto.getAgent2ndAmount() != null ? dto.getAgent2ndAmount() : 0) +
|
||||
(dto.getMchAmount() != null ? dto.getMchAmount() : 0);
|
||||
System.out.println(" 分账平衡验证: " + (totalDistributed == dto.getTotalSeparateAmount() ? "通过" : "失败"));
|
||||
System.out.println(" 计算的分账总额: " + totalDistributed + "分");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算金额占总额的百分比
|
||||
*
|
||||
* @param amount 金额
|
||||
* @param total 总金额
|
||||
* @return 百分比字符串
|
||||
*/
|
||||
public static String calculatePercentage(Integer amount, Integer total) {
|
||||
if (amount == null || total == null || total == 0) {
|
||||
return "0.00";
|
||||
}
|
||||
BigDecimal percentage = new BigDecimal(amount).multiply(new BigDecimal("100"))
|
||||
.divide(new BigDecimal(total), 2, RoundingMode.HALF_UP);
|
||||
return percentage.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将分账对象转换为JSON格式字符串
|
||||
*
|
||||
* @return JSON格式字符串
|
||||
*/
|
||||
public String toJSON() {
|
||||
StringBuilder json = new StringBuilder();
|
||||
json.append("{\n");
|
||||
|
||||
// 基础信息
|
||||
json.append(" \"分账算法类型\": \"拉卡拉订单分账信息处理\",\n");
|
||||
json.append(" \"分账总金额\": ").append(totalSeparateAmount != null ? totalSeparateAmount : 0).append(",\n");
|
||||
json.append(" \"配送费\": ").append(shippingFee != null ? shippingFee : 0).append(",\n");
|
||||
|
||||
// 分账比例
|
||||
json.append(" \"分账比例\": {\n");
|
||||
json.append(" \"拉卡拉分账比例\": \"").append(lklRatio != null ? lklRatio.toString() : "0").append("\",\n");
|
||||
json.append(" \"商家分账比例\": \"").append(mchRatio != null ? mchRatio.toString() : "0").append("\",\n");
|
||||
json.append(" \"平台分账比例\": \"").append(platRatio != null ? platRatio.toString() : "0").append("\",\n");
|
||||
json.append(" \"一级代理商分账比例\": \"").append(agent1stRatio != null ? agent1stRatio.toString() : "0")
|
||||
.append("\",\n");
|
||||
json.append(" \"二级代理商分账比例\": \"").append(agent2ndRatio != null ? agent2ndRatio.toString() : "0")
|
||||
.append("\"\n");
|
||||
json.append(" },\n");
|
||||
|
||||
// 分账金额结果
|
||||
json.append(" \"分账金额结果\": {\n");
|
||||
json.append(" \"拉卡拉分账金额\": ").append(lklAmount != null ? lklAmount : 0).append(",\n");
|
||||
json.append(" \"可分账金额\": ").append(canSeparateAmount != null ? canSeparateAmount : 0).append(",\n");
|
||||
json.append(" \"平台分账金额\": ").append(platAmount != null ? platAmount : 0).append(",\n");
|
||||
json.append(" \"一级代理商分账金额\": ").append(agent1stAmount != null ? agent1stAmount : 0).append(",\n");
|
||||
json.append(" \"二级代理商分账金额\": ").append(agent2ndAmount != null ? agent2ndAmount : 0).append(",\n");
|
||||
json.append(" \"商家分账金额\": ").append(mchAmount != null ? mchAmount : 0).append("\n");
|
||||
json.append(" },\n");
|
||||
|
||||
// 分账百分比(基于分账总金额)
|
||||
json.append(" \"基于分账总金额的百分比\": {\n");
|
||||
if (totalSeparateAmount != null && totalSeparateAmount > 0) {
|
||||
json.append(" \"拉卡拉分账占比\": \"").append(calculatePercentage(lklAmount, totalSeparateAmount))
|
||||
.append("%\",\n");
|
||||
json.append(" \"配送费占比\": \"").append(calculatePercentage(shippingFee, totalSeparateAmount))
|
||||
.append("%\",\n");
|
||||
json.append(" \"平台分账占比\": \"").append(calculatePercentage(platAmount, totalSeparateAmount))
|
||||
.append("%\",\n");
|
||||
json.append(" \"一级代理商分账占比\": \"").append(calculatePercentage(agent1stAmount, totalSeparateAmount))
|
||||
.append("%\",\n");
|
||||
json.append(" \"二级代理商分账占比\": \"").append(calculatePercentage(agent2ndAmount, totalSeparateAmount))
|
||||
.append("%\",\n");
|
||||
json.append(" \"商家分账占比\": \"").append(calculatePercentage(mchAmount, totalSeparateAmount))
|
||||
.append("%\"\n");
|
||||
} else {
|
||||
json.append(" \"拉卡拉分账占比\": \"0.00%\",\n");
|
||||
json.append(" \"配送费占比\": \"0.00%\",\n");
|
||||
json.append(" \"平台分账占比\": \"0.00%\",\n");
|
||||
json.append(" \"一级代理商分账占比\": \"0.00%\",\n");
|
||||
json.append(" \"二级代理商分账占比\": \"0.00%\",\n");
|
||||
json.append(" \"商家分账占比\": \"0.00%\"\n");
|
||||
}
|
||||
json.append(" },\n");
|
||||
|
||||
// 分账百分比(基于可分账金额)
|
||||
json.append(" \"基于可分账金额的百分比\": {\n");
|
||||
if (canSeparateAmount != null && canSeparateAmount > 0) {
|
||||
json.append(" \"平台分账占比\": \"").append(calculatePercentage(platAmount, canSeparateAmount))
|
||||
.append("%\",\n");
|
||||
json.append(" \"一级代理商分账占比\": \"").append(calculatePercentage(agent1stAmount, canSeparateAmount))
|
||||
.append("%\",\n");
|
||||
json.append(" \"二级代理商分账占比\": \"").append(calculatePercentage(agent2ndAmount, canSeparateAmount))
|
||||
.append("%\",\n");
|
||||
json.append(" \"商家分账占比\": \"").append(calculatePercentage(mchAmount, canSeparateAmount)).append("%\"\n");
|
||||
} else {
|
||||
json.append(" \"平台分账占比\": \"0.00%\",\n");
|
||||
json.append(" \"一级代理商分账占比\": \"0.00%\",\n");
|
||||
json.append(" \"二级代理商分账占比\": \"0.00%\",\n");
|
||||
json.append(" \"商家分账占比\": \"0.00%\"\n");
|
||||
}
|
||||
json.append(" }\n");
|
||||
json.append("}");
|
||||
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写toString方法,输出分账算法的关键信息
|
||||
*
|
||||
* @return 分账对象的字符串表示
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("LklSeparateDTO{\n");
|
||||
|
||||
// 基础信息
|
||||
sb.append(" 分账算法类型: 拉卡拉订单分账信息处理\n");
|
||||
sb.append(" 分账总金额: ").append(totalSeparateAmount != null ? totalSeparateAmount : 0).append("分\n");
|
||||
sb.append(" 配送费: ").append(shippingFee != null ? shippingFee : 0).append("分\n");
|
||||
|
||||
// 分账比例
|
||||
sb.append(" 分账比例: {\n");
|
||||
sb.append(" 拉卡拉分账比例: ").append(lklRatio != null ? lklRatio.toString() : "0").append("\n");
|
||||
sb.append(" 商家分账比例: ").append(mchRatio != null ? mchRatio.toString() : "0").append("\n");
|
||||
sb.append(" 平台分账比例: ").append(platRatio != null ? platRatio.toString() : "0").append("\n");
|
||||
sb.append(" 一级代理商分账比例: ").append(agent1stRatio != null ? agent1stRatio.toString() : "0").append("\n");
|
||||
sb.append(" 二级代理商分账比例: ").append(agent2ndRatio != null ? agent2ndRatio.toString() : "0").append("\n");
|
||||
sb.append(" }\n");
|
||||
|
||||
// 分账金额结果
|
||||
sb.append(" 分账金额结果: {\n");
|
||||
sb.append(" 拉卡拉分账金额: ").append(lklAmount != null ? lklAmount : 0).append("分\n");
|
||||
sb.append(" 可分账金额: ").append(canSeparateAmount != null ? canSeparateAmount : 0).append("分\n");
|
||||
sb.append(" 平台分账金额: ").append(platAmount != null ? platAmount : 0).append("分\n");
|
||||
sb.append(" 一级代理商分账金额: ").append(agent1stAmount != null ? agent1stAmount : 0).append("分\n");
|
||||
sb.append(" 二级代理商分账金额: ").append(agent2ndAmount != null ? agent2ndAmount : 0).append("分\n");
|
||||
sb.append(" 商家分账金额: ").append(mchAmount != null ? mchAmount : 0).append("分\n");
|
||||
sb.append(" }\n");
|
||||
|
||||
// 分账百分比(基于分账总金额)
|
||||
sb.append(" 基于分账总金额的百分比: {\n");
|
||||
if (totalSeparateAmount != null && totalSeparateAmount > 0) {
|
||||
sb.append(" 拉卡拉分账占比: ").append(calculatePercentage(lklAmount, totalSeparateAmount)).append("%\n");
|
||||
sb.append(" 配送费占比: ").append(calculatePercentage(shippingFee, totalSeparateAmount)).append("%\n");
|
||||
sb.append(" 平台分账占比: ").append(calculatePercentage(platAmount, totalSeparateAmount)).append("%\n");
|
||||
sb.append(" 一级代理商分账占比: ").append(calculatePercentage(agent1stAmount, totalSeparateAmount)).append("%\n");
|
||||
sb.append(" 二级代理商分账占比: ").append(calculatePercentage(agent2ndAmount, totalSeparateAmount)).append("%\n");
|
||||
sb.append(" 商家分账占比: ").append(calculatePercentage(mchAmount, totalSeparateAmount)).append("%\n");
|
||||
} else {
|
||||
sb.append(" 拉卡拉分账占比: 0.00%\n");
|
||||
sb.append(" 配送费占比: 0.00%\n");
|
||||
sb.append(" 平台分账占比: 0.00%\n");
|
||||
sb.append(" 一级代理商分账占比: 0.00%\n");
|
||||
sb.append(" 二级代理商分账占比: 0.00%\n");
|
||||
sb.append(" 商家分账占比: 0.00%\n");
|
||||
}
|
||||
sb.append(" }\n");
|
||||
|
||||
// 分账百分比(基于可分账金额)
|
||||
sb.append(" 基于可分账金额的百分比: {\n");
|
||||
if (canSeparateAmount != null && canSeparateAmount > 0) {
|
||||
sb.append(" 平台分账占比: ").append(calculatePercentage(platAmount, canSeparateAmount)).append("%\n");
|
||||
sb.append(" 一级代理商分账占比: ").append(calculatePercentage(agent1stAmount, canSeparateAmount)).append("%\n");
|
||||
sb.append(" 二级代理商分账占比: ").append(calculatePercentage(agent2ndAmount, canSeparateAmount)).append("%\n");
|
||||
sb.append(" 商家分账占比: ").append(calculatePercentage(mchAmount, canSeparateAmount)).append("%\n");
|
||||
} else {
|
||||
sb.append(" 平台分账占比: 0.00%\n");
|
||||
sb.append(" 一级代理商分账占比: 0.00%\n");
|
||||
sb.append(" 二级代理商分账占比: 0.00%\n");
|
||||
sb.append(" 商家分账占比: 0.00%\n");
|
||||
}
|
||||
sb.append(" }\n");
|
||||
sb.append("}");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -387,11 +200,7 @@ public class LklSeparateDTO {
|
||||
}
|
||||
|
||||
// 2. 计算拉卡拉分账金额
|
||||
int lklAmount = 0;
|
||||
if (lklRatio != null && lklRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
lklAmount = lklRatio.multiply(new BigDecimal(totalSeparateAmount))
|
||||
.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||
}
|
||||
int lklAmount = calculateAmountWithRatio(lklRatio, totalSeparateAmount, RoundingMode.HALF_UP);
|
||||
|
||||
// 3. 处理配送费(可以为空或0,表示免配送费)
|
||||
int effectiveShippingFee = (shippingFee != null && shippingFee > 0) ? shippingFee : 0;
|
||||
@ -408,7 +217,28 @@ public class LklSeparateDTO {
|
||||
}
|
||||
|
||||
int canSeparateAmount = availableAmount;
|
||||
int refCanSeparateAmount = availableAmount;
|
||||
// 保持canSeparateAmount和refCanSeparateAmount的独立性,不进行相互赋值
|
||||
|
||||
// 记录refCanSeparateAmount相关信息
|
||||
System.out.println("基于总金额算法 - 可分账金额计算完成: canSeparateAmount=" + canSeparateAmount +
|
||||
", refCanSeparateAmount=" + this.refCanSeparateAmount);
|
||||
|
||||
// 5.1 检查refCanSeparateAmount是否为有效值,如果是有效值且与计算出的canSeparateAmount不一致,则使用refCanSeparateAmount作为分账金额
|
||||
int separateAmountForCalculation = canSeparateAmount; // 默认使用计算出的可分账金额
|
||||
if (this.refCanSeparateAmount != null && this.refCanSeparateAmount > 0 && this.refCanSeparateAmount < totalSeparateAmount) {
|
||||
// refCanSeparateAmount是非空非零且比totalSeparateAmount小的有效值
|
||||
if (!this.refCanSeparateAmount.equals(canSeparateAmount)) {
|
||||
// 有效值如果和计算出来的canSeparateAmount的值不一致
|
||||
separateAmountForCalculation = this.refCanSeparateAmount; // 使用refCanSeparateAmount作为分账算法中的可分金额
|
||||
System.out.println("基于总金额算法 - 使用refCanSeparateAmount作为分账金额: refCanSeparateAmount=" +
|
||||
this.refCanSeparateAmount + ", canSeparateAmount=" + canSeparateAmount +
|
||||
", 差值=" + (this.refCanSeparateAmount - canSeparateAmount));
|
||||
} else {
|
||||
System.out.println("基于总金额算法 - refCanSeparateAmount与canSeparateAmount相等,无需调整");
|
||||
}
|
||||
} else {
|
||||
System.out.println("基于总金额算法 - refCanSeparateAmount无效,使用计算出的canSeparateAmount");
|
||||
}
|
||||
|
||||
// 6. 初始化各分账金额
|
||||
int platAmount = 0;
|
||||
@ -416,18 +246,19 @@ public class LklSeparateDTO {
|
||||
int agent2ndAmount = 0;
|
||||
int mchAmount = 0;
|
||||
|
||||
// 7. 根据参与方动态调整分账比例
|
||||
// 7. 根据参与方动态调整分账比例(基于总金额的独立逻辑)
|
||||
BigDecimal effectivePlatRatio = platRatio != null ? platRatio : BigDecimal.ZERO;
|
||||
BigDecimal effectiveAgent1stRatio = agent1stRatio != null ? agent1stRatio : BigDecimal.ZERO;
|
||||
BigDecimal effectiveAgent2ndRatio = agent2ndRatio != null ? agent2ndRatio : BigDecimal.ZERO;
|
||||
BigDecimal effectiveMchRatio = mchRatio != null ? mchRatio : BigDecimal.ZERO;
|
||||
|
||||
// 判断哪些代理商参与分账
|
||||
// 判断代理商是否参与分账(在调整比例前进行判断)
|
||||
boolean hasAgent1st = effectiveAgent1stRatio.compareTo(BigDecimal.ZERO) > 0;
|
||||
boolean hasAgent2nd = effectiveAgent2ndRatio.compareTo(BigDecimal.ZERO) > 0;
|
||||
|
||||
// 根据商家分账比例动态调整其他方比例
|
||||
if (mchRatio != null && mchRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
BigDecimal remainingRatio = BigDecimal.ONE.subtract(mchRatio);
|
||||
// 根据商家分账比例动态调整其他方比例(独立于基于可分账金额的算法)
|
||||
if (effectiveMchRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
BigDecimal remainingRatio = BigDecimal.ONE.subtract(effectiveMchRatio);
|
||||
BigDecimal onePercent = new BigDecimal("0.01");
|
||||
|
||||
if (hasAgent1st && hasAgent2nd) {
|
||||
@ -449,44 +280,46 @@ public class LklSeparateDTO {
|
||||
// 只有平台参与
|
||||
effectivePlatRatio = remainingRatio;
|
||||
}
|
||||
|
||||
// 重新判断代理商是否参与分账(基于调整后的比例)
|
||||
hasAgent1st = effectiveAgent1stRatio.compareTo(BigDecimal.ZERO) > 0;
|
||||
hasAgent2nd = effectiveAgent2ndRatio.compareTo(BigDecimal.ZERO) > 0;
|
||||
}
|
||||
// 如果商家比例不存在或为0,使用各自设置的固定比例,代理商参与状态已在前面确定
|
||||
|
||||
// 8. 按优先级顺序计算各分账方金额
|
||||
// 平台分账(优先级1)- 基于总金额计算
|
||||
if (effectivePlatRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
platAmount = effectivePlatRatio.multiply(new BigDecimal(totalSeparateAmount))
|
||||
.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||
platAmount = calculateAmountWithRatio(effectivePlatRatio, totalSeparateAmount, RoundingMode.HALF_UP);
|
||||
// 确保平台分账金额不超过可分账金额
|
||||
if (platAmount > availableAmount) {
|
||||
platAmount = availableAmount;
|
||||
if (platAmount > separateAmountForCalculation) {
|
||||
platAmount = separateAmountForCalculation;
|
||||
}
|
||||
availableAmount -= platAmount;
|
||||
separateAmountForCalculation -= platAmount;
|
||||
}
|
||||
|
||||
// 一级代理商分账(优先级2)- 基于总金额计算
|
||||
if (hasAgent1st && effectiveAgent1stRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
agent1stAmount = effectiveAgent1stRatio.multiply(new BigDecimal(totalSeparateAmount))
|
||||
.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||
agent1stAmount = calculateAmountWithRatio(effectiveAgent1stRatio, totalSeparateAmount, RoundingMode.HALF_UP);
|
||||
// 确保不超过剩余金额
|
||||
if (agent1stAmount > availableAmount) {
|
||||
agent1stAmount = availableAmount;
|
||||
if (agent1stAmount > separateAmountForCalculation) {
|
||||
agent1stAmount = separateAmountForCalculation;
|
||||
}
|
||||
availableAmount -= agent1stAmount;
|
||||
separateAmountForCalculation -= agent1stAmount;
|
||||
}
|
||||
|
||||
// 二级代理商分账(优先级3)- 基于总金额计算
|
||||
if (hasAgent2nd && effectiveAgent2ndRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
agent2ndAmount = effectiveAgent2ndRatio.multiply(new BigDecimal(totalSeparateAmount))
|
||||
.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||
agent2ndAmount = calculateAmountWithRatio(effectiveAgent2ndRatio, totalSeparateAmount, RoundingMode.HALF_UP);
|
||||
// 确保不超过剩余金额
|
||||
if (agent2ndAmount > availableAmount) {
|
||||
agent2ndAmount = availableAmount;
|
||||
if (agent2ndAmount > separateAmountForCalculation) {
|
||||
agent2ndAmount = separateAmountForCalculation;
|
||||
}
|
||||
availableAmount -= agent2ndAmount;
|
||||
separateAmountForCalculation -= agent2ndAmount;
|
||||
}
|
||||
|
||||
// 9. 商家分账(优先级4,获得剩余所有金额)
|
||||
mchAmount = availableAmount;
|
||||
mchAmount = separateAmountForCalculation;
|
||||
|
||||
// 10. 检查商家分账金额是否合法
|
||||
if (mchAmount < 0) {
|
||||
@ -497,7 +330,7 @@ public class LklSeparateDTO {
|
||||
SharingCalculationResult calculationResult = new SharingCalculationResult(true, null);
|
||||
calculationResult.setLklAmount(lklAmount);
|
||||
calculationResult.setCanSeparateAmount(canSeparateAmount);
|
||||
calculationResult.setRefCanSeparateAmount(refCanSeparateAmount);
|
||||
calculationResult.setRefCanSeparateAmount(this.refCanSeparateAmount);
|
||||
calculationResult.setShippingFee(effectiveShippingFee);
|
||||
calculationResult.setPlatAmount(platAmount);
|
||||
calculationResult.setAgent1stAmount(agent1stAmount);
|
||||
@ -553,11 +386,7 @@ public class LklSeparateDTO {
|
||||
int amountAfterShipping = totalSeparateAmount - effectiveShippingFee;
|
||||
|
||||
// 4. 计算拉卡拉分账金额(手续费)= 分账总金额 * 拉卡拉分账比例
|
||||
int lklAmount = 0;
|
||||
if (lklRatio != null && lklRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
lklAmount = lklRatio.multiply(new BigDecimal(totalSeparateAmount))
|
||||
.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||
}
|
||||
int lklAmount = calculateAmountWithRatio(lklRatio, totalSeparateAmount, RoundingMode.HALF_UP);
|
||||
|
||||
// 5. 检查拉卡拉分账金额是否合法
|
||||
if (lklAmount >= amountAfterShipping) {
|
||||
@ -571,7 +400,26 @@ public class LklSeparateDTO {
|
||||
}
|
||||
|
||||
int canSeparateAmount = availableAmount;
|
||||
int refCanSeparateAmount = availableAmount;
|
||||
// 记录refCanSeparateAmount相关信息
|
||||
System.out.println("基于可分账金额算法 - 可分账金额计算完成: canSeparateAmount=" + canSeparateAmount +
|
||||
", refCanSeparateAmount=" + this.refCanSeparateAmount);
|
||||
|
||||
// 6.1 检查refCanSeparateAmount是否为有效值,如果是有效值且与计算出的canSeparateAmount不一致,则使用refCanSeparateAmount作为分账金额
|
||||
int separateAmountForCalculation = canSeparateAmount; // 默认使用计算出的可分账金额
|
||||
if (this.refCanSeparateAmount != null && this.refCanSeparateAmount > 0 && this.refCanSeparateAmount < totalSeparateAmount) {
|
||||
// refCanSeparateAmount是非空非零且比totalSeparateAmount小的有效值
|
||||
if (!this.refCanSeparateAmount.equals(canSeparateAmount)) {
|
||||
// 有效值如果和计算出来的canSeparateAmount的值不一致
|
||||
separateAmountForCalculation = this.refCanSeparateAmount; // 使用refCanSeparateAmount作为分账算法中的可分金额
|
||||
System.out.println("基于可分账金额算法 - 使用refCanSeparateAmount作为分账金额: refCanSeparateAmount=" +
|
||||
this.refCanSeparateAmount + ", canSeparateAmount=" + canSeparateAmount +
|
||||
", 差值=" + (this.refCanSeparateAmount - canSeparateAmount));
|
||||
} else {
|
||||
System.out.println("基于可分账金额算法 - refCanSeparateAmount与canSeparateAmount相等,无需调整");
|
||||
}
|
||||
} else {
|
||||
System.out.println("基于可分账金额算法 - refCanSeparateAmount无效,使用计算出的canSeparateAmount");
|
||||
}
|
||||
|
||||
// 7. 初始化各分账金额
|
||||
int platAmount = 0;
|
||||
@ -579,18 +427,19 @@ public class LklSeparateDTO {
|
||||
int agent2ndAmount = 0;
|
||||
int mchAmount = 0;
|
||||
|
||||
// 8. 根据参与方动态调整分账比例
|
||||
// 8. 根据参与方动态调整分账比例(基于可分账金额的独立逻辑)
|
||||
BigDecimal effectivePlatRatio = platRatio != null ? platRatio : BigDecimal.ZERO;
|
||||
BigDecimal effectiveAgent1stRatio = agent1stRatio != null ? agent1stRatio : BigDecimal.ZERO;
|
||||
BigDecimal effectiveAgent2ndRatio = agent2ndRatio != null ? agent2ndRatio : BigDecimal.ZERO;
|
||||
BigDecimal effectiveMchRatio = mchRatio != null ? mchRatio : BigDecimal.ZERO;
|
||||
|
||||
// 判断哪些代理商参与分账
|
||||
// 判断代理商是否参与分账(在调整比例前进行判断)
|
||||
boolean hasAgent1st = effectiveAgent1stRatio.compareTo(BigDecimal.ZERO) > 0;
|
||||
boolean hasAgent2nd = effectiveAgent2ndRatio.compareTo(BigDecimal.ZERO) > 0;
|
||||
|
||||
// 根据商家分账比例动态调整其他方比例
|
||||
if (mchRatio != null && mchRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
BigDecimal remainingRatio = BigDecimal.ONE.subtract(mchRatio);
|
||||
// 根据商家分账比例动态调整其他方比例(独立于基于总金额的算法)
|
||||
if (effectiveMchRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
BigDecimal remainingRatio = BigDecimal.ONE.subtract(effectiveMchRatio);
|
||||
BigDecimal onePercent = new BigDecimal("0.01");
|
||||
|
||||
if (hasAgent1st && hasAgent2nd) {
|
||||
@ -612,56 +461,57 @@ public class LklSeparateDTO {
|
||||
// 只有平台参与
|
||||
effectivePlatRatio = remainingRatio;
|
||||
}
|
||||
|
||||
// 重新判断代理商是否参与分账(基于调整后的比例)
|
||||
hasAgent1st = effectiveAgent1stRatio.compareTo(BigDecimal.ZERO) > 0;
|
||||
hasAgent2nd = effectiveAgent2ndRatio.compareTo(BigDecimal.ZERO) > 0;
|
||||
}
|
||||
// 如果商家比例不存在或为0,使用各自设置的固定比例,代理商参与状态已在前面确定
|
||||
|
||||
// 9. 按新的优先级顺序计算各分账方金额(基于可分账金额计算)
|
||||
// 商家分账(优先级1)- 基于可分账金额计算,采用向上进位方式
|
||||
if (mchRatio != null && mchRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
mchAmount = mchRatio.multiply(new BigDecimal(canSeparateAmount))
|
||||
.setScale(0, RoundingMode.UP).intValue();
|
||||
// 确保商家分账金额不超过可分账金额
|
||||
if (mchAmount > availableAmount) {
|
||||
mchAmount = availableAmount;
|
||||
if (effectiveMchRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
mchAmount = calculateAmountWithRatio(effectiveMchRatio, canSeparateAmount, RoundingMode.UP);
|
||||
// 确保商家分账金额不超过剩余金额
|
||||
if (mchAmount > separateAmountForCalculation) {
|
||||
mchAmount = separateAmountForCalculation;
|
||||
}
|
||||
availableAmount -= mchAmount;
|
||||
separateAmountForCalculation -= mchAmount;
|
||||
}
|
||||
|
||||
// 平台分账(优先级2)- 基于可分账金额计算,采用四舍五入方式
|
||||
if (effectivePlatRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
platAmount = effectivePlatRatio.multiply(new BigDecimal(canSeparateAmount))
|
||||
.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||
platAmount = calculateAmountWithRatio(effectivePlatRatio, canSeparateAmount, RoundingMode.HALF_UP);
|
||||
// 确保平台分账金额不超过剩余金额
|
||||
if (platAmount > availableAmount) {
|
||||
platAmount = availableAmount;
|
||||
if (platAmount > separateAmountForCalculation) {
|
||||
platAmount = separateAmountForCalculation;
|
||||
}
|
||||
availableAmount -= platAmount;
|
||||
separateAmountForCalculation -= platAmount;
|
||||
}
|
||||
|
||||
// 一级代理商分账(优先级3)- 基于可分账金额计算,采用四舍五入方式
|
||||
if (hasAgent1st && effectiveAgent1stRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
agent1stAmount = effectiveAgent1stRatio.multiply(new BigDecimal(canSeparateAmount))
|
||||
.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||
agent1stAmount = calculateAmountWithRatio(effectiveAgent1stRatio, canSeparateAmount, RoundingMode.HALF_UP);
|
||||
// 确保不超过剩余金额
|
||||
if (agent1stAmount > availableAmount) {
|
||||
agent1stAmount = availableAmount;
|
||||
if (agent1stAmount > separateAmountForCalculation) {
|
||||
agent1stAmount = separateAmountForCalculation;
|
||||
}
|
||||
availableAmount -= agent1stAmount;
|
||||
separateAmountForCalculation -= agent1stAmount;
|
||||
}
|
||||
|
||||
// 二级代理商分账(优先级4)- 基于可分账金额计算,采用四舍五入方式
|
||||
if (hasAgent2nd && effectiveAgent2ndRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
agent2ndAmount = effectiveAgent2ndRatio.multiply(new BigDecimal(canSeparateAmount))
|
||||
.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||
agent2ndAmount = calculateAmountWithRatio(effectiveAgent2ndRatio, canSeparateAmount, RoundingMode.HALF_UP);
|
||||
// 确保不超过剩余金额
|
||||
if (agent2ndAmount > availableAmount) {
|
||||
agent2ndAmount = availableAmount;
|
||||
if (agent2ndAmount > separateAmountForCalculation) {
|
||||
agent2ndAmount = separateAmountForCalculation;
|
||||
}
|
||||
availableAmount -= agent2ndAmount;
|
||||
separateAmountForCalculation -= agent2ndAmount;
|
||||
}
|
||||
|
||||
// 10. 如果还有剩余金额,将其分配给商家
|
||||
if (availableAmount > 0) {
|
||||
mchAmount += availableAmount;
|
||||
if (separateAmountForCalculation > 0) {
|
||||
mchAmount += separateAmountForCalculation;
|
||||
}
|
||||
|
||||
// 11. 检查商家分账金额是否合法
|
||||
@ -673,7 +523,7 @@ public class LklSeparateDTO {
|
||||
SharingCalculationResult calculationResult = new SharingCalculationResult(true, null);
|
||||
calculationResult.setLklAmount(lklAmount);
|
||||
calculationResult.setCanSeparateAmount(canSeparateAmount);
|
||||
calculationResult.setRefCanSeparateAmount(refCanSeparateAmount);
|
||||
calculationResult.setRefCanSeparateAmount(this.refCanSeparateAmount);
|
||||
calculationResult.setShippingFee(effectiveShippingFee);
|
||||
calculationResult.setPlatAmount(platAmount);
|
||||
calculationResult.setAgent1stAmount(agent1stAmount);
|
||||
@ -683,14 +533,113 @@ public class LklSeparateDTO {
|
||||
return calculationResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将分账信息转换为格式化的JSON字符串
|
||||
*
|
||||
* @return JSON格式的字符串
|
||||
*/
|
||||
public String toJSON() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("{");
|
||||
|
||||
// 基础金额信息
|
||||
sb.append("基础金额信息:{");
|
||||
sb.append("分账总金额:").append(totalSeparateAmount != null ? totalSeparateAmount : 0).append("分,");
|
||||
sb.append("配送费:").append(shippingFee != null ? shippingFee : 0);
|
||||
sb.append("},");
|
||||
|
||||
// 分账比例信息
|
||||
sb.append("分账比例信息:{");
|
||||
sb.append("拉卡拉分账比例:").append(lklRatio != null ? lklRatio.stripTrailingZeros().toPlainString() : "0").append(",");
|
||||
sb.append("商家分账比例:").append(mchRatio != null ? mchRatio.stripTrailingZeros().toPlainString() : "0").append(",");
|
||||
sb.append("平台分账比例:").append(platRatio != null ? platRatio.stripTrailingZeros().toPlainString() : "0").append(",");
|
||||
sb.append("一级代理商分账比例:").append(agent1stRatio != null ? agent1stRatio.stripTrailingZeros().toPlainString() : "0").append(",");
|
||||
sb.append("二级代理商分账比例:").append(agent2ndRatio != null ? agent2ndRatio.stripTrailingZeros().toPlainString() : "0");
|
||||
sb.append("},");
|
||||
|
||||
// 分账金额结果
|
||||
sb.append("分账金额结果:{");
|
||||
sb.append("拉卡拉分账金额:").append(lklAmount != null ? lklAmount : 0).append("分,");
|
||||
sb.append("可分账金额:").append(canSeparateAmount != null ? canSeparateAmount : 0).append("分,");
|
||||
sb.append("参考可分账金额:").append(refCanSeparateAmount != null ? refCanSeparateAmount : 0).append("分,");
|
||||
if (canSeparateAmount != null && refCanSeparateAmount != null) {
|
||||
sb.append("参考可分账差值:").append(refCanSeparateAmount - canSeparateAmount).append("分,");
|
||||
}
|
||||
sb.append("配送费:").append(shippingFee != null ? shippingFee : 0).append("分,");
|
||||
sb.append("平台分账金额:").append(platAmount != null ? platAmount : 0).append("分,");
|
||||
sb.append("一级代理商分账金额:").append(agent1stAmount != null ? agent1stAmount : 0).append("分,");
|
||||
sb.append("二级代理商分账金额:").append(agent2ndAmount != null ? agent2ndAmount : 0).append("分,");
|
||||
sb.append("商家分账金额:").append(mchAmount != null ? mchAmount : 0).append("分");
|
||||
sb.append("}");
|
||||
|
||||
sb.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据比例计算金额
|
||||
*
|
||||
* @param ratio 比例
|
||||
* @param baseAmount 基础金额
|
||||
* @param roundingMode 舍入模式
|
||||
* @return 计算后的金额
|
||||
*/
|
||||
private int calculateAmountWithRatio(BigDecimal ratio, int baseAmount, RoundingMode roundingMode) {
|
||||
if (ratio == null || ratio.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return 0;
|
||||
}
|
||||
return ratio.multiply(new BigDecimal(baseAmount))
|
||||
.setScale(0, roundingMode).intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("LklSeparateDTO{");
|
||||
|
||||
// 基础金额信息
|
||||
sb.append("基础金额信息:{");
|
||||
sb.append("分账总金额:").append(totalSeparateAmount != null ? totalSeparateAmount : 0).append("分,");
|
||||
sb.append("配送费:").append(shippingFee != null ? shippingFee : 0);
|
||||
sb.append("},");
|
||||
|
||||
// 分账比例信息
|
||||
sb.append("分账比例信息:{");
|
||||
sb.append("拉卡拉分账比例:").append(lklRatio != null ? lklRatio.stripTrailingZeros().toPlainString() : "0").append(",");
|
||||
sb.append("商家分账比例:").append(mchRatio != null ? mchRatio.stripTrailingZeros().toPlainString() : "0").append(",");
|
||||
sb.append("平台分账比例:").append(platRatio != null ? platRatio.stripTrailingZeros().toPlainString() : "0").append(",");
|
||||
sb.append("一级代理商分账比例:").append(agent1stRatio != null ? agent1stRatio.stripTrailingZeros().toPlainString() : "0").append(",");
|
||||
sb.append("二级代理商分账比例:").append(agent2ndRatio != null ? agent2ndRatio.stripTrailingZeros().toPlainString() : "0");
|
||||
sb.append("},");
|
||||
|
||||
// 分账金额结果
|
||||
sb.append("分账金额结果:{");
|
||||
sb.append("拉卡拉分账金额:").append(lklAmount != null ? lklAmount : 0).append("分,");
|
||||
sb.append("可分账金额:").append(canSeparateAmount != null ? canSeparateAmount : 0).append("分,");
|
||||
sb.append("参考可分账金额:").append(refCanSeparateAmount != null ? refCanSeparateAmount : 0).append("分,");
|
||||
if (canSeparateAmount != null && refCanSeparateAmount != null) {
|
||||
sb.append("参考可分账差值:").append(refCanSeparateAmount - canSeparateAmount).append("分,");
|
||||
}
|
||||
sb.append("配送费:").append(shippingFee != null ? shippingFee : 0).append("分,");
|
||||
sb.append("平台分账金额:").append(platAmount != null ? platAmount : 0).append("分,");
|
||||
sb.append("一级代理商分账金额:").append(agent1stAmount != null ? agent1stAmount : 0).append("分,");
|
||||
sb.append("二级代理商分账金额:").append(agent2ndAmount != null ? agent2ndAmount : 0).append("分,");
|
||||
sb.append("商家分账金额:").append(mchAmount != null ? mchAmount : 0).append("分");
|
||||
sb.append("}");
|
||||
|
||||
sb.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分账结果类,包含分账是否成功以及失败原因
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public static class SharingResult {
|
||||
private final boolean success;
|
||||
private final String errorMessage;
|
||||
private boolean success;
|
||||
private String errorMessage;
|
||||
|
||||
public SharingResult() {
|
||||
}
|
||||
|
||||
public SharingResult(boolean success, String errorMessage) {
|
||||
this.success = success;
|
||||
@ -701,6 +650,18 @@ public class LklSeparateDTO {
|
||||
return success;
|
||||
}
|
||||
|
||||
public void setSuccess(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public void setErrorMessage(String errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return success ? "分账成功" : "分账失败: " + errorMessage;
|
||||
@ -721,56 +682,20 @@ public class LklSeparateDTO {
|
||||
private Integer agent2ndAmount; // 二级代理商分账金额(分)
|
||||
private Integer mchAmount; // 商户分账金额(分)
|
||||
|
||||
public SharingCalculationResult() {
|
||||
}
|
||||
|
||||
public SharingCalculationResult(boolean success, String errorMessage) {
|
||||
super(success, errorMessage);
|
||||
}
|
||||
|
||||
public Integer getMchAmount() {
|
||||
return mchAmount;
|
||||
// Getters and Setters
|
||||
public Integer getLklAmount() {
|
||||
return lklAmount;
|
||||
}
|
||||
|
||||
public void setMchAmount(Integer mchAmount) {
|
||||
this.mchAmount = mchAmount;
|
||||
}
|
||||
|
||||
public Integer getAgent2ndAmount() {
|
||||
return agent2ndAmount;
|
||||
}
|
||||
|
||||
public void setAgent2ndAmount(Integer agent2ndAmount) {
|
||||
this.agent2ndAmount = agent2ndAmount;
|
||||
}
|
||||
|
||||
public Integer getAgent1stAmount() {
|
||||
return agent1stAmount;
|
||||
}
|
||||
|
||||
public void setAgent1stAmount(Integer agent1stAmount) {
|
||||
this.agent1stAmount = agent1stAmount;
|
||||
}
|
||||
|
||||
public Integer getPlatAmount() {
|
||||
return platAmount;
|
||||
}
|
||||
|
||||
public void setPlatAmount(Integer platAmount) {
|
||||
this.platAmount = platAmount;
|
||||
}
|
||||
|
||||
public Integer getShippingFee() {
|
||||
return shippingFee;
|
||||
}
|
||||
|
||||
public void setShippingFee(Integer shippingFee) {
|
||||
this.shippingFee = shippingFee;
|
||||
}
|
||||
|
||||
public Integer getRefCanSeparateAmount() {
|
||||
return refCanSeparateAmount;
|
||||
}
|
||||
|
||||
public void setRefCanSeparateAmount(Integer refCanSeparateAmount) {
|
||||
this.refCanSeparateAmount = refCanSeparateAmount;
|
||||
public void setLklAmount(Integer lklAmount) {
|
||||
this.lklAmount = lklAmount;
|
||||
}
|
||||
|
||||
public Integer getCanSeparateAmount() {
|
||||
@ -781,12 +706,52 @@ public class LklSeparateDTO {
|
||||
this.canSeparateAmount = canSeparateAmount;
|
||||
}
|
||||
|
||||
public Integer getLklAmount() {
|
||||
return lklAmount;
|
||||
public Integer getRefCanSeparateAmount() {
|
||||
return refCanSeparateAmount;
|
||||
}
|
||||
|
||||
public void setLklAmount(Integer lklAmount) {
|
||||
this.lklAmount = lklAmount;
|
||||
public void setRefCanSeparateAmount(Integer refCanSeparateAmount) {
|
||||
this.refCanSeparateAmount = refCanSeparateAmount;
|
||||
}
|
||||
|
||||
public Integer getShippingFee() {
|
||||
return shippingFee;
|
||||
}
|
||||
|
||||
public void setShippingFee(Integer shippingFee) {
|
||||
this.shippingFee = shippingFee;
|
||||
}
|
||||
|
||||
public Integer getPlatAmount() {
|
||||
return platAmount;
|
||||
}
|
||||
|
||||
public void setPlatAmount(Integer platAmount) {
|
||||
this.platAmount = platAmount;
|
||||
}
|
||||
|
||||
public Integer getAgent1stAmount() {
|
||||
return agent1stAmount;
|
||||
}
|
||||
|
||||
public void setAgent1stAmount(Integer agent1stAmount) {
|
||||
this.agent1stAmount = agent1stAmount;
|
||||
}
|
||||
|
||||
public Integer getAgent2ndAmount() {
|
||||
return agent2ndAmount;
|
||||
}
|
||||
|
||||
public void setAgent2ndAmount(Integer agent2ndAmount) {
|
||||
this.agent2ndAmount = agent2ndAmount;
|
||||
}
|
||||
|
||||
public Integer getMchAmount() {
|
||||
return mchAmount;
|
||||
}
|
||||
|
||||
public void setMchAmount(Integer mchAmount) {
|
||||
this.mchAmount = mchAmount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,849 +0,0 @@
|
||||
package com.suisung.mall.common.pojo.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.util.Pair;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
/**
|
||||
* 拉卡拉订单分账信息对象
|
||||
* <p>
|
||||
* 分账计算支持两种模式:
|
||||
* 1. 基于可分账金额模式(默认):先扣除拉卡拉手续费和配送费,再对剩余金额进行分账
|
||||
* 2. 基于总金额模式:基于总分账金额进行分账计算
|
||||
* <p>
|
||||
* 分账优先级顺序:拉卡拉 > 平台 > 一级代理商 > 二级代理商 > 商户
|
||||
* 商户作为最后分账方,其金额为剩余金额,不强制遵循分账比例
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@ApiModel(value = "拉卡拉订单分账信息对象", description = "拉卡拉订单分账信息对象")
|
||||
public class LklSeparateDTOBak implements java.io.Serializable {
|
||||
private static final Logger logger = LoggerFactory.getLogger(LklSeparateDTOBak.class);
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// ================================ 基础金额属性 ================================
|
||||
|
||||
@ApiModelProperty(value = "分账总金额(分)")
|
||||
private Integer totalSeparateAmount;
|
||||
|
||||
@ApiModelProperty(value = "可分账金额(分)")
|
||||
private Integer canSeparateAmount;
|
||||
|
||||
@ApiModelProperty(value = "拉卡拉参考可分账金额(分)")
|
||||
private Integer refCanSeparateAmount;
|
||||
|
||||
@ApiModelProperty(value = "配送费(分)")
|
||||
private Integer shippingFee;
|
||||
|
||||
// ================================ 分账比例属性 ================================
|
||||
|
||||
@ApiModelProperty(value = "拉卡拉分账比例(如 0.0025=0.25%)")
|
||||
private BigDecimal lklRatio;
|
||||
|
||||
@ApiModelProperty(value = "商户分账比例(如 0.96=96%)")
|
||||
private BigDecimal mchRatio;
|
||||
|
||||
@ApiModelProperty(value = "平台分账比例(如 0.01=1%)")
|
||||
private BigDecimal platRatio;
|
||||
|
||||
@ApiModelProperty(value = "一级代理商分账比例(如 0.01=1%)")
|
||||
private BigDecimal agent1stRatio;
|
||||
|
||||
@ApiModelProperty(value = "二级代理商分账比例(如 0.03=3%)")
|
||||
private BigDecimal agent2ndRatio;
|
||||
|
||||
// ================================ 分账金额结果属性 ================================
|
||||
|
||||
@ApiModelProperty(value = "拉卡拉分账金额(分)")
|
||||
private Integer lklAmount;
|
||||
|
||||
@ApiModelProperty(value = "商户分账金额(分)")
|
||||
private Integer mchAmount;
|
||||
|
||||
@ApiModelProperty(value = "平台分账金额(分)")
|
||||
private Integer platAmount;
|
||||
|
||||
@ApiModelProperty(value = "一级代理商分账金额(分)")
|
||||
private Integer agent1stAmount;
|
||||
|
||||
@ApiModelProperty(value = "二级代理商分账金额(分)")
|
||||
private Integer agent2ndAmount;
|
||||
|
||||
// ================================ 内部状态属性 ================================
|
||||
|
||||
/**
|
||||
* 分账计算方法类型
|
||||
* true表示基于总金额分账(calcOnTotalAmount方法被调用)
|
||||
* false表示基于可分账金额分账(calcOnCanAmount方法被调用)
|
||||
*/
|
||||
private boolean isBasedOnTotalAmount = false;
|
||||
|
||||
// ================================ 构造方法 ================================
|
||||
|
||||
public LklSeparateDTOBak() {
|
||||
// 默认构造函数
|
||||
}
|
||||
|
||||
// ================================ 公共方法 ================================
|
||||
|
||||
/**
|
||||
* 测试方法
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
logger.info("开始测试分账计算功能...");
|
||||
|
||||
// 临界点测试用例2: 小金额测试
|
||||
logger.info("\n临界点测试用例2 - 小金额测试:");
|
||||
LklSeparateDTOBak dto2 = new LklSeparateDTOBak();
|
||||
dto2.setTotalSeparateAmount(800);
|
||||
dto2.setShippingFee(600);
|
||||
dto2.setLklRatio(new BigDecimal("0.0025"));
|
||||
dto2.setMchRatio(new BigDecimal("0.96"));
|
||||
dto2.setPlatRatio(new BigDecimal("0.04"));
|
||||
dto2.setBasedOnTotalAmount(true);
|
||||
|
||||
// dto2.setAgent1stRatio(new BigDecimal("0.01"));
|
||||
// dto2.setAgent2ndRatio(new BigDecimal("0.04"));
|
||||
// dto2.setRefCanSeparateAmount(8079); // 设置参考可分账金额
|
||||
|
||||
logger.info("测试参数: 总分账金额={}分, 配送费={}分, 拉卡拉比例={}, 商户比例={}, 平台比例={}",
|
||||
dto2.getTotalSeparateAmount(), dto2.getShippingFee(), dto2.getLklRatio(),
|
||||
dto2.getMchRatio(), dto2.getPlatRatio());
|
||||
|
||||
Pair<Boolean, String> result2 = dto2.calcOnCanSeparateAmount();
|
||||
logger.info("分账计算结果: {}", (result2.getFirst() ? "成功" : "失败"));
|
||||
if (result2.getFirst()) {
|
||||
logger.info("分账结果: 总金额={}分, 拉卡拉={}分, 配送费={}分, 可分账={}分, 参考可分账={}分, 商户={}分, 平台={}分, 一级代理商={}分, 二级代理商={}分",
|
||||
dto2.getTotalSeparateAmount(), dto2.getLklAmount(), dto2.getShippingFee(), dto2.getCanSeparateAmount(), dto2.getRefCanSeparateAmount(),
|
||||
dto2.getMchAmount(), dto2.getPlatAmount(), dto2.getAgent1stAmount(), dto2.getAgent2ndAmount());
|
||||
|
||||
// 计算并打印各分账方占可分账金额和总金额的百分比
|
||||
int canSeparateAmount = dto2.getCanSeparateAmount();
|
||||
int totalSeparateAmount = dto2.getTotalSeparateAmount();
|
||||
|
||||
if (canSeparateAmount > 0) {
|
||||
double lklRatioOfTotal = (double) dto2.getLklAmount() / totalSeparateAmount * 100;
|
||||
double mchRatioOfTotal = (double) dto2.getMchAmount() / totalSeparateAmount * 100;
|
||||
double platRatioOfTotal = (double) dto2.getPlatAmount() / totalSeparateAmount * 100;
|
||||
double agent1stRatioOfTotal = 0.0;
|
||||
double agent2ndRatioOfTotal = 0.0;
|
||||
|
||||
// 安全检查,避免空指针异常
|
||||
if (dto2.getAgent1stAmount() != null) {
|
||||
agent1stRatioOfTotal = (double) dto2.getAgent1stAmount() / totalSeparateAmount * 100;
|
||||
}
|
||||
if (dto2.getAgent2ndAmount() != null) {
|
||||
agent2ndRatioOfTotal = (double) dto2.getAgent2ndAmount() / totalSeparateAmount * 100;
|
||||
}
|
||||
|
||||
double lklRatioOfAvailable = (double) dto2.getLklAmount() / canSeparateAmount * 100;
|
||||
double mchRatioOfAvailable = (double) dto2.getMchAmount() / canSeparateAmount * 100;
|
||||
double platRatioOfAvailable = (double) dto2.getPlatAmount() / canSeparateAmount * 100;
|
||||
double agent1stRatioOfAvailable = 0.0;
|
||||
double agent2ndRatioOfAvailable = 0.0;
|
||||
|
||||
// 安全检查,避免空指针异常
|
||||
if (dto2.getAgent1stAmount() != null) {
|
||||
agent1stRatioOfAvailable = (double) dto2.getAgent1stAmount() / canSeparateAmount * 100;
|
||||
}
|
||||
if (dto2.getAgent2ndAmount() != null) {
|
||||
agent2ndRatioOfAvailable = (double) dto2.getAgent2ndAmount() / canSeparateAmount * 100;
|
||||
}
|
||||
|
||||
logger.info("占比详情 (占总金额/占可分账金额): 拉卡拉={}%/{}%, 商户={}%/{}%, 平台={}%/{}%, 一级代理商={}%/{}%, 二级代理商={}%/{}%",
|
||||
String.format("%.2f", lklRatioOfTotal), String.format("%.2f", lklRatioOfAvailable),
|
||||
String.format("%.2f", mchRatioOfTotal), String.format("%.2f", mchRatioOfAvailable),
|
||||
String.format("%.2f", platRatioOfTotal), String.format("%.2f", platRatioOfAvailable),
|
||||
String.format("%.2f", agent1stRatioOfTotal), String.format("%.2f", agent1stRatioOfAvailable),
|
||||
String.format("%.2f", agent2ndRatioOfTotal), String.format("%.2f", agent2ndRatioOfAvailable));
|
||||
}
|
||||
|
||||
int total = dto2.getLklAmount() + dto2.getMchAmount() + dto2.getPlatAmount() +
|
||||
(dto2.getAgent1stAmount() != null ? dto2.getAgent1stAmount() : 0) +
|
||||
(dto2.getAgent2ndAmount() != null ? dto2.getAgent2ndAmount() : 0) + dto2.getShippingFee();
|
||||
logger.info("金额校验: {} (计算总金额={}分, 原始总金额={}分)", (total == dto2.getTotalSeparateAmount() ? "通过" : "不通过"), total, dto2.getTotalSeparateAmount());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于可分账金额的分账计算方法(默认)
|
||||
* <p>
|
||||
* 计算逻辑:
|
||||
* 1. 计算拉卡拉分账金额 = 总分账金额 × 拉卡拉分账比例(向上取整)
|
||||
* 2. 计算可分账金额 = 总分账金额 - 配送费 - 拉卡拉分账金额
|
||||
* 3. 如果refCanSeparateAmount有效且与计算出的canSeparateAmount不一致,则使用refCanSeparateAmount作为分账基数
|
||||
* 4. 调整分账比例,确保有效比例之和等于1.0
|
||||
* 5. 按优先级计算各参与方分账金额(商户 > 平台 > 一级代理商 > 二级代理商)
|
||||
* 6. 确保总额平衡并保障各参与方分账比例
|
||||
*
|
||||
* @return Pair<Boolean, String> 分账结果是否成功和失败的原因
|
||||
*/
|
||||
public Pair<Boolean, String> calcOnCanSeparateAmount() {
|
||||
// 设置分账计算方法类型
|
||||
isBasedOnTotalAmount = false;
|
||||
|
||||
// 检查前提条件
|
||||
if (!validateInputs()) {
|
||||
return Pair.of(false, "分账参数不全");
|
||||
}
|
||||
|
||||
logger.info("开始基于可分账金额的分账计算,总金额={}分,配送费={}分", totalSeparateAmount, shippingFee);
|
||||
|
||||
// 计算拉卡拉分账金额
|
||||
calculateLklAmount();
|
||||
|
||||
// 计算可分账金额
|
||||
calculateCanSeparateAmount();
|
||||
if (canSeparateAmount <= 0) {
|
||||
String errorMsg = "分账计算失败:可分账金额必须大于0,当前值=" + canSeparateAmount;
|
||||
logger.info(errorMsg);
|
||||
return Pair.of(false, errorMsg);
|
||||
}
|
||||
|
||||
// 检查并应用参考可分账金额
|
||||
checkAndApplyRefCanSeparateAmount();
|
||||
|
||||
// 调整分账比例
|
||||
adjustRatios();
|
||||
|
||||
// 按优先级分账
|
||||
performSeparate();
|
||||
|
||||
// 确保总额平衡
|
||||
balanceAmounts();
|
||||
|
||||
// 保障各参与方分账比例
|
||||
guaranteeRatios();
|
||||
|
||||
String successMsg = String.format("基于可分账金额的分账计算完成:拉卡拉=%d分, 平台=%d分, 一级代理商=%d分, 二级代理商=%d分, 商户=%d分",
|
||||
lklAmount, platAmount, agent1stAmount, agent2ndAmount, mchAmount);
|
||||
logger.info(successMsg);
|
||||
return Pair.of(true, successMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于总金额的分账计算方法
|
||||
* <p>
|
||||
* 计算逻辑:
|
||||
* 1. 计算拉卡拉分账金额 = 总分账金额 × 拉卡拉分账比例(四舍五入保留两位小数)
|
||||
* 2. 计算可分账金额 = 总分账金额 - 配送费 - 拉卡拉分账金额
|
||||
* 3. 如果refCanSeparateAmount有效且与计算出的canSeparateAmount不一致,则使用refCanSeparateAmount作为分账基数
|
||||
* 4. 调整分账比例,确保有效比例之和等于1.0
|
||||
* 5. 按优先级计算各参与方分账金额(平台 > 一级代理商 > 二级代理商 > 商户),基于可分账金额进行分账
|
||||
* 6. 确保总额平衡并保障各参与方分账比例
|
||||
*
|
||||
* @return Pair<Boolean, String> 分账结果是否成功和失败的原因
|
||||
*/
|
||||
public Pair<Boolean, String> calcOnTotalAmount() {
|
||||
// 设置分账计算方法类型
|
||||
isBasedOnTotalAmount = true;
|
||||
|
||||
// 检查前提条件
|
||||
if (!validateInputsForTotalAmount()) {
|
||||
return Pair.of(false, "分账参数不全");
|
||||
}
|
||||
|
||||
logger.info("开始基于总金额的分账计算,总金额={}分,配送费={}分", totalSeparateAmount, shippingFee);
|
||||
|
||||
// 计算拉卡拉分账金额
|
||||
calculateLklAmount();
|
||||
|
||||
// 计算可分账金额
|
||||
calculateCanSeparateAmount();
|
||||
if (canSeparateAmount <= 0) {
|
||||
String errorMsg = "基于总金额的分账计算失败:可分账金额必须大于0,当前值=" + canSeparateAmount;
|
||||
logger.info(errorMsg);
|
||||
return Pair.of(false, errorMsg);
|
||||
}
|
||||
|
||||
// 调整分账比例
|
||||
adjustRatios();
|
||||
|
||||
// 检查并应用参考可分账金额
|
||||
checkAndApplyRefCanSeparateAmount();
|
||||
|
||||
// 按优先级分账(基于总金额)
|
||||
performSeparateBasedOnTotalAmount();
|
||||
|
||||
// 确保总额平衡
|
||||
balanceAmounts();
|
||||
|
||||
// 保障各参与方分账比例(忽略商户比例保障)
|
||||
guaranteeRatiosForTotalAmount();
|
||||
|
||||
String successMsg = String.format("基于总金额的分账计算完成:拉卡拉=%d分, 平台=%d分, 一级代理商=%d分, 二级代理商=%d分, 商户=%d分",
|
||||
lklAmount, platAmount, agent1stAmount, agent2ndAmount, mchAmount);
|
||||
logger.info(successMsg);
|
||||
return Pair.of(true, successMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出具体的分账结果
|
||||
*
|
||||
* @return 分账结果字符串
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
int canSeparateAmount = getCanSeparateAmount();
|
||||
int totalSeparateAmount = getTotalSeparateAmount();
|
||||
|
||||
// 计算各分账方占总金额和可分账金额的百分比
|
||||
double lklRatioOfTotal = 0.0;
|
||||
double mchRatioOfTotal = 0.0;
|
||||
double platRatioOfTotal = 0.0;
|
||||
double agent1stRatioOfTotal = 0.0;
|
||||
double agent2ndRatioOfTotal = 0.0;
|
||||
double shippingFeeRatioOfTotal = 0.0;
|
||||
|
||||
double lklRatioOfAvailable = 0.0;
|
||||
double mchRatioOfAvailable = 0.0;
|
||||
double platRatioOfAvailable = 0.0;
|
||||
double agent1stRatioOfAvailable = 0.0;
|
||||
double agent2ndRatioOfAvailable = 0.0;
|
||||
double shippingFeeRatioOfAvailable = 0.0;
|
||||
|
||||
if (totalSeparateAmount > 0) {
|
||||
if (getLklAmount() != null) {
|
||||
lklRatioOfTotal = (double) getLklAmount() / totalSeparateAmount * 100;
|
||||
}
|
||||
if (getMchAmount() != null) {
|
||||
mchRatioOfTotal = (double) getMchAmount() / totalSeparateAmount * 100;
|
||||
}
|
||||
if (getPlatAmount() != null) {
|
||||
platRatioOfTotal = (double) getPlatAmount() / totalSeparateAmount * 100;
|
||||
}
|
||||
if (getAgent1stAmount() != null) {
|
||||
agent1stRatioOfTotal = (double) getAgent1stAmount() / totalSeparateAmount * 100;
|
||||
}
|
||||
if (getAgent2ndAmount() != null) {
|
||||
agent2ndRatioOfTotal = (double) getAgent2ndAmount() / totalSeparateAmount * 100;
|
||||
}
|
||||
if (getShippingFee() != null) {
|
||||
shippingFeeRatioOfTotal = (double) getShippingFee() / totalSeparateAmount * 100;
|
||||
}
|
||||
}
|
||||
|
||||
if (canSeparateAmount > 0) {
|
||||
if (getLklAmount() != null) {
|
||||
lklRatioOfAvailable = (double) getLklAmount() / canSeparateAmount * 100;
|
||||
}
|
||||
if (getMchAmount() != null) {
|
||||
mchRatioOfAvailable = (double) getMchAmount() / canSeparateAmount * 100;
|
||||
}
|
||||
if (getPlatAmount() != null) {
|
||||
platRatioOfAvailable = (double) getPlatAmount() / canSeparateAmount * 100;
|
||||
}
|
||||
if (getAgent1stAmount() != null) {
|
||||
agent1stRatioOfAvailable = (double) getAgent1stAmount() / canSeparateAmount * 100;
|
||||
}
|
||||
if (getAgent2ndAmount() != null) {
|
||||
agent2ndRatioOfAvailable = (double) getAgent2ndAmount() / canSeparateAmount * 100;
|
||||
}
|
||||
if (getShippingFee() != null) {
|
||||
shippingFeeRatioOfAvailable = (double) getShippingFee() / canSeparateAmount * 100;
|
||||
}
|
||||
}
|
||||
|
||||
String calculationMethod = isBasedOnTotalAmount ? "基于总交易额方式计算" : "基于可分账额方式计算";
|
||||
|
||||
return String.format("分账结果%s,总交易额=%d分, 可分账额=%d分, 拉卡拉手续费=%d分(%.2f%%/%.2f%%), 配送费=%d分(%.2f%%/%.2f%%), 商户=%d分(%.2f%%/%.2f%%), 平台=%d分(%.2f%%/%.2f%%), 一级代理商=%d分(%.2f%%/%.2f%%), 二级代理商=%d分(%.2f%%/%.2f%%)",
|
||||
calculationMethod,
|
||||
totalSeparateAmount,
|
||||
canSeparateAmount,
|
||||
getLklAmount() != null ? getLklAmount() : 0,
|
||||
lklRatioOfTotal, lklRatioOfAvailable,
|
||||
getShippingFee() != null ? getShippingFee() : 0,
|
||||
shippingFeeRatioOfTotal, shippingFeeRatioOfAvailable,
|
||||
getMchAmount() != null ? getMchAmount() : 0,
|
||||
mchRatioOfTotal, mchRatioOfAvailable,
|
||||
getPlatAmount() != null ? getPlatAmount() : 0,
|
||||
platRatioOfTotal, platRatioOfAvailable,
|
||||
getAgent1stAmount() != null ? getAgent1stAmount() : 0,
|
||||
agent1stRatioOfTotal, agent1stRatioOfAvailable,
|
||||
getAgent2ndAmount() != null ? getAgent2ndAmount() : 0,
|
||||
agent2ndRatioOfTotal, agent2ndRatioOfAvailable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将对象转换为JSON字符串格式
|
||||
*
|
||||
* @return 包含所有属性的JSON字符串
|
||||
*/
|
||||
public String toJSON() {
|
||||
StringBuilder json = new StringBuilder();
|
||||
json.append("{");
|
||||
|
||||
// 添加基本属性
|
||||
appendProperty(json, "totalSeparateAmount", totalSeparateAmount, true);
|
||||
appendProperty(json, "canSeparateAmount", canSeparateAmount, false);
|
||||
appendProperty(json, "refCanSeparateAmount", refCanSeparateAmount, false);
|
||||
appendProperty(json, "shippingFee", shippingFee, false);
|
||||
|
||||
// 添加比例属性
|
||||
appendProperty(json, "lklRatio", lklRatio, false);
|
||||
appendProperty(json, "mchRatio", mchRatio, false);
|
||||
appendProperty(json, "platRatio", platRatio, false);
|
||||
appendProperty(json, "agent1stRatio", agent1stRatio, false);
|
||||
appendProperty(json, "agent2ndRatio", agent2ndRatio, false);
|
||||
|
||||
// 添加金额属性
|
||||
appendProperty(json, "lklAmount", lklAmount, false);
|
||||
appendProperty(json, "mchAmount", mchAmount, false);
|
||||
appendProperty(json, "platAmount", platAmount, false);
|
||||
appendProperty(json, "agent1stAmount", agent1stAmount, false);
|
||||
appendProperty(json, "agent2ndAmount", agent2ndAmount, false);
|
||||
|
||||
// 移除最后的逗号并关闭JSON对象
|
||||
if (json.charAt(json.length() - 1) == ',') {
|
||||
json.setLength(json.length() - 1);
|
||||
}
|
||||
json.append("}");
|
||||
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
// ================================ 私有方法 ================================
|
||||
|
||||
/**
|
||||
* 验证基于可分账金额分账的输入参数
|
||||
*/
|
||||
private boolean validateInputs() {
|
||||
if (totalSeparateAmount == null || totalSeparateAmount <= 0) {
|
||||
logger.info("分账计算失败:分账总金额必须大于0,当前值={}", totalSeparateAmount);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (shippingFee == null || shippingFee < 0) {
|
||||
logger.info("分账计算失败:配送费不能小于0,当前值={}", shippingFee);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lklRatio == null || lklRatio.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
logger.info("分账计算失败:拉卡拉分账比例必须大于0,当前值={}", lklRatio);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mchRatio == null || mchRatio.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
logger.info("分账计算失败:商户分账比例必须大于0,当前值={}", mchRatio);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (platRatio == null || platRatio.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
logger.info("分账计算失败:平台分账比例必须大于0,当前值={}", platRatio);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证基于总金额分账的输入参数
|
||||
*/
|
||||
private boolean validateInputsForTotalAmount() {
|
||||
// 基于总金额的分账计算参数验证与基于可分账金额的验证相同
|
||||
return validateInputs();
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算拉卡拉分账金额
|
||||
*/
|
||||
private void calculateLklAmount() {
|
||||
BigDecimal lklAmountDecimal = new BigDecimal(totalSeparateAmount).multiply(lklRatio);
|
||||
lklAmount = lklAmountDecimal.setScale(2, RoundingMode.HALF_UP).intValue();
|
||||
logger.debug("拉卡拉分账计算:总金额{} × 拉卡拉比例{} = {},四舍五入保留两位小数后={}",
|
||||
totalSeparateAmount, lklRatio, lklAmountDecimal, lklAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算可分账金额
|
||||
*/
|
||||
private void calculateCanSeparateAmount() {
|
||||
canSeparateAmount = totalSeparateAmount - shippingFee - lklAmount;
|
||||
logger.debug("可分账金额计算:总金额{} - 配送费{} - 拉卡拉分账{} = {}",
|
||||
totalSeparateAmount, shippingFee, lklAmount, canSeparateAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查refCanSeparateAmount是否有效
|
||||
* 有效条件:非空且大于0且小于totalSeparateAmount
|
||||
*
|
||||
* @return true表示有效,false表示无效
|
||||
*/
|
||||
private boolean isRefCanSeparateAmountValid() {
|
||||
return refCanSeparateAmount != null && refCanSeparateAmount > 0 && refCanSeparateAmount < totalSeparateAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分账基数金额
|
||||
* 如果refCanSeparateAmount有效,则使用refCanSeparateAmount,否则使用canSeparateAmount
|
||||
*
|
||||
* @return 分账基数金额
|
||||
*/
|
||||
private int getSeparateBaseAmount() {
|
||||
if (isRefCanSeparateAmountValid()) {
|
||||
return refCanSeparateAmount;
|
||||
}
|
||||
return canSeparateAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查并应用参考可分账金额
|
||||
* 当refCanSeparateAmount有效且与计算出的canSeparateAmount不一致时,
|
||||
* 将差额分配给指定优先级的分账对象(平台 > 一级代理商 > 二级代理商 > 商户)
|
||||
*/
|
||||
private void checkAndApplyRefCanSeparateAmount() {
|
||||
// 判断refCanSeparateAmount是否有效(非空且大于0且小于totalSeparateAmount)
|
||||
if (isRefCanSeparateAmountValid()) {
|
||||
// 比较refCanSeparateAmount与计算出的canSeparateAmount
|
||||
if (!refCanSeparateAmount.equals(canSeparateAmount)) {
|
||||
int difference = refCanSeparateAmount - canSeparateAmount;
|
||||
logger.info("检测到refCanSeparateAmount与计算出的canSeparateAmount不一致,差额={}分。" +
|
||||
"refCanSeparateAmount={}分,计算出的canSeparateAmount={}分。",
|
||||
difference, refCanSeparateAmount, canSeparateAmount);
|
||||
|
||||
// 将差额分配给指定优先级的分账对象(商户 > 二级代理商 > 一级代理商 > 平台)
|
||||
if (difference != 0) {
|
||||
if (mchAmount == null) mchAmount = 0;
|
||||
if (agent2ndAmount == null) agent2ndAmount = 0;
|
||||
if (agent1stAmount == null) agent1stAmount = 0;
|
||||
if (platAmount == null) platAmount = 0;
|
||||
|
||||
if (difference > 0) {
|
||||
// 如果差额为正,优先增加高优先级参与方的金额
|
||||
mchAmount += difference;
|
||||
} else {
|
||||
// 如果差额为负,优先从低优先级参与方扣除
|
||||
int diff = -difference;
|
||||
if (mchAmount >= diff) {
|
||||
mchAmount -= diff;
|
||||
} else if (agent2ndAmount > 0 && agent2ndAmount >= diff) {
|
||||
agent2ndAmount -= diff;
|
||||
} else if (agent1stAmount > 0 && agent1stAmount >= diff) {
|
||||
agent1stAmount -= diff;
|
||||
} else {
|
||||
platAmount -= diff;
|
||||
}
|
||||
}
|
||||
logger.debug("已将差额{}分应用于分账金额调整", difference);
|
||||
}
|
||||
} else {
|
||||
logger.debug("refCanSeparateAmount与计算出的canSeparateAmount一致,值={}分", canSeparateAmount);
|
||||
}
|
||||
} else {
|
||||
logger.debug("refCanSeparateAmount无效或未设置,使用计算出的canSeparateAmount={}分作为分账基数", canSeparateAmount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调整分账比例,确保有效值比例相加等于1.0
|
||||
*/
|
||||
private void adjustRatios() {
|
||||
// 计算有效的分账比例总和
|
||||
BigDecimal effectiveRatioSum = BigDecimal.ZERO
|
||||
.add(mchRatio)
|
||||
.add(platRatio)
|
||||
.add(agent1stRatio != null ? agent1stRatio : BigDecimal.ZERO)
|
||||
.add(agent2ndRatio != null ? agent2ndRatio : BigDecimal.ZERO);
|
||||
|
||||
logger.debug("调整前各分账比例:商户={},平台={},一级代理商={},二级代理商={},有效比例总和={}",
|
||||
mchRatio, platRatio, agent1stRatio, agent2ndRatio, effectiveRatioSum);
|
||||
|
||||
// 动态调整最后一个分账方的比例,确保总和为1.0
|
||||
BigDecimal adjustmentRatio = BigDecimal.ONE.subtract(effectiveRatioSum);
|
||||
if (agent2ndRatio != null && agent2ndRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
// 调整二级代理商比例
|
||||
agent2ndRatio = agent2ndRatio.add(adjustmentRatio);
|
||||
} else if (agent1stRatio != null && agent1stRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
// 调整一级代理商比例
|
||||
agent1stRatio = agent1stRatio.add(adjustmentRatio);
|
||||
} else {
|
||||
// 调整平台比例
|
||||
platRatio = platRatio.add(adjustmentRatio);
|
||||
}
|
||||
|
||||
logger.debug("调整后各分账比例:商户={},平台={},一级代理商={},二级代理商={}",
|
||||
mchRatio, platRatio, agent1stRatio, agent2ndRatio);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按优先级进行分账(基于可分账金额)
|
||||
*/
|
||||
private void performSeparate() {
|
||||
// 确定分账基数
|
||||
int separateBaseAmount = getSeparateBaseAmount();
|
||||
|
||||
// 商户分账金额 = 可分账金额 × 商户分账比例(四舍五入)
|
||||
BigDecimal mchAmountDecimal = new BigDecimal(separateBaseAmount).multiply(mchRatio);
|
||||
mchAmount = mchAmountDecimal.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||
logger.debug("商户分账计算:可分账金额{} × 商户比例{} = {},四舍五入后={}", separateBaseAmount, mchRatio, mchAmountDecimal, mchAmount);
|
||||
|
||||
// 平台分账金额 = 可分账金额 × 平台分账比例(四舍五入)
|
||||
BigDecimal platAmountDecimal = new BigDecimal(separateBaseAmount).multiply(platRatio);
|
||||
platAmount = platAmountDecimal.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||
logger.debug("平台分账计算:可分账金额{} × 平台比例{} = {},四舍五入后={}", separateBaseAmount, platRatio, platAmountDecimal, platAmount);
|
||||
|
||||
// 一级代理商分账金额 = 可分账金额 × 一级代理商分账比例(四舍五入)
|
||||
if (agent1stRatio != null && agent1stRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
BigDecimal agent1stAmountDecimal = new BigDecimal(separateBaseAmount).multiply(agent1stRatio);
|
||||
agent1stAmount = agent1stAmountDecimal.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||
logger.debug("一级代理商分账计算:可分账金额{} × 一级代理商比例{} = {},四舍五入后={}", separateBaseAmount, agent1stRatio, agent1stAmountDecimal, agent1stAmount);
|
||||
} else {
|
||||
agent1stAmount = 0;
|
||||
}
|
||||
|
||||
// 二级代理商分账金额 = 可分账金额 × 二级代理商分账比例(四舍五入)
|
||||
if (agent2ndRatio != null && agent2ndRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
BigDecimal agent2ndAmountDecimal = new BigDecimal(separateBaseAmount).multiply(agent2ndRatio);
|
||||
agent2ndAmount = agent2ndAmountDecimal.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||
logger.debug("二级代理商分账计算:可分账金额{} × 二级代理商比例{} = {},四舍五入后={}", separateBaseAmount, agent2ndRatio, agent2ndAmountDecimal, agent2ndAmount);
|
||||
} else {
|
||||
agent2ndAmount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 按优先级进行分账(基于总金额)
|
||||
*/
|
||||
private void performSeparateBasedOnTotalAmount() {
|
||||
// 确定分账基数
|
||||
int separateBaseAmount = getSeparateBaseAmount();
|
||||
|
||||
// 平台分账金额 = 可分账金额 × 平台分账比例(四舍五入)
|
||||
BigDecimal platAmountDecimal = new BigDecimal(separateBaseAmount).multiply(platRatio);
|
||||
platAmount = platAmountDecimal.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||
logger.debug("平台分账计算:可分账金额{} × 平台比例{} = {},四舍五入后={}", separateBaseAmount, platRatio, platAmountDecimal, platAmount);
|
||||
|
||||
// 一级代理商分账金额 = 可分账金额 × 一级代理商分账比例(四舍五入)
|
||||
if (agent1stRatio != null && agent1stRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
BigDecimal agent1stAmountDecimal = new BigDecimal(separateBaseAmount).multiply(agent1stRatio);
|
||||
agent1stAmount = agent1stAmountDecimal.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||
logger.debug("一级代理商分账计算:可分账金额{} × 一级代理商比例{} = {},四舍五入后={}", separateBaseAmount, agent1stRatio, agent1stAmountDecimal, agent1stAmount);
|
||||
} else {
|
||||
agent1stAmount = 0;
|
||||
}
|
||||
|
||||
// 二级代理商分账金额 = 可分账金额 × 二级代理商分账比例(四舍五入)
|
||||
if (agent2ndRatio != null && agent2ndRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
BigDecimal agent2ndAmountDecimal = new BigDecimal(separateBaseAmount).multiply(agent2ndRatio);
|
||||
agent2ndAmount = agent2ndAmountDecimal.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||
logger.debug("二级代理商分账计算:可分账金额{} × 二级代理商比例{} = {},四舍五入后={}", separateBaseAmount, agent2ndRatio, agent2ndAmountDecimal, agent2ndAmount);
|
||||
} else {
|
||||
agent2ndAmount = 0;
|
||||
}
|
||||
|
||||
// 商户分账金额 = 可分账金额 - 平台分账金额 - 一级代理商分账金额 - 二级代理商分账金额
|
||||
mchAmount = separateBaseAmount - platAmount - agent1stAmount - agent2ndAmount;
|
||||
logger.debug("商户分账计算:可分账金额{} - 平台分账{} - 一级代理商分账{} - 二级代理商分账{} = {}",
|
||||
separateBaseAmount, platAmount, agent1stAmount, agent2ndAmount, mchAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 确保总额平衡
|
||||
*/
|
||||
private void balanceAmounts() {
|
||||
// 确定分账基数
|
||||
int separateBaseAmount = getSeparateBaseAmount();
|
||||
|
||||
int totalAmount = mchAmount + platAmount + agent1stAmount + agent2ndAmount;
|
||||
if (totalAmount != separateBaseAmount) {
|
||||
int diff = separateBaseAmount - totalAmount;
|
||||
logger.debug("分账总额与可分账金额不符,差额={},开始调整", diff);
|
||||
|
||||
// 将差额分配给优先级最低的参与方,确保总额平衡
|
||||
if (mchAmount + diff >= 0) {
|
||||
mchAmount += diff;
|
||||
logger.debug("调整商户分账金额:{} + {} = {}", mchAmount - diff, diff, mchAmount);
|
||||
} else if (agent2ndAmount > 0 && agent2ndAmount + diff >= 0) {
|
||||
agent2ndAmount += diff;
|
||||
logger.debug("调整二级代理商分账金额:{} + {} = {}", agent2ndAmount - diff, diff, agent2ndAmount);
|
||||
} else if (agent1stAmount > 0 && agent1stAmount + diff >= 0) {
|
||||
agent1stAmount += diff;
|
||||
logger.debug("调整一级代理商分账金额:{} + {} = {}", agent1stAmount - diff, diff, agent1stAmount);
|
||||
} else if (platAmount + diff >= 0) {
|
||||
platAmount += diff;
|
||||
logger.debug("调整平台分账金额:{} + {} = {}", platAmount - diff, diff, platAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保障各参与方分账比例不低于指定值(基于总金额的分账计算专用)
|
||||
* 忽略商户比例保障,只保障平台、一级代理商、二级代理商的比例
|
||||
*/
|
||||
private void guaranteeRatiosForTotalAmount() {
|
||||
// 平台优先级最高
|
||||
guaranteePlatformRatio();
|
||||
|
||||
// 一级代理商优先级次之
|
||||
guaranteeAgent1stRatio();
|
||||
|
||||
// 不保障商户比例,商户只分到剩余余额
|
||||
}
|
||||
|
||||
/**
|
||||
* 保障各参与方分账比例不低于指定值
|
||||
*/
|
||||
private void guaranteeRatios() {
|
||||
// 商户优先级最高
|
||||
guaranteeMerchantRatio();
|
||||
|
||||
// 平台优先级次之
|
||||
guaranteePlatformRatio();
|
||||
|
||||
// 一级代理商优先级再次之
|
||||
guaranteeAgent1stRatio();
|
||||
|
||||
// 最终验证和调整,确保所有参与方分账比例不低于指定值
|
||||
finalGuaranteeMerchantRatio();
|
||||
}
|
||||
|
||||
/**
|
||||
* 保障商户分账比例
|
||||
*/
|
||||
private void guaranteeMerchantRatio() {
|
||||
// 确定分账基数
|
||||
int separateBaseAmount = getSeparateBaseAmount();
|
||||
|
||||
BigDecimal actualMchRatio = new BigDecimal(mchAmount).divide(new BigDecimal(separateBaseAmount), 6, RoundingMode.HALF_UP);
|
||||
if (actualMchRatio.compareTo(mchRatio) < 0) {
|
||||
int requiredMchAmount = mchRatio.multiply(new BigDecimal(separateBaseAmount)).setScale(0, RoundingMode.HALF_UP).intValue();
|
||||
int diff = requiredMchAmount - mchAmount;
|
||||
if (diff > 0) {
|
||||
logger.debug("商户分账比例不足,需要调整金额={},商户当前金额={},应得金额={}", diff, mchAmount, requiredMchAmount);
|
||||
|
||||
if (agent2ndAmount > 0 && agent2ndAmount >= diff) {
|
||||
agent2ndAmount -= diff;
|
||||
mchAmount += diff;
|
||||
logger.debug("从二级代理商调整{}给商户,调整后:商户={},二级代理商={}", diff, mchAmount, agent2ndAmount);
|
||||
} else if (agent1stAmount > 0 && agent1stAmount >= diff) {
|
||||
agent1stAmount -= diff;
|
||||
mchAmount += diff;
|
||||
logger.debug("从一级代理商调整{}给商户,调整后:商户={},一级代理商={}", diff, mchAmount, agent1stAmount);
|
||||
} else if (platAmount >= diff) {
|
||||
platAmount -= diff;
|
||||
mchAmount += diff;
|
||||
logger.debug("从平台调整{}给商户,调整后:商户={},平台={}", diff, mchAmount, platAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保障平台分账比例
|
||||
*/
|
||||
private void guaranteePlatformRatio() {
|
||||
// 确定分账基数
|
||||
int separateBaseAmount = getSeparateBaseAmount();
|
||||
|
||||
BigDecimal actualPlatRatio = new BigDecimal(platAmount).divide(new BigDecimal(separateBaseAmount), 6, RoundingMode.HALF_UP);
|
||||
if (actualPlatRatio.compareTo(platRatio) < 0) {
|
||||
int requiredPlatAmount = platRatio.multiply(new BigDecimal(separateBaseAmount)).setScale(0, RoundingMode.HALF_UP).intValue();
|
||||
int diff = requiredPlatAmount - platAmount;
|
||||
if (diff > 0) {
|
||||
logger.debug("平台分账比例不足,需要调整金额={},平台当前金额={},应得金额={}", diff, platAmount, requiredPlatAmount);
|
||||
|
||||
if (agent2ndAmount > 0 && agent2ndAmount >= diff) {
|
||||
agent2ndAmount -= diff;
|
||||
platAmount += diff;
|
||||
logger.debug("从二级代理商调整{}给平台,调整后:平台={},二级代理商={}", diff, platAmount, agent2ndAmount);
|
||||
} else if (agent1stAmount > 0 && agent1stAmount >= diff) {
|
||||
agent1stAmount -= diff;
|
||||
platAmount += diff;
|
||||
logger.debug("从一级代理商调整{}给平台,调整后:平台={},一级代理商={}", diff, platAmount, agent1stAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保障一级代理商分账比例
|
||||
*/
|
||||
private void guaranteeAgent1stRatio() {
|
||||
// 确定分账基数
|
||||
int separateBaseAmount = getSeparateBaseAmount();
|
||||
|
||||
if (agent1stRatio != null && agent1stRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
BigDecimal actualAgent1stRatio = new BigDecimal(agent1stAmount).divide(new BigDecimal(separateBaseAmount), 6, RoundingMode.HALF_UP);
|
||||
if (actualAgent1stRatio.compareTo(agent1stRatio) < 0) {
|
||||
int requiredAgent1stAmount = agent1stRatio.multiply(new BigDecimal(separateBaseAmount)).setScale(0, RoundingMode.HALF_UP).intValue();
|
||||
int diff = requiredAgent1stAmount - agent1stAmount;
|
||||
if (diff > 0) {
|
||||
logger.debug("一级代理商分账比例不足,需要调整金额={},一级代理商当前金额={},应得金额={}", diff, agent1stAmount, requiredAgent1stAmount);
|
||||
|
||||
if (agent2ndAmount > 0 && agent2ndAmount >= diff) {
|
||||
agent2ndAmount -= diff;
|
||||
agent1stAmount += diff;
|
||||
logger.debug("从二级代理商调整{}给一级代理商,调整后:一级代理商={},二级代理商={}", diff, agent1stAmount, agent2ndAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 最终保障商户分账比例
|
||||
*/
|
||||
private void finalGuaranteeMerchantRatio() {
|
||||
// 确定分账基数
|
||||
int separateBaseAmount = getSeparateBaseAmount();
|
||||
|
||||
BigDecimal finalMchRatio = new BigDecimal(mchAmount).divide(new BigDecimal(separateBaseAmount), 6, RoundingMode.HALF_UP);
|
||||
if (finalMchRatio.compareTo(mchRatio) < 0) {
|
||||
int requiredMchAmount = mchRatio.multiply(new BigDecimal(separateBaseAmount)).setScale(0, RoundingMode.UP).intValue();
|
||||
int diff = requiredMchAmount - mchAmount;
|
||||
if (diff > 0) {
|
||||
logger.debug("商户最终分账比例仍不足,需要调整金额={},商户当前金额={},应得金额={}", diff, mchAmount, requiredMchAmount);
|
||||
|
||||
if (agent2ndAmount > 0 && agent2ndAmount >= diff) {
|
||||
agent2ndAmount -= diff;
|
||||
mchAmount += diff;
|
||||
logger.debug("最终调整:从二级代理商调整{}给商户,调整后:商户={},二级代理商={}", diff, mchAmount, agent2ndAmount);
|
||||
} else {
|
||||
int remainingDiff = diff - agent2ndAmount;
|
||||
if (agent1stAmount > 0 && agent1stAmount >= remainingDiff) {
|
||||
agent1stAmount -= remainingDiff;
|
||||
mchAmount += diff;
|
||||
logger.debug("最终调整:从一级代理商调整{}给商户,调整后:商户={},一级代理商={}", remainingDiff, mchAmount, agent1stAmount);
|
||||
} else {
|
||||
int remainingDiff2 = remainingDiff - agent1stAmount;
|
||||
if (platAmount >= remainingDiff2) {
|
||||
platAmount -= remainingDiff2;
|
||||
mchAmount += diff;
|
||||
logger.debug("最终调整:从平台调整{}给商户,调整后:商户={},平台={}", remainingDiff2, mchAmount, platAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 向JSON字符串中添加属性
|
||||
*
|
||||
* @param json StringBuilder对象
|
||||
* @param key 属性名
|
||||
* @param value 属性值
|
||||
* @param first 是否为第一个属性
|
||||
*/
|
||||
private void appendProperty(StringBuilder json, String key, Object value, boolean first) {
|
||||
if (!first) {
|
||||
json.append(",");
|
||||
}
|
||||
json.append("\"").append(key).append("\":");
|
||||
if (value == null) {
|
||||
json.append("null");
|
||||
} else if (value instanceof String) {
|
||||
json.append("\"").append(value).append("\"");
|
||||
} else {
|
||||
json.append(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package com.suisung.mall.shop.components.quartz.job;
|
||||
|
||||
import com.suisung.mall.shop.config.SpringUtil;
|
||||
import com.suisung.mall.shop.lakala.service.LakalaApiService;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
|
||||
/**
|
||||
* 分账状态更改补偿 定时任务
|
||||
*/
|
||||
public class UpdateOrderSeparateJob extends QuartzJobBean {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(UpdateOrderSeparateJob.class);
|
||||
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
|
||||
LakalaApiService lakalaApiService = SpringUtil.getBean(LakalaApiService.class);
|
||||
|
||||
// lakalaApiService.fixedOrderSeparateStatus();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -73,6 +73,10 @@ public class LakalaController extends BaseControllerImpl {
|
||||
@Resource
|
||||
private MqMessageService mqMessageService;
|
||||
|
||||
@Lazy
|
||||
@Resource
|
||||
private LakalaApiService lakalaApiService;
|
||||
|
||||
@Resource
|
||||
private LklLedgerEcService lklLedgerEcService;
|
||||
|
||||
@ -110,8 +114,9 @@ public class LakalaController extends BaseControllerImpl {
|
||||
|
||||
// return shopOrderBaseService.sameCityOrderExpireSeconds(10000L);
|
||||
|
||||
return sfExpressApiService.createSfExpressShop(66, "能辉超市", "桂平市", "广西壮族自治区贵港市桂平市广佰汇超市(桂平店)", "谢能坤", "17777525395", "110.07165452271", "23.369069486251");
|
||||
// return sfExpressApiService.createSfExpressShop(66, "能辉超市", "桂平市", "广西壮族自治区贵港市桂平市广佰汇超市(桂平店)", "谢能坤", "17777525395", "110.07165452271", "23.369069486251");
|
||||
|
||||
return lakalaApiService.sacsQuery("8226330541100GU", "20250918770188017227140800").toString();
|
||||
}
|
||||
|
||||
@ApiOperation(value = "批量发送推送消息 - 测试案例", notes = "批量发送推送消息 - 测试案例")
|
||||
@ -224,7 +229,7 @@ public class LakalaController extends BaseControllerImpl {
|
||||
@ApiOperation(value = "分账关系绑定申请异步回调通知", notes = "分账关系绑定申请异步回调通知")
|
||||
@RequestMapping(value = "/sacs/separateNotify", method = RequestMethod.POST)
|
||||
public ResponseEntity<JSONObject> separateNotify(HttpServletRequest request) {
|
||||
JSONObject resp = lakalaPayService.sacsSeparateNotify(request);
|
||||
JSONObject resp = lakalaPayService.sacsSeparateNotify(request, "", "");
|
||||
if (resp != null && "SUCCESS".equals(resp.get("code"))) {
|
||||
return ResponseEntity.ok(resp);
|
||||
}
|
||||
|
||||
@ -213,9 +213,11 @@ public interface LakalaApiService {
|
||||
* 参考:https://o.lakala.com/#/home/document/detail?id=393
|
||||
*
|
||||
* @param request
|
||||
* @param merchantNo 分账方商户号,非空表示是事后补偿
|
||||
* @param separateNo 分账指令流水号,非空表示是事后补偿
|
||||
* @return
|
||||
*/
|
||||
JSONObject sacsSeparateNotify(HttpServletRequest request);
|
||||
JSONObject sacsSeparateNotify(HttpServletRequest request, String merchantNo, String separateNo);
|
||||
|
||||
/**
|
||||
* 查询拉卡拉商户可分账的金额
|
||||
@ -252,6 +254,19 @@ public interface LakalaApiService {
|
||||
*/
|
||||
JSONObject queryMchCanSplitAmtInner(String merchantNo, String logNo, String logDate);
|
||||
|
||||
|
||||
/**
|
||||
* 分账查询结果
|
||||
* <p>
|
||||
* 用于查询已发起的分账交易的处理结果状态
|
||||
* 参考:https://o.lakala.com/#/home/document/detail?id=392
|
||||
*
|
||||
* @param merchantNo 分账方商户号
|
||||
* @param separateNo 分账指令流水号
|
||||
* @return 分账结果数据,包含分账状态等信息;查询失败时返回null
|
||||
*/
|
||||
JSONObject sacsQuery(String merchantNo, String separateNo);
|
||||
|
||||
/**
|
||||
* 订单分账撤销
|
||||
* 参考:https://o.lakala.com/#/home/document/detail?id=390
|
||||
|
||||
@ -11,6 +11,9 @@ package com.suisung.mall.shop.lakala.service;
|
||||
import com.suisung.mall.common.modules.lakala.LklOrderSeparate;
|
||||
import com.suisung.mall.core.web.service.IBaseService;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public interface LklOrderSeparateService extends IBaseService<LklOrderSeparate> {
|
||||
|
||||
/**
|
||||
@ -58,4 +61,14 @@ public interface LklOrderSeparateService extends IBaseService<LklOrderSeparate>
|
||||
* @return
|
||||
*/
|
||||
Boolean updateRemark(String logNo, String separateNo, String remark);
|
||||
|
||||
|
||||
/**
|
||||
* 查询未成功分账的记录
|
||||
*
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
List<LklOrderSeparate> unSuccessSeparateList(Date beginDate, Date endDate);
|
||||
|
||||
}
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
|
||||
package com.suisung.mall.shop.lakala.service.impl;
|
||||
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
@ -32,7 +31,7 @@ import com.suisung.mall.common.modules.lakala.*;
|
||||
import com.suisung.mall.common.modules.order.ShopOrderLkl;
|
||||
import com.suisung.mall.common.modules.store.ShopMchEntry;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreBase;
|
||||
import com.suisung.mall.common.pojo.dto.LklSeparateDTOBak;
|
||||
import com.suisung.mall.common.pojo.dto.LklSeparateDTO;
|
||||
import com.suisung.mall.common.service.impl.CommonService;
|
||||
import com.suisung.mall.common.utils.*;
|
||||
import com.suisung.mall.shop.lakala.service.*;
|
||||
@ -1851,6 +1850,77 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分账查询结果
|
||||
* <p>
|
||||
* 用于查询已发起的分账交易的处理结果状态
|
||||
* 参考:https://o.lakala.com/#/home/document/detail?id=392
|
||||
*
|
||||
* @param merchantNo 分账方商户号
|
||||
* @param separateNo 分账指令流水号
|
||||
* @return 分账结果数据,包含分账状态等信息;查询失败时返回null
|
||||
*/
|
||||
@Override
|
||||
public JSONObject sacsQuery(String merchantNo, String separateNo) {
|
||||
// 1. 参数校验
|
||||
if (StrUtil.hasBlank(merchantNo, separateNo)) {
|
||||
log.warn("[分账查询结果] 参数缺失, merchantNo={}, separateNo={}", merchantNo, separateNo);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// 2. 初始化拉卡拉SDK配置
|
||||
initLKLSDK();
|
||||
|
||||
// 3. 构造请求参数
|
||||
V3SacsQueryRequest v3QueryRequest = new V3SacsQueryRequest();
|
||||
v3QueryRequest.setMerchantNo(merchantNo);
|
||||
v3QueryRequest.setSeparateNo(separateNo);
|
||||
|
||||
// 4. 发送HTTP请求到拉卡拉服务器
|
||||
String responseStr = LKLSDK.httpPost(v3QueryRequest);
|
||||
|
||||
// 5. 检查响应结果
|
||||
if (StrUtil.isBlank(responseStr)) {
|
||||
log.warn("[分账查询结果] 服务器无返回值, merchantNo={}, separateNo={}", merchantNo, separateNo);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 6. 解析响应JSON
|
||||
JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr);
|
||||
if (lakalaRespJSON == null) {
|
||||
log.error("[分账查询结果] 响应数据解析失败, merchantNo={}, separateNo={}, response={}",
|
||||
merchantNo, separateNo, responseStr);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 7. 检查业务状态码
|
||||
String code = lakalaRespJSON.getStr("code");
|
||||
if (!"SACS0000".equals(code)) {
|
||||
log.warn("[分账查询结果] 业务处理失败, merchantNo={}, separateNo={}, code={}, message={}",
|
||||
merchantNo, separateNo, code, lakalaRespJSON.getStr("message"));
|
||||
return null;
|
||||
}
|
||||
|
||||
// 8. 检查响应数据
|
||||
JSONObject respData = lakalaRespJSON.getJSONObject("resp_data");
|
||||
if (respData == null) {
|
||||
log.warn("[分账查询结果] 响应数据为空, merchantNo={}, separateNo={}, response={}",
|
||||
merchantNo, separateNo, responseStr);
|
||||
return null;
|
||||
}
|
||||
|
||||
log.info("[分账查询结果] 查询成功, merchantNo={}, separateNo={}", merchantNo, separateNo);
|
||||
return respData;
|
||||
} catch (SDKException e) {
|
||||
log.error("[分账查询结果] SDK调用异常, merchantNo={}, separateNo={}", merchantNo, separateNo, e);
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
log.error("[分账查询结果] 查询过程中发生未知异常, merchantNo={}, separateNo={}", merchantNo, separateNo, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 执行拉卡拉订单分账操作
|
||||
@ -2221,31 +2291,32 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
BigDecimal wxFeeRatio = StrUtil.isEmpty(wxFee) ? BigDecimal.valueOf(0.0025) : new BigDecimal(wxFee).divide(BigDecimal.valueOf(100));
|
||||
|
||||
// 构建分账参数对象
|
||||
LklSeparateDTOBak lklSeparateDTOBak = new LklSeparateDTOBak();
|
||||
lklSeparateDTOBak.setTotalSeparateAmount(shopOrderLkl.getTotal_amt());
|
||||
lklSeparateDTOBak.setShippingFee(shoppingFeeInner);
|
||||
lklSeparateDTOBak.setLklRatio(wxFeeRatio); // 拉卡拉给的微信分账比例 0.0025 千分之2.5
|
||||
lklSeparateDTOBak.setMchRatio(mchSplitRatio);
|
||||
lklSeparateDTOBak.setPlatRatio(platformSplitRatio);
|
||||
LklSeparateDTO lklSeparateDTO = new LklSeparateDTO();
|
||||
lklSeparateDTO.setTotalSeparateAmount(shopOrderLkl.getTotal_amt());
|
||||
lklSeparateDTO.setShippingFee(shoppingFeeInner);
|
||||
lklSeparateDTO.setLklRatio(wxFeeRatio); // 拉卡拉给的微信分账比例 0.0025 千分之2.5
|
||||
lklSeparateDTO.setMchRatio(mchSplitRatio);
|
||||
lklSeparateDTO.setPlatRatio(platformSplitRatio);
|
||||
|
||||
if (distributorSplitRatio.compareTo(BigDecimal.ZERO) > 0) { // 二级代理商参与分账
|
||||
lklSeparateDTOBak.setAgent2ndRatio(distributorSplitRatio);
|
||||
lklSeparateDTO.setAgent2ndRatio(distributorSplitRatio);
|
||||
}
|
||||
lklSeparateDTOBak.setRefCanSeparateAmount(canSeparateAmt); // 拉卡拉实时返回的可分账金额
|
||||
lklSeparateDTO.setRefCanSeparateAmount(canSeparateAmt); // 拉卡拉实时返回的可分账金额
|
||||
|
||||
// 分账方式:根据可分账金额分账
|
||||
Pair<Boolean, String> canSeparateAmtResult = lklSeparateDTOBak.calcOnCanSeparateAmount();
|
||||
if (!canSeparateAmtResult.getFirst()) {
|
||||
log.error("[分账操作] 分账参数评估,结果无法分账 {}", lklSeparateDTOBak);
|
||||
LklSeparateDTO.SharingResult canSeparateAmtResult = lklSeparateDTO.sharingOnCanSeparateAmount();
|
||||
if (!canSeparateAmtResult.isSuccess()) {
|
||||
log.error("[分账操作] 分账参数评估,结果无法分账 {}", lklSeparateDTO);
|
||||
return Pair.of(false, "分账参数评估,结果无法分账");
|
||||
}
|
||||
|
||||
log.debug("[分账操作] 分账参数计算结果:{}", lklSeparateDTOBak);
|
||||
log.debug("[分账操作] 分账参数计算结果:{}", lklSeparateDTO);
|
||||
|
||||
// 更新分账计算结果
|
||||
shopOrderLkl.setSeparate_remark(lklSeparateDTOBak.toString());
|
||||
shopOrderLkl.setSeparate_remark(lklSeparateDTO.toString());
|
||||
if (CheckUtil.isEmpty(canSeparateAmt)) {
|
||||
shopOrderLkl.setSplit_amt(lklSeparateDTOBak.getCanSeparateAmount());
|
||||
canSeparateAmt = lklSeparateDTOBak.getCanSeparateAmount();
|
||||
shopOrderLkl.setSplit_amt(lklSeparateDTO.getCanSeparateAmount());
|
||||
canSeparateAmt = lklSeparateDTO.getCanSeparateAmount();
|
||||
} else {
|
||||
shopOrderLkl.setSplit_amt_ref(canSeparateAmt);
|
||||
}
|
||||
@ -2265,9 +2336,9 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
// 构建分账接收方列表
|
||||
List<V3SacsSeparateRecvDatas> recvDatas = new ArrayList<>();
|
||||
|
||||
Integer merchantAmount = lklSeparateDTOBak.getMchAmount();
|
||||
Integer platformAmount = lklSeparateDTOBak.getPlatAmount();
|
||||
Integer agentAmount = lklSeparateDTOBak.getAgent2ndAmount();
|
||||
Integer merchantAmount = lklSeparateDTO.getMchAmount();
|
||||
Integer platformAmount = lklSeparateDTO.getPlatAmount();
|
||||
Integer agentAmount = lklSeparateDTO.getAgent2ndAmount();
|
||||
|
||||
log.info("[分账操作] 金额计算结果:订单={}, 商户={}, 总金额={}分, 可分金额={}分, 商家比例={}, 商家分得={}分, 平台比例={}, 平台分得={}分, 代理商比例={}, 代理商分得={}分",
|
||||
orderId, merchantNo, shopOrderLkl.getTotal_amt(), canSeparateAmt, mchSplitRatio, merchantAmount,
|
||||
@ -2362,7 +2433,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
separateRecord.setStatus(respData.getStr("status"));
|
||||
separateRecord.setTotal_amt(separateRequest.getTotalAmt());
|
||||
separateRecord.setActual_separate_amt(Convert.toStr(canSeparateAmt));
|
||||
separateRecord.setTotal_fee_amt(Convert.toStr(lklSeparateDTOBak.getLklAmount()));
|
||||
separateRecord.setTotal_fee_amt(Convert.toStr(lklSeparateDTO.getLklAmount()));
|
||||
|
||||
if (lklOrderSeparateService.addOrUpdateByReceiverNo(separateRecord)) {
|
||||
log.info("[分账操作] 记录保存成功:订单={}, 分账单号={}, 状态={}, 分账流水号={}",
|
||||
@ -2394,30 +2465,39 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
* 参考文档:https://o.lakala.com/#/home/document/detail?id=393
|
||||
* </p>
|
||||
*
|
||||
* @param request HTTP请求对象,包含拉卡拉分账结果通知的参数
|
||||
* @return JSONObject 响应结果对象,包含处理结果状态
|
||||
* <ul>
|
||||
* <li>成功: {"code": "SUCCESS", "message": "操作成功"}</li>
|
||||
* <li>失败: {"code": "FAIL", "message": "错误信息"}</li>
|
||||
* </ul>
|
||||
* @param request
|
||||
* @param merchantNo 分账方商户号,非空表示是事后补偿
|
||||
* @param separateNo 分账指令流水号,非空表示是事后补偿
|
||||
* <ul>
|
||||
* <li>成功: {"code": "SUCCESS", "message": "操作成功"}</li>
|
||||
* <li>失败: {"code": "FAIL", "message": "错误信息"}</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Override
|
||||
public JSONObject sacsSeparateNotify(HttpServletRequest request) {
|
||||
log.info("[拉卡拉分账通知] 开始处理拉卡拉分账结果通知异步回调");
|
||||
|
||||
public JSONObject sacsSeparateNotify(HttpServletRequest request, String merchantNo, String separateNo) {
|
||||
try {
|
||||
// 1. 验签处理 - 验证通知来源的合法性
|
||||
Pair<Boolean, String> signCheckResult = LakalaUtil.chkLklApiNotifySign(request, lklNotifyCerPath, false);
|
||||
if (!signCheckResult.getFirst()) {
|
||||
String errorMsg = "分账通知验签失败: " + signCheckResult.getSecond();
|
||||
log.warn("[拉卡拉分账通知] {}", errorMsg);
|
||||
return JSONUtil.createObj()
|
||||
.set("code", "FAIL")
|
||||
.set("message", signCheckResult.getSecond());
|
||||
JSONObject paramsJson = null;
|
||||
if (!StrUtil.hasBlank(merchantNo, separateNo)) {
|
||||
log.info("[拉卡拉分账通知] 开始处理拉卡拉分账结果查询补偿");
|
||||
paramsJson = sacsQuery(merchantNo, separateNo);
|
||||
} else {
|
||||
log.info("[拉卡拉分账通知] 开始处理拉卡拉分账结果通知异步回调");
|
||||
|
||||
// 1. 验签处理 - 验证通知来源的合法性
|
||||
Pair<Boolean, String> signCheckResult = LakalaUtil.chkLklApiNotifySign(request, lklNotifyCerPath, false);
|
||||
if (!signCheckResult.getFirst()) {
|
||||
String errorMsg = "分账通知验签失败: " + signCheckResult.getSecond();
|
||||
log.warn("[拉卡拉分账通知] {}", errorMsg);
|
||||
return JSONUtil.createObj()
|
||||
.set("code", "FAIL")
|
||||
.set("message", signCheckResult.getSecond());
|
||||
}
|
||||
|
||||
// 2. 解析请求参数 - 将验签后的参数转换为JSON对象
|
||||
paramsJson = JSONUtil.parseObj(signCheckResult.getSecond());
|
||||
}
|
||||
|
||||
// 2. 解析请求参数 - 将验签后的参数转换为JSON对象
|
||||
JSONObject paramsJson = JSONUtil.parseObj(signCheckResult.getSecond());
|
||||
|
||||
if (paramsJson == null) {
|
||||
String errorMsg = "分账通知参数解析失败: 请求参数为空";
|
||||
log.error("[拉卡拉分账通知] {}", errorMsg);
|
||||
@ -2428,7 +2508,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
|
||||
// 3. 提取关键参数并校验 - 确保必要参数完整
|
||||
String logNo = paramsJson.getStr("log_no"); // 合单订单是子单(确认收货)流水号,非合单时是主单(确认收货)流水号
|
||||
String separateNo = paramsJson.getStr("separate_no");
|
||||
String separateNoNew = paramsJson.getStr("separate_no");
|
||||
String outSeparateNo = paramsJson.getStr("out_separate_no");
|
||||
String status = paramsJson.getStr("status");
|
||||
String finalStatus = paramsJson.getStr("final_status");
|
||||
@ -2436,7 +2516,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
// 必要参数
|
||||
List<String> missingParams = new ArrayList<>();
|
||||
if (StrUtil.isBlank(outSeparateNo)) missingParams.add("outSeparateNo");
|
||||
if (StrUtil.isBlank(separateNo)) missingParams.add("separateNo");
|
||||
if (StrUtil.isBlank(separateNoNew)) missingParams.add("separateNo");
|
||||
if (StrUtil.isBlank(status)) missingParams.add("status");
|
||||
|
||||
if (!missingParams.isEmpty()) {
|
||||
@ -2460,7 +2540,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
|
||||
// 5. 检查分账记录状态,避免重复处理
|
||||
String existingFinalStatus = lklOrderSeparateExist.getFinal_status();
|
||||
if ("SUCCESS".equals(existingFinalStatus)) {
|
||||
if ("SUCCESS".equals(existingFinalStatus) && "SUCCESS".equals(lklOrderSeparateExist.getStatus())) {
|
||||
String warnMsg = "分账已处理成功,请不要重复通知";
|
||||
log.warn("[拉卡拉分账通知] {},订单号={},外部分账单号={},参数详情: {}",
|
||||
warnMsg, logNo, outSeparateNo, paramsJson);
|
||||
@ -2489,7 +2569,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
lklOrderSeparate.setTotal_fee_amt(paramsJson.getStr("total_fee_amt", "0"));
|
||||
lklOrderSeparate.setRemark("分账已完成");
|
||||
lklOrderSeparate.setFinish_date(paramsJson.getStr("finish_date"));
|
||||
lklOrderSeparate.setNotify_resp(signCheckResult.getSecond());
|
||||
lklOrderSeparate.setNotify_resp(paramsJson.toString());
|
||||
|
||||
// 处理detail_datas(避免空指针)
|
||||
JSONArray detailDatas = paramsJson.getJSONArray("detail_datas");
|
||||
|
||||
@ -18,6 +18,8 @@ import com.suisung.mall.shop.lakala.service.LklOrderSeparateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@ -150,4 +152,51 @@ public class LklOrderSeparateServiceImpl extends BaseServiceImpl<LklOrderSeparat
|
||||
lklOrderSeparate.setRemark(remark);
|
||||
return updateById(lklOrderSeparate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询未成功分账的记录
|
||||
*
|
||||
* @param beginDate 开始时间(必须)
|
||||
* @param endDate 结束时间(可选,为空时默认为当前时间)
|
||||
* @return 未成功分账的记录列表,参数无效时返回空列表而非null
|
||||
*/
|
||||
@Override
|
||||
public List<LklOrderSeparate> unSuccessSeparateList(Date beginDate, Date endDate) {
|
||||
// 1. 参数校验
|
||||
if (beginDate == null) {
|
||||
log.warn("[查询未成功分账记录] 开始时间不能为空");
|
||||
return Collections.emptyList(); // 返回空列表而非null,避免NPE
|
||||
}
|
||||
|
||||
// 2. 处理结束时间默认值
|
||||
Date actualEndDate = (endDate != null) ? endDate : new Date();
|
||||
|
||||
// 3. 参数合理性校验
|
||||
if (beginDate.after(actualEndDate)) {
|
||||
log.warn("[查询未成功分账记录] 开始时间{}不能晚于结束时间{}", beginDate, actualEndDate);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
try {
|
||||
// 4. 构造查询条件
|
||||
QueryWrapper<LklOrderSeparate> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper
|
||||
.ne("status", "SUCCESS")
|
||||
.ne("final_status", "SUCCESS")
|
||||
.ge("created_at", beginDate)
|
||||
.le("created_at", actualEndDate)
|
||||
.orderByDesc("id");
|
||||
|
||||
// 5. 执行查询
|
||||
List<LklOrderSeparate> result = list(queryWrapper);
|
||||
|
||||
log.info("[查询未成功分账记录] 查询完成,开始时间={},结束时间={},结果数量={}",
|
||||
beginDate, actualEndDate, (result != null ? result.size() : 0));
|
||||
|
||||
return result != null ? result : Collections.emptyList();
|
||||
} catch (Exception e) {
|
||||
log.error("[查询未成功分账记录] 查询过程中发生异常,开始时间={},结束时间={}", beginDate, actualEndDate, e);
|
||||
return Collections.emptyList(); // 发生异常时返回空列表而非null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1490,7 +1490,6 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
// return_state_id 是当前状态(旧状态)
|
||||
if (ObjectUtil.equal(return_state_id, StateCode.RETURN_PROCESS_CHECK)) {
|
||||
// 同意退款退货,判断是否全部都退款退货,修改订单状态
|
||||
// todo 判断是否全部退货
|
||||
|
||||
UserDto user = getCurrentUser();
|
||||
|
||||
@ -1553,6 +1552,10 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
throw new ApiException(I18nUtil._("订单信息不存在!"));
|
||||
}
|
||||
|
||||
// 取消订单,更改订单的状态为已取消
|
||||
shopOrderBaseService.cancel(order_id, info_row, false);
|
||||
logger.info("订单已取消:{}", order_id);
|
||||
|
||||
// 当前订单状态
|
||||
Integer order_state_id = info_row.getOrder_state_id();
|
||||
|
||||
@ -1563,8 +1566,8 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
StateCode.ORDER_STATE_FINISH);
|
||||
if (order_state_id != null && !forbiddenStates.contains(order_state_id)) {
|
||||
// 取消订单,更改订单的状态为已取消
|
||||
shopOrderBaseService.cancel(order_id, info_row, false);
|
||||
logger.info("全部退款完成,订单已取消:{}", order_id);
|
||||
// shopOrderBaseService.cancel(order_id, info_row, false);
|
||||
logger.info("处理运费和打包费事宜:{}", order_id);
|
||||
|
||||
// 未发货,退运费 - 判断运费是否存在
|
||||
ShopOrderData order_data_row = shopOrderDataService.get(order_id);
|
||||
|
||||
@ -147,34 +147,34 @@ sf-express:
|
||||
#拉卡拉进件配置
|
||||
lakala:
|
||||
#服务地址
|
||||
server_url: https://test.wsmsd.cn/sit
|
||||
server_url: https://s2.lakala.com
|
||||
#应用Id
|
||||
app_id: OP00000003
|
||||
app_id: OP10000439
|
||||
#商户证书序列号
|
||||
serial_no: 00dfba8194c41b84cf
|
||||
serial_no: 1737359895636
|
||||
#商户证书
|
||||
api_cert_path: payKey/lakala/dev/OP00000003_cert.cer
|
||||
api_cert_path: payKey/lakala/prod/api_cert.cer
|
||||
#商户私钥
|
||||
api_pri_key_path: payKey/lakala/dev/OP00000003_private_key.pem
|
||||
api_pri_key_path: payKey/lakala/prod/api_private_key.pem
|
||||
#拉卡拉平台证书
|
||||
lkl_platform_cer_path: payKey/lakala/dev/lkl_notify_cert_v2.cer
|
||||
lkl_platform_cer_path: payKey/lakala/prod/lkl_platform.cer
|
||||
#机构代码
|
||||
org_code: 1951582
|
||||
is_prod: false
|
||||
# 拉卡拉拓客进件配置
|
||||
org_code: 980688
|
||||
is_prod: true
|
||||
tk:
|
||||
#服务地址
|
||||
server_url: https://test.wsmsd.cn
|
||||
client_id: lsycs
|
||||
client_secret: XPa1HB5d55Ig0qV8
|
||||
user_no: 29153396
|
||||
server_url: https://tkapi.lakala.com
|
||||
client_id: gpff
|
||||
client_secret: uRjvaJkWS1A0VsAv
|
||||
user_no: 22874827
|
||||
split_lowest_ratio: 94.00
|
||||
activity_id: 687
|
||||
wx_fee: 0.6 # 微信手续费 6/1000
|
||||
api_pub_key_path: payKey/lakala/dev/tk_api_public_key.txt
|
||||
api_pri_key_path: payKey/lakala/dev/tk_api_private_key.txt
|
||||
notify_pub_key_path: payKey/lakala/dev/tk_notify_public_key.txt
|
||||
notify_pri_key_path: payKey/lakala/dev/tk_notify_private_key.txt
|
||||
activity_id: 208
|
||||
wx_fee: 0.25 # 微信手续费 千分之2.5
|
||||
api_pub_key_path: payKey/lakala/prod/tk_api_public_key.txt
|
||||
api_pri_key_path: payKey/lakala/prod/tk_api_private_key.txt
|
||||
notify_pub_key_path: payKey/lakala/prod/tk_notify_public_key.txt
|
||||
notify_pri_key_path: payKey/lakala/prod/tk_notify_private_key.txt
|
||||
|
||||
#e签宝配置
|
||||
esign:
|
||||
server_url: https://smlopenapi.esign.cn
|
||||
|
||||
Loading…
Reference in New Issue
Block a user