临时提交

This commit is contained in:
墨大叔 2024-09-27 09:13:44 +08:00
parent d39a4a4171
commit f6b9d92c4e
10 changed files with 199 additions and 40 deletions

View File

@ -91,4 +91,12 @@ public class Bonus extends BaseEntity
@JsonView(JsonViewProfile.AppMch.class)
private LocalDateTime prePayTime;
@Excel(name = "已分成金额")
@ApiModelProperty("已分成金额")
private BigDecimal payedAmount;
@Excel(name = "待分成金额")
@ApiModelProperty("待分成金额")
private BigDecimal waitAmount;
}

View File

@ -97,9 +97,14 @@ public interface BonusMapper
List<ProvideBonusVO> selectProvideBonus(@Param("query") BonusProvideQuery query);
/**
* 增加退款金额
* 当未分成时退款
*/
int addRefundAmount(@Param("id") Long id, @Param("amount") BigDecimal amount);
int refundWhenWaitDivide(@Param("id") Long id, @Param("amount") BigDecimal amount);
/**
* 当已分成时退款
*/
int refundWhenDividend(@Param("id") Long id, @Param("amount") BigDecimal amount);
/**
* 按月查询

View File

@ -22,7 +22,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
sb.create_time,
sb.pay_time,
sb.dept_id,
sb.pre_pay_time
sb.pre_pay_time,
sb.payed_amount,
sb.wait_amount
<include refid="searchTables"/>
</sql>
@ -178,6 +180,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="payTime != null">pay_time,</if>
<if test="deptId != null">dept_id,</if>
<if test="prePayTime != null">pre_pay_time,</if>
<if test="payedAmount != null">payed_amount,</if>
<if test="waitAmount != null">wait_amount,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="billId != null">#{billId},</if>
@ -194,6 +198,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="payTime != null">#{payTime},</if>
<if test="deptId != null">#{deptId},</if>
<if test="prePayTime != null">#{prePayTime},</if>
<if test="payedAmount != null">#{payedAmount},</if>
<if test="waitAmount != null">#{waitAmount},</if>
</trim>
</insert>
@ -249,11 +255,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach>
</insert>
<insert id="addRefundAmount">
<update id="refundWhenWaitDivide">
update ss_bonus
set refund_amount = refund_amount + #{amount}
where id = #{id} and amount >= refund_amount + #{amount}
</insert>
set refund_amount = refund_amount + #{amount},
wait_amount = wait_amount - #{amount}
where id = #{id} and wait_amount >= #{amount} and status = '2' and amount >= refund_amount + #{amount}
</update>
<update id="refundWhenDividend">
update ss_bonus
set refund_amount = refund_amount + #{amount},
payed_amount = payed_amount - #{amount}
where id = #{id} and payed_amount >= #{amount} and status = '3' and amount >= refund_amount + #{amount}
</update>
<update id="updateBonus" parameterType="Bonus">
update ss_bonus
@ -319,6 +333,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="data.payTime != null">pay_time = #{data.payTime},</if>
<if test="data.deptId != null">dept_id = #{data.deptId},</if>
<if test="data.prePayTime != null">pre_pay_time = #{data.prePayTime},</if>
<if test="data.payedAmount != null">payed_amount = #{data.payedAmount},</if>
<if test="data.waitAmount != null">wait_amount = #{data.waitAmount},</if>
</sql>
<delete id="deleteBonusById" parameterType="Long">

View File

@ -105,9 +105,14 @@ public interface BonusService
List<ProvideBonusVO> selectProvideBonus(BonusProvideQuery query);
/**
* 增加已退款金额
* 当未分成时退款
*/
int addRefundAmount(Long id, BigDecimal amount);
int refundWhenWaitDivide(Long id, BigDecimal amount);
/**
* 当已分成时退款
*/
int refundWhenDividend(Long id, BigDecimal amount);
/**
* 数据隔离过滤
@ -123,4 +128,5 @@ public interface BonusService
* 按日查询分成
*/
List<BonusDailyAmountVO> selectDailyAmount(BonusQuery query);
}

View File

