feat(console): add reward grant records

This commit is contained in:
zhx 2026-07-14 20:29:50 +08:00
parent 8de4ce3837
commit 0104ad5100
23 changed files with 701 additions and 0 deletions

View File

@ -0,0 +1,119 @@
-- Webconsole reward grant record menu and list API permission.
-- The menu follows the existing room contribution page and inherits only its roles.
SET NAMES utf8mb4;
INSERT INTO sys_resource (id, resource_name, mapping, method, auth_type, perm, update_time)
VALUES (
'activity:reward-grant-record:page',
'奖励发放记录列表',
'/reward-grant-record/page',
'GET',
3,
'activity:reward-grant-record:page',
NOW()
)
ON DUPLICATE KEY UPDATE
resource_name = VALUES(resource_name),
mapping = VALUES(mapping),
method = VALUES(method),
auth_type = VALUES(auth_type),
perm = VALUES(perm),
update_time = NOW();
-- 关键逻辑:优先使用现有“房间支持活动”的父目录,确保新页面与活动记录同级。
INSERT INTO sys_menu (
parent_id,
menu_name,
path,
router,
menu_type,
icon,
alias,
sort,
status,
create_user,
update_user,
create_time,
update_time
)
SELECT
source_menu.parent_id,
'奖励发放记录',
'activity/reward-grant-record/index',
'activity/reward-grant-record',
2,
'form',
'activity:reward-grant-record',
source_menu.sort - 1,
0,
'0',
'0',
NOW(),
NOW()
FROM sys_menu source_menu
LEFT JOIN sys_menu existing ON existing.alias = 'activity:reward-grant-record'
WHERE (
source_menu.router = 'activity/room/contribution'
OR source_menu.router = '/activity/room/contribution'
OR source_menu.path = 'activity/room-contribution-list/index'
OR source_menu.menu_name = '房间支持活动'
)
AND source_menu.menu_type = 2
AND existing.id IS NULL
LIMIT 1;
-- 关键逻辑:迁移可重复执行,已存在菜单时仍同步页面路径和所属目录。
UPDATE sys_menu reward_menu
JOIN (
SELECT parent_id, sort
FROM sys_menu
WHERE (
router = 'activity/room/contribution'
OR router = '/activity/room/contribution'
OR path = 'activity/room-contribution-list/index'
OR menu_name = '房间支持活动'
)
AND menu_type = 2
LIMIT 1
) source_menu ON 1 = 1
SET
reward_menu.parent_id = source_menu.parent_id,
reward_menu.menu_name = '奖励发放记录',
reward_menu.path = 'activity/reward-grant-record/index',
reward_menu.router = 'activity/reward-grant-record',
reward_menu.menu_type = 2,
reward_menu.icon = 'form',
reward_menu.sort = source_menu.sort - 1,
reward_menu.status = 0,
reward_menu.update_user = '0',
reward_menu.update_time = NOW()
WHERE reward_menu.alias = 'activity:reward-grant-record';
INSERT INTO sys_menu_resource (menu_id, resource_id)
SELECT menu.id, resource.id
FROM sys_menu menu
JOIN sys_resource resource ON resource.id = 'activity:reward-grant-record:page'
LEFT JOIN sys_menu_resource existing
ON existing.menu_id = menu.id
AND existing.resource_id = resource.id
WHERE menu.alias = 'activity:reward-grant-record'
AND existing.id IS NULL;
-- 关键逻辑:仅继承已有房间活动记录的角色,避免扩大后台数据可见范围。
INSERT INTO sys_role_menu (role_id, menu_id)
SELECT DISTINCT source_role.role_id, reward_menu.id
FROM sys_role_menu source_role
JOIN sys_menu source_menu ON source_menu.id = source_role.menu_id
JOIN sys_menu reward_menu ON reward_menu.alias = 'activity:reward-grant-record'
LEFT JOIN sys_role_menu existing
ON existing.role_id = source_role.role_id
AND existing.menu_id = reward_menu.id
WHERE (
source_menu.router = 'activity/room/contribution'
OR source_menu.router = '/activity/room/contribution'
OR source_menu.path = 'activity/room-contribution-list/index'
OR source_menu.menu_name = '房间支持活动'
)
AND source_menu.menu_type = 2
AND existing.id IS NULL;

View File

@ -0,0 +1,119 @@
-- Webconsole reward grant record menu and list API permission.
-- The menu follows the existing room contribution page and inherits only its roles.
SET NAMES utf8mb4;
INSERT INTO sys_resource (id, resource_name, mapping, method, auth_type, perm, update_time)
VALUES (
'activity:reward-grant-record:page',
'奖励发放记录列表',
'/reward-grant-record/page',
'GET',
3,
'activity:reward-grant-record:page',
NOW()
)
ON DUPLICATE KEY UPDATE
resource_name = VALUES(resource_name),
mapping = VALUES(mapping),
method = VALUES(method),
auth_type = VALUES(auth_type),
perm = VALUES(perm),
update_time = NOW();
-- 关键逻辑:优先使用现有“房间支持活动”的父目录,确保新页面与活动记录同级。
INSERT INTO sys_menu (
parent_id,
menu_name,
path,
router,
menu_type,
icon,
alias,
sort,
status,
create_user,
update_user,
create_time,
update_time
)
SELECT
source_menu.parent_id,
'奖励发放记录',
'activity/reward-grant-record/index',
'activity/reward-grant-record',
2,
'form',
'activity:reward-grant-record',
source_menu.sort - 1,
0,
'0',
'0',
NOW(),
NOW()
FROM sys_menu source_menu
LEFT JOIN sys_menu existing ON existing.alias = 'activity:reward-grant-record'
WHERE (
source_menu.router = 'activity/room/contribution'
OR source_menu.router = '/activity/room/contribution'
OR source_menu.path = 'activity/room-contribution-list/index'
OR source_menu.menu_name = '房间支持活动'
)
AND source_menu.menu_type = 2
AND existing.id IS NULL
LIMIT 1;
-- 关键逻辑:迁移可重复执行,已存在菜单时仍同步页面路径和所属目录。
UPDATE sys_menu reward_menu
JOIN (
SELECT parent_id, sort
FROM sys_menu
WHERE (
router = 'activity/room/contribution'
OR router = '/activity/room/contribution'
OR path = 'activity/room-contribution-list/index'
OR menu_name = '房间支持活动'
)
AND menu_type = 2
LIMIT 1
) source_menu ON 1 = 1
SET
reward_menu.parent_id = source_menu.parent_id,
reward_menu.menu_name = '奖励发放记录',
reward_menu.path = 'activity/reward-grant-record/index',
reward_menu.router = 'activity/reward-grant-record',
reward_menu.menu_type = 2,
reward_menu.icon = 'form',
reward_menu.sort = source_menu.sort - 1,
reward_menu.status = 0,
reward_menu.update_user = '0',
reward_menu.update_time = NOW()
WHERE reward_menu.alias = 'activity:reward-grant-record';
INSERT INTO sys_menu_resource (menu_id, resource_id)
SELECT menu.id, resource.id
FROM sys_menu menu
JOIN sys_resource resource ON resource.id = 'activity:reward-grant-record:page'
LEFT JOIN sys_menu_resource existing
ON existing.menu_id = menu.id
AND existing.resource_id = resource.id
WHERE menu.alias = 'activity:reward-grant-record'
AND existing.id IS NULL;
-- 关键逻辑:仅继承已有房间活动记录的角色,避免扩大后台数据可见范围。
INSERT INTO sys_role_menu (role_id, menu_id)
SELECT DISTINCT source_role.role_id, reward_menu.id
FROM sys_role_menu source_role
JOIN sys_menu source_menu ON source_menu.id = source_role.menu_id
JOIN sys_menu reward_menu ON reward_menu.alias = 'activity:reward-grant-record'
LEFT JOIN sys_role_menu existing
ON existing.role_id = source_role.role_id
AND existing.menu_id = reward_menu.id
WHERE (
source_menu.router = 'activity/room/contribution'
OR source_menu.router = '/activity/room/contribution'
OR source_menu.path = 'activity/room-contribution-list/index'
OR source_menu.menu_name = '房间支持活动'
)
AND source_menu.menu_type = 2
AND existing.id IS NULL;

View File

@ -2,8 +2,11 @@ package com.red.circle.other.inner.endpoint.activity.api;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.other.inner.model.cmd.activity.RoomContributionRewardRecordPageQryCmd;
import com.red.circle.other.inner.model.dto.activity.RoomContributionActivityCountDTO;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
/**
@ -30,4 +33,11 @@ public interface RoomContributionActivityCountClientApi {
@RequestParam("limitSize") Integer limitSize
);
/**
* 查询已成功直发给房主的周流水奖励记录.
*/
@PostMapping("/pageOwnerRewardSent")
ResultResponse<PageResult<RoomContributionActivityCountDTO>> pageOwnerRewardSent(
@RequestBody RoomContributionRewardRecordPageQryCmd qryCmd);
}

