init
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
package com.tailbet.service.impl;
|
||||
|
||||
import com.tailbet.model.entity.RedPacket;
|
||||
import com.tailbet.model.entity.RedPacketRecv;
|
||||
import com.tailbet.model.entity.User;
|
||||
import com.tailbet.mapper.RedPacketMapper;
|
||||
import com.tailbet.mapper.RedPacketRecvMapper;
|
||||
import com.tailbet.mapper.UserMapper;
|
||||
import com.tailbet.mapper.GameRoundMapper;
|
||||
import com.tailbet.service.IRedPacketService;
|
||||
import com.tailbet.service.IPointsService;
|
||||
import com.tailbet.service.IAuditService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 红包Service实现
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class RedPacketServiceImpl implements IRedPacketService {
|
||||
|
||||
private final RedPacketMapper redPacketMapper;
|
||||
private final RedPacketRecvMapper redPacketRecvMapper;
|
||||
private final UserMapper userMapper;
|
||||
private final GameRoundMapper gameRoundMapper;
|
||||
private final IPointsService pointsService;
|
||||
private final IAuditService auditService;
|
||||
|
||||
/**
|
||||
* 发红包
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public RedPacket sendRp(Long userId, Long groupId, BigDecimal totalAmount,
|
||||
Integer totalCount, Long roundId) {
|
||||
User user = userMapper.selectById(userId);
|
||||
if (user == null) {
|
||||
throw new RuntimeException("用户不存在");
|
||||
}
|
||||
|
||||
// 扣积分
|
||||
boolean success = pointsService.subPoints(userId, totalAmount.longValue(),
|
||||
IPointsService.TYPE_RP_SEND, null, null, "发送红包");
|
||||
if (!success) {
|
||||
throw new RuntimeException("余额不足");
|
||||
}
|
||||
|
||||
// 创建红包
|
||||
RedPacket rp = new RedPacket();
|
||||
rp.setUserId(userId);
|
||||
rp.setGroupId(groupId);
|
||||
rp.setRoundId(roundId);
|
||||
rp.setTotalAmount(totalAmount);
|
||||
rp.setTotalCount(totalCount);
|
||||
rp.setRemainAmount(totalAmount);
|
||||
rp.setRemainCount(totalCount);
|
||||
rp.setStatus(STATUS_ONGOING);
|
||||
rp.setCreateTime(LocalDateTime.now());
|
||||
|
||||
// 判断红包类型
|
||||
if (roundId != null) {
|
||||
rp.setType(TYPE_GAME);
|
||||
} else {
|
||||
rp.setType(TYPE_RANDOM);
|
||||
}
|
||||
|
||||
redPacketMapper.insert(rp);
|
||||
|
||||
// 审计日志
|
||||
auditService.log(groupId, roundId, userId, "RP_SEND",
|
||||
String.format("{\"rpId\":%d,\"amount\":%s,\"count\":%d}",
|
||||
rp.getId(), totalAmount, totalCount));
|
||||
|
||||
return rp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 领红包
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public RedPacketRecv receiveRp(Long rpId, Long userId) {
|
||||
RedPacket rp = redPacketMapper.selectById(rpId);
|
||||
if (rp == null) {
|
||||
throw new RuntimeException("红包不存在");
|
||||
}
|
||||
if (rp.getStatus() != STATUS_ONGOING) {
|
||||
throw new RuntimeException("红包已领完");
|
||||
}
|
||||
|
||||
// 检查是否已领取
|
||||
RedPacketRecv existing = redPacketRecvMapper.selectOne(new LambdaQueryWrapper<RedPacketRecv>()
|
||||
.eq(RedPacketRecv::getRpId, rpId)
|
||||
.eq(RedPacketRecv::getUserId, userId));
|
||||
if (existing != null) {
|
||||
throw new RuntimeException("已领取过该红包");
|
||||
}
|
||||
|
||||
// 计算领取金额
|
||||
BigDecimal amount = calculateReceiveAmount(rp);
|
||||
|
||||
// 更新红包
|
||||
rp.setRemainAmount(rp.getRemainAmount().subtract(amount));
|
||||
rp.setRemainCount(rp.getRemainCount() - 1);
|
||||
if (rp.getRemainCount() <= 0) {
|
||||
rp.setStatus(STATUS_FINISHED);
|
||||
}
|
||||
redPacketMapper.updateById(rp);
|
||||
|
||||
// 加积分
|
||||
pointsService.addPoints(userId, amount.longValue(),
|
||||
IPointsService.TYPE_RP_RECV, String.valueOf(rpId), null, "领取红包");
|
||||
|
||||
// 记录领取
|
||||
RedPacketRecv recv = new RedPacketRecv();
|
||||
recv.setRpId(rpId);
|
||||
recv.setUserId(userId);
|
||||
recv.setAmount(amount);
|
||||
recv.setCreateTime(LocalDateTime.now());
|
||||
redPacketRecvMapper.insert(recv);
|
||||
|
||||
// 审计日志
|
||||
auditService.log(rp.getGroupId(), rp.getRoundId(), userId, "RP_RECV",
|
||||
String.format("{\"rpId\":%d,\"amount\":%s}", rpId, amount));
|
||||
|
||||
return recv;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算领取金额
|
||||
*/
|
||||
@Override
|
||||
public BigDecimal calculateReceiveAmount(RedPacket rp) {
|
||||
if (rp.getRemainCount() <= 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
// 如果是游戏红包且有目标尾数,则需要控制手气王
|
||||
// 简化实现:随机分配
|
||||
Random random = new Random();
|
||||
if (rp.getRemainCount() == 1) {
|
||||
// 最后一个,拿剩余全部
|
||||
return rp.getRemainAmount();
|
||||
}
|
||||
|
||||
// 随机金额,最小0.01
|
||||
double min = 0.01;
|
||||
double max = rp.getRemainAmount().divide(BigDecimal.valueOf(rp.getRemainCount()), 2, RoundingMode.HALF_UP).doubleValue() * 2;
|
||||
double amount = min + (max - min) * random.nextDouble();
|
||||
return BigDecimal.valueOf(amount).setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取红包详情
|
||||
*/
|
||||
@Override
|
||||
public RedPacket getById(Long rpId) {
|
||||
return redPacketMapper.selectById(rpId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取红包领取列表
|
||||
*/
|
||||
@Override
|
||||
public List<RedPacketRecv> getReceives(Long rpId) {
|
||||
return redPacketRecvMapper.selectList(new LambdaQueryWrapper<RedPacketRecv>()
|
||||
.eq(RedPacketRecv::getRpId, rpId)
|
||||
.orderByAsc(RedPacketRecv::getCreateTime));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询红包记录
|
||||
*/
|
||||
@Override
|
||||
public Page<RedPacket> getRecords(Long userId, Integer pageNum, Integer pageSize) {
|
||||
Page<RedPacket> page = new Page<>(pageNum, pageSize);
|
||||
LambdaQueryWrapper<RedPacket> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(RedPacket::getUserId, userId)
|
||||
.orderByDesc(RedPacket::getCreateTime);
|
||||
return redPacketMapper.selectPage(page, wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找进行中的游戏红包
|
||||
*/
|
||||
@Override
|
||||
public RedPacket getOngoingGameRp(Long groupId) {
|
||||
return redPacketMapper.selectOne(new LambdaQueryWrapper<RedPacket>()
|
||||
.eq(RedPacket::getGroupId, groupId)
|
||||
.eq(RedPacket::getType, TYPE_GAME)
|
||||
.eq(RedPacket::getStatus, STATUS_ONGOING)
|
||||
.isNotNull(RedPacket::getRoundId));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user