更新分成逻辑

This commit is contained in:
磷叶 2025-03-04 11:10:50 +08:00
parent 0f6251455f
commit 9758933156
11 changed files with 121 additions and 63 deletions

View File

@ -163,4 +163,14 @@ public interface BonusMapper
* 查询总金额
*/
BigDecimal selectSumOfAmount(@Param("query") BonusQuery query);
/**
* 根据条件更新
*/
int updateByQuery(@Param("data") Bonus data, @Param("query") BonusQuery query);
/**
* 预支付
*/
int prePay(@Param("list") List<? extends Bonus> bonusList);
}

View File

@ -454,6 +454,37 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
and `status` = '1'
</update>
<update id="updateByQuery">
update ss_bonus sb
<trim prefix="SET" suffixOverrides=",">
<include refid="updateColumns"/>
</trim>
<where>
<include refid="searchCondition"/>
</where>
</update>
<update id="prePay">
update ss_bonus
<trim prefix="SET" suffixOverrides=",">
<foreach open="pre_pay_time = CASE id" collection="list" item="item" close="END,">
<choose>
<when test="item.prePayTime != null">
WHEN #{item.id} THEN #{item.prePayTime}
</when>
<otherwise>
WHEN #{item.id} THEN pre_pay_time
</otherwise>
</choose>
</foreach>
</trim>
where id in
<foreach collection="list" item="item" open="(" separator="," close=")">
#{item.id}
</foreach>
and `status` = '2'
</update>
<sql id="updateColumns">
<if test="data.billId != null">bill_id = #{data.billId},</if>
<if test="data.billNo != null">bill_no = #{data.billNo},</if>
@ -498,7 +529,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</where>
</select>
<!-- selectSumOfAmount -->
<!-- selectSumOfAmount -->
<select id="selectSumOfAmount" resultType="java.math.BigDecimal">
select sum(sb.amount) as `value`

View File

