Commit d3385dcb4f7305e5632164e7c9b4defc3d0e58d5
1 parent
8e35a786
统计:会员分析数据接口重构
Showing
6 changed files
with
57 additions
and
36 deletions
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); |