[fix]优化分账逻辑

This commit is contained in:
wangqx 2025-07-14 18:22:02 +08:00
parent bb812c2bbe
commit dd68c8fe29
6 changed files with 174 additions and 88 deletions

View File

@ -8,6 +8,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
@ -131,4 +132,14 @@ public class SysTenant extends BaseEntity {
private LocalDateTime joinTime;
private Long accountId;
/**
* 分账比例
*/
private BigDecimal divideRate;
/**
* 是否承担手续费
*/
private Integer bearFeeFlag;
}

View File

@ -1,5 +1,6 @@
package org.dromara.system.domain.vo;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
@ -173,4 +174,16 @@ public class SysTenantVo implements Serializable {
@ExcelProperty(value = "入驻时间")
private LocalDateTime joinTime;
/**
* 分账是否承担手续费
*/
@Schema(description = "分账是否承担手续费")
private Integer bearFeeFlag;
/**
* 分账比例
*/
@Schema(description = "分账比例")
private BigDecimal divideRate;
}

View File

@ -40,13 +40,6 @@ public class DivideRuleBO extends BaseBO<DivideRule> {
@ExcelProperty(value ="名称", order = 3)
private String name;
@Schema(description ="是否分配手续费")
@ExcelProperty(value ="是否分配手续费", order = 4)
private Integer divideFeeFlag;
@Schema(description ="手续费分配方式")
@ExcelProperty(value ="手续费分配方式", order = 5)
private Integer feeType;
/**
* 状态
@ -61,6 +54,13 @@ public class DivideRuleBO extends BaseBO<DivideRule> {
@ExcelProperty(value ="类型", order = 8)
private Integer type;
@Schema(description = "区域id")
private Long regionId;
private List<DivideRuleDetailBO> details=new ArrayList<>();
}

View File

@ -40,13 +40,11 @@ public class DivideRule extends BaseEntity {
@ExcelProperty(value ="名称", order = 3)
private String name;
@Schema(description ="是否分配手续费")
@ExcelProperty(value ="是否分配手续费", order = 4)
private Integer divideFeeFlag;
@Schema(description ="手续费分配方式")
@ExcelProperty(value ="手续费分配方式", order = 5)
private Integer feeType;
@Schema(description = "区域id")
private Long regionId;
/**
* 状态

View File

@ -45,20 +45,17 @@ public class DivideRuleVO extends BaseEntity {
@ExcelProperty(value ="名称", order = 3)
private String name;
@Schema(description ="是否分配手续费")
@ExcelProperty(value ="是否分配手续费", order = 4)
private Integer divideFeeFlag;
@Schema(description ="手续费分配方式")
@ExcelProperty(value ="手续费分配方式", order = 5)
private Integer feeType;
/**
* 状态
*/
@Schema(description ="状态")
@ExcelProperty(value ="状态", order = 7)
private Integer status;
@Schema(description = "区域id")
private Long regionId;
/**
* 类型
*/

View File

@ -15,10 +15,11 @@ import com.wzj.soopin.transaction.convert.DivideDetailConvert;
import com.wzj.soopin.transaction.domain.bo.DivideBO;
import com.wzj.soopin.transaction.domain.po.Divide;
import com.wzj.soopin.transaction.domain.po.DivideDetail;
import com.wzj.soopin.transaction.domain.po.DivideRuleDetail;
import com.wzj.soopin.transaction.domain.vo.DivideRuleDetailVO;
import com.wzj.soopin.transaction.domain.vo.DivideRuleVO;
import com.wzj.soopin.transaction.domain.vo.DivideVO;
import com.wzj.soopin.transaction.enums.DivideRuleDetailType;
import com.wzj.soopin.transaction.enums.DivideRuleFeeType;
import com.wzj.soopin.transaction.enums.DivideStatus;
import com.wzj.soopin.transaction.mapper.DivideDetailMapper;
import com.wzj.soopin.transaction.mapper.DivideMapper;
@ -31,6 +32,7 @@ import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.ConfigService;
import org.dromara.system.domain.vo.SysTenantVo;
import org.dromara.system.service.ISysTenantService;
import org.slf4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -161,36 +163,157 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
throw new ServiceException("未找到分账规则");
}
//开始分账
//计算订单可分配金额,订单只考虑整单退不考虑单独退所以直接计算订单金额
//根据易生支付的合同查看手续费金额
BigDecimal totalAmount = order.getTotalAmount();
BigDecimal totalFee = new BigDecimal(0);
String feeRate = configService.getConfigValue("transaction.divide.feeRate");
if (StringUtils.isNotBlank(feeRate)) {
totalFee = totalAmount.multiply(new BigDecimal(feeRate)).divide(new BigDecimal(1000), 2, BigDecimal.ROUND_HALF_UP);
}
BigDecimal actualMoney = totalAmount.subtract(totalFee);
//计算订单可分配金额,订单只考虑整单退不考虑单独退所以直接计算订单金额
//先生成主表信息
divide = Divide.builder()
.ruleId(rule.getId())
.orderMoney(totalAmount)
.fee(totalFee)
.actualMoney(totalAmount.subtract(totalFee))
.actualMoney(actualMoney)
.orderSn(order.getOrderSn())
.status(DivideStatus.PENDING.getCode())
.build();
super.save(divide);
//生成分账明细信息
List<DivideDetail> details = saveDetails(order, divide.getId(), totalFee, totalAmount, rule);
//计算商户的手续费
SysTenantVo tenant = sysTenantService.queryById(order.getTenantId());
if (tenant == null) {
throw new ServiceException("租户信息不存在");
}
BigDecimal sellerFee = new BigDecimal(0);
BigDecimal platformFee = new BigDecimal(0);
if (tenant.getBearFeeFlag() == 1) {
//如果承担手续费计算手续费
sellerFee = totalFee;
} else {
platformFee = totalFee;
}
//生成商户的分账明细
BigDecimal sellerAmount = divideSeller(actualMoney, sellerFee, divide.getId(), tenant);
BigDecimal platformAmount = actualMoney.subtract(sellerAmount);
BigDecimal finalAmount = new BigDecimal(0);
//按规则进行分账
//先分代理 然后达人 最后的剩余都给平台
DivideRuleDetailVO divideRuleDetail = rule.getDetails().stream().filter(item -> item.getType() == DivideRuleDetailType.PROXY.getValue()).findFirst().orElse(null);
if ((divideRuleDetail != null)) {
finalAmount = platformAmount.subtract(divideproxy(platformAmount, divideRuleDetail, divide.getId(), order.getTenantId()));
}
divideRuleDetail = rule.getDetails().stream().filter(item -> item.getType() == DivideRuleDetailType.REFERENCE.getValue()).findFirst().orElse(null);
if ((divideRuleDetail != null)) {
finalAmount = finalAmount.subtract(divideDarren(platformAmount, divideRuleDetail, divide.getId(), order.getMemberId()));
}
dividePlatform(finalAmount, platformFee, divideRuleDetail, divide.getId(), tenant.getBearFeeFlag() == 1);
//同步订单状态
syncOrderStatus(order);
//同步易生支付
syncYisheng(details);
syncYisheng(null);
return true;
}
private BigDecimal divideSeller(BigDecimal actualMoney, BigDecimal sellerFee, Long divideId, SysTenantVo tenant) {
//获取商户的账户信息
Map<String, String> account = getSellerAccount(tenant.getId());
if (account == null) {
log.error("商户信息不存在,不参与分账");
}
//计算商户的分账金额
BigDecimal divideRate = tenant.getDivideRate();
Integer bearFeeFlag = tenant.getBearFeeFlag();
//计算商户的分账金额
BigDecimal sellerAmount = actualMoney.multiply(divideRate).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
//生成商户的分账明细
DivideDetail sellerDetail = DivideDetail.builder()
.divideId(divideId)
.money(sellerAmount)
.fee(sellerFee)
.feePercent(bearFeeFlag == 1 ? new BigDecimal(100) : new BigDecimal(0))
.moneyPercent(divideRate)
.type(DivideRuleDetailType.SELLER.getValue()).build();
detailMapper.insert(sellerDetail);
return sellerAmount;
}
private BigDecimal divideproxy(BigDecimal platformMoney, DivideRuleDetailVO rule, Long divideId, Long tenantId) {
//获取代理人的账户信息
Map<String, String> account = getProxyAccount(tenantId);
if (account == null) {
log.error("代理人信息不存在,不参与分账");
return new BigDecimal(0);
}
//计算代理人的分账金额
BigDecimal proxyAmount = platformMoney.multiply(rule.getMoneyPercent()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
DivideDetail proxyDetail = DivideDetail.builder()
.divideId(divideId)
.money(proxyAmount)
.fee(new BigDecimal(0))
.feePercent(new BigDecimal(0))
.moneyPercent(rule.getMoneyPercent())
.type(DivideRuleDetailType.PROXY.getValue())
.build();
detailMapper.insert(proxyDetail);
return proxyAmount;
}
private BigDecimal divideDarren(BigDecimal platformMoney, DivideRuleDetailVO rule, Long divideId, Long tenantId) {
//获取达人的账户信息
Map<String, String> account = getReferenceAccount(tenantId);
if (account == null) {
log.error("达人信息不存在,不参与分账");
return new BigDecimal(0);
}
//计算达人的分账金额
BigDecimal proxyAmount = platformMoney.multiply(rule.getMoneyPercent()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
DivideDetail proxyDetail = DivideDetail.builder()
.divideId(divideId)
.money(proxyAmount)
.fee(new BigDecimal(0))
.feePercent(new BigDecimal(0))
.moneyPercent(rule.getMoneyPercent())
.type(DivideRuleDetailType.REFERENCE.getValue())
.build();
detailMapper.insert(proxyDetail);
return proxyAmount;
}
private void dividePlatform(BigDecimal platformMoney, BigDecimal fee, DivideRuleDetailVO rule, Long divideId, boolean feeFlag) {
//获取平台的账户信息
Map<String, String> account = getPlatformAccount();
if (account == null) {
log.error("平台信息不存在,不参与分账");
}
//计算平台的分账金额
BigDecimal proxyAmount = platformMoney.multiply(rule.getMoneyPercent()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
DivideDetail proxyDetail = DivideDetail.builder()
.divideId(divideId)
.money(proxyAmount)
.fee(fee)
.feePercent(feeFlag ? new BigDecimal(100) : new BigDecimal(0))
.moneyPercent(rule.getMoneyPercent())
.type(DivideRuleDetailType.REFERENCE.getValue())
.build();
detailMapper.insert(proxyDetail);
}
@Override
public boolean cancelDivide(String orderNo) {
return false;
@ -206,60 +329,6 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
return false;
}
private List<DivideDetail> saveDetails(Order order, Long divideId, BigDecimal totalFee, BigDecimal totalAmount, DivideRuleVO rule) {
List<DivideDetail> details = rule.getDetails().stream().map(item -> {
//计算金额
BigDecimal amount = totalAmount.multiply(item.getMoneyPercent()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
//如果需要分配手续费计算手续费
BigDecimal fee = new BigDecimal(0);
//
if (rule.getDivideFeeFlag() == 1) {
if (rule.getFeeType() == DivideRuleFeeType.PLATFORM.getValue() && item.getType() == DivideRuleDetailType.PLATFORM.getValue()) {
fee = totalFee;
} else if (rule.getFeeType() == DivideRuleFeeType.PROXY.getValue() && item.getType() == DivideRuleDetailType.PROXY.getValue()) {
fee = totalFee;
} else if (rule.getFeeType() == DivideRuleFeeType.SELLER.getValue() && item.getType() == DivideRuleDetailType.SELLER.getValue()) {
fee = totalFee;
} else {
fee = totalFee.multiply(item.getFeePercent()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
}
}
DivideDetail detail = DivideDetail.builder()
.divideId(divideId)
.money(amount)
.fee(fee)
.feePercent(item.getFeePercent())
.moneyPercent(item.getMoneyPercent())
.type(item.getType())
.orderId(order.getId())
.orderSn(order.getOrderSn())
.build();
Map<String, String> account = new HashMap<>();
//如果是平台代理卖家直接分配
if (item.getType() == DivideRuleDetailType.PLATFORM.getValue()) {
account = getPlatformAccount();
} else if (item.getType() == DivideRuleDetailType.PROXY.getValue()) {
account = getProxyAccount(Long.valueOf(order.getTenantId()));
} else if (item.getType() == DivideRuleDetailType.SELLER.getValue()) {
account = getSellerAccount(Long.valueOf(order.getTenantId()));
} else if (item.getType() == DivideRuleDetailType.REFERENCE.getValue()) {
account = getReferenceAccount(order.getMemberId());
}
if (account == null) {
detail.setAccountId(Long.parseLong(account.get("accountId")));
detail.setAccountName(account.get("accountName"));
return detail;
} else {
throw new ServiceException(StringUtils.format("%s未找到分账账户", DivideRuleDetailType.getEnum(item.getType())));
}
}).collect(Collectors.toList());
detailMapper.insertBatch(details);
return details;
}
private Map<String, String> getPlatformAccount() {
return new HashMap<>() {{
@ -297,16 +366,14 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
/**
* 获取代理的账户信息
*
* @param sellerId
* @param
* @return
*/
private Map<String, String> getProxyAccount(Long sellerId) {
SysTenantVo tenant = sysTenantService.queryById(sellerId);
Long inviteUserId = tenant.getInviteUserId();
if (inviteUserId != null) {
private Map<String, String> getProxyAccount(Long memberId) {
if (memberId != null) {
return null;
}
MemberAccount account = accountService.getMemberAccount(inviteUserId);
MemberAccount account = accountService.getMemberAccount(memberId);
if (account == null) {
return null;