@ -26,7 +26,6 @@ import com.ruoyi.ss.store.service.StoreService;
import com.ruoyi.ss.user.domain.SmUserVo;
import com.ruoyi.ss.user.service.ISmUserService;
import com.ruoyi.ss.user.service.UserAssembler;
import com.ruoyi.system.domain.enums.config.ConfigKey;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysDeptService;
import org.springframework.beans.factory.annotation.Autowired;
@ -210,6 +209,7 @@ public class BonusServiceImpl implements BonusService
for (BonusVO bonus : bonusList) {
BigDecimal amount = money.multiply(bonus.getPoint()).divide(decimal100, 2, RoundingMode.HALF_UP);
bonus.setAmount(amount);
bonus.setWaitAmount(amount);
bonus.setStatus(BonusStatus.WAIT_DIVIDE.getStatus());
// 预计分成时间
if (BonusArrivalType.userList().contains(bonus.getArrivalType())) {
@ -258,12 +258,21 @@ public class BonusServiceImpl implements BonusService
}
@Override
public int addRefundAmount(Long id, BigDecimal amount) {
public int refundWhenWaitDivide(Long id, BigDecimal amount) {
if (id == null) {
return 0;
}
ServiceUtil.assertion(amount.compareTo(BigDecimal.ZERO) < 0, "退款金额必须大于0");
return bonusMapper.addRefundAmount(id, amount);
return bonusMapper.refundWhenWaitDivide(id, amount);
}
@Override
public int refundWhenDividend(Long id, BigDecimal amount) {
if (id == null) {
return 0;
}
ServiceUtil.assertion(amount.compareTo(BigDecimal.ZERO) < 0, "退款金额必须大于0");
return bonusMapper.refundWhenDividend(id, amount);
}
@Override

View File

@ -20,4 +20,15 @@ public interface TransactionAssembler {
* 拼接套餐剩余时长/度数
*/
void assembleSuitSurplus(List<TransactionBillVO> list);
/**
* 拼接分成信息
*/
void assembleBonusList(TransactionBillVO bill);
/**
* 拼接分成信息
* @param list
*/
void assembleBonusList(List<TransactionBillVO> list);
}

View File

@ -15,6 +15,7 @@ import com.ruoyi.ss.transactionBill.domain.TransactionBillQuery;
import com.ruoyi.ss.transactionBill.domain.bo.PaySuccessBO;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillStatus;
import com.ruoyi.ss.transactionBill.domain.vo.TransactionBillVO;
import com.ruoyi.ss.transactionBill.service.TransactionAssembler;
import com.ruoyi.ss.transactionBill.service.TransactionBillService;
import com.ruoyi.ss.user.service.ISmUserService;
import org.springframework.beans.factory.annotation.Autowired;
@ -47,6 +48,9 @@ public class RechargePayHandler implements AfterPay, AfterRefund {
@Autowired
private BonusService bonusService;
@Autowired
private TransactionAssembler transactionAssembler;
@Override
public int onPaySuccess(PayBillVO payBill) {
TransactionBillVO bill = transactionBillService.selectSmTransactionBillByBillId(payBill.getBstId());
@ -57,6 +61,8 @@ public class RechargePayHandler implements AfterPay, AfterRefund {
PaySuccessBO bo = new PaySuccessBO();
bo.setOrder(bill);
bo.setPayBill(payBill);
// 拼接分成列表
transactionAssembler.assembleBonusList(bill);
if (SuitFeeType.singleList().contains(bill.getSuitFeeType())) {
return transactionBillService.rechargeSuccess(bo);
@ -93,9 +99,6 @@ public class RechargePayHandler implements AfterPay, AfterRefund {
int update = transactionBillService.updateByQuery(data, query);
ServiceUtil.assertion(update != 1, "修改订单状态失败");
// 商户余额增加
// userService.addBalance(order.getMchId(), order.getArrivalAmount(), StringUtils.format("分时段订单%s", order.getBillNo()), RecordBalanceBstType.RECHARGE, order.getBillId());
// 处理分成
bonusService.partBonus(order.getBonusList(), order.getMoney());

View File

@ -1,6 +1,10 @@
package com.ruoyi.ss.transactionBill.service.impl;
import com.github.pagehelper.PageHelper;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.ss.bonus.domain.BonusQuery;
import com.ruoyi.ss.bonus.domain.BonusVO;
import com.ruoyi.ss.bonus.service.BonusService;
import com.ruoyi.ss.channel.domain.Channel;
import com.ruoyi.ss.channel.domain.ChannelQuery;
import com.ruoyi.ss.channel.domain.ChannelVO;
@ -16,6 +20,7 @@ import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@ -31,6 +36,9 @@ public class TransactionAssemblerImpl implements TransactionAssembler {
@Autowired
private ChannelService channelService;
@Autowired
private BonusService bonusService;
/**
* 拼接渠道名称
*
@ -82,4 +90,36 @@ public class TransactionAssemblerImpl implements TransactionAssembler {
}
}
}
@Override
public void assembleBonusList(TransactionBillVO bill) {
if (bill == null) {
return;
}
this.assembleBonusList(Collections.singletonList(bill));
}
@Override
public void assembleBonusList(List<TransactionBillVO> list) {
if (CollectionUtils.isEmptyElement(list)) {
return;
}
PageHelper.orderBy(" arrival_type desc");
BonusQuery query = new BonusQuery();
query.setBillIds(CollectionUtils.map(list, TransactionBillVO::getBillId));
Map<Long, List<BonusVO>> group = bonusService.selectBonusList(query)
.stream().collect(Collectors.groupingBy(BonusVO::getBillId));
for (TransactionBillVO bill : list) {
List<BonusVO> bonusList = group.get(bill.getBillId());
if (CollectionUtils.isNotEmpty(bonusList)) {
bill.setBonusList(bonusList);
} else {
bill.setBonusList(Collections.emptyList());
}
}
}
}

View File

@ -12,6 +12,9 @@ import com.ruoyi.iot.domain.response.CommandResponse;
import com.ruoyi.iot.service.IotService;
import com.ruoyi.ss.account.domain.AccountVO;
import com.ruoyi.ss.bonus.domain.Bonus;
import com.ruoyi.ss.bonus.domain.BonusVO;
import com.ruoyi.ss.bonus.domain.enums.BonusArrivalType;
import com.ruoyi.ss.bonus.domain.enums.BonusStatus;
import com.ruoyi.ss.bonus.service.BonusConverter;
import com.ruoyi.ss.bonus.service.BonusService;
import com.ruoyi.ss.channel.domain.ChannelVO;
@ -29,13 +32,10 @@ import com.ruoyi.ss.payBill.domain.enums.PayBillBstType;
import com.ruoyi.ss.payBill.domain.vo.DoPayVO;
import com.ruoyi.ss.payBill.service.PayBillConverter;
import com.ruoyi.ss.payBill.service.PayBillService;
import com.ruoyi.ss.receiveBill.service.ReceiveBillService;
import com.ruoyi.ss.record.time.domain.enums.RecordTimeType;
import com.ruoyi.ss.record.time.service.IRecordTimeService;
import com.ruoyi.ss.record.time.service.RecordTimeConverter;
import com.ruoyi.ss.recordBalance.domain.enums.RecordBalanceBstType;
import com.ruoyi.ss.refund.service.RefundConverter;
import com.ruoyi.ss.refund.service.RefundService;
import com.ruoyi.ss.store.domain.StoreVo;
import com.ruoyi.ss.suit.domain.SuitVO;
import com.ruoyi.ss.suit.domain.enums.SuitFeeMode;
@ -51,10 +51,7 @@ import com.ruoyi.ss.transactionBill.domain.vo.UserRechargeServiceVO;
import com.ruoyi.ss.transactionBill.domain.vo.UserWithdrawServiceVO;
import com.ruoyi.ss.transactionBill.domain.enums.*;
import com.ruoyi.ss.transactionBill.mapper.TransactionBillMapper;
import com.ruoyi.ss.transactionBill.service.TransactionBillConverter;
import com.ruoyi.ss.transactionBill.service.TransactionBillService;
import com.ruoyi.ss.transactionBill.service.TransactionBillValidator;
import com.ruoyi.ss.transactionBill.service.WithdrawValidator;
import com.ruoyi.ss.transactionBill.service.*;
import com.ruoyi.ss.transfer.domain.TransferVO;
import com.ruoyi.ss.transfer.interfaces.AfterTransfer;
import com.ruoyi.ss.transfer.service.TransferConverter;
@ -159,6 +156,9 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
@Autowired
private BonusService bonusService;
@Autowired
private TransactionAssembler transactionAssembler;
/**
* 查询充值记录
*
@ -1532,6 +1532,9 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
ServiceUtil.assertion(dto.getRefundAmount().compareTo(bill.getMoney()) > 0, "退款金额不允许大于订单金额");
ServiceUtil.assertion(!TransactionBillStatus.SUCCESS.getStatus().equals(bill.getStatus()), "当前订单状态不允许退款");
// 拼接分成列表
transactionAssembler.assembleBonusList(bill);
Integer result = transactionTemplate.execute(status -> {
// 修改订单状态
TransactionBill data = new TransactionBill();
@ -1542,16 +1545,16 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
int updateBill = this.updateByQuery(data, billQuery);
ServiceUtil.assertion(updateBill != 1, "退款时修改订单状态失败,订单状态已发生改变,请刷新后重试");
// 商户余额按照比例扣减
// 分成方余额按照比例扣减
// 按比例计算退款金额
BigDecimal refundAmount = dto.getRefundAmount();
BigDecimal refundRate = refundAmount.divide(bill.getMoney(), 2, RoundingMode.HALF_UP); // 退款金额比例
BigDecimal refundServiceAmount = bill.getServiceCharge().multiply(refundRate).setScale(2, RoundingMode.HALF_UP); // 退款的手续费
BigDecimal refundMchAmount = refundAmount.subtract(refundServiceAmount); // 退款的商户余额
userService.subtractBalance(bill.getMchId(), refundMchAmount, dto.getRefundReason(), RecordBalanceBstType.RECHARGE, bill.getBillId());
BigDecimal refundAmount = dto.getRefundAmount(); // 总退款金额
if (CollectionUtils.isNotEmptyElement(bill.getBonusList())) {
int updateRefundBonus = this.updateRefundBonus(bill.getBonusList(), refundAmount);
ServiceUtil.assertion(updateRefundBonus != bill.getBonusList().size(), "商户余额更新失败");
}
// 修改原订单的退款金额和退款手续费
int updateRefundAmount = this.addRefundAmount(bill.getBillId(), refundAmount, refundMchAmount, refundServiceAmount);
int updateRefundAmount = this.addRefundAmount(bill.getBillId(), refundAmount, refundAmount, BigDecimal.ZERO);
ServiceUtil.assertion(updateRefundAmount != 1, "修改原订单的退款金额和退款手续费失败");
// 发起退款
@ -1568,6 +1571,75 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
return result == null ? 0 : result;
}
/**
* 更新分成的退款金额
*/
private int updateRefundBonus(List<BonusVO> bonusList, BigDecimal refundAmount) {
if (CollectionUtils.isEmptyElement(bonusList)) {
return 0;
}
BigDecimal decimal100 = BigDecimal.valueOf(100);
// 构建退款列表
List<Bonus> refundList = new ArrayList<>(); // 退款的列表
BigDecimal dividedAmount = BigDecimal.ZERO; // 已分配金额
for (BonusVO bonus : bonusList) {
if (bonus == null) {
continue;
}
// 计算扣减金额
BigDecimal bonusRefundAmount = refundAmount.multiply(bonus.getPoint()).divide(decimal100, 2, RoundingMode.HALF_UP);
bonus.setRefundAmount(bonusRefundAmount);
refundList.add(bonus);
dividedAmount = dividedAmount.add(bonusRefundAmount);
}
// 平台吃掉误差
Bonus platform = refundList.stream().filter(bonus -> bonus.getArrivalType().equals(BonusArrivalType.PLATFORM.getType())).findFirst().orElse(null);
ServiceUtil.assertion(platform == null, "平台不存在");
if (dividedAmount.compareTo(refundAmount) != 0) {
BigDecimal subtract = refundAmount.subtract(dividedAmount); // 误差值
platform.setRefundAmount(platform.getRefundAmount().add(subtract));
}
BigDecimal sum = refundList.stream().map(Bonus::getRefundAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
ServiceUtil.assertion(sum.compareTo(refundAmount) != 0, "退款金额分配出错");
Integer result = transactionTemplate.execute(status -> {
int update = 0;
for (Bonus bonus : refundList) {
// 根据分成状态来决定是否扣减用户余额给用户加余额前需要判断分成状态是否为待分成
if (BonusStatus.WAIT_DIVIDE.getStatus().equals(bonus.getStatus())) {
// 待分成扣减待分成金额加上退款金额
int refund = bonusService.refundWhenWaitDivide(bonus.getId(), bonus.getRefundAmount());
ServiceUtil.assertion(refund != 1, "可退款金额不足");
} else if (BonusStatus.DIVIDEND.getStatus().equals(bonus.getStatus())) {
// 已分成扣减已分成金额加上退款金额
int refund = bonusService.refundWhenDividend(bonus.getId(), bonus.getRefundAmount());
ServiceUtil.assertion(refund != 1, "可退款金额不足");
// 扣减分成方余额
if (BonusArrivalType.userList().contains(bonus.getArrivalType())) {
userService.subtractBalance(bonus.getArrivalId(), bonus.getRefundAmount(), String.format("订单退款:%s", bonus.getBillNo()), RecordBalanceBstType.RECHARGE, bonus.getBillId());
} else if (BonusArrivalType.deptList().contains(bonus.getArrivalType())) {
// deptService.subtractBalance(bonus.getArrivalId(), bonus.getRefundAmount(), String.format("订单退款:%s", bonus.getBillNo()), RecordBalanceBstType.RECHARGE, bonus.getBillId());
}
}
update++;
}
return update;
});
return result == null ? 0 : result;
}
@Override
public int updateByQuery(TransactionBill data, TransactionBillQuery query) {
if (query == null) {

View File

@ -44,15 +44,4 @@ public class AppTimeBillController extends BaseController {
return toAjax(timeBillService.close(bill));
}
@ApiOperation("支付订单")
@PutMapping("/pay")
public AjaxResult pay(@RequestBody @Validated TimeBillPayDTO dto) {
TimeBillVO bill = timeBillService.selectTimeBillByBillId(dto.getBillId());
if (!timeBillValidator.canPay(bill, getUserId())) {
return error("您无权支付该订单");
}
dto.setChannelId(TransactionBillPayType.WECHAT.getType());
return success(timeBillService.pay(dto));
}
}