新增房间奖励查询和领取功能
This commit is contained in:
parent
a021eb8de9
commit
d063ce5f0d
@ -53,12 +53,14 @@ public enum ActivityErrorCode implements IResponseErrorCode {
|
|||||||
/**
|
/**
|
||||||
* 在无效的时间段内操作.
|
* 在无效的时间段内操作.
|
||||||
*/
|
*/
|
||||||
INVALID_TIME_OPERATION_ERROR(9507, "Please operate within the specified time period");
|
INVALID_TIME_OPERATION_ERROR(9507, "Please operate within the specified time period"),
|
||||||
/**
|
|
||||||
* 活动房间未配置.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
AWARD_RECEIVED(9508, "The reward has been received, please do not receive it again"),
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
private final Integer code;
|
private final Integer code;
|
||||||
private final String message;
|
private final String message;
|
||||||
|
|
||||||
|
|||||||
@ -3,11 +3,16 @@ package com.red.circle.other.adapter.app.activity.room;
|
|||||||
import com.red.circle.common.business.dto.cmd.app.AppRoomIdCmd;
|
import com.red.circle.common.business.dto.cmd.app.AppRoomIdCmd;
|
||||||
import com.red.circle.framework.web.controller.BaseController;
|
import com.red.circle.framework.web.controller.BaseController;
|
||||||
import com.red.circle.other.app.dto.clientobject.activity.RoomContributionCountCO;
|
import com.red.circle.other.app.dto.clientobject.activity.RoomContributionCountCO;
|
||||||
|
import com.red.circle.other.app.dto.clientobject.activity.room.RoomRewardInfoCO;
|
||||||
|
import com.red.circle.other.app.dto.cmd.activity.room.ReceiveRoomRewardCmd;
|
||||||
import com.red.circle.other.app.service.activity.RoomContributionActivityService;
|
import com.red.circle.other.app.service.activity.RoomContributionActivityService;
|
||||||
|
import com.red.circle.other.app.service.activity.RoomRewardService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,6 +31,7 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
public class RoomContributionActivityRestController extends BaseController {
|
public class RoomContributionActivityRestController extends BaseController {
|
||||||
|
|
||||||
private final RoomContributionActivityService roomContributionActivityService;
|
private final RoomContributionActivityService roomContributionActivityService;
|
||||||
|
private final RoomRewardService roomRewardService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据.
|
* 数据.
|
||||||
@ -40,16 +46,44 @@ public class RoomContributionActivityRestController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 领取奖励.
|
* 领取奖励(已废弃,请使用 /room-reward/receive).
|
||||||
*
|
*
|
||||||
* @eo.name 领取奖励
|
* @deprecated 请使用新接口 /room-reward/receive
|
||||||
|
* @eo.name 领取奖励(已废弃)
|
||||||
* @eo.url /receive
|
* @eo.url /receive
|
||||||
* @eo.method post
|
* @eo.method post
|
||||||
* @eo.request-type json
|
* @eo.request-type json
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
@PostMapping("/receive")
|
@PostMapping("/receive")
|
||||||
public void receive(AppRoomIdCmd cmd) {
|
public void receive(AppRoomIdCmd cmd) {
|
||||||
roomContributionActivityService.receive(cmd);
|
roomContributionActivityService.receive(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询房间奖励信息.
|
||||||
|
*
|
||||||
|
* @eo.name 查询房间奖励信息
|
||||||
|
* @eo.url /room-reward/info
|
||||||
|
* @eo.method get
|
||||||
|
* @eo.request-type formdata
|
||||||
|
*/
|
||||||
|
@GetMapping("/room-reward/info")
|
||||||
|
public RoomRewardInfoCO getRoomRewardInfo(@RequestParam String roomId) {
|
||||||
|
return roomRewardService.getRoomRewardInfo(roomId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 领取房间奖励房主收入.
|
||||||
|
*
|
||||||
|
* @eo.name 领取房主收入
|
||||||
|
* @eo.url /room-reward/receive
|
||||||
|
* @eo.method post
|
||||||
|
* @eo.request-type json
|
||||||
|
*/
|
||||||
|
@PostMapping("/room-reward/receive")
|
||||||
|
public void receiveRoomReward(@RequestBody ReceiveRoomRewardCmd cmd) {
|
||||||
|
roomRewardService.receiveOwnerIncome(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,11 +50,6 @@ public class RoomContributionActivityReceiveAwardCmdExe {
|
|||||||
private final RoomContributionActivityCountService roomContributionActivityCountService;
|
private final RoomContributionActivityCountService roomContributionActivityCountService;
|
||||||
|
|
||||||
public void execute(AppExtCommand cmd) {
|
public void execute(AppExtCommand cmd) {
|
||||||
|
|
||||||
ResponseAssert.isTrue(ActivityErrorCode.INVALID_TIME_OPERATION_ERROR,
|
|
||||||
Objects.equals(ZonedDateTimeAsiaRiyadhUtils.getThisMonday(),
|
|
||||||
ZonedDateTimeAsiaRiyadhUtils.nowDateToInt()));
|
|
||||||
|
|
||||||
// 防止重复触发领取 3分钟后可重试领取
|
// 防止重复触发领取 3分钟后可重试领取
|
||||||
ResponseAssert.isTrue(UserErrorCode.AWARD_RECEIVED, redisService.setIfAbsent(
|
ResponseAssert.isTrue(UserErrorCode.AWARD_RECEIVED, redisService.setIfAbsent(
|
||||||
GoldOrigin.ROOM_CONTRIBUTION_REWARD + ":" + cmd.getReqUserId(),
|
GoldOrigin.ROOM_CONTRIBUTION_REWARD + ":" + cmd.getReqUserId(),
|
||||||
@ -158,33 +153,6 @@ public class RoomContributionActivityReceiveAwardCmdExe {
|
|||||||
String userRegionCode =
|
String userRegionCode =
|
||||||
userRegionGateway.getRegionCode(cmd.getReqUserId());
|
userRegionGateway.getRegionCode(cmd.getReqUserId());
|
||||||
|
|
||||||
// if (isExistsRegion(List.of("NG1", "NG", "PH", "PH1"), userRegionCode)) {
|
|
||||||
//
|
|
||||||
// var historyIntegral = activityCounts.stream()
|
|
||||||
// .filter(activityCount -> activityCount.getDateNumber() < 20230501)
|
|
||||||
// .map(count -> ImmutablePair.of(count.getId(), count.getContributionValue()))
|
|
||||||
// .toList();
|
|
||||||
//
|
|
||||||
// if (CollectionUtils.isNotEmpty(historyIntegral)) {
|
|
||||||
// resultProps.put("history", roomContributionActivityCountService
|
|
||||||
// .listAvailableAmount(cmd.requireReqSysOriginEnum(),userRegionCode, historyIntegral,
|
|
||||||
// new BigDecimal("0.1")));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var newIntegral = activityCounts.stream()
|
|
||||||
// .filter(activityCount -> activityCount.getDateNumber() >= 20230501)
|
|
||||||
// .map(count -> ImmutablePair.of(count.getId(), count.getContributionValue()))
|
|
||||||
// .toList();
|
|
||||||
//
|
|
||||||
// if (CollectionUtils.isNotEmpty(newIntegral)) {
|
|
||||||
// resultProps.put("notHistory",
|
|
||||||
// roomContributionActivityCountService
|
|
||||||
// .listAvailableAmount(cmd.requireReqSysOriginEnum(),userRegionCode, newIntegral, ratio));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return resultProps;
|
|
||||||
// }
|
|
||||||
|
|
||||||
resultProps.put("notHistory",
|
resultProps.put("notHistory",
|
||||||
roomContributionActivityCountService
|
roomContributionActivityCountService
|
||||||
.listAvailableAmount(cmd.requireReqSysOriginEnum(),userRegionCode,
|
.listAvailableAmount(cmd.requireReqSysOriginEnum(),userRegionCode,
|
||||||
|
|||||||
@ -0,0 +1,105 @@
|
|||||||
|
package com.red.circle.other.app.command.activity.room;
|
||||||
|
|
||||||
|
import com.red.circle.component.redis.service.RedisService;
|
||||||
|
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||||
|
import com.red.circle.framework.core.response.CommonErrorCode;
|
||||||
|
import com.red.circle.other.app.dto.cmd.activity.room.ReceiveRoomRewardCmd;
|
||||||
|
import com.red.circle.other.infra.database.mongo.entity.activity.RoomContributionActivityCount;
|
||||||
|
import com.red.circle.other.infra.database.mongo.service.activity.RoomContributionActivityCountService;
|
||||||
|
import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService;
|
||||||
|
import com.red.circle.other.inner.asserts.ActivityErrorCode;
|
||||||
|
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
|
||||||
|
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
|
||||||
|
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
|
||||||
|
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||||
|
import org.springframework.data.mongodb.core.query.Criteria;
|
||||||
|
import org.springframework.data.mongodb.core.query.Query;
|
||||||
|
import org.springframework.data.mongodb.core.query.Update;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.DayOfWeek;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 领取房间奖励房主收入执行器
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2025-12-01
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ReceiveRoomRewardCmdExe {
|
||||||
|
|
||||||
|
private final WalletGoldClient walletGoldClient;
|
||||||
|
private final RoomProfileManagerService roomProfileManagerService;
|
||||||
|
private final RoomContributionActivityCountService roomContributionActivityCountService;
|
||||||
|
private final MongoTemplate mongoTemplate;
|
||||||
|
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void execute(ReceiveRoomRewardCmd cmd) {
|
||||||
|
Long userId = cmd.getReqUserId();
|
||||||
|
String roomId = cmd.getRoomId();
|
||||||
|
|
||||||
|
// 2. 校验用户是否是房主
|
||||||
|
Long userRoomId = roomProfileManagerService.getRoomId(userId);
|
||||||
|
ResponseAssert.isTrue(
|
||||||
|
CommonErrorCode.DATA_ERROR,
|
||||||
|
Objects.equals(userRoomId, Long.parseLong(roomId))
|
||||||
|
);
|
||||||
|
|
||||||
|
// 3. 查询上周数据
|
||||||
|
String lastWeekDateNumber = ZonedDateTimeAsiaRiyadhUtils.getLastWeekMonday().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||||
|
RoomContributionActivityCount lastWeekData = roomContributionActivityCountService
|
||||||
|
.findByRoomIdAndDateNumber(Long.parseLong(roomId), Integer.valueOf(lastWeekDateNumber))
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_RECORD_INFO, lastWeekData);
|
||||||
|
|
||||||
|
// 4. 校验是否已领取
|
||||||
|
ResponseAssert.isFalse(ActivityErrorCode.AWARD_RECEIVED,
|
||||||
|
Optional.ofNullable(lastWeekData.getReceived()).orElse(false));
|
||||||
|
|
||||||
|
// 5. 计算房主收入(流水 * ratio)
|
||||||
|
BigDecimal contributionValue = lastWeekData.getContributionValue();
|
||||||
|
ResponseAssert.notNull(CommonErrorCode.DATA_ERROR, contributionValue);
|
||||||
|
|
||||||
|
BigDecimal ratio = Optional.ofNullable(lastWeekData.getRatio()).orElse(new BigDecimal("0.05"));
|
||||||
|
|
||||||
|
BigDecimal ownerIncome = contributionValue.multiply(ratio);
|
||||||
|
|
||||||
|
ResponseAssert.isTrue(
|
||||||
|
CommonErrorCode.DATA_ERROR,
|
||||||
|
ownerIncome.compareTo(BigDecimal.ZERO) > 0
|
||||||
|
);
|
||||||
|
|
||||||
|
// 6. 调用钱包服务增加金币
|
||||||
|
walletGoldClient.changeBalance(GoldReceiptCmd.builder()
|
||||||
|
.appIncome()
|
||||||
|
.eventId(Long.parseLong(roomId))
|
||||||
|
.userId(userId)
|
||||||
|
.sysOrigin(cmd.getReqSysOrigin().getOrigin())
|
||||||
|
.origin(GoldOrigin.ROOM_CONTRIBUTION_REWARD)
|
||||||
|
.amount(ownerIncome)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
// 7. 更新received状态为true
|
||||||
|
Query query = new Query(Criteria.where("_id").is(lastWeekData.getId()));
|
||||||
|
Update update = new Update().set("received", true);
|
||||||
|
mongoTemplate.updateFirst(query, update, RoomContributionActivityCount.class);
|
||||||
|
|
||||||
|
log.info("房间奖励领取成功, userId={}, roomId={}, dateNumber={}, income={}",
|
||||||
|
userId, roomId, lastWeekDateNumber, ownerIncome);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,138 @@
|
|||||||
|
package com.red.circle.other.app.command.activity.room.query;
|
||||||
|
|
||||||
|
import com.red.circle.other.app.dto.clientobject.activity.room.RoomRewardInfoCO;
|
||||||
|
import com.red.circle.other.app.enums.RoomRewardLevelEnum;
|
||||||
|
import com.red.circle.other.infra.database.mongo.entity.activity.RoomContributionActivityCount;
|
||||||
|
import com.red.circle.other.infra.database.mongo.service.activity.RoomContributionActivityCountService;
|
||||||
|
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.*;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 房间奖励信息查询执行器
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2025-12-01
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RoomRewardInfoQryExe {
|
||||||
|
|
||||||
|
private final RoomContributionActivityCountService roomContributionActivityCountService;
|
||||||
|
|
||||||
|
public RoomRewardInfoCO execute(String roomId) {
|
||||||
|
RoomRewardInfoCO result = new RoomRewardInfoCO();
|
||||||
|
|
||||||
|
// 1. 计算倒计时
|
||||||
|
result.setCountdown(calculateCountdown());
|
||||||
|
|
||||||
|
// 2. 查询当前周数据
|
||||||
|
Integer currentWeekDateNumber = ZonedDateTimeAsiaRiyadhUtils.getThisMonday();
|
||||||
|
RoomContributionActivityCount currentWeek = findByRoomIdAndDateNumber(roomId, currentWeekDateNumber);
|
||||||
|
result.setCurrentProgress(buildCurrentProgress(currentWeek));
|
||||||
|
|
||||||
|
// 3. 查询上周数据
|
||||||
|
String lastWeekDateNumber = ZonedDateTimeAsiaRiyadhUtils.getLastWeekMonday().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||||
|
RoomContributionActivityCount lastWeek = findByRoomIdAndDateNumber(roomId, Integer.parseInt(lastWeekDateNumber));
|
||||||
|
result.setLastWeekProgress(buildLastWeekProgress(lastWeek));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算到下周一沙特时间0点的倒计时
|
||||||
|
*/
|
||||||
|
private RoomRewardInfoCO.CountdownCO calculateCountdown() {
|
||||||
|
ZonedDateTime now = ZonedDateTimeAsiaRiyadhUtils.now();
|
||||||
|
ZonedDateTime nextMondayZoned = now.plusDays(7 - (now.getDayOfWeek().getValue() - 1));
|
||||||
|
|
||||||
|
Duration duration = Duration.between(now, nextMondayZoned);
|
||||||
|
RoomRewardInfoCO.CountdownCO countdown = new RoomRewardInfoCO.CountdownCO();
|
||||||
|
countdown.setDays(duration.toDays());
|
||||||
|
countdown.setHours(duration.toHours());
|
||||||
|
countdown.setMinutes(duration.toMinutes());
|
||||||
|
countdown.setSeconds(duration.getSeconds());
|
||||||
|
|
||||||
|
return countdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据房间ID和日期查询数据
|
||||||
|
*/
|
||||||
|
private RoomContributionActivityCount findByRoomIdAndDateNumber(String roomId, Integer dateNumber) {
|
||||||
|
Long roomIdLong = Long.parseLong(roomId);
|
||||||
|
return roomContributionActivityCountService
|
||||||
|
.findByRoomIdAndDateNumber(roomIdLong, dateNumber)
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建当前周进度
|
||||||
|
*/
|
||||||
|
private RoomRewardInfoCO.CurrentProgressCO buildCurrentProgress(RoomContributionActivityCount data) {
|
||||||
|
RoomRewardInfoCO.CurrentProgressCO progress = new RoomRewardInfoCO.CurrentProgressCO();
|
||||||
|
|
||||||
|
if (data == null || data.getContributionValue() == null) {
|
||||||
|
progress.setAmount(0L);
|
||||||
|
progress.setLevel(null);
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
Long amount = data.getContributionValue().longValue();
|
||||||
|
progress.setAmount(amount);
|
||||||
|
|
||||||
|
RoomRewardLevelEnum level = RoomRewardLevelEnum.getLevelByAmount(amount);
|
||||||
|
progress.setLevel(level != null ? level.getLevel() : null);
|
||||||
|
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建上周进度
|
||||||
|
*/
|
||||||
|
private RoomRewardInfoCO.LastWeekProgressCO buildLastWeekProgress(RoomContributionActivityCount data) {
|
||||||
|
RoomRewardInfoCO.LastWeekProgressCO progress = new RoomRewardInfoCO.LastWeekProgressCO();
|
||||||
|
|
||||||
|
if (data == null || data.getContributionValue() == null) {
|
||||||
|
progress.setAmount(0L);
|
||||||
|
progress.setLevel(null);
|
||||||
|
progress.setOwnerIncome(0L);
|
||||||
|
progress.setOwnerIncomeReceived(false);
|
||||||
|
progress.setRewardCoins(0L);
|
||||||
|
progress.setRewardCoinsSent(false);
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
Long amount = data.getContributionValue().longValue();
|
||||||
|
progress.setAmount(amount);
|
||||||
|
|
||||||
|
// 计算等级
|
||||||
|
RoomRewardLevelEnum level = RoomRewardLevelEnum.getLevelByAmount(amount);
|
||||||
|
progress.setLevel(level != null ? level.getLevel() : null);
|
||||||
|
|
||||||
|
// 计算房主收入(流水 * ratio)
|
||||||
|
BigDecimal ratio = Optional.ofNullable(data.getRatio()).orElse(new BigDecimal("0.05"));
|
||||||
|
Long ownerIncome = data.getContributionValue().multiply(ratio).longValue();
|
||||||
|
progress.setOwnerIncome(ownerIncome);
|
||||||
|
|
||||||
|
// 是否已领取
|
||||||
|
progress.setOwnerIncomeReceived(Optional.ofNullable(data.getReceived()).orElse(false));
|
||||||
|
|
||||||
|
// 奖励金币
|
||||||
|
Long rewardCoins = level != null ? level.getRewardCoins() : 0L;
|
||||||
|
progress.setRewardCoins(rewardCoins);
|
||||||
|
|
||||||
|
// 奖励金币是否已发放
|
||||||
|
progress.setRewardCoinsSent(Optional.ofNullable(data.getRewardCoinsSent()).orElse(false));
|
||||||
|
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,7 +4,12 @@ import com.red.circle.common.business.dto.cmd.app.AppIdLongCmd;
|
|||||||
import com.red.circle.common.business.dto.cmd.app.AppRoomIdCmd;
|
import com.red.circle.common.business.dto.cmd.app.AppRoomIdCmd;
|
||||||
import com.red.circle.other.app.command.activity.RoomRewardReceiveCmdExe;
|
import com.red.circle.other.app.command.activity.RoomRewardReceiveCmdExe;
|
||||||
import com.red.circle.other.app.command.activity.RoomRewardReceiveQueryExe;
|
import com.red.circle.other.app.command.activity.RoomRewardReceiveQueryExe;
|
||||||
|
import com.red.circle.other.app.command.activity.room.ReceiveRoomRewardCmdExe;
|
||||||
|
import com.red.circle.other.app.command.activity.room.query.RoomRewardInfoQryExe;
|
||||||
import com.red.circle.other.app.dto.clientobject.activity.RoomRewardActivityCO;
|
import com.red.circle.other.app.dto.clientobject.activity.RoomRewardActivityCO;
|
||||||
|
import com.red.circle.other.app.dto.clientobject.activity.room.RoomRewardInfoCO;
|
||||||
|
import com.red.circle.other.app.dto.cmd.activity.room.ReceiveRoomRewardCmd;
|
||||||
|
import com.red.circle.other.app.util.DistributedLockUtil;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@ -19,6 +24,10 @@ public class RoomRewardServiceImpl implements RoomRewardService {
|
|||||||
|
|
||||||
private final RoomRewardReceiveCmdExe roomRewardReceiveCmdExe;
|
private final RoomRewardReceiveCmdExe roomRewardReceiveCmdExe;
|
||||||
private final RoomRewardReceiveQueryExe roomRewardReceiveQueryExe;
|
private final RoomRewardReceiveQueryExe roomRewardReceiveQueryExe;
|
||||||
|
private final RoomRewardInfoQryExe roomRewardInfoQryExe;
|
||||||
|
private final ReceiveRoomRewardCmdExe receiveRoomRewardCmdExe;
|
||||||
|
private final DistributedLockUtil distributedLockUtil;
|
||||||
|
private static final String REDIS_KEY_PREFIX = "room:reward:receive:";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RoomRewardActivityCO getReward(AppRoomIdCmd cmd) {
|
public RoomRewardActivityCO getReward(AppRoomIdCmd cmd) {
|
||||||
@ -30,4 +39,18 @@ public class RoomRewardServiceImpl implements RoomRewardService {
|
|||||||
roomRewardReceiveCmdExe.execute(cmd);
|
roomRewardReceiveCmdExe.execute(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RoomRewardInfoCO getRoomRewardInfo(String roomId) {
|
||||||
|
return roomRewardInfoQryExe.execute(roomId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void receiveOwnerIncome(ReceiveRoomRewardCmd cmd) {
|
||||||
|
String key = REDIS_KEY_PREFIX + cmd.getRoomId();
|
||||||
|
distributedLockUtil.executeWithLock(key, () -> {
|
||||||
|
receiveRoomRewardCmdExe.execute(cmd);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,16 @@ public class DistributedLockUtil {
|
|||||||
*/
|
*/
|
||||||
private static final long DEFAULT_LOCK_EXPIRE_TIME = 10;
|
private static final long DEFAULT_LOCK_EXPIRE_TIME = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用分布式锁执行业务逻辑(无返回值)
|
||||||
|
*
|
||||||
|
* @param lockKey 锁的key
|
||||||
|
* @param runnable 业务逻辑
|
||||||
|
*/
|
||||||
|
public void executeWithLock(String lockKey, Runnable runnable) {
|
||||||
|
executeWithLock(lockKey, DEFAULT_LOCK_EXPIRE_TIME, runnable, "The request is too frequent. Please try again later");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用分布式锁执行业务逻辑(无返回值)
|
* 使用分布式锁执行业务逻辑(无返回值)
|
||||||
*
|
*
|
||||||
|
|||||||
@ -0,0 +1,106 @@
|
|||||||
|
package com.red.circle.other.app.dto.clientobject.activity.room;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 房间奖励信息
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2025-12-01
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RoomRewardInfoCO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 倒计时信息
|
||||||
|
*/
|
||||||
|
private CountdownCO countdown;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前周进度
|
||||||
|
*/
|
||||||
|
private CurrentProgressCO currentProgress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上周进度
|
||||||
|
*/
|
||||||
|
private LastWeekProgressCO lastWeekProgress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 倒计时对象
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class CountdownCO {
|
||||||
|
/**
|
||||||
|
* 剩余天数
|
||||||
|
*/
|
||||||
|
private Long days;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 剩余小时
|
||||||
|
*/
|
||||||
|
private Long hours;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 剩余分钟
|
||||||
|
*/
|
||||||
|
private Long minutes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 剩余秒数
|
||||||
|
*/
|
||||||
|
private Long seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前周进度
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class CurrentProgressCO {
|
||||||
|
/**
|
||||||
|
* 当前流水金额
|
||||||
|
*/
|
||||||
|
private Long amount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前等级 (1-4)
|
||||||
|
*/
|
||||||
|
private Integer level;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上周进度
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class LastWeekProgressCO {
|
||||||
|
/**
|
||||||
|
* 上周流水金额
|
||||||
|
*/
|
||||||
|
private Long amount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上周等级 (1-4)
|
||||||
|
*/
|
||||||
|
private Integer level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 房主收入金币数(流水的5%)
|
||||||
|
*/
|
||||||
|
private Long ownerIncome;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 房主收入是否已领取
|
||||||
|
*/
|
||||||
|
private Boolean ownerIncomeReceived;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 奖励金币数量
|
||||||
|
*/
|
||||||
|
private Long rewardCoins;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 奖励金币是否已发放
|
||||||
|
*/
|
||||||
|
private Boolean rewardCoinsSent;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
package com.red.circle.other.app.dto.cmd.activity.room;
|
||||||
|
|
||||||
|
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 领取房间奖励房主收入命令
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2025-12-01
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class ReceiveRoomRewardCmd extends AppExtCommand {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 房间ID
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "房间ID不能为空")
|
||||||
|
private String roomId;
|
||||||
|
}
|
||||||
@ -0,0 +1,91 @@
|
|||||||
|
package com.red.circle.other.app.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 房间奖励等级枚举
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2025-12-01
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum RoomRewardLevelEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lv.1: 100,000 - 499,999,奖励2,000金币
|
||||||
|
*/
|
||||||
|
LEVEL_1(1, 100000L, 500000L, 2000L),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lv.2: 500,000 - 1,999,999,奖励15,000金币
|
||||||
|
*/
|
||||||
|
LEVEL_2(2, 500000L, 2000000L, 15000L),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lv.3: 2,000,000 - 4,999,999,奖励80,000金币
|
||||||
|
*/
|
||||||
|
LEVEL_3(3, 2000000L, 5000000L, 80000L),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lv.4: 5,000,000+,奖励250,000金币
|
||||||
|
*/
|
||||||
|
LEVEL_4(4, 5000000L, Long.MAX_VALUE, 250000L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 等级
|
||||||
|
*/
|
||||||
|
private final Integer level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最小流水金额(包含)
|
||||||
|
*/
|
||||||
|
private final Long minAmount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最大流水金额(不包含)
|
||||||
|
*/
|
||||||
|
private final Long maxAmount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 奖励金币数量
|
||||||
|
*/
|
||||||
|
private final Long rewardCoins;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据流水金额获取等级
|
||||||
|
*
|
||||||
|
* @param amount 流水金额
|
||||||
|
* @return 等级枚举,如果未达到最低要求则返回null
|
||||||
|
*/
|
||||||
|
public static RoomRewardLevelEnum getLevelByAmount(Long amount) {
|
||||||
|
if (amount == null || amount < LEVEL_1.minAmount) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(level -> amount >= level.minAmount && amount < level.maxAmount)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据等级数字获取枚举
|
||||||
|
*
|
||||||
|
* @param level 等级数字
|
||||||
|
* @return 等级枚举
|
||||||
|
*/
|
||||||
|
public static RoomRewardLevelEnum getByLevel(Integer level) {
|
||||||
|
if (level == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.level.equals(level))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,6 +4,8 @@ package com.red.circle.other.app.service.activity;
|
|||||||
import com.red.circle.common.business.dto.cmd.app.AppIdLongCmd;
|
import com.red.circle.common.business.dto.cmd.app.AppIdLongCmd;
|
||||||
import com.red.circle.common.business.dto.cmd.app.AppRoomIdCmd;
|
import com.red.circle.common.business.dto.cmd.app.AppRoomIdCmd;
|
||||||
import com.red.circle.other.app.dto.clientobject.activity.RoomRewardActivityCO;
|
import com.red.circle.other.app.dto.clientobject.activity.RoomRewardActivityCO;
|
||||||
|
import com.red.circle.other.app.dto.clientobject.activity.room.RoomRewardInfoCO;
|
||||||
|
import com.red.circle.other.app.dto.cmd.activity.room.ReceiveRoomRewardCmd;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 房间奖励相关.
|
* 房间奖励相关.
|
||||||
@ -16,4 +18,19 @@ public interface RoomRewardService {
|
|||||||
|
|
||||||
void receive(AppIdLongCmd cmd);
|
void receive(AppIdLongCmd cmd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询房间奖励信息
|
||||||
|
*
|
||||||
|
* @param roomId 房间ID
|
||||||
|
* @return 房间奖励信息
|
||||||
|
*/
|
||||||
|
RoomRewardInfoCO getRoomRewardInfo(String roomId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 领取房主收入
|
||||||
|
*
|
||||||
|
* @param cmd 领取命令
|
||||||
|
*/
|
||||||
|
void receiveOwnerIncome(ReceiveRoomRewardCmd cmd);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,6 +57,11 @@ public class RoomContributionActivityCount extends Convert implements Serializab
|
|||||||
*/
|
*/
|
||||||
Boolean received;
|
Boolean received;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 奖励金币是否已发放.
|
||||||
|
*/
|
||||||
|
Boolean rewardCoinsSent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 比例.
|
* 比例.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import com.red.circle.framework.dto.PageResult;
|
|||||||
import com.red.circle.other.infra.database.mongo.entity.activity.RoomContributionActivityCount;
|
import com.red.circle.other.infra.database.mongo.entity.activity.RoomContributionActivityCount;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -106,4 +107,13 @@ public interface RoomContributionActivityCountService {
|
|||||||
*/
|
*/
|
||||||
List<RoomContributionActivityCount> getAllRoomsLastWeekData();
|
List<RoomContributionActivityCount> getAllRoomsLastWeekData();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据房间ID和日期查询数据
|
||||||
|
*
|
||||||
|
* @param roomId 房间ID
|
||||||
|
* @param dateNumber 日期编号(格式:yyyyMMdd)
|
||||||
|
* @return 房间贡献数据
|
||||||
|
*/
|
||||||
|
Optional<RoomContributionActivityCount> findByRoomIdAndDateNumber(Long roomId, Integer dateNumber);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import java.math.RoundingMode;
|
|||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -302,4 +303,17 @@ public class RoomContributionActivityCountServiceImpl implements
|
|||||||
return mongoTemplate.find(Query.query(criteria), RoomContributionActivityCount.class);
|
return mongoTemplate.find(Query.query(criteria), RoomContributionActivityCount.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<RoomContributionActivityCount> findByRoomIdAndDateNumber(Long roomId, Integer dateNumber) {
|
||||||
|
Criteria criteria = Criteria.where("roomId").is(roomId)
|
||||||
|
.and("dateNumber").is(dateNumber);
|
||||||
|
|
||||||
|
RoomContributionActivityCount result = mongoTemplate.findOne(
|
||||||
|
Query.query(criteria),
|
||||||
|
RoomContributionActivityCount.class
|
||||||
|
);
|
||||||
|
|
||||||
|
return Optional.ofNullable(result);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -76,7 +76,7 @@ public class TeamMonthBillTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void processTeamBillSettle() {
|
public void processTeamBillSettle() {
|
||||||
String json = "['1984235784268349441']";
|
String json = "['1989278352807731201']";
|
||||||
List<String> teamList = JSON.parseArray(json, String.class);
|
List<String> teamList = JSON.parseArray(json, String.class);
|
||||||
for (String teamId : teamList) {
|
for (String teamId : teamList) {
|
||||||
Long id = Long.parseLong(teamId);
|
Long id = Long.parseLong(teamId);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user