Commit b376de1ad30e2a30b02b0e4da1543df4adb72742

Authored by 芋道源码
Committed by Gitee
2 parents 96b1662e 6b7f0719

!640 交易统计

Merge pull request !640 from 疯狂的世界/feature/mall_product
Showing 30 changed files with 752 additions and 231 deletions
sql/mysql/statistics.sql 0 → 100644
  1 +-- 交易统计表
  2 +CREATE TABLE trade_statistics
  3 +(
  4 + id bigint AUTO_INCREMENT COMMENT '编号,主键自增'
  5 + PRIMARY KEY,
  6 + time datetime NOT NULL COMMENT '统计日期',
  7 + order_create_count int DEFAULT 0 NOT NULL COMMENT '创建订单数',
  8 + order_pay_count int DEFAULT 0 NOT NULL COMMENT '支付订单商品数',
  9 + order_pay_price int DEFAULT 0 NOT NULL COMMENT '总支付金额,单位:分',
  10 + order_wallet_pay_price int DEFAULT 0 NOT NULL COMMENT '总支付金额(余额),单位:分',
  11 + after_sale_count int DEFAULT 0 NOT NULL COMMENT '退款订单数',
  12 + after_sale_refund_price int DEFAULT 0 NOT NULL COMMENT '总退款金额,单位:分',
  13 + brokerage_settlement_price int DEFAULT 0 NOT NULL COMMENT '佣金金额(已结算),单位:分',
  14 + recharge_pay_count int DEFAULT 0 NOT NULL COMMENT '充值订单数',
  15 + recharge_pay_price int DEFAULT 0 NOT NULL COMMENT '充值金额,单位:分',
  16 + recharge_refund_count int DEFAULT 0 NOT NULL COMMENT '充值退款订单数',
  17 + recharge_refund_price int DEFAULT 0 NOT NULL COMMENT '充值退款金额,单位:分',
  18 + creator varchar(64) DEFAULT '' NULL COMMENT '创建者',
  19 + create_time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL COMMENT '创建时间',
  20 + updater varchar(64) DEFAULT '' NULL COMMENT '更新者',
  21 + update_time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  22 + deleted bit DEFAULT b'0' NOT NULL COMMENT '是否删除',
  23 + tenant_id bigint DEFAULT 0 NOT NULL COMMENT '租户编号'
  24 +)
  25 + COMMENT '交易统计表';
  26 +
  27 +CREATE INDEX trade_statistics_time_index
  28 + ON trade_statistics (time);
  29 +
  30 +-- 菜单
  31 +INSERT INTO `ruoyi-vue-pro`.system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name)
  32 +VALUES ('统计管理', '', 1, 4, 0, '/statistics', 'ep:data-line', '', '');
  33 +SELECT @parentId := LAST_INSERT_ID();
  34 +INSERT INTO `ruoyi-vue-pro`.system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name)
  35 +VALUES ('交易统计', '', 2, 4, @parentId, 'trade', 'fa-solid:credit-card', 'statistics/trade/index', 'TradeStatistics');
  36 +SELECT @parentId := LAST_INSERT_ID();
  37 +-- 按钮
  38 +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
  39 +VALUES ('交易统计查询', 'statistics:trade:query', 3, 1, @parentId, '', '', '', 0);
  40 +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
  41 +VALUES ('交易统计导出', 'statistics:trade:export', 3, 2, @parentId, '', '', '', 0);
  42 +
  43 +
... ...
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java
... ... @@ -11,40 +11,40 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
11 11 */
12 12 public interface SmsFrameworkErrorCodeConstants {
13 13  
14   - ErrorCode SMS_UNKNOWN = new ErrorCode(2001000000, "未知错误,需要解析");
  14 + ErrorCode SMS_UNKNOWN = new ErrorCode(2_001_000_000, "未知错误,需要解析");
15 15  
16   - // ========== 权限 / 限流等相关 2001000100 ==========
  16 + // ========== 权限 / 限流等相关 2-001-000-100 ==========
17 17  
18   - ErrorCode SMS_PERMISSION_DENY = new ErrorCode(2001000100, "没有发送短信的权限");
19   - ErrorCode SMS_IP_DENY = new ErrorCode(2001000100, "IP 不允许发送短信");
  18 + ErrorCode SMS_PERMISSION_DENY = new ErrorCode(2_001_000_100, "没有发送短信的权限");
  19 + ErrorCode SMS_IP_DENY = new ErrorCode(2_001_000_100, "IP 不允许发送短信");
20 20  
21 21 // 阿里云:将短信发送频率限制在正常的业务限流范围内。默认短信验证码:使用同一签名,对同一个手机号验证码,支持 1 条 / 分钟,5 条 / 小时,累计 10 条 / 天。
22   - ErrorCode SMS_SEND_BUSINESS_LIMIT_CONTROL = new ErrorCode(2001000102, "指定手机的发送限流");
  22 + ErrorCode SMS_SEND_BUSINESS_LIMIT_CONTROL = new ErrorCode(2_001_000_102, "指定手机的发送限流");
23 23 // 阿里云:已经达到您在控制台设置的短信日发送量限额值。在国内消息设置 > 安全设置,修改发送总量阈值。
24   - ErrorCode SMS_SEND_DAY_LIMIT_CONTROL = new ErrorCode(2001000103, "每天的发送限流");
  24 + ErrorCode SMS_SEND_DAY_LIMIT_CONTROL = new ErrorCode(2_001_000_103, "每天的发送限流");
25 25  
26   - ErrorCode SMS_SEND_CONTENT_INVALID = new ErrorCode(2001000104, "短信内容有敏感词");
  26 + ErrorCode SMS_SEND_CONTENT_INVALID = new ErrorCode(2_001_000_104, "短信内容有敏感词");
27 27  
28 28 // 腾讯云:为避免骚扰用户,营销短信只允许在8点到22点发送。
29   - ErrorCode SMS_SEND_MARKET_LIMIT_CONTROL = new ErrorCode(2001000105, "营销短信发送时间限制");
  29 + ErrorCode SMS_SEND_MARKET_LIMIT_CONTROL = new ErrorCode(2_001_000_105, "营销短信发送时间限制");
30 30  
31   - // ========== 模板相关 2001000200 ==========
32   - ErrorCode SMS_TEMPLATE_INVALID = new ErrorCode(2001000200, "短信模板不合法"); // 包括短信模板不存在
33   - ErrorCode SMS_TEMPLATE_PARAM_ERROR = new ErrorCode(2001000201, "模板参数不正确");
  31 + // ========== 模板相关 2-001-000-200 ==========
  32 + ErrorCode SMS_TEMPLATE_INVALID = new ErrorCode(2_001_000_200, "短信模板不合法"); // 包括短信模板不存在
  33 + ErrorCode SMS_TEMPLATE_PARAM_ERROR = new ErrorCode(2_001_000_201, "模板参数不正确");
34 34  
35   - // ========== 签名相关 2001000300 ==========
36   - ErrorCode SMS_SIGN_INVALID = new ErrorCode(2001000300, "短信签名不可用");
  35 + // ========== 签名相关 2-001-000-300 ==========
  36 + ErrorCode SMS_SIGN_INVALID = new ErrorCode(2_001_000_300, "短信签名不可用");
37 37  
38   - // ========== 账户相关 2001000400 ==========
39   - ErrorCode SMS_ACCOUNT_MONEY_NOT_ENOUGH = new ErrorCode(2001000400, "账户余额不足");
40   - ErrorCode SMS_ACCOUNT_INVALID = new ErrorCode(2001000401, "apiKey 不存在");
  38 + // ========== 账户相关 2-001-000-400 ==========
  39 + ErrorCode SMS_ACCOUNT_MONEY_NOT_ENOUGH = new ErrorCode(2_001_000_400, "账户余额不足");
  40 + ErrorCode SMS_ACCOUNT_INVALID = new ErrorCode(2_001_000_401, "apiKey 不存在");
41 41  
42   - // ========== 其它相关 2001000900 开头 ==========
43   - ErrorCode SMS_API_PARAM_ERROR = new ErrorCode(2001000900, "请求参数缺失");
44   - ErrorCode SMS_MOBILE_INVALID = new ErrorCode(2001000901, "手机格式不正确");
45   - ErrorCode SMS_MOBILE_BLACK = new ErrorCode(2001000902, "手机号在黑名单中");
46   - ErrorCode SMS_APP_ID_INVALID = new ErrorCode(2001000903, "SdkAppId不合法");
  42 + // ========== 其它相关 2-001-000-900 开头 ==========
  43 + ErrorCode SMS_API_PARAM_ERROR = new ErrorCode(2_001_000_900, "请求参数缺失");
  44 + ErrorCode SMS_MOBILE_INVALID = new ErrorCode(2_001_000_901, "手机格式不正确");
  45 + ErrorCode SMS_MOBILE_BLACK = new ErrorCode(2_001_000_902, "手机号在黑名单中");
  46 + ErrorCode SMS_APP_ID_INVALID = new ErrorCode(2_001_000_903, "SdkAppId不合法");
47 47  
48   - ErrorCode EXCEPTION = new ErrorCode(2001000999, "调用异常");
  48 + ErrorCode EXCEPTION = new ErrorCode(2_001_000_999, "调用异常");
49 49  
50 50 }
... ...
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
... ... @@ -50,12 +50,12 @@ public interface ErrorCodeConstants {
50 50 // ========== TODO 空着 1-013-007-000 ============
51 51  
52 52 // ========== 秒杀活动 1-013-008-000 ==========
53   - ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1013008000, "秒杀活动不存在");
54   - ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013008002, "存在商品参加了其它秒杀活动,秒杀时段冲突");
55   - ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改");
56   - ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除");
57   - ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭");
58   - ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "秒杀失败,原因秒杀库存不足");
  53 + ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_008_000, "秒杀活动不存在");
  54 + ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_008_002, "存在商品参加了其它秒杀活动,秒杀时段冲突");
  55 + ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_008_003, "秒杀活动已关闭,不能修改");
  56 + ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1_013_008_004, "秒杀活动未关闭或未结束,不能删除");
  57 + ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_008_005, "秒杀活动已关闭,不能重复关闭");
  58 + ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1_013_008_006, "秒杀失败,原因秒杀库存不足");
59 59  
60 60 // ========== 秒杀时段 1-013-009-000 ==========
61 61 ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1_013_009_000, "秒杀时段不存在");
... ... @@ -63,28 +63,28 @@ public interface ErrorCodeConstants {
63 63 ErrorCode SECKILL_CONFIG_DISABLE = new ErrorCode(1_013_009_004, "秒杀时段已关闭");
64 64  
65 65 // ========== 拼团活动 1-013-010-000 ==========
66   - ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在");
67   - ErrorCode COMBINATION_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013010001, "存在商品参加了其它拼团活动");
68   - ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE_NOT_UPDATE = new ErrorCode(1013010002, "拼团活动已关闭不能修改");
69   - ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013010003, "拼团活动未关闭或未结束,不能删除");
70   - ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013010004, "拼团失败,原因:拼团活动已关闭");
  66 + ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_010_000, "拼团活动不存在");
  67 + ErrorCode COMBINATION_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_010_001, "存在商品参加了其它拼团活动");
  68 + ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE_NOT_UPDATE = new ErrorCode(1_013_010_002, "拼团活动已关闭不能修改");
  69 + ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1_013_010_003, "拼团活动未关闭或未结束,不能删除");
  70 + ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1_013_010_004, "拼团失败,原因:拼团活动已关闭");
71 71  
72 72 // ========== 拼团记录 1-013-011-000 ==========
73   - ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013011000, "拼团不存在");
74   - ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1013011001, "拼团失败,已参与过该拼团");
75   - ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013011002, "拼团失败,父拼团不存在");
76   - ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1013011003, "拼团失败,拼团人数已满");
77   - ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1013011004, "拼团失败,已参与其它拼团");
78   - ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1013011005, "拼团失败,活动已经结束");
79   - ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011006, "拼团失败,原因:单次限购超出");
80   - ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011007, "拼团失败,原因:超出总购买次数");
  73 + ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1_013_011_000, "拼团不存在");
  74 + ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1_013_011_001, "拼团失败,已参与过该拼团");
  75 + ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1_013_011_002, "拼团失败,父拼团不存在");
  76 + ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1_013_011_003, "拼团失败,拼团人数已满");
  77 + ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1_013_011_004, "拼团失败,已参与其它拼团");
  78 + ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1_013_011_005, "拼团失败,活动已经结束");
  79 + ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1_013_011_006, "拼团失败,原因:单次限购超出");
  80 + ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1_013_011_007, "拼团失败,原因:超出总购买次数");
81 81  
82 82 // ========== 砍价活动 1-013-012-000 ==========
83   - ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1013012000, "砍价活动不存在");
84   - ErrorCode BARGAIN_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013012001, "存在商品参加了其它砍价活动");
85   - ErrorCode BARGAIN_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013012002, "砍价活动已关闭不能修改");
86   - ErrorCode BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013012003, "砍价活动未关闭或未结束,不能删除");
87   - ErrorCode BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013012004, "砍价失败,原因:该砍价活动库存不足");
  83 + ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_012_000, "砍价活动不存在");
  84 + ErrorCode BARGAIN_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_012_001, "存在商品参加了其它砍价活动");
  85 + ErrorCode BARGAIN_ACTIVITY_STATUS_DISABLE = new ErrorCode(1_013_012_002, "砍价活动已关闭不能修改");
  86 + ErrorCode BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1_013_012_003, "砍价活动未关闭或未结束,不能删除");
  87 + ErrorCode BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1_013_012_004, "砍价失败,原因:该砍价活动库存不足");
88 88  
89 89 // ========== 砍价记录 1-013-013-000 ==========
90 90 ErrorCode BARGAIN_RECORD_NOT_EXISTS = new ErrorCode(1_013_013_000, "砍价记录不存在");
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java
1 1 package cn.iocoder.yudao.module.promotion.controller.app.coupon;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4   -import cn.hutool.core.map.MapUtil;
5 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 6 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
... ... @@ -50,9 +49,7 @@ public class AppCouponController {
50 49 CouponTemplateDO couponTemplate = couponTemplateService.getCouponTemplate(reqVO.getTemplateId());
51 50 boolean canTakeAgain = true;
52 51 if (couponTemplate.getTakeLimitCount() != null && couponTemplate.getTakeLimitCount() > 0) {
53   - // TODO @疯狂:要不要搞个 getTakeCount 方法?
54   - Integer takeCount = MapUtil.getInt(couponService.getTakeCountMapByTemplateIds(
55   - Collections.singleton(reqVO.getTemplateId()), userId), reqVO.getTemplateId(), 0);
  52 + Integer takeCount = couponService.getTakeCount(reqVO.getTemplateId(), userId);
56 53 canTakeAgain = takeCount < couponTemplate.getTakeLimitCount();
57 54 }
58 55 return success(canTakeAgain);
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java
... ... @@ -8,10 +8,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
8 8 import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
9 9 import cn.iocoder.yudao.module.promotion.service.coupon.bo.CouponTakeCountBO;
10 10  
11   -import java.util.Collection;
12   -import java.util.List;
13   -import java.util.Map;
14   -import java.util.Set;
  11 +import java.util.*;
15 12  
16 13 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
17 14  
... ... @@ -130,6 +127,21 @@ public interface CouponService {
130 127 }
131 128  
132 129 /**
  130 + * 获取会员领取指定优惠券的数量
  131 + *
  132 + * @param templateId 优惠券模板编号
  133 + * @param userId 用户编号
  134 + * @return 领取优惠券的数量
  135 + */
  136 + default Integer getTakeCount(Long templateId, Long userId) {
  137 + return CollUtil.emptyIfNull(getTakeCountListByTemplateIds(Collections.singleton(templateId), userId))
  138 + .stream()
  139 + .findFirst()
  140 + .map(CouponTakeCountBO::getCount)
  141 + .orElse(0);
  142 + }
  143 +
  144 + /**
133 145 * 统计会员领取优惠券的数量
134 146 *
135 147 * @param templateIds 优惠券模板编号列表
... ...
yudao-module-mall/yudao-module-statistics-biz/pom.xml
... ... @@ -49,6 +49,10 @@
49 49 <groupId>cn.iocoder.boot</groupId>
50 50 <artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
51 51 </dependency>
  52 + <dependency>
  53 + <groupId>cn.iocoder.boot</groupId>
  54 + <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
  55 + </dependency>
52 56  
53 57 <!-- Web 相关 -->
54 58 <dependency>
... ...
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/TradeStatisticsController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.statistics.controller.admin.trade;
  2 +
  3 +import cn.hutool.core.util.ArrayUtil;
  4 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  5 +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  6 +import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.*;
  7 +import cn.iocoder.yudao.module.statistics.convert.trade.TradeStatisticsConvert;
  8 +import cn.iocoder.yudao.module.statistics.service.trade.TradeStatisticsService;
  9 +import io.swagger.v3.oas.annotations.Operation;
  10 +import io.swagger.v3.oas.annotations.tags.Tag;
  11 +import lombok.extern.slf4j.Slf4j;
  12 +import org.springframework.security.access.prepost.PreAuthorize;
  13 +import org.springframework.validation.annotation.Validated;
  14 +import org.springframework.web.bind.annotation.GetMapping;
  15 +import org.springframework.web.bind.annotation.RequestMapping;
  16 +import org.springframework.web.bind.annotation.RestController;
  17 +
  18 +import javax.annotation.Resource;
  19 +import javax.servlet.http.HttpServletResponse;
  20 +import java.io.IOException;
  21 +import java.util.List;
  22 +
  23 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  24 +
  25 +@Tag(name = "管理后台 - 交易统计")
  26 +@RestController
  27 +@RequestMapping("/statistics/trade")
  28 +@Validated
  29 +@Slf4j
  30 +public class TradeStatisticsController {
  31 +
  32 + @Resource
  33 + private TradeStatisticsService tradeStatisticsService;
  34 +
  35 + @GetMapping("/summary")
  36 + @Operation(summary = "获得交易统计")
  37 + @PreAuthorize("@ss.hasPermission('statistics:trade:query')")
  38 + public CommonResult<TradeStatisticsComparisonRespVO<TradeSummaryRespVO>> getTradeSummaryComparison() {
  39 + return success(tradeStatisticsService.getTradeSummaryComparison());
  40 + }
  41 +
  42 + @GetMapping("/trend/summary")
  43 + @Operation(summary = "获得交易状况统计")
  44 + @PreAuthorize("@ss.hasPermission('statistics:trade:query')")
  45 + public CommonResult<TradeStatisticsComparisonRespVO<TradeTrendSummaryRespVO>> getTradeTrendSummaryComparison(
  46 + TradeTrendReqVO reqVO) {
  47 + return success(tradeStatisticsService.getTradeTrendSummaryComparison(ArrayUtil.get(reqVO.getTimes(), 0),
  48 + ArrayUtil.get(reqVO.getTimes(), 1)));
  49 + }
  50 +
  51 + @GetMapping("/trend/list")
  52 + @Operation(summary = "获得交易状况明细")
  53 + @PreAuthorize("@ss.hasPermission('statistics:trade:query')")
  54 + public CommonResult<List<TradeTrendSummaryRespVO>> getTradeStatisticsList(
  55 + TradeTrendReqVO reqVO) {
  56 + return success(tradeStatisticsService.getTradeStatisticsList(ArrayUtil.get(reqVO.getTimes(), 0),
  57 + ArrayUtil.get(reqVO.getTimes(), 1)));
  58 + }
  59 +
  60 + @GetMapping("/trend/export-excel")
  61 + @Operation(summary = "导出获得交易状况明细 Excel")
  62 + @PreAuthorize("@ss.hasPermission('statistics:trade:export')")
  63 + public void exportTradeStatisticsExcel(TradeTrendReqVO reqVO, HttpServletResponse response) throws IOException {
  64 + List<TradeTrendSummaryRespVO> list = tradeStatisticsService.getTradeStatisticsList(ArrayUtil.get(reqVO.getTimes(), 0),
  65 + ArrayUtil.get(reqVO.getTimes(), 1));
  66 + // 导出 Excel
  67 + List<TradeTrendSummaryExcelVO> data = TradeStatisticsConvert.INSTANCE.convertList02(list);
  68 + ExcelUtils.write(response, "交易状况.xls", "数据", TradeTrendSummaryExcelVO.class, data);
  69 + }
  70 +
  71 +}
... ...
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeStatisticsComparisonRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Data;
  6 +import lombok.NoArgsConstructor;
  7 +
  8 +@Schema(description = "管理后台 - 交易统计对照 Response VO")
  9 +@Data
  10 +@NoArgsConstructor
  11 +@AllArgsConstructor
  12 +public class TradeStatisticsComparisonRespVO<T> {
  13 +
  14 + @Schema(description = "当前数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  15 + private T value;
  16 +
  17 + @Schema(description = "参照数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  18 + private T reference;
  19 +
  20 +}
... ...
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeSummaryRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +@Schema(description = "管理后台 - 交易统计 Response VO")
  7 +@Data
  8 +public class TradeSummaryRespVO {
  9 + @Schema(description = "昨日订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  10 + private Integer yesterdayOrderCount;
  11 + @Schema(description = "昨日支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  12 + private Integer yesterdayPayPrice;
  13 +
  14 + @Schema(description = "本月订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  15 + private Integer monthOrderCount;
  16 + @Schema(description = "本月支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  17 + private Integer monthPayPrice;
  18 +}
... ...
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import org.springframework.format.annotation.DateTimeFormat;
  6 +
  7 +import java.time.LocalDateTime;
  8 +
  9 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  10 +
  11 +@Schema(description = "管理后台 - 交易状况 Request VO")
  12 +@Data
  13 +public class TradeTrendReqVO {
  14 +
  15 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  16 + @Schema(description = "时间范围")
  17 + private LocalDateTime[] times;
  18 +}
... ...
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryExcelVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo;
  2 +
  3 +import cn.iocoder.yudao.framework.excel.core.convert.MoneyConvert;
  4 +import com.alibaba.excel.annotation.ExcelProperty;
  5 +import com.alibaba.excel.annotation.format.DateTimeFormat;
  6 +import lombok.Data;
  7 +
  8 +import java.time.LocalDate;
  9 +
  10 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
  11 +
  12 +/**
  13 + * 交易状况统计 Excel VO
  14 + *
  15 + * @author owen
  16 + */
  17 +@Data
  18 +public class TradeTrendSummaryExcelVO {
  19 +
  20 + @ExcelProperty(value = "日期")
  21 + @DateTimeFormat(FORMAT_YEAR_MONTH_DAY)
  22 + private LocalDate date;
  23 +
  24 + @ExcelProperty(value = "营业额", converter = MoneyConvert.class)
  25 + private Integer turnover;
  26 +
  27 + @ExcelProperty(value = "商品支付金额", converter = MoneyConvert.class)
  28 + private Integer orderPayPrice;
  29 +
  30 + @ExcelProperty(value = "充值金额", converter = MoneyConvert.class)
  31 + private Integer rechargePrice;
  32 +
  33 + @ExcelProperty(value = "支出金额", converter = MoneyConvert.class)
  34 + private Integer expensePrice;
  35 +
  36 + @ExcelProperty(value = "余额支付金额", converter = MoneyConvert.class)
  37 + private Integer balancePrice;
  38 +
  39 + @ExcelProperty(value = "支付佣金金额", converter = MoneyConvert.class)
  40 + private Integer brokerageSettlementPrice;
  41 +
  42 + @ExcelProperty(value = "商品退款金额", converter = MoneyConvert.class)
  43 + private Integer orderRefundPrice;
  44 +}
... ...
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonFormat;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import lombok.Data;
  6 +
  7 +import java.time.LocalDate;
  8 +
  9 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
  10 +
  11 +@Schema(description = "管理后台 - 交易状况统计 Response VO")
  12 +@Data
  13 +public class TradeTrendSummaryRespVO {
  14 +
  15 + @Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  16 + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY)
  17 + private LocalDate date;
  18 +
  19 + @Schema(description = "营业额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  20 + private Integer turnover;
  21 +
  22 + @Schema(description = "商品支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  23 + private Integer orderPayPrice;
  24 +
  25 + @Schema(description = "充值金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  26 + private Integer rechargePrice;
  27 +
  28 + @Schema(description = "支出金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  29 + private Integer expensePrice;
  30 +
  31 + @Schema(description = "余额支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  32 + private Integer balancePrice;
  33 +
  34 + @Schema(description = "支付佣金金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  35 + private Integer brokerageSettlementPrice;
  36 +
  37 + @Schema(description = "商品退款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  38 + private Integer orderRefundPrice;
  39 +}
... ...
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/trade/TradeStatisticsController.java deleted
1   -package cn.iocoder.yudao.module.statistics.controller.trade;
2   -
3   -import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4   -import cn.iocoder.yudao.module.statistics.dal.mysql.trade.TradeStatisticsDO;
5   -import io.swagger.v3.oas.annotations.tags.Tag;
6   -import lombok.extern.slf4j.Slf4j;
7   -import org.springframework.validation.annotation.Validated;
8   -import org.springframework.web.bind.annotation.RequestMapping;
9   -import org.springframework.web.bind.annotation.RestController;
10   -
11   -import java.time.LocalDateTime;
12   -import java.util.List;
13   -
14   -@Tag(name = "管理后台 - 交易统计")
15   -@RestController
16   -@RequestMapping("/statistics/product")
17   -@Validated
18   -@Slf4j
19   -public class TradeStatisticsController {
20   -
21   - // TODO @疯狂:有个 summary 接口,返回昨日、本月、支付金额、本月订单金额等数据;具体看 ui 哈;
22   -
23   - // TODO @疯狂:返回 ProductStatisticsComparisonResp, 里面有两个字段,一个是选择的时间范围的合计结果,一个是对比的时间范围的合计结果;
24   - // 例如说,选择时间范围是 2023-10-01 ~ 2023-10-02,那么对比就是 2023-09-30,再倒推 2 天;
25   - public CommonResult<Object> getTradeStatisticsComparison() {
26   - return null;
27   - }
28   -
29   - // TODO @疯狂:查询指定时间范围内的交易统计数据;DO 到时需要改成 VO 哈
30   - // 总收入(营业额)= 订单、充值的支付 - 订单、充值的退款
31   - public CommonResult<List<TradeStatisticsDO>> getTradeStatisticsList(
32   - LocalDateTime[] times) {
33   - return null;
34   - }
35   -
36   -}
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/convert/trade/TradeStatisticsConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.statistics.convert.trade;
  2 +
  3 +import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO;
  4 +import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeSummaryRespVO;
  5 +import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryExcelVO;
  6 +import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO;
  7 +import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeSummaryRespBO;
  8 +import org.mapstruct.Mapper;
  9 +import org.mapstruct.factory.Mappers;
  10 +
  11 +import java.util.List;
  12 +
  13 +/**
  14 + * 交易统计 Convert
  15 + *
  16 + * @author owen
  17 + */
  18 +@Mapper
  19 +public interface TradeStatisticsConvert {
  20 +
  21 + TradeStatisticsConvert INSTANCE = Mappers.getMapper(TradeStatisticsConvert.class);
  22 +
  23 + default TradeStatisticsComparisonRespVO<TradeSummaryRespVO> convert(TradeSummaryRespBO yesterdayData,
  24 + TradeSummaryRespBO beforeYesterdayData,
  25 + TradeSummaryRespBO monthData,
  26 + TradeSummaryRespBO lastMonthData) {
  27 + return convert(convert(yesterdayData, monthData), convert(beforeYesterdayData, lastMonthData));
  28 + }
  29 +
  30 +
  31 + default TradeSummaryRespVO convert(TradeSummaryRespBO yesterdayData, TradeSummaryRespBO monthData) {
  32 + return new TradeSummaryRespVO()
  33 + .setYesterdayOrderCount(yesterdayData.getCount()).setYesterdayPayPrice(yesterdayData.getSummary())
  34 + .setMonthOrderCount(monthData.getCount()).setMonthPayPrice(monthData.getSummary());
  35 + }
  36 +
  37 + TradeStatisticsComparisonRespVO<TradeSummaryRespVO> convert(TradeSummaryRespVO value, TradeSummaryRespVO reference);
  38 +
  39 + TradeStatisticsComparisonRespVO<TradeTrendSummaryRespVO> convert(TradeTrendSummaryRespVO value, TradeTrendSummaryRespVO reference);
  40 +
  41 + List<TradeTrendSummaryExcelVO> convertList02(List<TradeTrendSummaryRespVO> list);
  42 +}
... ...
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/TradeStatisticsDO.java renamed to yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/dataobject/trade/TradeStatisticsDO.java
1   -package cn.iocoder.yudao.module.statistics.dal.mysql.trade;
  1 +package cn.iocoder.yudao.module.statistics.dal.dataobject.trade;
2 2  
3   -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  3 +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
4 4 import com.baomidou.mybatisplus.annotation.KeySequence;
5 5 import com.baomidou.mybatisplus.annotation.TableId;
6 6 import com.baomidou.mybatisplus.annotation.TableName;
... ... @@ -10,7 +10,7 @@ import java.time.LocalDateTime;
10 10  
11 11 /**
12 12 * 交易统计 DO
13   - *
  13 + * <p>
14 14 * 以天为维度,统计全部的数据
15 15 *
16 16 * @author 芋道源码
... ... @@ -23,7 +23,7 @@ import java.time.LocalDateTime;
23 23 @Builder
24 24 @NoArgsConstructor
25 25 @AllArgsConstructor
26   -public class TradeStatisticsDO extends BaseDO {
  26 +public class TradeStatisticsDO extends TenantBaseDO {
27 27  
28 28 /**
29 29 * 编号,主键自增
... ... @@ -69,7 +69,7 @@ public class TradeStatisticsDO extends BaseDO {
69 69  
70 70 /**
71 71 * 充值订单数
72   - *
  72 + * <p>
73 73 * 从 PayWalletRechargeDO 计算
74 74 */
75 75 private Integer rechargePayCount;
... ...
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/TradeStatisticsMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.statistics.dal.mysql.trade;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  4 +import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO;
  5 +import cn.iocoder.yudao.module.statistics.dal.dataobject.trade.TradeStatisticsDO;
  6 +import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeSummaryRespBO;
  7 +import org.apache.ibatis.annotations.Mapper;
  8 +import org.apache.ibatis.annotations.Param;
  9 +import org.apache.ibatis.annotations.Select;
  10 +
  11 +import java.time.LocalDateTime;
  12 +import java.util.List;
  13 +
  14 +/**
  15 + * 交易统计 Mapper
  16 + *
  17 + * @author owen
  18 + */
  19 +@Mapper
  20 +public interface TradeStatisticsMapper extends BaseMapperX<TradeStatisticsDO> {
  21 +
  22 + @Select("SELECT IFNULL(SUM(order_create_count), 0) AS count, IFNULL(SUM(order_pay_price), 0) AS summary " +
  23 + "FROM trade_statistics " +
  24 + "WHERE time BETWEEN #{beginTime} AND #{endTime} AND deleted = FALSE")
  25 + TradeSummaryRespBO selectOrderCreateCountSumAndOrderPayPriceSumByTimeBetween(@Param("beginTime") LocalDateTime beginTime,
  26 + @Param("endTime") LocalDateTime endTime);
  27 +
  28 + TradeTrendSummaryRespVO selectByTimeBetween(@Param("beginTime") LocalDateTime beginTime,
  29 + @Param("endTime") LocalDateTime endTime);
  30 +
  31 + List<TradeTrendSummaryRespVO> selectListByTimeBetween(@Param("beginTime") LocalDateTime beginTime,
  32 + @Param("endTime") LocalDateTime endTime);
  33 +}
... ...
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.statistics.service.trade;
  2 +
  3 +import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO;
  4 +import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeSummaryRespVO;
  5 +import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO;
  6 +
  7 +import java.time.LocalDateTime;
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * 交易统计 Service 接口
  12 + *
  13 + * @author owen
  14 + */
  15 +public interface TradeStatisticsService {
  16 +
  17 + /**
  18 + * 获得交易统计
  19 + *
  20 + * @return 统计数据对照
  21 + */
  22 + TradeStatisticsComparisonRespVO<TradeSummaryRespVO> getTradeSummaryComparison();
  23 +
  24 + /**
  25 + * 获得交易状况统计
  26 + *
  27 + * @return 统计数据对照
  28 + */
  29 + TradeStatisticsComparisonRespVO<TradeTrendSummaryRespVO> getTradeTrendSummaryComparison(LocalDateTime beginTime, LocalDateTime endTime);
  30 +
  31 + /**
  32 + * 获得交易状况明细
  33 + *
  34 + * @return 统计数据列表
  35 + */
  36 + List<TradeTrendSummaryRespVO> getTradeStatisticsList(LocalDateTime beginTime, LocalDateTime endTime);
  37 +}
... ...
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.statistics.service.trade;
  2 +
  3 +import cn.hutool.core.date.LocalDateTimeUtil;
  4 +import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO;
  5 +import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeSummaryRespVO;
  6 +import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO;
  7 +import cn.iocoder.yudao.module.statistics.convert.trade.TradeStatisticsConvert;
  8 +import cn.iocoder.yudao.module.statistics.dal.mysql.trade.TradeStatisticsMapper;
  9 +import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeSummaryRespBO;
  10 +import org.springframework.stereotype.Service;
  11 +import org.springframework.validation.annotation.Validated;
  12 +
  13 +import javax.annotation.Resource;
  14 +import java.time.Duration;
  15 +import java.time.LocalDateTime;
  16 +import java.time.LocalTime;
  17 +import java.time.temporal.TemporalAdjusters;
  18 +import java.util.List;
  19 +
  20 +/**
  21 + * 交易统计 Service 实现类
  22 + *
  23 + * @author owen
  24 + */
  25 +@Service
  26 +@Validated
  27 +public class TradeStatisticsServiceImpl implements TradeStatisticsService {
  28 +
  29 + @Resource
  30 + private TradeStatisticsMapper tradeStatisticsMapper;
  31 +
  32 + @Override
  33 + public TradeStatisticsComparisonRespVO<TradeSummaryRespVO> getTradeSummaryComparison() {
  34 + // 昨天的数据
  35 + TradeSummaryRespBO yesterdayData = getTradeSummaryByDays(-1);
  36 + // 前天的数据(用于对照昨天的数据)
  37 + TradeSummaryRespBO beforeYesterdayData = getTradeSummaryByDays(-2);
  38 +
  39 + // 本月数据;
  40 + TradeSummaryRespBO monthData = getTradeSummaryByMonths(0);
  41 + // 上月数据(用于对照本月的数据)
  42 + TradeSummaryRespBO lastMonthData = getTradeSummaryByMonths(-1);
  43 +
  44 + return TradeStatisticsConvert.INSTANCE.convert(yesterdayData, beforeYesterdayData, monthData, lastMonthData);
  45 + }
  46 +
  47 + @Override
  48 + public TradeStatisticsComparisonRespVO<TradeTrendSummaryRespVO> getTradeTrendSummaryComparison(LocalDateTime beginTime,
  49 + LocalDateTime endTime) {
  50 + // 统计数据
  51 + TradeTrendSummaryRespVO value = tradeStatisticsMapper.selectByTimeBetween(beginTime, endTime);
  52 + // 对照数据
  53 + LocalDateTime referenceBeginTime = beginTime.minus(Duration.between(beginTime, endTime));
  54 + TradeTrendSummaryRespVO reference = tradeStatisticsMapper.selectByTimeBetween(referenceBeginTime, beginTime);
  55 + return TradeStatisticsConvert.INSTANCE.convert(value, reference);
  56 + }
  57 +
  58 + @Override
  59 + public List<TradeTrendSummaryRespVO> getTradeStatisticsList(LocalDateTime beginTime, LocalDateTime endTime) {
  60 + return tradeStatisticsMapper.selectListByTimeBetween(beginTime, endTime);
  61 + }
  62 +
  63 + /**
  64 + * 统计指定日期的交易数据
  65 + *
  66 + * @param days 增加的天数
  67 + * @return 交易数据
  68 + */
  69 + private TradeSummaryRespBO getTradeSummaryByDays(int days) {
  70 + LocalDateTime date = LocalDateTime.now().plusDays(days);
  71 + return tradeStatisticsMapper.selectOrderCreateCountSumAndOrderPayPriceSumByTimeBetween(
  72 + LocalDateTimeUtil.beginOfDay(date), LocalDateTimeUtil.endOfDay(date));
  73 + }
  74 +
  75 + /**
  76 + * 统计指定月份的交易数据
  77 + *
  78 + * @param months 增加的月数
  79 + * @return 交易数据
  80 + */
  81 + private TradeSummaryRespBO getTradeSummaryByMonths(int months) {
  82 + // 月份开始时间
  83 + LocalDateTime beginOfMonth = LocalDateTime.now()
  84 + .plusMonths(months)
  85 + .with(TemporalAdjusters.firstDayOfMonth())
  86 + .with(LocalTime.MIN);
  87 + // 月份截止时间
  88 + LocalDateTime endOfToday = LocalDateTime.now()
  89 + .plusMonths(months)
  90 + .with(TemporalAdjusters.lastDayOfMonth())
  91 + .with(LocalTime.MAX);
  92 + return tradeStatisticsMapper.selectOrderCreateCountSumAndOrderPayPriceSumByTimeBetween(beginOfMonth, endOfToday);
  93 + }
  94 +
  95 +}
... ...
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/bo/TradeSummaryRespBO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.statistics.service.trade.bo;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * 交易统计 Resp BO
  7 + *
  8 + * @author owen
  9 + */
  10 +@Data
  11 +public class TradeSummaryRespBO {
  12 +
  13 + /**
  14 + * 数量
  15 + */
  16 + private Integer count;
  17 +
  18 + /**
  19 + * 合计
  20 + */
  21 + private Integer summary;
  22 +}
... ...
yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/TradeStatisticsMapper.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3 +<mapper namespace="cn.iocoder.yudao.module.statistics.dal.mysql.trade.TradeStatisticsMapper">
  4 + <select id="selectByTimeBetween"
  5 + resultType="cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO">
  6 + SELECT
  7 + -- 营业额 = 商品支付金额 + 充值金额
  8 + SUM(order_pay_price + recharge_pay_price) AS turnover,
  9 + SUM(order_pay_price) AS orderPayPrice,
  10 + SUM(recharge_pay_price) AS rechargePrice,
  11 + -- 支出金额 = 余额支付金额 + 支付佣金金额 + 商品退款金额
  12 + SUM(order_wallet_pay_price + brokerage_settlement_price + after_sale_refund_price) AS expensePrice,
  13 + SUM(order_wallet_pay_price) AS balancePrice,
  14 + SUM(brokerage_settlement_price) AS brokerageSettlementPrice,
  15 + SUM(after_sale_refund_price) AS orderRefundPrice
  16 + FROM trade_statistics
  17 + WHERE time BETWEEN #{beginTime} AND #{endTime}
  18 + AND deleted = FALSE
  19 + </select>
  20 +
  21 + <select id="selectListByTimeBetween"
  22 + resultType="cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO">
  23 + SELECT DATE_FORMAT(time, '%Y-%m-%d') AS date,
  24 + -- 营业额 = 商品支付金额 + 充值金额
  25 + SUM(order_pay_price + recharge_pay_price) AS turnover,
  26 + SUM(order_pay_price) AS orderPayPrice,
  27 + SUM(recharge_pay_price) AS rechargePrice,
  28 + -- 支出金额 = 余额支付金额 + 支付佣金金额 + 商品退款金额
  29 + SUM(order_wallet_pay_price + brokerage_settlement_price + after_sale_refund_price) AS expensePrice,
  30 + SUM(order_wallet_pay_price) AS balancePrice,
  31 + SUM(brokerage_settlement_price) AS brokerageSettlementPrice,
  32 + SUM(after_sale_refund_price) AS orderRefundPrice
  33 + FROM trade_statistics
  34 + WHERE time BETWEEN #{beginTime} AND #{endTime}
  35 + AND deleted = FALSE
  36 + GROUP BY date
  37 + </select>
  38 +</mapper>
... ...
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
... ... @@ -12,26 +12,26 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
12 12 public interface ErrorCodeConstants {
13 13  
14 14 // ========== Order 模块 1-011-000-000 ==========
15   - ErrorCode ORDER_ITEM_NOT_FOUND = new ErrorCode(1011000010, "交易订单项不存在");
16   - ErrorCode ORDER_NOT_FOUND = new ErrorCode(1011000011, "交易订单不存在");
17   - ErrorCode ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL = new ErrorCode(1011000012, "交易订单项更新售后状态失败,请重试");
18   - ErrorCode ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1011000013, "交易订单更新支付状态失败,订单不是【未支付】状态");
19   - ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1011000014, "交易订单更新支付状态失败,支付单编号不匹配");
20   - ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1011000015, "交易订单更新支付状态失败,支付单状态不是【支付成功】状态");
21   - ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1011000016, "交易订单更新支付状态失败,支付单金额不匹配");
22   - ErrorCode ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED = new ErrorCode(1011000017, "交易订单发货失败,订单不是【待发货】状态");
23   - ErrorCode ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED = new ErrorCode(1011000018, "交易订单收货失败,订单不是【待收货】状态");
24   - ErrorCode ORDER_COMMENT_FAIL_STATUS_NOT_COMPLETED = new ErrorCode(1011000019, "创建交易订单项的评价失败,订单不是【已完成】状态");
25   - ErrorCode ORDER_COMMENT_STATUS_NOT_FALSE = new ErrorCode(1011000020, "创建交易订单项的评价失败,订单已评价");
26   - ErrorCode ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE = new ErrorCode(1011000021, "交易订单发货失败,订单已退款或部分退款");
27   - ErrorCode ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1011000022, "交易订单发货失败,拼团未成功");
28   - ErrorCode ORDER_DELIVERY_FAIL_BARGAIN_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1011000023, "交易订单发货失败,砍价未成功");
29   - ErrorCode ORDER_DELIVERY_FAIL_DELIVERY_TYPE_NOT_EXPRESS = new ErrorCode(1011000024, "交易订单发货失败,发货类型不是快递");
30   - ErrorCode ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID = new ErrorCode(1011000025, "交易订单取消失败,订单不是【待支付】状态");
31   - ErrorCode ORDER_UPDATE_PRICE_FAIL_PAID = new ErrorCode(1011000026, "支付订单调价失败,原因:支付订单已付款,不能调价");
32   - ErrorCode ORDER_UPDATE_PRICE_FAIL_ALREADY = new ErrorCode(1011000027, "支付订单调价失败,原因:已经修改过价格");
33   - ErrorCode ORDER_UPDATE_PRICE_FAIL_PRICE_ERROR = new ErrorCode(1011000028, "支付订单调价失败,原因:调整后支付价格不能小于 0.01 元");
34   - ErrorCode ORDER_DELETE_FAIL_STATUS_NOT_CANCEL = new ErrorCode(1011000029, "交易订单删除失败,订单不是【已取消】状态");
  15 + ErrorCode ORDER_ITEM_NOT_FOUND = new ErrorCode(1_011_000_010, "交易订单项不存在");
  16 + ErrorCode ORDER_NOT_FOUND = new ErrorCode(1_011_000_011, "交易订单不存在");
  17 + ErrorCode ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL = new ErrorCode(1_011_000_012, "交易订单项更新售后状态失败,请重试");
  18 + ErrorCode ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1_011_000_013, "交易订单更新支付状态失败,订单不是【未支付】状态");
  19 + ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1_011_000_014, "交易订单更新支付状态失败,支付单编号不匹配");
  20 + ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1_011_000_015, "交易订单更新支付状态失败,支付单状态不是【支付成功】状态");
  21 + ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1_011_000_016, "交易订单更新支付状态失败,支付单金额不匹配");
  22 + ErrorCode ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED = new ErrorCode(1_011_000_017, "交易订单发货失败,订单不是【待发货】状态");
  23 + ErrorCode ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED = new ErrorCode(1_011_000_018, "交易订单收货失败,订单不是【待收货】状态");
  24 + ErrorCode ORDER_COMMENT_FAIL_STATUS_NOT_COMPLETED = new ErrorCode(1_011_000_019, "创建交易订单项的评价失败,订单不是【已完成】状态");
  25 + ErrorCode ORDER_COMMENT_STATUS_NOT_FALSE = new ErrorCode(1_011_000_020, "创建交易订单项的评价失败,订单已评价");
  26 + ErrorCode ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE = new ErrorCode(1_011_000_021, "交易订单发货失败,订单已退款或部分退款");
  27 + ErrorCode ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1_011_000_022, "交易订单发货失败,拼团未成功");
  28 + ErrorCode ORDER_DELIVERY_FAIL_BARGAIN_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1_011_000_023, "交易订单发货失败,砍价未成功");
  29 + ErrorCode ORDER_DELIVERY_FAIL_DELIVERY_TYPE_NOT_EXPRESS = new ErrorCode(1_011_000_024, "交易订单发货失败,发货类型不是快递");
  30 + ErrorCode ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID = new ErrorCode(1_011_000_025, "交易订单取消失败,订单不是【待支付】状态");
  31 + ErrorCode ORDER_UPDATE_PRICE_FAIL_PAID = new ErrorCode(1_011_000_026, "支付订单调价失败,原因:支付订单已付款,不能调价");
  32 + ErrorCode ORDER_UPDATE_PRICE_FAIL_ALREADY = new ErrorCode(1_011_000_027, "支付订单调价失败,原因:已经修改过价格");
  33 + ErrorCode ORDER_UPDATE_PRICE_FAIL_PRICE_ERROR = new ErrorCode(1_011_000_028, "支付订单调价失败,原因:调整后支付价格不能小于 0.01 元");
  34 + ErrorCode ORDER_DELETE_FAIL_STATUS_NOT_CANCEL = new ErrorCode(1_011_000_029, "交易订单删除失败,订单不是【已取消】状态");
