统计:会员分析数据接口重构

This commit is contained in:
owen 2023-10-16 13:52:00 +08:00
parent 8e35a786ba
commit d3385dcb4f
6 changed files with 57 additions and 36 deletions

View File

@ -1,11 +1,16 @@
package cn.iocoder.yudao.module.statistics.controller.admin.member; package cn.iocoder.yudao.module.statistics.controller.admin.member;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.NumberUtil;
import cn.iocoder.yudao.framework.common.enums.TerminalEnum; import cn.iocoder.yudao.framework.common.enums.TerminalEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO; import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO;
import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.*; import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.*;
import cn.iocoder.yudao.module.statistics.convert.member.MemberStatisticsConvert;
import cn.iocoder.yudao.module.statistics.service.infra.ApiAccessLogStatisticsService;
import cn.iocoder.yudao.module.statistics.service.member.MemberStatisticsService; import cn.iocoder.yudao.module.statistics.service.member.MemberStatisticsService;
import cn.iocoder.yudao.module.statistics.service.trade.TradeOrderStatisticsService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -16,6 +21,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -30,6 +36,10 @@ public class MemberStatisticsController {
@Resource @Resource
private MemberStatisticsService memberStatisticsService; private MemberStatisticsService memberStatisticsService;
@Resource
private TradeOrderStatisticsService tradeOrderStatisticsService;
@Resource
private ApiAccessLogStatisticsService apiAccessLogStatisticsService;
// TODO 芋艿已经 review // TODO 芋艿已经 review
@GetMapping("/summary") @GetMapping("/summary")
@ -44,8 +54,28 @@ public class MemberStatisticsController {
@Operation(summary = "获得会员分析数据") @Operation(summary = "获得会员分析数据")
@PreAuthorize("@ss.hasPermission('statistics:member:query')") @PreAuthorize("@ss.hasPermission('statistics:member:query')")
public CommonResult<MemberAnalyseRespVO> getMemberAnalyse(MemberAnalyseReqVO reqVO) { public CommonResult<MemberAnalyseRespVO> getMemberAnalyse(MemberAnalyseReqVO reqVO) {
return success(memberStatisticsService.getMemberAnalyse( // 1. 查询数据
ArrayUtil.get(reqVO.getTimes(), 0), ArrayUtil.get(reqVO.getTimes(), 1))); LocalDateTime beginTime = ArrayUtil.get(reqVO.getTimes(), 0);
LocalDateTime endTime = ArrayUtil.get(reqVO.getTimes(), 1);
// 1.1 查询分析对照数据
DataComparisonRespVO<MemberAnalyseDataRespVO> comparisonData = memberStatisticsService.getMemberAnalyseComparisonData(beginTime, endTime);
// TODO @疯狂这个可能有点特殊要按照 create_time 来查询不然它的漏斗就不统一因为是访问数量 > 今日下单人 > 今日支付人是一个统一的维度
// 1.2 查询成交用户数量
Integer payUserCount = tradeOrderStatisticsService.getPayUserCount(beginTime, endTime);
// 1.3 计算客单价
int atv = 0;
if (payUserCount != null && payUserCount > 0) {
// TODO @疯狂类似上面的 payUserCount
Integer payPrice = tradeOrderStatisticsService.getOrderPayPrice(beginTime, endTime);
atv = NumberUtil.div(payPrice, payUserCount).intValue();
}
// 1.4 查询访客数量
Integer visitUserCount = apiAccessLogStatisticsService.getIpCount(UserTypeEnum.MEMBER.getValue(), beginTime, endTime);
// 1.5 下单用户数量
Integer orderUserCount = tradeOrderStatisticsService.getOrderUserCount(beginTime, endTime);
// 2. 拼接返回
return success(MemberStatisticsConvert.INSTANCE.convert(visitUserCount, orderUserCount, payUserCount, atv, comparisonData));
} }
// TODO 芋艿已经 review // TODO 芋艿已经 review

View File

@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.statistics.controller.admin.member.vo;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@Schema(description = "管理后台 - 会员分析对照数据 Response VO") @Schema(description = "管理后台 - 会员分析数据 Response VO")
@Data @Data
public class MemberAnalyseComparisonRespVO { public class MemberAnalyseDataRespVO {
@Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer registerUserCount; private Integer registerUserCount;

View File

@ -21,6 +21,6 @@ public class MemberAnalyseRespVO {
private Integer atv; private Integer atv;
@Schema(description = "对照数据", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "对照数据", requiredMode = Schema.RequiredMode.REQUIRED)
private DataComparisonRespVO<MemberAnalyseComparisonRespVO> comparison; private DataComparisonRespVO<MemberAnalyseDataRespVO> comparison;
} }

View File

@ -4,6 +4,9 @@ import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.ip.core.Area; import cn.iocoder.yudao.framework.ip.core.Area;
import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO;
import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAnalyseDataRespVO;
import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAnalyseRespVO;
import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAreaStatisticsRespVO; import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAreaStatisticsRespVO;
import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberSummaryRespVO; import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberSummaryRespVO;
import cn.iocoder.yudao.module.statistics.service.pay.bo.RechargeSummaryRespBO; import cn.iocoder.yudao.module.statistics.service.pay.bo.RechargeSummaryRespBO;
@ -28,7 +31,8 @@ public interface MemberStatisticsConvert {
Map<Integer, Integer> userCountMap, Map<Integer, Integer> userCountMap,
Map<Integer, MemberAreaStatisticsRespVO> orderMap) { Map<Integer, MemberAreaStatisticsRespVO> orderMap) {
return CollectionUtils.convertList(areaList, area -> { return CollectionUtils.convertList(areaList, area -> {
MemberAreaStatisticsRespVO orderVo = Optional.ofNullable(orderMap.get(area.getId())).orElseGet(MemberAreaStatisticsRespVO::new); MemberAreaStatisticsRespVO orderVo = Optional.ofNullable(orderMap.get(area.getId()))
.orElseGet(MemberAreaStatisticsRespVO::new);
return new MemberAreaStatisticsRespVO() return new MemberAreaStatisticsRespVO()
.setAreaId(area.getId()).setAreaName(area.getName()) .setAreaId(area.getId()).setAreaName(area.getName())
.setUserCount(MapUtil.getInt(userCountMap, area.getId(), 0)) .setUserCount(MapUtil.getInt(userCountMap, area.getId(), 0))
@ -40,4 +44,7 @@ public interface MemberStatisticsConvert {
MemberSummaryRespVO convert(RechargeSummaryRespBO rechargeSummary, Integer expensePrice, Integer userCount); MemberSummaryRespVO convert(RechargeSummaryRespBO rechargeSummary, Integer expensePrice, Integer userCount);
MemberAnalyseRespVO convert(Integer visitUserCount, Integer orderUserCount, Integer payUserCount, int atv,
DataComparisonRespVO<MemberAnalyseDataRespVO> comparison);
} }

View File

@ -21,15 +21,15 @@ public interface MemberStatisticsService {
*/ */
MemberSummaryRespVO getMemberSummary(); MemberSummaryRespVO getMemberSummary();
// TODO 芋艿已经 review
/** /**
* 获取用户分析数据 * 获取会员分析对照数据
* *
* @param beginTime 起始时间 * @param beginTime 起始时间
* @param endTime 截止时间 * @param endTime 截止时间
* @return 用户分析数据 * @return 会员分析对照数据
*/ */
MemberAnalyseRespVO getMemberAnalyse(LocalDateTime beginTime, LocalDateTime endTime); DataComparisonRespVO<MemberAnalyseDataRespVO> getMemberAnalyseComparisonData(LocalDateTime beginTime,
LocalDateTime endTime);
/** /**
* 按照省份获得会员统计列表 * 按照省份获得会员统计列表

View File

@ -1,7 +1,6 @@
package cn.iocoder.yudao.module.statistics.service.member; package cn.iocoder.yudao.module.statistics.service.member;
import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.NumberUtil;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.ip.core.Area; import cn.iocoder.yudao.framework.ip.core.Area;
import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum;
@ -79,37 +78,22 @@ public class MemberStatisticsServiceImpl implements MemberStatisticsService {
return MemberStatisticsConvert.INSTANCE.convertList(areaList, userCountMap, orderMap); return MemberStatisticsConvert.INSTANCE.convertList(areaList, userCountMap, orderMap);
} }
// TODO @疯狂这个方法要不拆成1controller 调用 getMemberAnalyseComparisonData2tradeOrderStatisticsService.getPayUserCount3tradeOrderStatisticsService.getOrderPayPrice4
// TODO 就是说分析交给 controller 去组合
@Override @Override
public MemberAnalyseRespVO getMemberAnalyse(LocalDateTime beginTime, LocalDateTime endTime) { public DataComparisonRespVO<MemberAnalyseDataRespVO> getMemberAnalyseComparisonData(LocalDateTime beginTime, LocalDateTime endTime) {
// 当前数据
MemberAnalyseDataRespVO vo = getMemberAnalyseData(beginTime, endTime);
// 对照数据 // 对照数据
MemberAnalyseComparisonRespVO vo = getMemberAnalyseComparisonData(beginTime, endTime); LocalDateTime referenceEndDate = beginTime.minusDays(1); // 减少1天防止出现时间重叠
// TODO @疯狂如果时间段这么处理会不会 beginTime 重叠了因为是 <= 一个时间如果数据库插入的是 xxxx-yy-zz 00:00:00 的话它既满足 >= ? 也满足 <= 如果不好理解微信聊) LocalDateTime referenceBeginDate = referenceEndDate.minus(Duration.between(beginTime, endTime));
LocalDateTime referenceBeginTime = beginTime.minus(Duration.between(beginTime, endTime)); MemberAnalyseDataRespVO reference = getMemberAnalyseData(
MemberAnalyseComparisonRespVO reference = getMemberAnalyseComparisonData(referenceBeginTime, beginTime); LocalDateTimeUtil.beginOfDay(referenceBeginDate), LocalDateTimeUtil.endOfDay(referenceEndDate));
return new DataComparisonRespVO<>(vo, reference);
// 计算客单价
// TODO @疯狂这个可能有点特殊要按照 create_time 来查询不然它的漏斗就不统一因为是访问数量 > 今日下单人 > 今日支付人是一个统一的维度
Integer payUserCount = tradeOrderStatisticsService.getPayUserCount(beginTime, endTime);
int atv = 0;
if (payUserCount != null && payUserCount > 0) {
// TODO @疯狂类似上面的 payUserCount
Integer payPrice = tradeOrderStatisticsService.getOrderPayPrice(beginTime, endTime);
atv = NumberUtil.div(payPrice, payUserCount).intValue();
}
return new MemberAnalyseRespVO()
.setVisitUserCount(apiAccessLogStatisticsService.getIpCount(UserTypeEnum.MEMBER.getValue(), beginTime, endTime))
.setOrderUserCount(tradeOrderStatisticsService.getOrderUserCount(beginTime, endTime))
.setPayUserCount(payUserCount)
.setAtv(atv)
.setComparison(new DataComparisonRespVO<>(vo, reference));
} }
private MemberAnalyseComparisonRespVO getMemberAnalyseComparisonData(LocalDateTime beginTime, LocalDateTime endTime) { private MemberAnalyseDataRespVO getMemberAnalyseData(LocalDateTime beginTime, LocalDateTime endTime) {
Integer rechargeUserCount = Optional.ofNullable(payWalletStatisticsService.getUserRechargeSummary(beginTime, endTime)) Integer rechargeUserCount = Optional.ofNullable(payWalletStatisticsService.getUserRechargeSummary(beginTime, endTime))
.map(RechargeSummaryRespBO::getRechargeUserCount).orElse(0); .map(RechargeSummaryRespBO::getRechargeUserCount).orElse(0);
return new MemberAnalyseComparisonRespVO() return new MemberAnalyseDataRespVO()
.setRegisterUserCount(memberStatisticsMapper.selectUserCount(beginTime, endTime)) .setRegisterUserCount(memberStatisticsMapper.selectUserCount(beginTime, endTime))
.setVisitUserCount(apiAccessLogStatisticsService.getUserCount(UserTypeEnum.MEMBER.getValue(), beginTime, endTime)) .setVisitUserCount(apiAccessLogStatisticsService.getUserCount(UserTypeEnum.MEMBER.getValue(), beginTime, endTime))
.setRechargeUserCount(rechargeUserCount); .setRechargeUserCount(rechargeUserCount);