@ -4,18 +4,14 @@ import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import com.ruoyi.common.domain.vo.CommonCountVO;
import com.ruoyi.common.domain.vo.CommonSumVO;
import com.ruoyi.common.domain.vo.LocalDateDecimalVO;
import com.ruoyi.common.domain.vo.LongDecimalVO;
import com.ruoyi.ss.bonus.domain.Bonus;
import com.ruoyi.ss.bonus.domain.BonusProvideQuery;
import com.ruoyi.ss.bonus.domain.BonusQuery;
import com.ruoyi.ss.bonus.domain.BonusVO;
import com.ruoyi.ss.bonus.domain.enums.BonusBstType;
import com.ruoyi.ss.bonus.domain.vo.BonusDailyAmountVO;
import com.ruoyi.ss.bonus.domain.vo.BonusMonthAmountVO;
import com.ruoyi.ss.bonus.domain.vo.ProvideBonusVO;
/**
* 分成明细Service接口
@ -88,9 +84,8 @@ public interface BonusService
* 分配分成金额按照比例分出金额
*
* @param bonusList 分成列表
* @param money 总金额
*/
int partBonus(List<? extends Bonus> bonusList, BigDecimal money);
int prePay(List<? extends Bonus> bonusList);
/**
* 当未分成时退款

View File

@ -158,9 +158,14 @@ public class BonusConverterImpl implements BonusConverter {
bonus.setBillNo(order.getOrderNo());
bonus.setToBalance(isPlatform);
bonus.setChannelId(channelId);
bonus.setStatus(BonusStatus.UN_DIVIDEND.getStatus());
bonus.setStatus(BonusStatus.WAIT_DIVIDE.getStatus());
}
// 拆分金额
// 平台最低需要的分成金额
BigDecimal minService = sysConfigService.getBigDecimal(ConfigKey.RECHARGE_MIN_SERVICE);
BonusUtil.partBonusAmount(result, order.getAmount(), minService);
return result;
}
@ -219,9 +224,10 @@ public class BonusConverterImpl implements BonusConverter {
bonus.setBillNo(bill.getBillNo());
bonus.setToBalance(true);
bonus.setChannelId(channel.getChannelId());
bonus.setStatus(BonusStatus.UN_DIVIDEND.getStatus());
bonus.setStatus(BonusStatus.WAIT_DIVIDE.getStatus());
}
// 拆分金额
// 平台最低需要的分成金额
BigDecimal minService = sysConfigService.getBigDecimal(ConfigKey.RECHARGE_MIN_SERVICE);
BonusUtil.partBonusAmount(bonusList, bill.getMoney(), minService);

View File

@ -2,7 +2,6 @@ package com.ruoyi.ss.bonus.service.impl;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@ -11,18 +10,12 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.domain.vo.CommonCountVO;
import com.ruoyi.common.domain.vo.CommonSumVO;
import com.ruoyi.common.domain.vo.LocalDateDecimalVO;
import com.ruoyi.common.domain.vo.LongDecimalVO;
import com.ruoyi.common.enums.LoginType;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.ss.bonus.domain.Bonus;
import com.ruoyi.ss.bonus.domain.BonusProvideQuery;
import com.ruoyi.ss.bonus.domain.BonusQuery;
import com.ruoyi.ss.bonus.domain.BonusVO;
import com.ruoyi.ss.bonus.domain.enums.BonusArrivalType;
@ -30,15 +23,12 @@ import com.ruoyi.ss.bonus.domain.enums.BonusBstType;
import com.ruoyi.ss.bonus.domain.enums.BonusStatus;
import com.ruoyi.ss.bonus.domain.vo.BonusDailyAmountVO;
import com.ruoyi.ss.bonus.domain.vo.BonusMonthAmountVO;
import com.ruoyi.ss.bonus.domain.vo.ProvideBonusVO;
import com.ruoyi.ss.bonus.mapper.BonusMapper;
import com.ruoyi.ss.bonus.service.BonusService;
import com.ruoyi.ss.bonus.utils.BonusUtil;
import com.ruoyi.ss.recordBalance.domain.enums.RecordBalanceBstType;
import com.ruoyi.ss.user.domain.SmUserVO;
import com.ruoyi.ss.user.service.UserAssembler;
import com.ruoyi.ss.user.service.UserService;
import com.ruoyi.system.domain.enums.config.ConfigKey;
import com.ruoyi.system.service.ISysConfigService;
import lombok.extern.slf4j.Slf4j;
@ -205,22 +195,12 @@ public class BonusServiceImpl implements BonusService
}
@Override
public int partBonus(List<? extends Bonus> bonusList, BigDecimal money) {
if (CollectionUtils.isEmptyElement(bonusList) || money == null) {
public int prePay(List<? extends Bonus> bonusList) {
if (CollectionUtils.isEmptyElement(bonusList)) {
return 0;
}
// 设置预计分成时间等数据
this.setWaitBonusInfo(bonusList);
// 更新数据库
return this.batchUpdateAmount(bonusList);
}
/**
* 设置待分成数据
*/
private void setWaitBonusInfo(List<? extends Bonus> bonusList) {
LocalDateTime now = LocalDateTime.now();
// 获取用户列表
@ -233,7 +213,6 @@ public class BonusServiceImpl implements BonusService
userAssembler.assembleRealArrivalDelay(userList);
for (Bonus bonus : bonusList) {
bonus.setStatus(BonusStatus.WAIT_DIVIDE.getStatus());
// 设置预计分成时间
if (BonusArrivalType.userList().contains(bonus.getArrivalType())) {
SmUserVO user = userList.stream().filter(item -> item.getUserId().equals(bonus.getArrivalId())).findFirst().orElse(null);
@ -245,6 +224,15 @@ public class BonusServiceImpl implements BonusService
bonus.setPrePayTime(now);
}
}
// 更新数据库
Integer result = transactionTemplate.execute(status -> {
int rows = bonusMapper.prePay(bonusList);
ServiceUtil.assertion(rows != bonusList.size(), "预分成失败,请刷新后重试");
return rows;
});
return result == null ? 0 : result;
}
@Override

View File

@ -200,5 +200,9 @@ public class BonusUtil {
// 处理误差后的分配金额
dividedAmount = CollectionUtils.sumDecimal(bonusList, Bonus::getAmount);
ServiceUtil.assertion(dividedAmount.compareTo(money) != 0, "分成金额分配出错");
for (Bonus bonus : bonusList) {
bonus.setWaitAmount(bonus.getAmount());
}
}
}

