statistics:初始化
parent
e26b29c5eb
commit
97103a8846
|
@ -7,12 +7,16 @@ import cn.hutool.core.text.csv.CsvUtil;
|
|||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import cn.iocoder.yudao.framework.ip.core.Area;
|
||||
import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum;
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
|
||||
/**
|
||||
* 区域工具类
|
||||
|
@ -108,7 +112,7 @@ public class AreaUtils {
|
|||
// “递归”父节点
|
||||
area = area.getParent();
|
||||
if (area == null
|
||||
|| ObjectUtils.equalsAny(area.getId(), Area.ID_GLOBAL, Area.ID_CHINA)) { // 跳过父节点为中国的情况
|
||||
|| ObjectUtils.equalsAny(area.getId(), Area.ID_GLOBAL, Area.ID_CHINA)) { // 跳过父节点为中国的情况
|
||||
break;
|
||||
}
|
||||
sb.insert(0, separator);
|
||||
|
@ -116,4 +120,43 @@ public class AreaUtils {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定类型的区域列表
|
||||
*
|
||||
* @param type 区域类型
|
||||
* @param func 转换函数
|
||||
* @param <T> 结果类型
|
||||
* @return 区域列表
|
||||
*/
|
||||
public static <T> List<T> getByType(AreaTypeEnum type, Function<Area, T> func) {
|
||||
return convertList(areas.values(), func, area -> type.getType().equals(area.getType()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据区域编号、上级区域类型,获取上级区域编号
|
||||
*
|
||||
* @param id 区域编号
|
||||
* @param type 区域类型
|
||||
* @return 上级区域编号
|
||||
*/
|
||||
public static Integer getParentIdByType(Integer id, @NonNull AreaTypeEnum type) {
|
||||
for (int i = 0; i < Byte.MAX_VALUE; i++) {
|
||||
Area area = AreaUtils.getArea(id);
|
||||
if (area == null) {
|
||||
return null;
|
||||
}
|
||||
// 情况一:匹配到,返回它
|
||||
if (type.getType().equals(area.getType())) {
|
||||
return area.getId();
|
||||
}
|
||||
// 情况二:找到根节点,返回空
|
||||
if (area.getParent() == null || area.getParent().getId() == null) {
|
||||
return null;
|
||||
}
|
||||
// 其它:继续向上查找
|
||||
id = area.getParent().getId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
<module>yudao-module-product-biz</module>
|
||||
<module>yudao-module-trade-api</module>
|
||||
<module>yudao-module-trade-biz</module>
|
||||
<!-- <module>yudao-module-statistics-api</module>-->
|
||||
<!-- <module>yudao-module-statistics-biz</module>-->
|
||||
<module>yudao-module-statistics-api</module>
|
||||
<module>yudao-module-statistics-biz</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-module-mall</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>yudao-module-statistics-api</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>
|
||||
statistics 模块 API,暴露给其它模块调用
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Web 相关 -->
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-ui</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- 参数校验 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- RPC 远程调用相关 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* TODO 占位,无特殊含义
|
||||
*/
|
||||
package cn.iocoder.yudao.module.statistics.api;
|
|
@ -0,0 +1,48 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* TODO 占位,无特殊含义
|
||||
*/
|
||||
package cn.iocoder.yudao.module.statistics.enums;
|
|
@ -0,0 +1,141 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-module-mall</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>yudao-module-statistics-biz</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>
|
||||
statistics 模块,主要实现统计相关功能
|
||||
例如:统计商品、会员、交易等功能。
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring Cloud 基础 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-bootstrap</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-env</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 依赖服务 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-module-statistics-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-module-promotion-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-module-product-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-module-trade-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-module-member-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-module-pay-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 业务组件 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-ip</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Web 相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- DB 相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- RPC 远程调用相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-rpc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Registry 注册中心相关 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Config 配置中心相关 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Job 定时任务相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-job</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test 测试相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 工具类相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-excel</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-dict</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 监控相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-monitor</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,30 @@
|
|||
package cn.iocoder.yudao.module.statistics;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* 项目的启动类
|
||||
*
|
||||
* 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
|
||||
* 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
|
||||
* 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class StatisticsServerApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
|
||||
// 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
|
||||
// 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
|
||||
|
||||
SpringApplication.run(StatisticsServerApplication.class, args);
|
||||
|
||||
// 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
|
||||
// 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
|
||||
// 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
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;
|
||||
|
||||
@Schema(description = "管理后台 - 数据对照 Response VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class DataComparisonRespVO<T> {
|
||||
|
||||
@Schema(description = "当前数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private T value;
|
||||
|
||||
@Schema(description = "参照数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private T reference;
|
||||
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
package cn.iocoder.yudao.module.statistics.controller.admin.member;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
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;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
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 java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 会员统计")
|
||||
@RestController
|
||||
@RequestMapping("/statistics/member")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class MemberStatisticsController {
|
||||
|
||||
@Resource
|
||||
private MemberStatisticsService memberStatisticsService;
|
||||
@Resource
|
||||
private TradeOrderStatisticsService tradeOrderStatisticsService;
|
||||
@Resource
|
||||
private ApiAccessLogStatisticsService apiAccessLogStatisticsService;
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
@GetMapping("/summary")
|
||||
@Operation(summary = "获得会员统计(实时统计)")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:member:query')")
|
||||
public CommonResult<MemberSummaryRespVO> getMemberSummary() {
|
||||
return success(memberStatisticsService.getMemberSummary());
|
||||
}
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
@GetMapping("/analyse")
|
||||
@Operation(summary = "获得会员分析数据")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:member:query')")
|
||||
public CommonResult<MemberAnalyseRespVO> getMemberAnalyse(MemberAnalyseReqVO reqVO) {
|
||||
// 1. 查询数据
|
||||
LocalDateTime beginTime = ArrayUtil.get(reqVO.getTimes(), 0);
|
||||
LocalDateTime endTime = ArrayUtil.get(reqVO.getTimes(), 1);
|
||||
// 1.1 查询分析对照数据
|
||||
DataComparisonRespVO<MemberAnalyseDataRespVO> comparisonData = memberStatisticsService.getMemberAnalyseComparisonData(beginTime, endTime);
|
||||
// TODO @疯狂:这个可能有点特殊,要按照 create_time 来查询;不然它的漏斗就不统一;因为是访问数量 > 今日下单人 > 今日支付人;是一个统一的维度;
|
||||
// 1.2 查询成交用户数量
|
||||
Integer payUserCount = tradeOrderStatisticsService.getPayUserCount(beginTime, endTime);
|
||||
// 1.3 计算客单价
|
||||
int atv = 0;
|
||||
if (payUserCount != null && payUserCount > 0) {
|
||||
// TODO @疯狂:类似上面的 payUserCount
|
||||
Integer payPrice = tradeOrderStatisticsService.getOrderPayPrice(beginTime, endTime);
|
||||
atv = NumberUtil.div(payPrice, payUserCount).intValue();
|
||||
}
|
||||
// 1.4 查询访客数量
|
||||
Integer visitUserCount = apiAccessLogStatisticsService.getIpCount(UserTypeEnum.MEMBER.getValue(), beginTime, endTime);
|
||||
// 1.5 下单用户数量
|
||||
Integer orderUserCount = tradeOrderStatisticsService.getOrderUserCount(beginTime, endTime);
|
||||
|
||||
// 2. 拼接返回
|
||||
return success(MemberStatisticsConvert.INSTANCE.convert(visitUserCount, orderUserCount, payUserCount, atv, comparisonData));
|
||||
}
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
@GetMapping("/area-statistics-list")
|
||||
@Operation(summary = "按照省份,获得会员统计列表")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:member:query')")
|
||||
public CommonResult<List<MemberAreaStatisticsRespVO>> getMemberAreaStatisticsList() {
|
||||
return success(memberStatisticsService.getMemberAreaStatisticsList());
|
||||
}
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
@GetMapping("/sex-statistics-list")
|
||||
@Operation(summary = "按照性别,获得会员统计列表")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:member:query')")
|
||||
public CommonResult<List<MemberSexStatisticsRespVO>> getMemberSexStatisticsList() {
|
||||
return success(memberStatisticsService.getMemberSexStatisticsList());
|
||||
}
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
@GetMapping("/terminal-statistics-list")
|
||||
@Operation(summary = "按照终端,获得会员统计列表")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:member:query')")
|
||||
public CommonResult<List<MemberTerminalStatisticsRespVO>> getMemberTerminalStatisticsList() {
|
||||
return success(memberStatisticsService.getMemberTerminalStatisticsList());
|
||||
}
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
// TODO @疯狂:要注意 date 的排序;
|
||||
@GetMapping("/user-count-comparison")
|
||||
@Operation(summary = "获得用户数量对照")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:member:query')")
|
||||
public CommonResult<DataComparisonRespVO<MemberCountRespVO>> getUserCountComparison() {
|
||||
return success(memberStatisticsService.getUserCountComparison());
|
||||
}
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
@GetMapping("/register-count-list")
|
||||
@Operation(summary = "获得会员注册数量列表")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:member:query')")
|
||||
public CommonResult<List<MemberRegisterCountRespVO>> getMemberRegisterCountList(MemberAnalyseReqVO reqVO) {
|
||||
return success(memberStatisticsService.getMemberRegisterCountList(
|
||||
ArrayUtil.get(reqVO.getTimes(), 0), ArrayUtil.get(reqVO.getTimes(), 1)));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
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 MemberAnalyseDataRespVO {
|
||||
|
||||
@Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer registerUserCount;
|
||||
|
||||
@Schema(description = "活跃用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer visitUserCount;
|
||||
|
||||
@Schema(description = "充值会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "221")
|
||||
private Integer rechargeUserCount;
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package cn.iocoder.yudao.module.statistics.controller.admin.member.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
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 MemberAnalyseReqVO {
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@Schema(description = "时间范围")
|
||||
private LocalDateTime[] times;
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package cn.iocoder.yudao.module.statistics.controller.admin.member.vo;
|
||||
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - 会员分析 Response VO")
|
||||
@Data
|
||||
public class MemberAnalyseRespVO {
|
||||
|
||||
@Schema(description = "访客数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer visitUserCount;
|
||||
|
||||
@Schema(description = "下单用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer orderUserCount;
|
||||
|
||||
@Schema(description = "成交用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer payUserCount;
|
||||
|
||||
@Schema(description = "客单价,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer atv;
|
||||
|
||||
@Schema(description = "对照数据", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private DataComparisonRespVO<MemberAnalyseDataRespVO> comparison;
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
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 MemberAreaStatisticsRespVO {
|
||||
|
||||
@Schema(description = "省份编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer areaId;
|
||||
@Schema(description = "省份名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "浙江省")
|
||||
private String areaName;
|
||||
|
||||
@Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer userCount;
|
||||
|
||||
@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;
|
||||
|
||||
}
|
|
@ -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 registerUserCount;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
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 MemberSexStatisticsRespVO {
|
||||
|
||||
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer sex;
|
||||
|
||||
// TODO @疯狂:要不还是其它字段,我们也补全,这样方便使用的用户,做定制化;就保持和 MemberAreaStatisticsRespVO 一致;
|
||||
@Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer userCount;
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
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 MemberSummaryRespVO {
|
||||
|
||||
@Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer userCount;
|
||||
|
||||
@Schema(description = "充值会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "221")
|
||||
private Integer rechargeUserCount;
|
||||
|
||||
@Schema(description = "充值金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer rechargePrice;
|
||||
|
||||
// TODO @疯狂:要不干脆这个字段改成:orderPayPrice??
|
||||
@Schema(description = "支出金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer expensePrice; // 只计算 mall 交易订单的支付金额,不考虑退款
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
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 MemberTerminalStatisticsRespVO {
|
||||
|
||||
@Schema(description = "终端", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer terminal;
|
||||
|
||||
// TODO @疯狂:要不 orderCreateUserCount 和 orderPayUserCount 貌似更统一一些;
|
||||
@Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer userCount;
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package cn.iocoder.yudao.module.statistics.controller.admin.pay;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.pay.vo.PaySummaryRespVO;
|
||||
import cn.iocoder.yudao.module.statistics.convert.pay.PayStatisticsConvert;
|
||||
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("/summary")
|
||||
@Operation(summary = "获取充值金额")
|
||||
public CommonResult<PaySummaryRespVO> getWalletRechargePrice() {
|
||||
Integer rechargePrice = payWalletStatisticsService.getRechargePriceSummary();
|
||||
return success(PayStatisticsConvert.INSTANCE.convert(rechargePrice));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package cn.iocoder.yudao.module.statistics.controller.admin.pay.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - 支付统计 Response VO")
|
||||
@Data
|
||||
public class PaySummaryRespVO {
|
||||
|
||||
@Schema(description = "充值金额,单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer rechargePrice;
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package cn.iocoder.yudao.module.statistics.controller.admin.product;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.statistics.dal.mysql.product.ProductSpuStatisticsDO;
|
||||
import cn.iocoder.yudao.module.statistics.dal.mysql.product.ProductStatisticsDO;
|
||||
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.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "管理后台 - 商品统计")
|
||||
@RestController
|
||||
@RequestMapping("/statistics/product")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class ProductStatisticsController {
|
||||
|
||||
// TODO @麦子:返回 ProductStatisticsComparisonResp, 里面有两个字段,一个是选择的时间范围的合计结果,一个是对比的时间范围的合计结果;
|
||||
// 例如说,选择时间范围是 2023-10-01 ~ 2023-10-02,那么对比就是 2023-09-30,再倒推 2 天;
|
||||
public CommonResult<Object> getProductStatisticsComparison() {
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO @麦子:查询指定时间范围内的商品统计数据;DO 到时需要改成 VO 哈
|
||||
public CommonResult<List<ProductStatisticsDO>> getProductStatisticsList(
|
||||
LocalDateTime[] times) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO @麦子:查询指定时间范围内的商品 SPU 统计数据;DO 到时需要改成 VO 哈
|
||||
// 入参是分页参数 + 时间范围 + 排序字段
|
||||
public CommonResult<PageResult<ProductSpuStatisticsDO>> getProductSpuStatisticsPage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
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 cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
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 javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 交易统计")
|
||||
@RestController
|
||||
@RequestMapping("/statistics/trade")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class TradeStatisticsController {
|
||||
|
||||
@Resource
|
||||
private TradeStatisticsService tradeStatisticsService;
|
||||
@Resource
|
||||
private TradeOrderStatisticsService tradeOrderStatisticsService;
|
||||
@Resource
|
||||
private AfterSaleStatisticsService afterSaleStatisticsService;
|
||||
@Resource
|
||||
private BrokerageStatisticsService brokerageStatisticsService;
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
@GetMapping("/summary")
|
||||
@Operation(summary = "获得交易统计")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:trade:query')")
|
||||
public CommonResult<DataComparisonRespVO<TradeSummaryRespVO>> 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<DataComparisonRespVO<TradeTrendSummaryRespVO>> getTradeTrendSummaryComparison(
|
||||
TradeTrendReqVO reqVO) {
|
||||
return success(tradeStatisticsService.getTradeTrendSummaryComparison(ArrayUtil.get(reqVO.getTimes(), 0),
|
||||
ArrayUtil.get(reqVO.getTimes(), 1)));
|
||||
}
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "获得交易状况明细")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:trade:query')")
|
||||
public CommonResult<List<TradeTrendSummaryRespVO>> getTradeStatisticsList(TradeTrendReqVO reqVO) {
|
||||
List<TradeStatisticsDO> list = tradeStatisticsService.getTradeStatisticsList(ArrayUtil.get(reqVO.getTimes(), 0),
|
||||
ArrayUtil.get(reqVO.getTimes(), 1));
|
||||
return success(TradeStatisticsConvert.INSTANCE.convertList(list));
|
||||
}
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出获得交易状况明细 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:trade:export')")
|
||||
public void exportTradeStatisticsExcel(TradeTrendReqVO reqVO, HttpServletResponse response) throws IOException {
|
||||
List<TradeStatisticsDO> list = tradeStatisticsService.getTradeStatisticsList(ArrayUtil.get(reqVO.getTimes(), 0),
|
||||
ArrayUtil.get(reqVO.getTimes(), 1));
|
||||
// 导出 Excel
|
||||
List<TradeTrendSummaryRespVO> voList = TradeStatisticsConvert.INSTANCE.convertList(list);
|
||||
List<TradeTrendSummaryExcelVO> data = TradeStatisticsConvert.INSTANCE.convertList02(voList);
|
||||
ExcelUtils.write(response, "交易状况.xls", "数据", TradeTrendSummaryExcelVO.class, data);
|
||||
}
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
@GetMapping("/order-count")
|
||||
@Operation(summary = "获得交易订单数量")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:trade:query')")
|
||||
public CommonResult<TradeOrderCountRespVO> getOrderCount() {
|
||||
// 订单统计
|
||||
Long undeliveredCount = tradeOrderStatisticsService.getCountByStatusAndDeliveryType(
|
||||
TradeOrderStatusEnum.UNDELIVERED.getStatus(), DeliveryTypeEnum.EXPRESS.getType());
|
||||
// TODO @疯狂:订单支付后,如果是门店自提的,需要 update 成 DELIVERED;;目前还没搞~~突然反应过来
|
||||
Long pickUpCount = tradeOrderStatisticsService.getCountByStatusAndDeliveryType(
|
||||
TradeOrderStatusEnum.DELIVERED.getStatus(), DeliveryTypeEnum.PICK_UP.getType());
|
||||
// 售后统计
|
||||
Long afterSaleApplyCount = afterSaleStatisticsService.getCountByStatus(AfterSaleStatusEnum.APPLY);
|
||||
Long auditingWithdrawCount = brokerageStatisticsService.getWithdrawCountByStatus(BrokerageWithdrawStatusEnum.AUDITING);
|
||||
// 拼接返回
|
||||
return success(TradeStatisticsConvert.INSTANCE.convert(undeliveredCount, pickUpCount, afterSaleApplyCount, auditingWithdrawCount));
|
||||
}
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
@GetMapping("/order-comparison")
|
||||
@Operation(summary = "获得交易订单数量")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:trade:query')")
|
||||
public CommonResult<DataComparisonRespVO<TradeOrderSummaryRespVO>> getOrderComparison() {
|
||||
return success(tradeOrderStatisticsService.getOrderComparison());
|
||||
}
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
@GetMapping("/order-count-trend")
|
||||
@Operation(summary = "获得订单量趋势统计")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:trade:query')")
|
||||
public CommonResult<List<DataComparisonRespVO<TradeOrderTrendRespVO>>> getOrderCountTrendComparison(@Valid TradeOrderTrendReqVO reqVO) {
|
||||
// TODO @疯狂:要注意 date 的排序;
|
||||
return success(tradeOrderStatisticsService.getOrderCountTrendComparison(reqVO));
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
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 TradeSummaryRespVO {
|
||||
|
||||
@Schema(description = "昨日订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer yesterdayOrderCount;
|
||||
@Schema(description = "昨日支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer yesterdayPayPrice;
|
||||
|
||||
@Schema(description = "本月订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer monthOrderCount;
|
||||
@Schema(description = "本月支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer monthPayPrice;
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
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 TradeTrendReqVO {
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@Schema(description = "时间范围")
|
||||
private LocalDateTime[] times;
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.convert.MoneyConvert;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.alibaba.excel.annotation.format.DateTimeFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
|
||||
|
||||
/**
|
||||
* 交易状况统计 Excel VO
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Data
|
||||
public class TradeTrendSummaryExcelVO {
|
||||
|
||||
@ExcelProperty(value = "日期")
|
||||
@DateTimeFormat(FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate date;
|
||||
|
||||
@ExcelProperty(value = "营业额", converter = MoneyConvert.class)
|
||||
private Integer turnoverPrice;
|
||||
|
||||
@ExcelProperty(value = "商品支付金额", converter = MoneyConvert.class)
|
||||
private Integer orderPayPrice;
|
||||
|
||||
@ExcelProperty(value = "充值金额", converter = MoneyConvert.class)
|
||||
private Integer rechargePrice;
|
||||
|
||||
@ExcelProperty(value = "支出金额", converter = MoneyConvert.class)
|
||||
private Integer expensePrice;
|
||||
|
||||
@ExcelProperty(value = "余额支付金额", converter = MoneyConvert.class)
|
||||
private Integer walletPayPrice;
|
||||
|
||||
@ExcelProperty(value = "支付佣金金额", converter = MoneyConvert.class)
|
||||
private Integer brokerageSettlementPrice;
|
||||
|
||||
@ExcelProperty(value = "商品退款金额", converter = MoneyConvert.class)
|
||||
private Integer afterSaleRefundPrice;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package cn.iocoder.yudao.module.statistics.controller.admin.trade.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;
|
||||
|
||||
@Schema(description = "管理后台 - 交易状况统计 Response VO")
|
||||
@Data
|
||||
public class TradeTrendSummaryRespVO {
|
||||
|
||||
@Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate date;
|
||||
|
||||
@Schema(description = "营业额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer turnoverPrice; // 营业额 = 商品支付金额 + 充值金额
|
||||
|
||||
@Schema(description = "订单支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer orderPayPrice;
|
||||
|
||||
@Schema(description = "余额支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer walletPayPrice;
|
||||
|
||||
@Schema(description = "订单退款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer afterSaleRefundPrice;
|
||||
|
||||
@Schema(description = "支付佣金金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer brokerageSettlementPrice;
|
||||
|
||||
@Schema(description = "充值金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer rechargePrice;
|
||||
|
||||
@Schema(description = "支出金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer expensePrice; // 余额支付金额 + 支付佣金金额 + 商品退款金额
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* TODO 芋艿:占位
|
||||
*/
|
||||
package cn.iocoder.yudao.module.statistics.controller.app;
|
|
@ -0,0 +1,51 @@
|
|||
package cn.iocoder.yudao.module.statistics.convert.member;
|
||||
|
||||
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.member.bo.MemberAreaStatisticsRespBO;
|
||||
import cn.iocoder.yudao.module.statistics.service.pay.bo.RechargeSummaryRespBO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 会员统计 Convert
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Mapper
|
||||
public interface MemberStatisticsConvert {
|
||||
|
||||
MemberStatisticsConvert INSTANCE = Mappers.getMapper(MemberStatisticsConvert.class);
|
||||
|
||||
default List<MemberAreaStatisticsRespVO> convertList(List<Area> areaList,
|
||||
Map<Integer, Integer> userCountMap,
|
||||
Map<Integer, MemberAreaStatisticsRespBO> orderMap) {
|
||||
return CollectionUtils.convertList(areaList, area -> {
|
||||
MemberAreaStatisticsRespBO orderVo = Optional.ofNullable(orderMap.get(area.getId()))
|
||||
.orElseGet(MemberAreaStatisticsRespBO::new);
|
||||
return new MemberAreaStatisticsRespVO()
|
||||
.setAreaId(area.getId()).setAreaName(area.getName())
|
||||
.setUserCount(MapUtil.getInt(userCountMap, area.getId(), 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<MemberAnalyseDataRespVO> comparison);
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package cn.iocoder.yudao.module.statistics.convert.pay;
|
||||
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.pay.vo.PaySummaryRespVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* 支付统计 Convert
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Mapper
|
||||
public interface PayStatisticsConvert {
|
||||
|
||||
PayStatisticsConvert INSTANCE = Mappers.getMapper(PayStatisticsConvert.class);
|
||||
|
||||
PaySummaryRespVO convert(Integer rechargePrice);
|
||||
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package cn.iocoder.yudao.module.statistics.convert.trade;
|
||||
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO;
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeOrderCountRespVO;
|
||||
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.WalletSummaryRespBO;
|
||||
import org.mapstruct.IterableMapping;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Named;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 交易统计 Convert
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Mapper
|
||||
public interface TradeStatisticsConvert {
|
||||
|
||||
TradeStatisticsConvert INSTANCE = Mappers.getMapper(TradeStatisticsConvert.class);
|
||||
|
||||
default DataComparisonRespVO<TradeSummaryRespVO> convert(TradeSummaryRespBO yesterdayData,
|
||||
TradeSummaryRespBO beforeYesterdayData,
|
||||
TradeSummaryRespBO monthData,
|
||||
TradeSummaryRespBO lastMonthData) {
|
||||
return convert(convert(yesterdayData, monthData), convert(beforeYesterdayData, lastMonthData));
|
||||
}
|
||||
|
||||
|
||||
default TradeSummaryRespVO convert(TradeSummaryRespBO yesterdayData, TradeSummaryRespBO monthData) {
|
||||
return new TradeSummaryRespVO()
|
||||
.setYesterdayOrderCount(yesterdayData.getCount()).setYesterdayPayPrice(yesterdayData.getSummary())
|
||||
.setMonthOrderCount(monthData.getCount()).setMonthPayPrice(monthData.getSummary());
|
||||
}
|
||||
|
||||
DataComparisonRespVO<TradeSummaryRespVO> convert(TradeSummaryRespVO value, TradeSummaryRespVO reference);
|
||||
|
||||
DataComparisonRespVO<TradeTrendSummaryRespVO> convert(TradeTrendSummaryRespVO value,
|
||||
TradeTrendSummaryRespVO reference);
|
||||
|
||||
List<TradeTrendSummaryExcelVO> convertList02(List<TradeTrendSummaryRespVO> list);
|
||||
|
||||
TradeStatisticsDO convert(LocalDateTime time, TradeOrderSummaryRespBO orderSummary,
|
||||
AfterSaleSummaryRespBO afterSaleSummary, Integer brokerageSettlementPrice,
|
||||
WalletSummaryRespBO walletSummary);
|
||||
|
||||
@IterableMapping(qualifiedByName = "convert")
|
||||
List<TradeTrendSummaryRespVO> convertList(List<TradeStatisticsDO> list);
|
||||
|
||||
TradeTrendSummaryRespVO convertA(TradeStatisticsDO tradeStatistics);
|
||||
|
||||
@Named("convert")
|
||||
default TradeTrendSummaryRespVO convert(TradeStatisticsDO tradeStatistics) {
|
||||
TradeTrendSummaryRespVO vo = convertA(tradeStatistics);
|
||||
return vo
|
||||
.setDate(tradeStatistics.getTime().toLocalDate())
|
||||
// 营业额 = 商品支付金额 + 充值金额
|
||||
.setTurnoverPrice(tradeStatistics.getOrderPayPrice() + tradeStatistics.getRechargePayPrice())
|
||||
// 支出金额 = 余额支付金额 + 支付佣金金额 + 商品退款金额
|
||||
.setExpensePrice(tradeStatistics.getWalletPayPrice() + tradeStatistics.getBrokerageSettlementPrice() + tradeStatistics.getAfterSaleRefundPrice());
|
||||
}
|
||||
|
||||
TradeOrderCountRespVO convert(Long undelivered, Long pickUp, Long afterSaleApply, Long auditingWithdraw);
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package cn.iocoder.yudao.module.statistics.dal.dataobject.member;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 会员统计 DO
|
||||
* <p>
|
||||
* 以天为维度,统计全部的数据
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("member_statistics")
|
||||
@KeySequence("member_statistics_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MemberStatisticsDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号,主键自增
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 统计日期
|
||||
*/
|
||||
private LocalDateTime time;
|
||||
|
||||
/**
|
||||
* 注册用户数量
|
||||
*/
|
||||
private Integer userRegisterCount;
|
||||
/**
|
||||
* 访问用户数量(UV)
|
||||
*/
|
||||
private Integer userVisitCount;
|
||||
/**
|
||||
* 访问页面数量(PV)
|
||||
*/
|
||||
private Integer pageVisitCount;
|
||||
|
||||
/**
|
||||
* 充值用户数量
|
||||
*/
|
||||
private Integer rechargeUserCount;
|
||||
|
||||
/**
|
||||
* 创建订单用户数
|
||||
*/
|
||||
private Integer orderCreateUserCount;
|
||||
/**
|
||||
* 支付订单用户数
|
||||
*/
|
||||
private Integer orderPayUserCount;
|
||||
/**
|
||||
* 总支付金额,单位:分
|
||||
*/
|
||||
private Integer orderPayPrice;
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* 占位 todo
|
||||
*/
|
||||
package cn.iocoder.yudao.module.statistics.dal.dataobject;
|
|
@ -0,0 +1,89 @@
|
|||
package cn.iocoder.yudao.module.statistics.dal.dataobject.trade;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 交易统计 DO
|
||||
* <p>
|
||||
* 以天为维度,统计全部的数据
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("trade_statistics")
|
||||
@KeySequence("trade_statistics_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TradeStatisticsDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号,主键自增
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 统计日期
|
||||
*/
|
||||
private LocalDateTime time;
|
||||
|
||||
/**
|
||||
* 创建订单数
|
||||
*/
|
||||
private Integer orderCreateCount;
|
||||
/**
|
||||
* 支付订单商品数
|
||||
*/
|
||||
private Integer orderPayCount;
|
||||
/**
|
||||
* 总支付金额,单位:分
|
||||
*/
|
||||
private Integer orderPayPrice;
|
||||
|
||||
/**
|
||||
* 退款订单数
|
||||
*/
|
||||
private Integer afterSaleCount;
|
||||
/**
|
||||
* 总退款金额,单位:分
|
||||
*/
|
||||
private Integer afterSaleRefundPrice;
|
||||
|
||||
/**
|
||||
* 佣金金额(已结算),单位:分
|
||||
*/
|
||||
private Integer brokerageSettlementPrice;
|
||||
|
||||
/**
|
||||
* 总支付金额(余额),单位:分
|
||||
*/
|
||||
private Integer walletPayPrice;
|
||||
/**
|
||||
* 充值订单数
|
||||
* <p>
|
||||
* 从 PayWalletRechargeDO 计算
|
||||
*/
|
||||
private Integer rechargePayCount;
|
||||
/**
|
||||
* 充值金额,单位:分
|
||||
*/
|
||||
private Integer rechargePayPrice;
|
||||
/**
|
||||
* 充值退款订单数
|
||||
*/
|
||||
private Integer rechargeRefundCount;
|
||||
/**
|
||||
* 充值退款金额,单位:分
|
||||
*/
|
||||
private Integer rechargeRefundPrice;
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package cn.iocoder.yudao.module.statistics.dal.mysql.infra;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
// TODO @芋艿:api 访问日志,现在会清理,可能要单独有个偏业务的访问表;
|
||||
/**
|
||||
* API 访问日志的统计 Mapper
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Mapper
|
||||
@SuppressWarnings("rawtypes")
|
||||
public interface ApiAccessLogStatisticsMapper extends BaseMapperX {
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
Integer selectIpCountByUserTypeAndCreateTimeBetween(@Param("userType") Integer userType,
|
||||
@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
Integer selectUserCountByUserTypeAndCreateTimeBetween(@Param("userType") Integer userType,
|
||||
@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
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.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;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 会员信息的统计 Mapper
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Mapper
|
||||
@SuppressWarnings("rawtypes")
|
||||
public interface MemberStatisticsMapper extends BaseMapperX {
|
||||
|
||||
// TODO @芋艿:已经 review
|
||||
List<MemberAreaStatisticsRespBO> selectSummaryListByAreaId();
|
||||
|
||||
// TODO @芋艿:已经 review
|
||||
List<MemberSexStatisticsRespVO> selectSummaryListBySex();
|
||||
|
||||
// TODO @芋艿:已经 review
|
||||
List<MemberTerminalStatisticsRespVO> selectSummaryListByRegisterTerminal();
|
||||
|
||||
// TODO @芋艿:已经 review
|
||||
Integer selectUserCount(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
// TODO @芋艿:已经 review
|
||||
/**
|
||||
* 获得用户的每天注册数量列表
|
||||
*
|
||||
* @param beginTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return 每天注册数量列表
|
||||
*/
|
||||
List<MemberRegisterCountRespVO> selectListByCreateTimeBetween(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package cn.iocoder.yudao.module.statistics.dal.mysql.pay;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
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;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 支付钱包的统计 Mapper
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Mapper
|
||||
@SuppressWarnings("rawtypes")
|
||||
public interface PayWalletStatisticsMapper extends BaseMapperX {
|
||||
|
||||
// TODO 芋艿:已经 review;
|
||||
WalletSummaryRespBO selectRechargeSummaryByPayTimeBetween(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime,
|
||||
@Param("payStatus") Boolean payStatus);
|
||||
|
||||
// TODO 芋艿:已经 review;
|
||||
WalletSummaryRespBO selectRechargeSummaryByRefundTimeBetween(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime,
|
||||
@Param("refundStatus") Integer refundStatus);
|
||||
|
||||
// TODO 芋艿:已经 review;
|
||||
Integer selectPriceSummaryByBizTypeAndCreateTimeBetween(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime,
|
||||
@Param("bizType") Integer bizType);
|
||||
|
||||
// TODO 芋艿:已经 review;
|
||||
RechargeSummaryRespBO selectRechargeSummaryGroupByWalletId(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime,
|
||||
@Param("payStatus") Boolean payStatus);
|
||||
|
||||
// TODO 芋艿:已经 review;
|
||||
Integer selectRechargePriceSummary(@Param("payStatus") Integer payStatus);
|
||||
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package cn.iocoder.yudao.module.statistics.dal.mysql.product;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 商品 SPU 统计 DO
|
||||
*
|
||||
* 以天为维度,统计商品 SPU 的数据
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("product_spu_statistics")
|
||||
@KeySequence("product_spu_statistics_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ProductSpuStatisticsDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号,主键自增
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 商品 SPU 编号
|
||||
*
|
||||
* 关联 ProductSpuDO 的 id 字段
|
||||
*/
|
||||
private Long spuId;
|
||||
/**
|
||||
* 统计日期
|
||||
*/
|
||||
private LocalDateTime time;
|
||||
|
||||
/**
|
||||
* 浏览量
|
||||
*/
|
||||
private Integer browseCount;
|
||||
/**
|
||||
* 收藏量
|
||||
*/
|
||||
private Integer favoriteCount;
|
||||
|
||||
/**
|
||||
* 添加购物车次数
|
||||
*
|
||||
* 以商品被添加到购物车的 createTime 计算,后续多次添加,不会增加该值。
|
||||
* 直到该次被下单、或者被删除,后续再次被添加到购物车。
|
||||
*/
|
||||
private Integer addCartCount;
|
||||
/**
|
||||
* 创建订单商品数
|
||||
*/
|
||||
private Integer createOrderCount;
|
||||
/**
|
||||
* 支付订单商品数
|
||||
*/
|
||||
private Integer payOrderCount;
|
||||
/**
|
||||
* 总支付金额,单位:分
|
||||
*/
|
||||
private Integer payPrice;
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package cn.iocoder.yudao.module.statistics.dal.mysql.product;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 商品统计 DO
|
||||
*
|
||||
* 以天为维度,统计全部的数据
|
||||
*
|
||||
* 和 {@link ProductSpuStatisticsDO} 的差异是,它是全局的统计
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("product_spu_statistics")
|
||||
@KeySequence("product_spu_statistics_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ProductStatisticsDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号,主键自增
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 统计日期
|
||||
*/
|
||||
private LocalDateTime time;
|
||||
|
||||
/**
|
||||
* 浏览量
|
||||
*/
|
||||
private Integer browseCount;
|
||||
/**
|
||||
* 收藏量
|
||||
*/
|
||||
private Integer favoriteCount;
|
||||
|
||||
/**
|
||||
* 添加购物车次数
|
||||
*
|
||||
* 以商品被添加到购物车的 createTime 计算,后续多次添加,不会增加该值。
|
||||
* 直到该次被下单、或者被删除,后续再次被添加到购物车。
|
||||
*/
|
||||
private Integer addCartCount;
|
||||
/**
|
||||
* 创建订单商品数
|
||||
*/
|
||||
private Integer createOrderCount;
|
||||
/**
|
||||
* 支付订单商品数
|
||||
*/
|
||||
private Integer payOrderCount;
|
||||
/**
|
||||
* 总支付金额,单位:分
|
||||
*/
|
||||
private Integer payPrice;
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package cn.iocoder.yudao.module.statistics.dal.mysql.trade;
|
||||
|
||||
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.trade.bo.AfterSaleSummaryRespBO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 售后订单的统计 Mapper
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Mapper
|
||||
public interface AfterSaleStatisticsMapper extends BaseMapperX<TradeStatisticsDO> {
|
||||
|
||||
// TODO 芋艿:已 review
|
||||
AfterSaleSummaryRespBO selectSummaryByRefundTimeBetween(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
Long selectCountByStatus(@Param("status") Integer status);
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package cn.iocoder.yudao.module.statistics.dal.mysql.trade;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.statistics.dal.dataobject.trade.TradeStatisticsDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 订单分销的统计 Mapper
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Mapper
|
||||
public interface BrokerageStatisticsMapper extends BaseMapperX<TradeStatisticsDO> {
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
Integer selectSummaryPriceByStatusAndUnfreezeTimeBetween(@Param("bizType") Integer bizType,
|
||||
@Param("status") Integer status,
|
||||
@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
Long selectWithdrawCountByStatus(@Param("status") Integer status);
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package cn.iocoder.yudao.module.statistics.dal.mysql.trade;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeOrderSummaryRespVO;
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeOrderTrendRespVO;
|
||||
import cn.iocoder.yudao.module.statistics.dal.dataobject.trade.TradeStatisticsDO;
|
||||
import cn.iocoder.yudao.module.statistics.service.member.bo.MemberAreaStatisticsRespBO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 交易订单的统计 Mapper
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Mapper
|
||||
public interface TradeOrderStatisticsMapper extends BaseMapperX<TradeStatisticsDO> {
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
List<MemberAreaStatisticsRespBO> selectSummaryListByAreaId();
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
Integer selectCountByCreateTimeBetween(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
Integer selectCountByPayTimeBetween(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
Integer selectSummaryPriceByPayTimeBetween(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
Integer selectUserCountByCreateTimeBetween(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
Integer selectUserCountByPayTimeBetween(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 按照支付时间统计订单(按天分组)
|
||||
*
|
||||
* @param beginTime 支付起始时间
|
||||
* @param endTime 支付截止时间
|
||||
* @return 订单统计列表
|
||||
*/
|
||||
List<TradeOrderTrendRespVO> selectListByPayTimeBetweenAndGroupByDay(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 按照支付时间统计订单(按月分组)
|
||||
*
|
||||
* @param beginTime 支付起始时间
|
||||
* @param endTime 支付截止时间
|
||||
* @return 订单统计列表
|
||||
*/
|
||||
List<TradeOrderTrendRespVO> selectListByPayTimeBetweenAndGroupByMonth(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
// TODO @芋艿:已经 review
|
||||
Long selectCountByStatusAndDeliveryType(@Param("status") Integer status, @Param("deliveryType") Integer deliveryType);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
TradeOrderSummaryRespVO selectPaySummaryByStatusAndPayTimeBetween(@Param("status") Integer status,
|
||||
@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
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;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 交易统计 Mapper
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Mapper
|
||||
public interface TradeStatisticsMapper extends BaseMapperX<TradeStatisticsDO> {
|
||||
|
||||
TradeSummaryRespBO selectOrderCreateCountSumAndOrderPayPriceSumByTimeBetween(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
TradeTrendSummaryRespVO selectVoByTimeBetween(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
// TODO @芋艿:已经 review
|
||||
default List<TradeStatisticsDO> selectListByTimeBetween(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
return selectList(new LambdaQueryWrapperX<TradeStatisticsDO>()
|
||||
.between(TradeStatisticsDO::getTime, beginTime, endTime));
|
||||
}
|
||||
|
||||
// TODO @芋艿:已经 review
|
||||
Integer selectExpensePriceByTimeBetween(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
// TODO @芋艿:已经 review
|
||||
default TradeStatisticsDO selectByTimeBetween(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
return selectOne(new LambdaQueryWrapperX<TradeStatisticsDO>()
|
||||
.between(TradeStatisticsDO::getTime, beginTime, endTime));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* TODO 芋艿,占坑,无特殊含义
|
||||
*/
|
||||
package cn.iocoder.yudao.module.statistics.job;
|
|
@ -0,0 +1,49 @@
|
|||
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.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
|
||||
import cn.iocoder.yudao.module.statistics.service.trade.TradeStatisticsService;
|
||||
import com.xxl.job.core.handler.annotation.XxlJob;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
// TODO 芋艿:缺个 Job 的配置;等和 Product 一起配置
|
||||
/**
|
||||
* 交易统计 Job
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Component
|
||||
public class TradeStatisticsJob {
|
||||
|
||||
@Resource
|
||||
private TradeStatisticsService tradeStatisticsService;
|
||||
|
||||
/**
|
||||
* 执行交易统计任务
|
||||
*
|
||||
* @param param 要统计的天数,只能是正整数,1 代表昨日数据
|
||||
* @return 统计结果
|
||||
*/
|
||||
@XxlJob("tradeStatisticsJob")
|
||||
@TenantJob
|
||||
public String execute(String param) {
|
||||
// 默认昨日
|
||||
param = ObjUtil.defaultIfBlank(param, "1");
|
||||
// 校验参数的合理性
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* statistics 模块,主要实现统计相关功能。
|
||||
* 例如:统计商品、会员、交易等功能。
|
||||
*
|
||||
* 1. Controller URL:以 /statistics/ 开头,避免和其它 Module 冲突
|
||||
* 2. DataObject 表名:以 statistics_ 为后缀,方便在数据库中区分【特殊】
|
||||
*/
|
||||
package cn.iocoder.yudao.module.statistics;
|
|
@ -0,0 +1,34 @@
|
|||
package cn.iocoder.yudao.module.statistics.service.infra;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* API 访问日志的统计 Service 接口
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
public interface ApiAccessLogStatisticsService {
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 获取活跃用户数量
|
||||
*
|
||||
* @param userType 用户类型
|
||||
* @param beginTime 起始时间
|
||||
* @param endTime 截止时间
|
||||
* @return 活跃用户数量
|
||||
*/
|
||||
Integer getUserCount(Integer userType, LocalDateTime beginTime, LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 获取访问用户数量
|
||||
*
|
||||
* @param userType 用户类型
|
||||
* @param beginTime 起始时间
|
||||
* @param endTime 截止时间
|
||||
* @return 访问用户数量
|
||||
*/
|
||||
Integer getIpCount(Integer userType, LocalDateTime beginTime, LocalDateTime endTime);
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package cn.iocoder.yudao.module.statistics.service.infra;
|
||||
|
||||
import cn.iocoder.yudao.module.statistics.dal.mysql.infra.ApiAccessLogStatisticsMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* API 访问日志的统计 Service 实现类
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class ApiAccessLogStatisticsServiceImpl implements ApiAccessLogStatisticsService {
|
||||
|
||||
@Resource
|
||||
private ApiAccessLogStatisticsMapper apiAccessLogStatisticsMapper;
|
||||
|
||||
@Override
|
||||
public Integer getUserCount(Integer userType, LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
return apiAccessLogStatisticsMapper.selectUserCountByUserTypeAndCreateTimeBetween(userType, beginTime, endTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getIpCount(Integer userType, LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
return apiAccessLogStatisticsMapper.selectIpCountByUserTypeAndCreateTimeBetween(userType, beginTime, endTime);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package cn.iocoder.yudao.module.statistics.service.member;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 会员信息的统计 Service 接口
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
public interface MemberStatisticsService {
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 获取会员统计(实时统计)
|
||||
*
|
||||
* @return 会员统计
|
||||
*/
|
||||
MemberSummaryRespVO getMemberSummary();
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 获取会员分析对照数据
|
||||
*
|
||||
* @param beginTime 起始时间
|
||||
* @param endTime 截止时间
|
||||
* @return 会员分析对照数据
|
||||
*/
|
||||
DataComparisonRespVO<MemberAnalyseDataRespVO> getMemberAnalyseComparisonData(LocalDateTime beginTime,
|
||||
LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 按照省份,获得会员统计列表
|
||||
*
|
||||
* @return 会员统计列表
|
||||
*/
|
||||
List<MemberAreaStatisticsRespVO> getMemberAreaStatisticsList();
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 按照性别,获得会员统计列表
|
||||
*
|
||||
* @return 会员统计列表
|
||||
*/
|
||||
List<MemberSexStatisticsRespVO> getMemberSexStatisticsList();
|
||||
|
||||
/**
|
||||
* 按照终端,获得会员统计列表
|
||||
*
|
||||
* @return 会员统计列表
|
||||
*/
|
||||
List<MemberTerminalStatisticsRespVO> getMemberTerminalStatisticsList();
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 获取用户注册数量列表
|
||||
*
|
||||
* @param beginTime 起始时间
|
||||
* @param endTime 截止时间
|
||||
* @return 注册数量列表
|
||||
*/
|
||||
List<MemberRegisterCountRespVO> getMemberRegisterCountList(LocalDateTime beginTime, LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 获得用户数量量统计对照
|
||||
*
|
||||
* @return 用户数量量统计对照
|
||||
*/
|
||||
DataComparisonRespVO<MemberCountRespVO> getUserCountComparison();
|
||||
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
package cn.iocoder.yudao.module.statistics.service.member;
|
||||
|
||||
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.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 javax.annotation.Resource;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
|
||||
/**
|
||||
* 会员信息的统计 Service 实现类
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class MemberStatisticsServiceImpl implements MemberStatisticsService {
|
||||
|
||||
@Resource
|
||||
private MemberStatisticsMapper memberStatisticsMapper;
|
||||
|
||||
@Resource
|
||||
private PayWalletStatisticsService payWalletStatisticsService;
|
||||
@Resource
|
||||
private TradeStatisticsService tradeStatisticsService;
|
||||
@Resource
|
||||
private TradeOrderStatisticsService tradeOrderStatisticsService;
|
||||
@Resource
|
||||
private ApiAccessLogStatisticsService apiAccessLogStatisticsService;
|
||||
|
||||
@Override
|
||||
public MemberSummaryRespVO getMemberSummary() {
|
||||
RechargeSummaryRespBO rechargeSummary = payWalletStatisticsService.getUserRechargeSummary(null, null);
|
||||
// TODO @疯狂:1)这里是实时统计,不好走走 TradeStatistics 表;2)因为这个放在商城下,所以只考虑订单数据,即按照 trade_order 的 pay_price 并且已支付来计算;
|
||||
Integer expensePrice = tradeStatisticsService.getExpensePrice(null, null);
|
||||
Integer userCount = memberStatisticsMapper.selectUserCount(null, null);
|
||||
return MemberStatisticsConvert.INSTANCE.convert(rechargeSummary, expensePrice, userCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MemberAreaStatisticsRespVO> getMemberAreaStatisticsList() {
|
||||
// 统计用户
|
||||
// TODO @疯狂:可能得把每个省的用户,都查询出来,然后去 order 那边 in;因为要按照这些人为基础来计算;;用户规模量大可能不太好,但是暂时就先这样搞吧 = =
|
||||
Map<Integer, Integer> userCountMap = convertMap(memberStatisticsMapper.selectSummaryListByAreaId(),
|
||||
vo -> AreaUtils.getParentIdByType(vo.getAreaId(), AreaTypeEnum.PROVINCE),
|
||||
MemberAreaStatisticsRespBO::getUserCount, Integer::sum);
|
||||
// 统计订单
|
||||
Map<Integer, MemberAreaStatisticsRespBO> orderMap = convertMap(tradeOrderStatisticsService.getSummaryListByAreaId(),
|
||||
bo -> AreaUtils.getParentIdByType(bo.getAreaId(), AreaTypeEnum.PROVINCE),
|
||||
bo -> bo,
|
||||
(a, b) -> new MemberAreaStatisticsRespBO()
|
||||
.setOrderCreateUserCount(a.getOrderCreateUserCount() + b.getOrderCreateUserCount())
|
||||
.setOrderPayUserCount(a.getOrderPayUserCount() + b.getOrderPayUserCount())
|
||||
.setOrderPayPrice(a.getOrderPayPrice() + b.getOrderPayPrice()));
|
||||
// 拼接数据
|
||||
List<Area> areaList = AreaUtils.getByType(AreaTypeEnum.PROVINCE, area -> area);
|
||||
areaList.add(new Area().setId(null).setName("未知"));
|
||||
return MemberStatisticsConvert.INSTANCE.convertList(areaList, userCountMap, orderMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataComparisonRespVO<MemberAnalyseDataRespVO> getMemberAnalyseComparisonData(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
// 当前数据
|
||||
MemberAnalyseDataRespVO vo = getMemberAnalyseData(beginTime, endTime);
|
||||
// 对照数据
|
||||
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 MemberAnalyseDataRespVO getMemberAnalyseData(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
Integer rechargeUserCount = Optional.ofNullable(payWalletStatisticsService.getUserRechargeSummary(beginTime, endTime))
|
||||
.map(RechargeSummaryRespBO::getRechargeUserCount).orElse(0);
|
||||
return new MemberAnalyseDataRespVO()
|
||||
.setRegisterUserCount(memberStatisticsMapper.selectUserCount(beginTime, endTime))
|
||||
.setVisitUserCount(apiAccessLogStatisticsService.getUserCount(UserTypeEnum.MEMBER.getValue(), beginTime, endTime))
|
||||
.setRechargeUserCount(rechargeUserCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MemberSexStatisticsRespVO> getMemberSexStatisticsList() {
|
||||
return memberStatisticsMapper.selectSummaryListBySex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MemberTerminalStatisticsRespVO> getMemberTerminalStatisticsList() {
|
||||
return memberStatisticsMapper.selectSummaryListByRegisterTerminal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MemberRegisterCountRespVO> getMemberRegisterCountList(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
return memberStatisticsMapper.selectListByCreateTimeBetween(beginTime, endTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataComparisonRespVO<MemberCountRespVO> 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<MemberCountRespVO>()
|
||||
.setValue(getUserCount(beginOfToday, endOfToday))
|
||||
.setReference(getUserCount(beginOfYesterday, endOfYesterday));
|
||||
}
|
||||
|
||||
private MemberCountRespVO getUserCount(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
return new MemberCountRespVO()
|
||||
.setRegisterUserCount(memberStatisticsMapper.selectUserCount(beginTime, endTime))
|
||||
.setVisitUserCount(apiAccessLogStatisticsService.getIpCount(UserTypeEnum.MEMBER.getValue(), beginTime, endTime));
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package cn.iocoder.yudao.module.statistics.service.pay;
|
||||
|
||||
import cn.iocoder.yudao.module.statistics.service.pay.bo.RechargeSummaryRespBO;
|
||||
import cn.iocoder.yudao.module.statistics.service.trade.bo.WalletSummaryRespBO;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 钱包的统计 Service 接口
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
public interface PayWalletStatisticsService {
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 获取钱包统计
|
||||
*
|
||||
* @param beginTime 起始时间
|
||||
* @param endTime 截止时间
|
||||
* @return 钱包统计
|
||||
*/
|
||||
WalletSummaryRespBO getWalletSummary(LocalDateTime beginTime, LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 获取钱包充值统计
|
||||
*
|
||||
* @param beginTime 起始时间
|
||||
* @param endTime 截止时间
|
||||
* @return 钱包充值统计
|
||||
*/
|
||||
RechargeSummaryRespBO getUserRechargeSummary(LocalDateTime beginTime, LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 获取充值金额合计
|
||||
*
|
||||
* @return 充值金额合计
|
||||
*/
|
||||
Integer getRechargePriceSummary();
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package cn.iocoder.yudao.module.statistics.service.pay;
|
||||
|
||||
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.statistics.dal.mysql.pay.PayWalletStatisticsMapper;
|
||||
import cn.iocoder.yudao.module.statistics.service.pay.bo.RechargeSummaryRespBO;
|
||||
import cn.iocoder.yudao.module.statistics.service.trade.bo.WalletSummaryRespBO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 钱包的统计 Service 实现类
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class PayWalletStatisticsServiceImpl implements PayWalletStatisticsService {
|
||||
|
||||
@Resource
|
||||
private PayWalletStatisticsMapper payWalletStatisticsMapper;
|
||||
|
||||
@Override
|
||||
public WalletSummaryRespBO getWalletSummary(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
WalletSummaryRespBO paySummary = payWalletStatisticsMapper.selectRechargeSummaryByPayTimeBetween(
|
||||
beginTime, endTime, true);
|
||||
WalletSummaryRespBO refundSummary = payWalletStatisticsMapper.selectRechargeSummaryByRefundTimeBetween(
|
||||
beginTime, endTime, PayRefundStatusEnum.SUCCESS.getStatus());
|
||||
Integer walletPayPrice = payWalletStatisticsMapper.selectPriceSummaryByBizTypeAndCreateTimeBetween(
|
||||
beginTime, endTime, PayWalletBizTypeEnum.PAYMENT.getType());
|
||||
// 拼接
|
||||
paySummary.setWalletPayPrice(walletPayPrice)
|
||||
.setRechargeRefundCount(refundSummary.getRechargeRefundCount())
|
||||
.setRechargeRefundPrice(refundSummary.getRechargeRefundPrice());
|
||||
return paySummary;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RechargeSummaryRespBO getUserRechargeSummary(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
return payWalletStatisticsMapper.selectRechargeSummaryGroupByWalletId(beginTime, endTime, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getRechargePriceSummary() {
|
||||
return payWalletStatisticsMapper.selectRechargePriceSummary(PayOrderStatusEnum.SUCCESS.getStatus());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package cn.iocoder.yudao.module.statistics.service.pay.bo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 充值统计 Response BO
|
||||
*/
|
||||
@Data
|
||||
public class RechargeSummaryRespBO {
|
||||
|
||||
/**
|
||||
* 充值会员数量
|
||||
*/
|
||||
private Integer rechargeUserCount;
|
||||
|
||||
/**
|
||||
* 充值金额
|
||||
*/
|
||||
private Integer rechargePrice;
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
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;
|
||||
|
||||
/**
|
||||
* 售后统计 Service 接口
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
public interface AfterSaleStatisticsService {
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 获取售后单统计
|
||||
*
|
||||
* @param beginTime 起始时间
|
||||
* @param endTime 截止时间
|
||||
* @return 售后统计结果
|
||||
*/
|
||||
AfterSaleSummaryRespBO getAfterSaleSummary(LocalDateTime beginTime, LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 获取指定状态的售后订单数量
|
||||
*
|
||||
* @param status 售后状态
|
||||
* @return 售后订单数量
|
||||
*/
|
||||
Long getCountByStatus(AfterSaleStatusEnum status);
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
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;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 售后统计 Service 实现类
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class AfterSaleStatisticsServiceImpl implements AfterSaleStatisticsService {
|
||||
|
||||
@Resource
|
||||
private AfterSaleStatisticsMapper afterSaleStatisticsMapper;
|
||||
|
||||
@Override
|
||||
public AfterSaleSummaryRespBO getAfterSaleSummary(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
return afterSaleStatisticsMapper.selectSummaryByRefundTimeBetween(beginTime, endTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getCountByStatus(AfterSaleStatusEnum status) {
|
||||
return afterSaleStatisticsMapper.selectCountByStatus(status.getStatus());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package cn.iocoder.yudao.module.statistics.service.trade;
|
||||
|
||||
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 分销统计 Service 接口
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
public interface BrokerageStatisticsService {
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 获取已结算的佣金金额
|
||||
*
|
||||
* @param beginTime 起始时间
|
||||
* @param endTime 截止时间
|
||||
* @return 已结算的佣金金额
|
||||
*/
|
||||
Integer getBrokerageSettlementPriceSummary(LocalDateTime beginTime, LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 获取指定状态的提现记录数量
|
||||
*
|
||||
* @param status 提现记录状态
|
||||
* @return 提现记录数量
|
||||
*/
|
||||
Long getWithdrawCountByStatus(BrokerageWithdrawStatusEnum status);
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
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;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 分销统计 Service 实现类
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class BrokerageStatisticsServiceImpl implements BrokerageStatisticsService {
|
||||
|
||||
@Resource
|
||||
private BrokerageStatisticsMapper brokerageStatisticsMapper;
|
||||
|
||||
@Override
|
||||
public Integer getBrokerageSettlementPriceSummary(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
return brokerageStatisticsMapper.selectSummaryPriceByStatusAndUnfreezeTimeBetween(
|
||||
BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus(),
|
||||
beginTime, endTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getWithdrawCountByStatus(BrokerageWithdrawStatusEnum status) {
|
||||
return brokerageStatisticsMapper.selectWithdrawCountByStatus(status.getStatus());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
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.trade.vo.*;
|
||||
import cn.iocoder.yudao.module.statistics.service.member.bo.MemberAreaStatisticsRespBO;
|
||||
import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeOrderSummaryRespBO;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 交易订单的统计 Service 接口
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
public interface TradeOrderStatisticsService {
|
||||
|
||||
/**
|
||||
* 获取订单统计
|
||||
*
|
||||
* @param beginTime 起始时间
|
||||
* @param endTime 截止时间
|
||||
* @return 订单统计结果
|
||||
*/
|
||||
TradeOrderSummaryRespBO getOrderSummary(LocalDateTime beginTime, LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 获取地区订单统计
|
||||
*
|
||||
* @return 订单统计结果
|
||||
*/
|
||||
List<MemberAreaStatisticsRespBO> getSummaryListByAreaId();
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 获取下单用户数量
|
||||
*
|
||||
* @param beginTime 起始时间
|
||||
* @param endTime 截止时间
|
||||
* @return 下单用户数量
|
||||
*/
|
||||
Integer getOrderUserCount(LocalDateTime beginTime, LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 获取支付用户数量
|
||||
*
|
||||
* @param beginTime 起始时间
|
||||
* @param endTime 截止时间
|
||||
* @return 支付用户数量
|
||||
*/
|
||||
Integer getPayUserCount(LocalDateTime beginTime, LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 获取支付金额
|
||||
*
|
||||
* @param beginTime 起始时间
|
||||
* @param endTime 截止时间
|
||||
* @return 支付用户金额
|
||||
*/
|
||||
Integer getOrderPayPrice(LocalDateTime beginTime, LocalDateTime endTime);
|
||||
|
||||
/**
|
||||
* 根据订单状态、物流类型,获得交易订单数量
|
||||
*
|
||||
* @return 订单数量
|
||||
*/
|
||||
Long getCountByStatusAndDeliveryType(Integer status, Integer deliveryType);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 交易订单销售额对照
|
||||
*
|
||||
* @return 销售额对照
|
||||
*/
|
||||
DataComparisonRespVO<TradeOrderSummaryRespVO> getOrderComparison();
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 获得订单量趋势统计
|
||||
*
|
||||
* @param reqVO 统计参数
|
||||
* @return 订单量趋势统计
|
||||
*/
|
||||
List<DataComparisonRespVO<TradeOrderTrendRespVO>> getOrderCountTrendComparison(TradeOrderTrendReqVO reqVO);
|
||||
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package cn.iocoder.yudao.module.statistics.service.trade;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
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.trade.vo.TradeOrderSummaryRespVO;
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeOrderTrendReqVO;
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeOrderTrendRespVO;
|
||||
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.member.bo.MemberAreaStatisticsRespBO;
|
||||
import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeOrderSummaryRespBO;
|
||||
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 实现类
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class TradeOrderStatisticsServiceImpl implements TradeOrderStatisticsService {
|
||||
|
||||
@Resource
|
||||
private TradeOrderStatisticsMapper tradeOrderStatisticsMapper;
|
||||
|
||||
@Override
|
||||
public TradeOrderSummaryRespBO getOrderSummary(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
return new TradeOrderSummaryRespBO()
|
||||
.setOrderCreateCount(tradeOrderStatisticsMapper.selectCountByCreateTimeBetween(beginTime, endTime))
|
||||
.setOrderPayCount(tradeOrderStatisticsMapper.selectCountByPayTimeBetween(beginTime, endTime))
|
||||
.setOrderPayPrice(tradeOrderStatisticsMapper.selectSummaryPriceByPayTimeBetween(beginTime, endTime));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MemberAreaStatisticsRespBO> getSummaryListByAreaId() {
|
||||
return tradeOrderStatisticsMapper.selectSummaryListByAreaId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getOrderUserCount(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
return tradeOrderStatisticsMapper.selectUserCountByCreateTimeBetween(beginTime, endTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPayUserCount(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
return tradeOrderStatisticsMapper.selectUserCountByPayTimeBetween(beginTime, endTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getOrderPayPrice(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
return tradeOrderStatisticsMapper.selectSummaryPriceByPayTimeBetween(beginTime, endTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getCountByStatusAndDeliveryType(Integer status, Integer deliveryType) {
|
||||
return tradeOrderStatisticsMapper.selectCountByStatusAndDeliveryType(status, deliveryType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataComparisonRespVO<TradeOrderSummaryRespVO> getOrderComparison() {
|
||||
return new DataComparisonRespVO<TradeOrderSummaryRespVO>()
|
||||
.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<DataComparisonRespVO<TradeOrderTrendRespVO>> getOrderCountTrendComparison(TradeOrderTrendReqVO reqVO) {
|
||||
// 查询当前数据
|
||||
List<TradeOrderTrendRespVO> 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<TradeOrderTrendRespVO> reference = getOrderCountTrend(reqVO.getType(), referenceBeginTime, referenceEndTime);
|
||||
// 顺序对比返回
|
||||
return IntStream.range(0, value.size())
|
||||
.mapToObj(index -> new DataComparisonRespVO<TradeOrderTrendRespVO>()
|
||||
.setValue(CollUtil.get(value, index))
|
||||
.setReference(CollUtil.get(reference, index)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<TradeOrderTrendRespVO> getOrderCountTrend(Integer timeRangeType, LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
// 情况一:按年统计时,以月份分组
|
||||
if (TimeRangeTypeEnum.YEAR.getType().equals(timeRangeType)) {
|
||||
return tradeOrderStatisticsMapper.selectListByPayTimeBetweenAndGroupByMonth(beginTime, endTime);
|
||||
}
|
||||
// 情况二:其它以天分组(天、周、月)
|
||||
return tradeOrderStatisticsMapper.selectListByPayTimeBetweenAndGroupByDay(beginTime, endTime);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
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.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;
|
||||
|
||||
/**
|
||||
* 交易统计 Service 接口
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
public interface TradeStatisticsService {
|
||||
|
||||
/**
|
||||
* 获得交易状况统计对照
|
||||
*
|
||||
* @return 统计数据对照
|
||||
*/
|
||||
DataComparisonRespVO<TradeTrendSummaryRespVO> getTradeTrendSummaryComparison(
|
||||
LocalDateTime beginTime, LocalDateTime endTime);
|
||||
|
||||
/**
|
||||
* 获得交易状况统计
|
||||
*
|
||||
* @param beginTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return 统计数据对照
|
||||
*/
|
||||
Integer getExpensePrice(LocalDateTime beginTime, LocalDateTime endTime);
|
||||
|
||||
/**
|
||||
* 获得交易状况明细
|
||||
*
|
||||
* @param beginTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return 统计数据列表
|
||||
*/
|
||||
List<TradeStatisticsDO> getTradeStatisticsList(LocalDateTime beginTime, LocalDateTime endTime);
|
||||
|
||||
// TODO 芋艿:已经 review;
|
||||
/**
|
||||
* 统计指定天数的交易数据
|
||||
*
|
||||
* @return 统计结果
|
||||
*/
|
||||
String statisticsTrade(Integer days);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 统计指定日期的交易数据
|
||||
*
|
||||
* @param days 增加的天数
|
||||
* @return 交易数据
|
||||
*/
|
||||
TradeSummaryRespBO getTradeSummaryByDays(int days);
|
||||
|
||||
// TODO 芋艿:已经 review
|
||||
/**
|
||||
* 统计指定月份的交易数据
|
||||
*
|
||||
* @param months 增加的月数
|
||||
* @return 交易数据
|
||||
*/
|
||||
TradeSummaryRespBO getTradeSummaryByMonths(int months);
|
||||
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
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.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.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;
|
||||
|
||||
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 实现类
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class TradeStatisticsServiceImpl implements TradeStatisticsService {
|
||||
|
||||
@Resource
|
||||
private TradeStatisticsMapper tradeStatisticsMapper;
|
||||
|
||||
@Resource
|
||||
private TradeOrderStatisticsService tradeOrderStatisticsService;
|
||||
@Resource
|
||||
private AfterSaleStatisticsService afterSaleStatisticsService;
|
||||
@Resource
|
||||
private BrokerageStatisticsService brokerageStatisticsService;
|
||||
@Resource
|
||||
private PayWalletStatisticsService payWalletStatisticsService;
|
||||
|
||||
@Override
|
||||
public TradeSummaryRespBO getTradeSummaryByDays(int days) {
|
||||
LocalDateTime date = LocalDateTime.now().plusDays(days);
|
||||
return tradeStatisticsMapper.selectOrderCreateCountSumAndOrderPayPriceSumByTimeBetween(
|
||||
LocalDateTimeUtil.beginOfDay(date), LocalDateTimeUtil.endOfDay(date));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TradeSummaryRespBO getTradeSummaryByMonths(int months) {
|
||||
LocalDateTime monthDate = LocalDateTime.now().plusMonths(months);
|
||||
return tradeStatisticsMapper.selectOrderCreateCountSumAndOrderPayPriceSumByTimeBetween(
|
||||
LocalDateTimeUtils.beginOfMonth(monthDate), LocalDateTimeUtils.endOfMonth(monthDate));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataComparisonRespVO<TradeTrendSummaryRespVO> getTradeTrendSummaryComparison(LocalDateTime beginTime,
|
||||
LocalDateTime endTime) {
|
||||
// 统计数据
|
||||
TradeTrendSummaryRespVO value = tradeStatisticsMapper.selectVoByTimeBetween(beginTime, endTime);
|
||||
// 对照数据
|
||||
LocalDateTime referenceBeginTime = beginTime.minus(Duration.between(beginTime, endTime));
|
||||
TradeTrendSummaryRespVO reference = tradeStatisticsMapper.selectVoByTimeBetween(referenceBeginTime, beginTime);
|
||||
return TradeStatisticsConvert.INSTANCE.convert(value, reference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getExpensePrice(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
return tradeStatisticsMapper.selectExpensePriceByTimeBetween(beginTime, endTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TradeStatisticsDO> getTradeStatisticsList(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
return tradeStatisticsMapper.selectListByTimeBetween(beginTime, endTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String statisticsTrade(Integer days) {
|
||||
LocalDateTime today = LocalDateTime.now();
|
||||
return IntStream.rangeClosed(1, days)
|
||||
.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();
|
||||
// 3.2 统计售后
|
||||
stopWatch.start("统计售后");
|
||||
AfterSaleSummaryRespBO afterSaleSummary = afterSaleStatisticsService.getAfterSaleSummary(beginTime, endTime);
|
||||
stopWatch.stop();
|
||||
// 3.3 统计佣金
|
||||
stopWatch.start("统计佣金");
|
||||
Integer brokerageSettlementPrice = brokerageStatisticsService.getBrokerageSettlementPriceSummary(beginTime, endTime);
|
||||
stopWatch.stop();
|
||||
// 3.4 统计充值
|
||||
stopWatch.start("统计充值");
|
||||
WalletSummaryRespBO walletSummary = payWalletStatisticsService.getWalletSummary(beginTime, endTime);
|
||||
stopWatch.stop();
|
||||
|
||||
// 4. 插入数据
|
||||
entity = TradeStatisticsConvert.INSTANCE.convert(date, orderSummary, afterSaleSummary, brokerageSettlementPrice,
|
||||
walletSummary);
|
||||
tradeStatisticsMapper.insert(entity);
|
||||
return stopWatch.prettyPrint();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package cn.iocoder.yudao.module.statistics.service.trade.bo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 售后统计 Response DTO
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Data
|
||||
public class AfterSaleSummaryRespBO {
|
||||
|
||||
/**
|
||||
* 退款订单数
|
||||
*/
|
||||
private Integer afterSaleCount;
|
||||
/**
|
||||
* 总退款金额,单位:分
|
||||
*/
|
||||
private Integer afterSaleRefundPrice;
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package cn.iocoder.yudao.module.statistics.service.trade.bo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 会员地区统计 Response BO
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Data
|
||||
public class MemberAreaStatisticsRespBO {
|
||||
|
||||
/**
|
||||
* 省份编号
|
||||
*/
|
||||
private Integer areaId;
|
||||
/**
|
||||
* 省份名称
|
||||
*/
|
||||
private String areaName;
|
||||
|
||||
/**
|
||||
* 会员数量
|
||||
*/
|
||||
private Integer userCount;
|
||||
|
||||
/**
|
||||
* 下单的会员数量
|
||||
*/
|
||||
private Integer orderCreateUserCount;
|
||||
/**
|
||||
* 支付订单的会员数量
|
||||
*/
|
||||
private Integer orderPayUserCount;
|
||||
|
||||
/**
|
||||
* 订单支付金额,单位:分
|
||||
*/
|
||||
private Integer orderPayPrice;
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package cn.iocoder.yudao.module.statistics.service.trade.bo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 订单统计 Response BO
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Data
|
||||
public class TradeOrderSummaryRespBO {
|
||||
|
||||
/**
|
||||
* 创建订单数
|
||||
*/
|
||||
private Integer orderCreateCount;
|
||||
/**
|
||||
* 支付订单商品数
|
||||
*/
|
||||
private Integer orderPayCount;
|
||||
/**
|
||||
* 总支付金额,单位:分
|
||||
*/
|
||||
private Integer orderPayPrice;
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package cn.iocoder.yudao.module.statistics.service.trade.bo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 交易统计 Resp BO
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Data
|
||||
public class TradeSummaryRespBO {
|
||||
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
private Integer count;
|
||||
|
||||
/**
|
||||
* 合计
|
||||
*/
|
||||
private Integer summary;
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package cn.iocoder.yudao.module.statistics.service.trade.bo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 钱包统计 Response DTO
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Data
|
||||
public class WalletSummaryRespBO {
|
||||
|
||||
/**
|
||||
* 总支付金额(余额),单位:分
|
||||
*/
|
||||
private Integer walletPayPrice;
|
||||
|
||||
/**
|
||||
* 充值订单数
|
||||
*/
|
||||
private Integer rechargePayCount;
|
||||
/**
|
||||
* 充值金额,单位:分
|
||||
*/
|
||||
private Integer rechargePayPrice;
|
||||
/**
|
||||
* 充值退款订单数
|
||||
*/
|
||||
private Integer rechargeRefundCount;
|
||||
/**
|
||||
* 充值退款金额,单位:分
|
||||
*/
|
||||
private Integer rechargeRefundPrice;
|
||||
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
--- #################### 数据库相关配置 ####################
|
||||
spring:
|
||||
# 数据源配置项
|
||||
autoconfigure:
|
||||
exclude:
|
||||
- com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
|
||||
datasource:
|
||||
druid: # Druid 【监控】相关的全局配置
|
||||
web-stat-filter:
|
||||
enabled: true
|
||||
stat-view-servlet:
|
||||
enabled: true
|
||||
allow: # 设置白名单,不填则允许所有访问
|
||||
url-pattern: /druid/*
|
||||
login-username: # 控制台管理用户名和密码
|
||||
login-password:
|
||||
filter:
|
||||
stat:
|
||||
enabled: true
|
||||
log-slow-sql: true # 慢 SQL 记录
|
||||
slow-sql-millis: 100
|
||||
merge-sql: true
|
||||
wall:
|
||||
config:
|
||||
multi-statement-allow: true
|
||||
dynamic: # 多数据源配置
|
||||
druid: # Druid 【连接池】相关的全局配置
|
||||
initial-size: 5 # 初始连接数
|
||||
min-idle: 10 # 最小连接池数量
|
||||
max-active: 20 # 最大连接池数量
|
||||
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒
|
||||
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
|
||||
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒
|
||||
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒
|
||||
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
|
||||
test-while-idle: true
|
||||
test-on-borrow: false
|
||||
test-on-return: false
|
||||
primary: master
|
||||
datasource:
|
||||
master:
|
||||
name: ruoyi-vue-pro
|
||||
url: jdbc:mysql://400-infra.server.iocoder.cn:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT&nullCatalogMeansCurrent=true
|
||||
driver-class-name: com.mysql.jdbc.Driver
|
||||
username: root
|
||||
password: 3WLiVUBEwTbvAfsh
|
||||
slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改
|
||||
name: ruoyi-vue-pro
|
||||
url: jdbc:mysql://400-infra.server.iocoder.cn:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT&nullCatalogMeansCurrent=true
|
||||
driver-class-name: com.mysql.jdbc.Driver
|
||||
username: root
|
||||
password: 3WLiVUBEwTbvAfsh
|
||||
|
||||
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
|
||||
redis:
|
||||
host: 400-infra.server.iocoder.cn # 地址
|
||||
port: 6379 # 端口
|
||||
database: 1 # 数据库索引
|
||||
# password: 123456 # 密码,建议生产环境开启
|
||||
|
||||
--- #################### MQ 消息队列相关配置 ####################
|
||||
spring:
|
||||
cloud:
|
||||
stream:
|
||||
rocketmq:
|
||||
# RocketMQ Binder 配置项,对应 RocketMQBinderConfigurationProperties 类
|
||||
binder:
|
||||
name-server: 127.0.0.1:9876 # RocketMQ Namesrv 地址
|
||||
|
||||
--- #################### 定时任务相关配置 ####################
|
||||
xxl:
|
||||
job:
|
||||
admin:
|
||||
addresses: http://127.0.0.1:9090/xxl-job-admin # 调度中心部署跟地址
|
||||
|
||||
--- #################### 服务保障相关配置 ####################
|
||||
|
||||
# Lock4j 配置项
|
||||
lock4j:
|
||||
acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒
|
||||
expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒
|
||||
|
||||
--- #################### 监控相关配置 ####################
|
||||
|
||||
# Actuator 监控端点的配置项
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator
|
||||
exposure:
|
||||
include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
|
||||
|
||||
# Spring Boot Admin 配置项
|
||||
spring:
|
||||
boot:
|
||||
admin:
|
||||
# Spring Boot Admin Client 客户端的相关配置
|
||||
client:
|
||||
instance:
|
||||
service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME]
|
||||
# Spring Boot Admin Server 服务端的相关配置
|
||||
context-path: /admin # 配置 Spring
|
||||
|
||||
--- #################### 芋道相关配置 ####################
|
||||
|
||||
# 芋道配置项,设置当前项目所有自定义的配置
|
||||
yudao:
|
||||
xss:
|
||||
enable: false
|
||||
web:
|
||||
admin-ui:
|
||||
url: http://dashboard.yudao.iocoder.cn # Admin 管理后台 UI 的地址
|
||||
demo: true # 开启演示模式
|
|
@ -0,0 +1,141 @@
|
|||
--- #################### 数据库相关配置 ####################
|
||||
spring:
|
||||
# 数据源配置项
|
||||
autoconfigure:
|
||||
exclude:
|
||||
- com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
|
||||
- de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置
|
||||
datasource:
|
||||
druid: # Druid 【监控】相关的全局配置
|
||||
web-stat-filter:
|
||||
enabled: true
|
||||
stat-view-servlet:
|
||||
enabled: true
|
||||
allow: # 设置白名单,不填则允许所有访问
|
||||
url-pattern: /druid/*
|
||||
login-username: # 控制台管理用户名和密码
|
||||
login-password:
|
||||
filter:
|
||||
stat:
|
||||
enabled: true
|
||||
log-slow-sql: true # 慢 SQL 记录
|
||||
slow-sql-millis: 100
|
||||
merge-sql: true
|
||||
wall:
|
||||
config:
|
||||
multi-statement-allow: true
|
||||
dynamic: # 多数据源配置
|
||||
druid: # Druid 【连接池】相关的全局配置
|
||||
initial-size: 1 # 初始连接数
|
||||
min-idle: 1 # 最小连接池数量
|
||||
max-active: 20 # 最大连接池数量
|
||||
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒
|
||||
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
|
||||
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒
|
||||
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒
|
||||
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
|
||||
test-while-idle: true
|
||||
test-on-borrow: false
|
||||
test-on-return: false
|
||||
primary: master
|
||||
datasource:
|
||||
master:
|
||||
name: ruoyi-vue-pro
|
||||
url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
|
||||
# url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例
|
||||
# url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.master.name} # PostgreSQL 连接的示例
|
||||
# url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例
|
||||
# url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.master.name} # SQLServer 连接的示例
|
||||
username: root
|
||||
password: 123456
|
||||
# username: sa
|
||||
# password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W
|
||||
slave: # 模拟从库,可根据自己需要修改
|
||||
name: ruoyi-vue-pro
|
||||
url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
|
||||
# url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例
|
||||
# url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例
|
||||
# url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例
|
||||
# url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.slave.name} # SQLServer 连接的示例
|
||||
username: root
|
||||
password: 123456
|
||||
# username: sa
|
||||
# password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W
|
||||
|
||||
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
|
||||
redis:
|
||||
host: 127.0.0.1 # 地址
|
||||
port: 6379 # 端口
|
||||
database: 0 # 数据库索引
|
||||
# password: 123456 # 密码,建议生产环境开启
|
||||
|
||||
--- #################### MQ 消息队列相关配置 ####################
|
||||
spring:
|
||||
cloud:
|
||||
stream:
|
||||
rocketmq:
|
||||
# RocketMQ Binder 配置项,对应 RocketMQBinderConfigurationProperties 类
|
||||
binder:
|
||||
name-server: 127.0.0.1:9876 # RocketMQ Namesrv 地址
|
||||
binding-retry-interval: 7200 # 消息绑定重试间隔时间,单位:秒,默认为 30 秒。考虑到本地可能不启动 RocketMQ 服务,设置为 2 小时
|
||||
|
||||
--- #################### 定时任务相关配置 ####################
|
||||
|
||||
xxl:
|
||||
job:
|
||||
enabled: false # 是否开启调度中心,默认为 true 开启
|
||||
admin:
|
||||
addresses: http://127.0.0.1:9090/xxl-job-admin # 调度中心部署跟地址
|
||||
|
||||
--- #################### 服务保障相关配置 ####################
|
||||
|
||||
# Lock4j 配置项
|
||||
lock4j:
|
||||
acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒
|
||||
expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒
|
||||
|
||||
--- #################### 监控相关配置 ####################
|
||||
|
||||
# Actuator 监控端点的配置项
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator
|
||||
exposure:
|
||||
include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
|
||||
|
||||
# Spring Boot Admin 配置项
|
||||
spring:
|
||||
boot:
|
||||
admin:
|
||||
# Spring Boot Admin Client 客户端的相关配置
|
||||
client:
|
||||
instance:
|
||||
service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME]
|
||||
|
||||
# 日志文件配置
|
||||
logging:
|
||||
level:
|
||||
# 配置自己写的 MyBatis Mapper 打印日志
|
||||
cn.iocoder.yudao.module.system.dal.mysql: debug
|
||||
cn.iocoder.yudao.module.system.dal.mysql.sensitiveword.SensitiveWordMapper: INFO # 配置 SensitiveWordMapper 的日志级别为 info
|
||||
cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper: INFO # 配置 SmsChannelMapper 的日志级别为 info
|
||||
|
||||
--- #################### 芋道相关配置 ####################
|
||||
|
||||
# 芋道配置项,设置当前项目所有自定义的配置
|
||||
yudao:
|
||||
env: # 多环境的配置项
|
||||
tag: ${HOSTNAME}
|
||||
web:
|
||||
admin-ui:
|
||||
url: http://dashboard.yudao.iocoder.cn # Admin 管理后台 UI 的地址
|
||||
security:
|
||||
mock-enable: true
|
||||
xss:
|
||||
enable: false
|
||||
access-log: # 访问日志的配置项
|
||||
enable: false
|
||||
error-code: # 错误码相关配置项
|
||||
enable: false
|
||||
demo: false # 关闭演示模式
|
|
@ -0,0 +1,134 @@
|
|||
spring:
|
||||
main:
|
||||
allow-circular-references: true # 允许循环依赖,因为项目是三层架构,无法避免这个情况。
|
||||
allow-bean-definition-overriding: true # 允许 Bean 覆盖,例如说 Feign 等会存在重复定义的服务
|
||||
|
||||
# Servlet 配置
|
||||
servlet:
|
||||
# 文件上传相关配置项
|
||||
multipart:
|
||||
max-file-size: 16MB # 单个文件大小
|
||||
max-request-size: 32MB # 设置总上传的文件大小
|
||||
mvc:
|
||||
pathmatch:
|
||||
matching-strategy: ANT_PATH_MATCHER # 解决 SpringFox 与 SpringBoot 2.6.x 不兼容的问题,参见 SpringFoxHandlerProviderBeanPostProcessor 类
|
||||
|
||||
# Jackson 配置项
|
||||
jackson:
|
||||
serialization:
|
||||
write-dates-as-timestamps: true # 设置 LocalDateTime 的格式,使用时间戳
|
||||
write-date-timestamps-as-nanoseconds: false # 设置不使用 nanoseconds 的格式。例如说 1611460870.401,而是直接 1611460870401
|
||||
write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳
|
||||
fail-on-empty-beans: false # 允许序列化无属性的 Bean
|
||||
|
||||
# Cache 配置项
|
||||
cache:
|
||||
type: REDIS
|
||||
redis:
|
||||
time-to-live: 1h # 设置过期时间为 1 小时
|
||||
|
||||
--- #################### 接口文档配置 ####################
|
||||
|
||||
springdoc:
|
||||
api-docs:
|
||||
enabled: true # 1. 是否开启 Swagger 接文档的元数据
|
||||
path: /v3/api-docs
|
||||
swagger-ui:
|
||||
enabled: true # 2.1 是否开启 Swagger 文档的官方 UI 界面
|
||||
path: /swagger-ui.html
|
||||
default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档
|
||||
|
||||
knife4j:
|
||||
enable: true # 2.2 是否开启 Swagger 文档的 Knife4j UI 界面
|
||||
setting:
|
||||
language: zh_cn
|
||||
|
||||
# MyBatis Plus 的配置项
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
|
||||
global-config:
|
||||
db-config:
|
||||
id-type: NONE # “智能”模式,基于 IdTypeEnvironmentPostProcessor + 数据源的类型,自动适配成 AUTO、INPUT 模式。
|
||||
# id-type: AUTO # 自增 ID,适合 MySQL 等直接自增的数据库
|
||||
# id-type: INPUT # 用户输入 ID,适合 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库
|
||||
# id-type: ASSIGN_ID # 分配 ID,默认使用雪花算法。注意,Oracle、PostgreSQL、Kingbase、DB2、H2 数据库时,需要去除实体类上的 @KeySequence 注解
|
||||
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
|
||||
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
|
||||
banner: false # 关闭控制台的 Banner 打印
|
||||
type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject
|
||||
encryptor:
|
||||
password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成
|
||||
|
||||
mybatis-plus-join:
|
||||
banner: false # 关闭控制台的 Banner 打印
|
||||
|
||||
# Spring Data Redis 配置
|
||||
spring:
|
||||
data:
|
||||
redis:
|
||||
repositories:
|
||||
enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度
|
||||
|
||||
--- #################### RPC 远程调用相关配置 ####################
|
||||
|
||||
--- #################### MQ 消息队列相关配置 ####################
|
||||
|
||||
spring:
|
||||
cloud:
|
||||
# Spring Cloud Stream 配置项,对应 BindingServiceProperties 类
|
||||
stream:
|
||||
function:
|
||||
definition: busConsumer;
|
||||
# Binding 配置项,对应 BindingProperties Map
|
||||
# Spring Cloud Stream RocketMQ 配置项
|
||||
rocketmq:
|
||||
# RocketMQ Binder 配置项,对应 RocketMQBinderConfigurationProperties 类
|
||||
binder:
|
||||
name-server: 127.0.0.1:9876 # RocketMQ Namesrv 地址
|
||||
default: # 默认 bindings 全局配置
|
||||
producer: # RocketMQ Producer 配置项,对应 RocketMQProducerProperties 类
|
||||
group: statistics_producer_group # 生产者分组
|
||||
send-type: SYNC # 发送模式,SYNC 同步
|
||||
bindings:
|
||||
springCloudBusInput:
|
||||
consumer:
|
||||
message-model: BROADCASTING # 重要,解决 Spring Cloud Bus RocketMQ 默认不是 BROADCASTING 广播消费的问题
|
||||
|
||||
# Spring Cloud Bus 配置项,对应 BusProperties 类
|
||||
bus:
|
||||
enabled: true # 是否开启,默认为 true
|
||||
id: ${spring.application.name}:${server.port} # 编号,Spring Cloud Alibaba 建议使用“应用:端口”的格式
|
||||
destination: springCloudBus # 目标消息队列,默认为 springCloudBus
|
||||
|
||||
--- #################### 定时任务相关配置 ####################
|
||||
|
||||
xxl:
|
||||
job:
|
||||
executor:
|
||||
appname: ${spring.application.name} # 执行器 AppName
|
||||
logpath: ${user.home}/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径
|
||||
accessToken: default_token # 执行器通讯TOKEN
|
||||
|
||||
--- #################### 芋道相关配置 ####################
|
||||
|
||||
yudao:
|
||||
info:
|
||||
version: 1.0.0
|
||||
base-package: cn.iocoder.yudao.module.statistics
|
||||
swagger:
|
||||
title: 管理后台
|
||||
description: 提供管理员管理的所有功能
|
||||
version: ${yudao.info.version}
|
||||
base-package: ${yudao.info.base-package}
|
||||
captcha:
|
||||
enable: true # 验证码的开关,默认为 true;
|
||||
error-code: # 错误码相关配置项
|
||||
constants-class-list:
|
||||
- cn.iocoder.yudao.module.statistics.enums.ErrorCodeConstants
|
||||
tenant: # 多租户相关配置项
|
||||
enable: true
|
||||
ignore-urls:
|
||||
ignore-tables:
|
||||
|
||||
debug: false
|
|
@ -0,0 +1,23 @@
|
|||
--- #################### 注册中心相关配置 ####################
|
||||
|
||||
spring:
|
||||
cloud:
|
||||
nacos:
|
||||
server-addr: 127.0.0.1:8848
|
||||
discovery:
|
||||
namespace: dev # 命名空间。这里使用 dev 开发环境
|
||||
metadata:
|
||||
version: 1.0.0 # 服务实例的版本号,可用于灰度发布
|
||||
|
||||
--- #################### 配置中心相关配置 ####################
|
||||
|
||||
spring:
|
||||
cloud:
|
||||
nacos:
|
||||
# Nacos Config 配置项,对应 NacosConfigProperties 配置属性类
|
||||
config:
|
||||
server-addr: 127.0.0.1:8848 # Nacos 服务器地址
|
||||
namespace: dev # 命名空间 dev 的ID,不能直接使用 dev 名称。创建命名空间的时候需要指定ID为 dev,这里使用 dev 开发环境
|
||||
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
||||
name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId,默认为 spring.application.name
|
||||
file-extension: yaml # 使用的 Nacos 配置集的 dataId 的文件拓展名,同时也是 Nacos 配置集的配置格式,默认为 properties
|
|
@ -0,0 +1,14 @@
|
|||
spring:
|
||||
application:
|
||||
name: statistics-server
|
||||
|
||||
profiles:
|
||||
active: local
|
||||
|
||||
server:
|
||||
port: 48103
|
||||
|
||||
# 日志文件配置。注意,如果 logging.file.name 不放在 bootstrap.yaml 配置文件,而是放在 application.yaml 中,会导致出现 LOG_FILE_IS_UNDEFINED 文件
|
||||
logging:
|
||||
file:
|
||||
name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径
|
|
@ -0,0 +1,76 @@
|
|||
<configuration>
|
||||
<!-- 引用 Spring Boot 的 logback 基础配置 -->
|
||||
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
|
||||
<!-- 变量 yudao.info.base-package,基础业务包 -->
|
||||
<springProperty scope="context" name="yudao.info.base-package" source="yudao.info.base-package"/>
|
||||
<!-- 格式化输出:%d 表示日期,%X{tid} SkWalking 链路追踪编号,%thread 表示线程名,%-5level:级别从左显示 5 个字符宽度,%msg:日志消息,%n是换行符 -->
|
||||
<property name="PATTERN_DEFAULT" value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} | %highlight(${LOG_LEVEL_PATTERN:-%5p} ${PID:- }) | %boldYellow(%thread [%tid]) %boldGreen(%-40.40logger{39}) | %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
|
||||
|
||||
<!-- 控制台 Appender -->
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
|
||||
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
|
||||
<pattern>${PATTERN_DEFAULT}</pattern>
|
||||
</layout>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 文件 Appender -->
|
||||
<!-- 参考 Spring Boot 的 file-appender.xml 编写 -->
|
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
|
||||
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
|
||||
<pattern>${PATTERN_DEFAULT}</pattern>
|
||||
</layout>
|
||||
</encoder>
|
||||
<!-- 日志文件名 -->
|
||||
<file>${LOG_FILE}</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<!-- 滚动后的日志文件名 -->
|
||||
<fileNamePattern>${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}</fileNamePattern>
|
||||
<!-- 启动服务时,是否清理历史日志,一般不建议清理 -->
|
||||
<cleanHistoryOnStart>${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false}</cleanHistoryOnStart>
|
||||
<!-- 日志文件,到达多少容量,进行滚动 -->
|
||||
<maxFileSize>${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB}</maxFileSize>
|
||||
<!-- 日志文件的总大小,0 表示不限制 -->
|
||||
<totalSizeCap>${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0}</totalSizeCap>
|
||||
<!-- 日志文件的保留天数 -->
|
||||
<maxHistory>${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-30}</maxHistory>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
<!-- 异步写入日志,提升性能 -->
|
||||
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
|
||||
<!-- 不丢失日志。默认的,如果队列的 80% 已满,则会丢弃 TRACT、DEBUG、INFO 级别的日志 -->
|
||||
<discardingThreshold>0</discardingThreshold>
|
||||
<!-- 更改默认的队列的深度,该值会影响性能。默认值为 256 -->
|
||||
<queueSize>256</queueSize>
|
||||
<appender-ref ref="FILE"/>
|
||||
</appender>
|
||||
|
||||
<!-- SkyWalking GRPC 日志收集,实现日志中心。注意:SkyWalking 8.4.0 版本开始支持 -->
|
||||
<appender name="GRPC" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
|
||||
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
|
||||
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
|
||||
<pattern>${PATTERN_DEFAULT}</pattern>
|
||||
</layout>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 本地环境 -->
|
||||
<springProfile name="local">
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
<appender-ref ref="GRPC"/> <!-- 本地环境下,如果不想接入 SkyWalking 日志服务,可以注释掉本行 -->
|
||||
<appender-ref ref="ASYNC"/> <!-- 本地环境下,如果不想打印日志,可以注释掉本行 -->
|
||||
</root>
|
||||
</springProfile>
|
||||
<!-- 其它环境 -->
|
||||
<springProfile name="dev,test,stage,prod,default">
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
<appender-ref ref="ASYNC"/>
|
||||
<appender-ref ref="GRPC"/>
|
||||
</root>
|
||||
</springProfile>
|
||||
|
||||
</configuration>
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.iocoder.yudao.module.statistics.dal.mysql.infra.ApiAccessLogStatisticsMapper">
|
||||
|
||||
<select id="selectIpCountByUserTypeAndCreateTimeBetween" resultType="java.lang.Integer">
|
||||
SELECT COUNT(DISTINCT user_ip)
|
||||
FROM infra_api_access_log
|
||||
WHERE user_type = #{userType}
|
||||
AND create_time BETWEEN #{beginTime} AND #{endTime}
|
||||
AND deleted = FALSE
|
||||
</select>
|
||||
|
||||
<select id="selectUserCountByUserTypeAndCreateTimeBetween" resultType="java.lang.Integer">
|
||||
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
|
||||
</select>
|
||||
|
||||
</mapper>
|
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.iocoder.yudao.module.statistics.dal.mysql.member.MemberStatisticsMapper">
|
||||
|
||||
<select id="selectSummaryListByAreaId"
|
||||
resultType="cn.iocoder.yudao.module.statistics.service.member.bo.MemberAreaStatisticsRespBO">
|
||||
SELECT area_id, COUNT(1) AS userCount
|
||||
FROM member_user
|
||||
WHERE deleted = FALSE
|
||||
GROUP BY area_id
|
||||
</select>
|
||||
|
||||
<select id="selectSummaryListBySex"
|
||||
resultType="cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberSexStatisticsRespVO">
|
||||
SELECT sex, COUNT(1) AS userCount
|
||||
FROM member_user
|
||||
WHERE deleted = FALSE
|
||||
GROUP BY sex
|
||||
</select>
|
||||
|
||||
<select id="selectSummaryListByRegisterTerminal"
|
||||
resultType="cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberTerminalStatisticsRespVO">
|
||||
SELECT register_terminal as terminal, COUNT(1) AS userCount
|
||||
FROM member_user
|
||||
WHERE deleted = FALSE
|
||||
GROUP BY register_terminal
|
||||
</select>
|
||||
|
||||
<select id="selectUserCount" resultType="java.lang.Integer">
|
||||
SELECT COUNT(1)
|
||||
FROM member_user
|
||||
WHERE deleted = FALSE
|
||||
<if test="beginTime != null">
|
||||
AND create_time >= #{beginTime}
|
||||
</if>
|
||||
<if test="endTime != null">
|
||||
AND create_time <= #{endTime}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="selectListByCreateTimeBetween"
|
||||
resultType="cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberRegisterCountRespVO">
|
||||
SELECT DATE_FORMAT(create_time, '%Y-%m-%d') AS date,
|
||||
count(1) AS count
|
||||
FROM member_user
|
||||
WHERE create_time BETWEEN #{beginTime} AND #{endTime}
|
||||
AND deleted = FALSE
|
||||
GROUP BY date
|
||||
</select>
|
||||
|
||||
</mapper>
|
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.iocoder.yudao.module.statistics.dal.mysql.pay.PayWalletStatisticsMapper">
|
||||
|
||||
<select id="selectRechargeSummaryByPayTimeBetween"
|
||||
resultType="cn.iocoder.yudao.module.statistics.service.trade.bo.WalletSummaryRespBO">
|
||||
SELECT COUNT(1) AS rechargePayCount,
|
||||
SUM(pay_price) AS rechargePayPrice
|
||||
FROM pay_wallet_recharge
|
||||
WHERE pay_status = #{payStatus}
|
||||
AND pay_time BETWEEN #{beginTime} AND #{endTime}
|
||||
AND deleted = FALSE
|
||||
</select>
|
||||
|
||||
<select id="selectRechargeSummaryByRefundTimeBetween"
|
||||
resultType="cn.iocoder.yudao.module.statistics.service.trade.bo.WalletSummaryRespBO">
|
||||
SELECT COUNT(1) AS rechargeRefundCount,
|
||||
SUM(pay_price) AS rechargeRefundPrice
|
||||
FROM pay_wallet_recharge
|
||||
WHERE refund_status = #{refundStatus}
|
||||
AND refund_time BETWEEN #{beginTime} AND #{endTime}
|
||||
AND deleted = FALSE
|
||||
</select>
|
||||
|
||||
<select id="selectPriceSummaryByBizTypeAndCreateTimeBetween" resultType="java.lang.Integer">
|
||||
SELECT SUM(price)
|
||||
FROM pay_wallet_transaction
|
||||
WHERE biz_type = #{bizType}
|
||||
AND create_time BETWEEN #{beginTime} AND #{endTime}
|
||||
AND deleted = FALSE
|
||||
</select>
|
||||
|
||||
<select id="selectRechargeSummaryGroupByWalletId"
|
||||
resultType="cn.iocoder.yudao.module.statistics.service.pay.bo.RechargeSummaryRespBO">
|
||||
SELECT COUNT(DISTINCT wallet_id) AS rechargeUserCount,
|
||||
SUM(pay_price) AS rechargePrice
|
||||
FROM pay_wallet_recharge
|
||||
WHERE pay_status = #{payStatus}
|
||||
<if test="beginTime != null">
|
||||
AND pay_time >= #{beginTime}
|
||||
</if>
|
||||
<if test="endTime != null">
|
||||
AND pay_time <= #{endTime}
|
||||
</if>
|
||||
AND deleted = FALSE
|
||||
</select>
|
||||
|
||||
<select id="selectRechargePriceSummary" resultType="java.lang.Integer">
|
||||
SELECT IFNULL(SUM(pay_price), 0)
|
||||
FROM pay_wallet_recharge
|
||||
WHERE pay_status = #{payStatus}
|
||||
AND deleted = FALSE
|
||||
</select>
|
||||
|
||||
</mapper>
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.iocoder.yudao.module.statistics.dal.mysql.trade.AfterSaleStatisticsMapper">
|
||||
|
||||
<select id="selectSummaryByRefundTimeBetween"
|
||||
resultType="cn.iocoder.yudao.module.statistics.service.trade.bo.AfterSaleSummaryRespBO">
|
||||
SELECT COUNT(1) AS afterSaleCount,
|
||||
SUM(refund_price) AS afterSaleRefundPrice
|
||||
FROM trade_after_sale
|
||||
WHERE refund_time BETWEEN #{beginTime} AND #{endTime}
|
||||
AND deleted = FALSE
|
||||
</select>
|
||||
|
||||
<select id="selectCountByStatus" resultType="java.lang.Long">
|
||||
SELECT COUNT(1)
|
||||
FROM trade_after_sale
|
||||
WHERE status = #{status}
|
||||
AND deleted = FALSE
|
||||
</select>
|
||||
|
||||
</mapper>
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.iocoder.yudao.module.statistics.dal.mysql.trade.BrokerageStatisticsMapper">
|
||||
|
||||
<select id="selectSummaryPriceByStatusAndUnfreezeTimeBetween" resultType="java.lang.Integer">
|
||||
SELECT SUM(price)
|
||||
FROM trade_brokerage_record
|
||||
WHERE biz_type = #{bizType}
|
||||
AND status = #{status}
|
||||
AND unfreeze_time BETWEEN #{beginTime} AND #{endTime}
|
||||
AND deleted = FALSE
|
||||
</select>
|
||||
|
||||
<select id="selectWithdrawCountByStatus" resultType="java.lang.Long">
|
||||
SELECT COUNT(1)
|
||||
FROM trade_brokerage_withdraw
|
||||
WHERE status = #{status}
|
||||
AND deleted = FALSE
|
||||
</select>
|
||||
|
||||
</mapper>
|
|
@ -0,0 +1,106 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.iocoder.yudao.module.statistics.dal.mysql.trade.TradeOrderStatisticsMapper">
|
||||
|
||||
<select id="selectSummaryListByAreaId"
|
||||
resultType="cn.iocoder.yudao.module.statistics.service.member.bo.MemberAreaStatisticsRespBO">
|
||||
SELECT receiver_area_id AS areaId,
|
||||
(SELECT COUNT(DISTINCT s.user_id)
|
||||
FROM trade_order AS s
|
||||
WHERE s.receiver_area_id = m.receiver_area_id) AS orderCreateUserCount,
|
||||
(SELECT COUNT(DISTINCT s.user_id)
|
||||
FROM trade_order AS s
|
||||
WHERE s.receiver_area_id = m.receiver_area_id
|
||||
AND s.pay_status = TRUE
|
||||
AND s.deleted = FALSE) AS orderPayUserCount,
|
||||
(SELECT SUM(s.pay_price)
|
||||
FROM trade_order AS s
|
||||
WHERE s.receiver_area_id = m.receiver_area_id
|
||||
AND s.pay_status = TRUE
|
||||
AND s.deleted = FALSE) AS orderPayPrice
|
||||
FROM trade_order m
|
||||
WHERE deleted = FALSE
|
||||
GROUP BY receiver_area_id
|
||||
</select>
|
||||
|
||||
<select id="selectUserCountByCreateTimeBetween" resultType="java.lang.Integer">
|
||||
SELECT COUNT(DISTINCT (user_id))
|
||||
FROM trade_order
|
||||
WHERE deleted = FALSE
|
||||
AND create_time BETWEEN #{beginTime} AND #{endTime}
|
||||
</select>
|
||||
|
||||
<select id="selectUserCountByPayTimeBetween" resultType="java.lang.Integer">
|
||||
SELECT COUNT(DISTINCT (user_id))
|
||||
FROM trade_order
|
||||
WHERE pay_time BETWEEN #{beginTime} AND #{endTime}
|
||||
AND pay_status = TRUE
|
||||
AND deleted = FALSE
|
||||
</select>
|
||||
|
||||
<select id="selectCountByCreateTimeBetween" resultType="java.lang.Integer">
|
||||
SELECT COUNT(1)
|
||||
FROM trade_order
|
||||
WHERE create_time BETWEEN #{beginTime} AND #{endTime}
|
||||
AND deleted = FALSE
|
||||
</select>
|
||||
|
||||
<select id="selectCountByPayTimeBetween" resultType="java.lang.Integer">
|
||||
SELECT COUNT(1)
|
||||
FROM trade_order
|
||||
WHERE pay_status = TRUE
|
||||
AND create_time BETWEEN #{beginTime} AND #{endTime}
|
||||
AND deleted = FALSE
|
||||
</select>
|
||||
|
||||
<select id="selectSummaryPriceByPayTimeBetween" resultType="java.lang.Integer">
|
||||
SELECT SUM(pay_price)
|
||||
FROM trade_order AS s
|
||||
WHERE s.pay_status = TRUE
|
||||
AND deleted = FALSE
|
||||
AND create_time BETWEEN #{beginTime} AND #{endTime}
|
||||
</select>
|
||||
|
||||
<select id="selectListByPayTimeBetweenAndGroupByDay"
|
||||
resultType="cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeOrderTrendRespVO">
|
||||
SELECT DATE_FORMAT(pay_time, '%Y-%m-%d') AS date,
|
||||
COUNT(1) AS orderPayCount,
|
||||
SUM(pay_price) AS orderPayPrice
|
||||
FROM trade_order
|
||||
WHERE pay_status = TRUE
|
||||
AND create_time BETWEEN #{beginTime} AND #{endTime}
|
||||
AND deleted = FALSE
|
||||
GROUP BY date
|
||||
</select>
|
||||
|
||||
<select id="selectListByPayTimeBetweenAndGroupByMonth"
|
||||
resultType="cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeOrderTrendRespVO">
|
||||
SELECT DATE_FORMAT(pay_time, '%Y-%m') AS date,
|
||||
COUNT(1) AS orderPayCount,
|
||||
SUM(pay_price) AS orderPayPrice
|
||||
FROM trade_order
|
||||
WHERE pay_status = TRUE
|
||||
AND create_time BETWEEN #{beginTime} AND #{endTime}
|
||||
AND deleted = FALSE
|
||||
GROUP BY date
|
||||
</select>
|
||||
|
||||
<select id="selectCountByStatusAndDeliveryType" resultType="java.lang.Long">
|
||||
SELECT COUNT(1)
|
||||
FROM trade_order
|
||||
WHERE status = #{status}
|
||||
ANd delivery_type = #{deliveryType}
|
||||
AND deleted = FALSE
|
||||
</select>
|
||||
|
||||
<select id="selectPaySummaryByStatusAndPayTimeBetween"
|
||||
resultType="cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeOrderSummaryRespVO">
|
||||
SELECT IFNULL(SUM(pay_price), 0) AS orderPayPrice,
|
||||
COUNT(1) AS orderPayCount
|
||||
FROM trade_order
|
||||
WHERE status = #{status}
|
||||
AND pay_time BETWEEN #{beginTime} AND #{endTime}
|
||||
AND deleted = FALSE
|
||||
</select>
|
||||
|
||||
</mapper>
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.iocoder.yudao.module.statistics.dal.mysql.trade.TradeStatisticsMapper">
|
||||
|
||||
<select id="selectOrderCreateCountSumAndOrderPayPriceSumByTimeBetween"
|
||||
resultType="cn.iocoder.yudao.module.statistics.service.trade.bo.TradeSummaryRespBO">
|
||||
SELECT IFNULL(SUM(order_create_count), 0) AS count,
|
||||
IFNULL(SUM(order_pay_price), 0) AS summary
|
||||
FROM trade_statistics
|
||||
WHERE time BETWEEN #{beginTime} AND #{endTime}
|
||||
AND deleted = FALSE
|
||||
</select>
|
||||
|
||||
<select id="selectVoByTimeBetween"
|
||||
resultType="cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO">
|
||||
SELECT
|
||||
-- 营业额 = 商品支付金额 + 充值金额
|
||||
SUM(order_pay_price + recharge_pay_price) AS turnoverPrice,
|
||||
SUM(order_pay_price) AS orderPayPrice,
|
||||
SUM(recharge_pay_price) AS rechargePrice,
|
||||
-- 支出金额 = 余额支付金额 + 支付佣金金额 + 商品退款金额
|
||||
SUM(wallet_pay_price + brokerage_settlement_price + after_sale_refund_price) AS expensePrice,
|
||||
SUM(wallet_pay_price) AS walletPayPrice,
|
||||
SUM(brokerage_settlement_price) AS brokerageSettlementPrice,
|
||||
SUM(after_sale_refund_price) AS afterSaleRefundPrice
|
||||
FROM trade_statistics
|
||||
WHERE time BETWEEN #{beginTime} AND #{endTime}
|
||||
AND deleted = FALSE
|
||||
</select>
|
||||
|
||||
<select id="selectExpensePriceByTimeBetween" resultType="java.lang.Integer">
|
||||
SELECT -- 支出金额 = 余额支付金额 + 支付佣金金额 + 商品退款金额
|
||||
SUM(wallet_pay_price + brokerage_settlement_price + after_sale_refund_price) AS expensePrice
|
||||
FROM trade_statistics
|
||||
WHERE deleted = FALSE
|
||||
<if test="beginTime != null">
|
||||
AND time >= #{beginTime}
|
||||
</if>
|
||||
<if test="endTime != null">
|
||||
AND time <= #{endTime}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
</mapper>
|
|
@ -0,0 +1,40 @@
|
|||
package cn.iocoder.yudao.module.pay.enums.wallet;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 钱包交易业务分类
|
||||
*
|
||||
* @author jason
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum PayWalletBizTypeEnum implements IntArrayValuable {
|
||||
|
||||
RECHARGE(1, "充值"),
|
||||
RECHARGE_REFUND(2, "充值退款"),
|
||||
PAYMENT(3, "支付"),
|
||||
PAYMENT_REFUND(4, "支付退款");
|
||||
|
||||
// TODO 后续增加
|
||||
|
||||
/**
|
||||
* 业务分类
|
||||
*/
|
||||
private final Integer type;
|
||||
/**
|
||||
* 说明
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PayWalletBizTypeEnum::getType).toArray();
|
||||
|
||||
@Override
|
||||
public int[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue