抽奖 ticket迁移

This commit is contained in:
tianfeng 2025-10-21 11:38:19 +08:00
parent dddf6b1d4c
commit da9819085f
3 changed files with 160 additions and 85 deletions

View File

@ -1,16 +1,10 @@
package com.red.circle.other.app.inner.endpoint.activity; package com.red.circle.other.app.inner.endpoint.activity;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.red.circle.framework.dto.ResultResponse; import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.other.infra.database.rds.entity.activity.LotteryTicket; import com.red.circle.other.app.inner.service.activity.LotteryTicketClientService;
import com.red.circle.other.infra.database.rds.entity.activity.LotteryTicketRecord;
import com.red.circle.other.infra.database.rds.service.activity.LotteryTicketRecordService;
import com.red.circle.other.infra.database.rds.service.activity.LotteryTicketService;
import com.red.circle.other.inner.endpoint.activity.api.LotteryTicketClientApi; import com.red.circle.other.inner.endpoint.activity.api.LotteryTicketClientApi;
import java.util.List;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@ -27,95 +21,24 @@ import org.springframework.web.bind.annotation.RestController;
@RequiredArgsConstructor @RequiredArgsConstructor
public class LotteryTicketClientEndpoint implements LotteryTicketClientApi { public class LotteryTicketClientEndpoint implements LotteryTicketClientApi {
private final LotteryTicketService lotteryTicketService; private final LotteryTicketClientService lotteryTicketClientService;
private final LotteryTicketRecordService lotteryTicketRecordService;
@Override @Override
public ResultResponse<Integer> getUserTicketCount(Long userId) { public ResultResponse<Integer> getUserTicketCount(Long userId) {
List<LotteryTicket> tickets = lotteryTicketService.query() Integer count = lotteryTicketClientService.getUserTicketCount(userId);
.eq(LotteryTicket::getUserId, userId) return ResultResponse.success(count);
.eq(LotteryTicket::getStatus, 1)
.gt(LotteryTicket::getRemainingCount, 0)
.list();
int totalCount = tickets.stream()
.mapToInt(LotteryTicket::getRemainingCount)
.sum();
return ResultResponse.success(totalCount);
} }
@Override @Override
@Transactional(rollbackFor = Exception.class)
public ResultResponse<Boolean> deductTicket(Long userId, Integer count) { public ResultResponse<Boolean> deductTicket(Long userId, Integer count) {
List<LotteryTicket> tickets = lotteryTicketService.query() Boolean result = lotteryTicketClientService.deductTicket(userId, count);
.eq(LotteryTicket::getUserId, userId) return ResultResponse.success(result);
.eq(LotteryTicket::getStatus, 1)
.gt(LotteryTicket::getRemainingCount, 0)
.orderByAsc(LotteryTicket::getExpireTime)
.list();
int totalRemaining = tickets.stream()
.mapToInt(LotteryTicket::getRemainingCount)
.sum();
if (totalRemaining < count) {
return ResultResponse.success(false);
}
int remaining = count;
for (LotteryTicket ticket : tickets) {
if (remaining <= 0) {
break;
}
int deduct = Math.min(remaining, ticket.getRemainingCount());
LambdaUpdateWrapper<LotteryTicket> updateWrapper = new LambdaUpdateWrapper<LotteryTicket>()
.eq(LotteryTicket::getId, ticket.getId())
.setSql("used_count = used_count + " + deduct)
.setSql("remaining_count = remaining_count - " + deduct);
lotteryTicketService.update(updateWrapper);
// 记录使用
LotteryTicketRecord ticketRecord = new LotteryTicketRecord();
ticketRecord.setUserId(userId);
ticketRecord.setTicketId(ticket.getId());
ticketRecord.setChangeCount(-deduct);
ticketRecord.setChangeType(2); // 消耗
ticketRecord.setRemark("抽奖消耗");
lotteryTicketRecordService.save(ticketRecord);
remaining -= deduct;
}
return ResultResponse.success(true);
} }
@Override @Override
@Transactional(rollbackFor = Exception.class)
public ResultResponse<Boolean> addTicket(Long userId, Integer count, String source, String sourceId) { public ResultResponse<Boolean> addTicket(Long userId, Integer count, String source, String sourceId) {
LotteryTicket ticket = new LotteryTicket(); Boolean result = lotteryTicketClientService.addTicket(userId, count, source, sourceId);
ticket.setUserId(userId); return ResultResponse.success(result);
ticket.setTicketSource(source != null ? source : "SYSTEM");
ticket.setSourceId(sourceId);
ticket.setTotalCount(count);
ticket.setUsedCount(0);
ticket.setRemainingCount(count);
ticket.setStatus(1);
lotteryTicketService.save(ticket);
// 记录发放
LotteryTicketRecord ticketRecord = new LotteryTicketRecord();
ticketRecord.setUserId(userId);
ticketRecord.setTicketId(ticket.getId());
ticketRecord.setChangeCount(count);
ticketRecord.setChangeType(1); // 发放
ticketRecord.setRemark("系统发放");
lotteryTicketRecordService.save(ticketRecord);
return ResultResponse.success(true);
} }
} }