View File

@ -0,0 +1,33 @@
package com.red.circle.other.inner.model.cmd.activity;
import java.io.Serial;
import java.io.Serializable;
import java.util.Set;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 房间周流水奖励发放记录分页查询.
*/
@Data
@Accessors(chain = true)
public class RoomContributionRewardRecordPageQryCmd implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 房间ID集合为空时查询全部房间.
*/
private Set<Long> roomIds;
/**
* 当前页从1开始.
*/
private Integer current;
/**
* 每页数量.
*/
private Integer limitSize;
}

View File

@ -60,6 +60,21 @@ public class RoomContributionActivityCountDTO extends DTO implements Serializabl
*/
private BigDecimal balance;
/**
* 房主奖励金币直发事件ID.
*/
private String ownerRewardCoinsEventId;
/**
* 房主奖励金币直发时间.
*/
private Timestamp ownerRewardCoinsSentTime;
/**
* 房主奖励比例补差事件ID.
*/
private String ownerRewardRatioSupplementEventId;
/**
* 创建时间.
*/

View File

@ -13,6 +13,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author pengliang on 2023/5/26
@ -101,6 +102,13 @@ public interface WalletGoldClientApi {
@GetMapping("/existsEventId")
ResultResponse<Boolean> existsEventId(@RequestParam("eventId") String eventId);
/**
* 按事件ID批量查询金币流水.
*/
@PostMapping("/listByEventIds")
ResultResponse<List<WalletGoldAssetRecordDTO>> listByEventIds(
@RequestBody Set<String> eventIds);
/**
* 获取金币统计.

View File

@ -15,6 +15,7 @@ import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author pengliang on 2024/2/23
@ -93,6 +94,13 @@ public class WalletGoldClientCallback implements WalletGoldClient {
return ResultResponse.failure(CommonErrorCode.REQUEST_LIMITING);
}
@Override
public ResultResponse<List<WalletGoldAssetRecordDTO>> listByEventIds(Set<String> eventIds) {
log.warn("[listByEventIds] eventIds={}", JacksonUtils.toJson(eventIds));
// 奖励记录必须展示真实钱包流水熔断时明确失败不能用空列表伪装成发放 0 金币
return ResultResponse.failure(CommonErrorCode.REQUEST_LIMITING);
}
@Override
public ResultResponse<List<WalletGoldCountDTO>> listWalletGoldCount(String sysOrigin,
Integer groupNum) {

View File

@ -0,0 +1,30 @@
package com.red.circle.console.adapter.app.activity;
import com.red.circle.console.app.dto.clienobject.activity.RewardGrantRecordCO;
import com.red.circle.console.app.dto.cmd.app.activity.RewardGrantRecordQryCmd;
import com.red.circle.console.app.service.app.activity.RewardGrantRecordService;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.web.controller.BaseController;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 奖励发放记录后台接口.
*/
@RequiredArgsConstructor
@RestController
@RequestMapping("/reward-grant-record")
public class RewardGrantRecordRestController extends BaseController {
private final RewardGrantRecordService rewardGrantRecordService;
/**
* 分页查询.
*/
@GetMapping("/page")
public PageResult<RewardGrantRecordCO> page(RewardGrantRecordQryCmd qryCmd) {
return rewardGrantRecordService.pageQuery(qryCmd);
}
}

View File

@ -0,0 +1,181 @@
package com.red.circle.console.app.service.app.activity;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.console.app.dto.clienobject.activity.RewardGrantRecordCO;
import com.red.circle.console.app.dto.cmd.app.activity.RewardGrantRecordQryCmd;
import com.red.circle.console.app.dto.enums.RewardGrantTypeEnum;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.other.inner.endpoint.activity.RoomContributionActivityCountClient;
import com.red.circle.other.inner.endpoint.live.RoomManagerClient;
import com.red.circle.other.inner.endpoint.user.user.UserProfileClient;
import com.red.circle.other.inner.model.cmd.activity.RoomContributionRewardRecordPageQryCmd;
import com.red.circle.other.inner.model.dto.activity.RoomContributionActivityCountDTO;
import com.red.circle.other.inner.model.dto.live.RoomProfileDTO;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
import com.red.circle.wallet.inner.model.dto.WalletGoldAssetRecordDTO;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
/**
* 奖励发放记录实现.
*/
@Service
@RequiredArgsConstructor
public class RewardGrantRecordServiceImpl implements RewardGrantRecordService {
private static final String OWNER_REWARD_EVENT_PREFIX = "RCWR:";
private static final String OWNER_REWARD_SUPPLEMENT_EVENT_PREFIX = "RCWRS:";
private final UserProfileClient userProfileClient;
private final RoomManagerClient roomManagerClient;
private final RoomContributionActivityCountClient roomContributionActivityCountClient;
private final WalletGoldClient walletGoldClient;
@Override
public PageResult<RewardGrantRecordCO> pageQuery(RewardGrantRecordQryCmd qryCmd) {
RewardGrantTypeEnum rewardType = Objects.requireNonNullElse(qryCmd.getRewardType(),
RewardGrantTypeEnum.ROOM_WEEKLY_CONTRIBUTION);
if (rewardType != RewardGrantTypeEnum.ROOM_WEEKLY_CONTRIBUTION) {
return PageResult.newPageResult(qryCmd.getPageQuery().getLimit());
}
Set<Long> roomIds = resolveRoomIds(qryCmd.getUserAccount());
if (StringUtils.isNotBlank(qryCmd.getUserAccount()) && CollectionUtils.isEmpty(roomIds)) {
return PageResult.newPageResult(qryCmd.getPageQuery().getLimit());
}
RoomContributionRewardRecordPageQryCmd innerQry =
new RoomContributionRewardRecordPageQryCmd()
.setRoomIds(roomIds)
.setCurrent(qryCmd.getPageQuery().getCursor())
.setLimitSize(qryCmd.getPageQuery().getLimit());
PageResult<RoomContributionActivityCountDTO> pageResult = ResponseAssert.requiredSuccess(
roomContributionActivityCountClient.pageOwnerRewardSent(innerQry));
if (CollectionUtils.isEmpty(pageResult.getRecords())) {
return pageResult.emptyRecords();
}
Map<Long, RoomProfileDTO> roomProfileMap = loadRooms(pageResult.getRecords());
Map<Long, UserProfileDTO> userProfileMap = loadUsers(roomProfileMap);
WalletRewardData walletRewardData = loadWalletRewardData(pageResult.getRecords());
return pageResult.convert(record -> {
RoomProfileDTO room = roomProfileMap.get(record.getRoomId());
Long userId = Objects.nonNull(room) ? room.getUserId() : null;
Set<String> eventIds = rewardEventIds(record);
long rewardPenny = eventIds.stream()
.mapToLong(eventId -> walletRewardData.amountByEventId().getOrDefault(eventId, 0L))
.sum();
Timestamp grantTime = eventIds.stream()
.map(walletRewardData.timeByEventId()::get)
.filter(Objects::nonNull)
.max(Timestamp::compareTo)
.orElse(record.getOwnerRewardCoinsSentTime());
return new RewardGrantRecordCO()
.setRewardType(rewardType)
.setUserProfile(userProfileMap.get(userId))
.setRoomProfile(room)
.setRoomContribution(record.getContributionValue())
// 钱包以分存储页面统一展示金币单位
.setRewardCoins(BigDecimal.valueOf(rewardPenny, 2))
.setDateNumber(record.getDateNumber())
.setGrantTime(grantTime);
});
}
private Set<Long> resolveRoomIds(String userAccount) {
if (StringUtils.isBlank(userAccount)) {
return null;
}
// 平台内查询会先匹配短ID未命中时继续匹配有效靓号避免跨平台同号导致漏查
UserProfileDTO user = ResponseAssert.requiredSuccess(userProfileClient.getByAccount(
SysOriginPlatformEnum.ATYOU.name(), userAccount.trim()));
if (Objects.isNull(user) || Objects.isNull(user.getId())) {
return Collections.emptySet();
}
Map<Long, RoomProfileDTO> rooms = ResponseAssert.requiredSuccess(
roomManagerClient.mapProfileByUserIds(Set.of(user.getId())));
return rooms.values().stream()
.filter(Objects::nonNull)
.map(RoomProfileDTO::getId)
.collect(Collectors.toSet());
}
private Map<Long, RoomProfileDTO> loadRooms(
Collection<RoomContributionActivityCountDTO> records) {
Set<Long> roomIds = records.stream()
.map(RoomContributionActivityCountDTO::getRoomId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
return ResponseAssert.requiredSuccess(roomManagerClient.mapProfileByRoomIds(roomIds));
}
private Map<Long, UserProfileDTO> loadUsers(Map<Long, RoomProfileDTO> roomProfileMap) {
Set<Long> userIds = roomProfileMap.values().stream()
.filter(Objects::nonNull)
.map(RoomProfileDTO::getUserId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
if (CollectionUtils.isEmpty(userIds)) {
return Collections.emptyMap();
}
return ResponseAssert.requiredSuccess(userProfileClient.mapByUserIds(userIds));
}
private WalletRewardData loadWalletRewardData(
Collection<RoomContributionActivityCountDTO> records) {
Set<String> eventIds = records.stream()
.map(this::rewardEventIds)
.flatMap(Set::stream)
.collect(Collectors.toSet());
List<WalletGoldAssetRecordDTO> walletRecords = ResponseAssert.requiredSuccess(
walletGoldClient.listByEventIds(eventIds));
Map<String, Long> amountByEventId = new HashMap<>();
Map<String, Timestamp> timeByEventId = new HashMap<>();
walletRecords.stream()
.filter(Objects::nonNull)
.filter(record -> Objects.equals(record.getType(), 0))
.forEach(record -> {
amountByEventId.merge(record.getEventId(),
Objects.requireNonNullElse(record.getPennyAmount(), 0L), Long::sum);
if (Objects.nonNull(record.getCreateTime())) {
timeByEventId.merge(record.getEventId(), record.getCreateTime(),
(left, right) -> left.after(right) ? left : right);
}
});
return new WalletRewardData(amountByEventId, timeByEventId);
}
private Set<String> rewardEventIds(RoomContributionActivityCountDTO record) {
Set<String> eventIds = new HashSet<>();
eventIds.add(StringUtils.defaultIfBlank(record.getOwnerRewardCoinsEventId(),
OWNER_REWARD_EVENT_PREFIX + record.getId()));
// 兼容补差字段上线前已发放的数据派生事件ID后查询实际钱包流水
eventIds.add(StringUtils.defaultIfBlank(record.getOwnerRewardRatioSupplementEventId(),
OWNER_REWARD_SUPPLEMENT_EVENT_PREFIX + record.getId()));
return eventIds;
}
private record WalletRewardData(Map<String, Long> amountByEventId,
Map<String, Timestamp> timeByEventId) {
}
}

View File

@ -0,0 +1,32 @@
package com.red.circle.console.app.dto.clienobject.activity;
import com.red.circle.console.app.dto.enums.RewardGrantTypeEnum;
import com.red.circle.framework.dto.ClientObject;
import com.red.circle.other.inner.model.dto.live.RoomProfileDTO;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import java.io.Serial;
import java.math.BigDecimal;
import java.sql.Timestamp;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 奖励发放记录.
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class RewardGrantRecordCO extends ClientObject {
@Serial
private static final long serialVersionUID = 1L;
private RewardGrantTypeEnum rewardType;
private UserProfileDTO userProfile;
private RoomProfileDTO roomProfile;
private BigDecimal roomContribution;
private BigDecimal rewardCoins;
private Integer dateNumber;
private Timestamp grantTime;
}

View File

@ -0,0 +1,30 @@
package com.red.circle.console.app.dto.cmd.app.activity;
import com.red.circle.console.app.dto.enums.RewardGrantTypeEnum;
import com.red.circle.framework.core.dto.PageCommand;
import java.io.Serial;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 奖励发放记录分页查询.
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class RewardGrantRecordQryCmd extends PageCommand {
@Serial
private static final long serialVersionUID = 1L;
/**
* 奖励类型.
*/
private RewardGrantTypeEnum rewardType = RewardGrantTypeEnum.ROOM_WEEKLY_CONTRIBUTION;
/**
* 用户短ID或靓号.
*/
private String userAccount;
}

View File

@ -0,0 +1,12 @@
package com.red.circle.console.app.dto.enums;
/**
* 后台奖励发放记录类型.
*/
public enum RewardGrantTypeEnum {
/**
* 房间周流水奖励.
*/
ROOM_WEEKLY_CONTRIBUTION
}

View File

@ -0,0 +1,16 @@
package com.red.circle.console.app.service.app.activity;
import com.red.circle.console.app.dto.clienobject.activity.RewardGrantRecordCO;
import com.red.circle.console.app.dto.cmd.app.activity.RewardGrantRecordQryCmd;
import com.red.circle.framework.dto.PageResult;
/**
* 奖励发放记录.
*/
public interface RewardGrantRecordService {
/**
* 分页查询奖励发放记录.
*/
PageResult<RewardGrantRecordCO> pageQuery(RewardGrantRecordQryCmd qryCmd);
}

View File

@ -6,6 +6,7 @@ import com.red.circle.other.infra.database.mongo.entity.activity.RoomContributio
import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.apache.commons.lang3.tuple.ImmutablePair;
/**
@ -85,6 +86,12 @@ public interface RoomContributionActivityCountService {
PageResult<RoomContributionActivityCount> pageReceived(long pageNumber, long pageSize,
Long roomId);
/**
* 已成功直发给房主的周流水奖励分页记录.
*/
PageResult<RoomContributionActivityCount> pageOwnerRewardSent(long pageNumber, long pageSize,
Set<Long> roomIds);
/**
*
* @param roomId

View File

@ -19,6 +19,7 @@ import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.RequiredArgsConstructor;
@ -273,6 +274,18 @@ public class RoomContributionActivityCountServiceImpl implements
(int) pageNumber, Sort.Order.desc("createTime"));
}
@Override
public PageResult<RoomContributionActivityCount> pageOwnerRewardSent(long pageNumber,
long pageSize, Set<Long> roomIds) {
Criteria criteria = Criteria.where("ownerRewardCoinsSent").is(Boolean.TRUE);
if (CollectionUtils.isNotEmpty(roomIds)) {
// 账号筛选先解析成房间ID避免在奖励集合中做跨集合或模糊查询
criteria.and("roomId").in(roomIds);
}
return mongoPageHelper.query(new Query(criteria), RoomContributionActivityCount.class,
(int) pageSize, (int) pageNumber, Sort.Order.desc("ownerRewardCoinsSentTime"));
}
@Override
public List<RoomContributionActivityCount> listRoomContributionByPH(Long roomId,BigDecimal number) {

View File

@ -4,6 +4,7 @@ import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.other.app.inner.service.activity.RoomContributionActivityCountClientService;
import com.red.circle.other.inner.endpoint.activity.api.RoomContributionActivityCountClientApi;
import com.red.circle.other.inner.model.cmd.activity.RoomContributionRewardRecordPageQryCmd;
import com.red.circle.other.inner.model.dto.activity.RoomContributionActivityCountDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
@ -33,4 +34,11 @@ public class RoomContributionActivityCountClientEndpoint implements
);
}
@Override
public ResultResponse<PageResult<RoomContributionActivityCountDTO>> pageOwnerRewardSent(
RoomContributionRewardRecordPageQryCmd qryCmd) {
return ResultResponse.success(
roomContributionActivityCountClientService.pageOwnerRewardSent(qryCmd));
}
}

View File

@ -1,6 +1,7 @@
package com.red.circle.other.app.inner.service.activity;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.other.inner.model.cmd.activity.RoomContributionRewardRecordPageQryCmd;
import com.red.circle.other.inner.model.dto.activity.RoomContributionActivityCountDTO;
/**
@ -22,4 +23,10 @@ public interface RoomContributionActivityCountClientService {
PageResult<RoomContributionActivityCountDTO> pageReceived(Long roomId, Integer current,
Integer limitSize);
/**
* 已成功直发给房主的周流水奖励记录.
*/
PageResult<RoomContributionActivityCountDTO> pageOwnerRewardSent(
RoomContributionRewardRecordPageQryCmd qryCmd);
}

View File

@ -4,6 +4,7 @@ import com.red.circle.framework.dto.PageResult;
import com.red.circle.other.app.inner.convertor.activity.RoomContributionActivityCountInnerConvertor;
import com.red.circle.other.app.inner.service.activity.RoomContributionActivityCountClientService;
import com.red.circle.other.infra.database.mongo.service.activity.RoomContributionActivityCountService;
import com.red.circle.other.inner.model.cmd.activity.RoomContributionRewardRecordPageQryCmd;
import com.red.circle.other.inner.model.dto.activity.RoomContributionActivityCountDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@ -29,4 +30,12 @@ public class RoomContributionActivityCountClientServiceImpl implements
);
}
@Override
public PageResult<RoomContributionActivityCountDTO> pageOwnerRewardSent(
RoomContributionRewardRecordPageQryCmd qryCmd) {
return roomContributionActivityCountInnerConvertor.toPageRoomContributionActivityCountDTO(
roomContributionActivityCountService.pageOwnerRewardSent(qryCmd.getCurrent(),
qryCmd.getLimitSize(), qryCmd.getRoomIds()));
}
}

View File

@ -3,6 +3,7 @@ package com.red.circle.wallet.infra.database.rds.service;
import com.red.circle.framework.mybatis.service.BaseService;
import com.red.circle.wallet.infra.database.rds.entity.WalletGoldAssetRecord;
import java.util.List;
import java.util.Set;
/**
* 用户金币资产流水 服务.
@ -21,6 +22,11 @@ public interface WalletGoldAssetRecordService extends BaseService<WalletGoldAsse
*/
boolean existsRecentEventId(String eventId);
/**
* 按事件ID批量查询资产流水.
*/
List<WalletGoldAssetRecord> listByEventIds(Set<String> eventIds);
/**
* 获取本月指定数量资产记录.
*/

View File

@ -10,6 +10,7 @@ import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import org.springframework.stereotype.Service;
/**
@ -22,6 +23,8 @@ public class WalletGoldAssetRecordServiceImpl extends
BaseServiceImpl<WalletGoldAssetRecordDAO, WalletGoldAssetRecord> implements
WalletGoldAssetRecordService {
private static final int MAX_EVENT_ID_QUERY_SIZE = 200;
@Override
public boolean existsRecent(Long id) {
return Optional.ofNullable(
@ -44,6 +47,22 @@ public class WalletGoldAssetRecordServiceImpl extends
.orElse(Boolean.FALSE);
}
@Override
public List<WalletGoldAssetRecord> listByEventIds(Set<String> eventIds) {
if (eventIds == null || eventIds.isEmpty()) {
return List.of();
}
if (eventIds.size() > MAX_EVENT_ID_QUERY_SIZE) {
throw new IllegalArgumentException("eventIds size must not exceed "
+ MAX_EVENT_ID_QUERY_SIZE);
}
// event_id在每个月分片表都有索引限制批量大小避免跨月分片广播成大范围查询
return query().in(WalletGoldAssetRecord::getEventId, eventIds)
.eq(WalletGoldAssetRecord::getType, 0)
.last(PageConstant.formatLimitStrict(eventIds.size()))
.list();
}
@Override
public List<WalletGoldAssetRecord> listThisMonth(String sysOrigin, Long userId, Integer type,
Long lastId,

View File

@ -14,6 +14,7 @@ import com.red.circle.wallet.inner.service.wallet.WalletGoldClientService;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
@ -99,6 +100,11 @@ public class WalletGoldClientEndpoint implements WalletGoldClientApi {
return ResultResponse.success(walletGoldClientService.existsEventId(eventId));
}
@Override
public ResultResponse<List<WalletGoldAssetRecordDTO>> listByEventIds(Set<String> eventIds) {
return ResultResponse.success(walletGoldClientService.listByEventIds(eventIds));
}
@Override
public ResultResponse<List<WalletGoldCountDTO>> listWalletGoldCount(String sysOrigin,
Integer groupNum) {

View File

@ -9,6 +9,7 @@ import com.red.circle.wallet.inner.model.cmd.UserGoldRunningWaterBackQryCmd;
import com.red.circle.wallet.inner.model.dto.*;
import java.util.List;
import java.util.Set;
/**
* @author pengliang on 2023/5/26
@ -65,6 +66,11 @@ public interface WalletGoldClientService {
*/
Boolean existsEventId(String eventId);
/**
* 按事件ID批量查询金币流水.
*/
List<WalletGoldAssetRecordDTO> listByEventIds(Set<String> eventIds);
/**
* 获取最近一个月流水信息(app).
*/

View File

@ -367,6 +367,13 @@ public class WalletGoldClientServiceImpl implements WalletGoldClientService {
return walletGoldAssetRecordService.existsRecentEventId(eventId);
}
@Override
public List<WalletGoldAssetRecordDTO> listByEventIds(Set<String> eventIds) {
return walletGoldAssetRecordService.listByEventIds(eventIds).stream()
.map(walletInnerConvertor::toWalletGoldAssetRecordDTO)
.toList();
}
@Override
public List<AssetRecordRunningWaterDTO> listThisMonth(String sysOrigin, Long userId, Integer type,
Long lastId) {