Commit b376de1ad30e2a30b02b0e4da1543df4adb72742
Committed by
Gitee
!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<BrokerageUserDO> { |
| 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> | ... | ... |