Commit d3385dcb4f7305e5632164e7c9b4defc3d0e58d5

Authored by owen
1 parent 8e35a786

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

yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/MemberStatisticsController.java
1 package cn.iocoder.yudao.module.statistics.controller.admin.member; 1 package cn.iocoder.yudao.module.statistics.controller.admin.member;
2 2
3 import cn.hutool.core.util.ArrayUtil; 3 import cn.hutool.core.util.ArrayUtil;
  4 +import cn.hutool.core.util.NumberUtil;
4 import cn.iocoder.yudao.framework.common.enums.TerminalEnum; 5 import cn.iocoder.yudao.framework.common.enums.TerminalEnum;
  6 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
5 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 7 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO; 8 import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO;
7 import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.*; 9 import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.*;
  10 +import cn.iocoder.yudao.module.statistics.convert.member.MemberStatisticsConvert;
  11 +import cn.iocoder.yudao.module.statistics.service.infra.ApiAccessLogStatisticsService;
8 import cn.iocoder.yudao.module.statistics.service.member.MemberStatisticsService; 12 import cn.iocoder.yudao.module.statistics.service.member.MemberStatisticsService;
  13 +import cn.iocoder.yudao.module.statistics.service.trade.TradeOrderStatisticsService;
9 import io.swagger.v3.oas.annotations.Operation; 14 import io.swagger.v3.oas.annotations.Operation;
10 import io.swagger.v3.oas.annotations.tags.Tag; 15 import io.swagger.v3.oas.annotations.tags.Tag;
11 import lombok.extern.slf4j.Slf4j; 16 import lombok.extern.slf4j.Slf4j;
@@ -16,6 +21,7 @@ import org.springframework.web.bind.annotation.RequestMapping; @@ -16,6 +21,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
16 import org.springframework.web.bind.annotation.RestController; 21 import org.springframework.web.bind.annotation.RestController;
17 22
18 import javax.annotation.Resource; 23 import javax.annotation.Resource;
  24 +import java.time.LocalDateTime;