View File

@ -0,0 +1,39 @@
package com.red.circle.other.app.inner.service.activity;
/**
* 抽奖券Client服务.
*
* @author system
* @since 2025-10-21
*/
public interface LotteryTicketClientService {
/**
* 获取用户抽奖券数量.
*
* @param userId 用户ID
* @return 抽奖券数量
*/
Integer getUserTicketCount(Long userId);
/**
* 扣减抽奖券.
*
* @param userId 用户ID
* @param count 扣减数量
* @return 是否成功
*/
Boolean deductTicket(Long userId, Integer count);
/**
* 增加抽奖券.
*
* @param userId 用户ID
* @param count 增加数量
* @param source 来源
* @param sourceId 来源ID
* @return 是否成功
*/
Boolean addTicket(Long userId, Integer count, String source, String sourceId);
}

View File

@ -0,0 +1,113 @@
package com.red.circle.other.app.inner.service.activity.impl;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.red.circle.other.app.inner.service.activity.LotteryTicketClientService;
import com.red.circle.other.infra.database.rds.entity.activity.LotteryTicket;
import com.red.circle.other.infra.database.rds.entity.activity.LotteryTicketRecord;
import com.red.circle.other.infra.database.rds.service.activity.LotteryTicketRecordService;
import com.red.circle.other.infra.database.rds.service.activity.LotteryTicketService;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 抽奖券Client服务实现.
*
* @author system
* @since 2025-10-21
*/
@Service
@RequiredArgsConstructor
public class LotteryTicketClientServiceImpl implements LotteryTicketClientService {
private final LotteryTicketService lotteryTicketService;
private final LotteryTicketRecordService lotteryTicketRecordService;
@Override
public Integer getUserTicketCount(Long userId) {
List<LotteryTicket> tickets = lotteryTicketService.query()
.eq(LotteryTicket::getUserId, userId)
.eq(LotteryTicket::getStatus, 1)
.gt(LotteryTicket::getRemainingCount, 0)
.list();
return tickets.stream()
.mapToInt(LotteryTicket::getRemainingCount)
.sum();
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean deductTicket(Long userId, Integer count) {
List<LotteryTicket> tickets = lotteryTicketService.query()
.eq(LotteryTicket::getUserId, userId)
.eq(LotteryTicket::getStatus, 1)
.gt(LotteryTicket::getRemainingCount, 0)
.orderByAsc(LotteryTicket::getExpireTime)
.list();
int totalRemaining = tickets.stream()
.mapToInt(LotteryTicket::getRemainingCount)
.sum();
if (totalRemaining < count) {
return false;
}
int remaining = count;
for (LotteryTicket ticket : tickets) {
if (remaining <= 0) {
break;
}
int deduct = Math.min(remaining, ticket.getRemainingCount());
LambdaUpdateWrapper<LotteryTicket> updateWrapper = new LambdaUpdateWrapper<LotteryTicket>()
.eq(LotteryTicket::getId, ticket.getId())
.setSql("used_count = used_count + " + deduct)
.setSql("remaining_count = remaining_count - " + deduct);
lotteryTicketService.update(updateWrapper);
// 记录使用
LotteryTicketRecord ticketRecord = new LotteryTicketRecord();
ticketRecord.setUserId(userId);
ticketRecord.setTicketId(ticket.getId());
ticketRecord.setChangeCount(-deduct);
ticketRecord.setChangeType(2); // 消耗
ticketRecord.setRemark("抽奖消耗");
lotteryTicketRecordService.save(ticketRecord);
remaining -= deduct;
}
return true;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean addTicket(Long userId, Integer count, String source, String sourceId) {
LotteryTicket ticket = new LotteryTicket();
ticket.setUserId(userId);
ticket.setTicketSource(source != null ? source : "SYSTEM");
ticket.setSourceId(sourceId);
ticket.setTotalCount(count);
ticket.setUsedCount(0);
ticket.setRemainingCount(count);
ticket.setStatus(1);
lotteryTicketService.save(ticket);
// 记录发放
LotteryTicketRecord ticketRecord = new LotteryTicketRecord();
ticketRecord.setUserId(userId);
ticketRecord.setTicketId(ticket.getId());
ticketRecord.setChangeCount(count);
ticketRecord.setChangeType(1); // 发放
ticketRecord.setRemark("系统发放");
lotteryTicketRecordService.save(ticketRecord);
return true;
}
}