[fix]优化分账逻辑
This commit is contained in:
parent
bb812c2bbe
commit
dd68c8fe29
@ -8,6 +8,7 @@ import lombok.Data;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@ -131,4 +132,14 @@ public class SysTenant extends BaseEntity {
|
|||||||
private LocalDateTime joinTime;
|
private LocalDateTime joinTime;
|
||||||
|
|
||||||
private Long accountId;
|
private Long accountId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分账比例
|
||||||
|
*/
|
||||||
|
private BigDecimal divideRate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否承担手续费
|
||||||
|
*/
|
||||||
|
private Integer bearFeeFlag;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.dromara.system.domain.vo;
|
package org.dromara.system.domain.vo;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||||
@ -173,4 +174,16 @@ public class SysTenantVo implements Serializable {
|
|||||||
@ExcelProperty(value = "入驻时间")
|
@ExcelProperty(value = "入驻时间")
|
||||||
private LocalDateTime joinTime;
|
private LocalDateTime joinTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分账是否承担手续费
|
||||||
|
*/
|
||||||
|
@Schema(description = "分账是否承担手续费")
|
||||||
|
private Integer bearFeeFlag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分账比例
|
||||||
|
*/
|
||||||
|
@Schema(description = "分账比例")
|
||||||
|
private BigDecimal divideRate;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -40,13 +40,6 @@ public class DivideRuleBO extends BaseBO<DivideRule> {
|
|||||||
@ExcelProperty(value ="名称", order = 3)
|
@ExcelProperty(value ="名称", order = 3)
|
||||||
private String name;
|
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)
|
@ExcelProperty(value ="类型", order = 8)
|
||||||
private Integer type;
|
private Integer type;
|
||||||
|
|
||||||
|
|
||||||
|
@Schema(description = "区域id")
|
||||||
|
private Long regionId;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private List<DivideRuleDetailBO> details=new ArrayList<>();
|
private List<DivideRuleDetailBO> details=new ArrayList<>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -40,13 +40,11 @@ public class DivideRule extends BaseEntity {
|
|||||||
@ExcelProperty(value ="名称", order = 3)
|
@ExcelProperty(value ="名称", order = 3)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@Schema(description ="是否分配手续费")
|
|
||||||
@ExcelProperty(value ="是否分配手续费", order = 4)
|
|
||||||
private Integer divideFeeFlag;
|
|
||||||
|
|
||||||
@Schema(description ="手续费分配方式")
|
|
||||||
@ExcelProperty(value ="手续费分配方式", order = 5)
|
@Schema(description = "区域id")
|
||||||
private Integer feeType;
|
private Long regionId;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 状态
|
* 状态
|
||||||
|
@ -45,20 +45,17 @@ public class DivideRuleVO extends BaseEntity {
|
|||||||
@ExcelProperty(value ="名称", order = 3)
|
@ExcelProperty(value ="名称", order = 3)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@Schema(description ="是否分配手续费")
|
|
||||||
@ExcelProperty(value ="是否分配手续费", order = 4)
|
|
||||||
private Integer divideFeeFlag;
|
|
||||||
|
|
||||||
@Schema(description ="手续费分配方式")
|
|
||||||
@ExcelProperty(value ="手续费分配方式", order = 5)
|
|
||||||
private Integer feeType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 状态
|
* 状态
|
||||||
*/
|
*/
|
||||||
@Schema(description ="状态")
|
@Schema(description ="状态")
|
||||||
@ExcelProperty(value ="状态", order = 7)
|
@ExcelProperty(value ="状态", order = 7)
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
|
|
||||||
|
@Schema(description = "区域id")
|
||||||
|
private Long regionId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 类型
|
* 类型
|
||||||
*/
|
*/
|
||||||
|
@ -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.bo.DivideBO;
|
||||||
import com.wzj.soopin.transaction.domain.po.Divide;
|
import com.wzj.soopin.transaction.domain.po.Divide;
|
||||||
import com.wzj.soopin.transaction.domain.po.DivideDetail;
|
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.DivideRuleVO;
|
||||||
import com.wzj.soopin.transaction.domain.vo.DivideVO;
|
import com.wzj.soopin.transaction.domain.vo.DivideVO;
|
||||||
import com.wzj.soopin.transaction.enums.DivideRuleDetailType;
|
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.enums.DivideStatus;
|
||||||
import com.wzj.soopin.transaction.mapper.DivideDetailMapper;
|
import com.wzj.soopin.transaction.mapper.DivideDetailMapper;
|
||||||
import com.wzj.soopin.transaction.mapper.DivideMapper;
|
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.common.core.service.ConfigService;
|
||||||
import org.dromara.system.domain.vo.SysTenantVo;
|
import org.dromara.system.domain.vo.SysTenantVo;
|
||||||
import org.dromara.system.service.ISysTenantService;
|
import org.dromara.system.service.ISysTenantService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@ -161,36 +163,157 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
|
|||||||
throw new ServiceException("未找到分账规则");
|
throw new ServiceException("未找到分账规则");
|
||||||
}
|
}
|
||||||
//开始分账
|
//开始分账
|
||||||
//计算订单可分配金额,订单只考虑整单退,不考虑单独退,所以直接计算订单金额
|
|
||||||
|
//根据易生支付的合同查看手续费金额
|
||||||
BigDecimal totalAmount = order.getTotalAmount();
|
BigDecimal totalAmount = order.getTotalAmount();
|
||||||
BigDecimal totalFee = new BigDecimal(0);
|
BigDecimal totalFee = new BigDecimal(0);
|
||||||
String feeRate = configService.getConfigValue("transaction.divide.feeRate");
|
String feeRate = configService.getConfigValue("transaction.divide.feeRate");
|
||||||
if (StringUtils.isNotBlank(feeRate)) {
|
if (StringUtils.isNotBlank(feeRate)) {
|
||||||
totalFee = totalAmount.multiply(new BigDecimal(feeRate)).divide(new BigDecimal(1000), 2, BigDecimal.ROUND_HALF_UP);
|
totalFee = totalAmount.multiply(new BigDecimal(feeRate)).divide(new BigDecimal(1000), 2, BigDecimal.ROUND_HALF_UP);
|
||||||
}
|
}
|
||||||
|
BigDecimal actualMoney = totalAmount.subtract(totalFee);
|
||||||
|
//计算订单可分配金额,订单只考虑整单退,不考虑单独退,所以直接计算订单金额
|
||||||
//先生成主表信息
|
//先生成主表信息
|
||||||
divide = Divide.builder()
|
divide = Divide.builder()
|
||||||
.ruleId(rule.getId())
|
.ruleId(rule.getId())
|
||||||
.orderMoney(totalAmount)
|
.orderMoney(totalAmount)
|
||||||
.fee(totalFee)
|
.fee(totalFee)
|
||||||
.actualMoney(totalAmount.subtract(totalFee))
|
.actualMoney(actualMoney)
|
||||||
.orderSn(order.getOrderSn())
|
.orderSn(order.getOrderSn())
|
||||||
.status(DivideStatus.PENDING.getCode())
|
.status(DivideStatus.PENDING.getCode())
|
||||||
.build();
|
.build();
|
||||||
super.save(divide);
|
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);
|
syncOrderStatus(order);
|
||||||
|
|
||||||
//同步易生支付
|
//同步易生支付
|
||||||
syncYisheng(details);
|
syncYisheng(null);
|
||||||
return true;
|
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
|
@Override
|
||||||
public boolean cancelDivide(String orderNo) {
|
public boolean cancelDivide(String orderNo) {
|
||||||
return false;
|
return false;
|
||||||
@ -206,60 +329,6 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
|
|||||||
return false;
|
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() {
|
private Map<String, String> getPlatformAccount() {
|
||||||
return new HashMap<>() {{
|
return new HashMap<>() {{
|
||||||
@ -297,16 +366,14 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
|
|||||||
/**
|
/**
|
||||||
* 获取代理的账户信息
|
* 获取代理的账户信息
|
||||||
*
|
*
|
||||||
* @param sellerId
|
* @param
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private Map<String, String> getProxyAccount(Long sellerId) {
|
private Map<String, String> getProxyAccount(Long memberId) {
|
||||||
SysTenantVo tenant = sysTenantService.queryById(sellerId);
|
if (memberId != null) {
|
||||||
Long inviteUserId = tenant.getInviteUserId();
|
|
||||||
if (inviteUserId != null) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
MemberAccount account = accountService.getMemberAccount(inviteUserId);
|
MemberAccount account = accountService.getMemberAccount(memberId);
|
||||||
|
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
return null;
|
return null;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user