分账公共计算方法
This commit is contained in:
parent
4623650b18
commit
3e64c19f82
@ -98,4 +98,10 @@ public class CommonConstant {
|
|||||||
public static final String Sep_DeliveryFee_Prefix = "DF_";
|
public static final String Sep_DeliveryFee_Prefix = "DF_";
|
||||||
public static final String Sep_GoodsFee_Prefix = "ORD_";
|
public static final String Sep_GoodsFee_Prefix = "ORD_";
|
||||||
|
|
||||||
|
// 分账状态:1-已分账;2-未分账;3-分账已失败;
|
||||||
|
public static final Integer Sta_Separate_Success = 1;
|
||||||
|
public static final Integer Sta_Separate_Undone = 2;
|
||||||
|
public static final Integer Sta_Separate_Fail = 3;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,6 +90,8 @@ public class ShopOrderLkl implements Serializable {
|
|||||||
|
|
||||||
private Integer receive_status;
|
private Integer receive_status;
|
||||||
|
|
||||||
|
private Integer separate_status;
|
||||||
|
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
private Date created_at;
|
private Date created_at;
|
||||||
|
|||||||
@ -0,0 +1,579 @@
|
|||||||
|
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 java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拉卡拉订单分账信息对象
|
||||||
|
* <p>
|
||||||
|
* 分账计算逻辑说明:
|
||||||
|
* 前提条件:分账总金额必须大于0,配送费不能小于0;拉卡拉、商户、平台分账比例必须大于0,
|
||||||
|
* 一级、二级代理商分账比例可以为null或小于等于0
|
||||||
|
* <p>
|
||||||
|
* 分账计算步骤:
|
||||||
|
* 1. 计算拉卡拉分账金额 = 分账总金额 × 拉卡拉分账比例(结果向上取整)
|
||||||
|
* 2. 计算可分账金额 = 分账总金额 - 配送费 - 拉卡拉分账金额
|
||||||
|
* 3. 调整分账比例,确保商户、平台、一级代理商、二级代理商的有效比例之和等于1.0
|
||||||
|
* - 如果有二级代理商参与分账,则调整二级代理商比例
|
||||||
|
* - 否则如果有一级代理商参与分账,则调整一级代理商比例
|
||||||
|
* - 否则调整平台比例
|
||||||
|
* 4. 按优先级计算各参与方分账金额(结果四舍五入):
|
||||||
|
* - 商户分账金额 = 可分账金额 × 商户分账比例
|
||||||
|
* - 平台分账金额 = 可分账金额 × 平台分账比例
|
||||||
|
* - 一级代理商分账金额 = 可分账金额 × 一级代理商分账比例(如果参与分账)
|
||||||
|
* - 二级代理商分账金额 = 可分账金额 × 二级代理商分账比例(如果参与分账)
|
||||||
|
* 5. 如分配总额与可分账金额不符,则调整最后一个分账方(按优先级顺序)以确保总额平衡:
|
||||||
|
* - 优先调整二级代理商(如果参与分账)
|
||||||
|
* - 否则调整一级代理商(如果参与分账)
|
||||||
|
* - 否则调整平台
|
||||||
|
* - 最后调整商户
|
||||||
|
* 6. 保障各参与方分账比例不能低于指定属性的比例(按优先级处理):
|
||||||
|
* - 商户优先级最高
|
||||||
|
* - 平台优先级次之
|
||||||
|
* - 一级代理商优先级再次之
|
||||||
|
* - 二级代理商优先级最低
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@ApiModel(value = "拉卡拉订单分账信息对象", description = "拉卡拉订单分账信息对象")
|
||||||
|
public class LklSeparateDTO implements java.io.Serializable {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(LklSeparateDTO.class);
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "分账总金额(分)")
|
||||||
|
private Integer totalSeparateAmount;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "可分账金额(分)")
|
||||||
|
private Integer canSeparateAmount;
|
||||||
|
|
||||||
|
@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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试方法
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) {
|
||||||
|
logger.info("开始测试分账计算功能...");
|
||||||
|
|
||||||
|
// 临界点测试用例1: 极小金额测试
|
||||||
|
logger.info("\n\n临界点测试用例1 - 极小金额测试:");
|
||||||
|
LklSeparateDTO dto1 = new LklSeparateDTO();
|
||||||
|
dto1.setTotalSeparateAmount(3);
|
||||||
|
dto1.setShippingFee(0);
|
||||||
|
dto1.setLklRatio(new BigDecimal("0.0025"));
|
||||||
|
dto1.setMchRatio(new BigDecimal("0.94"));
|
||||||
|
dto1.setPlatRatio(new BigDecimal("0.06"));
|
||||||
|
|
||||||
|
logger.info("测试参数: 总分账金额={}分, 配送费={}分, 拉卡拉比例={}, 商户比例={}, 平台比例={}",
|
||||||
|
dto1.getTotalSeparateAmount(), dto1.getShippingFee(), dto1.getLklRatio(),
|
||||||
|
dto1.getMchRatio(), dto1.getPlatRatio());
|
||||||
|
|
||||||
|
boolean result1 = dto1.calculateProfitSharing();
|
||||||
|
logger.info("分账计算结果: {}", (result1 ? "成功" : "失败"));
|
||||||
|
if (result1) {
|
||||||
|
logger.info("分账结果: 总金额={}分, 拉卡拉={}分, 配送费={}分, 可分账={}分, 商户={}分, 平台={}分, 一级代理商={}分, 二级代理商={}分",
|
||||||
|
dto1.getTotalSeparateAmount(), dto1.getLklAmount(), dto1.getShippingFee(), dto1.getCanSeparateAmount(),
|
||||||
|
dto1.getMchAmount(), dto1.getPlatAmount(), dto1.getAgent1stAmount(), dto1.getAgent2ndAmount());
|
||||||
|
|
||||||
|
double lklRatioOfTotal = (double) dto1.getLklAmount() / dto1.getTotalSeparateAmount() * 100;
|
||||||
|
double mchRatioOfTotal = (double) dto1.getMchAmount() / dto1.getTotalSeparateAmount() * 100;
|
||||||
|
double platRatioOfTotal = (double) dto1.getPlatAmount() / dto1.getTotalSeparateAmount() * 100;
|
||||||
|
double agent1stRatioOfTotal = (double) dto1.getAgent1stAmount() / dto1.getTotalSeparateAmount() * 100;
|
||||||
|
double agent2ndRatioOfTotal = (double) dto1.getAgent2ndAmount() / dto1.getTotalSeparateAmount() * 100;
|
||||||
|
|
||||||
|
double lklRatioOfAvailable = (double) dto1.getLklAmount() / dto1.getCanSeparateAmount() * 100;
|
||||||
|
double mchRatioOfAvailable = (double) dto1.getMchAmount() / dto1.getCanSeparateAmount() * 100;
|
||||||
|
double platRatioOfAvailable = (double) dto1.getPlatAmount() / dto1.getCanSeparateAmount() * 100;
|
||||||
|
double agent1stRatioOfAvailable = (double) dto1.getAgent1stAmount() / dto1.getCanSeparateAmount() * 100;
|
||||||
|
double agent2ndRatioOfAvailable = (double) dto1.getAgent2ndAmount() / dto1.getCanSeparateAmount() * 100;
|
||||||
|
|
||||||
|
logger.info("占比详情 (总金额占比 / 可分账金额占比): 拉卡拉={}% / {}%, 商户={}% / {}%, 平台={}% / {}%, 一级代理商={}% / {}%, 二级代理商={}% / {}%",
|
||||||
|
String.format("%.4f", lklRatioOfTotal), String.format("%.4f", lklRatioOfAvailable),
|
||||||
|
String.format("%.4f", mchRatioOfTotal), String.format("%.4f", mchRatioOfAvailable),
|
||||||
|
String.format("%.4f", platRatioOfTotal), String.format("%.4f", platRatioOfAvailable),
|
||||||
|
String.format("%.4f", agent1stRatioOfTotal), String.format("%.4f", agent1stRatioOfAvailable),
|
||||||
|
String.format("%.4f", agent2ndRatioOfTotal), String.format("%.4f", agent2ndRatioOfAvailable));
|
||||||
|
|
||||||
|
int total = dto1.getLklAmount() + dto1.getMchAmount() + dto1.getPlatAmount() + dto1.getAgent1stAmount() + dto1.getAgent2ndAmount() + dto1.getShippingFee();
|
||||||
|
logger.info("金额校验: {} (计算总金额={}分, 原始总金额={}分)", (total == dto1.getTotalSeparateAmount() ? "通过" : "不通过"), total, dto1.getTotalSeparateAmount());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 临界点测试用例2: 小金额测试
|
||||||
|
logger.info("\n\n临界点测试用例2 - 小金额测试:");
|
||||||
|
LklSeparateDTO dto2 = new LklSeparateDTO();
|
||||||
|
dto2.setTotalSeparateAmount(800);
|
||||||
|
dto2.setShippingFee(500);
|
||||||
|
dto2.setLklRatio(new BigDecimal("0.0025"));
|
||||||
|
dto2.setMchRatio(new BigDecimal("0.94"));
|
||||||
|
dto2.setPlatRatio(new BigDecimal("0.06"));
|
||||||
|
|
||||||
|
logger.info("测试参数: 总分账金额={}分, 配送费={}分, 拉卡拉比例={}, 商户比例={}, 平台比例={}",
|
||||||
|
dto2.getTotalSeparateAmount(), dto2.getShippingFee(), dto2.getLklRatio(),
|
||||||
|
dto2.getMchRatio(), dto2.getPlatRatio());
|
||||||
|
|
||||||
|
boolean result2 = dto2.calculateProfitSharing();
|
||||||
|
logger.info("分账计算结果: {}", (result2 ? "成功" : "失败"));
|
||||||
|
if (result2) {
|
||||||
|
logger.info("分账结果: 总金额={}分, 拉卡拉={}分, 配送费={}分, 可分账={}分, 商户={}分, 平台={}分, 一级代理商={}分, 二级代理商={}分",
|
||||||
|
dto2.getTotalSeparateAmount(), dto2.getLklAmount(), dto2.getShippingFee(), dto2.getCanSeparateAmount(),
|
||||||
|
dto2.getMchAmount(), dto2.getPlatAmount(), dto2.getAgent1stAmount(), dto2.getAgent2ndAmount());
|
||||||
|
|
||||||
|
double lklRatioOfTotal = (double) dto2.getLklAmount() / dto2.getTotalSeparateAmount() * 100;
|
||||||
|
double mchRatioOfTotal = (double) dto2.getMchAmount() / dto2.getTotalSeparateAmount() * 100;
|
||||||
|
double platRatioOfTotal = (double) dto2.getPlatAmount() / dto2.getTotalSeparateAmount() * 100;
|
||||||
|
double agent1stRatioOfTotal = (double) dto2.getAgent1stAmount() / dto2.getTotalSeparateAmount() * 100;
|
||||||
|
double agent2ndRatioOfTotal = (double) dto2.getAgent2ndAmount() / dto2.getTotalSeparateAmount() * 100;
|
||||||
|
|
||||||
|
double lklRatioOfAvailable = (double) dto2.getLklAmount() / dto2.getCanSeparateAmount() * 100;
|
||||||
|
double mchRatioOfAvailable = (double) dto2.getMchAmount() / dto2.getCanSeparateAmount() * 100;
|
||||||
|
double platRatioOfAvailable = (double) dto2.getPlatAmount() / dto2.getCanSeparateAmount() * 100;
|
||||||
|
double agent1stRatioOfAvailable = (double) dto2.getAgent1stAmount() / dto2.getCanSeparateAmount() * 100;
|
||||||
|
double agent2ndRatioOfAvailable = (double) dto2.getAgent2ndAmount() / dto2.getCanSeparateAmount() * 100;
|
||||||
|
|
||||||
|
logger.info("占比详情 (总金额占比 / 可分账金额占比): 拉卡拉={}% / {}%, 商户={}% / {}%, 平台={}% / {}%, 一级代理商={}% / {}%, 二级代理商={}% / {}%",
|
||||||
|
String.format("%.4f", lklRatioOfTotal), String.format("%.4f", lklRatioOfAvailable),
|
||||||
|
String.format("%.4f", mchRatioOfTotal), String.format("%.4f", mchRatioOfAvailable),
|
||||||
|
String.format("%.4f", platRatioOfTotal), String.format("%.4f", platRatioOfAvailable),
|
||||||
|
String.format("%.4f", agent1stRatioOfTotal), String.format("%.4f", agent1stRatioOfAvailable),
|
||||||
|
String.format("%.4f", agent2ndRatioOfTotal), String.format("%.4f", agent2ndRatioOfAvailable));
|
||||||
|
|
||||||
|
int total = dto2.getLklAmount() + dto2.getMchAmount() + dto2.getPlatAmount() + dto2.getAgent1stAmount() + dto2.getAgent2ndAmount() + dto2.getShippingFee();
|
||||||
|
logger.info("金额校验: {} (计算总金额={}分, 原始总金额={}分)", (total == dto2.getTotalSeparateAmount() ? "通过" : "不通过"), total, dto2.getTotalSeparateAmount());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 临界点测试用例3: 中等金额测试
|
||||||
|
logger.info("\n\n临界点测试用例3 - 中等金额测试:");
|
||||||
|
LklSeparateDTO dto3 = new LklSeparateDTO();
|
||||||
|
dto3.setTotalSeparateAmount(100);
|
||||||
|
dto3.setShippingFee(30);
|
||||||
|
dto3.setLklRatio(new BigDecimal("0.0025"));
|
||||||
|
dto3.setMchRatio(new BigDecimal("0.94"));
|
||||||
|
dto3.setPlatRatio(new BigDecimal("0.06"));
|
||||||
|
|
||||||
|
logger.info("测试参数: 总分账金额={}分, 配送费={}分, 拉卡拉比例={}, 商户比例={}, 平台比例={}",
|
||||||
|
dto3.getTotalSeparateAmount(), dto3.getShippingFee(), dto3.getLklRatio(),
|
||||||
|
dto3.getMchRatio(), dto3.getPlatRatio());
|
||||||
|
|
||||||
|
boolean result3 = dto3.calculateProfitSharing();
|
||||||
|
logger.info("分账计算结果: {}", (result3 ? "成功" : "失败"));
|
||||||
|
if (result3) {
|
||||||
|
logger.info("分账结果: 总金额={}分, 拉卡拉={}分, 配送费={}分, 可分账={}分, 商户={}分, 平台={}分, 一级代理商={}分, 二级代理商={}分",
|
||||||
|
dto3.getTotalSeparateAmount(), dto3.getLklAmount(), dto3.getShippingFee(), dto3.getCanSeparateAmount(),
|
||||||
|
dto3.getMchAmount(), dto3.getPlatAmount(), dto3.getAgent1stAmount(), dto3.getAgent2ndAmount());
|
||||||
|
|
||||||
|
double lklRatioOfTotal = (double) dto3.getLklAmount() / dto3.getTotalSeparateAmount() * 100;
|
||||||
|
double mchRatioOfTotal = (double) dto3.getMchAmount() / dto3.getTotalSeparateAmount() * 100;
|
||||||
|
double platRatioOfTotal = (double) dto3.getPlatAmount() / dto3.getTotalSeparateAmount() * 100;
|
||||||
|
double agent1stRatioOfTotal = (double) dto3.getAgent1stAmount() / dto3.getTotalSeparateAmount() * 100;
|
||||||
|
double agent2ndRatioOfTotal = (double) dto3.getAgent2ndAmount() / dto3.getTotalSeparateAmount() * 100;
|
||||||
|
|
||||||
|
double lklRatioOfAvailable = (double) dto3.getLklAmount() / dto3.getCanSeparateAmount() * 100;
|
||||||
|
double mchRatioOfAvailable = (double) dto3.getMchAmount() / dto3.getCanSeparateAmount() * 100;
|
||||||
|
double platRatioOfAvailable = (double) dto3.getPlatAmount() / dto3.getCanSeparateAmount() * 100;
|
||||||
|
double agent1stRatioOfAvailable = (double) dto3.getAgent1stAmount() / dto3.getCanSeparateAmount() * 100;
|
||||||
|
double agent2ndRatioOfAvailable = (double) dto3.getAgent2ndAmount() / dto3.getCanSeparateAmount() * 100;
|
||||||
|
|
||||||
|
logger.info("占比详情 (总金额占比 / 可分账金额占比): 拉卡拉={}% / {}%, 商户={}% / {}%, 平台={}% / {}%, 一级代理商={}% / {}%, 二级代理商={}% / {}%",
|
||||||
|
String.format("%.4f", lklRatioOfTotal), String.format("%.4f", lklRatioOfAvailable),
|
||||||
|
String.format("%.4f", mchRatioOfTotal), String.format("%.4f", mchRatioOfAvailable),
|
||||||
|
String.format("%.4f", platRatioOfTotal), String.format("%.4f", platRatioOfAvailable),
|
||||||
|
String.format("%.4f", agent1stRatioOfTotal), String.format("%.4f", agent1stRatioOfAvailable),
|
||||||
|
String.format("%.4f", agent2ndRatioOfTotal), String.format("%.4f", agent2ndRatioOfAvailable));
|
||||||
|
|
||||||
|
int total = dto3.getLklAmount() + dto3.getMchAmount() + dto3.getPlatAmount() + dto3.getAgent1stAmount() + dto3.getAgent2ndAmount() + dto3.getShippingFee();
|
||||||
|
logger.info("金额校验: {} (计算总金额={}分, 原始总金额={}分)", (total == dto3.getTotalSeparateAmount() ? "通过" : "不通过"), total, dto3.getTotalSeparateAmount());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 临界点测试用例4: 大金额测试
|
||||||
|
logger.info("\n\n临界点测试用例4 - 大金额测试:");
|
||||||
|
LklSeparateDTO dto4 = new LklSeparateDTO();
|
||||||
|
dto4.setTotalSeparateAmount(10000);
|
||||||
|
dto4.setShippingFee(500);
|
||||||
|
dto4.setLklRatio(new BigDecimal("0.0025"));
|
||||||
|
dto4.setMchRatio(new BigDecimal("0.94"));
|
||||||
|
dto4.setPlatRatio(new BigDecimal("0.06"));
|
||||||
|
|
||||||
|
logger.info("测试参数: 总分账金额={}分, 配送费={}分, 拉卡拉比例={}, 商户比例={}, 平台比例={}",
|
||||||
|
dto4.getTotalSeparateAmount(), dto4.getShippingFee(), dto4.getLklRatio(),
|
||||||
|
dto4.getMchRatio(), dto4.getPlatRatio());
|
||||||
|
|
||||||
|
boolean result4 = dto4.calculateProfitSharing();
|
||||||
|
logger.info("分账计算结果: {}", (result4 ? "成功" : "失败"));
|
||||||
|
if (result4) {
|
||||||
|
logger.info("分账结果: 总金额={}分, 拉卡拉={}分, 配送费={}分, 可分账={}分, 商户={}分, 平台={}分, 一级代理商={}分, 二级代理商={}分",
|
||||||
|
dto4.getTotalSeparateAmount(), dto4.getLklAmount(), dto4.getShippingFee(), dto4.getCanSeparateAmount(),
|
||||||
|
dto4.getMchAmount(), dto4.getPlatAmount(), dto4.getAgent1stAmount(), dto4.getAgent2ndAmount());
|
||||||
|
|
||||||
|
double lklRatioOfTotal = (double) dto4.getLklAmount() / dto4.getTotalSeparateAmount() * 100;
|
||||||
|
double mchRatioOfTotal = (double) dto4.getMchAmount() / dto4.getTotalSeparateAmount() * 100;
|
||||||
|
double platRatioOfTotal = (double) dto4.getPlatAmount() / dto4.getTotalSeparateAmount() * 100;
|
||||||
|
double agent1stRatioOfTotal = (double) dto4.getAgent1stAmount() / dto4.getTotalSeparateAmount() * 100;
|
||||||
|
double agent2ndRatioOfTotal = (double) dto4.getAgent2ndAmount() / dto4.getTotalSeparateAmount() * 100;
|
||||||
|
|
||||||
|
double lklRatioOfAvailable = (double) dto4.getLklAmount() / dto4.getCanSeparateAmount() * 100;
|
||||||
|
double mchRatioOfAvailable = (double) dto4.getMchAmount() / dto4.getCanSeparateAmount() * 100;
|
||||||
|
double platRatioOfAvailable = (double) dto4.getPlatAmount() / dto4.getCanSeparateAmount() * 100;
|
||||||
|
double agent1stRatioOfAvailable = (double) dto4.getAgent1stAmount() / dto4.getCanSeparateAmount() * 100;
|
||||||
|
double agent2ndRatioOfAvailable = (double) dto4.getAgent2ndAmount() / dto4.getCanSeparateAmount() * 100;
|
||||||
|
|
||||||
|
logger.info("占比详情 (总金额占比 / 可分账金额占比): 拉卡拉={}% / {}%, 商户={}% / {}%, 平台={}% / {}%, 一级代理商={}% / {}%, 二级代理商={}% / {}%",
|
||||||
|
String.format("%.4f", lklRatioOfTotal), String.format("%.4f", lklRatioOfAvailable),
|
||||||
|
String.format("%.4f", mchRatioOfTotal), String.format("%.4f", mchRatioOfAvailable),
|
||||||
|
String.format("%.4f", platRatioOfTotal), String.format("%.4f", platRatioOfAvailable),
|
||||||
|
String.format("%.4f", agent1stRatioOfTotal), String.format("%.4f", agent1stRatioOfAvailable),
|
||||||
|
String.format("%.4f", agent2ndRatioOfTotal), String.format("%.4f", agent2ndRatioOfAvailable));
|
||||||
|
|
||||||
|
int total = dto4.getLklAmount() + dto4.getMchAmount() + dto4.getPlatAmount() + dto4.getAgent1stAmount() + dto4.getAgent2ndAmount() + dto4.getShippingFee();
|
||||||
|
logger.info("金额校验: {} (计算总金额={}分, 原始总金额={}分)", (total == dto4.getTotalSeparateAmount() ? "通过" : "不通过"), total, dto4.getTotalSeparateAmount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据实体类的属性,扣除拉卡拉手续费,配送费之后,从可用余额中进行分账计算
|
||||||
|
*
|
||||||
|
* @return 分账结果是否成功
|
||||||
|
*/
|
||||||
|
public boolean calculateProfitSharing() {
|
||||||
|
// 检查前提条件
|
||||||
|
if (!validateInputs()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("开始分账计算,分账总金额={}分,配送费={}分", totalSeparateAmount, shippingFee);
|
||||||
|
|
||||||
|
// 1. 计算拉卡拉分账金额 = 分账总金额 × 拉卡拉分账比例(向上取整)
|
||||||
|
calculateLklAmount();
|
||||||
|
|
||||||
|
// 2. 计算可分账金额 = 分账总金额 - 配送费 - 拉卡拉分账金额
|
||||||
|
calculateCanSeparateAmount();
|
||||||
|
if (canSeparateAmount <= 0) {
|
||||||
|
logger.info("分账计算失败:可分账金额必须大于0,当前值={}", canSeparateAmount);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 调整分账比例,确保有效值比例相加等于1.0
|
||||||
|
adjustRatios();
|
||||||
|
|
||||||
|
// 4. 按优先级分账:商户 > 平台 > 一级代理商 > 二级代理商
|
||||||
|
performSeparate();
|
||||||
|
|
||||||
|
// 5. 确保总额平衡
|
||||||
|
balanceAmounts();
|
||||||
|
|
||||||
|
// 6. 保障各参与方分账比例不低于指定值
|
||||||
|
guaranteeRatios();
|
||||||
|
|
||||||
|
logger.info("分账计算完成:商户={},平台={},一级代理商={},二级代理商={}",
|
||||||
|
mchAmount, platAmount, agent1stAmount, agent2ndAmount);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证输入参数
|
||||||
|
*/
|
||||||
|
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 void calculateLklAmount() {
|
||||||
|
BigDecimal lklAmountDecimal = new BigDecimal(totalSeparateAmount).multiply(lklRatio);
|
||||||
|
lklAmount = lklAmountDecimal.setScale(0, RoundingMode.UP).intValue();
|
||||||
|
logger.debug("拉卡拉分账计算:分账总金额{} × 拉卡拉比例{} = {},向上取整后={}", totalSeparateAmount, lklRatio, lklAmountDecimal, lklAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算可分账金额
|
||||||
|
*/
|
||||||
|
private void calculateCanSeparateAmount() {
|
||||||
|
canSeparateAmount = totalSeparateAmount - shippingFee - lklAmount;
|
||||||
|
logger.debug("可分账金额计算:分账总金额{} - 配送费{} - 拉卡拉分账{} = {}", totalSeparateAmount, shippingFee, lklAmount, canSeparateAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调整分账比例,确保有效值比例相加等于1.0
|
||||||
|
*/
|
||||||
|
private void adjustRatios() {
|
||||||
|
// 计算有效的分账比例总和
|
||||||
|
BigDecimal effectiveRatioSum = BigDecimal.ZERO
|
||||||
|
.add(mchRatio)
|
||||||
|
.add(platRatio)
|
||||||
|
.add(getOrDefault(agent1stRatio, BigDecimal.ZERO))
|
||||||
|
.add(getOrDefault(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() {
|
||||||
|
// 商户分账金额 = 可分账金额 × 商户分账比例(四舍五入)
|
||||||
|
BigDecimal mchAmountDecimal = new BigDecimal(canSeparateAmount).multiply(mchRatio);
|
||||||
|
mchAmount = mchAmountDecimal.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||||
|
logger.debug("商户分账计算:可分账金额{} × 商户比例{} = {},四舍五入后={}", canSeparateAmount, mchRatio, mchAmountDecimal, mchAmount);
|
||||||
|
|
||||||
|
// 平台分账金额 = 可分账金额 × 平台分账比例(四舍五入)
|
||||||
|
BigDecimal platAmountDecimal = new BigDecimal(canSeparateAmount).multiply(platRatio);
|
||||||
|
platAmount = platAmountDecimal.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||||
|
logger.debug("平台分账计算:可分账金额{} × 平台比例{} = {},四舍五入后={}", canSeparateAmount, platRatio, platAmountDecimal, platAmount);
|
||||||
|
|
||||||
|
// 一级代理商分账金额 = 可分账金额 × 一级代理商分账比例(四舍五入)
|
||||||
|
if (agent1stRatio != null && agent1stRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
BigDecimal agent1stAmountDecimal = new BigDecimal(canSeparateAmount).multiply(agent1stRatio);
|
||||||
|
agent1stAmount = agent1stAmountDecimal.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||||
|
logger.debug("一级代理商分账计算:可分账金额{} × 一级代理商比例{} = {},四舍五入后={}", canSeparateAmount, agent1stRatio, agent1stAmountDecimal, agent1stAmount);
|
||||||
|
} else {
|
||||||
|
agent1stAmount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 二级代理商分账金额 = 可分账金额 × 二级代理商分账比例(四舍五入)
|
||||||
|
if (agent2ndRatio != null && agent2ndRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
BigDecimal agent2ndAmountDecimal = new BigDecimal(canSeparateAmount).multiply(agent2ndRatio);
|
||||||
|
agent2ndAmount = agent2ndAmountDecimal.setScale(0, RoundingMode.HALF_UP).intValue();
|
||||||
|
logger.debug("二级代理商分账计算:可分账金额{} × 二级代理商比例{} = {},四舍五入后={}", canSeparateAmount, agent2ndRatio, agent2ndAmountDecimal, agent2ndAmount);
|
||||||
|
} else {
|
||||||
|
agent2ndAmount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确保总额平衡
|
||||||
|
*/
|
||||||
|
private void balanceAmounts() {
|
||||||
|
int totalAmount = mchAmount + platAmount + agent1stAmount + agent2ndAmount;
|
||||||
|
if (totalAmount != canSeparateAmount) {
|
||||||
|
int diff = canSeparateAmount - totalAmount;
|
||||||
|
logger.debug("分账总额与可分账金额不符,差额={},开始调整", diff);
|
||||||
|
|
||||||
|
// 将差额分配给优先级最低的参与方,确保总额平衡
|
||||||
|
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);
|
||||||
|
} else {
|
||||||
|
mchAmount += diff;
|
||||||
|
logger.debug("调整商户分账金额:{} + {} = {}", mchAmount - diff, diff, mchAmount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保障各参与方分账比例不低于指定值
|
||||||
|
*/
|
||||||
|
private void guaranteeRatios() {
|
||||||
|
// 商户优先级最高
|
||||||
|
guaranteeMerchantRatio();
|
||||||
|
|
||||||
|
// 平台优先级次之
|
||||||
|
guaranteePlatformRatio();
|
||||||
|
|
||||||
|
// 一级代理商优先级再次之
|
||||||
|
guaranteeAgent1stRatio();
|
||||||
|
|
||||||
|
// 最终验证和调整,确保所有参与方分账比例不低于指定值
|
||||||
|
finalGuaranteeMerchantRatio();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保障商户分账比例
|
||||||
|
*/
|
||||||
|
private void guaranteeMerchantRatio() {
|
||||||
|
BigDecimal actualMchRatio = new BigDecimal(mchAmount).divide(new BigDecimal(canSeparateAmount), 6, RoundingMode.HALF_UP);
|
||||||
|
if (actualMchRatio.compareTo(mchRatio) < 0) {
|
||||||
|
int requiredMchAmount = mchRatio.multiply(new BigDecimal(canSeparateAmount)).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() {
|
||||||
|
BigDecimal actualPlatRatio = new BigDecimal(platAmount).divide(new BigDecimal(canSeparateAmount), 6, RoundingMode.HALF_UP);
|
||||||
|
if (actualPlatRatio.compareTo(platRatio) < 0) {
|
||||||
|
int requiredPlatAmount = platRatio.multiply(new BigDecimal(canSeparateAmount)).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() {
|
||||||
|
if (agent1stRatio != null && agent1stRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
BigDecimal actualAgent1stRatio = new BigDecimal(agent1stAmount).divide(new BigDecimal(canSeparateAmount), 6, RoundingMode.HALF_UP);
|
||||||
|
if (actualAgent1stRatio.compareTo(agent1stRatio) < 0) {
|
||||||
|
int requiredAgent1stAmount = agent1stRatio.multiply(new BigDecimal(canSeparateAmount)).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() {
|
||||||
|
BigDecimal finalMchRatio = new BigDecimal(mchAmount).divide(new BigDecimal(canSeparateAmount), 6, RoundingMode.HALF_UP);
|
||||||
|
if (finalMchRatio.compareTo(mchRatio) < 0) {
|
||||||
|
int requiredMchAmount = mchRatio.multiply(new BigDecimal(canSeparateAmount)).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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取BigDecimal值,如果为null则返回默认值
|
||||||
|
*/
|
||||||
|
private BigDecimal getOrDefault(BigDecimal value, BigDecimal defaultValue) {
|
||||||
|
return value != null ? value : defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,6 +10,7 @@ package com.suisung.mall.shop.lakala.service.impl;
|
|||||||
|
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import cn.hutool.core.convert.Convert;
|
||||||
import cn.hutool.core.util.NumberUtil;
|
import cn.hutool.core.util.NumberUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
@ -555,8 +556,13 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
shopMchEntryService.updateMerchEntryEcResultUrlByMchId(mchId, ecResultUrl);
|
shopMchEntryService.updateMerchEntryEcResultUrlByMchId(mchId, ecResultUrl);
|
||||||
|
|
||||||
// 发短信给商家,及时签署合同 SMS_488465246
|
// 发短信给商家,及时签署合同 SMS_488465246
|
||||||
// 【小发同城商家】恭喜您的开店入驻申请已审核通过!请尽快登录小发同城商家版APP平台签署电子合同,签署链接24小时内有效(逾期需重新提交申请)。如有疑问请联系客服,感谢您的支持!
|
//
|
||||||
shopMessageTemplateService.aliyunSmsSend(contractMobile, "SMS_493160417", null);//SMS_479760276
|
//恭喜您的开店入驻申请已审核通过!请尽快登录小发商家版APP平台签署电子合同,签署链接24小时内有效(逾期需重新提交申请)。如有疑问请联系客服,感谢您的支持!
|
||||||
|
// shopMessageTemplateService.aliyunSmsSend(contractMobile, "SMS_493160417", null);//SMS_479760276
|
||||||
|
|
||||||
|
// 恭喜!您的开店入驻申请已审核通过,点击链接 https://mall.gpxscs.cn/api/mobile/shop/lakala/sign/ec/${code}
|
||||||
|
// 或前往小发商家版APP完成电子合同签署,链接24小时内有效(逾期需重新提交申请)。如有疑问可联系客服,感谢您的支持!
|
||||||
|
shopMessageTemplateService.aliyunSmsSend(contractMobile, "SMS_494860064", null);
|
||||||
|
|
||||||
JSONObject payload = new JSONObject();
|
JSONObject payload = new JSONObject();
|
||||||
payload.put("category", CommonConstant.PUSH_MSG_CATE_EC);
|
payload.put("category", CommonConstant.PUSH_MSG_CATE_EC);
|
||||||
@ -1737,42 +1743,56 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
@Override
|
@Override
|
||||||
public Pair<String, String> queryMchCanSplitAmt(String merchantNo, String logNo, String logDate) {
|
public Pair<String, String> queryMchCanSplitAmt(String merchantNo, String logNo, String logDate) {
|
||||||
if (StringUtils.isAnyBlank(merchantNo, logNo, logDate)) {
|
if (StringUtils.isAnyBlank(merchantNo, logNo, logDate)) {
|
||||||
|
log.warn("[查询可分账金额] 参数校验失败:缺少必要参数, merchantNo={}, logNo={}, logDate={}", merchantNo, logNo, logDate);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. 配置初始化
|
|
||||||
initLKLSDK();
|
|
||||||
|
|
||||||
//2. 装配数据
|
|
||||||
V3SacsQueryAmtRequest req = new V3SacsQueryAmtRequest();
|
|
||||||
req.setMerchantNo(merchantNo);
|
|
||||||
req.setLogNo(logNo);
|
|
||||||
req.setLogDate(logDate);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
log.info("[查询可分账金额] 开始查询商户可分账金额, merchantNo={}, logNo={}, logDate={}", merchantNo, logNo, logDate);
|
||||||
|
|
||||||
|
// 1. 配置初始化
|
||||||
|
initLKLSDK();
|
||||||
|
|
||||||
|
//2. 装配数据
|
||||||
|
V3SacsQueryAmtRequest req = new V3SacsQueryAmtRequest();
|
||||||
|
req.setMerchantNo(merchantNo);
|
||||||
|
req.setLogNo(logNo);
|
||||||
|
req.setLogDate(logDate);
|
||||||
|
|
||||||
//3. 发送请求
|
//3. 发送请求
|
||||||
String responseStr = LKLSDK.httpPost(req);
|
String responseStr = LKLSDK.httpPost(req);
|
||||||
if (StrUtil.isBlank(responseStr)) {
|
if (StrUtil.isBlank(responseStr)) {
|
||||||
log.error(I18nUtil._("服务器无返回值!"));
|
log.error("[查询可分账金额] 服务器无返回值, merchantNo={}, logNo={}, logDate={}", merchantNo, logNo, logDate);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject lklRespJSON = JSONUtil.parseObj(responseStr);
|
JSONObject lklRespJSON = JSONUtil.parseObj(responseStr);
|
||||||
if (lklRespJSON == null || !lklSacsSuccessCode.equals(lklRespJSON.getStr("code")) || lklRespJSON.get("resp_data") == null) {
|
if (lklRespJSON == null || !lklSacsSuccessCode.equals(lklRespJSON.getStr("code")) || lklRespJSON.get("resp_data") == null) {
|
||||||
log.error(I18nUtil._("返回值有误!"));
|
log.error("[查询可分账金额] 返回值有误, merchantNo={}, logNo={}, logDate={}, response={}",
|
||||||
|
merchantNo, logNo, logDate, responseStr);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject respData = (JSONObject) lklRespJSON.get("resp_data");
|
JSONObject respData = (JSONObject) lklRespJSON.get("resp_data");
|
||||||
if (respData == null
|
if (respData == null
|
||||||
|| StringUtils.isAnyBlank(respData.getStr("total_separate_amt"), respData.getStr("can_separate_amt"))) {
|
|| StringUtils.isAnyBlank(respData.getStr("total_separate_amt"), respData.getStr("can_separate_amt"))) {
|
||||||
log.error(I18nUtil._("返回值有误!"));
|
log.error("[查询可分账金额] 返回数据字段缺失, merchantNo={}, logNo={}, logDate={}, respData={}",
|
||||||
|
merchantNo, logNo, logDate, respData);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Pair.of(respData.getStr("total_separate_amt"), respData.getStr("can_separate_amt"));
|
String totalSeparateAmt = respData.getStr("total_separate_amt");
|
||||||
|
String canSeparateAmt = respData.getStr("can_separate_amt");
|
||||||
|
|
||||||
|
log.info("[查询可分账金额] 查询成功, merchantNo={}, logNo={}, logDate={}, totalSeparateAmt={}, canSeparateAmt={}",
|
||||||
|
merchantNo, logNo, logDate, totalSeparateAmt, canSeparateAmt);
|
||||||
|
|
||||||
|
return Pair.of(totalSeparateAmt, canSeparateAmt);
|
||||||
} catch (SDKException e) {
|
} catch (SDKException e) {
|
||||||
log.error("账户余额查询失败:", e);
|
log.error("[查询可分账金额] 账户余额查询失败, merchantNo={}, logNo={}, logDate={}", merchantNo, logNo, logDate, e);
|
||||||
|
return null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[查询可分账金额] 查询过程中发生未知异常, merchantNo={}, logNo={}, logDate={}", merchantNo, logNo, logDate, e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2077,8 +2097,6 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
log.info("[分账操作] 开始处理分账请求, lklMerchantNo={}, receiveTradeNo={}, receiveLogNo={}",
|
log.info("[分账操作] 开始处理分账请求, lklMerchantNo={}, receiveTradeNo={}, receiveLogNo={}",
|
||||||
lklMerchantNo, receiveTradeNo, receiveLogNo);
|
lklMerchantNo, receiveTradeNo, receiveLogNo);
|
||||||
|
|
||||||
// TODO 检查可分账余额是否足够?
|
|
||||||
|
|
||||||
// 2. 查询订单信息
|
// 2. 查询订单信息
|
||||||
ShopOrderLkl shopOrderLkl = shopOrderLklService.getByLklMchNoAndReceiveTradeNoAndReceiveLogNo(lklMerchantNo, receiveTradeNo, receiveLogNo);
|
ShopOrderLkl shopOrderLkl = shopOrderLklService.getByLklMchNoAndReceiveTradeNoAndReceiveLogNo(lklMerchantNo, receiveTradeNo, receiveLogNo);
|
||||||
if (shopOrderLkl == null) {
|
if (shopOrderLkl == null) {
|
||||||
@ -2086,6 +2104,19 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
return Pair.of(false, "订单不存在");
|
return Pair.of(false, "订单不存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO 检查可分账余额是否足够?
|
||||||
|
Pair<String, String> balanceCheckResult = queryMchCanSplitAmt(lklMerchantNo, receiveLogNo, shopOrderLkl.getLkl_log_date());
|
||||||
|
if (balanceCheckResult == null) {
|
||||||
|
log.error("[分账操作] 查询可分账余额失败:lklMerchantNo={} logDate={} receiveLogNo={}", lklMerchantNo, shopOrderLkl.getLkl_log_date(), receiveLogNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.warn("[分账操作] 可分账余额检查结果:分账总余额={}分 可分账金额={}分", balanceCheckResult.getFirst(), balanceCheckResult.getSecond());
|
||||||
|
Integer canSeparateAmt = Convert.toInt(balanceCheckResult.getSecond());
|
||||||
|
if (canSeparateAmt == null || canSeparateAmt <= 0) {
|
||||||
|
log.warn("[分账操作] lklMerchantNo={} receiveTradeNo={} receiveLogNo={} 可分账金额={}分 可分账余额不足,跳过处理", lklMerchantNo, receiveTradeNo, receiveLogNo, balanceCheckResult.getSecond());
|
||||||
|
return Pair.of(false, "可分账余额不足");
|
||||||
|
}
|
||||||
|
|
||||||
String orderId = shopOrderLkl.getOrder_id();
|
String orderId = shopOrderLkl.getOrder_id();
|
||||||
log.info("[分账操作] 开始处理订单[{}]的分账", orderId);
|
log.info("[分账操作] 开始处理订单[{}]的分账", orderId);
|
||||||
|
|
||||||
@ -2212,7 +2243,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
V3SacsSeparateRequest separateRequest = new V3SacsSeparateRequest();
|
V3SacsSeparateRequest separateRequest = new V3SacsSeparateRequest();
|
||||||
separateRequest.setMerchantNo(merchantNo);
|
separateRequest.setMerchantNo(merchantNo);
|
||||||
separateRequest.setOutSeparateNo(shopOrderLkl.getOut_separate_no());
|
separateRequest.setOutSeparateNo(shopOrderLkl.getOut_separate_no());
|
||||||
separateRequest.setLogNo(shopOrderLkl.getLkl_receive_log_no()); // 使用收货流水号作为分账流水号
|
separateRequest.setLogNo(shopOrderLkl.getLkl_receive_log_no()); // 使用确认收货流水号作为分账流水号
|
||||||
separateRequest.setLogDate(shopOrderLkl.getLkl_log_date());
|
separateRequest.setLogDate(shopOrderLkl.getLkl_log_date());
|
||||||
separateRequest.setTotalAmt(splitAmount.toString());
|
separateRequest.setTotalAmt(splitAmount.toString());
|
||||||
separateRequest.setLklOrgNo(orgCode);
|
separateRequest.setLklOrgNo(orgCode);
|
||||||
@ -2233,6 +2264,8 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
if (StrUtil.isBlank(response)) {
|
if (StrUtil.isBlank(response)) {
|
||||||
String errorMsg = String.format("[分账操作] 拉卡拉无响应,订单=%s,商户=%s,分账流水号=%s",
|
String errorMsg = String.format("[分账操作] 拉卡拉无响应,订单=%s,商户=%s,分账流水号=%s",
|
||||||
orderId, merchantNo, shopOrderLkl.getLkl_receive_log_no());
|
orderId, merchantNo, shopOrderLkl.getLkl_receive_log_no());
|
||||||
|
// 更改分账状态:分账失败
|
||||||
|
shopOrderLklService.updateSeparateStatusByReceiveLogNo(shopOrderLkl.getLkl_receive_log_no(), CommonConstant.Sta_Separate_Fail);
|
||||||
log.error(errorMsg);
|
log.error(errorMsg);
|
||||||
return Pair.of(false, "拉卡拉无响应");
|
return Pair.of(false, "拉卡拉无响应");
|
||||||
}
|
}
|
||||||
@ -2244,6 +2277,8 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
if (respJson == null || !lklSacsSuccessCode.equals(respJson.getStr("code")) || respJson.getJSONObject("resp_data") == null) {
|
if (respJson == null || !lklSacsSuccessCode.equals(respJson.getStr("code")) || respJson.getJSONObject("resp_data") == null) {
|
||||||
String errorMsg = String.format("[分账操作] 拉卡拉返回格式异常,订单=%s,商户=%s,分账流水号=%s,响应=%s,respJson=%s",
|
String errorMsg = String.format("[分账操作] 拉卡拉返回格式异常,订单=%s,商户=%s,分账流水号=%s,响应=%s,respJson=%s",
|
||||||
orderId, merchantNo, shopOrderLkl.getLkl_receive_log_no(), response, respJson);
|
orderId, merchantNo, shopOrderLkl.getLkl_receive_log_no(), response, respJson);
|
||||||
|
// 更改分账状态:分账失败
|
||||||
|
shopOrderLklService.updateSeparateStatusByReceiveLogNo(shopOrderLkl.getLkl_receive_log_no(), CommonConstant.Sta_Separate_Fail);
|
||||||
log.error(errorMsg);
|
log.error(errorMsg);
|
||||||
return Pair.of(false, "拉卡拉分账异常:[" + respJson.getStr("code") + "]" + respJson.getStr("msg"));
|
return Pair.of(false, "拉卡拉分账异常:[" + respJson.getStr("code") + "]" + respJson.getStr("msg"));
|
||||||
}
|
}
|
||||||
@ -2340,12 +2375,13 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. 提取关键参数并校验 - 确保必要参数完整
|
// 3. 提取关键参数并校验 - 确保必要参数完整
|
||||||
String logNo = paramsJson.getStr("log_no"); // 合单订单是子单流水号,非合单时是主单流水号
|
String logNo = paramsJson.getStr("log_no"); // 合单订单是子单(确认收货)流水号,非合单时是主单(确认收货)流水号
|
||||||
String separateNo = paramsJson.getStr("separate_no");
|
String separateNo = paramsJson.getStr("separate_no");
|
||||||
String outSeparateNo = paramsJson.getStr("out_separate_no");
|
String outSeparateNo = paramsJson.getStr("out_separate_no");
|
||||||
String status = paramsJson.getStr("status");
|
String status = paramsJson.getStr("status");
|
||||||
String finalStatus = paramsJson.getStr("final_status");
|
String finalStatus = paramsJson.getStr("final_status");
|
||||||
|
|
||||||
|
// 必要参数
|
||||||
List<String> missingParams = new ArrayList<>();
|
List<String> missingParams = new ArrayList<>();
|
||||||
if (StrUtil.isBlank(outSeparateNo)) missingParams.add("outSeparateNo");
|
if (StrUtil.isBlank(outSeparateNo)) missingParams.add("outSeparateNo");
|
||||||
if (StrUtil.isBlank(separateNo)) missingParams.add("separateNo");
|
if (StrUtil.isBlank(separateNo)) missingParams.add("separateNo");
|
||||||
@ -2404,6 +2440,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
lklOrderSeparate.setCal_type(paramsJson.getStr("cal_type"));
|
lklOrderSeparate.setCal_type(paramsJson.getStr("cal_type"));
|
||||||
lklOrderSeparate.setSeparate_type(paramsJson.getStr("separate_type"));
|
lklOrderSeparate.setSeparate_type(paramsJson.getStr("separate_type"));
|
||||||
lklOrderSeparate.setSeparate_date(paramsJson.getStr("separate_date"));
|
lklOrderSeparate.setSeparate_date(paramsJson.getStr("separate_date"));
|
||||||
|
// 总计分账金额
|
||||||
lklOrderSeparate.setTotal_separate_value(paramsJson.getInt("total_separate_value", 0));
|
lklOrderSeparate.setTotal_separate_value(paramsJson.getInt("total_separate_value", 0));
|
||||||
lklOrderSeparate.setRemark("分账已完成");
|
lklOrderSeparate.setRemark("分账已完成");
|
||||||
lklOrderSeparate.setFinish_date(paramsJson.getStr("finish_date"));
|
lklOrderSeparate.setFinish_date(paramsJson.getStr("finish_date"));
|
||||||
@ -2415,6 +2452,8 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
// 8. 持久化处理 - 更新分账记录到数据库
|
// 8. 持久化处理 - 更新分账记录到数据库
|
||||||
boolean updateSuccess = lklOrderSeparateService.addOrUpdateByReceiverNo(lklOrderSeparate);
|
boolean updateSuccess = lklOrderSeparateService.addOrUpdateByReceiverNo(lklOrderSeparate);
|
||||||
if (!updateSuccess) {
|
if (!updateSuccess) {
|
||||||
|
// 更改分账状态:分账失败
|
||||||
|
shopOrderLklService.updateSeparateStatusByReceiveLogNo(logNo, CommonConstant.Sta_Separate_Fail);
|
||||||
String errorMsg = String.format("分账记录更新失败, separateNo=%s", separateNo);
|
String errorMsg = String.format("分账记录更新失败, separateNo=%s", separateNo);
|
||||||
log.error("[拉卡拉分账通知] {}", errorMsg);
|
log.error("[拉卡拉分账通知] {}", errorMsg);
|
||||||
return JSONUtil.createObj()
|
return JSONUtil.createObj()
|
||||||
@ -2422,6 +2461,9 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
.put("message", "数据更新失败");
|
.put("message", "数据更新失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更改分账状态:分账成功
|
||||||
|
shopOrderLklService.updateSeparateStatusByReceiveLogNo(logNo, CommonConstant.Sta_Separate_Success);
|
||||||
|
|
||||||
// 9. 记录处理成功日志
|
// 9. 记录处理成功日志
|
||||||
log.info("[拉卡拉分账通知] 分账通知处理成功, separateNo={}, status={}", separateNo, status);
|
log.info("[拉卡拉分账通知] 分账通知处理成功, separateNo={}, status={}", separateNo, status);
|
||||||
return JSONUtil.createObj()
|
return JSONUtil.createObj()
|
||||||
|
|||||||
@ -94,4 +94,13 @@ public interface ShopOrderLklService extends IBaseService<ShopOrderLkl> {
|
|||||||
* @return ShopOrderLkl 拉卡拉订单记录
|
* @return ShopOrderLkl 拉卡拉订单记录
|
||||||
*/
|
*/
|
||||||
ShopOrderLkl getByLklMchNoAndReceiveTradeNoAndReceiveLogNo(String lklMerchantNo, String lklReceiveTradeNo, String lklReceiveLogNo);
|
ShopOrderLkl getByLklMchNoAndReceiveTradeNoAndReceiveLogNo(String lklMerchantNo, String lklReceiveTradeNo, String lklReceiveLogNo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据商户号、确认收货交易流水号、确认收货对账单流水号更新确认收货状态
|
||||||
|
*
|
||||||
|
* @param lklReceiveLogNo 拉卡拉确认收货对账单流水号
|
||||||
|
* @param separateStatus 分账状态:1-已分账;2-未分账;3-分账已失败;
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean updateSeparateStatusByReceiveLogNo(String lklReceiveLogNo, Integer separateStatus);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import cn.hutool.core.util.StrUtil;
|
|||||||
import cn.hutool.json.JSONObject;
|
import cn.hutool.json.JSONObject;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||||
import com.suisung.mall.common.modules.order.ShopOrderBase;
|
import com.suisung.mall.common.modules.order.ShopOrderBase;
|
||||||
import com.suisung.mall.common.modules.order.ShopOrderLkl;
|
import com.suisung.mall.common.modules.order.ShopOrderLkl;
|
||||||
import com.suisung.mall.common.utils.CheckUtil;
|
import com.suisung.mall.common.utils.CheckUtil;
|
||||||
@ -290,7 +291,7 @@ public class ShopOrderLklServiceImpl extends BaseServiceImpl<ShopOrderLklMapper,
|
|||||||
record.setLkl_trade_no(tradeNo);
|
record.setLkl_trade_no(tradeNo);
|
||||||
record.setTrade_status(tradeStatus);
|
record.setTrade_status(tradeStatus);
|
||||||
record.setWx_transaction_id(accTradeNo); //账户端交易订单号 对应微信的用户交易单号
|
record.setWx_transaction_id(accTradeNo); //账户端交易订单号 对应微信的用户交易单号
|
||||||
log.debug("[拉卡拉订单更新] 设置可选字段: tradeNo={} accTradeNo={} tradeStatus={}", tradeNo,accTradeNo, tradeStatus);
|
log.debug("[拉卡拉订单更新] 设置可选字段: tradeNo={} accTradeNo={} tradeStatus={}", tradeNo, accTradeNo, tradeStatus);
|
||||||
|
|
||||||
// 新增的订单字段,lkl_sub_log_no,out_separate_no,split_amt 四个字段无值,就给主单的值
|
// 新增的订单字段,lkl_sub_log_no,out_separate_no,split_amt 四个字段无值,就给主单的值
|
||||||
String outSeparateNo = JsonUtil.getJsonValueSmart(lklPayNotifyDataJson, "out_separate_no");
|
String outSeparateNo = JsonUtil.getJsonValueSmart(lklPayNotifyDataJson, "out_separate_no");
|
||||||
@ -502,4 +503,41 @@ public class ShopOrderLklServiceImpl extends BaseServiceImpl<ShopOrderLklMapper,
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据确认收货对账单流水号更新分账状态
|
||||||
|
*
|
||||||
|
* @param lklReceiveLogNo 拉卡拉确认收货对账单流水号
|
||||||
|
* @param separateStatus 分账状态:1-已分账;2-未分账;3-分账已失败;
|
||||||
|
* @return 更新结果 true-成功 false-失败
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Boolean updateSeparateStatusByReceiveLogNo(String lklReceiveLogNo, Integer separateStatus) {
|
||||||
|
// 检查参数是否全部为空
|
||||||
|
if (StringUtils.isBlank(lklReceiveLogNo) || separateStatus == null) {
|
||||||
|
log.warn("[更新分账状态] 参数校验失败:缺少必要参数, lklReceiveLogNo={}, separateStatus={}", lklReceiveLogNo, separateStatus);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
log.info("[更新分账状态] 开始更新分账状态, lklReceiveLogNo={}, separateStatus={}", lklReceiveLogNo, separateStatus);
|
||||||
|
|
||||||
|
UpdateWrapper<ShopOrderLkl> updateWrapper = new UpdateWrapper<>();
|
||||||
|
updateWrapper.eq("lkl_receive_log_no", lklReceiveLogNo);
|
||||||
|
updateWrapper.set("separate_status", separateStatus);
|
||||||
|
|
||||||
|
boolean result = update(updateWrapper);
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
log.info("[更新分账状态] 分账状态更新成功, lklReceiveLogNo={}, separateStatus={}", lklReceiveLogNo, separateStatus);
|
||||||
|
} else {
|
||||||
|
log.warn("[更新分账状态] 分账状态更新失败,未找到匹配记录, lklReceiveLogNo={}, separateStatus={}", lklReceiveLogNo, separateStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[更新分账状态] 分账状态更新异常, lklReceiveLogNo={}, separateStatus={}", lklReceiveLogNo, separateStatus, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user