feat: update room weekly reward ratio payout
This commit is contained in:
parent
7b6199f0b7
commit
bd5f8305df
@ -267,6 +267,11 @@ public enum OfficialNoticeTypeEnum {
|
||||
*/
|
||||
COIN_SELLER_COINS_RECEIVED,
|
||||
|
||||
/**
|
||||
* 房间流水奖励金币.
|
||||
*/
|
||||
ROOM_CONTRIBUTION_REWARD,
|
||||
|
||||
;
|
||||
|
||||
|
||||
|
||||
@ -2,8 +2,12 @@ package com.red.circle.other.app.scheduler;
|
||||
|
||||
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
||||
import com.red.circle.component.redis.annotation.TaskCacheLock;
|
||||
import com.red.circle.external.inner.endpoint.message.OfficialNoticeClient;
|
||||
import com.red.circle.external.inner.model.cmd.message.notice.official.NoticeExtTemplateCustomizeCmd;
|
||||
import com.red.circle.external.inner.model.enums.message.OfficialNoticeTypeEnum;
|
||||
import com.red.circle.framework.dto.ResultResponse;
|
||||
import com.red.circle.other.app.enums.RoomRewardLevelEnum;
|
||||
import com.red.circle.other.infra.constant.RegionConstants;
|
||||
import com.red.circle.other.infra.database.mongo.entity.activity.RoomContributionActivityCount;
|
||||
import com.red.circle.other.infra.database.mongo.entity.live.RoomProfileManager;
|
||||
import com.red.circle.other.infra.database.mongo.service.activity.RoomContributionActivityCountService;
|
||||
@ -15,9 +19,12 @@ import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
|
||||
import com.red.circle.wallet.inner.model.dto.WalletReceiptResDTO;
|
||||
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
@ -25,6 +32,8 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -42,10 +51,13 @@ public class RoomContributionWeeklyRewardTask {
|
||||
* wallet_gold_asset_record.event_id is varchar(50), keep the event id short.
|
||||
*/
|
||||
private static final String OWNER_REWARD_EVENT_PREFIX = "RCWR:";
|
||||
private static final BigDecimal DEFAULT_MIN_CONTRIBUTION = BigDecimal.valueOf(100000);
|
||||
private static final BigDecimal TARAB_MIN_CONTRIBUTION = BigDecimal.valueOf(150000);
|
||||
private static final String OWNER_REWARD_SUPPLEMENT_EVENT_PREFIX = "RCWRS:";
|
||||
private static final BigDecimal MIN_RATIO_REWARD_CONTRIBUTION = BigDecimal.valueOf(5000000);
|
||||
private static final BigDecimal DEFAULT_REWARD_RATIO = new BigDecimal("0.10");
|
||||
private static final BigDecimal LOW_REWARD_RATIO = new BigDecimal("0.05");
|
||||
|
||||
private final WalletGoldClient walletGoldClient;
|
||||
private final OfficialNoticeClient officialNoticeClient;
|
||||
private final RoomProfileManagerService roomProfileManagerService;
|
||||
private final RoomContributionActivityCountService roomContributionActivityCountService;
|
||||
|
||||
@ -55,6 +67,18 @@ public class RoomContributionWeeklyRewardTask {
|
||||
@Value("${activity.room-contribution.weekly-reward.sys-origins:ATYOU}")
|
||||
private String enabledSysOrigins;
|
||||
|
||||
@Value("${activity.room-contribution.weekly-reward.ratio-supplement-enabled:true}")
|
||||
private Boolean ratioSupplementEnabled;
|
||||
|
||||
@Value("${activity.room-contribution.weekly-reward.ratio-supplement-start-date-number:0}")
|
||||
private Integer ratioSupplementStartDateNumber;
|
||||
|
||||
@Value("${activity.room-contribution.weekly-reward.ratio-supplement-end-date-number:0}")
|
||||
private Integer ratioSupplementEndDateNumber;
|
||||
|
||||
@Value("${activity.room-contribution.weekly-reward.run-repair-on-startup:false}")
|
||||
private Boolean runRepairOnStartup;
|
||||
|
||||
/**
|
||||
* 每周一沙特时间 00:08 发送上周房间周流水奖励.
|
||||
*/
|
||||
@ -76,6 +100,20 @@ public class RoomContributionWeeklyRewardTask {
|
||||
return;
|
||||
}
|
||||
sendLastWeekRoomContributionRewards("repair");
|
||||
sendOwnerRewardRatioSupplements("repair");
|
||||
}
|
||||
|
||||
/**
|
||||
* 线上临时补偿入口:配置打开后服务启动执行一次 repair,执行完应关闭配置。
|
||||
*/
|
||||
@EventListener(ApplicationReadyEvent.class)
|
||||
@TaskCacheLock(key = "ROOM_CONTRIBUTION_WEEKLY_REWARD_STARTUP_REPAIR", expireSecond = 600)
|
||||
public void repairLastWeekRoomContributionRewardsOnStartup() {
|
||||
if (!Boolean.TRUE.equals(runRepairOnStartup)) {
|
||||
return;
|
||||
}
|
||||
log.warn("[RoomContributionWeeklyOwnerReward] startup repair enabled");
|
||||
repairLastWeekRoomContributionRewards();
|
||||
}
|
||||
|
||||
private void sendLastWeekRoomContributionRewards(String trigger) {
|
||||
@ -132,9 +170,8 @@ public class RoomContributionWeeklyRewardTask {
|
||||
return false;
|
||||
}
|
||||
|
||||
RoomRewardLevelEnum level = RoomRewardLevelEnum
|
||||
.getLevelByAmount(data.getContributionValue().longValue());
|
||||
if (Objects.isNull(level)) {
|
||||
Long rewardCoins = calculateRatioRewardCoins(room, sysOrigin, data.getContributionValue());
|
||||
if (rewardCoins <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -147,11 +184,16 @@ public class RoomContributionWeeklyRewardTask {
|
||||
|
||||
try {
|
||||
if (!ownerRewardEventExists(eventId)) {
|
||||
addOwnerGold(room.getUserId(), sysOrigin, level.getRewardCoins(), eventId);
|
||||
addOwnerGold(room.getUserId(), sysOrigin, rewardCoins, eventId);
|
||||
}
|
||||
sendOwnerRewardNotice(room.getUserId(), rewardCoins);
|
||||
if (!roomContributionActivityCountService.markOwnerRewardCoinsSent(data.getId(), eventId)) {
|
||||
log.warn("[RoomContributionWeeklyOwnerReward] mark sent skipped roomId={} ownerId={} dataId={} eventId={}",
|
||||
data.getRoomId(), room.getUserId(), data.getId(), eventId);
|
||||
} else {
|
||||
// 新发记录已经按比例全额发放,直接关闭补差入口,避免 repair 重复补发。
|
||||
roomContributionActivityCountService.markOwnerRewardRatioSupplementSent(data.getId(),
|
||||
eventId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
roomContributionActivityCountService.resetOwnerRewardCoinsSending(data.getId(), eventId,
|
||||
@ -159,16 +201,119 @@ public class RoomContributionWeeklyRewardTask {
|
||||
throw e;
|
||||
}
|
||||
|
||||
log.info("[RoomContributionWeeklyOwnerReward] sent roomId={} ownerId={} dataId={} level={} rewardCoins={} eventId={}",
|
||||
data.getRoomId(), room.getUserId(), data.getId(), level.getLevel(), level.getRewardCoins(),
|
||||
log.info("[RoomContributionWeeklyOwnerReward] sent roomId={} ownerId={} dataId={} rewardCoins={} eventId={}",
|
||||
data.getRoomId(), room.getUserId(), data.getId(), rewardCoins,
|
||||
eventId);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sendOwnerRewardRatioSupplements(String trigger) {
|
||||
if (!Boolean.TRUE.equals(ratioSupplementEnabled)) {
|
||||
return;
|
||||
}
|
||||
Integer lastWeekDateNumber = getLastWeekDateNumber();
|
||||
Integer startDateNumber = Objects.nonNull(ratioSupplementStartDateNumber)
|
||||
&& ratioSupplementStartDateNumber > 0 ? ratioSupplementStartDateNumber : lastWeekDateNumber;
|
||||
Integer endDateNumber = Objects.nonNull(ratioSupplementEndDateNumber)
|
||||
&& ratioSupplementEndDateNumber > 0 ? ratioSupplementEndDateNumber : lastWeekDateNumber;
|
||||
|
||||
log.warn("[RoomContributionWeeklyOwnerRewardSupplement] start trigger={} startDateNumber={} endDateNumber={}",
|
||||
trigger, startDateNumber, endDateNumber);
|
||||
List<RoomContributionActivityCount> list =
|
||||
roomContributionActivityCountService.listOwnerRewardRatioSupplementData(startDateNumber,
|
||||
endDateNumber);
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
log.warn("[RoomContributionWeeklyOwnerRewardSupplement] no supplement data trigger={}",
|
||||
trigger);
|
||||
return;
|
||||
}
|
||||
|
||||
int success = 0;
|
||||
int fail = 0;
|
||||
for (RoomContributionActivityCount data : list) {
|
||||
try {
|
||||
if (sendSupplementReward(data)) {
|
||||
success++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
fail++;
|
||||
log.error("[RoomContributionWeeklyOwnerRewardSupplement] send failed roomId={} dataId={} amount={}",
|
||||
data.getRoomId(), data.getId(), data.getContributionValue(), e);
|
||||
}
|
||||
}
|
||||
|
||||
log.warn("[RoomContributionWeeklyOwnerRewardSupplement] end trigger={} total={} success={} fail={}",
|
||||
trigger, list.size(), success, fail);
|
||||
}
|
||||
|
||||
private boolean sendSupplementReward(RoomContributionActivityCount data) {
|
||||
if (Objects.isNull(data) || Objects.isNull(data.getRoomId())
|
||||
|| Objects.isNull(data.getContributionValue())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RoomProfileManager room = roomProfileManagerService.getById(data.getRoomId());
|
||||
SysOriginPlatformEnum sysOrigin = getSysOrigin(room);
|
||||
if (Objects.isNull(room) || Objects.isNull(room.getUserId()) || Objects.isNull(sysOrigin)) {
|
||||
log.warn("[RoomContributionWeeklyOwnerRewardSupplement] skip invalid room roomId={} dataId={}",
|
||||
data.getRoomId(), data.getId());
|
||||
return false;
|
||||
}
|
||||
if (!getEnabledSysOrigins().contains(sysOrigin)
|
||||
|| !meetsPlatformThreshold(sysOrigin, data.getContributionValue())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 已经按旧档位直发过的记录,只补“新比例规则 - 旧档位金额”的差额。
|
||||
Long shouldRewardCoins = calculateRatioRewardCoins(room, sysOrigin,
|
||||
data.getContributionValue());
|
||||
Long oldLevelRewardCoins = calculateOldLevelRewardCoins(data.getContributionValue());
|
||||
Long supplementCoins = shouldRewardCoins - oldLevelRewardCoins;
|
||||
String eventId = buildOwnerRewardSupplementEventId(data.getId());
|
||||
if (!roomContributionActivityCountService.markOwnerRewardRatioSupplementSending(data.getId(),
|
||||
eventId)) {
|
||||
log.warn("[RoomContributionWeeklyOwnerRewardSupplement] skip sending occupied roomId={} dataId={} eventId={}",
|
||||
data.getRoomId(), data.getId(), eventId);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
if (supplementCoins > 0 && !ownerRewardEventExists(eventId)) {
|
||||
addOwnerGold(room.getUserId(), sysOrigin, supplementCoins, eventId);
|
||||
}
|
||||
if (supplementCoins > 0) {
|
||||
sendOwnerRewardNotice(room.getUserId(), supplementCoins);
|
||||
}
|
||||
if (!roomContributionActivityCountService.markOwnerRewardRatioSupplementSent(data.getId(),
|
||||
eventId)) {
|
||||
log.warn("[RoomContributionWeeklyOwnerRewardSupplement] mark sent skipped roomId={} ownerId={} dataId={} eventId={}",
|
||||
data.getRoomId(), room.getUserId(), data.getId(), eventId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
roomContributionActivityCountService.resetOwnerRewardRatioSupplementSending(data.getId(),
|
||||
eventId, e.getMessage());
|
||||
throw e;
|
||||
}
|
||||
|
||||
log.info("[RoomContributionWeeklyOwnerRewardSupplement] sent roomId={} ownerId={} dataId={} shouldRewardCoins={} oldLevelRewardCoins={} supplementCoins={} eventId={}",
|
||||
data.getRoomId(), room.getUserId(), data.getId(), shouldRewardCoins, oldLevelRewardCoins,
|
||||
Math.max(supplementCoins, 0L), eventId);
|
||||
return true;
|
||||
}
|
||||
|
||||
private String buildOwnerRewardEventId(String dataId) {
|
||||
return OWNER_REWARD_EVENT_PREFIX + dataId;
|
||||
}
|
||||
|
||||
private String buildOwnerRewardSupplementEventId(String dataId) {
|
||||
return OWNER_REWARD_SUPPLEMENT_EVENT_PREFIX + dataId;
|
||||
}
|
||||
|
||||
private Integer getLastWeekDateNumber() {
|
||||
return Integer.valueOf(com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils
|
||||
.getLastWeekMonday().format(DateTimeFormatter.ofPattern("yyyyMMdd")));
|
||||
}
|
||||
|
||||
private boolean ownerRewardEventExists(String eventId) {
|
||||
ResultResponse<Boolean> response = walletGoldClient.existsEventId(eventId);
|
||||
if (Objects.isNull(response) || !response.checkSuccess()) {
|
||||
@ -194,6 +339,21 @@ public class RoomContributionWeeklyRewardTask {
|
||||
}
|
||||
}
|
||||
|
||||
private void sendOwnerRewardNotice(Long userId, Long rewardCoins) {
|
||||
ResultResponse<Void> response = officialNoticeClient.send(
|
||||
NoticeExtTemplateCustomizeCmd.builder()
|
||||
.toAccount(userId)
|
||||
.noticeType(OfficialNoticeTypeEnum.ROOM_CONTRIBUTION_REWARD)
|
||||
.title("Room Rewards")
|
||||
.content(String.format(Locale.ENGLISH, "You get room rewards %,d coins",
|
||||
rewardCoins))
|
||||
.build()
|
||||
);
|
||||
if (Objects.isNull(response) || !response.checkSuccess()) {
|
||||
throw new IllegalStateException("send owner reward notice failed: " + userId);
|
||||
}
|
||||
}
|
||||
|
||||
private SysOriginPlatformEnum getSysOrigin(RoomProfileManager room) {
|
||||
if (Objects.isNull(room) || Objects.isNull(room.getSysOrigin())) {
|
||||
return null;
|
||||
@ -206,9 +366,37 @@ public class RoomContributionWeeklyRewardTask {
|
||||
}
|
||||
|
||||
private boolean meetsPlatformThreshold(SysOriginPlatformEnum sysOrigin, BigDecimal contribution) {
|
||||
BigDecimal minContribution = Objects.equals(sysOrigin, SysOriginPlatformEnum.TARAB)
|
||||
? TARAB_MIN_CONTRIBUTION : DEFAULT_MIN_CONTRIBUTION;
|
||||
return contribution.compareTo(minContribution) >= 0;
|
||||
return Objects.nonNull(contribution)
|
||||
&& contribution.compareTo(MIN_RATIO_REWARD_CONTRIBUTION) >= 0;
|
||||
}
|
||||
|
||||
private Long calculateRatioRewardCoins(RoomProfileManager room, SysOriginPlatformEnum sysOrigin,
|
||||
BigDecimal contribution) {
|
||||
if (!meetsPlatformThreshold(sysOrigin, contribution)) {
|
||||
return 0L;
|
||||
}
|
||||
// 新规则按房间流水比例发放;阿语区和土耳其按5%,其它地区按10%.
|
||||
return contribution.multiply(getRewardRatio(room, sysOrigin))
|
||||
.setScale(0, RoundingMode.DOWN)
|
||||
.longValue();
|
||||
}
|
||||
|
||||
private Long calculateOldLevelRewardCoins(BigDecimal contribution) {
|
||||
RoomRewardLevelEnum level = RoomRewardLevelEnum.getLevelByAmount(contribution.longValue());
|
||||
return Objects.nonNull(level) ? level.getRewardCoins() : 0L;
|
||||
}
|
||||
|
||||
private BigDecimal getRewardRatio(RoomProfileManager room, SysOriginPlatformEnum sysOrigin) {
|
||||
if (Objects.equals(sysOrigin, SysOriginPlatformEnum.TARAB)) {
|
||||
return LOW_REWARD_RATIO;
|
||||
}
|
||||
String countryCode = Objects.nonNull(room) && Objects.nonNull(room.getCountryCode())
|
||||
? room.getCountryCode().trim().toUpperCase(Locale.ROOT) : "";
|
||||
if (RegionConstants.AR_REGIONS.contains(countryCode)
|
||||
|| RegionConstants.TR_REGIONS.contains(countryCode)) {
|
||||
return LOW_REWARD_RATIO;
|
||||
}
|
||||
return DEFAULT_REWARD_RATIO;
|
||||
}
|
||||
|
||||
private Set<SysOriginPlatformEnum> getEnabledSysOrigins() {
|
||||
|
||||
@ -8,6 +8,8 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
||||
import com.red.circle.external.inner.endpoint.message.OfficialNoticeClient;
|
||||
import com.red.circle.external.inner.model.cmd.message.notice.official.NoticeExtTemplateCustomizeCmd;
|
||||
import com.red.circle.framework.dto.ResultResponse;
|
||||
import com.red.circle.other.infra.database.mongo.entity.activity.RoomContributionActivityCount;
|
||||
import com.red.circle.other.infra.database.mongo.entity.live.RoomProfileManager;
|
||||
@ -32,12 +34,15 @@ class RoomContributionWeeklyRewardTaskTest {
|
||||
|
||||
private static final String DATA_ID = "2071532202565136385_20260629";
|
||||
private static final String EVENT_ID = "RCWR:" + DATA_ID;
|
||||
private static final String SUPPLEMENT_EVENT_ID = "RCWRS:" + DATA_ID;
|
||||
private static final Long ROOM_ID = 2071532202565136385L;
|
||||
private static final Long OWNER_ID = 2071520380357021697L;
|
||||
|
||||
@Mock
|
||||
private WalletGoldClient walletGoldClient;
|
||||
@Mock
|
||||
private OfficialNoticeClient officialNoticeClient;
|
||||
@Mock
|
||||
private RoomProfileManagerService roomProfileManagerService;
|
||||
@Mock
|
||||
private RoomContributionActivityCountService roomContributionActivityCountService;
|
||||
@ -46,9 +51,13 @@ class RoomContributionWeeklyRewardTaskTest {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
task = new RoomContributionWeeklyRewardTask(walletGoldClient, roomProfileManagerService,
|
||||
roomContributionActivityCountService);
|
||||
task = new RoomContributionWeeklyRewardTask(walletGoldClient, officialNoticeClient,
|
||||
roomProfileManagerService, roomContributionActivityCountService);
|
||||
ReflectionTestUtils.setField(task, "enabledSysOrigins", "ATYOU");
|
||||
ReflectionTestUtils.setField(task, "repairEnabled", Boolean.TRUE);
|
||||
ReflectionTestUtils.setField(task, "ratioSupplementEnabled", Boolean.TRUE);
|
||||
ReflectionTestUtils.setField(task, "ratioSupplementStartDateNumber", 20260629);
|
||||
ReflectionTestUtils.setField(task, "ratioSupplementEndDateNumber", 20260629);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -61,8 +70,12 @@ class RoomContributionWeeklyRewardTaskTest {
|
||||
when(walletGoldClient.existsEventId(EVENT_ID)).thenReturn(ResultResponse.success(false));
|
||||
when(walletGoldClient.changeBalance(any(GoldReceiptCmd.class)))
|
||||
.thenReturn(ResultResponse.success(new WalletReceiptResDTO()));
|
||||
when(officialNoticeClient.send(any(NoticeExtTemplateCustomizeCmd.class)))
|
||||
.thenReturn(ResultResponse.success());
|
||||
when(roomContributionActivityCountService.markOwnerRewardCoinsSent(DATA_ID, EVENT_ID))
|
||||
.thenReturn(true);
|
||||
when(roomContributionActivityCountService.markOwnerRewardRatioSupplementSent(DATA_ID, EVENT_ID))
|
||||
.thenReturn(true);
|
||||
|
||||
task.sendLastWeekRoomContributionRewards();
|
||||
|
||||
@ -74,8 +87,15 @@ class RoomContributionWeeklyRewardTaskTest {
|
||||
assertEquals(EVENT_ID, cmd.getEventId());
|
||||
assertTrue(cmd.getEventId().length() <= 50);
|
||||
assertEquals(GoldOrigin.ROOM_CONTRIBUTION_REWARD, cmd.getOrigin());
|
||||
assertEquals(25000000L, cmd.getAmount().getPennyAmount());
|
||||
assertEquals(207777000L, cmd.getAmount().getPennyAmount());
|
||||
|
||||
ArgumentCaptor<NoticeExtTemplateCustomizeCmd> noticeCaptor =
|
||||
ArgumentCaptor.forClass(NoticeExtTemplateCustomizeCmd.class);
|
||||
verify(officialNoticeClient).send(noticeCaptor.capture());
|
||||
assertEquals("You get room rewards 2,077,770 coins", noticeCaptor.getValue().getContent());
|
||||
verify(roomContributionActivityCountService).markOwnerRewardCoinsSent(DATA_ID, EVENT_ID);
|
||||
verify(roomContributionActivityCountService).markOwnerRewardRatioSupplementSent(DATA_ID,
|
||||
EVENT_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -86,15 +106,79 @@ class RoomContributionWeeklyRewardTaskTest {
|
||||
when(roomContributionActivityCountService.markOwnerRewardCoinsSending(DATA_ID, EVENT_ID))
|
||||
.thenReturn(true);
|
||||
when(walletGoldClient.existsEventId(EVENT_ID)).thenReturn(ResultResponse.success(true));
|
||||
when(officialNoticeClient.send(any(NoticeExtTemplateCustomizeCmd.class)))
|
||||
.thenReturn(ResultResponse.success());
|
||||
when(roomContributionActivityCountService.markOwnerRewardCoinsSent(DATA_ID, EVENT_ID))
|
||||
.thenReturn(true);
|
||||
when(roomContributionActivityCountService.markOwnerRewardRatioSupplementSent(DATA_ID, EVENT_ID))
|
||||
.thenReturn(true);
|
||||
|
||||
task.sendLastWeekRoomContributionRewards();
|
||||
|
||||
verify(walletGoldClient, never()).changeBalance(any(GoldReceiptCmd.class));
|
||||
verify(officialNoticeClient).send(any(NoticeExtTemplateCustomizeCmd.class));
|
||||
verify(roomContributionActivityCountService).markOwnerRewardCoinsSent(DATA_ID, EVENT_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseFivePercentForArabicOrTurkeyRooms() {
|
||||
RoomProfileManager room = room();
|
||||
room.setCountryCode("AR");
|
||||
when(roomContributionActivityCountService.listLastWeekOwnerRewardUnsentData())
|
||||
.thenReturn(List.of(activityCount()));
|
||||
when(roomProfileManagerService.getById(ROOM_ID)).thenReturn(room);
|
||||
when(roomContributionActivityCountService.markOwnerRewardCoinsSending(DATA_ID, EVENT_ID))
|
||||
.thenReturn(true);
|
||||
when(walletGoldClient.existsEventId(EVENT_ID)).thenReturn(ResultResponse.success(false));
|
||||
when(walletGoldClient.changeBalance(any(GoldReceiptCmd.class)))
|
||||
.thenReturn(ResultResponse.success(new WalletReceiptResDTO()));
|
||||
when(officialNoticeClient.send(any(NoticeExtTemplateCustomizeCmd.class)))
|
||||
.thenReturn(ResultResponse.success());
|
||||
when(roomContributionActivityCountService.markOwnerRewardCoinsSent(DATA_ID, EVENT_ID))
|
||||
.thenReturn(true);
|
||||
when(roomContributionActivityCountService.markOwnerRewardRatioSupplementSent(DATA_ID, EVENT_ID))
|
||||
.thenReturn(true);
|
||||
|
||||
task.sendLastWeekRoomContributionRewards();
|
||||
|
||||
ArgumentCaptor<GoldReceiptCmd> captor = ArgumentCaptor.forClass(GoldReceiptCmd.class);
|
||||
verify(walletGoldClient).changeBalance(captor.capture());
|
||||
assertEquals(103888500L, captor.getValue().getAmount().getPennyAmount());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupplementOldLevelRewardDifference() {
|
||||
when(roomContributionActivityCountService.listLastWeekOwnerRewardUnsentData())
|
||||
.thenReturn(List.of());
|
||||
when(roomContributionActivityCountService.listOwnerRewardRatioSupplementData(20260629,
|
||||
20260629)).thenReturn(List.of(activityCount()));
|
||||
when(roomProfileManagerService.getById(ROOM_ID)).thenReturn(room());
|
||||
when(roomContributionActivityCountService.markOwnerRewardRatioSupplementSending(DATA_ID,
|
||||
SUPPLEMENT_EVENT_ID)).thenReturn(true);
|
||||
when(walletGoldClient.existsEventId(SUPPLEMENT_EVENT_ID)).thenReturn(ResultResponse.success(false));
|
||||
when(walletGoldClient.changeBalance(any(GoldReceiptCmd.class)))
|
||||
.thenReturn(ResultResponse.success(new WalletReceiptResDTO()));
|
||||
when(officialNoticeClient.send(any(NoticeExtTemplateCustomizeCmd.class)))
|
||||
.thenReturn(ResultResponse.success());
|
||||
when(roomContributionActivityCountService.markOwnerRewardRatioSupplementSent(DATA_ID,
|
||||
SUPPLEMENT_EVENT_ID)).thenReturn(true);
|
||||
|
||||
task.repairLastWeekRoomContributionRewards();
|
||||
|
||||
ArgumentCaptor<GoldReceiptCmd> goldCaptor = ArgumentCaptor.forClass(GoldReceiptCmd.class);
|
||||
verify(walletGoldClient).changeBalance(goldCaptor.capture());
|
||||
GoldReceiptCmd cmd = goldCaptor.getValue();
|
||||
assertEquals(SUPPLEMENT_EVENT_ID, cmd.getEventId());
|
||||
assertEquals(182777000L, cmd.getAmount().getPennyAmount());
|
||||
|
||||
ArgumentCaptor<NoticeExtTemplateCustomizeCmd> noticeCaptor =
|
||||
ArgumentCaptor.forClass(NoticeExtTemplateCustomizeCmd.class);
|
||||
verify(officialNoticeClient).send(noticeCaptor.capture());
|
||||
assertEquals("You get room rewards 1,827,770 coins", noticeCaptor.getValue().getContent());
|
||||
verify(roomContributionActivityCountService).markOwnerRewardRatioSupplementSent(DATA_ID,
|
||||
SUPPLEMENT_EVENT_ID);
|
||||
}
|
||||
|
||||
private RoomContributionActivityCount activityCount() {
|
||||
RoomContributionActivityCount count = new RoomContributionActivityCount();
|
||||
count.setId(DATA_ID);
|
||||
|
||||
@ -117,6 +117,36 @@ public class RoomContributionActivityCount extends Convert implements Serializab
|
||||
*/
|
||||
String ownerRewardCoinsSendError;
|
||||
|
||||
/**
|
||||
* 房主奖励金币比例规则补差是否已处理.
|
||||
*/
|
||||
Boolean ownerRewardRatioSupplementSent;
|
||||
|
||||
/**
|
||||
* 房主奖励金币比例规则补差是否处理中.
|
||||
*/
|
||||
Boolean ownerRewardRatioSupplementSending;
|
||||
|
||||
/**
|
||||
* 房主奖励金币比例规则补差事件ID.
|
||||
*/
|
||||
String ownerRewardRatioSupplementEventId;
|
||||
|
||||
/**
|
||||
* 房主奖励金币比例规则补差处理时间.
|
||||
*/
|
||||
Timestamp ownerRewardRatioSupplementSentTime;
|
||||
|
||||
/**
|
||||
* 房主奖励金币比例规则补差处理中时间.
|
||||
*/
|
||||
Timestamp ownerRewardRatioSupplementSendingTime;
|
||||
|
||||
/**
|
||||
* 房主奖励金币比例规则补差失败原因.
|
||||
*/
|
||||
String ownerRewardRatioSupplementSendError;
|
||||
|
||||
/**
|
||||
* 比例.
|
||||
*/
|
||||
|
||||
@ -133,6 +133,12 @@ public interface RoomContributionActivityCountService {
|
||||
*/
|
||||
List<RoomContributionActivityCount> listLastWeekOwnerRewardUnsentData();
|
||||
|
||||
/**
|
||||
* 获取已按旧档位直发、但未按比例规则补差的房间贡献数据.
|
||||
*/
|
||||
List<RoomContributionActivityCount> listOwnerRewardRatioSupplementData(Integer startDateNumber,
|
||||
Integer endDateNumber);
|
||||
|
||||
/**
|
||||
* 抢占房主奖励金币直发记录.
|
||||
*/
|
||||
@ -148,6 +154,21 @@ public interface RoomContributionActivityCountService {
|
||||
*/
|
||||
void resetOwnerRewardCoinsSending(String id, String eventId, String reason);
|
||||
|
||||
/**
|
||||
* 抢占房主奖励金币比例补差记录.
|
||||
*/
|
||||
boolean markOwnerRewardRatioSupplementSending(String id, String eventId);
|
||||
|
||||
/**
|
||||
* 标记房主奖励金币比例补差已处理.
|
||||
*/
|
||||
boolean markOwnerRewardRatioSupplementSent(String id, String eventId);
|
||||
|
||||
/**
|
||||
* 释放房主奖励金币比例补差处理中状态,等待重试.
|
||||
*/
|
||||
void resetOwnerRewardRatioSupplementSending(String id, String eventId, String reason);
|
||||
|
||||
/**
|
||||
* 根据房间ID和日期查询数据
|
||||
*
|
||||
|
||||
@ -46,6 +46,7 @@ public class RoomContributionActivityCountServiceImpl implements
|
||||
private final MongoPageHelper mongoPageHelper;
|
||||
private static final BigDecimal integralMin = BigDecimal.valueOf(100000);
|
||||
private static final BigDecimal otherIntegralMin = BigDecimal.valueOf(150000);
|
||||
private static final BigDecimal ownerRewardMinContribution = BigDecimal.valueOf(5000000);
|
||||
private static final long REWARD_SENDING_EXPIRE_MILLIS = 2 * 60 * 1000L;
|
||||
|
||||
private Criteria getUniquenessCriteria(Long roomId, Integer dateNumber) {
|
||||
@ -363,7 +364,7 @@ public class RoomContributionActivityCountServiceImpl implements
|
||||
public List<RoomContributionActivityCount> listLastWeekOwnerRewardUnsentData() {
|
||||
Criteria criteria = new Criteria().andOperator(
|
||||
Criteria.where("dateNumber").is(getLastWeekDateNumber()),
|
||||
Criteria.where("contributionValue").gte(integralMin),
|
||||
Criteria.where("contributionValue").gte(ownerRewardMinContribution),
|
||||
unsentOwnerRewardCriteria(),
|
||||
ownerRewardNotSendingOrExpiredCriteria()
|
||||
);
|
||||
@ -371,6 +372,25 @@ public class RoomContributionActivityCountServiceImpl implements
|
||||
return mongoTemplate.find(Query.query(criteria), RoomContributionActivityCount.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RoomContributionActivityCount> listOwnerRewardRatioSupplementData(
|
||||
Integer startDateNumber, Integer endDateNumber) {
|
||||
Criteria dateCriteria = Criteria.where("dateNumber").gte(startDateNumber);
|
||||
if (Objects.nonNull(endDateNumber)) {
|
||||
dateCriteria.lte(endDateNumber);
|
||||
}
|
||||
|
||||
Criteria criteria = new Criteria().andOperator(
|
||||
dateCriteria,
|
||||
Criteria.where("contributionValue").gte(ownerRewardMinContribution),
|
||||
Criteria.where("ownerRewardCoinsSent").is(Boolean.TRUE),
|
||||
unsentOwnerRewardRatioSupplementCriteria(),
|
||||
ownerRewardRatioSupplementNotSendingOrExpiredCriteria()
|
||||
);
|
||||
|
||||
return mongoTemplate.find(Query.query(criteria), RoomContributionActivityCount.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markOwnerRewardCoinsSending(String id, String eventId) {
|
||||
Query query = Query.query(new Criteria().andOperator(
|
||||
@ -415,6 +435,56 @@ public class RoomContributionActivityCountServiceImpl implements
|
||||
mongoTemplate.updateFirst(query, update, RoomContributionActivityCount.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markOwnerRewardRatioSupplementSending(String id, String eventId) {
|
||||
Query query = Query.query(new Criteria().andOperator(
|
||||
Criteria.where("_id").is(id),
|
||||
unsentOwnerRewardRatioSupplementCriteria(),
|
||||
ownerRewardRatioSupplementNotSendingOrExpiredCriteria()
|
||||
));
|
||||
Update update = new Update()
|
||||
.set("ownerRewardRatioSupplementSending", Boolean.TRUE)
|
||||
.set("ownerRewardRatioSupplementEventId", eventId)
|
||||
.set("ownerRewardRatioSupplementSendingTime", TimestampUtils.now())
|
||||
.unset("ownerRewardRatioSupplementSendError");
|
||||
UpdateResult result = mongoTemplate.updateFirst(query, update,
|
||||
RoomContributionActivityCount.class);
|
||||
return result.getModifiedCount() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markOwnerRewardRatioSupplementSent(String id, String eventId) {
|
||||
Query query = Query.query(new Criteria().andOperator(
|
||||
Criteria.where("_id").is(id),
|
||||
new Criteria().orOperator(
|
||||
Criteria.where("ownerRewardRatioSupplementEventId").exists(false),
|
||||
Criteria.where("ownerRewardRatioSupplementEventId").is(eventId)
|
||||
)
|
||||
));
|
||||
Update update = new Update()
|
||||
.set("ownerRewardRatioSupplementSent", Boolean.TRUE)
|
||||
.set("ownerRewardRatioSupplementSending", Boolean.FALSE)
|
||||
.set("ownerRewardRatioSupplementEventId", eventId)
|
||||
.set("ownerRewardRatioSupplementSentTime", TimestampUtils.now())
|
||||
.unset("ownerRewardRatioSupplementSendError");
|
||||
UpdateResult result = mongoTemplate.updateFirst(query, update,
|
||||
RoomContributionActivityCount.class);
|
||||
return result.getModifiedCount() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetOwnerRewardRatioSupplementSending(String id, String eventId, String reason) {
|
||||
Query query = Query.query(new Criteria().andOperator(
|
||||
Criteria.where("_id").is(id),
|
||||
Criteria.where("ownerRewardRatioSupplementEventId").is(eventId),
|
||||
unsentOwnerRewardRatioSupplementCriteria()
|
||||
));
|
||||
Update update = new Update()
|
||||
.set("ownerRewardRatioSupplementSending", Boolean.FALSE)
|
||||
.set("ownerRewardRatioSupplementSendError", limitErrorReason(reason));
|
||||
mongoTemplate.updateFirst(query, update, RoomContributionActivityCount.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<RoomContributionActivityCount> findByRoomIdAndDateNumber(Long roomId, Integer dateNumber) {
|
||||
Criteria criteria = Criteria.where("roomId").is(roomId)
|
||||
@ -465,6 +535,22 @@ public class RoomContributionActivityCountServiceImpl implements
|
||||
);
|
||||
}
|
||||
|
||||
private Criteria unsentOwnerRewardRatioSupplementCriteria() {
|
||||
return new Criteria().orOperator(
|
||||
Criteria.where("ownerRewardRatioSupplementSent").exists(false),
|
||||
Criteria.where("ownerRewardRatioSupplementSent").ne(Boolean.TRUE)
|
||||
);
|
||||
}
|
||||
|
||||
private Criteria ownerRewardRatioSupplementNotSendingOrExpiredCriteria() {
|
||||
return new Criteria().orOperator(
|
||||
Criteria.where("ownerRewardRatioSupplementSending").exists(false),
|
||||
Criteria.where("ownerRewardRatioSupplementSending").ne(Boolean.TRUE),
|
||||
Criteria.where("ownerRewardRatioSupplementSendingTime")
|
||||
.lt(new java.sql.Timestamp(System.currentTimeMillis() - REWARD_SENDING_EXPIRE_MILLIS))
|
||||
);
|
||||
}
|
||||
|
||||
private String limitErrorReason(String reason) {
|
||||
if (StringUtils.isBlank(reason) || reason.length() <= 500) {
|
||||
return reason;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user