diff --git a/sql/mysql/mall.sql b/sql/mysql/mall.sql new file mode 100644 index 000000000..558ec66f0 --- /dev/null +++ b/sql/mysql/mall.sql @@ -0,0 +1,2 @@ +INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name) +VALUES ('商城首页', '', 2, 1, 2362, 'home', 'ep:home-filled', 'mall/home/index', 'MallHome'); \ No newline at end of file diff --git a/sql/mysql/member.sql b/sql/mysql/member.sql new file mode 100644 index 000000000..e3cadc709 --- /dev/null +++ b/sql/mysql/member.sql @@ -0,0 +1 @@ +ALTER TABLE member_user ADD COLUMN register_terminal tinyint NULL COMMENT '注册终端' AFTER register_ip; \ No newline at end of file diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java index ad79784ed..368ac738f 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.common.util.servlet; +import cn.hutool.core.convert.Convert; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.servlet.ServletUtil; @@ -27,7 +28,7 @@ public class ServletUtils { * 返回 JSON 字符串 * * @param response 响应 - * @param object 对象,会序列化成 JSON 字符串 + * @param object 对象,会序列化成 JSON 字符串 */ @SuppressWarnings("deprecation") // 必须使用 APPLICATION_JSON_UTF8_VALUE,否则会乱码 public static void writeJSON(HttpServletResponse response, Object object) { @@ -40,7 +41,7 @@ public class ServletUtils { * * @param response 响应 * @param filename 文件名 - * @param content 附件内容 + * @param content 附件内容 */ public static void writeAttachment(HttpServletResponse response, String filename, byte[] content) throws IOException { // 设置 header 和 contentType @@ -88,6 +89,18 @@ public class ServletUtils { return ServletUtil.getClientIP(request); } + public static Integer getTerminal() { + return getHeaderInt("terminal"); + } + + public static String getHeader(String header) { + return getHeader(getRequest(), header); + } + + public static Integer getHeaderInt(String header) { + return Convert.toInt(getHeader(header)); + } + public static boolean isJsonRequest(ServletRequest request) { return StrUtil.startWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE); } @@ -107,4 +120,12 @@ public class ServletUtils { public static Map getParamMap(HttpServletRequest request) { return ServletUtil.getParamMap(request); } + + public static String getHeader(HttpServletRequest request, String header) { + if (request == null) { + return null; + } + return request.getHeader(header); + } + } diff --git a/yudao-module-mall/yudao-module-statistics-api/src/main/java/cn/iocoder/yudao/module/statistics/enums/TimeRangeTypeEnum.java b/yudao-module-mall/yudao-module-statistics-api/src/main/java/cn/iocoder/yudao/module/statistics/enums/TimeRangeTypeEnum.java new file mode 100644 index 000000000..1b2361e43 --- /dev/null +++ b/yudao-module-mall/yudao-module-statistics-api/src/main/java/cn/iocoder/yudao/module/statistics/enums/TimeRangeTypeEnum.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.statistics.enums; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 时间范围类型的枚举 + * + * @author owen + */ +@AllArgsConstructor +@Getter +public enum TimeRangeTypeEnum implements IntArrayValuable { + + /** + * 天 + */ + DAY(1), + /** + * 周 + */ + WEEK(7), + /** + * 月 + */ + MONTH(30), + /** + * 年 + */ + YEAR(365), + ; + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TimeRangeTypeEnum::getType).toArray(); + + + /** + * 状态 + */ + private final Integer type; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeStatisticsComparisonRespVO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/common/vo/DataComparisonRespVO.java similarity index 60% rename from yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeStatisticsComparisonRespVO.java rename to yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/common/vo/DataComparisonRespVO.java index fee5b4c29..efd889a87 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeStatisticsComparisonRespVO.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/common/vo/DataComparisonRespVO.java @@ -1,16 +1,15 @@ -package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo; +package cn.iocoder.yudao.module.statistics.controller.admin.common.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -// TODO @疯狂:是不是搞成公用的哈;类似,controller/admin/common,下面直接放它 -@Schema(description = "管理后台 - 交易统计对照 Response VO") +@Schema(description = "管理后台 - 数据对照 Response VO") @Data @NoArgsConstructor @AllArgsConstructor -public class TradeStatisticsComparisonRespVO { +public class DataComparisonRespVO { @Schema(description = "当前数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private T value; diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/MemberStatisticsController.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/MemberStatisticsController.java index 02a844064..3ee8eb919 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/MemberStatisticsController.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/MemberStatisticsController.java @@ -1,10 +1,15 @@ package cn.iocoder.yudao.module.statistics.controller.admin.member; import cn.hutool.core.util.ArrayUtil; -import cn.iocoder.yudao.framework.common.enums.TerminalEnum; +import cn.hutool.core.util.NumberUtil; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; 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.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.trade.TradeOrderStatisticsService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; @@ -15,10 +20,10 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; +import java.time.LocalDateTime; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @Tag(name = "管理后台 - 会员统计") @RestController @@ -29,6 +34,10 @@ public class MemberStatisticsController { @Resource private MemberStatisticsService memberStatisticsService; + @Resource + private TradeOrderStatisticsService tradeOrderStatisticsService; + @Resource + private ApiAccessLogStatisticsService apiAccessLogStatisticsService; // TODO 芋艿:已经 review @GetMapping("/summary") @@ -43,8 +52,28 @@ public class MemberStatisticsController { @Operation(summary = "获得会员分析数据") @PreAuthorize("@ss.hasPermission('statistics:member:query')") public CommonResult getMemberAnalyse(MemberAnalyseReqVO reqVO) { - return success(memberStatisticsService.getMemberAnalyse( - ArrayUtil.get(reqVO.getTimes(), 0), ArrayUtil.get(reqVO.getTimes(), 1))); + // 1. 查询数据 + LocalDateTime beginTime = ArrayUtil.get(reqVO.getTimes(), 0); + LocalDateTime endTime = ArrayUtil.get(reqVO.getTimes(), 1); + // 1.1 查询分析对照数据 + DataComparisonRespVO 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 @@ -67,12 +96,22 @@ public class MemberStatisticsController { @Operation(summary = "按照终端,获得会员统计列表") @PreAuthorize("@ss.hasPermission('statistics:member:query')") public CommonResult> getMemberTerminalStatisticsList() { - // TODO 疯狂:这个可以晚点写,因为 user = = 上还没记录 terminal - // TODO @疯狂:在 member_user 上,增加 registerTerminal 字段,基于它来统计哈; - List list = convertList(TerminalEnum.values(), - t -> new MemberTerminalStatisticsRespVO() - .setTerminal(t.getTerminal()).setUserCount(t.getTerminal() * 100)); - return success(list); + return success(memberStatisticsService.getRegisterTerminalStatisticsList()); + } + + @GetMapping("/user-count-comparison") + @Operation(summary = "获得用户数量对照") + @PreAuthorize("@ss.hasPermission('statistics:member:query')") + public CommonResult> getUserCountComparison() { + return success(memberStatisticsService.getUserCountComparison()); + } + + @GetMapping("/register-count-list") + @Operation(summary = "获得会员注册数量列表") + @PreAuthorize("@ss.hasPermission('statistics:member:query')") + public CommonResult> getMemberRegisterCountList(MemberAnalyseReqVO reqVO) { + return success(memberStatisticsService.getMemberRegisterCountList( + ArrayUtil.get(reqVO.getTimes(), 0), ArrayUtil.get(reqVO.getTimes(), 1))); } } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAnalyseComparisonRespVO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAnalyseDataRespVO.java similarity index 58% rename from yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAnalyseComparisonRespVO.java rename to yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAnalyseDataRespVO.java index f36930180..d2dd3e483 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAnalyseComparisonRespVO.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAnalyseDataRespVO.java @@ -3,17 +3,15 @@ package cn.iocoder.yudao.module.statistics.controller.admin.member.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@Schema(description = "管理后台 - 会员分析对照数据 Response VO") +@Schema(description = "管理后台 - 会员分析数据 Response VO") @Data -public class MemberAnalyseComparisonRespVO { +public class MemberAnalyseDataRespVO { - // TODO @疯狂:这个字段,要不改成注册用户量;registerUserCount; @Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer userCount; + private Integer registerUserCount; - // TODO @疯狂:这个字段,名字改成 visitUserCount;有访问,就算活跃; @Schema(description = "活跃用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer activeUserCount; + private Integer visitUserCount; @Schema(description = "充值会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "221") private Integer rechargeUserCount; diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAnalyseRespVO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAnalyseRespVO.java index df4e3d9ff..e1c46547b 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAnalyseRespVO.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAnalyseRespVO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.statistics.controller.admin.member.vo; -import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO; +import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -8,9 +8,8 @@ import lombok.Data; @Data public class MemberAnalyseRespVO { - // TODO @疯狂:这个字段改成 visitUserCount,保持和 userCount 字段统一 @Schema(description = "访客数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer visitorCount; + private Integer visitUserCount; @Schema(description = "下单用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Integer orderUserCount; @@ -22,6 +21,6 @@ public class MemberAnalyseRespVO { private Integer atv; @Schema(description = "对照数据", requiredMode = Schema.RequiredMode.REQUIRED) - private TradeStatisticsComparisonRespVO comparison; + private DataComparisonRespVO comparison; } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAreaStatisticsRespVO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAreaStatisticsRespVO.java index cd588aa30..1024d04ef 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAreaStatisticsRespVO.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAreaStatisticsRespVO.java @@ -15,11 +15,10 @@ public class MemberAreaStatisticsRespVO { @Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Integer userCount; - // TODO @疯狂:要不 orderCreateUserCount 和 orderPayUserCount 貌似更统一一些; - @Schema(description = "订单创建数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer orderCreateCount; - @Schema(description = "订单支付数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "512") - private Integer orderPayCount; + @Schema(description = "下单的会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer orderCreateUserCount; + @Schema(description = "支付订单的会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "512") + private Integer orderPayUserCount; @Schema(description = "订单支付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "622") private Integer orderPayPrice; diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberCountRespVO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberCountRespVO.java new file mode 100644 index 000000000..28e807e79 --- /dev/null +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberCountRespVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.statistics.controller.admin.member.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 会员数量统计 Response VO") +@Data +public class MemberCountRespVO { + + @Schema(description = "用户访问量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer visitUserCount; + + @Schema(description = "新增用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer createUserCount; + +} diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberRegisterCountRespVO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberRegisterCountRespVO.java new file mode 100644 index 000000000..fb7fc2ac4 --- /dev/null +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberRegisterCountRespVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.statistics.controller.admin.member.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDate; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; + +@Schema(description = "管理后台 - 会员注册数量 Response VO") +@Data +public class MemberRegisterCountRespVO { + + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY, timezone = TIME_ZONE_DEFAULT) + @Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private LocalDate date; + + @Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer count; + +} diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/pay/PayStatisticsController.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/pay/PayStatisticsController.java new file mode 100644 index 000000000..7a6fc7ab7 --- /dev/null +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/pay/PayStatisticsController.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.statistics.controller.admin.pay; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.statistics.service.pay.PayWalletStatisticsService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 支付统计") +@RestController +@RequestMapping("/statistics/pay") +@Validated +@Slf4j +public class PayStatisticsController { + + @Resource + private PayWalletStatisticsService payWalletStatisticsService; + + @GetMapping("/wallet-recharge-price") + @Operation(summary = "获取充值金额") + public CommonResult getWalletRechargePrice() { + return success(payWalletStatisticsService.getRechargePriceSummary()); + } + +} diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/TradeStatisticsController.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/TradeStatisticsController.java index 84a83d499..087b955d5 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/TradeStatisticsController.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/TradeStatisticsController.java @@ -3,9 +3,17 @@ package cn.iocoder.yudao.module.statistics.controller.admin.trade; import cn.hutool.core.util.ArrayUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO; import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.*; import cn.iocoder.yudao.module.statistics.convert.trade.TradeStatisticsConvert; +import cn.iocoder.yudao.module.statistics.dal.dataobject.trade.TradeStatisticsDO; +import cn.iocoder.yudao.module.statistics.service.trade.AfterSaleStatisticsService; +import cn.iocoder.yudao.module.statistics.service.trade.BrokerageStatisticsService; +import cn.iocoder.yudao.module.statistics.service.trade.TradeOrderStatisticsService; import cn.iocoder.yudao.module.statistics.service.trade.TradeStatisticsService; +import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeSummaryRespBO; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleStatusEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; @@ -17,6 +25,7 @@ import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.util.List; @@ -31,46 +40,82 @@ public class TradeStatisticsController { @Resource private TradeStatisticsService tradeStatisticsService; + @Resource + private TradeOrderStatisticsService tradeOrderStatisticsService; + @Resource + private AfterSaleStatisticsService afterSaleStatisticsService; + @Resource + private BrokerageStatisticsService brokerageStatisticsService; @GetMapping("/summary") @Operation(summary = "获得交易统计") @PreAuthorize("@ss.hasPermission('statistics:trade:query')") - public CommonResult> getTradeSummaryComparison() { - // TODO @疯狂:这个要不要 tradeStatisticsService 调用里面的多个方法,组合出最终的 TradeSummaryRespVO; - return success(tradeStatisticsService.getTradeSummaryComparison()); + public CommonResult> getTradeSummaryComparison() { + // 1.1 昨天的数据 + TradeSummaryRespBO yesterdayData = tradeStatisticsService.getTradeSummaryByDays(-1); + // 1.2 前天的数据(用于对照昨天的数据) + TradeSummaryRespBO beforeYesterdayData = tradeStatisticsService.getTradeSummaryByDays(-2); + // 2.1 本月数据 + TradeSummaryRespBO monthData = tradeStatisticsService.getTradeSummaryByMonths(0); + // 2.2 上月数据(用于对照本月的数据) + TradeSummaryRespBO lastMonthData = tradeStatisticsService.getTradeSummaryByMonths(-1); + // 拼接数据 + return success(TradeStatisticsConvert.INSTANCE.convert(yesterdayData, beforeYesterdayData, monthData, lastMonthData)); } // TODO @疯狂:【晚点再改和讨论;等首页的接口出来】这个要不还是叫 analyse,对比选中的时间段,和上一个时间段;类似 MemberStatisticsController 的 getMemberAnalyse @GetMapping("/trend/summary") @Operation(summary = "获得交易状况统计") @PreAuthorize("@ss.hasPermission('statistics:trade:query')") - public CommonResult> getTradeTrendSummaryComparison( + public CommonResult> getTradeTrendSummaryComparison( TradeTrendReqVO reqVO) { return success(tradeStatisticsService.getTradeTrendSummaryComparison(ArrayUtil.get(reqVO.getTimes(), 0), ArrayUtil.get(reqVO.getTimes(), 1))); } - // TODO 芋艿:已经 review - // TODO @疯狂:这个要不直接叫 list;它即使就是把每条统计拿出来 - @GetMapping("/trend/list") + @GetMapping("/list") @Operation(summary = "获得交易状况明细") @PreAuthorize("@ss.hasPermission('statistics:trade:query')") - public CommonResult> getTradeStatisticsList( - TradeTrendReqVO reqVO) { - return success(tradeStatisticsService.getTradeStatisticsList(ArrayUtil.get(reqVO.getTimes(), 0), - ArrayUtil.get(reqVO.getTimes(), 1))); + public CommonResult> getTradeStatisticsList(TradeTrendReqVO reqVO) { + List list = tradeStatisticsService.getTradeStatisticsList(ArrayUtil.get(reqVO.getTimes(), 0), + ArrayUtil.get(reqVO.getTimes(), 1)); + return success(TradeStatisticsConvert.INSTANCE.convertList(list)); } - // TODO @疯狂:这个要不直接叫 export;它即使就是把每条统计导出 - @GetMapping("/trend/export-excel") + @GetMapping("/export-excel") @Operation(summary = "导出获得交易状况明细 Excel") @PreAuthorize("@ss.hasPermission('statistics:trade:export')") public void exportTradeStatisticsExcel(TradeTrendReqVO reqVO, HttpServletResponse response) throws IOException { - List list = tradeStatisticsService.getTradeStatisticsList(ArrayUtil.get(reqVO.getTimes(), 0), + List list = tradeStatisticsService.getTradeStatisticsList(ArrayUtil.get(reqVO.getTimes(), 0), ArrayUtil.get(reqVO.getTimes(), 1)); // 导出 Excel - List data = TradeStatisticsConvert.INSTANCE.convertList02(list); + List voList = TradeStatisticsConvert.INSTANCE.convertList(list); + List data = TradeStatisticsConvert.INSTANCE.convertList02(voList); ExcelUtils.write(response, "交易状况.xls", "数据", TradeTrendSummaryExcelVO.class, data); } + @GetMapping("/order-count") + @Operation(summary = "获得交易订单数量") + @PreAuthorize("@ss.hasPermission('statistics:trade:query')") + public CommonResult getOrderCount() { + TradeOrderCountRespVO vo = tradeOrderStatisticsService.getOrderCount(); + vo.setAfterSaleApply(afterSaleStatisticsService.getCountByStatus(AfterSaleStatusEnum.APPLY)) + .setAuditingWithdraw(brokerageStatisticsService.getWithdrawCountByStatus(BrokerageWithdrawStatusEnum.AUDITING)); + return success(vo); + } + + @GetMapping("/order-comparison") + @Operation(summary = "获得交易订单数量") + @PreAuthorize("@ss.hasPermission('statistics:trade:query')") + public CommonResult> getOrderComparison() { + return success(tradeOrderStatisticsService.getOrderComparison()); + } + + @GetMapping("/order-count-trend") + @Operation(summary = "获得订单量趋势统计") + @PreAuthorize("@ss.hasPermission('statistics:trade:query')") + public CommonResult>> getOrderCountTrendComparison(@Valid TradeOrderTrendReqVO reqVO) { + return success(tradeOrderStatisticsService.getOrderCountTrendComparison(reqVO)); + } + } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeOrderCountRespVO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeOrderCountRespVO.java new file mode 100644 index 000000000..1320a889e --- /dev/null +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeOrderCountRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 交易订单数量 Response VO") +@Data +public class TradeOrderCountRespVO { + + @Schema(description = "待发货", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long undelivered; + + @Schema(description = "待核销", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long pickUp; + + @Schema(description = "退款中", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long afterSaleApply; + + @Schema(description = "提现待审核", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long auditingWithdraw; + +} diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeOrderSummaryRespVO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeOrderSummaryRespVO.java new file mode 100644 index 000000000..22d8f4a14 --- /dev/null +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeOrderSummaryRespVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 交易订单统计 Response VO") +@Data +public class TradeOrderSummaryRespVO { + + @Schema(description = "支付订单商品数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer orderPayCount; + + @Schema(description = "总支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer orderPayPrice; + +} diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeOrderTrendReqVO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeOrderTrendReqVO.java new file mode 100644 index 000000000..57f054629 --- /dev/null +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeOrderTrendReqVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.statistics.enums.TimeRangeTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 交易订单量趋势统计 Request VO") +@Data +public class TradeOrderTrendReqVO { + + @Schema(description = "日期范围类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "日期范围类型不能为空") + @InEnum(value = TimeRangeTypeEnum.class, message = "日期范围类型,必须是 {value}") + private Integer type; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @Schema(description = "起始时间") + private LocalDateTime beginTime; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @Schema(description = "截止时间") + private LocalDateTime endTime; + +} diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeOrderTrendRespVO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeOrderTrendRespVO.java new file mode 100644 index 000000000..d69c343cb --- /dev/null +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeOrderTrendRespVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 订单量趋势统计 Response VO") +@Data +public class TradeOrderTrendRespVO { + + @Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private String date; + + @Schema(description = "订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer orderPayCount; + + @Schema(description = "订单支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer orderPayPrice; + +} diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryExcelVO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryExcelVO.java index 3253df07d..654d75893 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryExcelVO.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryExcelVO.java @@ -22,7 +22,7 @@ public class TradeTrendSummaryExcelVO { private LocalDate date; @ExcelProperty(value = "营业额", converter = MoneyConvert.class) - private Integer turnover; + private Integer turnoverPrice; @ExcelProperty(value = "商品支付金额", converter = MoneyConvert.class) private Integer orderPayPrice; @@ -34,7 +34,7 @@ public class TradeTrendSummaryExcelVO { private Integer expensePrice; @ExcelProperty(value = "余额支付金额", converter = MoneyConvert.class) - private Integer balancePrice; + private Integer orderWalletPayPrice; @ExcelProperty(value = "支付佣金金额", converter = MoneyConvert.class) private Integer brokerageSettlementPrice; diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryRespVO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryRespVO.java index 79f5583e6..2525a9993 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryRespVO.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryRespVO.java @@ -16,13 +16,15 @@ public class TradeTrendSummaryRespVO { @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY) private LocalDate date; - // TODO @疯狂,要不加个 turnoverPrice? @Schema(description = "营业额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer turnover; // 营业额 = 商品支付金额 + 充值金额 + private Integer turnoverPrice; // 营业额 = 商品支付金额 + 充值金额 @Schema(description = "订单支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Integer orderPayPrice; + @Schema(description = "余额支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer orderWalletPayPrice; + @Schema(description = "订单退款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Integer orderRefundPrice; @@ -35,7 +37,4 @@ public class TradeTrendSummaryRespVO { @Schema(description = "支出金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Integer expensePrice; // 余额支付金额 + 支付佣金金额 + 商品退款金额 - @Schema(description = "余额支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer balancePrice; // TODO @疯狂:这个字段要不改成:walletPayPrice - } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/convert/member/MemberStatisticsConvert.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/convert/member/MemberStatisticsConvert.java index 974edbecd..14a1bcad8 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/convert/member/MemberStatisticsConvert.java +++ b/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; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 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.MemberSummaryRespVO; import cn.iocoder.yudao.module.statistics.service.pay.bo.RechargeSummaryRespBO; @@ -28,16 +31,20 @@ public interface MemberStatisticsConvert { Map userCountMap, Map orderMap) { 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() .setAreaId(area.getId()).setAreaName(area.getName()) .setUserCount(MapUtil.getInt(userCountMap, area.getId(), 0)) - .setOrderCreateCount(ObjUtil.defaultIfNull(orderVo.getOrderCreateCount(), 0)) - .setOrderPayCount(ObjUtil.defaultIfNull(orderVo.getOrderPayCount(), 0)) + .setOrderCreateUserCount(ObjUtil.defaultIfNull(orderVo.getOrderCreateUserCount(), 0)) + .setOrderPayUserCount(ObjUtil.defaultIfNull(orderVo.getOrderPayUserCount(), 0)) .setOrderPayPrice(ObjUtil.defaultIfNull(orderVo.getOrderPayPrice(), 0)); }); } MemberSummaryRespVO convert(RechargeSummaryRespBO rechargeSummary, Integer expensePrice, Integer userCount); + MemberAnalyseRespVO convert(Integer visitUserCount, Integer orderUserCount, Integer payUserCount, int atv, + DataComparisonRespVO comparison); + } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/convert/trade/TradeStatisticsConvert.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/convert/trade/TradeStatisticsConvert.java index a2bce34d9..9fe68f96c 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/convert/trade/TradeStatisticsConvert.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/convert/trade/TradeStatisticsConvert.java @@ -1,14 +1,14 @@ package cn.iocoder.yudao.module.statistics.convert.trade; -import cn.iocoder.yudao.module.statistics.service.trade.bo.WalletSummaryRespBO; -import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO; +import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO; import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeSummaryRespVO; import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryExcelVO; import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO; import cn.iocoder.yudao.module.statistics.dal.dataobject.trade.TradeStatisticsDO; +import cn.iocoder.yudao.module.statistics.service.trade.bo.AfterSaleSummaryRespBO; import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeOrderSummaryRespBO; import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeSummaryRespBO; -import cn.iocoder.yudao.module.statistics.service.trade.bo.AfterSaleSummaryRespBO; +import cn.iocoder.yudao.module.statistics.service.trade.bo.WalletSummaryRespBO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -25,10 +25,10 @@ public interface TradeStatisticsConvert { TradeStatisticsConvert INSTANCE = Mappers.getMapper(TradeStatisticsConvert.class); - default TradeStatisticsComparisonRespVO convert(TradeSummaryRespBO yesterdayData, - TradeSummaryRespBO beforeYesterdayData, - TradeSummaryRespBO monthData, - TradeSummaryRespBO lastMonthData) { + default DataComparisonRespVO convert(TradeSummaryRespBO yesterdayData, + TradeSummaryRespBO beforeYesterdayData, + TradeSummaryRespBO monthData, + TradeSummaryRespBO lastMonthData) { return convert(convert(yesterdayData, monthData), convert(beforeYesterdayData, lastMonthData)); } @@ -39,10 +39,10 @@ public interface TradeStatisticsConvert { .setMonthOrderCount(monthData.getCount()).setMonthPayPrice(monthData.getSummary()); } - TradeStatisticsComparisonRespVO convert(TradeSummaryRespVO value, TradeSummaryRespVO reference); + DataComparisonRespVO convert(TradeSummaryRespVO value, TradeSummaryRespVO reference); - TradeStatisticsComparisonRespVO convert(TradeTrendSummaryRespVO value, - TradeTrendSummaryRespVO reference); + DataComparisonRespVO convert(TradeTrendSummaryRespVO value, + TradeTrendSummaryRespVO reference); List convertList02(List list); @@ -50,4 +50,20 @@ public interface TradeStatisticsConvert { AfterSaleSummaryRespBO afterSaleSummary, Integer brokerageSettlementPrice, WalletSummaryRespBO walletSummary); + List convertList(List list); + + default TradeTrendSummaryRespVO convert(TradeStatisticsDO tradeStatistics) { + return new TradeTrendSummaryRespVO() + .setDate(tradeStatistics.getTime().toLocalDate()) + // 营业额 = 商品支付金额 + 充值金额 + .setTurnoverPrice(tradeStatistics.getOrderPayPrice() + tradeStatistics.getRechargePayPrice()) + .setOrderPayPrice(tradeStatistics.getOrderPayPrice()) + .setRechargePrice(tradeStatistics.getRechargePayPrice()) + // 支出金额 = 余额支付金额 + 支付佣金金额 + 商品退款金额 + .setExpensePrice(tradeStatistics.getOrderWalletPayPrice() + tradeStatistics.getBrokerageSettlementPrice() + tradeStatistics.getAfterSaleRefundPrice()) + .setOrderWalletPayPrice(tradeStatistics.getOrderWalletPayPrice()) + .setBrokerageSettlementPrice(tradeStatistics.getBrokerageSettlementPrice()) + .setOrderRefundPrice(tradeStatistics.getAfterSaleRefundPrice()); + } + } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/dataobject/trade/TradeStatisticsDO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/dataobject/trade/TradeStatisticsDO.java index f007aa21b..0cc3ba3f2 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/dataobject/trade/TradeStatisticsDO.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/dataobject/trade/TradeStatisticsDO.java @@ -48,11 +48,6 @@ public class TradeStatisticsDO extends TenantBaseDO { * 总支付金额,单位:分 */ private Integer orderPayPrice; - // TODO @疯狂:这个字段改成 walletPayPrice,然后挪到 rechargePayCount 前面; - /** - * 总支付金额(余额),单位:分 - */ - private Integer orderWalletPayPrice; /** * 退款订单数 @@ -68,6 +63,10 @@ public class TradeStatisticsDO extends TenantBaseDO { */ private Integer brokerageSettlementPrice; + /** + * 总支付金额(余额),单位:分 + */ + private Integer orderWalletPayPrice; /** * 充值订单数 *

diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/infra/ApiAccessLogStatisticsMapper.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/infra/ApiAccessLogStatisticsMapper.java index 37b04cfc2..5f76b58fd 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/infra/ApiAccessLogStatisticsMapper.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/infra/ApiAccessLogStatisticsMapper.java @@ -13,14 +13,15 @@ import java.time.LocalDateTime; * @author owen */ @Mapper -public interface ApiAccessLogStatisticsMapper extends BaseMapperX { +@SuppressWarnings("rawtypes") +public interface ApiAccessLogStatisticsMapper extends BaseMapperX { - // TODO @疯狂:是不是 selectIpCount - Integer selectCountByIp(@Param("beginTime") LocalDateTime beginTime, - @Param("endTime") LocalDateTime endTime); + Integer selectIpCountByUserTypeAndCreateTimeBetween(@Param("userType") Integer userType, + @Param("beginTime") LocalDateTime beginTime, + @Param("endTime") LocalDateTime endTime); - // TODO @疯狂:是不是 selectUserCount - Integer selectCountByUserId(@Param("beginTime") LocalDateTime beginTime, - @Param("endTime") LocalDateTime endTime); + Integer selectUserCountByUserTypeAndCreateTimeBetween(@Param("userType") Integer userType, + @Param("beginTime") LocalDateTime beginTime, + @Param("endTime") LocalDateTime endTime); } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/member/MemberStatisticsMapper.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/member/MemberStatisticsMapper.java index f1ac09c4f..4b1bc8783 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/member/MemberStatisticsMapper.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/member/MemberStatisticsMapper.java @@ -1,8 +1,10 @@ package cn.iocoder.yudao.module.statistics.dal.mysql.member; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAreaStatisticsRespVO; +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberRegisterCountRespVO; import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberSexStatisticsRespVO; +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberTerminalStatisticsRespVO; +import cn.iocoder.yudao.module.statistics.service.member.bo.MemberAreaStatisticsRespBO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -15,16 +17,20 @@ import java.util.List; * @author owen */ @Mapper -public interface MemberStatisticsMapper extends BaseMapperX { +@SuppressWarnings("rawtypes") +public interface MemberStatisticsMapper extends BaseMapperX { - // TODO @芋艿:已经 review - // TODO @疯狂:要不还是搞下 bo?虽然可能冗余了点~~ - List selectSummaryListByAreaId(); + List selectSummaryListByAreaId(); List selectSummaryListBySex(); + List selectSummaryListByRegisterTerminal(); + // TODO @芋艿:已经 review Integer selectUserCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); + List selectListByCreateTimeBetween(@Param("beginTime") LocalDateTime beginTime, + @Param("endTime") LocalDateTime endTime); + } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/pay/PayWalletStatisticsMapper.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/pay/PayWalletStatisticsMapper.java index 61f713d2c..4a2c47180 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/pay/PayWalletStatisticsMapper.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/pay/PayWalletStatisticsMapper.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.statistics.dal.mysql.pay; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.statistics.dal.dataobject.trade.TradeStatisticsDO; import cn.iocoder.yudao.module.statistics.service.pay.bo.RechargeSummaryRespBO; import cn.iocoder.yudao.module.statistics.service.trade.bo.WalletSummaryRespBO; import org.apache.ibatis.annotations.Mapper; @@ -15,7 +14,8 @@ import java.time.LocalDateTime; * @author owen */ @Mapper -public interface PayWalletStatisticsMapper extends BaseMapperX { +@SuppressWarnings("rawtypes") +public interface PayWalletStatisticsMapper extends BaseMapperX { // TODO 芋艿:已经 review; WalletSummaryRespBO selectRechargeSummaryByPayTimeBetween(@Param("beginTime") LocalDateTime beginTime, @@ -37,4 +37,6 @@ public interface PayWalletStatisticsMapper extends BaseMapperX selectListByPayTimeBetweenAndGroupByDay(@Param("beginTime") LocalDateTime beginTime, + @Param("endTime") LocalDateTime endTime); + + /** + * 按照支付时间统计订单(按月分组) + * + * @param beginTime 支付起始时间 + * @param endTime 支付截止时间 + * @return 订单统计列表 + */ + List selectListByPayTimeBetweenAndGroupByMonth(@Param("beginTime") LocalDateTime beginTime, + @Param("endTime") LocalDateTime endTime); + + Long selectCountByStatus(@Param("status") Integer status); + + Long selectCountByStatusAndPickUpStoreIdIsNotNull(@Param("status") Integer status); + + TradeOrderSummaryRespVO selectPaySummaryByStatusAndPayTimeBetween(@Param("status") Integer status, + @Param("beginTime") LocalDateTime beginTime, + @Param("endTime") LocalDateTime endTime); + } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/TradeStatisticsMapper.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/TradeStatisticsMapper.java index d07caa43e..67d2d5007 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/TradeStatisticsMapper.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/TradeStatisticsMapper.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.statistics.dal.mysql.trade; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO; import cn.iocoder.yudao.module.statistics.dal.dataobject.trade.TradeStatisticsDO; import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeSummaryRespBO; @@ -21,14 +22,20 @@ public interface TradeStatisticsMapper extends BaseMapperX { TradeSummaryRespBO selectOrderCreateCountSumAndOrderPayPriceSumByTimeBetween(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); - TradeTrendSummaryRespVO selectByTimeBetween(@Param("beginTime") LocalDateTime beginTime, - @Param("endTime") LocalDateTime endTime); + TradeTrendSummaryRespVO selectVoByTimeBetween(@Param("beginTime") LocalDateTime beginTime, + @Param("endTime") LocalDateTime endTime); - // TODO @芋艿:已经 review - List selectListByTimeBetween(@Param("beginTime") LocalDateTime beginTime, - @Param("endTime") LocalDateTime endTime); + default List selectListByTimeBetween(LocalDateTime beginTime, LocalDateTime endTime) { + return selectList(new LambdaQueryWrapperX() + .between(TradeStatisticsDO::getTime, beginTime, endTime)); + } Integer selectExpensePriceByTimeBetween(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); + default TradeStatisticsDO selectByTimeBetween(LocalDateTime beginTime, LocalDateTime endTime) { + return selectOne(new LambdaQueryWrapperX() + .between(TradeStatisticsDO::getTime, beginTime, endTime)); + } + } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/job/trade/TradeStatisticsJob.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/job/trade/TradeStatisticsJob.java index b97ba2338..2cefe22b5 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/job/trade/TradeStatisticsJob.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/job/trade/TradeStatisticsJob.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.statistics.job.trade; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; @@ -19,11 +21,24 @@ public class TradeStatisticsJob implements JobHandler { @Resource private TradeStatisticsService tradeStatisticsService; + /** + * 执行交易统计任务 + * + * @param param 要统计的天数,只能是正整数,1 代表昨日数据 + * @return 统计结果 + */ @Override @TenantJob public String execute(String param) { - String times = tradeStatisticsService.statisticsYesterdayTrade(); - return StrUtil.format("交易统计耗时: {}", times); + if (NumberUtil.isInteger(param)) { + throw new RuntimeException("交易统计任务的参数只能为是正整数"); + } + Integer days = Convert.toInt(param, 0); + if (days < 1) { + throw new RuntimeException("交易统计任务的参数只能为是正整数"); + } + String result = tradeStatisticsService.statisticsTrade(days); + return StrUtil.format("交易统计:\n{}", result); } } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/infra/ApiAccessLogStatisticsService.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/infra/ApiAccessLogStatisticsService.java index e67f9dd27..6c200fdef 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/infra/ApiAccessLogStatisticsService.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/infra/ApiAccessLogStatisticsService.java @@ -9,26 +9,24 @@ import java.time.LocalDateTime; */ public interface ApiAccessLogStatisticsService { - // TODO @疯狂:需要传递 userType;因为访问日志,可能涉及多种用户类型; - // TODO @疯狂:方法名,要不改成 getUserCount;原因:让它更业务无关 /** * 获取活跃用户数量 * + * @param userType 用户类型 * @param beginTime 起始时间 * @param endTime 截止时间 * @return 活跃用户数量 */ - Integer getActiveUserCount(LocalDateTime beginTime, LocalDateTime endTime); + Integer getUserCount(Integer userType, LocalDateTime beginTime, LocalDateTime endTime); - // TODO @疯狂:需要传递 userType;因为访问日志,可能涉及多种用户类型; - // TODO @疯狂:方法名,要不改成 getIpCount;原因:让它更业务无关 /** * 获取访问用户数量 * + * @param userType 用户类型 * @param beginTime 起始时间 * @param endTime 截止时间 * @return 访问用户数量 */ - Integer getVisitorUserCount(LocalDateTime beginTime, LocalDateTime endTime); + Integer getIpCount(Integer userType, LocalDateTime beginTime, LocalDateTime endTime); } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/infra/ApiAccessLogStatisticsServiceImpl.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/infra/ApiAccessLogStatisticsServiceImpl.java index 4abb02e96..7ad62d00a 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/infra/ApiAccessLogStatisticsServiceImpl.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/infra/ApiAccessLogStatisticsServiceImpl.java @@ -20,13 +20,13 @@ public class ApiAccessLogStatisticsServiceImpl implements ApiAccessLogStatistics private ApiAccessLogStatisticsMapper apiAccessLogStatisticsMapper; @Override - public Integer getActiveUserCount(LocalDateTime beginTime, LocalDateTime endTime) { - return apiAccessLogStatisticsMapper.selectCountByUserId(beginTime, endTime); + public Integer getUserCount(Integer userType, LocalDateTime beginTime, LocalDateTime endTime) { + return apiAccessLogStatisticsMapper.selectUserCountByUserTypeAndCreateTimeBetween(userType, beginTime, endTime); } @Override - public Integer getVisitorUserCount(LocalDateTime beginTime, LocalDateTime endTime) { - return apiAccessLogStatisticsMapper.selectCountByIp(beginTime, endTime); + public Integer getIpCount(Integer userType, LocalDateTime beginTime, LocalDateTime endTime) { + return apiAccessLogStatisticsMapper.selectIpCountByUserTypeAndCreateTimeBetween(userType, beginTime, endTime); } } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsService.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsService.java index 5b072b93c..2ace6f86a 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsService.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsService.java @@ -1,9 +1,7 @@ package cn.iocoder.yudao.module.statistics.service.member; -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.MemberSexStatisticsRespVO; -import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberSummaryRespVO; +import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO; +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.*; import java.time.LocalDateTime; import java.util.List; @@ -23,15 +21,15 @@ public interface MemberStatisticsService { */ MemberSummaryRespVO getMemberSummary(); - // TODO 芋艿:已经 review /** - * 获取用户分析数据 + * 获取会员分析对照数据 * * @param beginTime 起始时间 * @param endTime 截止时间 - * @return 用户分析数据 + * @return 会员分析对照数据 */ - MemberAnalyseRespVO getMemberAnalyse(LocalDateTime beginTime, LocalDateTime endTime); + DataComparisonRespVO getMemberAnalyseComparisonData(LocalDateTime beginTime, + LocalDateTime endTime); /** * 按照省份,获得会员统计列表 @@ -47,4 +45,27 @@ public interface MemberStatisticsService { */ List getMemberSexStatisticsList(); + /** + * 按照终端,获得会员统计列表 + * + * @return 会员统计列表 + */ + List getRegisterTerminalStatisticsList(); + + /** + * 获取用户注册数量列表 + * + * @param beginTime 起始时间 + * @param endTime 截止时间 + * @return 注册数量列表 + */ + List getMemberRegisterCountList(LocalDateTime beginTime, LocalDateTime endTime); + + /** + * 获得用户数量量统计对照 + * + * @return 用户数量量统计对照 + */ + DataComparisonRespVO getUserCountComparison(); + } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsServiceImpl.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsServiceImpl.java index a11d17aaa..0b8f9cb53 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsServiceImpl.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsServiceImpl.java @@ -1,19 +1,22 @@ package cn.iocoder.yudao.module.statistics.service.member; -import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.ip.core.Area; import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; +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.trade.vo.TradeStatisticsComparisonRespVO; +import cn.iocoder.yudao.module.statistics.convert.member.MemberStatisticsConvert; import cn.iocoder.yudao.module.statistics.dal.mysql.member.MemberStatisticsMapper; import cn.iocoder.yudao.module.statistics.service.infra.ApiAccessLogStatisticsService; +import cn.iocoder.yudao.module.statistics.service.member.bo.MemberAreaStatisticsRespBO; import cn.iocoder.yudao.module.statistics.service.pay.PayWalletStatisticsService; import cn.iocoder.yudao.module.statistics.service.pay.bo.RechargeSummaryRespBO; import cn.iocoder.yudao.module.statistics.service.trade.TradeOrderStatisticsService; import cn.iocoder.yudao.module.statistics.service.trade.TradeStatisticsService; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import cn.iocoder.yudao.module.statistics.convert.member.MemberStatisticsConvert; import javax.annotation.Resource; import java.time.Duration; @@ -57,63 +60,77 @@ public class MemberStatisticsServiceImpl implements MemberStatisticsService { @Override public List getMemberAreaStatisticsList() { // 统计用户 - // TODO @疯狂:要处理下,未知省份;就是没填写省份的情况; // TODO @疯狂:可能得把每个省的用户,都查询出来,然后去 order 那边 in;因为要按照这些人为基础来计算;;用户规模量大可能不太好,但是暂时就先这样搞吧 = = Map userCountMap = convertMap(memberStatisticsMapper.selectSummaryListByAreaId(), vo -> AreaUtils.getParentIdByType(vo.getAreaId(), AreaTypeEnum.PROVINCE), - MemberAreaStatisticsRespVO::getUserCount, Integer::sum); + MemberAreaStatisticsRespBO::getUserCount, Integer::sum); // 统计订单 Map orderMap = convertMap(tradeOrderStatisticsService.getSummaryListByAreaId(), vo -> AreaUtils.getParentIdByType(vo.getAreaId(), AreaTypeEnum.PROVINCE), vo -> vo, (a, b) -> new MemberAreaStatisticsRespVO() - .setOrderCreateCount(a.getOrderCreateCount() + b.getOrderCreateCount()) - .setOrderPayCount(a.getOrderPayCount() + b.getOrderPayCount()) + .setOrderCreateUserCount(a.getOrderCreateUserCount() + b.getOrderCreateUserCount()) + .setOrderPayUserCount(a.getOrderPayUserCount() + b.getOrderPayUserCount()) .setOrderPayPrice(a.getOrderPayPrice() + b.getOrderPayPrice())); // 拼接数据 - return MemberStatisticsConvert.INSTANCE.convertList(AreaUtils.getByType(AreaTypeEnum.PROVINCE, area -> area), userCountMap, orderMap); + List areaList = AreaUtils.getByType(AreaTypeEnum.PROVINCE, area -> area); + areaList.add(new Area().setId(null).setName("未知")); + return MemberStatisticsConvert.INSTANCE.convertList(areaList, userCountMap, orderMap); } - // TODO @疯狂:这个方法,要不拆成:1)controller 调用 getMemberAnalyseComparisonData;2)tradeOrderStatisticsService.getPayUserCount;3)tradeOrderStatisticsService.getOrderPayPrice;4)。。。 - // TODO 就是说:分析交给 controller 去组合; @Override - public MemberAnalyseRespVO getMemberAnalyse(LocalDateTime beginTime, LocalDateTime endTime) { + public DataComparisonRespVO getMemberAnalyseComparisonData(LocalDateTime beginTime, LocalDateTime endTime) { + // 当前数据 + MemberAnalyseDataRespVO vo = getMemberAnalyseData(beginTime, endTime); // 对照数据 - MemberAnalyseComparisonRespVO vo = getMemberAnalyseComparisonData(beginTime, endTime); - // TODO @疯狂:如果时间段这么处理,会不会 beginTime 重叠了。因为是 <= 一个时间;如果数据库插入的是 ,xxxx-yy-zz 00:00:00 的话,它既满足 >= ? 也满足 <= ;(如果不好理解,微信聊) - LocalDateTime referenceBeginTime = beginTime.minus(Duration.between(beginTime, endTime)); - MemberAnalyseComparisonRespVO reference = getMemberAnalyseComparisonData(referenceBeginTime, beginTime); - - // 计算客单价 - // 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() - .setVisitorCount(apiAccessLogStatisticsService.getVisitorUserCount(beginTime, endTime)) - .setOrderUserCount(tradeOrderStatisticsService.getOrderUserCount(beginTime, endTime)) - .setPayUserCount(payUserCount) - .setAtv(atv) - .setComparison(new TradeStatisticsComparisonRespVO<>(vo, reference)); + LocalDateTime referenceEndDate = beginTime.minusDays(1); // 减少1天,防止出现时间重叠 + LocalDateTime referenceBeginDate = referenceEndDate.minus(Duration.between(beginTime, endTime)); + MemberAnalyseDataRespVO reference = getMemberAnalyseData( + LocalDateTimeUtil.beginOfDay(referenceBeginDate), LocalDateTimeUtil.endOfDay(referenceEndDate)); + return 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)) .map(RechargeSummaryRespBO::getRechargeUserCount).orElse(0); - return new MemberAnalyseComparisonRespVO() - .setUserCount(memberStatisticsMapper.selectUserCount(beginTime, endTime)) - .setActiveUserCount(apiAccessLogStatisticsService.getActiveUserCount(beginTime, endTime)) + return new MemberAnalyseDataRespVO() + .setRegisterUserCount(memberStatisticsMapper.selectUserCount(beginTime, endTime)) + .setVisitUserCount(apiAccessLogStatisticsService.getUserCount(UserTypeEnum.MEMBER.getValue(), beginTime, endTime)) .setRechargeUserCount(rechargeUserCount); } @Override public List getMemberSexStatisticsList() { - // TODO @疯狂:需要考虑,用户性别为空,则是“未知” return memberStatisticsMapper.selectSummaryListBySex(); } + @Override + public List getRegisterTerminalStatisticsList() { + return memberStatisticsMapper.selectSummaryListByRegisterTerminal(); + } + + @Override + public List getMemberRegisterCountList(LocalDateTime beginTime, LocalDateTime endTime) { + return memberStatisticsMapper.selectListByCreateTimeBetween(beginTime, endTime); + } + + @Override + public DataComparisonRespVO getUserCountComparison() { + // 今日时间范围 + LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); + LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(beginOfToday); + // 昨日时间范围 + LocalDateTime beginOfYesterday = LocalDateTimeUtil.beginOfDay(beginOfToday.minusDays(1)); + LocalDateTime endOfYesterday = LocalDateTimeUtil.endOfDay(beginOfYesterday); + return new DataComparisonRespVO() + .setValue(getUserCount(beginOfToday, endOfToday)) + .setReference(getUserCount(beginOfYesterday, endOfYesterday)); + } + + private MemberCountRespVO getUserCount(LocalDateTime beginTime, LocalDateTime endTime) { + return new MemberCountRespVO() + .setCreateUserCount(memberStatisticsMapper.selectUserCount(beginTime, endTime)) + .setVisitUserCount(apiAccessLogStatisticsService.getIpCount(UserTypeEnum.MEMBER.getValue(), beginTime, endTime)); + } + } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/bo/MemberAreaStatisticsRespBO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/bo/MemberAreaStatisticsRespBO.java new file mode 100644 index 000000000..6b2d9ceab --- /dev/null +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/bo/MemberAreaStatisticsRespBO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.statistics.service.member.bo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 会员地区统计 Response BO") +@Data +public class MemberAreaStatisticsRespBO { + + /** + * 省份编号 + */ + private Integer areaId; + /** + * 省份名称 + */ + private String areaName; + + /** + * 会员数量 + */ + private Integer userCount; + + /** + * 下单的会员数量 + */ + private Integer orderCreateUserCount; + /** + * 支付订单的会员数量 + */ + private Integer orderPayUserCount; + + /** + * 订单支付金额,单位:分 + */ + private Integer orderPayPrice; + +} diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/PayWalletStatisticsService.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/PayWalletStatisticsService.java index 17e6c253c..be41584e9 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/PayWalletStatisticsService.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/PayWalletStatisticsService.java @@ -32,4 +32,11 @@ public interface PayWalletStatisticsService { */ RechargeSummaryRespBO getUserRechargeSummary(LocalDateTime beginTime, LocalDateTime endTime); + /** + * 获取充值金额合计 + * + * @return 充值金额合计 + */ + Integer getRechargePriceSummary(); + } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/PayWalletStatisticsServiceImpl.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/PayWalletStatisticsServiceImpl.java index 2ccc84fe1..10f8bdc97 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/PayWalletStatisticsServiceImpl.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/PayWalletStatisticsServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.statistics.service.pay; import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; import cn.iocoder.yudao.module.statistics.dal.mysql.pay.PayWalletStatisticsMapper; import cn.iocoder.yudao.module.statistics.service.pay.bo.RechargeSummaryRespBO; @@ -43,4 +44,9 @@ public class PayWalletStatisticsServiceImpl implements PayWalletStatisticsServic return payWalletStatisticsMapper.selectRechargeSummaryGroupByWalletId(beginTime, endTime, true); } + @Override + public Integer getRechargePriceSummary() { + return payWalletStatisticsMapper.selectRechargePriceSummary(PayOrderStatusEnum.SUCCESS.getStatus()); + } + } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/bo/RechargeSummaryRespBO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/bo/RechargeSummaryRespBO.java index 389ac2e4c..b99c05d44 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/bo/RechargeSummaryRespBO.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/bo/RechargeSummaryRespBO.java @@ -3,15 +3,21 @@ package cn.iocoder.yudao.module.statistics.service.pay.bo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -// TODO @疯狂:BO 不用写 swagger 注解哈,写注释就好啦; -@Schema(description = "管理后台 - 充值统计 Response VO") +/** + * 充值统计 Response BO + */ +@Schema(description = "管理后台 - ") @Data public class RechargeSummaryRespBO { - @Schema(description = "充值会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "221") + /** + * 充值会员数量 + */ private Integer rechargeUserCount; - @Schema(description = "充值金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + /** + * 充值金额 + */ private Integer rechargePrice; } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/AfterSaleStatisticsService.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/AfterSaleStatisticsService.java index 7b8593f44..fa09da770 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/AfterSaleStatisticsService.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/AfterSaleStatisticsService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.statistics.service.trade; import cn.iocoder.yudao.module.statistics.service.trade.bo.AfterSaleSummaryRespBO; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleStatusEnum; import java.time.LocalDateTime; @@ -21,4 +22,12 @@ public interface AfterSaleStatisticsService { */ AfterSaleSummaryRespBO getAfterSaleSummary(LocalDateTime beginTime, LocalDateTime endTime); + /** + * 获取指定状态的售后订单数量 + * + * @param status 售后状态 + * @return 售后订单数量 + */ + Long getCountByStatus(AfterSaleStatusEnum status); + } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/AfterSaleStatisticsServiceImpl.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/AfterSaleStatisticsServiceImpl.java index cc2ec4af9..46ab5f3ad 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/AfterSaleStatisticsServiceImpl.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/AfterSaleStatisticsServiceImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.statistics.service.trade; import cn.iocoder.yudao.module.statistics.dal.mysql.trade.AfterSaleStatisticsMapper; import cn.iocoder.yudao.module.statistics.service.trade.bo.AfterSaleSummaryRespBO; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleStatusEnum; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -25,4 +26,9 @@ public class AfterSaleStatisticsServiceImpl implements AfterSaleStatisticsServic return afterSaleStatisticsMapper.selectSummaryByRefundTimeBetween(beginTime, endTime); } + @Override + public Long getCountByStatus(AfterSaleStatusEnum status) { + return afterSaleStatisticsMapper.selectCountByStatus(status.getStatus()); + } + } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/BrokerageStatisticsService.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/BrokerageStatisticsService.java index 6da8e1c2e..2bcf393d5 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/BrokerageStatisticsService.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/BrokerageStatisticsService.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.statistics.service.trade; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum; + import java.time.LocalDateTime; /** @@ -19,4 +21,12 @@ public interface BrokerageStatisticsService { */ Integer getBrokerageSettlementPriceSummary(LocalDateTime beginTime, LocalDateTime endTime); + /** + * 获取指定状态的提现记录数量 + * + * @param status 提现记录状态 + * @return 提现记录数量 + */ + Long getWithdrawCountByStatus(BrokerageWithdrawStatusEnum status); + } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/BrokerageStatisticsServiceImpl.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/BrokerageStatisticsServiceImpl.java index 8c29166e5..d7af3d523 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/BrokerageStatisticsServiceImpl.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/BrokerageStatisticsServiceImpl.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.statistics.service.trade; import cn.iocoder.yudao.module.statistics.dal.mysql.trade.BrokerageStatisticsMapper; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -28,4 +29,9 @@ public class BrokerageStatisticsServiceImpl implements BrokerageStatisticsServic beginTime, endTime); } + @Override + public Long getWithdrawCountByStatus(BrokerageWithdrawStatusEnum status) { + return brokerageStatisticsMapper.selectWithdrawCountByStatus(status.getStatus()); + } + } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeOrderStatisticsService.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeOrderStatisticsService.java index 9e1e16aef..dc92b2660 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeOrderStatisticsService.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeOrderStatisticsService.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.statistics.service.trade; +import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO; import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAreaStatisticsRespVO; +import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.*; import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeOrderSummaryRespBO; import java.time.LocalDateTime; @@ -60,4 +62,26 @@ public interface TradeOrderStatisticsService { */ Integer getOrderPayPrice(LocalDateTime beginTime, LocalDateTime endTime); + /** + * 获得交易订单数量 + * + * @return 订单数量 + */ + TradeOrderCountRespVO getOrderCount(); + + /** + * 交易订单销售额对照 + * + * @return 销售额对照 + */ + DataComparisonRespVO getOrderComparison(); + + /** + * 获得订单量趋势统计 + * + * @param reqVO 统计参数 + * @return 订单量趋势统计 + */ + List> getOrderCountTrendComparison(TradeOrderTrendReqVO reqVO); + } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeOrderStatisticsServiceImpl.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeOrderStatisticsServiceImpl.java index 10dd180d0..2758979f5 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeOrderStatisticsServiceImpl.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeOrderStatisticsServiceImpl.java @@ -1,14 +1,25 @@ package cn.iocoder.yudao.module.statistics.service.trade; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; +import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO; import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAreaStatisticsRespVO; +import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.*; import cn.iocoder.yudao.module.statistics.dal.mysql.trade.TradeOrderStatisticsMapper; +import cn.iocoder.yudao.module.statistics.enums.TimeRangeTypeEnum; import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeOrderSummaryRespBO; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.time.Duration; import java.time.LocalDateTime; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; /** * 交易订单统计 Service 实现类 @@ -50,4 +61,53 @@ public class TradeOrderStatisticsServiceImpl implements TradeOrderStatisticsServ return tradeOrderStatisticsMapper.selectSummaryPriceByPayTimeBetween(beginTime, endTime); } + @Override + public TradeOrderCountRespVO getOrderCount() { + Long undeliveredCount = tradeOrderStatisticsMapper.selectCountByStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()); + Long pickUpCount = tradeOrderStatisticsMapper.selectCountByStatusAndPickUpStoreIdIsNotNull(TradeOrderStatusEnum.DELIVERED.getStatus()); + + return new TradeOrderCountRespVO() + .setPickUp(ObjUtil.defaultIfNull(pickUpCount, 0L)) + .setUndelivered(ObjUtil.defaultIfNull(undeliveredCount, 0L)); + } + + @Override + public DataComparisonRespVO getOrderComparison() { + return new DataComparisonRespVO() + .setValue(getPayPriceSummary(LocalDateTime.now())) + .setReference(getPayPriceSummary(LocalDateTime.now().minusDays(1))); + } + + private TradeOrderSummaryRespVO getPayPriceSummary(LocalDateTime date) { + LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(date); + LocalDateTime endTime = LocalDateTimeUtil.beginOfDay(date); + + return tradeOrderStatisticsMapper.selectPaySummaryByStatusAndPayTimeBetween(PayOrderStatusEnum.SUCCESS.getStatus(), beginTime, endTime); + } + + @Override + public List> getOrderCountTrendComparison(TradeOrderTrendReqVO reqVO) { + // 查询当前数据 + List value = getOrderCountTrend(reqVO.getType(), reqVO.getBeginTime(), reqVO.getEndTime()); + // 查询对照数据 + LocalDateTime referenceEndTime = reqVO.getBeginTime().minusDays(1); + LocalDateTime referenceBeginTime = referenceEndTime.minus(Duration.between(reqVO.getBeginTime(), reqVO.getEndTime())); + List reference = getOrderCountTrend(reqVO.getType(), referenceBeginTime, referenceEndTime); + + return IntStream.range(0, value.size()) + .mapToObj(index -> new DataComparisonRespVO() + .setValue(CollUtil.get(value, index)) + .setReference(CollUtil.get(reference, index))) + .collect(Collectors.toList()); + } + + private List getOrderCountTrend(Integer timeRangeType, LocalDateTime beginTime, LocalDateTime endTime) { + // 情况一:按年统计时,以月份分组 + if (TimeRangeTypeEnum.YEAR.getType().equals(timeRangeType)) { + return tradeOrderStatisticsMapper.selectListByPayTimeBetweenAndGroupByMonth(beginTime, endTime); + } + // 情况二:其它以天分组(天、周、月) + return tradeOrderStatisticsMapper.selectListByPayTimeBetweenAndGroupByDay(beginTime, endTime); + } + } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsService.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsService.java index cf0477455..949f95ba9 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsService.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsService.java @@ -1,8 +1,9 @@ package cn.iocoder.yudao.module.statistics.service.trade; -import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO; -import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeSummaryRespVO; +import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO; import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO; +import cn.iocoder.yudao.module.statistics.dal.dataobject.trade.TradeStatisticsDO; +import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeSummaryRespBO; import java.time.LocalDateTime; import java.util.List; @@ -14,26 +15,19 @@ import java.util.List; */ public interface TradeStatisticsService { - /** - * 获得交易统计 - * - * @return 统计数据对照 - */ - TradeStatisticsComparisonRespVO getTradeSummaryComparison(); - /** * 获得交易状况统计对照 * * @return 统计数据对照 */ - TradeStatisticsComparisonRespVO getTradeTrendSummaryComparison( + DataComparisonRespVO getTradeTrendSummaryComparison( LocalDateTime beginTime, LocalDateTime endTime); /** * 获得交易状况统计 * * @param beginTime 开始时间 - * @param endTime 结束时间 + * @param endTime 结束时间 * @return 统计数据对照 */ Integer getExpensePrice(LocalDateTime beginTime, LocalDateTime endTime); @@ -41,16 +35,34 @@ public interface TradeStatisticsService { /** * 获得交易状况明细 * + * @param beginTime 开始时间 + * @param endTime 结束时间 * @return 统计数据列表 */ - List getTradeStatisticsList(LocalDateTime beginTime, LocalDateTime endTime); + List getTradeStatisticsList(LocalDateTime beginTime, LocalDateTime endTime); // TODO 芋艿:已经 review; /** - * 统计昨日交易 + * 统计指定天数的交易数据 * - * @return 耗时 + * @return 统计结果 */ - String statisticsYesterdayTrade(); + String statisticsTrade(Integer days); + + /** + * 统计指定日期的交易数据 + * + * @param days 增加的天数 + * @return 交易数据 + */ + TradeSummaryRespBO getTradeSummaryByDays(int days); + + /** + * 统计指定月份的交易数据 + * + * @param months 增加的月数 + * @return 交易数据 + */ + TradeSummaryRespBO getTradeSummaryByMonths(int months); } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsServiceImpl.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsServiceImpl.java index e2f89eb41..43b3fa475 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsServiceImpl.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsServiceImpl.java @@ -1,18 +1,18 @@ package cn.iocoder.yudao.module.statistics.service.trade; +import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.LocalDateTimeUtil; import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; -import cn.iocoder.yudao.module.statistics.service.pay.PayWalletStatisticsService; -import cn.iocoder.yudao.module.statistics.service.trade.bo.WalletSummaryRespBO; -import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO; -import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeSummaryRespVO; +import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO; import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO; import cn.iocoder.yudao.module.statistics.convert.trade.TradeStatisticsConvert; import cn.iocoder.yudao.module.statistics.dal.dataobject.trade.TradeStatisticsDO; import cn.iocoder.yudao.module.statistics.dal.mysql.trade.TradeStatisticsMapper; -import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeSummaryRespBO; +import cn.iocoder.yudao.module.statistics.service.pay.PayWalletStatisticsService; import cn.iocoder.yudao.module.statistics.service.trade.bo.AfterSaleSummaryRespBO; import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeOrderSummaryRespBO; +import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeSummaryRespBO; +import cn.iocoder.yudao.module.statistics.service.trade.bo.WalletSummaryRespBO; import org.springframework.stereotype.Service; import org.springframework.util.StopWatch; import org.springframework.validation.annotation.Validated; @@ -21,6 +21,8 @@ import javax.annotation.Resource; import java.time.Duration; import java.time.LocalDateTime; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; /** * 交易统计 Service 实现类 @@ -44,51 +46,27 @@ public class TradeStatisticsServiceImpl implements TradeStatisticsService { private PayWalletStatisticsService payWalletStatisticsService; @Override - public TradeStatisticsComparisonRespVO getTradeSummaryComparison() { - // 1.1 昨天的数据 - TradeSummaryRespBO yesterdayData = getTradeSummaryByDays(-1); - // 1.2 前天的数据(用于对照昨天的数据) - TradeSummaryRespBO beforeYesterdayData = getTradeSummaryByDays(-2); - // 2.1 本月数据 - TradeSummaryRespBO monthData = getTradeSummaryByMonths(0); - // 2.2 上月数据(用于对照本月的数据) - TradeSummaryRespBO lastMonthData = getTradeSummaryByMonths(-1); - // 转换返回 - return TradeStatisticsConvert.INSTANCE.convert(yesterdayData, beforeYesterdayData, monthData, lastMonthData); - } - - /** - * 统计指定日期的交易数据 - * - * @param days 增加的天数 - * @return 交易数据 - */ - private TradeSummaryRespBO getTradeSummaryByDays(int days) { + public TradeSummaryRespBO getTradeSummaryByDays(int days) { LocalDateTime date = LocalDateTime.now().plusDays(days); return tradeStatisticsMapper.selectOrderCreateCountSumAndOrderPayPriceSumByTimeBetween( LocalDateTimeUtil.beginOfDay(date), LocalDateTimeUtil.endOfDay(date)); } - /** - * 统计指定月份的交易数据 - * - * @param months 增加的月数 - * @return 交易数据 - */ - private TradeSummaryRespBO getTradeSummaryByMonths(int months) { + @Override + public TradeSummaryRespBO getTradeSummaryByMonths(int months) { LocalDateTime monthDate = LocalDateTime.now().plusMonths(months); return tradeStatisticsMapper.selectOrderCreateCountSumAndOrderPayPriceSumByTimeBetween( LocalDateTimeUtils.beginOfMonth(monthDate), LocalDateTimeUtils.endOfMonth(monthDate)); } @Override - public TradeStatisticsComparisonRespVO getTradeTrendSummaryComparison(LocalDateTime beginTime, - LocalDateTime endTime) { + public DataComparisonRespVO getTradeTrendSummaryComparison(LocalDateTime beginTime, + LocalDateTime endTime) { // 统计数据 - TradeTrendSummaryRespVO value = tradeStatisticsMapper.selectByTimeBetween(beginTime, endTime); + TradeTrendSummaryRespVO value = tradeStatisticsMapper.selectVoByTimeBetween(beginTime, endTime); // 对照数据 LocalDateTime referenceBeginTime = beginTime.minus(Duration.between(beginTime, endTime)); - TradeTrendSummaryRespVO reference = tradeStatisticsMapper.selectByTimeBetween(referenceBeginTime, beginTime); + TradeTrendSummaryRespVO reference = tradeStatisticsMapper.selectVoByTimeBetween(referenceBeginTime, beginTime); return TradeStatisticsConvert.INSTANCE.convert(value, reference); } @@ -97,41 +75,60 @@ public class TradeStatisticsServiceImpl implements TradeStatisticsService { return tradeStatisticsMapper.selectExpensePriceByTimeBetween(beginTime, endTime); } - // TODO @疯狂:是不是直接返回 TradeStatisticsDO;上层在去聚合? @Override - public List getTradeStatisticsList(LocalDateTime beginTime, LocalDateTime endTime) { + public List getTradeStatisticsList(LocalDateTime beginTime, LocalDateTime endTime) { return tradeStatisticsMapper.selectListByTimeBetween(beginTime, endTime); } @Override - public String statisticsYesterdayTrade() { - // TODO @疯狂:如果已经统计,则跳过; - // TODO @疯狂:改成 statisticsTrade,然后传入 days,统计多少天;days 通过 job 传参;方便把历史给统计出来;或者大家有的时候要修复数据(会 fix 业务数据,然后清理统计表),重新统计的时候; - // 1. 从各个数据表,统计对应数据 - LocalDateTime yesterday = LocalDateTime.now().minusDays(1); - LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(yesterday); - LocalDateTime endTime = LocalDateTimeUtil.endOfDay(yesterday); - // 1.1 统计订单 - StopWatch stopWatch = new StopWatch("交易统计"); + public String statisticsTrade(Integer days) { + LocalDateTime today = LocalDateTime.now(); + return IntStream.rangeClosed(1, days) + .parallel() + .mapToObj(day -> statisticsTrade(today.minusDays(day))) + .sorted() + .collect(Collectors.joining("\n")); + } + + /** + * 统计交易数据 + * + * @param date 需要统计的日期 + * @return 统计结果 + */ + private String statisticsTrade(LocalDateTime date) { + // 1. 处理统计时间范围 + LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(date); + LocalDateTime endTime = LocalDateTimeUtil.endOfDay(date); + String dateStr = DatePattern.NORM_DATE_FORMAT.format(date); + // 2. 检查该日是否已经统计过 + TradeStatisticsDO entity = tradeStatisticsMapper.selectByTimeBetween(beginTime, endTime); + if (entity != null) { + return dateStr + " 数据已存在,如果需要重新统计,请先删除对应的数据"; + } + + // 3. 从各个数据表,统计对应数据 + StopWatch stopWatch = new StopWatch(dateStr); + // 3.1 统计订单 stopWatch.start("统计订单"); TradeOrderSummaryRespBO orderSummary = tradeOrderStatisticsService.getOrderSummary(beginTime, endTime); stopWatch.stop(); - // 1.2 统计售后 + // 3.2 统计售后 stopWatch.start("统计售后"); AfterSaleSummaryRespBO afterSaleSummary = afterSaleStatisticsService.getAfterSaleSummary(beginTime, endTime); stopWatch.stop(); - // 1.3 统计佣金 + // 3.3 统计佣金 stopWatch.start("统计佣金"); Integer brokerageSettlementPrice = brokerageStatisticsService.getBrokerageSettlementPriceSummary(beginTime, endTime); stopWatch.stop(); - // 1.4 统计充值 + // 3.4 统计充值 stopWatch.start("统计充值"); WalletSummaryRespBO walletSummary = payWalletStatisticsService.getWalletSummary(beginTime, endTime); stopWatch.stop(); - // 2. 插入数据 - TradeStatisticsDO entity = TradeStatisticsConvert.INSTANCE.convert(yesterday, orderSummary, afterSaleSummary, - brokerageSettlementPrice, walletSummary); + // 4. 插入数据 + entity = TradeStatisticsConvert.INSTANCE.convert(date, orderSummary, afterSaleSummary, brokerageSettlementPrice, + walletSummary); tradeStatisticsMapper.insert(entity); return stopWatch.prettyPrint(); } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/infra/ApiAccessLogStatisticsMapper.xml b/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/infra/ApiAccessLogStatisticsMapper.xml index 13bcdb419..e64161597 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/infra/ApiAccessLogStatisticsMapper.xml +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/infra/ApiAccessLogStatisticsMapper.xml @@ -2,23 +2,21 @@ - + SELECT COUNT(DISTINCT user_ip) FROM infra_api_access_log - WHERE create_time BETWEEN #{beginTime} AND #{endTime} - AND deleted = FALSE - GROUP BY user_ip + WHERE user_type = #{userType} + AND create_time BETWEEN #{beginTime} AND #{endTime} + AND deleted = FALSE - + SELECT COUNT(DISTINCT user_id) FROM infra_api_access_log WHERE user_id > 0 + AND user_type = #{userType} AND create_time BETWEEN #{beginTime} AND #{endTime} AND deleted = FALSE - GROUP BY user_id diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/member/MemberStatisticsMapper.xml b/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/member/MemberStatisticsMapper.xml index 648e93fe8..33500fb43 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/member/MemberStatisticsMapper.xml +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/member/MemberStatisticsMapper.xml @@ -3,7 +3,7 @@ + + + + diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/pay/PayWalletStatisticsMapper.xml b/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/pay/PayWalletStatisticsMapper.xml index cc9408356..097780841 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/pay/PayWalletStatisticsMapper.xml +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/pay/PayWalletStatisticsMapper.xml @@ -32,9 +32,8 @@ + + diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/AfterSaleStatisticsMapper.xml b/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/AfterSaleStatisticsMapper.xml index 000cb26fd..933c45610 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/AfterSaleStatisticsMapper.xml +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/AfterSaleStatisticsMapper.xml @@ -11,4 +11,11 @@ AND deleted = FALSE + + diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/BrokerageStatisticsMapper.xml b/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/BrokerageStatisticsMapper.xml index f8f9b2c11..dff7e444f 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/BrokerageStatisticsMapper.xml +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/BrokerageStatisticsMapper.xml @@ -11,4 +11,11 @@ AND deleted = FALSE + + diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/TradeOrderStatisticsMapper.xml b/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/TradeOrderStatisticsMapper.xml index 2cecd468e..22e468e3a 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/TradeOrderStatisticsMapper.xml +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/TradeOrderStatisticsMapper.xml @@ -1,18 +1,17 @@ - + + + + + + + + + + diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/TradeStatisticsMapper.xml b/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/TradeStatisticsMapper.xml index 1ef2e2f39..74cc11ac9 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/TradeStatisticsMapper.xml +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/TradeStatisticsMapper.xml @@ -11,16 +11,16 @@ AND deleted = FALSE - - -