新增用户送礼物汇总查询

This commit is contained in:
tianfeng 2025-12-26 16:48:43 +08:00
parent 6ffebc79f8
commit 77a0068eb3
10 changed files with 283 additions and 0 deletions

View File

@ -2,10 +2,13 @@ package com.red.circle.other.inner.endpoint.material.gift.api;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.other.inner.model.cmd.gift.GiftGiveRunningWaterBackQryCmd;
import com.red.circle.other.inner.model.cmd.gift.GiftStatisticQryCmd;
import com.red.circle.other.inner.model.cmd.gift.SumAnchorTargetQryCmd;
import com.red.circle.other.inner.model.dto.gift.GiftGiveRunningWaterDTO;
import java.math.BigDecimal;
import java.util.List;
import com.red.circle.other.inner.model.dto.gift.GiftStatisticDTO;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@ -63,4 +66,11 @@ public interface GiftGiveRunningWaterClientApi {
*/
@PostMapping("/sumAnchorTargetLuckyGift")
ResultResponse<BigDecimal> sumAnchorTargetLuckyGift(@RequestBody SumAnchorTargetQryCmd query);
/**
* 按礼物ID分组统计礼物详细信息.
*/
@PostMapping("/queryGiftStatistic")
ResultResponse<List<GiftStatisticDTO>> queryGiftStatistic(
@RequestBody GiftStatisticQryCmd query);
}

View File

@ -0,0 +1,33 @@
package com.red.circle.other.inner.model.cmd.gift;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
import lombok.Data;
/**
* 礼物统计查询命令
*/
@Data
public class GiftStatisticQryCmd {
/**
* 发送礼物的人IDnull表示查询所有发送人
*/
private Long userId;
/**
* 接收礼物的人ID主播ID
*/
@NotNull(message = "接收人ID不能为空")
private Long acceptUserId;
/**
* 开始时间
*/
private LocalDateTime startTime;
/**
* 结束时间
*/
private LocalDateTime endTime;
}

View File

@ -0,0 +1,51 @@
package com.red.circle.other.inner.model.dto.gift;
import java.math.BigDecimal;
import lombok.Data;
/**
* 礼物统计结果
*/
@Data
public class GiftStatisticDTO {
/**
* 礼物ID
*/
private Long giftId;
/**
* 礼物名称
*/
private String giftName;
/**
* 礼物类型
*/
private String giftType;
/**
* 是否幸运礼物
*/
private Boolean luckyGift;
/**
* 赠送次数记录数
*/
private Integer totalCount;
/**
* 总数量礼物个数累加
*/
private Integer totalQuantity;
/**
* 总价值礼物价值累加
*/
private BigDecimal totalGiftValue;
/**
* 总目标金额实际到账金额累加
*/
private BigDecimal totalTargetAmount;
}

View File

@ -0,0 +1,46 @@
package com.red.circle.other.infra.database.mongo.dto;
import java.math.BigDecimal;
import lombok.Data;
/**
* 礼物统计结果
*/
@Data
public class GiftStatisticResult {
/**
* 礼物ID
*/
private Long giftId;
/**
* 礼物类型
*/
private String giftType;
/**
* 是否幸运礼物
*/
private Boolean luckyGift;
/**
* 赠送次数记录数
*/
private Integer totalCount;
/**
* 总数量礼物个数累加
*/
private Integer totalQuantity;
/**
* 总价值礼物价值累加
*/
private BigDecimal totalGiftValue;
/**
* 总目标金额实际到账金额累加
*/
private BigDecimal totalTargetAmount;
}

View File

@ -1,6 +1,7 @@
package com.red.circle.other.infra.database.mongo.service.gift;
import com.red.circle.other.infra.database.mongo.dto.CountExclusiveGift;
import com.red.circle.other.infra.database.mongo.dto.GiftStatisticResult;
import com.red.circle.other.infra.database.mongo.dto.RoomActiveIndexDTO;
import com.red.circle.other.infra.database.mongo.dto.query.GiftGiveRunningWaterQuery;
import com.red.circle.other.infra.database.mongo.dto.query.NewSumAnchorTargetQuery;
@ -122,4 +123,16 @@ public interface GiftGiveRunningWaterService {
List<String> listByTrackId(List<String> trackIds);
List<GiftGiveRunningWater> listLatest(LocalDateTime startTime);
/**
* 按礼物ID分组统计礼物详细信息.
*
* @param userId 发送礼物的人IDnull表示查询所有发送人
* @param acceptUserId 接收礼物的人ID主播ID
* @param startTime 开始时间
* @param endTime 结束时间
* @return 礼物统计结果列表
*/
List<GiftStatisticResult> queryGiftStatisticGroupByGiftId(
Long userId, Long acceptUserId, LocalDateTime startTime, LocalDateTime endTime);
}