19 import java.util.List; 25 import java.util.List;
20 26
21 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 27 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -30,6 +36,10 @@ public class MemberStatisticsController { @@ -30,6 +36,10 @@ public class MemberStatisticsController {
30 36
31 @Resource 37 @Resource
32 private MemberStatisticsService memberStatisticsService; 38 private MemberStatisticsService memberStatisticsService;
  39 + @Resource
  40 + private TradeOrderStatisticsService tradeOrderStatisticsService;
  41 + @Resource
  42 + private ApiAccessLogStatisticsService apiAccessLogStatisticsService;
33 43
34 // TODO 芋艿:已经 review 44 // TODO 芋艿:已经 review
35 @GetMapping("/summary") 45 @GetMapping("/summary")
@@ -44,8 +54,28 @@ public class MemberStatisticsController { @@ -44,8 +54,28 @@ public class MemberStatisticsController {
44 @Operation(summary = "获得会员分析数据") 54 @Operation(summary = "获得会员分析数据")
45 @PreAuthorize("@ss.hasPermission('statistics:member:query')") 55 @PreAuthorize("@ss.hasPermission('statistics:member:query')")
46 public CommonResult<MemberAnalyseRespVO> getMemberAnalyse(MemberAnalyseReqVO reqVO) { 56 public CommonResult<MemberAnalyseRespVO> getMemberAnalyse(MemberAnalyseReqVO reqVO) {
47 - return success(memberStatisticsService.getMemberAnalyse(  
48 - ArrayUtil.get(reqVO.getTimes(), 0), ArrayUtil.get(reqVO.getTimes(), 1))); 57 + // 1. 查询数据
  58 + LocalDateTime beginTime = ArrayUtil.get(reqVO.getTimes(), 0);
  59 + LocalDateTime endTime = ArrayUtil.get(reqVO.getTimes(), 1);
  60 + // 1.1 查询分析对照数据
  61 + DataComparisonRespVO<MemberAnalyseDataRespVO> comparisonData = memberStatisticsService.getMemberAnalyseComparisonData(beginTime, endTime);
  62 + // TODO @疯狂:这个可能有点特殊,要按照 create_time 来查询;不然它的漏斗就不统一;因为是访问数量 > 今日下单人 > 今日支付人;是一个统一的维度;
  63 + // 1.2 查询成交用户数量
  64 + Integer payUserCount = tradeOrderStatisticsService.getPayUserCount(beginTime, endTime);
  65 + // 1.3 计算客单价
  66 + int atv = 0;
  67 + if (payUserCount != null && payUserCount > 0) {
  68 + // TODO @疯狂:类似上面的 payUserCount
  69 + Integer payPrice = tradeOrderStatisticsService.getOrderPayPrice(beginTime, endTime);
  70 + atv = NumberUtil.div(payPrice, payUserCount).intValue();
  71 + }
  72 + // 1.4 查询访客数量
  73 + Integer visitUserCount = apiAccessLogStatisticsService.getIpCount(UserTypeEnum.MEMBER.getValue(), beginTime, endTime);
  74 + // 1.5 下单用户数量
  75 + Integer orderUserCount = tradeOrderStatisticsService.getOrderUserCount(beginTime, endTime);
  76 +
  77 + // 2. 拼接返回
  78 + return success(MemberStatisticsConvert.INSTANCE.convert(visitUserCount, orderUserCount, payUserCount, atv, comparisonData));
49 } 79 }
50 80
51 // TODO 芋艿:已经 review 81 // TODO 芋艿:已经 review
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAnalyseComparisonRespVO.java renamed to yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAnalyseDataRespVO.java
@@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.statistics.controller.admin.member.vo; @@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.statistics.controller.admin.member.vo;
3 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 import lombok.Data; 4 import lombok.Data;
5 5
6 -@Schema(description = "管理后台 - 会员分析对照数据 Response VO") 6 +@Schema(description = "管理后台 - 会员分析数据 Response VO")
7 @Data 7 @Data
8 -public class MemberAnalyseComparisonRespVO { 8 +public class MemberAnalyseDataRespVO {
9 9
10 @Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") 10 @Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
11 private Integer registerUserCount; 11 private Integer registerUserCount;
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAnalyseRespVO.java
@@ -21,6 +21,6 @@ public class MemberAnalyseRespVO { @@ -21,6 +21,6 @@ public class MemberAnalyseRespVO {
21 private Integer atv; 21 private Integer atv;
22 22
23 @Schema(description = "对照数据", requiredMode = Schema.RequiredMode.REQUIRED) 23 @Schema(description = "对照数据", requiredMode = Schema.RequiredMode.REQUIRED)
24 - private DataComparisonRespVO<MemberAnalyseComparisonRespVO> comparison; 24 + private DataComparisonRespVO<MemberAnalyseDataRespVO> comparison;
25 25
26 } 26 }
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/convert/member/MemberStatisticsConvert.java
@@ -4,6 +4,9 @@ import cn.hutool.core.map.MapUtil; @@ -4,6 +4,9 @@ import cn.hutool.core.map.MapUtil;
4 import cn.hutool.core.util.ObjUtil; 4 import cn.hutool.core.util.ObjUtil;
5 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 5 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
6 import cn.iocoder.yudao.framework.ip.core.Area; 6 import cn.iocoder.yudao.framework.ip.core.Area;
  7 +import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO;
  8 +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAnalyseDataRespVO;
  9 +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAnalyseRespVO;
7 import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAreaStatisticsRespVO; 10 import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAreaStatisticsRespVO;
8 import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberSummaryRespVO; 11 import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberSummaryRespVO;
9 import cn.iocoder.yudao.module.statistics.service.pay.bo.RechargeSummaryRespBO; 12 import cn.iocoder.yudao.module.statistics.service.pay.bo.RechargeSummaryRespBO;
@@ -28,7 +31,8 @@ public interface MemberStatisticsConvert { @@ -28,7 +31,8 @@ public interface MemberStatisticsConvert {
28 Map<Integer, Integer> userCountMap, 31 Map<Integer, Integer> userCountMap,
29 Map<Integer, MemberAreaStatisticsRespVO> orderMap) { 32 Map<Integer, MemberAreaStatisticsRespVO> orderMap) {
30 return CollectionUtils.convertList(areaList, area -> { 33 return CollectionUtils.convertList(areaList, area -> {
31 - MemberAreaStatisticsRespVO orderVo = Optional.ofNullable(orderMap.get(area.getId())).orElseGet(MemberAreaStatisticsRespVO::new); 34 + MemberAreaStatisticsRespVO orderVo = Optional.ofNullable(orderMap.get(area.getId()))
  35 + .orElseGet(MemberAreaStatisticsRespVO::new);
32 return new MemberAreaStatisticsRespVO() 36 return new MemberAreaStatisticsRespVO()
33 .setAreaId(area.getId()).setAreaName(area.getName()) 37 .setAreaId(area.getId()).setAreaName(area.getName())
34 .setUserCount(MapUtil.getInt(userCountMap, area.getId(), 0)) 38 .setUserCount(MapUtil.getInt(userCountMap, area.getId(), 0))
@@ -40,4 +44,7 @@ public interface MemberStatisticsConvert { @@ -40,4 +44,7 @@ public interface MemberStatisticsConvert {
40 44
41 MemberSummaryRespVO convert(RechargeSummaryRespBO rechargeSummary, Integer expensePrice, Integer userCount); 45 MemberSummaryRespVO convert(RechargeSummaryRespBO rechargeSummary, Integer expensePrice, Integer userCount);
42 46
  47 + MemberAnalyseRespVO convert(Integer visitUserCount, Integer orderUserCount, Integer payUserCount, int atv,
  48 + DataComparisonRespVO<MemberAnalyseDataRespVO> comparison);
  49 +
43 } 50 }
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsService.java
@@ -21,15 +21,15 @@ public interface MemberStatisticsService { @@ -21,15 +21,15 @@ public interface MemberStatisticsService {
21 */ 21 */
22 MemberSummaryRespVO getMemberSummary(); 22 MemberSummaryRespVO getMemberSummary();
23 23
24 - // TODO 芋艿:已经 review  
25 /** 24 /**
26 - * 获取用户分析数据 25 + * 获取会员分析对照数据
27 * 26 *
28 * @param beginTime 起始时间 27 * @param beginTime 起始时间
29 * @param endTime 截止时间 28 * @param endTime 截止时间
30 - * @return 用户分析数据 29 + * @return 会员分析对照数据
31 */ 30 */
32 - MemberAnalyseRespVO getMemberAnalyse(LocalDateTime beginTime, LocalDateTime endTime); 31 + DataComparisonRespVO<MemberAnalyseDataRespVO> getMemberAnalyseComparisonData(LocalDateTime beginTime,
  32 + LocalDateTime endTime);
33 33
34 /** 34 /**
35 * 按照省份,获得会员统计列表 35 * 按照省份,获得会员统计列表
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsServiceImpl.java
1 package cn.iocoder.yudao.module.statistics.service.member; 1 package cn.iocoder.yudao.module.statistics.service.member;
2 2
3 import cn.hutool.core.date.LocalDateTimeUtil; 3 import cn.hutool.core.date.LocalDateTimeUtil;
4 -import cn.hutool.core.util.NumberUtil;  
5 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; 4 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
6 import cn.iocoder.yudao.framework.ip.core.Area; 5 import cn.iocoder.yudao.framework.ip.core.Area;
7 import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; 6 import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum;
@@ -79,37 +78,22 @@ public class MemberStatisticsServiceImpl implements MemberStatisticsService { @@ -79,37 +78,22 @@ public class MemberStatisticsServiceImpl implements MemberStatisticsService {
79 return MemberStatisticsConvert.INSTANCE.convertList(areaList, userCountMap, orderMap); 78 return MemberStatisticsConvert.INSTANCE.convertList(areaList, userCountMap, orderMap);
80 } 79 }
81 80
82 - // TODO @疯狂:这个方法,要不拆成:1)controller 调用 getMemberAnalyseComparisonData;2)tradeOrderStatisticsService.getPayUserCount;3)tradeOrderStatisticsService.getOrderPayPrice;4)。。。  
83 - // TODO 就是说:分析交给 controller 去组合;  
84 @Override 81 @Override
85 - public MemberAnalyseRespVO getMemberAnalyse(LocalDateTime beginTime, LocalDateTime endTime) { 82 + public DataComparisonRespVO<MemberAnalyseDataRespVO> getMemberAnalyseComparisonData(LocalDateTime beginTime, LocalDateTime endTime) {
  83 + // 当前数据
  84 + MemberAnalyseDataRespVO vo = getMemberAnalyseData(beginTime, endTime);
86 // 对照数据 85 // 对照数据
87 - MemberAnalyseComparisonRespVO vo = getMemberAnalyseComparisonData(beginTime, endTime);  
88 - // TODO @疯狂:如果时间段这么处理,会不会 beginTime 重叠了。因为是 <= 一个时间;如果数据库插入的是 ,xxxx-yy-zz 00:00:00 的话,它既满足 >= ? 也满足 <= ;(如果不好理解,微信聊)  
89 - LocalDateTime referenceBeginTime = beginTime.minus(Duration.between(beginTime, endTime));  
90 - MemberAnalyseComparisonRespVO reference = getMemberAnalyseComparisonData(referenceBeginTime, beginTime);  
91 -  
92 - // 计算客单价  
93 - // TODO @疯狂:这个可能有点特殊,要按照 create_time 来查询;不然它的漏斗就不统一;因为是访问数量 > 今日下单人 > 今日支付人;是一个统一的维度;  
94 - Integer payUserCount = tradeOrderStatisticsService.getPayUserCount(beginTime, endTime);  
95 - int atv = 0;  
96 - if (payUserCount != null && payUserCount > 0) {  
97 - // TODO @疯狂:类似上面的 payUserCount  
98 - Integer payPrice = tradeOrderStatisticsService.getOrderPayPrice(beginTime, endTime);  
99 - atv = NumberUtil.div(payPrice, payUserCount).intValue();  
100 - }  
101 - return new MemberAnalyseRespVO()  
102 - .setVisitUserCount(apiAccessLogStatisticsService.getIpCount(UserTypeEnum.MEMBER.getValue(), beginTime, endTime))  
103 - .setOrderUserCount(tradeOrderStatisticsService.getOrderUserCount(beginTime, endTime))  
104 - .setPayUserCount(payUserCount)  
105 - .setAtv(atv)  
106 - .setComparison(new DataComparisonRespVO<>(vo, reference)); 86 + LocalDateTime referenceEndDate = beginTime.minusDays(1); // 减少1天,防止出现时间重叠
  87 + LocalDateTime referenceBeginDate = referenceEndDate.minus(Duration.between(beginTime, endTime));
  88 + MemberAnalyseDataRespVO reference = getMemberAnalyseData(
  89 + LocalDateTimeUtil.beginOfDay(referenceBeginDate), LocalDateTimeUtil.endOfDay(referenceEndDate));
  90 + return new DataComparisonRespVO<>(vo, reference);
107 } 91 }
108 92
109 - private MemberAnalyseComparisonRespVO getMemberAnalyseComparisonData(LocalDateTime beginTime, LocalDateTime endTime) { 93 + private MemberAnalyseDataRespVO getMemberAnalyseData(LocalDateTime beginTime, LocalDateTime endTime) {
110 Integer rechargeUserCount = Optional.ofNullable(payWalletStatisticsService.getUserRechargeSummary(beginTime, endTime)) 94 Integer rechargeUserCount = Optional.ofNullable(payWalletStatisticsService.getUserRechargeSummary(beginTime, endTime))
111 .map(RechargeSummaryRespBO::getRechargeUserCount).orElse(0); 95 .map(RechargeSummaryRespBO::getRechargeUserCount).orElse(0);
112 - return new MemberAnalyseComparisonRespVO() 96 + return new MemberAnalyseDataRespVO()
113 .setRegisterUserCount(memberStatisticsMapper.selectUserCount(beginTime, endTime)) 97 .setRegisterUserCount(memberStatisticsMapper.selectUserCount(beginTime, endTime))
114 .setVisitUserCount(apiAccessLogStatisticsService.getUserCount(UserTypeEnum.MEMBER.getValue(), beginTime, endTime)) 98 .setVisitUserCount(apiAccessLogStatisticsService.getUserCount(UserTypeEnum.MEMBER.getValue(), beginTime, endTime))
115 .setRechargeUserCount(rechargeUserCount); 99 .setRechargeUserCount(rechargeUserCount);