diff --git a/mall-common/src/main/java/com/suisung/mall/common/pojo/dto/LklSeparateDTO.java b/mall-common/src/main/java/com/suisung/mall/common/pojo/dto/LklSeparateDTO.java index f9bf2a6f..46a00198 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/pojo/dto/LklSeparateDTO.java +++ b/mall-common/src/main/java/com/suisung/mall/common/pojo/dto/LklSeparateDTO.java @@ -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; } } -} +} \ No newline at end of file diff --git a/mall-common/src/main/java/com/suisung/mall/common/pojo/dto/LklSeparateDTOBak.java b/mall-common/src/main/java/com/suisung/mall/common/pojo/dto/LklSeparateDTOBak.java deleted file mode 100644 index 1038f51b..00000000 --- a/mall-common/src/main/java/com/suisung/mall/common/pojo/dto/LklSeparateDTOBak.java +++ /dev/null @@ -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; - -/** - * 拉卡拉订单分账信息对象 - *
- * 分账计算支持两种模式: - * 1. 基于可分账金额模式(默认):先扣除拉卡拉手续费和配送费,再对剩余金额进行分账 - * 2. 基于总金额模式:基于总分账金额进行分账计算 - *
- * 分账优先级顺序:拉卡拉 > 平台 > 一级代理商 > 二级代理商 > 商户
- * 商户作为最后分账方,其金额为剩余金额,不强制遵循分账比例
- */
-@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
- * 计算逻辑:
- * 1. 计算拉卡拉分账金额 = 总分账金额 × 拉卡拉分账比例(向上取整)
- * 2. 计算可分账金额 = 总分账金额 - 配送费 - 拉卡拉分账金额
- * 3. 如果refCanSeparateAmount有效且与计算出的canSeparateAmount不一致,则使用refCanSeparateAmount作为分账基数
- * 4. 调整分账比例,确保有效比例之和等于1.0
- * 5. 按优先级计算各参与方分账金额(商户 > 平台 > 一级代理商 > 二级代理商)
- * 6. 确保总额平衡并保障各参与方分账比例
- *
- * @return Pair
- * 计算逻辑:
- * 1. 计算拉卡拉分账金额 = 总分账金额 × 拉卡拉分账比例(四舍五入保留两位小数)
- * 2. 计算可分账金额 = 总分账金额 - 配送费 - 拉卡拉分账金额
- * 3. 如果refCanSeparateAmount有效且与计算出的canSeparateAmount不一致,则使用refCanSeparateAmount作为分账基数
- * 4. 调整分账比例,确保有效比例之和等于1.0
- * 5. 按优先级计算各参与方分账金额(平台 > 一级代理商 > 二级代理商 > 商户),基于可分账金额进行分账
- * 6. 确保总额平衡并保障各参与方分账比例
- *
- * @return Pair
+ * 用于查询已发起的分账交易的处理结果状态
+ * 参考: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
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LklOrderSeparateService.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LklOrderSeparateService.java
index 923802f0..567499b6 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LklOrderSeparateService.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LklOrderSeparateService.java
@@ -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
+ * 用于查询已发起的分账交易的处理结果状态
+ * 参考: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
- *
+ * @param request
+ * @param merchantNo 分账方商户号,非空表示是事后补偿
+ * @param separateNo 分账指令流水号,非空表示是事后补偿
+ *
+ *
*/
@Override
- public JSONObject sacsSeparateNotify(HttpServletRequest request) {
- log.info("[拉卡拉分账通知] 开始处理拉卡拉分账结果通知异步回调");
-
+ public JSONObject sacsSeparateNotify(HttpServletRequest request, String merchantNo, String separateNo) {
try {
- // 1. 验签处理 - 验证通知来源的合法性
- Pair