[fix]优化分账逻辑
This commit is contained in:
parent
bb812c2bbe
commit
dd68c8fe29
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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<>();
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
||||
/**
|
||||
* 状态
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user