View File

@ -6,6 +6,7 @@ import com.mongodb.client.model.Filters;
import com.red.circle.component.mongodb.config.MongoPrimaryService;
import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.other.infra.database.mongo.dto.CountExclusiveGift;
import com.red.circle.other.infra.database.mongo.dto.GiftStatisticResult;
import com.red.circle.other.infra.database.mongo.dto.RoomActiveIndexDTO;
import com.red.circle.other.infra.database.mongo.dto.query.GiftGiveRunningWaterQuery;
import com.red.circle.other.infra.database.mongo.dto.query.NewSumAnchorTargetQuery;
@ -36,6 +37,7 @@ import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
@ -645,4 +647,80 @@ public class GiftGiveRunningWaterServiceImpl implements GiftGiveRunningWaterServ
}
return quantityLong;
}
@Override
public List<GiftStatisticResult> queryGiftStatisticGroupByGiftId(
Long userId, Long acceptUserId, LocalDateTime startTime, LocalDateTime endTime) {
List<AggregationOperation> operations = Lists.newArrayList();
Criteria criteria = new Criteria();
if (userId != null) {
criteria.and("userId").is(userId);
}
if (startTime != null && endTime != null) {
criteria.and("createTime").gte(startTime).lte(endTime);
} else if (startTime != null) {
criteria.and("createTime").gte(startTime);
} else if (endTime != null) {
criteria.and("createTime").lte(endTime);
}
if (!criteria.getCriteriaObject().isEmpty()) {
operations.add(Aggregation.match(criteria));
}
operations.add(Aggregation.unwind("acceptUsers"));
operations.add(Aggregation.match(Criteria.where("acceptUsers.acceptUserId").is(acceptUserId)));
operations.add(Aggregation.group("giftId")
.first("giftId").as("giftId")
.first("giftType").as("giftType")
.first("luckyGift").as("luckyGift")
.count().as("totalCount")
.sum("giftValue.quantity").as("totalQuantity")
.sum("giftValue.giftValue").as("totalGiftValue")
.sum("acceptUsers.targetAmount").as("totalTargetAmount")
);
operations.add(Aggregation.sort(Sort.Direction.DESC, "totalTargetAmount"));
Aggregation aggregation = Aggregation.newAggregation(operations);
AggregationResults<Document> results = mongoTemplate.aggregate(
aggregation,
"gift_give_running_water",
Document.class
);
return results.getMappedResults().stream()
.map(this::convertToGiftStatisticResult)
.collect(Collectors.toList());
}
private GiftStatisticResult convertToGiftStatisticResult(Document doc) {
GiftStatisticResult result = new GiftStatisticResult();
result.setGiftId(doc.getLong("giftId"));
result.setGiftType(doc.getString("giftType"));
result.setLuckyGift(doc.getBoolean("luckyGift", false));
result.setTotalCount(doc.getInteger("totalCount", 0));
result.setTotalQuantity(doc.getInteger("totalQuantity", 0));
result.setTotalGiftValue(convertToBigDecimal(doc.get("totalGiftValue")));
result.setTotalTargetAmount(convertToBigDecimal(doc.get("totalTargetAmount")));
return result;
}
private BigDecimal convertToBigDecimal(Object value) {
if (value == null) {
return BigDecimal.ZERO;
}
if (value instanceof Decimal128) {
return ((Decimal128) value).bigDecimalValue();
} else if (value instanceof BigDecimal) {
return (BigDecimal) value;
} else if (value instanceof Number) {
return new BigDecimal(value.toString());
}
return BigDecimal.ZERO;
}
}

View File

@ -0,0 +1,18 @@
package com.red.circle.other.app.inner.convertor.material;
import com.red.circle.framework.core.convertor.ConvertorModel;
import com.red.circle.other.infra.database.mongo.dto.GiftStatisticResult;
import com.red.circle.other.inner.model.dto.gift.GiftStatisticDTO;
import java.util.List;
import org.mapstruct.Mapper;
/**
* 礼物统计转换器
*/
@Mapper(componentModel = ConvertorModel.SPRING)
public interface GiftStatisticInnerConvertor {
List<GiftStatisticDTO> toListGiftStatisticDTO(List<GiftStatisticResult> results);
GiftStatisticDTO toGiftStatisticDTO(GiftStatisticResult result);
}

View File