35 35  
36 36 // ========== After Sale 模块 1-011-000-100 ==========
37 37 ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1_011_000_100, "售后单不存在");
... ... @@ -52,9 +52,9 @@ public interface ErrorCodeConstants {
52 52 ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1_011_002_000, "购物车项不存在");
53 53  
54 54 // ========== Price 相关 1-011-003-000 ============
55   - ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1011003000, "支付价格计算异常,原因:价格小于等于 0");
56   - ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1011003002, "计算快递运费异常,找不到对应的运费模板");
57   - ErrorCode PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER = new ErrorCode(1011003004, "参与秒杀、拼团、砍价的营销商品,无法使用优惠劵");
  55 + ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1_011_003_000, "支付价格计算异常,原因:价格小于等于 0");
  56 + ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1_011_003_002, "计算快递运费异常,找不到对应的运费模板");
  57 + ErrorCode PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER = new ErrorCode(1_011_003_004, "参与秒杀、拼团、砍价的营销商品,无法使用优惠劵");
58 58  
59 59 // ========== 物流 Express 模块 1-011-004-000 ==========
60 60 ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1_011_004_000, "快递公司不存在");
... ... @@ -72,21 +72,21 @@ public interface ErrorCodeConstants {
72 72 // ========== 物流 PICK_UP 模块 1-011-006-000 ==========
73 73 ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1_011_006_000, "自提门店不存在");
74 74  
75   - // ========== 分销用户 模块 1011007000 ==========
76   - ErrorCode BROKERAGE_USER_NOT_EXISTS = new ErrorCode(1011007000, "分销用户不存在");
77   - ErrorCode BROKERAGE_USER_FROZEN_PRICE_NOT_ENOUGH = new ErrorCode(1011007001, "用户冻结佣金({})数量不足");
78   - ErrorCode BROKERAGE_BIND_SELF = new ErrorCode(1011007002, "不能绑定自己");
79   - ErrorCode BROKERAGE_BIND_USER_NOT_ENABLED = new ErrorCode(1011007003, "绑定用户没有推广资格");
80   - ErrorCode BROKERAGE_BIND_CONDITION_ADMIN = new ErrorCode(1011007004, "仅可在后台绑定推广员");
81   - ErrorCode BROKERAGE_BIND_MODE_REGISTER = new ErrorCode(1011007005, "只有在注册时可以绑定");
82   - ErrorCode BROKERAGE_BIND_OVERRIDE = new ErrorCode(1011007006, "已绑定了推广人");
83   - ErrorCode BROKERAGE_BIND_LOOP = new ErrorCode(1011007007, "下级不能绑定自己的上级");
  75 + // ========== 分销用户 模块 1-011-007-000 ==========
  76 + ErrorCode BROKERAGE_USER_NOT_EXISTS = new ErrorCode(1_011_007_000, "分销用户不存在");
  77 + ErrorCode BROKERAGE_USER_FROZEN_PRICE_NOT_ENOUGH = new ErrorCode(1_011_007_001, "用户冻结佣金({})数量不足");
  78 + ErrorCode BROKERAGE_BIND_SELF = new ErrorCode(1_011_007_002, "不能绑定自己");
  79 + ErrorCode BROKERAGE_BIND_USER_NOT_ENABLED = new ErrorCode(1_011_007_003, "绑定用户没有推广资格");
  80 + ErrorCode BROKERAGE_BIND_CONDITION_ADMIN = new ErrorCode(1_011_007_004, "仅可在后台绑定推广员");
  81 + ErrorCode BROKERAGE_BIND_MODE_REGISTER = new ErrorCode(1_011_007_005, "只有在注册时可以绑定");
  82 + ErrorCode BROKERAGE_BIND_OVERRIDE = new ErrorCode(1_011_007_006, "已绑定了推广人");
  83 + ErrorCode BROKERAGE_BIND_LOOP = new ErrorCode(1_011_007_007, "下级不能绑定自己的上级");