View File

@ -13,6 +13,7 @@ import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.ruoyi.ss.transactionBill.service.TransactionAssembler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -148,6 +149,10 @@ public class DeviceServiceImpl implements DeviceService
@Autowired
private ICommandLogService commandLogService;
@Autowired
private TransactionAssembler transactionAssembler;
/**
* 查询设备
*
@ -1254,6 +1259,7 @@ public class DeviceServiceImpl implements DeviceService
if (CollectionUtils.isEmptyElement(billList)) {
return 0;
}
transactionAssembler.assembleBonusList(billList);
return transactionBillService.batchCloseBillByDevice(billList, device, totalEle);
}

View File

@ -394,6 +394,6 @@ public interface TransactionBillService {
/**
* 处理已结束订单
*/
boolean handleFinished(TransactionBillVO bill);
boolean handleFinishedBonus(TransactionBillVO bill);
}

View File

@ -1032,7 +1032,7 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
ServiceUtil.assertion(!TransactionBillStatus.SUCCESS.getStatus().equals(order.getStatus()), "当前订单状态不允许结束");
ServiceUtil.assertion(device == null, "设备不存在");
LocalDateTime now = LocalDateTime.now(); // 结束使用的时间
LocalDateTime endTime = LocalDateTime.now(); // 结束使用的时间
// 结束使用的电量若蓝牙传过来的值为空或者小于当前电量则使用当前电量否则使用蓝牙传输的电量谁大用谁
BigDecimal totalEle = this.calcTotalEle(device, bo.getTotalEle());
@ -1041,9 +1041,9 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
ServiceUtil.assertion(order.getIsFinished() != null && order.getIsFinished(), "当前订单已结束,无法操作");
Integer result = transactionTemplate.execute(status -> {
// 修改结束使用的时间
// 修改结束使用的电量
TransactionBill data = new TransactionBill();
data.setSuitEndTime(now);
data.setSuitEndTime(endTime);
data.setSuitEndEle(totalEle);
TransactionBillQuery query = new TransactionBillQuery();
query.setBillId(order.getBillId());
@ -1054,7 +1054,7 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
// 若是分时段电量则记录一次电量金额
if (SuitFeeType.TIMING_COUNT.getType().equals(order.getSuitFeeType())) {
BillEleRecord record = billEleRecordConverter.toPo(order, device, now, now);
BillEleRecord record = billEleRecordConverter.toPo(order, device, endTime, endTime);
int insertRecord = billEleRecordService.insertBillEleRecord(record);
ServiceUtil.assertion(insertRecord != 1, "记录分时段订单%s用电量失败", order.getBillNo());
}
@ -1064,21 +1064,36 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
boolean success = result != null && result == 1; // 是否成功
// 若成功且为智能模式则计算需要退款的金额, 若金额 > 0.01 则申请退款
if (success && SuitFeeMode.SMART.getMode().equals(order.getSuitFeeMode())) {
BigDecimal refundAmount = this.calcRefundAmount(order, now, totalEle);
if (BigDecimal.valueOf(0.01).compareTo(refundAmount) < 0) {
// 成功后操作
if (success) {
scheduledExecutorService.schedule(() -> {
// 智能退款
BigDecimal refundAmount = this.calcRefundAmount(order, endTime, totalEle);
if (SuitFeeMode.SMART.getMode().equals(order.getSuitFeeMode())) {
if (BigDecimal.valueOf(0.01).compareTo(refundAmount) < 0) {
try {
BillRefundDTO refundDto = new BillRefundDTO();
refundDto.setBillId(order.getBillId());
refundDto.setRefundAmount(refundAmount);
refundDto.setRefundReason(String.format("充值订单%s智能退款%s元", order.getBillNo(), refundAmount));
refundDto.setCheckFinish(false);
int refund = this.refund(refundDto);
ServiceUtil.assertion(refund != 1, "申请退款失败");
} catch (Exception e) {
log.error("订单{}智能退款失败:{}", order.getBillNo(), e.getMessage());
}
}
}
// 处理分成
this.handleFinishedBonus(order);
// 10秒后执行一次分成
scheduledExecutorService.schedule(() -> {
// 申请退款
BillRefundDTO refundDto = new BillRefundDTO();
refundDto.setBillId(order.getBillId());
refundDto.setRefundAmount(refundAmount);
refundDto.setRefundReason(String.format("充值订单%s智能退款%s元", order.getBillNo(), refundAmount));
refundDto.setCheckFinish(false);
int refund = this.refund(refundDto);
ServiceUtil.assertion(refund != 1, "申请退款失败");
bonusService.payBonusBeforeTime(LocalDateTime.now());
}, 10, TimeUnit.SECONDS);
}
}, 10, TimeUnit.SECONDS);
}
return result == null ? 0 : result;
@ -1892,7 +1907,7 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
}
@Override
public boolean handleFinished(TransactionBillVO bill) {
public boolean handleFinishedBonus(TransactionBillVO bill) {
if (bill == null) {
return false;
}
@ -1901,11 +1916,11 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
}
Boolean result = transactionTemplate.execute(status -> {
// TODO 更新订单流程状态
// TODO 若订单没有结束时间则更新订单的结束时间
// 更新订单流程状态
// 若订单没有结束时间则更新订单的结束时间
TransactionBill data = new TransactionBill();
data.setFinished(true);
if (data.getSuitEndTime() == null) {
if (bill.getSuitEndTime() == null) {
data.setSuitEndTime(LocalDateTime.now());
}
TransactionBillQuery query = new TransactionBillQuery();
@ -1915,15 +1930,16 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
query.setStatusList(TransactionBillStatus.payedOrder());
query.setBillId(bill.getBillId());
int rows = this.updateByQuery(data, query);
ServiceUtil.assertion(rows != 1, "订单%s的流程状态已发生变化请稍后重试", bill.getBillNo());
if (rows == 1 && bill.getBonusList() != null) {
// 过滤未出账的分成
if (bill.getBonusList() != null) {
// 过滤没有预计支付时间的待分成
List<BonusVO> waitDivideBonusList = bill.getBonusList().stream()
.filter(item -> BonusStatus.UN_DIVIDEND.getStatus().equals(item.getStatus()))
.filter(item -> BonusStatus.WAIT_DIVIDE.getStatus().equals(item.getStatus()) && item.getPrePayTime() == null)
.collect(Collectors.toList());
if (CollectionUtils.isNotEmptyElement(waitDivideBonusList)) {
// 出账
bonusService.partBonus(bill.getBonusList(), bill.getMoney());
// 预支付
bonusService.prePay(bill.getBonusList());
}
}

View File

@ -229,8 +229,8 @@ public class VipOrderServiceImpl implements VipOrderService, AfterPay, AfterRefu
int insertBonus = bonusService.batchInsert(bonusList);
ServiceUtil.assertion(insertBonus != bonusList.size(), "创建分成失败");
// 分配金额
int part = bonusService.partBonus(bonusList, order.getAmount());
// 预分成
int part = bonusService.prePay(bonusList);
ServiceUtil.assertion(part != bonusList.size(), "分配分成失败");
}

View File

@ -4,6 +4,7 @@ import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import com.ruoyi.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -130,12 +131,13 @@ public class BillMonitorTask {
/**
* TODO 监控订单
*/
public void monitor() {
public void monitor(String startTime) {
// 查询已结束但未进行流程的订单
TransactionBillQuery query = new TransactionBillQuery();
query.setType(TransactionBillType.RECHARGE.getType());
query.setIsFinished(true);
query.setFinished(false);
query.setCreateTimeStart(DateUtils.toLocalDateTime(startTime));
query.setStatusList(TransactionBillStatus.payedOrder());
List<TransactionBillVO> list = transactionBillService.selectSmTransactionBillList(query);
@ -149,7 +151,7 @@ public class BillMonitorTask {
for (TransactionBillVO bill : list) {
try {
transactionBillService.handleFinished(bill);
transactionBillService.handleFinishedBonus(bill);
} catch (Exception e) {
log.warn("处理已结束订单{}出错:{}", bill.getBillNo(), e.getMessage());
}