@ -4,10 +4,13 @@ import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.other.app.inner.service.material.gift.GiftGiveRunningWaterClientService;
import com.red.circle.other.inner.endpoint.material.gift.api.GiftGiveRunningWaterClientApi;
import com.red.circle.other.inner.model.cmd.gift.GiftGiveRunningWaterBackQryCmd;
import com.red.circle.other.inner.model.cmd.gift.GiftStatisticQryCmd;
import com.red.circle.other.inner.model.cmd.gift.SumAnchorTargetQryCmd;
import com.red.circle.other.inner.model.dto.gift.GiftGiveRunningWaterDTO;
import java.math.BigDecimal;
import java.util.List;
import com.red.circle.other.inner.model.dto.gift.GiftStatisticDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
@ -64,4 +67,9 @@ public class GiftGiveRunningWaterClientEndpoint implements GiftGiveRunningWaterC
return ResultResponse.success(
giftGiveRunningWaterClientService.sumAnchorTargetLuckyGift(query));
}
@Override
public ResultResponse<List<GiftStatisticDTO>> queryGiftStatistic(GiftStatisticQryCmd query) {
return ResultResponse.success(giftGiveRunningWaterClientService.queryGiftStatistic(query));
}
}

View File

@ -1,8 +1,12 @@
package com.red.circle.other.app.inner.service.material.gift;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.other.inner.model.cmd.gift.GiftGiveRunningWaterBackQryCmd;
import com.red.circle.other.inner.model.cmd.gift.GiftStatisticQryCmd;
import com.red.circle.other.inner.model.cmd.gift.SumAnchorTargetQryCmd;
import com.red.circle.other.inner.model.dto.gift.GiftGiveRunningWaterDTO;
import com.red.circle.other.inner.model.dto.gift.GiftStatisticDTO;
import java.math.BigDecimal;
import java.util.List;
@ -47,4 +51,6 @@ public interface GiftGiveRunningWaterClientService {
* 恢复主播幸运礼物目标.
*/
BigDecimal sumAnchorTargetLuckyGift(SumAnchorTargetQryCmd query);
List<GiftStatisticDTO> queryGiftStatistic(GiftStatisticQryCmd query);
}

View File

@ -2,7 +2,9 @@ package com.red.circle.other.app.inner.service.material.gift.impl;
import com.google.common.collect.Lists;
import com.red.circle.other.app.inner.convertor.material.GiftInnerConvertor;
import com.red.circle.other.app.inner.convertor.material.GiftStatisticInnerConvertor;
import com.red.circle.other.app.inner.service.material.gift.GiftGiveRunningWaterClientService;
import com.red.circle.other.infra.database.mongo.dto.GiftStatisticResult;
import com.red.circle.other.infra.database.mongo.entity.gift.GiftGiveRunningWater;
import com.red.circle.other.infra.database.mongo.entity.live.RoomProfile;
import com.red.circle.other.infra.database.mongo.service.gift.GiftGiveRunningWaterService;
@ -10,8 +12,10 @@ import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManager
import com.red.circle.other.infra.database.rds.entity.gift.GiftConfig;
import com.red.circle.other.infra.database.rds.service.gift.GiftConfigService;
import com.red.circle.other.inner.model.cmd.gift.GiftGiveRunningWaterBackQryCmd;
import com.red.circle.other.inner.model.cmd.gift.GiftStatisticQryCmd;
import com.red.circle.other.inner.model.cmd.gift.SumAnchorTargetQryCmd;
import com.red.circle.other.inner.model.dto.gift.GiftGiveRunningWaterDTO;
import com.red.circle.other.inner.model.dto.gift.GiftStatisticDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.regex.RegexConstant;
import java.math.BigDecimal;
@ -33,6 +37,7 @@ public class GiftGiveRunningWaterClientServiceImpl implements GiftGiveRunningWat
private final GiftConfigService giftConfigService;
private final GiftInnerConvertor giftInnerConvertor;
private final GiftStatisticInnerConvertor giftStatisticInnerConvertor;
private final RoomProfileManagerService roomProfileManagerService;
private final GiftGiveRunningWaterService giftGiveRunningWaterService;
@ -107,4 +112,19 @@ public class GiftGiveRunningWaterClientServiceImpl implements GiftGiveRunningWat
public BigDecimal sumAnchorTargetLuckyGift(SumAnchorTargetQryCmd query) {
return giftGiveRunningWaterService.sumAnchorTargetLuckyGift(query);
}
@Override
public List<GiftStatisticDTO> queryGiftStatistic(GiftStatisticQryCmd query) {
List<GiftStatisticResult> results =
giftGiveRunningWaterService.queryGiftStatisticGroupByGiftId(
query.getUserId(),
query.getAcceptUserId(),
query.getStartTime(),
query.getEndTime()
);
Map<Long, GiftConfig> configMap = giftConfigService.listByIds(results.stream().map(GiftStatisticResult::getGiftId).collect(Collectors.toSet()))
.stream().collect(Collectors.toMap(GiftConfig::getId, e -> e, (v1, v2) -> v1));
return giftStatisticInnerConvertor.toListGiftStatisticDTO(results)
.stream().peek(e -> e.setGiftName(configMap.getOrDefault(e.getGiftId(), null).getGiftName())).toList();
}
}