84 84  
85 85  
86   - // ========== 分销提现 模块 1011008000 ==========
87   - ErrorCode BROKERAGE_WITHDRAW_NOT_EXISTS = new ErrorCode(1011008000, "佣金提现记录不存在");
88   - ErrorCode BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING = new ErrorCode(1011008001, "佣金提现记录状态不是审核中");
89   - ErrorCode BROKERAGE_WITHDRAW_MIN_PRICE = new ErrorCode(1011008002, "提现金额不能低于 {} 元");
90   - ErrorCode BROKERAGE_WITHDRAW_USER_BALANCE_NOT_ENOUGH = new ErrorCode(1011008003, "您当前最多可提现 {} 元");
  86 + // ========== 分销提现 模块 1-011-008-000 ==========
  87 + ErrorCode BROKERAGE_WITHDRAW_NOT_EXISTS = new ErrorCode(1_011_008_000, "佣金提现记录不存在");
  88 + ErrorCode BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING = new ErrorCode(1_011_008_001, "佣金提现记录状态不是审核中");
  89 + ErrorCode BROKERAGE_WITHDRAW_MIN_PRICE = new ErrorCode(1_011_008_002, "提现金额不能低于 {} 元");
  90 + ErrorCode BROKERAGE_WITHDRAW_USER_BALANCE_NOT_ENOUGH = new ErrorCode(1_011_008_003, "您当前最多可提现 {} 元");
91 91  
92 92 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/BrokerageUserConvert.java
... ... @@ -5,11 +5,13 @@ import cn.hutool.core.util.ObjUtil;
5 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 6 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
7 7 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user.BrokerageUserRespVO;
  8 +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO;
8 9 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserMySummaryRespVO;
9 10 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByUserCountRespVO;
10 11 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO;
11   -import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryRespBO;
12 12 import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO;
  13 +import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryRespBO;
  14 +import com.baomidou.mybatisplus.core.metadata.IPage;
13 15 import org.mapstruct.Mapper;
14 16 import org.mapstruct.MappingTarget;
15 17 import org.mapstruct.factory.Mappers;
... ... @@ -85,4 +87,11 @@ public interface BrokerageUserConvert {
85 87 .ifPresent(user -> respVO.setBrokeragePrice(user.getBrokeragePrice()).setFrozenPrice(user.getFrozenPrice()));
86 88 return respVO;
87 89 }
  90 +
  91 + default void copyTo(IPage<AppBrokerageUserChildSummaryRespVO> pageResult, Map<Long, MemberUserRespDTO> userMap) {
  92 + for (AppBrokerageUserChildSummaryRespVO vo : pageResult.getRecords()) {
  93 + Optional.ofNullable(userMap.get(vo.getId())).ifPresent(user ->
  94 + vo.setNickname(user.getNickname()).setAvatar(user.getAvatar()));
  95 + }
  96 + }
88 97 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/BrokerageUserMapper.java
... ... @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.trade.dal.mysql.brokerage;
2 2  
3 3 import cn.hutool.core.lang.Assert;
4 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.common.pojo.SortingField;
5 6 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
6 7 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
7 8 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user.BrokerageUserPageReqVO;
8   -import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryPageReqVO;
9 9 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO;
10 10 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByUserCountRespVO;
11 11 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO;
... ... @@ -139,8 +139,11 @@ public interface BrokerageUserMapper extends BaseMapperX&lt;BrokerageUserDO&gt; {
139 139 @Param("endTime") LocalDateTime endTime);
140 140  
141 141 IPage<AppBrokerageUserChildSummaryRespVO> selectSummaryPageByUserId(Page<?> page,
142   - @Param("param") AppBrokerageUserChildSummaryPageReqVO param,
143   - @Param("userId") Long userId);
  142 + @Param("ids") List<Long> ids,
  143 + @Param("bizType") Integer bizType,
  144 + @Param("status") Integer status,
  145 + @Param("bindUserIds") List<Long> bindUserIds,
  146 + @Param("sortingField") SortingField sortingField);
144 147  
145 148 default List<BrokerageUserDO> selectListByBindUserId(Long bindUserId) {
146 149 return selectList(BrokerageUserDO::getBindUserId, bindUserId);
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageRecordServiceImpl.java
... ... @@ -232,7 +232,7 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
232 232 }
233 233  
234 234 /**
235   - * 激动单条佣金记录
  235 + * 解冻单条佣金记录
236 236 *
237 237 * @param record 佣金记录
238 238 * @return 解冻是否成功
... ... @@ -258,9 +258,9 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
258 258 @Override
259 259 public List<UserBrokerageSummaryRespBO> getUserBrokerageSummaryListByUserId(Collection<Long> userIds,
260 260 Integer bizType, Integer status) {
261   - if (CollUtil.isEmpty(userIds)) {
262   - return Collections.emptyList();
263   - }
  261 + if (CollUtil.isEmpty(userIds)) {
  262 + return Collections.emptyList();
  263 + }
264 264 return brokerageRecordMapper.selectCountAndSumPriceByUserIdInAndBizTypeAndStatus(userIds, bizType, status);
265 265 }
266 266  
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageUserServiceImpl.java
... ... @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.lang.Assert;
5 5 import cn.hutool.core.util.ArrayUtil;
6 6 import cn.hutool.core.util.BooleanUtil;
  7 +import cn.hutool.core.util.StrUtil;
7 8 import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 9 import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
9 10 import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
... ... @@ -14,11 +15,14 @@ import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokera
14 15 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO;
15 16 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByUserCountRespVO;
16 17 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankPageReqVO;
  18 +import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageUserConvert;
17 19 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO;
18 20 import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
19 21 import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageUserMapper;
20 22 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageBindModeEnum;
21 23 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageEnabledConditionEnum;
  24 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
  25 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum;
22 26 import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
23 27 import com.baomidou.mybatisplus.core.metadata.IPage;
24 28 import org.springframework.stereotype.Service;
... ... @@ -221,7 +225,21 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
221 225  
222 226 @Override
223 227 public PageResult<AppBrokerageUserChildSummaryRespVO> getBrokerageUserChildSummaryPage(AppBrokerageUserChildSummaryPageReqVO pageReqVO, Long userId) {
224   - IPage<AppBrokerageUserChildSummaryRespVO> pageResult = brokerageUserMapper.selectSummaryPageByUserId(MyBatisUtils.buildPage(pageReqVO), pageReqVO, userId);
  228 + // 1.1 根据昵称过滤用户
  229 + List<Long> ids = StrUtil.isBlank(pageReqVO.getNickname())
  230 + ? Collections.emptyList()
  231 + : convertList(memberUserApi.getUserListByNickname(pageReqVO.getNickname()), MemberUserRespDTO::getId);
  232 + // 1.2 生成推广员编号列表
  233 + List<Long> bindUserIds = buildBindUserIdsByLevel(userId, pageReqVO.getLevel());
  234 + // 2. 分页查询
  235 + IPage<AppBrokerageUserChildSummaryRespVO> pageResult = brokerageUserMapper.selectSummaryPageByUserId(
  236 + MyBatisUtils.buildPage(pageReqVO), ids, BrokerageRecordBizTypeEnum.ORDER.getType(),
  237 + BrokerageRecordStatusEnum.SETTLEMENT.getStatus(), bindUserIds, pageReqVO.getSortingField()
  238 + );
  239 + // 3. 拼接数据并返回
  240 + List<Long> userIds = convertList(pageResult.getRecords(), AppBrokerageUserChildSummaryRespVO::getId);
  241 + Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
  242 + BrokerageUserConvert.INSTANCE.copyTo(pageResult, userMap);
225 243 return new PageResult<>(pageResult.getRecords(), pageResult.getTotal());
226 244 }
227 245  
... ... @@ -253,9 +271,9 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
253 271  
254 272 /**
255 273 * 判断是否为新用户
256   - *
  274 + * <p>
257 275 * 标准:注册时间在 30 秒内的,都算新用户
258   - *
  276 + * <p>
259 277 * 疑问:为什么通过这样的方式实现?
260 278 * 回答:因为注册在 member 模块,希望它和 trade 模块解耦,所以只能用这种约定的逻辑。
261 279 *
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
... ... @@ -5,7 +5,6 @@ import cn.hutool.core.lang.Assert;
5 5 import cn.hutool.core.map.MapUtil;
6 6 import cn.hutool.core.util.ObjectUtil;
7 7 import cn.hutool.core.util.RandomUtil;
8   -import cn.hutool.core.util.StrUtil;
9 8 import cn.hutool.extra.spring.SpringUtil;
10 9 import cn.iocoder.yudao.framework.common.core.KeyValue;
11 10 import cn.iocoder.yudao.framework.common.enums.TerminalEnum;
... ... @@ -667,7 +666,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
667 666 * 如果金额全部被退款,则取消订单
668 667 * 如果还有未被退款的金额,则无需取消订单
669 668 *
670   - * @param order 订单
  669 + * @param order 订单
671 670 * @param refundPrice 退款金额
672 671 */
673 672 @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.ADMIN_CANCEL_AFTER_SALE)
... ... @@ -774,11 +773,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
774 773  
775 774 @Override
776 775 public void updateOrderItemWhenAfterSaleCreate(Long id, Long afterSaleId) {
777   - // TODO @疯狂:这个可以直接在接口上,写 @Null 参数校验;
778   - if (afterSaleId == null) {
779   - throw new IllegalArgumentException(StrUtil.format("id({}) 退款发起,售后单编号不能为空", id));
780   - }
781   -
782 776 // 更新订单项
783 777 updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(),
784 778 TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), afterSaleId);
... ... @@ -787,11 +781,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
787 781 @Override
788 782 @Transactional(rollbackFor = Exception.class)
789 783 public void updateOrderItemWhenAfterSaleSuccess(Long id, Integer refundPrice) {
790   - // TODO @疯狂:这个可以直接在接口上,写 @Null 参数校验;
791   - if (refundPrice == null) {
792   - throw new IllegalArgumentException(StrUtil.format("id({}) 退款成功,退款金额不能为空", id));
793   - }
794   -
795 784 // 1. 更新订单项
796 785 updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(),
797 786 TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus(), null);
... ... @@ -821,8 +810,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
821 810 addUserPoint(order.getUserId(), orderItem.getUsePoint(), MemberPointBizTypeEnum.AFTER_SALE_REFUND_USED, orderItem.getAfterSaleId());
822 811  
823 812 // 5. 回滚经验:扣减用户经验
824   - // TODO @疯狂:orderRefundPrice 是不是改成 refundPrice?应该只退这个售后对应的经验
825   - getSelf().reduceUserExperienceAsync(order.getUserId(), orderRefundPrice, orderItem.getAfterSaleId());
  813 + getSelf().reduceUserExperienceAsync(order.getUserId(), refundPrice, orderItem.getAfterSaleId());
826 814  
827 815 // 6. 回滚佣金:更新分佣记录为已失效
828 816 getSelf().cancelBrokerageAsync(order.getUserId(), id);
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/resources/mapper/brokerage/BrokerageUserMapper.xml
... ... @@ -4,37 +4,38 @@
4 4  
5 5 <select id="selectSummaryPageByUserId"
6 6 resultType="cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO">
7   - SELECT bu.id, bu.bind_user_time AS brokerageTime, u.nickname, u.avatar,
8   - <!-- TODO @疯狂:biz_type、status 可以通过参数传入哇? -->
  7 + SELECT bu.id, bu.bind_user_time AS brokerageTime,
9 8 (SELECT SUM(price) FROM trade_brokerage_record r
10   - WHERE r.user_id = u.id AND biz_type = 1 AND r.status = 1 AND r.deleted = FALSE) AS brokeragePrice,
  9 + WHERE r.user_id = bu.id AND biz_type = #{bizType} AND r.status = #{status} AND r.deleted = FALSE) AS brokeragePrice,
11 10 (SELECT COUNT(1) FROM trade_brokerage_record r
12   - WHERE r.user_id = u.id AND biz_type = 1 AND r.status = 1 AND r.deleted = FALSE) AS brokerageOrderCount,
  11 + WHERE r.user_id = bu.id AND biz_type = #{bizType} AND r.status = #{status} AND r.deleted = FALSE) AS brokerageOrderCount,
13 12 (SELECT COUNT(1) FROM trade_brokerage_user c
14   - WHERE c.bind_user_id = u.id AND c.deleted = FALSE) AS brokerageUserCount
15   - FROM member_user AS u
16   - JOIN trade_brokerage_user AS bu ON bu.id = u.id
17   - <!-- TODO @疯狂:1)bind_user_id 是不是可以先改成内存查询出 userId 的集合,然后去 in 哈?2)nickname 是不是可以基于查询出来的 userId 对应的 nickname 在内存里过滤,主要是避免和 member_user 链表 -->
18   - <where>
19   - <if test="param.nickname != null and param.nickname != ''">
20   - AND u.nickname LIKE concat('', #{param.nickname}, '')
  13 + WHERE c.bind_user_id = bu.id AND c.deleted = FALSE) AS brokerageUserCount
  14 + FROM trade_brokerage_user AS bu
  15 + <where>
  16 + bu.deleted = false
  17 + <if test="ids != null and ids.size() > 0">
  18 + and bu.id in
  19 + <foreach collection="ids" open="(" item="id" separator="," close=")">
  20 + #{id}
  21 + </foreach>
21 22 </if>
22   - <if test="param.level == 1">
23   - AND bu.bind_user_id = #{userId}
24   - </if>
25   - <if test="param.level == 2">
26   - AND bu.bind_user_id IN (SELECT id FROM trade_brokerage_user c WHERE c.bind_user_id = #{userId})
  23 + <if test="bindUserIds != null and bindUserIds.size() > 0">
  24 + and bu.bind_user_id in
  25 + <foreach collection="bindUserIds" open="(" item="bindUserId" separator="," close=")">
  26 + #{bindUserId}
  27 + </foreach>
27 28 </if>
28 29 </where>
29 30 <choose>
30   - <when test="param.sortingField.field == 'userCount'">
31   - ORDER BY brokerageUserCount ${param.sortingField.order}
  31 + <when test="sortingField.field == 'userCount'">
  32 + ORDER BY brokerageUserCount ${sortingField.order}
32 33 </when>
33   - <when test="param.sortingField.field == 'orderCount'">
34   - ORDER BY brokerageOrderCount ${param.sortingField.order}
  34 + <when test="sortingField.field == 'orderCount'">
  35 + ORDER BY brokerageOrderCount ${sortingField.order}
35 36 </when>
36   - <when test="param.sortingField.field == 'price'">
37   - ORDER BY brokeragePrice ${param.sortingField.order}
  37 + <when test="sortingField.field == 'price'">
  38 + ORDER BY brokeragePrice ${sortingField.order}
38 39 </when>
39 40 <otherwise>
40 41 ORDER BY bu.bind_user_time DESC
... ...
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java
... ... @@ -10,10 +10,10 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
10 10 public interface ErrorCodeConstants {
11 11  
12 12 // ========== 用户相关 1-004-001-000 ============
13   - ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在");
14   - ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1004001001, "手机号未注册用户");
15   - ErrorCode USER_MOBILE_USED = new ErrorCode(1004001002, "修改手机失败,该手机号({})已经被使用");
16   - ErrorCode USER_POINT_NOT_ENOUGH = new ErrorCode(1004001003, "用户积分余额不足");
  13 + ErrorCode USER_NOT_EXISTS = new ErrorCode(1_004_001_000, "用户不存在");
  14 + ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1_004_001_001, "手机号未注册用户");
  15 + ErrorCode USER_MOBILE_USED = new ErrorCode(1_004_001_002, "修改手机失败,该手机号({})已经被使用");
  16 + ErrorCode USER_POINT_NOT_ENOUGH = new ErrorCode(1_004_001_003, "用户积分余额不足");
17 17  
18 18 // ========== AUTH 模块 1-004-003-000 ==========
19 19 ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1_004_003_000, "登录失败,账号密码不正确");
... ... @@ -40,7 +40,7 @@ public interface ErrorCodeConstants {
40 40 ErrorCode SIGN_IN_CONFIG_EXISTS = new ErrorCode(1_004_009_001, "签到天数规则已存在");
41 41  
42 42 //========== 签到配置 1-004-010-000 ==========
43   - ErrorCode SIGN_IN_RECORD_TODAY_EXISTS = new ErrorCode(1004010000,"今日已签到,请勿重复签到");
  43 + ErrorCode SIGN_IN_RECORD_TODAY_EXISTS = new ErrorCode(1_004_010_000,"今日已签到,请勿重复签到");
44 44  
45 45 //========== 用户等级 1-004-011-000 ==========
46 46 ErrorCode LEVEL_NOT_EXISTS = new ErrorCode(1_004_011_000, "用户等级不存在");
... ...
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
... ... @@ -21,19 +21,19 @@ public interface ErrorCodeConstants {
21 21 ErrorCode CHANNEL_EXIST_SAME_CHANNEL_ERROR = new ErrorCode(1_007_001_004, "已存在相同的渠道");
22 22  
23 23 // ========== ORDER 模块 1-007-002-000 ==========
24   - ErrorCode PAY_ORDER_NOT_FOUND = new ErrorCode(1007002000, "支付订单不存在");
25   - ErrorCode PAY_ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1007002001, "支付订单不处于待支付");
26   - ErrorCode PAY_ORDER_STATUS_IS_SUCCESS = new ErrorCode(1007002002, "订单已支付,请刷新页面");
27   - ErrorCode PAY_ORDER_IS_EXPIRED = new ErrorCode(1007002003, "支付订单已经过期");
28   - ErrorCode PAY_ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1007002004, "发起支付报错,错误码:{},错误提示:{}");
29   - ErrorCode PAY_ORDER_REFUND_FAIL_STATUS_ERROR = new ErrorCode(1007002005, "支付订单退款失败,原因:状态不是已支付或已退款");
  24 + ErrorCode PAY_ORDER_NOT_FOUND = new ErrorCode(1_007_002_000, "支付订单不存在");
  25 + ErrorCode PAY_ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1_007_002_001, "支付订单不处于待支付");
  26 + ErrorCode PAY_ORDER_STATUS_IS_SUCCESS = new ErrorCode(1_007_002_002, "订单已支付,请刷新页面");
  27 + ErrorCode PAY_ORDER_IS_EXPIRED = new ErrorCode(1_007_002_003, "支付订单已经过期");
  28 + ErrorCode PAY_ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1_007_002_004, "发起支付报错,错误码:{},错误提示:{}");
  29 + ErrorCode PAY_ORDER_REFUND_FAIL_STATUS_ERROR = new ErrorCode(1_007_002_005, "支付订单退款失败,原因:状态不是已支付或已退款");
30 30 ErrorCode ORDER_UPDATE_PRICE_FAIL_PAID = new ErrorCode(1_007_002_006, "支付订单调价失败,原因:支付订单已付款,不能调价");
31   - ErrorCode ORDER_UPDATE_PRICE_FAIL_EQUAL = new ErrorCode(1007002007, "支付订单调价失败,原因:价格没有变化");
  31 + ErrorCode ORDER_UPDATE_PRICE_FAIL_EQUAL = new ErrorCode(1_007_002_007, "支付订单调价失败,原因:价格没有变化");
32 32  
33 33 // ========== ORDER 模块(拓展单) 1-007-003-000 ==========
34   - ErrorCode PAY_ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1007003000, "支付交易拓展单不存在");
35   - ErrorCode PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING = new ErrorCode(1007003001, "支付交易拓展单不处于待支付");
36   - ErrorCode PAY_ORDER_EXTENSION_IS_PAID = new ErrorCode(1007003002, "订单已支付,请等待支付结果");
  34 + ErrorCode PAY_ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1_007_003_000, "支付交易拓展单不存在");
  35 + ErrorCode PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING = new ErrorCode(1_007_003_001, "支付交易拓展单不处于待支付");
  36 + ErrorCode PAY_ORDER_EXTENSION_IS_PAID = new ErrorCode(1_007_003_002, "订单已支付,请等待支付结果");
37 37  
38 38 // ========== 支付模块(退款) 1-007-006-000 ==========
39 39 ErrorCode REFUND_PRICE_EXCEED = new ErrorCode(1_007_006_000, "退款金额超过订单可退款金额");
... ... @@ -43,48 +43,48 @@ public interface ErrorCodeConstants {
43 43 ErrorCode REFUND_STATUS_IS_NOT_WAITING = new ErrorCode(1_007_006_005, "支付退款单不处于待退款");
44 44  
45 45 // ========== 钱包模块 1-007-007-000 ==========
46   - ErrorCode WALLET_NOT_FOUND = new ErrorCode(1007007000, "用户钱包不存在");
47   - ErrorCode WALLET_BALANCE_NOT_ENOUGH = new ErrorCode(1007007001, "钱包余额不足");
48   - ErrorCode WALLET_TRANSACTION_NOT_FOUND = new ErrorCode(1007007002, "未找到对应的钱包交易");
49   - ErrorCode WALLET_REFUND_EXIST = new ErrorCode(1007007003, "已经存在钱包退款");
50   - ErrorCode WALLET_FREEZE_PRICE_NOT_ENOUGH = new ErrorCode(1007007004, "钱包冻结余额不足");
  46 + ErrorCode WALLET_NOT_FOUND = new ErrorCode(1_007_007_000, "用户钱包不存在");
  47 + ErrorCode WALLET_BALANCE_NOT_ENOUGH = new ErrorCode(1_007_007_001, "钱包余额不足");
  48 + ErrorCode WALLET_TRANSACTION_NOT_FOUND = new ErrorCode(1_007_007_002, "未找到对应的钱包交易");
  49 + ErrorCode WALLET_REFUND_EXIST = new ErrorCode(1_007_007_003, "已经存在钱包退款");
  50 + ErrorCode WALLET_FREEZE_PRICE_NOT_ENOUGH = new ErrorCode(1_007_007_004, "钱包冻结余额不足");
51 51  
52 52 // ========== 钱包充值模块 1-007-008-000 ==========
53   - ErrorCode WALLET_RECHARGE_NOT_FOUND = new ErrorCode(1007008000, "钱包充值记录不存在");
54   - ErrorCode WALLET_RECHARGE_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1007008001, "钱包充值更新支付状态失败,钱包充值记录不是【未支付】状态");
55   - ErrorCode WALLET_RECHARGE_UPDATE_PAID_PAY_ORDER_ID_ERROR = new ErrorCode(1007008002, "钱包充值更新支付状态失败,支付单编号不匹配");
56   - ErrorCode WALLET_RECHARGE_UPDATE_PAID_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1007008003, "钱包充值更新支付状态失败,支付单状态不是【支付成功】状态");
57   - ErrorCode WALLET_RECHARGE_UPDATE_PAID_PAY_PRICE_NOT_MATCH = new ErrorCode(1007008004, "钱包充值更新支付状态失败,支付单金额不匹配");
58   - ErrorCode WALLET_RECHARGE_REFUND_FAIL_NOT_PAID = new ErrorCode(1007008005, "钱包发起退款失败,钱包充值订单未支付");
59   - ErrorCode WALLET_RECHARGE_REFUND_FAIL_REFUNDED = new ErrorCode(1007008006, "钱包发起退款失败,钱包充值订单已退款");
60   - ErrorCode WALLET_RECHARGE_REFUND_BALANCE_NOT_ENOUGH = new ErrorCode(1007008007, "钱包发起退款失败,钱包余额不足");
61   - ErrorCode WALLET_RECHARGE_REFUND_FAIL_REFUND_ORDER_ID_ERROR = new ErrorCode(1007008008, "钱包退款更新失败,钱包退款单编号不匹配");
62   - ErrorCode WALLET_RECHARGE_REFUND_FAIL_REFUND_NOT_FOUND = new ErrorCode(1007008009, "钱包退款更新失败,退款订单不存在");
63   - ErrorCode WALLET_RECHARGE_REFUND_FAIL_REFUND_PRICE_NOT_MATCH = new ErrorCode(1007008010, "钱包退款更新失败,退款单金额不匹配");
  53 + ErrorCode WALLET_RECHARGE_NOT_FOUND = new ErrorCode(1_007_008_000, "钱包充值记录不存在");
  54 + ErrorCode WALLET_RECHARGE_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1_007_008_001, "钱包充值更新支付状态失败,钱包充值记录不是【未支付】状态");
  55 + ErrorCode WALLET_RECHARGE_UPDATE_PAID_PAY_ORDER_ID_ERROR = new ErrorCode(1_007_008_002, "钱包充值更新支付状态失败,支付单编号不匹配");
  56 + ErrorCode WALLET_RECHARGE_UPDATE_PAID_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1_007_008_003, "钱包充值更新支付状态失败,支付单状态不是【支付成功】状态");
  57 + ErrorCode WALLET_RECHARGE_UPDATE_PAID_PAY_PRICE_NOT_MATCH = new ErrorCode(1_007_008_004, "钱包充值更新支付状态失败,支付单金额不匹配");
  58 + ErrorCode WALLET_RECHARGE_REFUND_FAIL_NOT_PAID = new ErrorCode(1_007_008_005, "钱包发起退款失败,钱包充值订单未支付");
  59 + ErrorCode WALLET_RECHARGE_REFUND_FAIL_REFUNDED = new ErrorCode(1_007_008_006, "钱包发起退款失败,钱包充值订单已退款");
  60 + ErrorCode WALLET_RECHARGE_REFUND_BALANCE_NOT_ENOUGH = new ErrorCode(1_007_008_007, "钱包发起退款失败,钱包余额不足");
  61 + ErrorCode WALLET_RECHARGE_REFUND_FAIL_REFUND_ORDER_ID_ERROR = new ErrorCode(1_007_008_008, "钱包退款更新失败,钱包退款单编号不匹配");
  62 + ErrorCode WALLET_RECHARGE_REFUND_FAIL_REFUND_NOT_FOUND = new ErrorCode(1_007_008_009, "钱包退款更新失败,退款订单不存在");
  63 + ErrorCode WALLET_RECHARGE_REFUND_FAIL_REFUND_PRICE_NOT_MATCH = new ErrorCode(1_007_008_010, "钱包退款更新失败,退款单金额不匹配");
64 64  
65 65 // ========== 转账模块 1-007-009-000 ==========
66   - ErrorCode PAY_TRANSFER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1007009000, "发起转账报错,错误码:{},错误提示:{}");
67   - ErrorCode PAY_TRANSFER_ALIPAY_LOGIN_ID_IS_EMPTY = new ErrorCode(1007009001, "支付宝登录 ID 不能为空");
68   - ErrorCode PAY_TRANSFER_ALIPAY_ACCOUNT_NAME_IS_EMPTY = new ErrorCode(1007009002, "支付宝账号名称不能为空");
69   - ErrorCode PAY_TRANSFER_NOT_FOUND = new ErrorCode(1007009003, "转账交易单不存在");
70   - ErrorCode PAY_TRANSFER_STATUS_IS_SUCCESS = new ErrorCode(1007009004, "转账单已成功转账");
71   - ErrorCode PAY_TRANSFER_STATUS_IS_NOT_WAITING = new ErrorCode(1007009005, "转账单不处于待转账");
72   - ErrorCode PAY_TRANSFER_STATUS_IS_NOT_PENDING = new ErrorCode(1007009006, "转账单不处于待转账或转账中");
73   - ErrorCode PAY_TRANSFER_EXTENSION_NOT_FOUND = new ErrorCode(1007009007, "转账交易拓展单不存在");
74   - ErrorCode PAY_TRANSFER_TYPE_AND_CHANNEL_NOT_MATCH = new ErrorCode(1007009008, "转账类型和转账渠道不匹配");
75   - ErrorCode PAY_TRANSFER_EXTENSION_STATUS_IS_NOT_PENDING = new ErrorCode(1007009009, "转账拓展单不处于待转账或转账中");
  66 + ErrorCode PAY_TRANSFER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1_007_009_000, "发起转账报错,错误码:{},错误提示:{}");
  67 + ErrorCode PAY_TRANSFER_ALIPAY_LOGIN_ID_IS_EMPTY = new ErrorCode(1_007_009_001, "支付宝登录 ID 不能为空");
  68 + ErrorCode PAY_TRANSFER_ALIPAY_ACCOUNT_NAME_IS_EMPTY = new ErrorCode(1_007_009_002, "支付宝账号名称不能为空");
  69 + ErrorCode PAY_TRANSFER_NOT_FOUND = new ErrorCode(1_007_009_003, "转账交易单不存在");
  70 + ErrorCode PAY_TRANSFER_STATUS_IS_SUCCESS = new ErrorCode(1_007_009_004, "转账单已成功转账");
  71 + ErrorCode PAY_TRANSFER_STATUS_IS_NOT_WAITING = new ErrorCode(1_007_009_005, "转账单不处于待转账");
  72 + ErrorCode PAY_TRANSFER_STATUS_IS_NOT_PENDING = new ErrorCode(1_007_009_006, "转账单不处于待转账或转账中");
  73 + ErrorCode PAY_TRANSFER_EXTENSION_NOT_FOUND = new ErrorCode(1_007_009_007, "转账交易拓展单不存在");
  74 + ErrorCode PAY_TRANSFER_TYPE_AND_CHANNEL_NOT_MATCH = new ErrorCode(1_007_009_008, "转账类型和转账渠道不匹配");
  75 + ErrorCode PAY_TRANSFER_EXTENSION_STATUS_IS_NOT_PENDING = new ErrorCode(1_007_009_009, "转账拓展单不处于待转账或转账中");
76 76  
77 77 // ========== 示例订单 1-007-900-000 ==========
78   - ErrorCode DEMO_ORDER_NOT_FOUND = new ErrorCode(1007900000, "示例订单不存在");
79   - ErrorCode DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1007900001, "示例订单更新支付状态失败,订单不是【未支付】状态");
80   - ErrorCode DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1007900002, "示例订单更新支付状态失败,支付单编号不匹配");
81   - ErrorCode DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1007900003, "示例订单更新支付状态失败,支付单状态不是【支付成功】状态");
82   - ErrorCode DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1007900004, "示例订单更新支付状态失败,支付单金额不匹配");
83   - ErrorCode DEMO_ORDER_REFUND_FAIL_NOT_PAID = new ErrorCode(1007900005, "发起退款失败,示例订单未支付");
84   - ErrorCode DEMO_ORDER_REFUND_FAIL_REFUNDED = new ErrorCode(1007900006, "发起退款失败,示例订单已退款");
85   - ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_NOT_FOUND = new ErrorCode(1007900007, "发起退款失败,退款订单不存在");
86   - ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_NOT_SUCCESS = new ErrorCode(1007900008, "发起退款失败,退款订单未退款成功");
87   - ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR = new ErrorCode(1007900009, "发起退款失败,退款单编号不匹配");
88   - ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_PRICE_NOT_MATCH = new ErrorCode(1007900010, "发起退款失败,退款单金额不匹配");
  78 + ErrorCode DEMO_ORDER_NOT_FOUND = new ErrorCode(1_007_900_000, "示例订单不存在");
  79 + ErrorCode DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1_007_900_001, "示例订单更新支付状态失败,订单不是【未支付】状态");
  80 + ErrorCode DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1_007_900_002, "示例订单更新支付状态失败,支付单编号不匹配");
  81 + ErrorCode DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1_007_900_003, "示例订单更新支付状态失败,支付单状态不是【支付成功】状态");
  82 + ErrorCode DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1_007_900_004, "示例订单更新支付状态失败,支付单金额不匹配");
  83 + ErrorCode DEMO_ORDER_REFUND_FAIL_NOT_PAID = new ErrorCode(1_007_900_005, "发起退款失败,示例订单未支付");
  84 + ErrorCode DEMO_ORDER_REFUND_FAIL_REFUNDED = new ErrorCode(1_007_900_006, "发起退款失败,示例订单已退款");
  85 + ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_NOT_FOUND = new ErrorCode(1_007_900_007, "发起退款失败,退款订单不存在");
  86 + ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_NOT_SUCCESS = new ErrorCode(1_007_900_008, "发起退款失败,退款订单未退款成功");
  87 + ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR = new ErrorCode(1_007_900_009, "发起退款失败,退款单编号不匹配");
  88 + ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_PRICE_NOT_MATCH = new ErrorCode(1_007_900_010, "发起退款失败,退款单金额不匹配");
89 89  
90 90 }
... ...
yudao-server/pom.xml
... ... @@ -85,6 +85,11 @@
85 85 <artifactId>yudao-module-trade-biz</artifactId>
86 86 <version>${revision}</version>
87 87 </dependency>
  88 + <dependency>
  89 + <groupId>cn.iocoder.boot</groupId>
  90 + <artifactId>yudao-module-statistics-biz</artifactId>
  91 + <version>${revision}</version>
  92 + </dependency>
88 93  
89 94 <!-- spring boot 配置所需依赖 -->
90 95 <dependency>
... ...