From 75afab1f86c00f4e465ea6fd94de7fbd66bb5a5b Mon Sep 17 00:00:00 2001 From: chenchen <934298133@qq.com> Date: Sun, 25 Jun 2023 23:08:07 +0800 Subject: [PATCH 01/17] =?UTF-8?q?=E5=94=AE=E5=90=8E=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../enums/aftersale/AfterSaleOperateTypeEnum.java | 15 +++++++++------ .../dataobject/aftersale/TradeAfterSaleLogDO.java | 1 - ...iguration.java => AfterSaleConfiguration.java} | 5 ++--- .../aftersalelog/core/aop/AfterSaleLogAspect.java | 7 ++++--- .../aftersale/TradeAfterSaleServiceImpl.java | 11 +---------- 5 files changed, 16 insertions(+), 23 deletions(-) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/config/{AfterSaleLogConfiguration.java => AfterSaleConfiguration.java} (76%) diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleOperateTypeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleOperateTypeEnum.java index da41c2b93..7e374e335 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleOperateTypeEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleOperateTypeEnum.java @@ -1,26 +1,29 @@ package cn.iocoder.yudao.module.trade.enums.aftersale; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + /** * 售后操作类型的枚举 * * @author 陈賝 * @since 2023/6/13 13:53 */ -// TODO @chenchen:可以 lombok 简化构造方法,和 get 方法 +@RequiredArgsConstructor +@Getter public enum AfterSaleOperateTypeEnum { /** * 用户申请 */ - APPLY("用户申请"), + APPLY(0, "用户申请"), ; + // 类型 + private final Integer type; + // 描述 private final String description; - AfterSaleOperateTypeEnum(String description) { - this.description = description; - } - public String description() { return description; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleLogDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleLogDO.java index 56a0f0f32..168eb741f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleLogDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleLogDO.java @@ -49,7 +49,6 @@ public class TradeAfterSaleLogDO extends BaseDO { * 关联 {@link TradeAfterSaleDO#getId()} */ private Long afterSaleId; - // todo @CHENCHEN: 改成 Integer 哈;主要未来改文案,不好洗 log 存的字段; /** * 操作类型 * diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/config/AfterSaleLogConfiguration.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/config/AfterSaleConfiguration.java similarity index 76% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/config/AfterSaleLogConfiguration.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/config/AfterSaleConfiguration.java index 1c382d24f..7c7fc7f4f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/config/AfterSaleLogConfiguration.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/config/AfterSaleConfiguration.java @@ -4,15 +4,14 @@ import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.aop.AfterSaleLo import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -// TODO @chenchen:改成 aftersale 好点哈; /** - * trade 模块的 afterSaleLog 组件的 Configuration + * trade 模块的 afterSale 组件的 Configuration * * @author 陈賝 * @since 2023/6/18 11:09 */ @Configuration(proxyBeanMethods = false) -public class AfterSaleLogConfiguration { +public class AfterSaleConfiguration { @Bean public AfterSaleLogAspect afterSaleLogAspect() { diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java index 93186edf1..5ff16d38a 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java @@ -31,12 +31,13 @@ import static java.util.Arrays.asList; @Aspect public class AfterSaleLogAspect { + private final static String OPERATE_TYPE = "operateType"; + private final static String ID = "id"; + private final static String CONTENT = "content"; + @Resource private AfterSaleLogService afterSaleLogService; - // TODO chenchen: 这个分 3 行把; - private final static String OPERATE_TYPE = "operateType", ID = "id", CONTENT = "content"; - /** * 切面存入日志 */ diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java index fc86f230a..a5fa11c9e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java @@ -398,14 +398,6 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa this.createLog(logDTO); } - // TODO @CHENCHEN:这个注释,写在接口就好了,补充重复写哈;@date 应该是 @since - /** - * 日志记录 - * - * @param logDTO 日志记录 - * @author 陈賝 - * @date 2023/6/12 14:18 - */ @Override @Async public void createLog(TradeAfterSaleLogCreateReqDTO logDTO) { @@ -417,8 +409,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa .setOperateType(logDTO.getOperateType()) .setContent(logDTO.getContent()); tradeAfterSaleLogMapper.insert(afterSaleLog); - // TODO @CHENCHEN:代码排版哈;空格要正确 - }catch (Exception exception){ + } catch (Exception exception) { log.error("[createLog][request({}) 日志记录错误]", toJsonString(logDTO), exception); } } From 2865c28a9f8768f805db262da10fdc5bdbb71477 Mon Sep 17 00:00:00 2001 From: chenchen <934298133@qq.com> Date: Tue, 27 Jun 2023 23:07:06 +0800 Subject: [PATCH 02/17] =?UTF-8?q?=E5=94=AE=E5=90=8E=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=8Cmap->=E6=8A=BD=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aftersale/TradeAfterSaleLogDO.java | 2 +- .../core/aop/AfterSaleLogAspect.java | 65 +++++++++++++------ .../dto/TradeAfterSaleLogCreateReqDTO.java | 2 +- .../aftersale/TradeAfterSaleServiceImpl.java | 2 +- 4 files changed, 47 insertions(+), 24 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleLogDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleLogDO.java index 168eb741f..1e18bf6e5 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleLogDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleLogDO.java @@ -54,7 +54,7 @@ public class TradeAfterSaleLogDO extends BaseDO { * * 枚举 {@link AfterSaleOperateTypeEnum} */ - private String operateType; + private Integer operateType; /** * 操作明细 */ diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java index 5ff16d38a..cdb2c0a48 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java @@ -4,6 +4,7 @@ import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleOperateTypeEnum; import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.annotations.AfterSaleLog; import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogCreateReqDTO; import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service.AfterSaleLogService; @@ -47,13 +48,12 @@ public class AfterSaleLogAspect { // 日志对象拼接 Integer userType = WebFrameworkUtils.getLoginUserType(); Long id = WebFrameworkUtils.getLoginUserId(); - Map formatObj = spelFormat(joinPoint, info); TradeAfterSaleLogCreateReqDTO dto = new TradeAfterSaleLogCreateReqDTO() .setUserId(id) .setUserType(userType) - .setAfterSaleId(MapUtil.getLong(formatObj, ID)) - .setOperateType(MapUtil.getStr(formatObj, OPERATE_TYPE)) - .setContent(MapUtil.getStr(formatObj, CONTENT)); + .setAfterSaleId(getAfterSaleId(joinPoint, info, afterSaleLog.id())) + .setOperateType(afterSaleLog.operateType().getType()) + .setContent(getContent(joinPoint, info, afterSaleLog)); // 异步存入数据库 afterSaleLogService.createLog(dto); } catch (Exception exception) { @@ -64,26 +64,49 @@ public class AfterSaleLogAspect { /** * 获取描述信息 */ - public static Map spelFormat(JoinPoint joinPoint, Object info) { + private static Map spelFormat(JoinPoint joinPoint, Object info) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); AfterSaleLog afterSaleLogPoint = signature.getMethod().getAnnotation(AfterSaleLog.class); - HashMap result = Maps.newHashMapWithExpectedSize(2); - Map spelMap = SpringExpressionUtils.parseExpression(joinPoint, info, + return SpringExpressionUtils.parseExpression(joinPoint, info, asList(afterSaleLogPoint.id(), afterSaleLogPoint.content())); - // TODO @chenchen:是不是抽成 3 个方法好点;毕竟 map 太抽象了;; - // 售后ID - String id = MapUtil.getStr(spelMap, afterSaleLogPoint.id()); - result.put(ID, id); - // 操作类型 - String operateType = afterSaleLogPoint.operateType().description(); - result.put(OPERATE_TYPE, operateType); - // 日志内容 - String content = MapUtil.getStr(spelMap, afterSaleLogPoint.content()); - if (ObjectUtil.isNotNull(afterSaleLogPoint.operateType())) { - content += operateType; - } - result.put(CONTENT, content); - return result; } + /** + * 获取售后ID + */ + private static Long getAfterSaleId(JoinPoint joinPoint, Object info, String spel) { + Map spelMap = spelFormat(joinPoint, info); + return MapUtil.getLong(spelMap, spel); + } + + /** + * 获取解析后的日志内容 + */ + private static String getContent(JoinPoint joinPoint, Object info, AfterSaleLog afterSaleLog) { + Map spelMap = spelFormat(joinPoint, info); + StringBuilder content = new StringBuilder().append(MapUtil.getStr(spelMap, afterSaleLog.content())); + AfterSaleOperateTypeEnum afterSaleOperateTypeEnum = afterSaleLog.operateType(); + return ObjectUtil.isNotNull(afterSaleOperateTypeEnum) ? + content.append(afterSaleOperateTypeEnum.getDescription()).toString() : content.toString(); + } + + // public static Map spelFormat(JoinPoint joinPoint, Object info) { + // MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + // AfterSaleLog afterSaleLogPoint = signature.getMethod().getAnnotation(AfterSaleLog.class); + // HashMap result = Maps.newHashMapWithExpectedSize(2); + // Map spelMap = SpringExpressionUtils.parseExpression(joinPoint, info, + // asList(afterSaleLogPoint.id(), afterSaleLogPoint.content())); + // + // // 售后ID + // result.put(ID, MapUtil.getLong(spelMap, afterSaleLogPoint.id())); + // // 操作类型 + // result.put(OPERATE_TYPE, afterSaleLogPoint.operateType().getType()); + // // 日志内容 + // StringBuilder content = new StringBuilder().append(MapUtil.getStr(spelMap, afterSaleLogPoint.content())); + // + // result.put(CONTENT, ObjectUtil.isNotNull(afterSaleLogPoint.operateType()) ? + // content.append(afterSaleLogPoint.operateType().getDescription()).toString() : content.toString()); + // return result; + // } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/dto/TradeAfterSaleLogCreateReqDTO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/dto/TradeAfterSaleLogCreateReqDTO.java index 7beac68cf..1b2c640a2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/dto/TradeAfterSaleLogCreateReqDTO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/dto/TradeAfterSaleLogCreateReqDTO.java @@ -37,7 +37,7 @@ public class TradeAfterSaleLogCreateReqDTO { /** * 操作类型 */ - private String operateType; + private Integer operateType; /** * 操作明细 */ diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java index a5fa11c9e..1ebfe5664 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java @@ -393,7 +393,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa .setUserId(userId) .setUserType(userType) .setAfterSaleId(afterSale.getId()) - .setOperateType(afterStatus.toString()); + .setOperateType(afterStatus); // TODO 废弃,待删除 this.createLog(logDTO); } From eaeb435459a42826980184a3fdf9ba7a810a4d56 Mon Sep 17 00:00:00 2001 From: chenchen <934298133@qq.com> Date: Thu, 29 Jun 2023 21:44:36 +0800 Subject: [PATCH 03/17] =?UTF-8?q?=E4=BA=A4=E6=98=93=E6=97=A5=E5=BF=97sql?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/optional/mall_trade_log.sql | 62 +++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 sql/mysql/optional/mall_trade_log.sql diff --git a/sql/mysql/optional/mall_trade_log.sql b/sql/mysql/optional/mall_trade_log.sql new file mode 100644 index 000000000..b3367416b --- /dev/null +++ b/sql/mysql/optional/mall_trade_log.sql @@ -0,0 +1,62 @@ +/* + Navicat Premium Data Transfer + + + Source Server : 127.0.0.1 MySQL + Source Server Type : MySQL + Source Server Version : 80030 + Source Host : localhost:3306 + + Target Server Type : MySQL + Target Server Version : 80030 + File Encoding : 65001 + + Date: 29/06/2023 21:05:23 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for trade_after_sale_log +-- ---------------------------- +DROP TABLE IF EXISTS `trade_after_sale_log`; +CREATE TABLE `trade_after_sale_log` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', + `after_sale_id` bigint NOT NULL COMMENT '售后服务单号', + `content` varchar(255) CHARACTER SET utf8mb4 NOT NULL COMMENT '售后服务信息', + `operate_type` varchar(255) NOT NULL COMMENT '操作类型', + `user_id` bigint NOT NULL COMMENT '创建者ID', + `user_type` int NOT NULL COMMENT '创建者类型', + `creator` varchar(255) CHARACTER SET utf8mb4 DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='售后日志'; + +-- ---------------------------- +-- Table structure for trade_order_log +-- ---------------------------- +DROP TABLE IF EXISTS `trade_order_log`; +CREATE TABLE `trade_order_log` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', + `order_id` bigint NOT NULL COMMENT '订单号', + `content` varchar(255) CHARACTER SET utf8mb4 NOT NULL COMMENT '订单日志信息', + `operate_type` varchar(255) CHARACTER SET utf8mb4 NOT NULL COMMENT '操作类型', + `user_id` bigint NOT NULL COMMENT '创建者ID', + `user_type` int NOT NULL COMMENT '创建者类型', + `creator` varchar(255) CHARACTER SET utf8mb4 DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单日志'; + +SET FOREIGN_KEY_CHECKS = 1; From f492797fba881ccdffb11a624e79ccb7c3f988ca Mon Sep 17 00:00:00 2001 From: chenchen <934298133@qq.com> Date: Thu, 6 Jul 2023 16:04:18 +0800 Subject: [PATCH 04/17] =?UTF-8?q?update=20=E5=94=AE=E5=90=8E=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/aop/AfterSaleLogAspect.java | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java index cdb2c0a48..68444936e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java @@ -32,10 +32,6 @@ import static java.util.Arrays.asList; @Aspect public class AfterSaleLogAspect { - private final static String OPERATE_TYPE = "operateType"; - private final static String ID = "id"; - private final static String CONTENT = "content"; - @Resource private AfterSaleLogService afterSaleLogService; @@ -90,23 +86,4 @@ public class AfterSaleLogAspect { content.append(afterSaleOperateTypeEnum.getDescription()).toString() : content.toString(); } - // public static Map spelFormat(JoinPoint joinPoint, Object info) { - // MethodSignature signature = (MethodSignature) joinPoint.getSignature(); - // AfterSaleLog afterSaleLogPoint = signature.getMethod().getAnnotation(AfterSaleLog.class); - // HashMap result = Maps.newHashMapWithExpectedSize(2); - // Map spelMap = SpringExpressionUtils.parseExpression(joinPoint, info, - // asList(afterSaleLogPoint.id(), afterSaleLogPoint.content())); - // - // // 售后ID - // result.put(ID, MapUtil.getLong(spelMap, afterSaleLogPoint.id())); - // // 操作类型 - // result.put(OPERATE_TYPE, afterSaleLogPoint.operateType().getType()); - // // 日志内容 - // StringBuilder content = new StringBuilder().append(MapUtil.getStr(spelMap, afterSaleLogPoint.content())); - // - // result.put(CONTENT, ObjectUtil.isNotNull(afterSaleLogPoint.operateType()) ? - // content.append(afterSaleLogPoint.operateType().getDescription()).toString() : content.toString()); - // return result; - // } - } From 284506b3561205a8bb68631a464c3c2adb59a985 Mon Sep 17 00:00:00 2001 From: chenchen <934298133@qq.com> Date: Fri, 7 Jul 2023 14:06:32 +0800 Subject: [PATCH 05/17] =?UTF-8?q?mall=20=E4=B8=8B=E5=8D=95=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../enums/aftersale/OrderOperateTypeEnum.java | 30 +++++++ .../app/order/AppTradeOrderController.java | 5 ++ .../dal/dataobject/order/OrderLogDO.java | 51 +++++++++++ .../trade/dal/mysql/order/OrderLogMapper.java | 16 ++++ .../order/config/TradeOrderConfig.java | 9 ++ .../order/core/annotations/OrderLog.java | 33 +++++++ .../order/core/aop/OrderLogAspect.java | 86 +++++++++++++++++++ .../core/dto/TradeOrderLogCreateReqDTO.java | 46 ++++++++++ .../order/core/service/OrderLogService.java | 22 +++++ .../service/order/TradeOrderServiceImpl.java | 31 ++++++- 10 files changed, 328 insertions(+), 1 deletion(-) create mode 100644 yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/OrderOperateTypeEnum.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/OrderLogDO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/OrderLogMapper.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/annotations/OrderLog.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/aop/OrderLogAspect.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/dto/TradeOrderLogCreateReqDTO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/service/OrderLogService.java diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/OrderOperateTypeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/OrderOperateTypeEnum.java new file mode 100644 index 000000000..04b137f8a --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/OrderOperateTypeEnum.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.trade.enums.aftersale; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * 订单操作类型的枚举 + * + * @author 陈賝 + * @since 2023/7/6 15:31 + */ +@RequiredArgsConstructor +@Getter +public enum OrderOperateTypeEnum { + + /** + * 用户下单 + */ + ORDER(0, "用户下单"), + ; + + // 类型 + private final Integer type; + // 描述 + private final String description; + + public String description() { + return description; + } +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java index 6567e3169..2428922e0 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java @@ -14,8 +14,12 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderI import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleOperateTypeEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.OrderOperateTypeEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; +import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.annotations.AfterSaleLog; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; +import cn.iocoder.yudao.module.trade.framework.order.core.annotations.OrderLog; import cn.iocoder.yudao.module.trade.service.order.TradeOrderService; import com.google.common.collect.Maps; import io.swagger.v3.oas.annotations.Operation; @@ -66,6 +70,7 @@ public class AppTradeOrderController { @PostMapping("/create") @Operation(summary = "创建订单") @PreAuthenticated + @OrderLog(id = "#info.id", content = "'创建订单:支付订单编号['+#info.payOrderId+'], 订单编号['+#info.id+'], '", operateType = OrderOperateTypeEnum.ORDER) public CommonResult createOrder(@RequestBody AppTradeOrderCreateReqVO createReqVO) { TradeOrderDO order = tradeOrderService.createOrder(getLoginUserId(), getClientIP(), createReqVO); return success(new AppTradeOrderCreateRespVO().setId(order.getId()).setPayOrderId(order.getPayOrderId())); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/OrderLogDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/OrderLogDO.java new file mode 100644 index 000000000..c65acfe06 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/OrderLogDO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.trade.dal.dataobject.order; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 订单日志 DO + * + * @author 陈賝 + */ +@TableName("trade_order_log") +@KeySequence("trade_order_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OrderLogDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 订单号 + */ + private Long orderId; + /** + * 订单日志信息 + */ + private String content; + /** + * 操作类型 + */ + private Integer operateType; + /** + * 创建者ID + */ + private Long userId; + /** + * 创建者类型 + */ + private Integer userType; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/OrderLogMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/OrderLogMapper.java new file mode 100644 index 000000000..868a962d5 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/OrderLogMapper.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.trade.dal.mysql.order; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.OrderLogDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 订单日志 Mapper + * + * @author 陈賝 + */ +@Mapper +public interface OrderLogMapper extends BaseMapperX { + + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/config/TradeOrderConfig.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/config/TradeOrderConfig.java index 715169275..86466fa92 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/config/TradeOrderConfig.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/config/TradeOrderConfig.java @@ -1,9 +1,13 @@ package cn.iocoder.yudao.module.trade.framework.order.config; +import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.aop.AfterSaleLogAspect; +import cn.iocoder.yudao.module.trade.framework.order.core.aop.OrderLogAspect; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; // TODO @LeeYan9: 可以直接给 TradeOrderProperties 一个 @Component生效哈 + /** * @author LeeYan9 * @since 2022-09-15 @@ -11,4 +15,9 @@ import org.springframework.context.annotation.Configuration; @Configuration @EnableConfigurationProperties(TradeOrderProperties.class) public class TradeOrderConfig { + + @Bean + public OrderLogAspect orderLogAspect() { + return new OrderLogAspect(); + } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/annotations/OrderLog.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/annotations/OrderLog.java new file mode 100644 index 000000000..994a6a368 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/annotations/OrderLog.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.trade.framework.order.core.annotations; + +import cn.iocoder.yudao.module.trade.enums.aftersale.OrderOperateTypeEnum; + +import java.lang.annotation.*; + +/** + * 订单日志AOP注解 + * + * @author 陈賝 + * @since 2023/7/6 15:37 + */ +@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface OrderLog { + + /** + * 日志内容 + */ + String content(); + + /** + * 订单编号 + */ + String id(); + + /** + * 操作类型 + */ + OrderOperateTypeEnum operateType(); + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/aop/OrderLogAspect.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/aop/OrderLogAspect.java new file mode 100644 index 000000000..460649c43 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/aop/OrderLogAspect.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.trade.framework.order.core.aop; + + +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.module.trade.enums.aftersale.OrderOperateTypeEnum; +import cn.iocoder.yudao.module.trade.framework.order.core.annotations.OrderLog; +import cn.iocoder.yudao.module.trade.framework.order.core.dto.TradeOrderLogCreateReqDTO; +import cn.iocoder.yudao.module.trade.framework.order.core.service.OrderLogService; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; + +import javax.annotation.Resource; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; +import static java.util.Arrays.asList; + +/** + * 记录订单操作日志的 AOP 切面 + * + * @author 陈賝 + * @since 2023/6/13 13:54 + */ +@Slf4j +@Aspect +public class OrderLogAspect { + + @Resource + private OrderLogService orderLogService; + + @AfterReturning(pointcut = "@annotation(orderLog)", returning = "info") + public void doAfterReturning(JoinPoint joinPoint, OrderLog orderLog, Object info) { + try { + // 日志对象拼接 + Integer userType = WebFrameworkUtils.getLoginUserType(); + Long id = WebFrameworkUtils.getLoginUserId(); + TradeOrderLogCreateReqDTO dto = new TradeOrderLogCreateReqDTO() + .setUserId(id) + .setUserType(userType) + .setOrderId(getAfterSaleId(joinPoint, info, orderLog.id())) + .setOperateType(orderLog.operateType().getType()) + .setContent(getContent(joinPoint, info, orderLog)); + // 异步存入数据库 + orderLogService.createLog(dto); + } catch (Exception exception) { + log.error("[doAfterReturning][orderLog({}) 订单日志错误]", toJsonString(orderLog), exception); + } + } + + /** + * 获取描述信息 + */ + private static Map spelFormat(JoinPoint joinPoint, Object info) { + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + OrderLog afterSaleLogPoint = signature.getMethod().getAnnotation(OrderLog.class); + return SpringExpressionUtils.parseExpression(joinPoint, info, + asList(afterSaleLogPoint.id(), afterSaleLogPoint.content())); + } + + + /** + * 获取订单ID + */ + private static Long getAfterSaleId(JoinPoint joinPoint, Object info, String spel) { + Map spelMap = spelFormat(joinPoint, info); + return MapUtil.getLong(spelMap, spel); + } + + /** + * 获取解析后的日志内容 + */ + private static String getContent(JoinPoint joinPoint, Object info, OrderLog afterSaleLog) { + Map spelMap = spelFormat(joinPoint, info); + StringBuilder content = new StringBuilder().append(MapUtil.getStr(spelMap, afterSaleLog.content())); + OrderOperateTypeEnum operateTypeEnum = afterSaleLog.operateType(); + return ObjectUtil.isNotNull(operateTypeEnum) ? + content.append(operateTypeEnum.getDescription()).toString() : content.toString(); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/dto/TradeOrderLogCreateReqDTO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/dto/TradeOrderLogCreateReqDTO.java new file mode 100644 index 000000000..81d87711f --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/dto/TradeOrderLogCreateReqDTO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.trade.framework.order.core.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 订单日志的创建 Request DTO + * + * @author 陈賝 + * @since 2023/7/6 15:27 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class TradeOrderLogCreateReqDTO { + + /** + * 编号 + */ + private Long id; + /** + * 用户编号 + *

+ * 关联 1:AdminUserDO 的 id 字段 + * 关联 2:MemberUserDO 的 id 字段 + */ + private Long userId; + /** + * 用户类型 + */ + private Integer userType; + /** + * 订单编号 + */ + private Long orderId; + /** + * 操作类型 + */ + private Integer operateType; + /** + * 操作明细 + */ + private String content; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/service/OrderLogService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/service/OrderLogService.java new file mode 100644 index 000000000..0b7541ee6 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/service/OrderLogService.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.trade.framework.order.core.service; + +import cn.iocoder.yudao.module.trade.framework.order.core.dto.TradeOrderLogCreateReqDTO; + +/** + * 交易下单日志 Service 接口 + * + * @author 陈賝 + * @since 2023/7/6 15:44 + */ +public interface OrderLogService { + + /** + * 创建交易下单日志 + * + * @param logDTO 日志记录 + * @author 陈賝 + * @since 2023/7/6 15:45 + */ + void createLog(TradeOrderLogCreateReqDTO logDTO); + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java index d06987ba6..f79732891 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java @@ -31,16 +31,21 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageRe import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleLogDO; import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.OrderLogDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.dal.mysql.order.OrderLogMapper; import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants; import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; import cn.iocoder.yudao.module.trade.enums.order.*; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; +import cn.iocoder.yudao.module.trade.framework.order.core.dto.TradeOrderLogCreateReqDTO; +import cn.iocoder.yudao.module.trade.framework.order.core.service.OrderLogService; import cn.iocoder.yudao.module.trade.service.cart.TradeCartService; import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; import cn.iocoder.yudao.module.trade.service.price.TradePriceService; @@ -57,6 +62,7 @@ import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; +import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_ORDER_NOT_FOUND; import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; @@ -68,11 +74,13 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; */ @Service @Slf4j -public class TradeOrderServiceImpl implements TradeOrderService { +public class TradeOrderServiceImpl implements TradeOrderService, OrderLogService { @Resource private TradeOrderMapper tradeOrderMapper; @Resource + private OrderLogMapper orderLogMapper; + @Resource private TradeOrderItemMapper tradeOrderItemMapper; @Resource @@ -568,4 +576,25 @@ public class TradeOrderServiceImpl implements TradeOrderService { TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus())); } + /** + * 创建交易下单日志 + * + * @param logDTO 日志记录 + * @author 陈賝 + * @since 2023/7/6 15:45 + */ + @Override + public void createLog(TradeOrderLogCreateReqDTO logDTO) { + try { + OrderLogDO orderLogDO = new OrderLogDO() + .setUserId(logDTO.getUserId()) + .setUserType(logDTO.getUserType()) + .setOrderId(logDTO.getOrderId()) + .setOperateType(logDTO.getOperateType()) + .setContent(logDTO.getContent()); + orderLogMapper.insert(orderLogDO); + } catch (Exception exception) { + log.error("[createLog][request({}) 日志记录错误]", toJsonString(logDTO), exception); + } + } } From 95d8be045571053546846dc930d92982b8c85a28 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 9 Sep 2023 23:04:13 +0800 Subject: [PATCH 06/17] =?UTF-8?q?=E8=AE=A2=E5=8D=95=E7=AE=A1=E7=90=86?= =?UTF-8?q?=EF=BC=9A=E5=AE=8C=E5=96=84=E8=AE=A2=E5=8D=95=E8=81=9A=E5=90=88?= =?UTF-8?q?=E6=90=9C=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/aftersale/TradeAfterSaleController.java | 7 +++---- .../controller/admin/order/TradeOrderController.java | 7 +++---- .../admin/order/vo/TradeOrderPageReqVO.java | 12 ++++-------- .../trade/dal/mysql/order/TradeOrderMapper.java | 5 ++--- 4 files changed, 12 insertions(+), 19 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java index fec1fc1aa..0bf5a9cd9 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java @@ -76,10 +76,9 @@ public class TradeAfterSaleController { public CommonResult getOrderDetail(@RequestParam("id") Long id) { // 查询订单 TradeAfterSaleDO afterSale = afterSaleService.getAfterSale(id); - // TODO @puhui999:这里建议改成,如果为 null,直接返回 success null;主要查询操作,尽量不要有非空的提示哈;交给前端处理; -// if (afterSale == null) { -// return success(null, AFTER_SALE_NOT_FOUND.getMsg()); -// } + if (afterSale == null) { + return success(null); + } // 查询订单 TradeOrderDO order = tradeOrderQueryService.getOrder(afterSale.getOrderId()); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java index 546519a1b..ddc7c1dd5 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java @@ -67,10 +67,9 @@ public class TradeOrderController { public CommonResult getOrderDetail(@RequestParam("id") Long id) { // 查询订单 TradeOrderDO order = tradeOrderQueryService.getOrder(id); - // TODO @puhui999:这里建议改成,如果为 null,直接返回 success null;主要查询操作,尽量不要有非空的提示哈;交给前端处理; -// if (order == null) { -// return success(null, ORDER_NOT_FOUND.getMsg()); -// } + if (order == null) { + return success(null); + } // 查询订单项 List orderItems = tradeOrderQueryService.getOrderItemListByOrderId(id); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderPageReqVO.java index 58361379c..dca688588 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderPageReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderPageReqVO.java @@ -31,19 +31,15 @@ public class TradeOrderPageReqVO extends PageParam { @Mobile private String userMobile; + @Schema(description = "配送方式", example = "1") + private Integer deliveryType; + @Schema(description = "发货物流公司编号", example = "1") private Long logisticsId; @Schema(description = "自提门店编号", example = "[1,2]") private List pickUpStoreIds; - @Schema(description = "收件人名称", example = "小红") - private String receiverName; - - @Schema(description = "收件人手机", example = "1560") - @Mobile - private String receiverMobile; - @Schema(description = "订单类型", example = "1") private Integer type; @@ -61,5 +57,5 @@ public class TradeOrderPageReqVO extends PageParam { @Schema(description = "订单来源", example = "10") @InEnum(value = TerminalEnum.class, message = "订单来源 {value}") private Integer terminal; -// TODO 添加配送方式筛选 + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java index 9555c0592..0aae7ec69 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java @@ -27,13 +27,12 @@ public interface TradeOrderMapper extends BaseMapperX { return selectPage(reqVO, new LambdaQueryWrapperX() .likeIfPresent(TradeOrderDO::getNo, reqVO.getNo()) .eqIfPresent(TradeOrderDO::getUserId, reqVO.getUserId()) + .eqIfPresent(TradeOrderDO::getDeliveryType, reqVO.getDeliveryType()) .inIfPresent(TradeOrderDO::getUserId, userIds) - .likeIfPresent(TradeOrderDO::getReceiverName, reqVO.getReceiverName()) - .likeIfPresent(TradeOrderDO::getReceiverMobile, reqVO.getReceiverMobile()) .eqIfPresent(TradeOrderDO::getType, reqVO.getType()) .eqIfPresent(TradeOrderDO::getStatus, reqVO.getStatus()) .eqIfPresent(TradeOrderDO::getPayChannelCode, reqVO.getPayChannelCode()) - .eqIfPresent(TradeOrderDO::getTerminal,reqVO.getTerminal()) + .eqIfPresent(TradeOrderDO::getTerminal, reqVO.getTerminal()) .eqIfPresent(TradeOrderDO::getLogisticsId, reqVO.getLogisticsId()) .inIfPresent(TradeOrderDO::getPickUpStoreId, reqVO.getPickUpStoreIds()) .betweenIfPresent(TradeOrderDO::getCreateTime, reqVO.getCreateTime())); From 50354462fef35505080cfc4194ac2d06036e9bd2 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 9 Sep 2023 23:18:09 +0800 Subject: [PATCH 07/17] =?UTF-8?q?spu=EF=BC=9A=E5=88=86=E4=BD=A3=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=E5=92=8C=E5=88=86=E4=BD=A3=E4=BF=9D=E6=8C=81=E4=B8=80?= =?UTF-8?q?=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/product/api/sku/dto/ProductSkuRespDTO.java | 6 ++---- .../product/controller/admin/sku/vo/ProductSkuBaseVO.java | 4 ++-- .../module/product/dal/dataobject/sku/ProductSkuDO.java | 4 ++-- .../product/service/spu/ProductSpuServiceImplTest.java | 8 ++++---- .../module/trade/convert/order/TradeOrderConvert.java | 6 +++--- 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java index c412faf4e..b69bbd5ec 100644 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java +++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java @@ -59,15 +59,13 @@ public class ProductSkuRespDTO { * 商品体积,单位:m^3 平米 */ private Double volume; - - // TODO @puhui:这 2 字段,需要改下;firstBrokerageRecord、secondBrokerageRecord;和分佣保持一致; /** * 一级分销的佣金,单位:分 */ - private Integer subCommissionFirstPrice; + private Integer firstBrokerageRecord; /** * 二级分销的佣金,单位:分 */ - private Integer subCommissionSecondPrice; + private Integer secondBrokerageRecord; } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java index 13da82214..f3eee6123 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java @@ -51,10 +51,10 @@ public class ProductSkuBaseVO { private Double volume; @Schema(description = "一级分销的佣金,单位:分", example = "199") - private Integer subCommissionFirstPrice; + private Integer firstBrokerageRecord; @Schema(description = "二级分销的佣金,单位:分", example = "19") - private Integer subCommissionSecondPrice; + private Integer secondBrokerageRecord; @Schema(description = "属性数组") private List properties; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java index fa576683b..e164915dd 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java @@ -81,11 +81,11 @@ public class ProductSkuDO extends BaseDO { /** * 一级分销的佣金,单位:分 */ - private Integer subCommissionFirstPrice; + private Integer firstBrokerageRecord; /** * 二级分销的佣金,单位:分 */ - private Integer subCommissionSecondPrice; + private Integer secondBrokerageRecord; // ========== 营销相关字段 ========= diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java index e57540292..b505ad161 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java @@ -92,8 +92,8 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { o.setMarketPrice(generaInt()); o.setStock(generaInt()); o.setWarnStock(10); - o.setSubCommissionFirstPrice(generaInt()); - o.setSubCommissionSecondPrice(generaInt()); + o.setFirstBrokerageRecord(generaInt()); + o.setSecondBrokerageRecord(generaInt()); // 限制分数为两位数 o.setWeight(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP)); o.setVolume(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP)); @@ -143,8 +143,8 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { o.setMarketPrice(generaInt()); o.setStock(generaInt()); o.setWarnStock(10); - o.setSubCommissionFirstPrice(generaInt()); - o.setSubCommissionSecondPrice(generaInt()); + o.setFirstBrokerageRecord(generaInt()); + o.setSecondBrokerageRecord(generaInt()); // 限制分数为两位数 o.setWeight(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP)); o.setVolume(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP)); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java index e4c996da5..feaa1bab0 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java @@ -7,7 +7,6 @@ import cn.iocoder.yudao.framework.common.util.string.StrUtils; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; -import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; @@ -31,6 +30,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; import org.mapstruct.Mapper; @@ -280,7 +280,7 @@ public interface TradeOrderConvert { default BrokerageAddReqBO convert(TradeOrderItemDO item, ProductSkuRespDTO sku) { return new BrokerageAddReqBO().setBizId(String.valueOf(item.getId())) .setBasePrice(item.getPayPrice() * item.getCount()) - .setFirstFixedPrice(sku.getSubCommissionFirstPrice()) - .setSecondFixedPrice(sku.getSubCommissionSecondPrice()); + .setFirstFixedPrice(sku.getFirstBrokerageRecord()) + .setSecondFixedPrice(sku.getSecondBrokerageRecord()); } } From 51dab96889dfd3b5a1a8e1617b090ac9cc717c5b Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sun, 10 Sep 2023 00:48:30 +0800 Subject: [PATCH 08/17] =?UTF-8?q?=E6=94=AF=E4=BB=98=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E7=A0=81=E6=9E=9A=E4=B8=BE=E7=B1=BB=E5=8F=98?= =?UTF-8?q?=E9=87=8F=E6=B7=BB=E5=8A=A0=20PAY=5F=20=E5=89=8D=E7=BC=80?= =?UTF-8?q?=E5=92=8C=E4=BA=A4=E6=98=93=E8=AE=A2=E5=8D=95=E5=8C=BA=E5=88=86?= =?UTF-8?q?=E5=BC=80=E9=81=BF=E5=85=8D=E5=86=B2=E7=AA=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trade/enums/ErrorCodeConstants.java | 3 + .../module/pay/enums/ErrorCodeConstants.java | 20 +++--- .../framework/pay/wallet/WalletPayClient.java | 6 +- .../service/demo/PayDemoOrderServiceImpl.java | 4 +- .../service/order/PayOrderServiceImpl.java | 64 ++++++++++--------- .../service/refund/PayRefundServiceImpl.java | 4 +- .../service/wallet/PayWalletServiceImpl.java | 2 +- .../service/order/PayOrderServiceTest.java | 30 ++++----- .../service/refund/PayRefundServiceTest.java | 4 +- 9 files changed, 72 insertions(+), 65 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java index 236e7af23..b49571c9c 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java @@ -34,6 +34,9 @@ public interface ErrorCodeConstants { ErrorCode ORDER_DELIVERY_FAIL_BARGAIN_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1011000023, "交易订单发货失败,砍价未成功"); ErrorCode ORDER_DELIVERY_FAIL_DELIVERY_TYPE_NOT_EXPRESS = new ErrorCode(1011000024, "交易订单发货失败,发货类型不是快递"); ErrorCode ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID = new ErrorCode(1011000025, "交易订单取消失败,订单不是【待支付】状态"); + ErrorCode ORDER_UPDATE_PRICE_FAIL_PAID = new ErrorCode(1011000026, "支付订单调价失败,原因:支付订单已付款,不能调价"); + ErrorCode ORDER_UPDATE_PRICE_FAIL_EQUAL = new ErrorCode(1011000027, "支付订单调价失败,原因:价格没有变化"); + ErrorCode ORDER_UPDATE_PRICE_FAIL_NOT_ITEM = new ErrorCode(1011000028, "支付订单调价失败,原因:订单项不存在"); // ========== After Sale 模块 1011000100 ========== ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在"); diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java index 2ee11f1be..f3d6d8685 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java @@ -21,19 +21,17 @@ public interface ErrorCodeConstants { ErrorCode CHANNEL_EXIST_SAME_CHANNEL_ERROR = new ErrorCode(1007001004, "已存在相同的渠道"); // ========== ORDER 模块 1007002000 ========== - ErrorCode ORDER_NOT_FOUND = new ErrorCode(1007002000, "支付订单不存在"); - ErrorCode ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1007002001, "支付订单不处于待支付"); - ErrorCode ORDER_STATUS_IS_SUCCESS = new ErrorCode(1007002002, "订单已支付,请刷新页面"); - ErrorCode ORDER_IS_EXPIRED = new ErrorCode(1007002003, "支付订单已经过期"); - ErrorCode ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1007002004, "发起支付报错,错误码:{},错误提示:{}"); - ErrorCode ORDER_REFUND_FAIL_STATUS_ERROR = new ErrorCode(1007002005, "支付订单退款失败,原因:状态不是已支付或已退款"); - ErrorCode ORDER_UPDATE_PRICE_FAIL_PAID = new ErrorCode(1007002006, "支付订单调价失败,原因:支付订单已付款,不能调价"); - ErrorCode ORDER_UPDATE_PRICE_FAIL_EQUAL = new ErrorCode(1007002007, "支付订单调价失败,原因:价格没有变化"); + ErrorCode PAY_ORDER_NOT_FOUND = new ErrorCode(1007002000, "支付订单不存在"); + ErrorCode PAY_ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1007002001, "支付订单不处于待支付"); + ErrorCode PAY_ORDER_STATUS_IS_SUCCESS = new ErrorCode(1007002002, "订单已支付,请刷新页面"); + ErrorCode PAY_ORDER_IS_EXPIRED = new ErrorCode(1007002003, "支付订单已经过期"); + ErrorCode PAY_ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1007002004, "发起支付报错,错误码:{},错误提示:{}"); + ErrorCode PAY_ORDER_REFUND_FAIL_STATUS_ERROR = new ErrorCode(1007002005, "支付订单退款失败,原因:状态不是已支付或已退款"); // ========== ORDER 模块(拓展单) 1007003000 ========== - ErrorCode ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1007003000, "支付交易拓展单不存在"); - ErrorCode ORDER_EXTENSION_STATUS_IS_NOT_WAITING = new ErrorCode(1007003001, "支付交易拓展单不处于待支付"); - ErrorCode ORDER_EXTENSION_IS_PAID = new ErrorCode(1007003002, "订单已支付,请等待支付结果"); + ErrorCode PAY_ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1007003000, "支付交易拓展单不存在"); + ErrorCode PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING = new ErrorCode(1007003001, "支付交易拓展单不处于待支付"); + ErrorCode PAY_ORDER_EXTENSION_IS_PAID = new ErrorCode(1007003002, "订单已支付,请等待支付结果"); // ========== 支付模块(退款) 1007006000 ========== ErrorCode REFUND_PRICE_EXCEED = new ErrorCode(1007006000, "退款金额超过订单可退款金额"); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java index 47e8217d3..edc77c335 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java @@ -26,7 +26,7 @@ import lombok.extern.slf4j.Slf4j; import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_EXTENSION_NOT_FOUND; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_ORDER_EXTENSION_NOT_FOUND; import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.REFUND_NOT_FOUND; /** @@ -99,8 +99,8 @@ public class WalletPayClient extends AbstractPayClient { PayOrderExtensionDO orderExtension = orderService.getOrderExtensionByNo(outTradeNo); // 支付交易拓展单不存在, 返回关闭状态 if (orderExtension == null) { - return PayOrderRespDTO.closedOf(String.valueOf(ORDER_EXTENSION_NOT_FOUND.getCode()), - ORDER_EXTENSION_NOT_FOUND.getMsg(), outTradeNo, ""); + return PayOrderRespDTO.closedOf(String.valueOf(PAY_ORDER_EXTENSION_NOT_FOUND.getCode()), + PAY_ORDER_EXTENSION_NOT_FOUND.getMsg(), outTradeNo, ""); } // 关闭状态 if (PayOrderStatusEnum.isClosed(orderExtension.getStatus())) { diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java index f5ebf7961..7e1090248 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java @@ -25,7 +25,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Objects; -import static cn.hutool.core.util.ObjectUtil.*; +import static cn.hutool.core.util.ObjectUtil.notEqual; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; @@ -156,7 +156,7 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId); if (payOrder == null) { log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId); - throw exception(ORDER_NOT_FOUND); + throw exception(PAY_ORDER_NOT_FOUND); } // 2.2 校验支付单已支付 if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) { diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java index f172eb187..6e85b2b8c 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java @@ -160,7 +160,7 @@ public class PayOrderServiceImpl implements PayOrderService { getSelf().notifyOrder(channel, unifiedOrderResp); // 如有渠道错误码,则抛出业务异常,提示用户 if (StrUtil.isNotEmpty(unifiedOrderResp.getChannelErrorCode())) { - throw exception(ORDER_SUBMIT_CHANNEL_ERROR, unifiedOrderResp.getChannelErrorCode(), + throw exception(PAY_ORDER_SUBMIT_CHANNEL_ERROR, unifiedOrderResp.getChannelErrorCode(), unifiedOrderResp.getChannelErrorMsg()); } // 此处需要读取最新的状态 @@ -172,16 +172,16 @@ public class PayOrderServiceImpl implements PayOrderService { private PayOrderDO validateOrderCanSubmit(Long id) { PayOrderDO order = orderMapper.selectById(id); if (order == null) { // 是否存在 - throw exception(ORDER_NOT_FOUND); + throw exception(PAY_ORDER_NOT_FOUND); } if (PayOrderStatusEnum.isSuccess(order.getStatus())) { // 校验状态,发现已支付 - throw exception(ORDER_STATUS_IS_SUCCESS); + throw exception(PAY_ORDER_STATUS_IS_SUCCESS); } if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付 - throw exception(ORDER_STATUS_IS_NOT_WAITING); + throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING); } if (LocalDateTimeUtils.beforeNow(order.getExpireTime())) { // 校验是否过期 - throw exception(ORDER_IS_EXPIRED); + throw exception(PAY_ORDER_IS_EXPIRED); } // 【重要】校验是否支付拓展单已支付,只是没有回调、或者数据不正常 @@ -202,7 +202,7 @@ public class PayOrderServiceImpl implements PayOrderService { if (PayOrderStatusEnum.isSuccess(orderExtension.getStatus())) { log.warn("[validateOrderCanSubmit][order({}) 的 extension({}) 已支付,可能是数据不一致]", id, orderExtension.getId()); - throw exception(ORDER_EXTENSION_IS_PAID); + throw exception(PAY_ORDER_EXTENSION_IS_PAID); } // 情况二:调用三方接口,查询支付单状态,是不是已支付 PayClient payClient = payClientFactory.getPayClient(orderExtension.getChannelId()); @@ -214,7 +214,7 @@ public class PayOrderServiceImpl implements PayOrderService { if (respDTO != null && PayOrderStatusRespEnum.isSuccess(respDTO.getStatus())) { log.warn("[validateOrderCanSubmit][order({}) 的 PayOrderRespDTO({}) 已支付,可能是回调延迟]", id, toJsonString(respDTO)); - throw exception(ORDER_EXTENSION_IS_PAID); + throw exception(PAY_ORDER_EXTENSION_IS_PAID); } }); } @@ -254,9 +254,10 @@ public class PayOrderServiceImpl implements PayOrderService { * 通知并更新订单的支付结果 * * @param channel 支付渠道 - * @param notify 通知 + * @param notify 通知 */ - @Transactional(rollbackFor = Exception.class) // 注意,如果是方法内调用该方法,需要通过 getSelf().notifyPayOrder(channel, notify) 调用,否则事务不生效 + @Transactional(rollbackFor = Exception.class) + // 注意,如果是方法内调用该方法,需要通过 getSelf().notifyPayOrder(channel, notify) 调用,否则事务不生效 public void notifyOrder(PayChannelDO channel, PayOrderRespDTO notify) { // 情况一:支付成功的回调 if (PayOrderStatusRespEnum.isSuccess(notify.getStatus())) { @@ -295,21 +296,21 @@ public class PayOrderServiceImpl implements PayOrderService { // 1. 查询 PayOrderExtensionDO PayOrderExtensionDO orderExtension = orderExtensionMapper.selectByNo(notify.getOutTradeNo()); if (orderExtension == null) { - throw exception(ORDER_EXTENSION_NOT_FOUND); + throw exception(PAY_ORDER_EXTENSION_NOT_FOUND); } if (PayOrderStatusEnum.isSuccess(orderExtension.getStatus())) { // 如果已经是成功,直接返回,不用重复更新 log.info("[updateOrderExtensionSuccess][orderExtension({}) 已经是已支付,无需更新]", orderExtension.getId()); return orderExtension; } if (ObjectUtil.notEqual(orderExtension.getStatus(), PayOrderStatusEnum.WAITING.getStatus())) { // 校验状态,必须是待支付 - throw exception(ORDER_EXTENSION_STATUS_IS_NOT_WAITING); + throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); } // 2. 更新 PayOrderExtensionDO int updateCounts = orderExtensionMapper.updateByIdAndStatus(orderExtension.getId(), orderExtension.getStatus(), PayOrderExtensionDO.builder().status(PayOrderStatusEnum.SUCCESS.getStatus()).channelNotifyData(toJsonString(notify)).build()); if (updateCounts == 0) { // 校验状态,必须是待支付 - throw exception(ORDER_EXTENSION_STATUS_IS_NOT_WAITING); + throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); } log.info("[updateOrderExtensionSuccess][orderExtension({}) 更新为已支付]", orderExtension.getId()); return orderExtension; @@ -318,17 +319,17 @@ public class PayOrderServiceImpl implements PayOrderService { /** * 更新 PayOrderDO 支付成功 * - * @param channel 支付渠道 + * @param channel 支付渠道 * @param orderExtension 支付拓展单 - * @param notify 通知回调 + * @param notify 通知回调 * @return 是否之前已经成功回调 */ private Boolean updateOrderSuccess(PayChannelDO channel, PayOrderExtensionDO orderExtension, - PayOrderRespDTO notify) { + PayOrderRespDTO notify) { // 1. 判断 PayOrderDO 是否处于待支付 PayOrderDO order = orderMapper.selectById(orderExtension.getOrderId()); if (order == null) { - throw exception(ORDER_NOT_FOUND); + throw exception(PAY_ORDER_NOT_FOUND); } if (PayOrderStatusEnum.isSuccess(order.getStatus()) // 如果已经是成功,直接返回,不用重复更新 && Objects.equals(order.getExtensionId(), orderExtension.getId())) { @@ -336,7 +337,7 @@ public class PayOrderServiceImpl implements PayOrderService { return true; } if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付 - throw exception(ORDER_STATUS_IS_NOT_WAITING); + throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING); } // 2. 更新 PayOrderDO @@ -346,10 +347,10 @@ public class PayOrderServiceImpl implements PayOrderService { .successTime(notify.getSuccessTime()).extensionId(orderExtension.getId()).no(orderExtension.getNo()) .channelOrderNo(notify.getChannelOrderNo()).channelUserId(notify.getChannelUserId()) .channelFeeRate(channel.getFeeRate()) - .channelFeePrice(MoneyUtils.calculateRatePrice(order.getPrice(), channel.getFeeRate())) + .channelFeePrice(MoneyUtils.calculateRatePrice(order.getPrice(), channel.getFeeRate())) .build()); if (updateCounts == 0) { // 校验状态,必须是待支付 - throw exception(ORDER_STATUS_IS_NOT_WAITING); + throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING); } log.info("[updateOrderExtensionSuccess][order({}) 更新为已支付]", order.getId()); return false; @@ -363,7 +364,7 @@ public class PayOrderServiceImpl implements PayOrderService { // 1. 查询 PayOrderExtensionDO PayOrderExtensionDO orderExtension = orderExtensionMapper.selectByNo(notify.getOutTradeNo()); if (orderExtension == null) { - throw exception(ORDER_EXTENSION_NOT_FOUND); + throw exception(PAY_ORDER_EXTENSION_NOT_FOUND); } if (PayOrderStatusEnum.isClosed(orderExtension.getStatus())) { // 如果已经是关闭,直接返回,不用重复更新 log.info("[updateOrderExtensionClosed][orderExtension({}) 已经是支付关闭,无需更新]", orderExtension.getId()); @@ -375,7 +376,7 @@ public class PayOrderServiceImpl implements PayOrderService { return; } if (ObjectUtil.notEqual(orderExtension.getStatus(), PayOrderStatusEnum.WAITING.getStatus())) { // 校验状态,必须是待支付 - throw exception(ORDER_EXTENSION_STATUS_IS_NOT_WAITING); + throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); } // 2. 更新 PayOrderExtensionDO @@ -383,7 +384,7 @@ public class PayOrderServiceImpl implements PayOrderService { PayOrderExtensionDO.builder().status(PayOrderStatusEnum.CLOSED.getStatus()).channelNotifyData(toJsonString(notify)) .channelErrorCode(notify.getChannelErrorCode()).channelErrorMsg(notify.getChannelErrorMsg()).build()); if (updateCounts == 0) { // 校验状态,必须是待支付 - throw exception(ORDER_EXTENSION_STATUS_IS_NOT_WAITING); + throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); } log.info("[updateOrderExtensionClosed][orderExtension({}) 更新为支付关闭]", orderExtension.getId()); } @@ -392,10 +393,10 @@ public class PayOrderServiceImpl implements PayOrderService { public void updateOrderRefundPrice(Long id, Integer incrRefundPrice) { PayOrderDO order = orderMapper.selectById(id); if (order == null) { - throw exception(ORDER_NOT_FOUND); + throw exception(PAY_ORDER_NOT_FOUND); } if (!PayOrderStatusEnum.isSuccessOrRefund(order.getStatus())) { - throw exception(ORDER_REFUND_FAIL_STATUS_ERROR); + throw exception(PAY_ORDER_REFUND_FAIL_STATUS_ERROR); } if (order.getRefundPrice() + incrRefundPrice > order.getPrice()) { throw exception(REFUND_PRICE_EXCEED); @@ -407,16 +408,21 @@ public class PayOrderServiceImpl implements PayOrderService { .setStatus(PayOrderStatusEnum.REFUND.getStatus()); int updateCount = orderMapper.updateByIdAndStatus(id, order.getStatus(), updateObj); if (updateCount == 0) { - throw exception(ORDER_REFUND_FAIL_STATUS_ERROR); + throw exception(PAY_ORDER_REFUND_FAIL_STATUS_ERROR); } } @Override - public void updatePayOrderPriceById(Long payOrderId, Integer payPrice) { - // TODO @puhui999:不能直接这样修改哈;应该只有未支付状态的订单才可以改;另外,如果价格如果没变,可以直接 return 哈; - PayOrderDO order = orderMapper.selectById(payOrderId); + public void updatePayOrderPrice(Long id, Integer payPrice) { + PayOrderDO order = orderMapper.selectById(id); if (order == null) { - throw exception(ORDER_NOT_FOUND); + throw exception(PAY_ORDER_NOT_FOUND); + } + if (ObjectUtil.notEqual(PayOrderStatusEnum.WAITING.getStatus(), order.getStatus())) { + throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING); + } + if (ObjectUtil.equal(order.getPrice(), payPrice)) { + return; } order.setPrice(payPrice); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java index e4d75c035..643b46360 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java @@ -160,11 +160,11 @@ public class PayRefundServiceImpl implements PayRefundService { private PayOrderDO validatePayOrderCanRefund(PayRefundCreateReqDTO reqDTO) { PayOrderDO order = orderService.getOrder(reqDTO.getAppId(), reqDTO.getMerchantOrderId()); if (order == null) { - throw exception(ORDER_NOT_FOUND); + throw exception(PAY_ORDER_NOT_FOUND); } // 校验状态,必须是已支付、或者已退款 if (!PayOrderStatusEnum.isSuccessOrRefund(order.getStatus())) { - throw exception(ORDER_REFUND_FAIL_STATUS_ERROR); + throw exception(PAY_ORDER_REFUND_FAIL_STATUS_ERROR); } // 校验金额,退款金额不能大于原定的金额 diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java index d017e5332..0e51fee6f 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java @@ -74,7 +74,7 @@ public class PayWalletServiceImpl implements PayWalletService { // 1. 判断支付交易拓展单是否存 PayOrderExtensionDO orderExtension = orderService.getOrderExtensionByNo(outTradeNo); if (orderExtension == null) { - throw exception(ORDER_EXTENSION_NOT_FOUND); + throw exception(PAY_ORDER_EXTENSION_NOT_FOUND); } // 2. 扣减余额 return reduceWalletBalance(userId, userType, orderExtension.getOrderId(), PAYMENT, price); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java index 6a5f15ce3..c9a74d1d1 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java @@ -261,7 +261,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { String userIp = randomString(); // 调用, 并断言异常 - assertServiceException(() -> orderService.submitOrder(reqVO, userIp), ORDER_NOT_FOUND); + assertServiceException(() -> orderService.submitOrder(reqVO, userIp), PAY_ORDER_NOT_FOUND); } @Test @@ -274,7 +274,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { String userIp = randomString(); // 调用, 并断言异常 - assertServiceException(() -> orderService.submitOrder(reqVO, userIp), ORDER_STATUS_IS_NOT_WAITING); + assertServiceException(() -> orderService.submitOrder(reqVO, userIp), PAY_ORDER_STATUS_IS_NOT_WAITING); } @Test @@ -287,7 +287,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { String userIp = randomString(); // 调用, 并断言异常 - assertServiceException(() -> orderService.submitOrder(reqVO, userIp), ORDER_STATUS_IS_SUCCESS); + assertServiceException(() -> orderService.submitOrder(reqVO, userIp), PAY_ORDER_STATUS_IS_SUCCESS); } @Test @@ -301,7 +301,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { String userIp = randomString(); // 调用, 并断言异常 - assertServiceException(() -> orderService.submitOrder(reqVO, userIp), ORDER_IS_EXPIRED); + assertServiceException(() -> orderService.submitOrder(reqVO, userIp), PAY_ORDER_IS_EXPIRED); } @Test @@ -366,7 +366,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { // 调用,并断言异常 assertServiceException(() -> orderService.submitOrder(reqVO, userIp), - ORDER_SUBMIT_CHANNEL_ERROR, "001", "模拟异常"); + PAY_ORDER_SUBMIT_CHANNEL_ERROR, "001", "模拟异常"); // 断言,数据记录(PayOrderExtensionDO) PayOrderExtensionDO orderExtension = orderExtensionMapper.selectOne(null); assertNotNull(orderExtension); @@ -450,7 +450,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { // 调用,并断言异常 assertServiceException(() -> orderService.validateOrderActuallyPaid(id), - ORDER_EXTENSION_IS_PAID); + PAY_ORDER_EXTENSION_IS_PAID); } @Test @@ -469,7 +469,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { // 调用,并断言异常 assertServiceException(() -> orderService.validateOrderActuallyPaid(id), - ORDER_EXTENSION_IS_PAID); + PAY_ORDER_EXTENSION_IS_PAID); } @Test @@ -519,7 +519,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { // 调用,并断言异常 assertServiceException(() -> orderService.notifyOrder(channel, notify), - ORDER_EXTENSION_NOT_FOUND); + PAY_ORDER_EXTENSION_NOT_FOUND); } @Test @@ -537,7 +537,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { // 调用,并断言异常 assertServiceException(() -> orderService.notifyOrder(channel, notify), - ORDER_EXTENSION_STATUS_IS_NOT_WAITING); + PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); } @Test @@ -555,7 +555,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { // 调用,并断言异常 assertServiceException(() -> orderService.notifyOrder(channel, notify), - ORDER_NOT_FOUND); + PAY_ORDER_NOT_FOUND); // 断言 PayOrderExtensionDO :数据更新被回滚 assertPojoEquals(orderExtension, orderExtensionMapper.selectOne(null)); } @@ -588,7 +588,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { // 调用,并断言异常 assertServiceException(() -> orderService.notifyOrder(channel, notify), - ORDER_STATUS_IS_NOT_WAITING); + PAY_ORDER_STATUS_IS_NOT_WAITING); // 断言 PayOrderExtensionDO :数据未更新,因为它是 SUCCESS assertPojoEquals(orderExtension, orderExtensionMapper.selectOne(null)); } @@ -673,7 +673,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { // 调用,并断言异常 assertServiceException(() -> orderService.notifyOrder(channel, notify), - ORDER_EXTENSION_NOT_FOUND); + PAY_ORDER_EXTENSION_NOT_FOUND); } @Test @@ -729,7 +729,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { // 调用,并断言异常 assertServiceException(() -> orderService.notifyOrder(channel, notify), - ORDER_EXTENSION_STATUS_IS_NOT_WAITING); + PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); } @Test @@ -762,7 +762,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { // 调用,并断言异常 assertServiceException(() -> orderService.updateOrderRefundPrice(id, incrRefundPrice), - ORDER_NOT_FOUND); + PAY_ORDER_NOT_FOUND); } @Test @@ -786,7 +786,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { // 调用,并断言异常 assertServiceException(() -> orderService.updateOrderRefundPrice(id, incrRefundPrice), - ORDER_REFUND_FAIL_STATUS_ERROR); + PAY_ORDER_REFUND_FAIL_STATUS_ERROR); } @Test diff --git a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java index b0b31fbc4..512f952e8 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java @@ -219,7 +219,7 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest { // 调用,并断言异常 assertServiceException(() -> refundService.createPayRefund(reqDTO), - ORDER_NOT_FOUND); + PAY_ORDER_NOT_FOUND); } @Test @@ -245,7 +245,7 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest { // 调用,并断言异常 assertServiceException(() -> refundService.createPayRefund(reqDTO), - ORDER_REFUND_FAIL_STATUS_ERROR); + PAY_ORDER_REFUND_FAIL_STATUS_ERROR); } @Test From c023209aa529d6a8a9f64ceb38d4ac67ba458236 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sun, 10 Sep 2023 00:50:13 +0800 Subject: [PATCH 09/17] =?UTF-8?q?=E8=AE=A2=E5=8D=95=E7=AE=A1=E7=90=86?= =?UTF-8?q?=EF=BC=9A=E5=AE=8C=E5=96=84=E8=AE=A2=E5=8D=95=E8=B0=83=E4=BB=B7?= =?UTF-8?q?=E5=88=86=E6=91=8A=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../order/TradeOrderUpdateServiceImpl.java | 73 +++++++++++++------ .../module/pay/api/order/PayOrderApi.java | 5 +- .../module/pay/api/order/PayOrderApiImpl.java | 4 +- .../pay/service/order/PayOrderService.java | 4 +- 4 files changed, 58 insertions(+), 28 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 7893d62a9..61aea8789 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -53,8 +53,8 @@ import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; import cn.iocoder.yudao.module.trade.enums.order.*; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; -import cn.iocoder.yudao.module.trade.service.brokerage.record.BrokerageRecordService; import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; +import cn.iocoder.yudao.module.trade.service.brokerage.record.BrokerageRecordService; import cn.iocoder.yudao.module.trade.service.cart.CartService; import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; import cn.iocoder.yudao.module.trade.service.message.TradeMessageService; @@ -70,14 +70,13 @@ import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_UPDATE_PRICE_FAIL_EQUAL; -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_UPDATE_PRICE_FAIL_PAID; import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; /** @@ -562,35 +561,67 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { } @Override - // TODO @puhui999:考虑事务性 + @Transactional(rollbackFor = Exception.class) public void updateOrderPrice(TradeOrderUpdatePriceReqVO reqVO) { - // 校验交易订单 + // 1、校验交易订单 TradeOrderDO order = validateOrderExists(reqVO.getId()); if (order.getPayStatus()) { throw exception(ORDER_UPDATE_PRICE_FAIL_PAID); } + // 2、校验订单项 + List items = tradeOrderItemMapper.selectListByOrderId(order.getId()); + if (CollUtil.isEmpty(items)) { + throw exception(ORDER_UPDATE_PRICE_FAIL_NOT_ITEM); + } + // 3、校验调价金额是否变化 if (ObjectUtil.equal(order.getAdjustPrice(), reqVO.getAdjustPrice())) { throw exception(ORDER_UPDATE_PRICE_FAIL_EQUAL); } - // TODO @puhui999:应该是按照 payPrice 分配;并且要考虑取余问题;payPrice 也要考虑,item 里的 - List itemDOs = tradeOrderItemMapper.selectListByOrderId(order.getId()); - // TradeOrderItemDO 需要做 adjustPrice 的分摊 - int price = reqVO.getAdjustPrice() / itemDOs.size(); - itemDOs.forEach(item -> { - item.setAdjustPrice(price); - }); - // 更新 TradeOrderItem - // TODO @puhui999:不要整个对象去更新哈;应该 new 一下; - tradeOrderItemMapper.updateBatch(itemDOs); - // 更新订单 - // TODO @puhui999:要考虑多次修改价格,不能单单的 payPrice + 价格; - TradeOrderDO update = TradeOrderConvert.INSTANCE.convert(reqVO); - update.setPayPrice(update.getPayPrice() + update.getAdjustPrice()); + // 4、更新订单 + TradeOrderDO update = new TradeOrderDO(); + update.setId(order.getId()); + update.setAdjustPrice(reqVO.getAdjustPrice()); + int orderPayPrice = order.getAdjustPrice() != null ? (order.getPayPrice() - order.getAdjustPrice()) + + reqVO.getAdjustPrice() : order.getPayPrice() + reqVO.getAdjustPrice(); + update.setPayPrice(orderPayPrice); // TODO @芋艿:改价时,赠送的积分,要不要做改动??? tradeOrderMapper.updateById(update); - // 更新支付订单 - payOrderApi.updatePayOrderPriceById(order.getPayOrderId(), update.getPayPrice()); + + // TODO @puhui999:应该是按照 payPrice 分配;并且要考虑取余问题;payPrice 也要考虑,item 里的 + // TODO:先按 adjustPrice 实现,没明白 payPrice 怎么搞哈哈哈 + // 5、更新 TradeOrderItem + if (items.size() > 1) { + // TradeOrderItemDO 需要做 adjustPrice 的分摊 + int price = reqVO.getAdjustPrice() / items.size(); + int remainderPrice = reqVO.getAdjustPrice() % items.size(); + List orders = new ArrayList<>(); + for (int i = 0; i < items.size(); i++) { + // 把平摊后剩余的金额加到第一个订单项 + if (remainderPrice != 0 && i == 0) { + orders.add(convertOrderItemPrice(items.get(i), price + remainderPrice)); + } + orders.add(convertOrderItemPrice(items.get(i), price)); + } + tradeOrderItemMapper.updateBatch(orders); + } else { + TradeOrderItemDO orderItem = items.get(0); + TradeOrderItemDO updateItem = convertOrderItemPrice(orderItem, reqVO.getAdjustPrice()); + tradeOrderItemMapper.updateById(updateItem); + } + + // 6、更新支付订单 + payOrderApi.updatePayOrderPrice(order.getPayOrderId(), update.getPayPrice()); + } + + private TradeOrderItemDO convertOrderItemPrice(TradeOrderItemDO orderItem, Integer price) { + TradeOrderItemDO newOrderItem = new TradeOrderItemDO(); + newOrderItem.setId(orderItem.getId()); + newOrderItem.setAdjustPrice(price); + int payPrice = orderItem.getAdjustPrice() != null ? (orderItem.getPayPrice() - orderItem.getAdjustPrice()) + + price : orderItem.getPayPrice() + price; + newOrderItem.setPayPrice(payPrice); + return newOrderItem; } @Override diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java index b46f19534..8a18381dd 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java @@ -29,13 +29,12 @@ public interface PayOrderApi { */ PayOrderRespDTO getOrder(Long id); - // TODO @puhui999:可以去掉 byId;然后 payOrderId 参数改成 id; /** * 更新支付订单价格 * - * @param payOrderId 支付单编号 + * @param id 支付单编号 * @param payPrice 支付单价格 */ - void updatePayOrderPriceById(Long payOrderId, Integer payPrice); + void updatePayOrderPrice(Long id, Integer payPrice); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java index 1740e3bba..26234acb0 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java @@ -32,8 +32,8 @@ public class PayOrderApiImpl implements PayOrderApi { } @Override - public void updatePayOrderPriceById(Long payOrderId, Integer payPrice) { - payOrderService.updatePayOrderPriceById(payOrderId, payPrice); + public void updatePayOrderPrice(Long id, Integer payPrice) { + payOrderService.updatePayOrderPrice(id, payPrice); } } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java index e03bda117..978a7950c 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java @@ -101,10 +101,10 @@ public interface PayOrderService { /** * 更新支付订单价格 * - * @param payOrderId 支付单编号 + * @param id 支付单编号 * @param payPrice 支付单价格 */ - void updatePayOrderPriceById(Long payOrderId, Integer payPrice); + void updatePayOrderPrice(Long id, Integer payPrice); /** * 获得支付订单 From 57f0ea04f72fb4ebe68d4bc1d7a3bee38e3aca09 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sun, 10 Sep 2023 11:06:39 +0800 Subject: [PATCH 10/17] =?UTF-8?q?mall-order:=20=E5=AE=8C=E5=96=84=E6=B4=BB?= =?UTF-8?q?=E5=8A=A8=E5=95=86=E5=93=81=E5=BA=93=E5=AD=98=E6=89=A3=E5=87=8F?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=88=E5=B9=B6=E5=8F=91=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E5=BA=93=E5=AD=98=E4=B8=8B=E4=B8=80=E6=8F=90=E4=BA=A4=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/bargain/BargainActivityApi.java | 4 +- .../dto/SeckillActivityUpdateStockReqDTO.java | 36 ++++------- .../api/bargain/BargainActivityApiImpl.java | 21 +------ .../api/seckill/SeckillActivityApiImpl.java | 61 +------------------ .../bargain/BargainActivityService.java | 9 ++- .../bargain/BargainActivityServiceImpl.java | 19 ++++++ .../seckill/SeckillActivityService.java | 7 +++ .../seckill/SeckillActivityServiceImpl.java | 35 +++++++++++ .../app/order/AppTradeOrderController.java | 7 +-- .../order/TradeOrderUpdateServiceImpl.java | 26 ++++---- 10 files changed, 104 insertions(+), 121 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApi.java index 5e62d6e9e..eb912e417 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApi.java @@ -10,9 +10,9 @@ public interface BargainActivityApi { /** * 更新砍价活动库存 * - * @param activityId 砍价活动编号 + * @param id 砍价活动编号 * @param count 购买数量 */ - void updateBargainActivityStock(Long activityId, Integer count); + void updateBargainActivityStock(Long id, Integer count); } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java index df7c5649c..07a25b3d6 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.seckill.dto; import lombok.Data; -import java.util.List; +import javax.validation.constraints.NotNull; /** * 更新秒杀库存 request DTO @@ -12,37 +12,25 @@ import java.util.List; @Data public class SeckillActivityUpdateStockReqDTO { - // TODO @puhui999:参数校验 - - // TODO @puhui999:秒杀的话,一次只能购买一种商品哈;不能多个哈; - - /** - * 活动编号 - */ + @NotNull(message = "活动编号不能为空") private Long activityId; - /** - * 总购买数量 - */ + + @NotNull(message = "购买数量不能为空") private Integer count; - /** - * 活动商品 - */ - private List items; + + @NotNull(message = "活动商品不能为空") + private Item item; @Data public static class Item { - /** - * SPU 编号 - */ + @NotNull(message = "SPU 编号不能为空") private Long spuId; - /** - * SKU 编号 - */ + + @NotNull(message = "SKU 编号活动商品不能为空") private Long skuId; - /** - * 购买数量 - */ + + @NotNull(message = "购买数量不能为空") private Integer count; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApiImpl.java index 02620c5ec..c439fcbc2 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApiImpl.java @@ -1,15 +1,10 @@ package cn.iocoder.yudao.module.promotion.api.bargain; -import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityUpdateReqVO; -import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService; import org.springframework.stereotype.Service; import javax.annotation.Resource; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.BARGAIN_ACTIVITY_NOT_EXISTS; - /** * 砍价活动 Api 接口实现类 * @@ -22,20 +17,8 @@ public class BargainActivityApiImpl implements BargainActivityApi { private BargainActivityService bargainActivityService; @Override - public void updateBargainActivityStock(Long activityId, Integer count) { - // TODO @puhui999:可以整个实现到 bargainActivityService 中 - // 查询砍价活动 - BargainActivityDO activity = bargainActivityService.getBargainActivity(activityId); - if (activity == null) { - throw exception(BARGAIN_ACTIVITY_NOT_EXISTS); - } - - // 更新砍价库存 - // TODO @puhui999:考虑下并发更新问题 - BargainActivityUpdateReqVO reqVO = new BargainActivityUpdateReqVO(); - reqVO.setId(activityId); - reqVO.setStock(activity.getStock() - count); - bargainActivityService.updateBargainActivity(reqVO); + public void updateBargainActivityStock(Long id, Integer count) { + bargainActivityService.updateBargainActivityStock(id, count); } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java index 1f5c15755..f8840415a 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java @@ -1,20 +1,10 @@ package cn.iocoder.yudao.module.promotion.api.seckill; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO; -import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; -import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService; import org.springframework.stereotype.Service; import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_ACTIVITY_UPDATE_STOCK_FAIL; /** * 秒杀活动接口 Api 接口实现类 @@ -27,58 +17,9 @@ public class SeckillActivityApiImpl implements SeckillActivityApi { @Resource private SeckillActivityService activityService; - // TODO @puhui:建议这块弄到 activityService 实现哈; - // TODO @puhui:这个方法,要考虑事务性 @Override public void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO) { - // TODO @puhui999:长方法,最好有 1.1 1.2 2.1 这种步骤哈; - SeckillActivityDO seckillActivity = activityService.getSeckillActivity(updateStockReqDTO.getActivityId()); - if (seckillActivity.getStock() < updateStockReqDTO.getCount()) { - throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); - } - // 获取活动商品 - // TODO @puhui999:在一个方法里,dos 和 dolist 最好保持一致,要么用 s,要么用 list 哈; - List productDOs = activityService.getSeckillProductListByActivityId(updateStockReqDTO.getActivityId()); - // TODO @puhui999:这个是不是搞成 CollectionUtils.convertMultiMap() - List items = updateStockReqDTO.getItems(); - Map> map = new HashMap<>(); - items.forEach(item -> { - if (map.containsKey(item.getSpuId())) { - List skuIds = map.get(item.getSpuId()); - skuIds.add(item.getSkuId()); - map.put(item.getSpuId(), skuIds); - } else { - List list = new ArrayList<>(); - list.add(item.getSkuId()); - map.put(item.getSpuId(), list); - } - }); - // 过滤出购买的商品 - // TODO @puhui999:productDOList 可以简化成 productList;一般来说,do 之类不用带着哈,在变量里; - List productDOList = CollectionUtils.filterList(productDOs, item -> map.get(item.getSpuId()).contains(item.getSkuId())); - Map productDOMap = CollectionUtils.convertMap(items, SeckillActivityUpdateStockReqDTO.Item::getSkuId, p -> p); - // 检查活动商品库存是否充足 - // TODO @puhui999:避免 b 这种无业务含义的变量; - boolean b = CollectionUtils.anyMatch(productDOList, item -> { - SeckillActivityUpdateStockReqDTO.Item item1 = productDOMap.get(item.getSkuId()); - return (item.getStock() < item1.getCount()) || (item.getStock() - item1.getCount()) < 0; - }); - if (b) { - throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); - } - // TODO @puhui999:类似 doList,应该和下面的 update 逻辑粘的更紧密一点;so 在空行的时候,应该挪到 74 之后里去;甚至更合理,应该是 79 之后;说白了,逻辑要分块,每个模块涉及的代码要紧密在一起; - List doList = CollectionUtils.convertList(productDOList, item -> { - item.setStock(item.getStock() - productDOMap.get(item.getSkuId()).getCount()); - return item; - }); - - // 更新活动库存 - // TODO @puhui999:考虑下并发更新 - seckillActivity.setStock(seckillActivity.getStock() + updateStockReqDTO.getCount()); - seckillActivity.setTotalStock(seckillActivity.getTotalStock() - updateStockReqDTO.getCount()); - activityService.updateSeckillActivity(seckillActivity); - // 更新活动商品库存 - activityService.updateSeckillActivityProductList(doList); + activityService.updateSeckillStock(updateStockReqDTO); } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityService.java index 1c49155a8..71eedfc7f 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityService.java @@ -30,6 +30,14 @@ public interface BargainActivityService { */ void updateBargainActivity(@Valid BargainActivityUpdateReqVO updateReqVO); + /** + * 更新砍价活动库存 + * + * @param id 砍价活动编号 + * @param count 购买数量 + */ + void updateBargainActivityStock(Long id, Integer count); + /** * 删除砍价活动 * @@ -53,5 +61,4 @@ public interface BargainActivityService { */ PageResult getBargainActivityPage(BargainActivityPageReqVO pageReqVO); - } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java index 4a889fbf7..4f9085be8 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java @@ -39,6 +39,7 @@ public class BargainActivityServiceImpl implements BargainActivityService { private ProductSkuApi productSkuApi; @Override + @Transactional(rollbackFor = Exception.class) public Long createBargainActivity(BargainActivityCreateReqVO createReqVO) { // 校验商品 SPU 是否存在是否参加的别的活动 validateBargainConflict(createReqVO.getSpuId(), null); @@ -53,6 +54,7 @@ public class BargainActivityServiceImpl implements BargainActivityService { } @Override + @Transactional(rollbackFor = Exception.class) public void updateBargainActivity(BargainActivityUpdateReqVO updateReqVO) { // 校验存在 BargainActivityDO activityDO = validateBargainActivityExists(updateReqVO.getId()); @@ -70,6 +72,23 @@ public class BargainActivityServiceImpl implements BargainActivityService { bargainActivityMapper.updateById(updateObj); } + @Override + @Transactional(rollbackFor = Exception.class) + public void updateBargainActivityStock(Long id, Integer count) { + // 查询砍价活动 + BargainActivityDO activity = getBargainActivity(id); + if (activity == null) { + throw exception(BARGAIN_ACTIVITY_NOT_EXISTS); + } + + // 更新砍价库存 + // TODO @puhui999:考虑下并发更新问题 + BargainActivityUpdateReqVO reqVO = new BargainActivityUpdateReqVO(); + reqVO.setId(id); + reqVO.setStock(activity.getStock() - count); + //bargainActivityService.updateBargainActivity(reqVO); + } + private void validateBargainConflict(Long spuId, Long activityId) { // 查询所有开启的砍价活动 List activityList = bargainActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus()); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java index 079470814..8ecb29466 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.promotion.service.seckill; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO; @@ -40,6 +41,12 @@ public interface SeckillActivityService { */ void updateSeckillActivity(SeckillActivityDO activityDO); + /** + * 更新秒杀库存 + * + * @param updateStockReqDTO 更新信息 + */ + void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO); /** * 更新秒杀活动商品 * diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java index 28f654049..e6539c186 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO; @@ -149,6 +150,40 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { seckillActivityMapper.updateById(activityDO); } + @Override + @Transactional(rollbackFor = Exception.class) + public void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO) { + // 1、校验秒杀活动是否存在 + SeckillActivityDO seckillActivity = getSeckillActivity(updateStockReqDTO.getActivityId()); + // 1.1、校验库存是否充足 + if (seckillActivity.getStock() < updateStockReqDTO.getCount()) { + throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); + } + + // 2、更新活动库存 + // TODO @puhui999:考虑下并发更新 + seckillActivity.setStock(seckillActivity.getStock() + updateStockReqDTO.getCount()); + seckillActivity.setTotalStock(seckillActivity.getTotalStock() - updateStockReqDTO.getCount()); + updateSeckillActivity(seckillActivity); + + // 3、获取活动商品 + List products = getSeckillProductListByActivityId(updateStockReqDTO.getActivityId()); + // 3.1、过滤出购买的商品 + SeckillProductDO product = findFirst(products, item -> ObjectUtil.equal(updateStockReqDTO.getItem().getSkuId(), item.getSkuId())); + // 3.2、检查活动商品库存是否充足 + boolean isSufficient = product == null || (product.getStock() == 0 || (product.getStock() < updateStockReqDTO.getItem().getCount()) || (product.getStock() - updateStockReqDTO.getItem().getCount()) < 0); + if (isSufficient) { + throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); + } + + // 4、更新活动商品库存 + SeckillProductDO updateProduct = new SeckillProductDO(); + updateProduct.setId(product.getId()); + updateProduct.setStock(product.getStock() - updateStockReqDTO.getItem().getCount()); + // TODO @puhui999:考虑下并发更新 + + } + @Override public void updateSeckillActivityProductList(List productList) { seckillProductMapper.updateBatch(productList); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java index a2ea2f79f..4a53b6684 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java @@ -81,10 +81,9 @@ public class AppTradeOrderController { public CommonResult getOrder(@RequestParam("id") Long id) { // 查询订单 TradeOrderDO order = tradeOrderQueryService.getOrder(getLoginUserId(), id); - // TODO @puhui999:这里建议改成,如果为 null,直接返回 success null;主要查询操作,尽量不要有非空的提示哈;交给前端处理; -// if (order == null) { -// return success(null, ORDER_NOT_FOUND.getMsg()); -// } + if (order == null) { + return success(null); + } // 查询订单项 List orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId()); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 61aea8789..3ea5a76c1 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -313,17 +313,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { Integer count = getSumValue(orderItems, TradeOrderItemDO::getCount, Integer::sum); // 1)如果是秒杀商品:额外扣减秒杀的库存; if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), tradeOrderDO.getType())) { - SeckillActivityUpdateStockReqDTO updateStockReqDTO = new SeckillActivityUpdateStockReqDTO(); - updateStockReqDTO.setActivityId(createReqVO.getSeckillActivityId()); - updateStockReqDTO.setCount(count); - updateStockReqDTO.setItems(CollectionUtils.convertList(orderItems, item -> { - SeckillActivityUpdateStockReqDTO.Item item1 = new SeckillActivityUpdateStockReqDTO.Item(); - item1.setSpuId(item.getSpuId()); - item1.setSkuId(item.getSkuId()); - item1.setCount(item.getCount()); - return item1; - })); - seckillActivityApi.updateSeckillStock(updateStockReqDTO); + seckillActivityApi.updateSeckillStock(getSeckillActivityUpdateStockReqDTO(createReqVO, orderItems, count)); } // 2)如果是砍价活动:额外扣减砍价的库存; bargainActivityApi.updateBargainActivityStock(createReqVO.getBargainActivityId(), count); @@ -351,6 +341,20 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { // 增加订单日志 TODO 芋艿:待实现 } + private SeckillActivityUpdateStockReqDTO getSeckillActivityUpdateStockReqDTO(AppTradeOrderCreateReqVO createReqVO, List orderItems, Integer count) { + SeckillActivityUpdateStockReqDTO updateStockReqDTO = new SeckillActivityUpdateStockReqDTO(); + updateStockReqDTO.setActivityId(createReqVO.getSeckillActivityId()); + updateStockReqDTO.setCount(count); + // 秒杀活动只能选择一个商品 + TradeOrderItemDO item = orderItems.get(0); + SeckillActivityUpdateStockReqDTO.Item item1 = new SeckillActivityUpdateStockReqDTO.Item(); + item1.setSpuId(item.getSpuId()); + item1.setSkuId(item.getSkuId()); + item1.setCount(item.getCount()); + updateStockReqDTO.setItem(item1); + return updateStockReqDTO; + } + private void createPayOrder(TradeOrderDO order, List orderItems, TradePriceCalculateRespBO calculateRespBO) { // 创建支付单,用于后续的支付 PayOrderCreateReqDTO payOrderCreateReqDTO = TradeOrderConvert.INSTANCE.convert( From 7fb455096c89d125fe44091e546db4fd2c3cb5fc Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 11 Sep 2023 00:13:45 +0800 Subject: [PATCH 11/17] =?UTF-8?q?=E5=95=86=E5=9F=8E=E6=B4=BB=E5=8A=A8:=20?= =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=B4=BB=E5=8A=A8=E5=95=86=E5=93=81=E5=B9=B6?= =?UTF-8?q?=E5=8F=91=E5=BA=93=E5=AD=98=E6=89=A3=E5=87=8F=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../promotion/enums/ErrorCodeConstants.java | 3 +- .../mysql/bargain/BargainActivityMapper.java | 15 ++++++++++ .../SeckillActivityMapper.java | 16 ++++++++++ .../seckillactivity/SeckillProductMapper.java | 15 ++++++++++ .../bargain/BargainActivityServiceImpl.java | 9 +++--- .../seckill/SeckillActivityServiceImpl.java | 29 +++++++++---------- 6 files changed, 66 insertions(+), 21 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java index 8c873b5ad..baca6c273 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java @@ -55,7 +55,7 @@ public interface ErrorCodeConstants { ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改"); ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除"); ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭"); - ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "更新秒杀活动库存失败,原因秒杀库存不足"); + ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "秒杀失败,原因秒杀库存不足"); // ========== 秒杀时段 1013009000 ========== ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在"); @@ -83,6 +83,7 @@ public interface ErrorCodeConstants { ErrorCode BARGAIN_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013012001, "存在商品参加了其它砍价活动"); ErrorCode BARGAIN_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013012002, "砍价活动已关闭不能修改"); ErrorCode BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013012003, "砍价活动未关闭或未结束,不能删除"); + ErrorCode BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013012004, "砍价失败,原因:该砍价活动库存不足"); // ========== 砍价记录 1013013000 ========== ErrorCode BARGAIN_RECORD_NOT_EXISTS = new ErrorCode(1013013000, "砍价记录不存在"); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java index 836127ab9..28366dc89 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityPageReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import java.util.List; @@ -28,4 +29,18 @@ public interface BargainActivityMapper extends BaseMapperX { return selectList(BargainActivityDO::getStatus, status); } + /** + * 更新活动库存 + * + * @param id 活动编号 + * @param count 扣减的库存数量 + * @return 影响的行数 + */ + default int updateActivityStock(Long id, int count) { + return update(null, new LambdaUpdateWrapper() + .eq(BargainActivityDO::getId, id) + .gt(BargainActivityDO::getStock, 0) + .setSql("stock = stock - " + count)); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java index 70fe79d53..79eca4aa0 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import java.util.List; @@ -32,4 +33,19 @@ public interface SeckillActivityMapper extends BaseMapperX { .eqIfPresent(SeckillActivityDO::getStatus, status)); } + /** + * 更新活动库存 + * + * @param id 活动编号 + * @param count 扣减的库存数量 + * @return 影响的行数 + */ + default int updateActivityStock(Long id, int count) { + return update(null, new LambdaUpdateWrapper() + .eq(SeckillActivityDO::getId, id) + .gt(SeckillActivityDO::getTotalStock, 0) + .setSql("stock = stock + " + count) + .setSql("totalStock = totalStock - " + count)); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java index f11bd1aba..79eee0cec 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import java.util.Collection; @@ -23,4 +24,18 @@ public interface SeckillProductMapper extends BaseMapperX { return selectList(SeckillProductDO::getActivityId, ids); } + /** + * 更新活动库存 + * + * @param id 活动编号 + * @param count 扣减的库存数量 + * @return 影响的行数 + */ + default int updateActivityStock(Long id, int count) { + return update(null, new LambdaUpdateWrapper() + .eq(SeckillProductDO::getId, id) + .gt(SeckillProductDO::getStock, 0) + .setSql("stock = stock - " + count)); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java index 4f9085be8..158766daf 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java @@ -82,11 +82,10 @@ public class BargainActivityServiceImpl implements BargainActivityService { } // 更新砍价库存 - // TODO @puhui999:考虑下并发更新问题 - BargainActivityUpdateReqVO reqVO = new BargainActivityUpdateReqVO(); - reqVO.setId(id); - reqVO.setStock(activity.getStock() - count); - //bargainActivityService.updateBargainActivity(reqVO); + int row = bargainActivityMapper.updateActivityStock(id, count); + if (row == 0) { + throw exception(BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL); + } } private void validateBargainConflict(Long spuId, Long activityId) { diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java index e6539c186..388f612cd 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java @@ -156,32 +156,31 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { // 1、校验秒杀活动是否存在 SeckillActivityDO seckillActivity = getSeckillActivity(updateStockReqDTO.getActivityId()); // 1.1、校验库存是否充足 - if (seckillActivity.getStock() < updateStockReqDTO.getCount()) { + if (seckillActivity.getTotalStock() < updateStockReqDTO.getCount()) { throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); } - // 2、更新活动库存 - // TODO @puhui999:考虑下并发更新 - seckillActivity.setStock(seckillActivity.getStock() + updateStockReqDTO.getCount()); - seckillActivity.setTotalStock(seckillActivity.getTotalStock() - updateStockReqDTO.getCount()); - updateSeckillActivity(seckillActivity); - - // 3、获取活动商品 + // 2、获取活动商品 List products = getSeckillProductListByActivityId(updateStockReqDTO.getActivityId()); - // 3.1、过滤出购买的商品 + // 2.1、过滤出购买的商品 SeckillProductDO product = findFirst(products, item -> ObjectUtil.equal(updateStockReqDTO.getItem().getSkuId(), item.getSkuId())); - // 3.2、检查活动商品库存是否充足 + // 2.2、检查活动商品库存是否充足 boolean isSufficient = product == null || (product.getStock() == 0 || (product.getStock() < updateStockReqDTO.getItem().getCount()) || (product.getStock() - updateStockReqDTO.getItem().getCount()) < 0); if (isSufficient) { throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); } - // 4、更新活动商品库存 - SeckillProductDO updateProduct = new SeckillProductDO(); - updateProduct.setId(product.getId()); - updateProduct.setStock(product.getStock() - updateStockReqDTO.getItem().getCount()); - // TODO @puhui999:考虑下并发更新 + // 3、更新活动商品库存 + int itemRow = seckillProductMapper.updateActivityStock(product.getId(), updateStockReqDTO.getItem().getCount()); + if (itemRow == 0) { + throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); + } + // 4、更新活动库存 + int row = seckillActivityMapper.updateActivityStock(seckillActivity.getId(), updateStockReqDTO.getCount()); + if (row == 0) { + throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); + } } @Override From 254d7828aa3f4abd927dd7330ddc730af6346b31 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 11 Sep 2023 17:48:01 +0800 Subject: [PATCH 12/17] =?UTF-8?q?mall+order:=20=E8=AE=A2=E5=8D=95=E6=B4=BB?= =?UTF-8?q?=E5=8A=A8=E7=89=B9=E6=AE=8A=E9=80=BB=E8=BE=91=E7=9A=84=E6=8A=BD?= =?UTF-8?q?=E7=A6=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/combination/CombinationApi.java | 19 +++++ .../CombinationActivityUpdateStockReqDTO.java | 40 ++++++++++ .../dto/CombinationRecordCreateReqDTO.java | 57 ++------------ .../dto/SeckillActivityUpdateStockReqDTO.java | 2 + .../promotion/enums/ErrorCodeConstants.java | 19 ++--- .../yudao-module-promotion-biz/pom.xml | 5 ++ .../api/combination/CombinationApiImpl.java | 23 ++++++ .../CombinationActivityService.java | 8 ++ .../CombinationActivityServiceImpl.java | 42 +++++++++- .../CombinationRecordServiceImpl.java | 30 +++++++- .../module/trade/api/order/TradeOrderApi.java | 11 +++ .../trade/api/order/TradeOrderApiImpl.java | 6 ++ .../convert/order/TradeOrderConvert.java | 46 +++++++---- .../dal/mysql/order/TradeOrderItemMapper.java | 2 +- .../service/order/TradeOrderQueryService.java | 9 +++ .../order/TradeOrderQueryServiceImpl.java | 7 ++ .../order/TradeOrderUpdateServiceImpl.java | 76 ++++--------------- .../order/bo/TradeAfterOrderCreateReqBO.java | 39 ++++++++++ .../order/bo/TradeBeforeOrderCreateReqBO.java | 57 ++++++++++++++ .../order/handler/TradeBargainHandler.java | 44 +++++++++++ .../handler/TradeCombinationHandler.java | 49 ++++++++++++ .../order/handler/TradeOrderHandler.java | 32 ++++++++ .../order/handler/TradeSeckillHandler.java | 44 +++++++++++ 23 files changed, 526 insertions(+), 141 deletions(-) create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationActivityUpdateStockReqDTO.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterOrderCreateReqBO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java new file mode 100644 index 000000000..ec8d5c714 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.promotion.api.combination; + +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO; + +/** + * 拼团活动 Api 接口 + * + * @author HUIHUI + */ +public interface CombinationApi { + + /** + * 更新活动库存 + * + * @param reqDTO 请求 + */ + void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO); + +} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationActivityUpdateStockReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationActivityUpdateStockReqDTO.java new file mode 100644 index 000000000..a1d0ebce7 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationActivityUpdateStockReqDTO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.promotion.api.combination.dto; + +import lombok.Data; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +/** + * 拼团活动更新活动库存 Request DTO + * + * @author HUIHUI + */ +@Data +public class CombinationActivityUpdateStockReqDTO { + + @NotNull(message = "活动编号不能为空") + private Long activityId; + + @NotNull(message = "购买数量不能为空") + private Integer count; + + @NotNull(message = "活动商品不能为空") + private Item item; + + @Data + @Valid + public static class Item { + + @NotNull(message = "SPU 编号不能为空") + private Long spuId; + + @NotNull(message = "SKU 编号活动商品不能为空") + private Long skuId; + + @NotNull(message = "购买数量不能为空") + private Integer count; + + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java index 4d4c0dafd..288a83d4c 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.promotion.api.combination.dto; import lombok.Data; -import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; // TODO @芋艿:这块要在看看 @@ -14,65 +13,25 @@ import javax.validation.constraints.NotNull; @Data public class CombinationRecordCreateReqDTO { - /** - * 拼团活动编号 - */ @NotNull(message = "拼团活动编号不能为空") private Long activityId; - /** - * spu 编号 - */ + @NotNull(message = "spu 编号不能为空") private Long spuId; - /** - * sku 编号 - */ + @NotNull(message = "sku 编号不能为空") private Long skuId; - /** - * 用户编号 - */ - @NotNull(message = "用户编号不能为空") - private Long userId; - /** - * 订单编号 - */ + @NotNull(message = "订单编号不能为空") private Long orderId; - /** - * 团长编号 - */ + + @NotNull(message = "用户编号不能为空") + private Long userId; + @NotNull(message = "团长编号不能为空") private Long headId; - /** - * 商品名字 - */ - @NotEmpty(message = "商品名字不能为空") - private String spuName; - /** - * 商品图片 - */ - @NotEmpty(message = "商品图片不能为空") - private String picUrl; - /** - * 拼团商品单价 - */ + @NotNull(message = "拼团商品单价不能为空") private Integer combinationPrice; - /** - * 用户昵称 - */ - @NotEmpty(message = "用户昵称不能为空") - private String nickname; - /** - * 用户头像 - */ - @NotEmpty(message = "用户头像不能为空") - private String avatar; - /** - * 开团状态:正在开团 拼团成功 拼团失败 - */ - @NotNull(message = "开团状态不能为空") - private Integer status; } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java index 07a25b3d6..f3cf1d2b2 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.seckill.dto; import lombok.Data; +import javax.validation.Valid; import javax.validation.constraints.NotNull; /** @@ -22,6 +23,7 @@ public class SeckillActivityUpdateStockReqDTO { private Item item; @Data + @Valid public static class Item { @NotNull(message = "SPU 编号不能为空") diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java index baca6c273..4fc58004a 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java @@ -65,18 +65,19 @@ public interface ErrorCodeConstants { // ========== 拼团活动 1013010000 ========== ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在"); ErrorCode COMBINATION_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013010001, "存在商品参加了其它拼团活动"); - ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013010002, "拼团活动已关闭不能修改"); + ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE_NOT_UPDATE = new ErrorCode(1013010002, "拼团活动已关闭不能修改"); ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013010003, "拼团活动未关闭或未结束,不能删除"); - ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013010004, "拼团不存在"); + ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013010004, "拼团失败,原因:拼团活动已关闭"); // ========== 拼团记录 1013011000 ========== - ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1013011000, "拼团失败,已参与过该拼团"); - ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013011001, "拼团失败,父拼团不存在"); - ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1013011002, "拼团失败,拼团人数已满"); - ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1013011003, "拼团失败,已参与其它拼团"); - ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1013011004, "拼团失败,活动已经结束"); - ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011005, "拼团失败,单次限购超出"); - ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011006, "拼团失败,单次限购超出"); + ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013011000, "拼团不存在"); + ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1013011001, "拼团失败,已参与过该拼团"); + ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013011002, "拼团失败,父拼团不存在"); + ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1013011003, "拼团失败,拼团人数已满"); + ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1013011004, "拼团失败,已参与其它拼团"); + ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1013011005, "拼团失败,活动已经结束"); + ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011006, "拼团失败,原因:单次限购超出"); + ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011007, "拼团失败,原因:超出总购买次数"); // ========== 砍价活动 1013012000 ========== ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1013012000, "砍价活动不存在"); diff --git a/yudao-module-mall/yudao-module-promotion-biz/pom.xml b/yudao-module-mall/yudao-module-promotion-biz/pom.xml index 266cb1511..bad2c8a35 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/pom.xml +++ b/yudao-module-mall/yudao-module-promotion-biz/pom.xml @@ -29,6 +29,11 @@ yudao-module-product-api ${revision} + + cn.iocoder.boot + yudao-module-trade-api + ${revision} + cn.iocoder.boot yudao-module-member-api diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java new file mode 100644 index 000000000..767b2e680 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.promotion.api.combination; + +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO; +import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService; + +import javax.annotation.Resource; + +/** + * 拼团活动 Api 接口实现类 + * + * @author HUIHUI + */ +public class CombinationApiImpl implements CombinationApi { + + @Resource + private CombinationActivityService activityService; + + @Override + public void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO) { + activityService.validateCombination(reqDTO); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java index 99b87df6c..c3ee01fcc 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.promotion.service.combination; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO; @@ -72,4 +73,11 @@ public interface CombinationActivityService { */ List getCombinationProductsByActivityIds(Collection activityIds); + /** + * 更新拼图活动库存 + * + * @param reqDTO 请求 + */ + void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO); + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java index c6a7c8c49..026c1a0ff 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO; @@ -16,8 +17,11 @@ import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationActivityMapper; import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationProductMapper; +import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; +import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -28,8 +32,8 @@ import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; @@ -48,11 +52,15 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic private CombinationActivityMapper combinationActivityMapper; @Resource private CombinationProductMapper combinationProductMapper; + @Resource + private CombinationRecordService combinationRecordService; @Resource private ProductSpuApi productSpuApi; @Resource private ProductSkuApi productSkuApi; + @Resource + private TradeOrderApi tradeOrderApi; @Override @Transactional(rollbackFor = Exception.class) @@ -97,7 +105,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic * 校验拼团商品是否都存在 * * @param spuId 商品 SPU 编号 - * @param products 秒杀商品 + * @param products 拼团商品 */ private void validateProductExists(Long spuId, List products) { // 1. 校验商品 spu 是否存在 @@ -123,7 +131,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic CombinationActivityDO activityDO = validateCombinationActivityExists(updateReqVO.getId()); // 校验状态 if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { - throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE); + throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE_NOT_UPDATE); } // 校验商品冲突 validateProductConflict(updateReqVO.getSpuId(), updateReqVO.getId()); @@ -205,4 +213,30 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic return combinationProductMapper.selectListByActivityIds(activityIds); } + @Override + public void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO) { + // 1、校验拼团活动是否存在 + CombinationActivityDO activity = validateCombinationActivityExists(reqDTO.getActivityId()); + // 1.1、校验活动是否开启 + if (ObjectUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { + throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE); + } + // 1.2、校验是否超出单次限购数量 + if (activity.getSingleLimitCount() < reqDTO.getCount()) { + throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED); + } + // 1.3、校验是否超出总限购数量 + List recordList = combinationRecordService.getRecordListByUserIdAndActivityId(getLoginUserId(), reqDTO.getActivityId()); + if (CollUtil.isNotEmpty(recordList)) { + // 过滤出拼团成功的 + List skuIds = convertList(recordList, CombinationRecordDO::getSkuId, + item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())); + Integer countSum = tradeOrderApi.getOrderItemCountSumByOrderIdAndSkuId(convertList(recordList, CombinationRecordDO::getOrderId, + item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds); + if (activity.getTotalLimitCount() < countSum) { + throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED); + } + } + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java index bc9c1df4c..63df4ad0d 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java @@ -2,12 +2,19 @@ package cn.iocoder.yudao.module.promotion.service.combination; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper; import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -32,10 +39,18 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @Resource private CombinationActivityService combinationActivityService; - @Resource private CombinationRecordMapper recordMapper; + @Resource + private MemberUserApi memberUserApi; + @Resource + @Lazy + private ProductSpuApi productSpuApi; + @Resource + @Lazy + private ProductSkuApi productSkuApi; + @Override @Transactional(rollbackFor = Exception.class) public void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId) { @@ -102,12 +117,12 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { // 1.5 父拼团是否存在,是否已经满了 if (reqDTO.getHeadId() != null) { // 查询进行中的父拼团 - CombinationRecordDO recordDO1 = recordMapper.selectOneByHeadId(reqDTO.getHeadId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); - if (recordDO1 == null) { + CombinationRecordDO record = recordMapper.selectOneByHeadId(reqDTO.getHeadId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); + if (record == null) { throw exception(COMBINATION_RECORD_HEAD_NOT_EXISTS); } // 校验拼团是否满足要求 - if (ObjectUtil.equal(recordDO1.getUserCount(), recordDO1.getUserSize())) { + if (ObjectUtil.equal(record.getUserCount(), record.getUserSize())) { throw exception(COMBINATION_RECORD_USER_FULL); } } @@ -117,6 +132,13 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { record.setVirtualGroup(false); record.setExpireTime(record.getStartTime().plusHours(activity.getLimitDuration())); record.setUserSize(activity.getUserSize()); + MemberUserRespDTO user = memberUserApi.getUser(reqDTO.getUserId()); + record.setNickname(user.getNickname()); + record.setAvatar(user.getAvatar()); + ProductSpuRespDTO spu = productSpuApi.getSpu(record.getSpuId()); + record.setSpuName(spu.getName()); + ProductSkuRespDTO sku = productSkuApi.getSku(record.getSkuId()); + record.setPicUrl(sku.getPicUrl()); recordMapper.insert(record); } diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApi.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApi.java index 5f98073d1..8f33fff28 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApi.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApi.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.trade.api.order; +import java.util.Collection; + /** * 订单 API 接口 * @@ -16,4 +18,13 @@ public interface TradeOrderApi { */ Long validateOrder(Long userId, Long orderItemId); + /** + * 获取订单项商品购买数量总和 + * + * @param orderIds 订单编号 + * @param skuIds sku 编号 + * @return 订单项商品购买数量总和 + */ + Integer getOrderItemCountSumByOrderIdAndSkuId(Collection orderIds, Collection skuIds); + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java index 7895386cf..3ee315ccb 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java @@ -6,6 +6,7 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.util.Collection; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_ITEM_NOT_FOUND; @@ -32,4 +33,9 @@ public class TradeOrderApiImpl implements TradeOrderApi { return item.getOrderId(); } + @Override + public Integer getOrderItemCountSumByOrderIdAndSkuId(Collection orderIds, Collection skuIds) { + return tradeOrderQueryService.getOrderItemCountSumByOrderIdAndSkuId(orderIds, skuIds); + } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java index feaa1bab0..72fe9ff59 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java @@ -14,7 +14,9 @@ import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDT import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO; import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO; import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO; import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; @@ -31,6 +33,8 @@ import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEn import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; +import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO; +import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; import org.mapstruct.Mapper; @@ -253,21 +257,15 @@ public interface TradeOrderConvert { AppTradeOrderSettlementRespVO convert0(TradePriceCalculateRespBO calculate, AddressRespDTO address); @Mappings({ - @Mapping(target = "activityId", source = "createReqVO.combinationActivityId"), - @Mapping(target = "spuId", source = "orderItem.spuId"), - @Mapping(target = "skuId", source = "orderItem.skuId"), - @Mapping(target = "userId", source = "order.userId"), - @Mapping(target = "orderId", source = "order.id"), - @Mapping(target = "headId", source = "createReqVO.combinationHeadId"), - @Mapping(target = "spuName", source = "orderItem.spuName"), - @Mapping(target = "picUrl", source = "orderItem.picUrl"), - @Mapping(target = "combinationPrice", source = "orderItem.payPrice"), - @Mapping(target = "nickname", source = "user.nickname"), - @Mapping(target = "avatar", source = "user.avatar"), - @Mapping(target = "status", ignore = true) + @Mapping(target = "activityId", source = "afterOrderCreateReqBO.combinationActivityId"), + @Mapping(target = "spuId", source = "afterOrderCreateReqBO.spuId"), + @Mapping(target = "skuId", source = "afterOrderCreateReqBO.skuId"), + @Mapping(target = "orderId", source = "afterOrderCreateReqBO.orderId"), + @Mapping(target = "userId", source = "afterOrderCreateReqBO.userId"), + @Mapping(target = "headId", source = "afterOrderCreateReqBO.combinationHeadId"), + @Mapping(target = "combinationPrice", source = "afterOrderCreateReqBO.payPrice"), }) - CombinationRecordCreateReqDTO convert(TradeOrderDO order, TradeOrderItemDO orderItem, - AppTradeOrderCreateReqVO createReqVO, MemberUserRespDTO user); + CombinationRecordCreateReqDTO convert(TradeAfterOrderCreateReqBO afterOrderCreateReqBO); List convertList02(List list); @@ -283,4 +281,24 @@ public interface TradeOrderConvert { .setFirstFixedPrice(sku.getFirstBrokerageRecord()) .setSecondFixedPrice(sku.getSecondBrokerageRecord()); } + + @Mapping(target = "activityId", source = "reqBO.seckillActivityId") + SeckillActivityUpdateStockReqDTO convert(TradeBeforeOrderCreateReqBO reqBO); + + @Mapping(target = "activityId", source = "reqBO.combinationActivityId") + CombinationActivityUpdateStockReqDTO convert1(TradeBeforeOrderCreateReqBO reqBO); + + TradeBeforeOrderCreateReqBO convert(AppTradeOrderCreateReqVO createReqVO); + + @Mappings({ + @Mapping(target = "combinationActivityId", source = "createReqVO.combinationActivityId"), + @Mapping(target = "combinationHeadId", source = "createReqVO.combinationHeadId"), + @Mapping(target = "spuId", source = "orderItem.spuId"), + @Mapping(target = "skuId", source = "orderItem.skuId"), + @Mapping(target = "orderId", source = "tradeOrderDO.id"), + @Mapping(target = "userId", source = "userId"), + @Mapping(target = "payPrice", source = "tradeOrderDO.payPrice"), + }) + TradeAfterOrderCreateReqBO convert(Long userId, AppTradeOrderCreateReqVO createReqVO, TradeOrderDO tradeOrderDO, TradeOrderItemDO orderItem); + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java index a9538cc91..e7121077b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java @@ -29,7 +29,7 @@ public interface TradeOrderItemMapper extends BaseMapperX { default List selectListByOrderIdAnSkuId(Collection orderIds, Collection skuIds) { return selectList(new LambdaQueryWrapperX() .in(TradeOrderItemDO::getOrderId, orderIds) - .eq(TradeOrderItemDO::getSkuId, skuIds)); + .in(TradeOrderItemDO::getSkuId, skuIds)); } default TradeOrderItemDO selectByIdAndUserId(Long orderItemId, Long loginUserId) { diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java index 0cd5240bd..c64de4a58 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java @@ -119,4 +119,13 @@ public interface TradeOrderQueryService { */ List getOrderItemListByOrderId(Collection orderIds); + /** + * 获取订单项商品购买数量总和 + * + * @param orderIds 订单编号 + * @param skuIds sku 编号 + * @return 订单项商品购买数量总和 + */ + Integer getOrderItemCountSumByOrderIdAndSkuId(Collection orderIds, Collection skuIds); + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java index 657c6f0f8..733ec9780 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; @@ -167,4 +168,10 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { return tradeOrderItemMapper.selectListByOrderId(orderIds); } + @Override + public Integer getOrderItemCountSumByOrderIdAndSkuId(Collection orderIds, Collection skuIds) { + List tradeOrderItems = tradeOrderItemMapper.selectListByOrderIdAnSkuId(orderIds, skuIds); + return CollectionUtils.getSumValue(tradeOrderItems, TradeOrderItemDO::getCount, Integer::sum); + } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 3ea5a76c1..a90c505e3 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -13,8 +13,6 @@ import cn.iocoder.yudao.module.member.api.address.AddressApi; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; import cn.iocoder.yudao.module.member.api.level.MemberLevelApi; import cn.iocoder.yudao.module.member.api.point.MemberPointApi; -import cn.iocoder.yudao.module.member.api.user.MemberUserApi; -import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; @@ -24,15 +22,10 @@ import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi; import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; -import cn.iocoder.yudao.module.promotion.api.bargain.BargainActivityApi; import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi; import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; -import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi; -import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO; -import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO; @@ -59,6 +52,8 @@ import cn.iocoder.yudao.module.trade.service.cart.CartService; import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; import cn.iocoder.yudao.module.trade.service.message.TradeMessageService; import cn.iocoder.yudao.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO; +import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; +import cn.iocoder.yudao.module.trade.service.order.handler.TradeOrderHandler; import cn.iocoder.yudao.module.trade.service.price.TradePriceService; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; @@ -95,6 +90,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { private TradeOrderItemMapper tradeOrderItemMapper; @Resource private TradeOrderNoRedisDAO orderNoRedisDAO; + @Resource + private List orderHandlers; @Resource private CartService cartService; @@ -118,12 +115,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Resource private BargainRecordApi bargainRecordApi; @Resource - private SeckillActivityApi seckillActivityApi; - @Resource - private BargainActivityApi bargainActivityApi; - @Resource - private MemberUserApi memberUserApi; - @Resource private MemberLevelApi memberLevelApi; @Resource private MemberPointApi memberPointApi; @@ -188,7 +179,13 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Override @Transactional(rollbackFor = Exception.class) public TradeOrderDO createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO) { - // 1. 价格计算 + // 1、执行订单创建前置处理器 + TradeBeforeOrderCreateReqBO beforeOrderCreateReqBO = TradeOrderConvert.INSTANCE.convert(createReqVO); + beforeOrderCreateReqBO.setOrderType(validateActivity(createReqVO)); + beforeOrderCreateReqBO.setCount(CollectionUtils.getSumValue(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCount, Integer::sum)); + orderHandlers.forEach(handler -> handler.beforeOrderCreate(beforeOrderCreateReqBO)); + + // 2. 价格计算 TradePriceCalculateRespBO calculateRespBO = calculatePrice(userId, createReqVO); // 2.1 插入 TradeOrderDO 订单 @@ -198,37 +195,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { // 3. 订单创建完后的逻辑 afterCreateTradeOrder(userId, createReqVO, order, orderItems, calculateRespBO); - // 3.1 拼团的特殊逻辑 - // TODO @puhui999:这个逻辑,先抽个小方法;未来要通过设计模式,把这些拼团之类的逻辑,抽象出去 - // 拼团 - if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { - createCombinationRecord(userId, createReqVO, orderItems, order); - } - // 3.2 秒杀的特殊逻辑 - if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), order.getType())) { - - } - // 3.3 砍价的特殊逻辑 // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来! return order; } - private void createCombinationRecord(Long userId, AppTradeOrderCreateReqVO createReqVO, List orderItems, TradeOrderDO order) { - MemberUserRespDTO user = memberUserApi.getUser(userId); - List recordRespDTOS = combinationRecordApi.getRecordListByUserIdAndActivityId(userId, createReqVO.getCombinationActivityId()); - // TODO 拼团一次应该只能选择一种规格的商品 - TradeOrderItemDO orderItemDO = orderItems.get(0); - if (CollUtil.isNotEmpty(recordRespDTOS)) { - List skuIds = convertList(recordRespDTOS, CombinationRecordRespDTO::getSkuId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())); - List tradeOrderItemDOS = tradeOrderItemMapper.selectListByOrderIdAnSkuId(convertList(recordRespDTOS, - CombinationRecordRespDTO::getOrderId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds); - combinationRecordApi.validateCombinationLimitCount(createReqVO.getCombinationActivityId(), - CollectionUtils.getSumValue(tradeOrderItemDOS, TradeOrderItemDO::getCount, Integer::sum), orderItemDO.getCount()); - } - - combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(order, orderItemDO, createReqVO, user)); - } // TODO @puhui999:订单超时,自动取消; @@ -310,13 +281,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { private void afterCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO, TradeOrderDO tradeOrderDO, List orderItems, TradePriceCalculateRespBO calculateRespBO) { - Integer count = getSumValue(orderItems, TradeOrderItemDO::getCount, Integer::sum); - // 1)如果是秒杀商品:额外扣减秒杀的库存; - if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), tradeOrderDO.getType())) { - seckillActivityApi.updateSeckillStock(getSeckillActivityUpdateStockReqDTO(createReqVO, orderItems, count)); - } - // 2)如果是砍价活动:额外扣减砍价的库存; - bargainActivityApi.updateBargainActivityStock(createReqVO.getBargainActivityId(), count); + // 执行订单创建后置处理器 + orderHandlers.forEach(handler -> handler.afterOrderCreate(TradeOrderConvert.INSTANCE.convert(userId, createReqVO, tradeOrderDO, orderItems.get(0)))); // 扣减积分 TODO 芋艿:待实现,需要前置; // 这个是不是应该放到支付成功之后?如果支付后的话,可能积分可以重复使用哈。资源类,都要预扣 @@ -341,19 +307,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { // 增加订单日志 TODO 芋艿:待实现 } - private SeckillActivityUpdateStockReqDTO getSeckillActivityUpdateStockReqDTO(AppTradeOrderCreateReqVO createReqVO, List orderItems, Integer count) { - SeckillActivityUpdateStockReqDTO updateStockReqDTO = new SeckillActivityUpdateStockReqDTO(); - updateStockReqDTO.setActivityId(createReqVO.getSeckillActivityId()); - updateStockReqDTO.setCount(count); - // 秒杀活动只能选择一个商品 - TradeOrderItemDO item = orderItems.get(0); - SeckillActivityUpdateStockReqDTO.Item item1 = new SeckillActivityUpdateStockReqDTO.Item(); - item1.setSpuId(item.getSpuId()); - item1.setSkuId(item.getSkuId()); - item1.setCount(item.getCount()); - updateStockReqDTO.setItem(item1); - return updateStockReqDTO; - } private void createPayOrder(TradeOrderDO order, List orderItems, TradePriceCalculateRespBO calculateRespBO) { // 创建支付单,用于后续的支付 @@ -768,6 +721,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); } + // TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来 + orderHandlers.forEach(handler -> handler.rollbackStock()); + // 2.回滚库存 List orderItems = tradeOrderItemMapper.selectListByOrderId(id); productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems)); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterOrderCreateReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterOrderCreateReqBO.java new file mode 100644 index 000000000..8a33e3eaf --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterOrderCreateReqBO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.trade.service.order.bo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 订单创建之后 Request BO + * + * @author HUIHUI + */ +@Data +public class TradeAfterOrderCreateReqBO { + + // ========== 拼团活动相关字段 ========== + + @Schema(description = "拼团活动编号", example = "1024") + private Long combinationActivityId; + + @Schema(description = "拼团团长编号", example = "2048") + private Long combinationHeadId; + + @NotNull(message = "SPU 编号不能为空") + private Long spuId; + + @NotNull(message = "SKU 编号活动商品不能为空") + private Long skuId; + + @NotNull(message = "订单编号不能为空") + private Long orderId; + + @NotNull(message = "用户编号不能为空") + private Long userId; + + @NotNull(message = "支付金额不能为空") + private Integer payPrice; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java new file mode 100644 index 000000000..e1b7faa35 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.trade.service.order.bo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +/** + * 订单创建之前 Request BO + * + * @author HUIHUI + */ +@Data +public class TradeBeforeOrderCreateReqBO { + + @NotNull(message = "订单类型不能为空") + private Integer orderType; + + // ========== 秒杀活动相关字段 ========== + + @Schema(description = "秒杀活动编号", example = "1024") + private Long seckillActivityId; + + // ========== 拼团活动相关字段 ========== + + @Schema(description = "拼团活动编号", example = "1024") + private Long combinationActivityId; + + @Schema(description = "拼团团长编号", example = "2048") + private Long combinationHeadId; + + @Schema(description = "砍价活动编号", example = "123") + private Long bargainActivityId; + + @NotNull(message = "购买数量不能为空") + private Integer count; + + @NotNull(message = "活动商品不能为空") + private Item item; + + @Data + @Valid + public static class Item { + + @NotNull(message = "SPU 编号不能为空") + private Long spuId; + + @NotNull(message = "SKU 编号活动商品不能为空") + private Long skuId; + + @NotNull(message = "购买数量不能为空") + private Integer count; + + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java new file mode 100644 index 000000000..fc410963a --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.trade.service.order.handler; + +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.module.promotion.api.bargain.BargainActivityApi; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; +import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO; +import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 砍价订单 handler 实现类 + * + * @author HUIHUI + */ +@Component +public class TradeBargainHandler implements TradeOrderHandler { + + @Resource + private BargainActivityApi bargainActivityApi; + + @Override + public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) { + // 如果是秒杀订单 + if (ObjectUtil.notEqual(TradeOrderTypeEnum.BARGAIN.getType(), reqBO.getOrderType())) { + return; + } + + // 额外扣减砍价的库存 + bargainActivityApi.updateBargainActivityStock(reqBO.getBargainActivityId(), reqBO.getCount()); + } + + @Override + public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) { + + } + + @Override + public void rollbackStock() { + + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java new file mode 100644 index 000000000..f9fce744b --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.trade.service.order.handler; + +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.module.promotion.api.combination.CombinationApi; +import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; +import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; +import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO; +import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 拼团订单 handler 接口实现类 + * + * @author HUIHUI + */ +@Component +public class TradeCombinationHandler implements TradeOrderHandler { + + @Resource + private CombinationApi combinationApi; + @Resource + private CombinationRecordApi combinationRecordApi; + + @Override + public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) { + // 如果是拼团订单; + if (ObjectUtil.notEqual(TradeOrderTypeEnum.COMBINATION.getType(), reqBO.getOrderType())) { + return; + } + + // 校验是否满足拼团活动相关限制 + combinationApi.validateCombination(TradeOrderConvert.INSTANCE.convert1(reqBO)); + } + + @Override + public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) { + // 创建砍价记录 + combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(reqBO)); + } + + @Override + public void rollbackStock() { + + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java new file mode 100644 index 000000000..37dda82ce --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.trade.service.order.handler; + +import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO; +import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; + +/** + * 订单活动特殊逻辑处理器 handler 接口 + * + * @author HUIHUI + */ +public interface TradeOrderHandler { + + /** + * 订单创建前 + * + * @param reqBO 请求 + */ + void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO); + + /** + * 订单创建后 + * + * @param reqBO 请求 + */ + void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO); + + /** + * 回滚活动相关库存 + */ + void rollbackStock(); + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java new file mode 100644 index 000000000..0774543a5 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.trade.service.order.handler; + +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi; +import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; +import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO; +import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 秒杀订单 handler 实现类 + * + * @author HUIHUI + */ +@Component +public class TradeSeckillHandler implements TradeOrderHandler { + + @Resource + private SeckillActivityApi seckillActivityApi; + + @Override + public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) { + // 如果是秒杀订单:额外扣减秒杀的库存; + if (ObjectUtil.notEqual(TradeOrderTypeEnum.SECKILL.getType(), reqBO.getOrderType())) { + return; + } + + seckillActivityApi.updateSeckillStock(TradeOrderConvert.INSTANCE.convert(reqBO)); + } + + @Override + public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) { + + } + + @Override + public void rollbackStock() { + + } + +} From 82c6354e1d2bc8f1ab6e05d9b8f7dd856c05305b Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 12 Sep 2023 09:20:42 +0800 Subject: [PATCH 13/17] =?UTF-8?q?code=20review=EF=BC=9A=E5=88=86=E9=94=80?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/trade/api/brokerage/BrokerageApi.java | 7 ++++++- .../enums/brokerage/BrokerageUserTypeEnum.java | 1 + .../record/BrokerageRecordController.java | 3 ++- .../vo/user/AppBrokerageUserMySummaryRespVO.java | 2 +- .../brokerage/record/BrokerageRecordConvert.java | 3 --- .../brokerage/user/BrokerageUserConvert.java | 12 ++++++------ .../trade/convert/order/TradeOrderConvert.java | 8 +++----- .../brokerage/record/BrokerageRecordDO.java | 4 ++-- .../brokerage/record/BrokerageRecordMapper.java | 5 +++-- .../brokerage/user/BrokerageUserMapper.java | 8 +++++--- .../service/brokerage/bo/BrokerageAddReqBO.java | 5 +++++ .../record/BrokerageRecordServiceImpl.java | 16 ++++++++++------ .../brokerage/user/BrokerageUserServiceImpl.java | 4 ++-- 13 files changed, 46 insertions(+), 32 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApi.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApi.java index 180cf4d8f..a08ce7f46 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApi.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApi.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.trade.api.brokerage.dto.BrokerageUserDTO; import javax.validation.constraints.NotNull; import java.time.LocalDateTime; +// TODO @疯狂:是不是不需要这个啦? /** * 分销 API 接口 * @@ -31,6 +32,7 @@ public interface BrokerageApi { */ default boolean bindUser(@NotNull Long userId, @NotNull Long bindUserId, @NotNull LocalDateTime registerTime) { // 注册时间在30秒内的,都算新用户 + // TODO @疯狂:这个要不抽到 service 里哈? boolean isNewUser = LocalDateTimeUtils.afterNow(registerTime.minusSeconds(30)); return bindUser(userId, bindUserId, isNewUser); } @@ -43,5 +45,8 @@ public interface BrokerageApi { * @param isNewUser 是否为新用户 * @return 是否绑定 */ - boolean bindUser(@NotNull Long userId, @NotNull Long bindUserId, @NotNull Boolean isNewUser); + boolean bindUser(@NotNull(message = "用户编号不能为空") Long userId, + @NotNull(message = "推广员编号不能为空") Long bindUserId, + @NotNull Boolean isNewUser); + } diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageUserTypeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageUserTypeEnum.java index ed71b8434..a75ad4414 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageUserTypeEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageUserTypeEnum.java @@ -6,6 +6,7 @@ import lombok.Getter; import java.util.Arrays; +// TODO @疯狂:是不是搞成层级,类似 level 这样?因为本质上,它是 1 级、2 级、3 级这样的关系哈 /** * 分销用户类型枚举 * diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/BrokerageRecordController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/BrokerageRecordController.java index e015922a0..9bb135670 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/BrokerageRecordController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/BrokerageRecordController.java @@ -55,10 +55,11 @@ public class BrokerageRecordController { public CommonResult> getBrokerageRecordPage(@Valid BrokerageRecordPageReqVO pageVO) { PageResult pageResult = brokerageRecordService.getBrokerageRecordPage(pageVO); + // 查询用户信息 Set userIds = convertSet(pageResult.getList(), BrokerageRecordDO::getUserId); userIds.addAll(convertList(pageResult.getList(), BrokerageRecordDO::getSourceUserId)); Map userMap = memberUserApi.getUserMap(userIds); - + // 拼接数据 return success(BrokerageRecordConvert.INSTANCE.convertPage(pageResult, userMap)); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java index c1b4631db..cc9a03ebc 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java @@ -19,7 +19,7 @@ public class AppBrokerageUserMySummaryRespVO { @Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234") private Integer frozenPrice; - @Schema(description = "分销用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @Schema(description = "分销用户数量(一级)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") private Integer firstBrokerageUserCount; @Schema(description = "分销用户数量(二级)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java index be0cc6bbb..90527896f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java @@ -52,15 +52,12 @@ public interface BrokerageRecordConvert { default PageResult convertPage(PageResult pageResult, Map userMap) { PageResult result = convertPage(pageResult); - for (BrokerageRecordRespVO respVO : result.getList()) { Optional.ofNullable(userMap.get(respVO.getUserId())).ifPresent(user -> respVO.setUserNickname(user.getNickname()).setUserAvatar(user.getAvatar())); - Optional.ofNullable(userMap.get(respVO.getSourceUserId())).ifPresent(user -> respVO.setSourceUserNickname(user.getNickname()).setSourceUserAvatar(user.getAvatar())); } - return result; } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java index 2a23f1095..544e29a87 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java @@ -35,18 +35,18 @@ public interface BrokerageUserConvert { Map brokerageUserCountMap, Map userOrderSummaryMap) { PageResult result = convertPage(pageResult); - for (BrokerageUserRespVO vo : result.getList()) { + for (BrokerageUserRespVO userVO : result.getList()) { // 用户信息 - copyTo(userMap.get(vo.getId()), vo); + copyTo(userMap.get(userVO.getId()), userVO); // 推广用户数量 - vo.setBrokerageUserCount(MapUtil.getInt(brokerageUserCountMap, vo.getId(), 0)); + userVO.setBrokerageUserCount(MapUtil.getInt(brokerageUserCountMap, userVO.getId(), 0)); // 推广订单数量、推广订单金额 - Optional orderSummaryOptional = Optional.ofNullable(userOrderSummaryMap.get(vo.getId())); - vo.setBrokerageOrderCount(orderSummaryOptional.map(UserBrokerageSummaryBO::getCount).orElse(0)) + Optional orderSummaryOptional = Optional.ofNullable(userOrderSummaryMap.get(userVO.getId())); + userVO.setBrokerageOrderCount(orderSummaryOptional.map(UserBrokerageSummaryBO::getCount).orElse(0)) .setBrokerageOrderPrice(orderSummaryOptional.map(UserBrokerageSummaryBO::getPrice).orElse(0)); // todo 已提现次数、已提现金额 - vo.setWithdrawCount(0).setWithdrawPrice(0); + userVO.setWithdrawCount(0).setWithdrawPrice(0); } return result; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java index 46f4362b9..484ea2f43 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java @@ -279,11 +279,9 @@ public interface TradeOrderConvert { TradeOrderDO convert(TradeOrderRemarkReqVO reqVO); default BrokerageAddReqBO convert(TradeOrderItemDO item, ProductSkuRespDTO sku) { - return new BrokerageAddReqBO().setBizId(String.valueOf(item.getId())) - .setSourceUserId(item.getUserId()) + return new BrokerageAddReqBO().setBizId(String.valueOf(item.getId())).setSourceUserId(item.getUserId()) .setBasePrice(item.getPayPrice() * item.getCount()) - .setFirstFixedPrice(sku.getSubCommissionFirstPrice()) - .setSecondFixedPrice(sku.getSubCommissionSecondPrice()) - .setTitle(BrokerageRecordBizTypeEnum.ORDER.getTitle()); + .setTitle(BrokerageRecordBizTypeEnum.ORDER.getTitle()) // TODO @疯狂:标题类似:木晴冰雪成功购买云时代的JVM原理与实战;茫农成功购买深入拆解消息队列47讲 + .setFirstFixedPrice(sku.getSubCommissionFirstPrice()).setSecondFixedPrice(sku.getSubCommissionSecondPrice()); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/BrokerageRecordDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/BrokerageRecordDO.java index a01462069..a9ececb68 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/BrokerageRecordDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/BrokerageRecordDO.java @@ -85,13 +85,13 @@ public class BrokerageRecordDO extends BaseDO { /** * 来源用户类型 *

- * 枚举 {@link BrokerageUserTypeEnum} + * 枚举 {@link BrokerageUserTypeEnum},被推广用户和 {@link #userId} 的推广层级关系 */ private Integer sourceUserType; /** * 来源用户编号 *

- * 关联 MemberUserDO.id + * 关联 MemberUserDO.id 字段,被推广用户的编号 */ private Long sourceUserId; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/BrokerageRecordMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/BrokerageRecordMapper.java index 16a0ae83a..8e749b41c 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/BrokerageRecordMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/BrokerageRecordMapper.java @@ -26,7 +26,7 @@ public interface BrokerageRecordMapper extends BaseMapperX { default PageResult selectPage(BrokerageRecordPageReqVO reqVO) { boolean sourceUserTypeCondition = reqVO.getSourceUserType() != null && !BrokerageUserTypeEnum.ALL.getType().equals(reqVO.getSourceUserType()); - + // 分页查询 return selectPage(reqVO, new LambdaQueryWrapperX() .eqIfPresent(BrokerageRecordDO::getUserId, reqVO.getUserId()) .eqIfPresent(BrokerageRecordDO::getBizType, reqVO.getBizType()) @@ -54,7 +54,8 @@ public interface BrokerageRecordMapper extends BaseMapperX { BrokerageRecordDO::getUserId, userId); } - @Select("SELECT COUNT(1), SUM(price) FROM trade_brokerage_record WHERE user_id = #{userId} AND biz_type = #{bizType} AND status = #{status}") + @Select("SELECT COUNT(1), SUM(price) FROM trade_brokerage_record " + + "WHERE user_id = #{userId} AND biz_type = #{bizType} AND status = #{status}") UserBrokerageSummaryBO selectCountAndSumPriceByUserIdAndBizTypeAndStatus(@Param("userId") Long userId, @Param("bizType") Integer bizType, @Param("status") Integer status); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java index 1566767f3..18ddef3b2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java @@ -36,8 +36,9 @@ public interface BrokerageUserMapper extends BaseMapperX { } else if (BrokerageUserTypeEnum.SECOND.getType().equals(reqVO.getUserType())) { buildSecondBindUserCondition(reqVO.getBindUserId(), wrapper); } else { + // TODO @疯狂:要不要把这个逻辑,挪到 Service 里,算出子用户有哪些,然后 IN? buildFirstBindUserCondition(reqVO.getBindUserId(), wrapper); - buildSecondBindUserCondition(reqVO.getBindUserId(), wrapper.or()); + buildSecondBindUserCondition(reqVO.getBindUserId(), wrapper.or()); // 通过 or 实现多个条件 } } @@ -45,8 +46,8 @@ public interface BrokerageUserMapper extends BaseMapperX { wrapper.eq(BrokerageUserDO::getBindUserId, bindUserId); } - static void buildSecondBindUserCondition(Long bindUserId, LambdaQueryWrapper w) { - w.inSql(BrokerageUserDO::getBindUserId, StrUtil.format("SELECT id FROM trade_brokerage_user WHERE bind_user_id = {}", bindUserId)); + static void buildSecondBindUserCondition(Long bindUserId, LambdaQueryWrapper wrapper) { + wrapper.inSql(BrokerageUserDO::getBindUserId, StrUtil.format("SELECT id FROM trade_brokerage_user WHERE bind_user_id = {}", bindUserId)); } /** @@ -142,4 +143,5 @@ public interface BrokerageUserMapper extends BaseMapperX { @Select("SELECT COUNT(1) from trade_brokerage_user WHERE bind_user_id IN (SELECT id FROM trade_brokerage_user WHERE bind_user_id = #{bindUserId})") Long selectCountByBindUserIdInBindUserId(Long bindUserId); + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java index 0412abc58..1b5de5431 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java @@ -5,6 +5,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; /** @@ -30,6 +31,7 @@ public class BrokerageAddReqBO { /** * 一级佣金(固定) */ + @NotNull(message = "一级佣金(固定)不能为空") private Integer firstFixedPrice; /** * 二级佣金(固定) @@ -39,10 +41,13 @@ public class BrokerageAddReqBO { /** * 来源用户编号 */ + @NotNull(message = "来源用户编号不能为空") private Long sourceUserId; /** * 佣金记录标题 */ + @NotEmpty(message = "佣金记录标题不能为空") private String title; + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java index 5dd00cc22..e5dc343ef 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.service.brokerage.record; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; @@ -154,21 +155,24 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { int totalBrokerage = 0; List records = new ArrayList<>(); for (BrokerageAddReqBO item : list) { - Integer fixedPrice = 0; + // 计算金额 + Integer fixedPrice; if (BrokerageUserTypeEnum.FIRST.equals(sourceUserType)) { fixedPrice = item.getFirstFixedPrice(); } else if (BrokerageUserTypeEnum.SECOND.equals(sourceUserType)) { fixedPrice = item.getSecondFixedPrice(); + } else { + throw new IllegalArgumentException(StrUtil.format("来源用户({}) 不合法", sourceUserType)); } - - int brokeragePerItem = calculatePrice(item.getBasePrice(), brokeragePercent, fixedPrice); - if (brokeragePerItem <= 0) { + int brokeragePrice = calculatePrice(item.getBasePrice(), brokeragePercent, fixedPrice); + if (brokeragePrice <= 0) { continue; } + totalBrokerage += brokeragePrice; + // 创建记录实体 records.add(BrokerageRecordConvert.INSTANCE.convert(user, bizType, item.getBizId(), - brokerageFrozenDays, brokeragePerItem, unfreezeTime, item.getTitle(), + brokerageFrozenDays, brokeragePrice, unfreezeTime, item.getTitle(), item.getSourceUserId(), sourceUserType.getType())); - totalBrokerage += brokeragePerItem; } if (CollUtil.isEmpty(records)) { return; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java index 11ab5c6c1..e317f2b7f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java @@ -134,7 +134,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { @Override public Long getBrokerageUserCountByBindUserId(Long bindUserId, BrokerageUserTypeEnum userType) { switch (userType) { - case ALL: + case ALL: // TODO @疯狂:ALL 是不是不用搞个枚举,默认为空就是不过滤哈~ Long firstCount = brokerageUserMapper.selectCountByBindUserId(bindUserId); Long secondCount = brokerageUserMapper.selectCountByBindUserIdInBindUserId(bindUserId); return firstCount + secondCount; @@ -183,7 +183,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { public Boolean getUserBrokerageEnabled(Long userId) { // 全局分销功能是否开启 TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig(); - if (tradeConfig == null || !BooleanUtil.isTrue(tradeConfig.getBrokerageEnabled())) { + if (tradeConfig == null || BooleanUtil.isFalse(tradeConfig.getBrokerageEnabled())) { return false; } From e8bdd8349c45893128171ab907b6c4c77b235f43 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 12 Sep 2023 13:54:52 +0800 Subject: [PATCH 14/17] =?UTF-8?q?code=20review=EF=BC=9A=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E9=83=A8=E5=88=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../product/api/sku/dto/ProductSkuRespDTO.java | 1 + .../api/combination/CombinationApi.java | 2 ++ .../CombinationActivityUpdateStockReqDTO.java | 2 ++ .../dto/CombinationRecordCreateReqDTO.java | 2 ++ .../dto/SeckillActivityUpdateStockReqDTO.java | 2 ++ .../mysql/bargain/BargainActivityMapper.java | 2 +- .../seckillactivity/SeckillProductMapper.java | 2 +- .../bargain/BargainActivityServiceImpl.java | 4 ++-- .../CombinationActivityServiceImpl.java | 18 ++++++++++++------ .../CombinationRecordServiceImpl.java | 1 + .../seckill/SeckillActivityService.java | 13 ------------- .../seckill/SeckillActivityServiceImpl.java | 18 ++++-------------- .../trade/convert/order/TradeOrderConvert.java | 3 +-- .../order/TradeOrderUpdateServiceImpl.java | 3 ++- 14 files changed, 33 insertions(+), 40 deletions(-) diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java index b69bbd5ec..03641012f 100644 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java +++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java @@ -59,6 +59,7 @@ public class ProductSkuRespDTO { * 商品体积,单位:m^3 平米 */ private Double volume; + // TODO @puhui999:firstBrokeragePrice ;尴尬,我当时打错了;secondBrokeragePrice /** * 一级分销的佣金,单位:分 */ diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java index ec8d5c714..11ea1c4f3 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.combination; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO; +// TODO @puhui999:是不是改成 CombinationActivityApi /** * 拼团活动 Api 接口 * @@ -14,6 +15,7 @@ public interface CombinationApi { * * @param reqDTO 请求 */ + // TODO @puhui999:应该是更新哇?还是校验哈; void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO); } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationActivityUpdateStockReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationActivityUpdateStockReqDTO.java index a1d0ebce7..078f22fb0 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationActivityUpdateStockReqDTO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationActivityUpdateStockReqDTO.java @@ -13,6 +13,8 @@ import javax.validation.constraints.NotNull; @Data public class CombinationActivityUpdateStockReqDTO { + // TODO @puhui999:是不是一个 activityId、count、skuId 参数就完事啦。 + @NotNull(message = "活动编号不能为空") private Long activityId; diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java index 288a83d4c..21e6d4965 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java @@ -13,6 +13,8 @@ import javax.validation.constraints.NotNull; @Data public class CombinationRecordCreateReqDTO { + // TODO @puhui999:注释还是要的哈 + @NotNull(message = "拼团活动编号不能为空") private Long activityId; diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java index f3cf1d2b2..fa274744d 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java @@ -13,6 +13,8 @@ import javax.validation.constraints.NotNull; @Data public class SeckillActivityUpdateStockReqDTO { + // TODO @puhui999:可以不用 dto,直接 activityId、skuId、count 即可 + @NotNull(message = "活动编号不能为空") private Long activityId; diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java index 28366dc89..94d46d1eb 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java @@ -39,7 +39,7 @@ public interface BargainActivityMapper extends BaseMapperX { default int updateActivityStock(Long id, int count) { return update(null, new LambdaUpdateWrapper() .eq(BargainActivityDO::getId, id) - .gt(BargainActivityDO::getStock, 0) + .gt(BargainActivityDO::getStock, 0) // TODO @puhui999:不是 > 0,是要大于 count 哈 .setSql("stock = stock - " + count)); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java index 79eee0cec..13e2c1e2f 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java @@ -34,7 +34,7 @@ public interface SeckillProductMapper extends BaseMapperX { default int updateActivityStock(Long id, int count) { return update(null, new LambdaUpdateWrapper() .eq(SeckillProductDO::getId, id) - .gt(SeckillProductDO::getStock, 0) + .gt(SeckillProductDO::getStock, 0) // TODO @puhui999:不是 > 0,是要大于 count 哈 .setSql("stock = stock - " + count)); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java index 158766daf..9c79c4ad4 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java @@ -82,8 +82,8 @@ public class BargainActivityServiceImpl implements BargainActivityService { } // 更新砍价库存 - int row = bargainActivityMapper.updateActivityStock(id, count); - if (row == 0) { + int updateCount = bargainActivityMapper.updateActivityStock(id, count); + if (updateCount == 0) { throw exception(BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL); } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java index 026c1a0ff..1471353e8 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java @@ -215,23 +215,29 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @Override public void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO) { - // 1、校验拼团活动是否存在 + // 1.1 校验拼团活动是否存在 CombinationActivityDO activity = validateCombinationActivityExists(reqDTO.getActivityId()); - // 1.1、校验活动是否开启 + // 1.2 校验活动是否开启 if (ObjectUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE); } - // 1.2、校验是否超出单次限购数量 + // 1.3 校验是否超出单次限购数量 if (activity.getSingleLimitCount() < reqDTO.getCount()) { throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED); } - // 1.3、校验是否超出总限购数量 - List recordList = combinationRecordService.getRecordListByUserIdAndActivityId(getLoginUserId(), reqDTO.getActivityId()); + + // 2. 校验是否超出总限购数量 + // TODO @puhui999:userId 应该接口传递哈;要保证 service 无状态 + List recordList = combinationRecordService.getRecordListByUserIdAndActivityId( + getLoginUserId(), reqDTO.getActivityId()); + // TODO @puhui999:最好 if true return;减少括号层数 if (CollUtil.isNotEmpty(recordList)) { // 过滤出拼团成功的 + // TODO @puhui999:count 要不存一个在 record 里? List skuIds = convertList(recordList, CombinationRecordDO::getSkuId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())); - Integer countSum = tradeOrderApi.getOrderItemCountSumByOrderIdAndSkuId(convertList(recordList, CombinationRecordDO::getOrderId, + Integer countSum = tradeOrderApi.getOrderItemCountSumByOrderIdAndSkuId(convertList(recordList, + CombinationRecordDO::getOrderId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds); if (activity.getTotalLimitCount() < countSum) { throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java index 63df4ad0d..556e47363 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java @@ -128,6 +128,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { } // 2. 创建拼团记录 + // TODO @puhui999:可以把 user、spu、sku 一起放 convert 里哈; CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO); record.setVirtualGroup(false); record.setExpireTime(record.getStartTime().plusHours(activity.getLimitDuration())); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java index 8ecb29466..89fa6fb84 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java @@ -34,25 +34,12 @@ public interface SeckillActivityService { */ void updateSeckillActivity(@Valid SeckillActivityUpdateReqVO updateReqVO); - /** - * 更新秒杀活动 - * - * @param activityDO 秒杀活动 - */ - void updateSeckillActivity(SeckillActivityDO activityDO); - /** * 更新秒杀库存 * * @param updateStockReqDTO 更新信息 */ void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO); - /** - * 更新秒杀活动商品 - * - * @param productList 活动商品列表 - */ - void updateSeckillActivityProductList(List productList); /** * 关闭秒杀活动 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java index 388f612cd..da098914c 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java @@ -145,11 +145,6 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { updateSeckillProduct(updateObj, updateReqVO.getProducts()); } - @Override - public void updateSeckillActivity(SeckillActivityDO activityDO) { - seckillActivityMapper.updateById(activityDO); - } - @Override @Transactional(rollbackFor = Exception.class) public void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO) { @@ -171,23 +166,18 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { } // 3、更新活动商品库存 - int itemRow = seckillProductMapper.updateActivityStock(product.getId(), updateStockReqDTO.getItem().getCount()); - if (itemRow == 0) { + int updateCount = seckillProductMapper.updateActivityStock(product.getId(), updateStockReqDTO.getItem().getCount()); + if (updateCount == 0) { throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); } // 4、更新活动库存 - int row = seckillActivityMapper.updateActivityStock(seckillActivity.getId(), updateStockReqDTO.getCount()); - if (row == 0) { + updateCount = seckillActivityMapper.updateActivityStock(seckillActivity.getId(), updateStockReqDTO.getCount()); + if (updateCount == 0) { throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); } } - @Override - public void updateSeckillActivityProductList(List productList) { - seckillProductMapper.updateBatch(productList); - } - /** * 更新秒杀商品 * diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java index 0d4b30829..b31aaa007 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java @@ -34,7 +34,6 @@ import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEn import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; -import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO; import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; @@ -281,7 +280,7 @@ public interface TradeOrderConvert { return new BrokerageAddReqBO().setBizId(String.valueOf(item.getId())).setSourceUserId(item.getUserId()) .setBasePrice(item.getPayPrice() * item.getCount()) .setTitle(BrokerageRecordBizTypeEnum.ORDER.getTitle()) // TODO @疯狂:标题类似:木晴冰雪成功购买云时代的JVM原理与实战;茫农成功购买深入拆解消息队列47讲 - .setFirstFixedPrice(sku.getFirstBrokerageRecord()).getSecondBrokerageRecord(sku.getSecondBrokerageRecord()); + .setFirstFixedPrice(sku.getFirstBrokerageRecord()).setSecondFixedPrice(sku.getSecondBrokerageRecord()); } @Mapping(target = "activityId", source = "reqBO.seckillActivityId") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index a90c505e3..d8e82c3e3 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -542,11 +542,12 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { int orderPayPrice = order.getAdjustPrice() != null ? (order.getPayPrice() - order.getAdjustPrice()) + reqVO.getAdjustPrice() : order.getPayPrice() + reqVO.getAdjustPrice(); update.setPayPrice(orderPayPrice); - // TODO @芋艿:改价时,赠送的积分,要不要做改动??? tradeOrderMapper.updateById(update); + // TODO @芋艿:改价时,赠送的积分,要不要做改动??? // TODO @puhui999:应该是按照 payPrice 分配;并且要考虑取余问题;payPrice 也要考虑,item 里的 // TODO:先按 adjustPrice 实现,没明白 payPrice 怎么搞哈哈哈 + // TODO @puhui999:就是对比新老 adjustPrice 的差值,然后计算补充的 adjustPrice 最终值;另外,可以不用区分 items.size 是不是 > 1 哈;应该是一致的逻辑;分摊的逻辑,有点类似 dividePrice 方法噢; // 5、更新 TradeOrderItem if (items.size() > 1) { // TradeOrderItemDO 需要做 adjustPrice 的分摊 From 9358639c417849bf2591c551a8720f42a404a091 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 12 Sep 2023 23:01:12 +0800 Subject: [PATCH 15/17] =?UTF-8?q?code=20review=EF=BC=9A=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E9=83=A8=E5=88=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../order/TradeOrderUpdateServiceImpl.java | 15 +++++++++------ .../order/bo/TradeAfterOrderCreateReqBO.java | 1 + .../order/bo/TradeBeforeOrderCreateReqBO.java | 1 + 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index d8e82c3e3..9a2b34a93 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -7,7 +7,6 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.enums.TerminalEnum; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.member.api.address.AddressApi; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; @@ -90,8 +89,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { private TradeOrderItemMapper tradeOrderItemMapper; @Resource private TradeOrderNoRedisDAO orderNoRedisDAO; + @Resource - private List orderHandlers; + private List tradeOrderHandlers; @Resource private CartService cartService; @@ -180,10 +180,12 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Transactional(rollbackFor = Exception.class) public TradeOrderDO createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO) { // 1、执行订单创建前置处理器 + // TODO @puhui999:最好也抽个 beforeOrderCreate 方法; TradeBeforeOrderCreateReqBO beforeOrderCreateReqBO = TradeOrderConvert.INSTANCE.convert(createReqVO); beforeOrderCreateReqBO.setOrderType(validateActivity(createReqVO)); - beforeOrderCreateReqBO.setCount(CollectionUtils.getSumValue(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCount, Integer::sum)); - orderHandlers.forEach(handler -> handler.beforeOrderCreate(beforeOrderCreateReqBO)); + beforeOrderCreateReqBO.setCount(getSumValue(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCount, Integer::sum)); + // TODO @puhui999:这里有个纠结点;handler 的定义是只处理指定类型的订单的拓展逻辑;还是通用的 handler,类似可以处理优惠劵等等 + tradeOrderHandlers.forEach(handler -> handler.beforeOrderCreate(beforeOrderCreateReqBO)); // 2. 价格计算 TradePriceCalculateRespBO calculateRespBO = calculatePrice(userId, createReqVO); @@ -282,7 +284,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { TradeOrderDO tradeOrderDO, List orderItems, TradePriceCalculateRespBO calculateRespBO) { // 执行订单创建后置处理器 - orderHandlers.forEach(handler -> handler.afterOrderCreate(TradeOrderConvert.INSTANCE.convert(userId, createReqVO, tradeOrderDO, orderItems.get(0)))); + tradeOrderHandlers.forEach(handler -> handler.afterOrderCreate(TradeOrderConvert.INSTANCE.convert(userId, createReqVO, tradeOrderDO, orderItems.get(0)))); + // 扣减积分 TODO 芋艿:待实现,需要前置; // 这个是不是应该放到支付成功之后?如果支付后的话,可能积分可以重复使用哈。资源类,都要预扣 @@ -723,7 +726,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { } // TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来 - orderHandlers.forEach(handler -> handler.rollbackStock()); + tradeOrderHandlers.forEach(handler -> handler.rollbackStock()); // 2.回滚库存 List orderItems = tradeOrderItemMapper.selectListByOrderId(id); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterOrderCreateReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterOrderCreateReqBO.java index 8a33e3eaf..0a96745d9 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterOrderCreateReqBO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterOrderCreateReqBO.java @@ -5,6 +5,7 @@ import lombok.Data; import javax.validation.constraints.NotNull; +// TODO 芋艿:在想想这些参数的定义 /** * 订单创建之后 Request BO * diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java index e1b7faa35..e78c4a460 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java @@ -6,6 +6,7 @@ import lombok.Data; import javax.validation.Valid; import javax.validation.constraints.NotNull; +// TODO 芋艿:在想想这些参数的定义 /** * 订单创建之前 Request BO * From bcb3b19418ee81e27f23c14ef4c68d60dd5e24dc Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Wed, 13 Sep 2023 17:28:42 +0800 Subject: [PATCH 16/17] =?UTF-8?q?=E9=92=B1=E5=8C=85=E5=85=85=E5=80=BC=20?= =?UTF-8?q?=E8=A1=A8=E7=BB=93=E6=9E=84=E8=AE=BE=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/pay_wallet.sql | 55 +++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/sql/mysql/pay_wallet.sql b/sql/mysql/pay_wallet.sql index 7d092ef45..9fab83c0e 100644 --- a/sql/mysql/pay_wallet.sql +++ b/sql/mysql/pay_wallet.sql @@ -4,18 +4,18 @@ DROP TABLE IF EXISTS `pay_wallet`; CREATE TABLE `pay_wallet` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', - `user_id` bigint NOT NULL COMMENT '用户编号', - `user_type` tinyint NOT NULL DEFAULT 0 COMMENT '用户类型', - `balance` int NOT NULL DEFAULT 0 COMMENT '余额,单位分', - `total_expense` int NOT NULL DEFAULT 0 COMMENT '累计支出,单位分', - `total_recharge` int NOT NULL DEFAULT 0 COMMENT '累计充值,单位分', - `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', - `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', - `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', - `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', + `user_id` bigint NOT NULL COMMENT '用户编号', + `user_type` tinyint NOT NULL DEFAULT 0 COMMENT '用户类型', + `balance` int NOT NULL DEFAULT 0 COMMENT '余额,单位分', + `total_expense` int NOT NULL DEFAULT 0 COMMENT '累计支出,单位分', + `total_recharge` int NOT NULL DEFAULT 0 COMMENT '累计充值,单位分', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB COMMENT='会员钱包表'; @@ -41,3 +41,34 @@ CREATE TABLE `pay_wallet_transaction` `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB COMMENT='会员钱包流水表'; + +-- ---------------------------- +-- 会员钱包充值 +-- ---------------------------- +DROP TABLE IF EXISTS `pay_wallet_recharge`; +CREATE TABLE `pay_wallet_recharge` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', + `wallet_id` bigint NOT NULL COMMENT '会员钱包 id', + `price` int NOT NULL COMMENT '用户实际到账余额,例如充 100 送 20,则该值是 120', + `pay_price` int NOT NULL COMMENT '实际支付金额', + `wallet_bonus` int NOT NULL COMMENT '钱包赠送金额', + `pay_status` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否已支付:[0:未支付 1:已经支付过]', + `pay_order_id` bigint NULL COMMENT '支付订单编号', + `pay_channel_code` varchar(16) NULL COMMENT '支付成功的支付渠道', + `pay_time` datetime NULL COMMENT '订单支付时间', + `wallet_transaction_id` bigint NULL COMMENT '充值钱包流水', + `pay_refund_id` bigint NULL COMMENT '支付退款单编号', + `refund_price` int NOT NULL DEFAULT 0 COMMENT '退款金额,包含赠送金额', + `refund_pay_price` int NOT NULL DEFAULT 0 COMMENT '退款支付金额', + `refund_wallet_bonus` int NOT NULL DEFAULT 0 COMMENT '退款钱包赠送金额', + `refund_wallet_transaction_id` bigint NULL COMMENT '充值退款钱包流水', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB COMMENT='会员钱包充值'; + From 0e1b8126dd6cd28e1cd55224810fb60c7b8eb08e Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Thu, 14 Sep 2023 16:55:31 +0800 Subject: [PATCH 17/17] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=92=B1=E5=8C=85?= =?UTF-8?q?=E5=85=85=E5=80=BC=E3=80=82=E5=90=AF=E5=8A=A8=E6=8A=A5=E9=94=99?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/pay_wallet.sql | 3 +- .../api/combination/CombinationApiImpl.java | 2 + .../CombinationRecordServiceImpl.java | 1 + .../module/pay/enums/ErrorCodeConstants.java | 5 + .../AppPayWalletRechargeController.java | 55 +++++++ .../AppPayWalletTransactionController.java | 1 - .../AppPayWalletRechargeCreateReqVO.java | 22 +++ .../AppPayWalletRechargeCreateRespVO.java | 15 ++ .../wallet/PayWalletRechargeConvert.java | 27 ++++ .../pay/dal/mysql/wallet/PayWalletMapper.java | 13 ++ .../wallet/PayWalletRechargeService.java | 29 ++++ .../wallet/PayWalletRechargeServiceImpl.java | 135 ++++++++++++++++++ .../pay/service/wallet/PayWalletService.java | 14 +- .../service/wallet/PayWalletServiceImpl.java | 27 +++- 14 files changed, 335 insertions(+), 14 deletions(-) create mode 100644 yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletRechargeController.java create mode 100644 yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/recharge/AppPayWalletRechargeCreateReqVO.java create mode 100644 yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/recharge/AppPayWalletRechargeCreateRespVO.java create mode 100644 yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletRechargeConvert.java create mode 100644 yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeService.java create mode 100644 yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java diff --git a/sql/mysql/pay_wallet.sql b/sql/mysql/pay_wallet.sql index 9fab83c0e..e9cc6a288 100644 --- a/sql/mysql/pay_wallet.sql +++ b/sql/mysql/pay_wallet.sql @@ -57,12 +57,11 @@ CREATE TABLE `pay_wallet_recharge` `pay_order_id` bigint NULL COMMENT '支付订单编号', `pay_channel_code` varchar(16) NULL COMMENT '支付成功的支付渠道', `pay_time` datetime NULL COMMENT '订单支付时间', - `wallet_transaction_id` bigint NULL COMMENT '充值钱包流水', `pay_refund_id` bigint NULL COMMENT '支付退款单编号', `refund_price` int NOT NULL DEFAULT 0 COMMENT '退款金额,包含赠送金额', `refund_pay_price` int NOT NULL DEFAULT 0 COMMENT '退款支付金额', `refund_wallet_bonus` int NOT NULL DEFAULT 0 COMMENT '退款钱包赠送金额', - `refund_wallet_transaction_id` bigint NULL COMMENT '充值退款钱包流水', + `refund_time` datetime NULL COMMENT '退款时间', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java index 767b2e680..6c8ac989d 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.combination; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO; import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService; +import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -10,6 +11,7 @@ import javax.annotation.Resource; * * @author HUIHUI */ +@Service public class CombinationApiImpl implements CombinationApi { @Resource diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java index 556e47363..c82621805 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java @@ -38,6 +38,7 @@ import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; public class CombinationRecordServiceImpl implements CombinationRecordService { @Resource + @Lazy private CombinationActivityService combinationActivityService; @Resource private CombinationRecordMapper recordMapper; diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java index f3d6d8685..62adb63c5 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java @@ -46,6 +46,11 @@ public interface ErrorCodeConstants { ErrorCode WALLET_TRANSACTION_NOT_FOUND = new ErrorCode(1007007002, "未找到对应的钱包交易"); ErrorCode WALLET_REFUND_AMOUNT_ERROR = new ErrorCode(1007007003, "钱包退款金额不对"); ErrorCode WALLET_REFUND_EXIST = new ErrorCode(1007007004, "已经存在钱包退款"); + ErrorCode WALLET_RECHARGE_NOT_FOUND = new ErrorCode(1007007005, "钱包充值记录不存在"); + ErrorCode WALLET_RECHARGE_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1007007006, "钱包充值更新支付状态失败,钱包充值记录不是【未支付】状态"); + ErrorCode WALLET_RECHARGE_UPDATE_PAID_PAY_ORDER_ID_ERROR = new ErrorCode(1007007007, "钱包充值更新支付状态失败,支付单编号不匹配"); + ErrorCode WALLET_RECHARGE_UPDATE_PAID_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1007007008, "钱包充值更新支付状态失败,支付单状态不是【支付成功】状态"); + ErrorCode WALLET_RECHARGE_UPDATE_PAID_PAY_PRICE_NOT_MATCH = new ErrorCode(1007007009, "钱包充值更新支付状态失败,支付单金额不匹配"); // ========== 示例订单 1007900000 ========== ErrorCode DEMO_ORDER_NOT_FOUND = new ErrorCode(1007900000, "示例订单不存在"); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletRechargeController.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletRechargeController.java new file mode 100644 index 000000000..0d8ae4913 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletRechargeController.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.pay.controller.app.wallet; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO; +import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge.AppPayWalletRechargeCreateReqVO; +import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge.AppPayWalletRechargeCreateRespVO; +import cn.iocoder.yudao.module.pay.convert.wallet.PayWalletRechargeConvert; +import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargeDO; +import cn.iocoder.yudao.module.pay.service.wallet.PayWalletRechargeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.annotation.security.PermitAll; +import javax.validation.Valid; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserType; + +@Tag(name = "用户 APP - 钱包充值") +@RestController +@RequestMapping("/pay/wallet-recharge") +@Validated +@Slf4j +public class AppPayWalletRechargeController { + + @Resource + private PayWalletRechargeService payWalletRechargeService; + + @PostMapping("/create") + @Operation(summary = "创建钱包充值记录") + public CommonResult createWalletRecharge(@Valid @RequestBody AppPayWalletRechargeCreateReqVO reqVO) { + PayWalletRechargeDO walletRecharge = payWalletRechargeService.createWalletRecharge(getLoginUserId(), + getLoginUserType(), reqVO); + return success(PayWalletRechargeConvert.INSTANCE.convert(walletRecharge)); + } + + @PostMapping("/update-paid") + @Operation(summary = "更新钱包充值为已充值") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob + @PermitAll // 无需登录,安全由 内部校验实现 + @OperateLog(enable = false) // 禁用操作日志,因为没有操作人 + public CommonResult updateWalletRechargerPaid(@RequestBody PayOrderNotifyReqDTO notifyReqDTO) { + payWalletRechargeService.updateWalletRechargerPaid(Long.valueOf(notifyReqDTO.getMerchantOrderId()), + notifyReqDTO.getPayOrderId()); + return success(true); + } +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletTransactionController.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletTransactionController.java index f9e908845..db0c7844d 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletTransactionController.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletTransactionController.java @@ -18,7 +18,6 @@ import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.validation.Valid; - import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/recharge/AppPayWalletRechargeCreateReqVO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/recharge/AppPayWalletRechargeCreateReqVO.java new file mode 100644 index 000000000..1478c4ceb --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/recharge/AppPayWalletRechargeCreateReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.DecimalMin; +import javax.validation.constraints.NotNull; + +@Schema(description = "用户 APP - 创建钱包充值 Request VO") +@Data +public class AppPayWalletRechargeCreateReqVO { + + @Schema(description = "支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") + @NotNull(message = "支付金额不能为空") + @DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零") + private Integer payPrice; + + @Schema(description = "钱包赠送金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") + @NotNull(message = "钱包赠送金额不能为空") + @DecimalMin(value = "0", message = "钱包赠送金额必须大于等于零") + private Integer walletBonus; +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/recharge/AppPayWalletRechargeCreateRespVO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/recharge/AppPayWalletRechargeCreateRespVO.java new file mode 100644 index 000000000..b1a80d2b3 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/recharge/AppPayWalletRechargeCreateRespVO.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 APP - 创建钱包充值 Resp VO") +@Data +public class AppPayWalletRechargeCreateRespVO { + + @Schema(description = "钱包充值编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "支付订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Long payOrderId; +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletRechargeConvert.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletRechargeConvert.java new file mode 100644 index 000000000..173cf75de --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletRechargeConvert.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.pay.convert.wallet; + +import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge.AppPayWalletRechargeCreateReqVO; +import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge.AppPayWalletRechargeCreateRespVO; +import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargeDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * @author jason + */ +@Mapper +public interface PayWalletRechargeConvert { + + PayWalletRechargeConvert INSTANCE = Mappers.getMapper(PayWalletRechargeConvert.class); + + PayWalletRechargeDO convert(AppPayWalletRechargeCreateReqVO vo); + + default PayWalletRechargeDO convert(Long walletId, AppPayWalletRechargeCreateReqVO vo) { + PayWalletRechargeDO walletRecharge = convert(vo); + return walletRecharge.setWalletId(walletId) + .setPrice(walletRecharge.getPayPrice() + walletRecharge.getWalletBonus()); + } + + AppPayWalletRechargeCreateRespVO convert(PayWalletRechargeDO bean); + +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java index ef695c9fe..b93c240d2 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java @@ -42,6 +42,19 @@ public interface PayWalletMapper extends BaseMapperX { .ge(PayWalletDO::getBalance, price); // cas 逻辑 return update(null, lambdaUpdateWrapper); } + + /** + * 当充值的时候,更新钱包 + * @param price 钱包金额 + * @param id 钱包 id + */ + default int updateWhenRecharge(Integer price, Long id){ + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" balance = balance + " + price + + ", total_recharge = total_recharge + " + price) + .eq(PayWalletDO::getId, id); + return update(null, lambdaUpdateWrapper); + } } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeService.java new file mode 100644 index 000000000..0752dbe99 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeService.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.pay.service.wallet; + +import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge.AppPayWalletRechargeCreateReqVO; +import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargeDO; + +/** + * 钱包充值 Service 接口 + * + * @author jason + */ +public interface PayWalletRechargeService { + + /** + * 创建钱包充值记录 + * @param userId 用户 id + * @param userType 用户类型 + * @param vo 钱包充值请求 vo + * @return 钱包充值记录 + */ + PayWalletRechargeDO createWalletRecharge(Long userId, Integer userType, AppPayWalletRechargeCreateReqVO vo); + + + /** + * 更新钱包充值成功 + * @param walletRechargeId 钱包充值 id + * @param payOrderId 支付订单 id + */ + void updateWalletRechargerPaid(Long walletRechargeId, Long payOrderId); +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java new file mode 100644 index 000000000..a68f034bc --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java @@ -0,0 +1,135 @@ +package cn.iocoder.yudao.module.pay.service.wallet; + +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; +import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge.AppPayWalletRechargeCreateReqVO; +import cn.iocoder.yudao.module.pay.convert.wallet.PayWalletRechargeConvert; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargeDO; +import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletRechargeMapper; +import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; +import cn.iocoder.yudao.module.pay.service.order.PayOrderService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.time.Duration; +import java.time.LocalDateTime; + +import static cn.hutool.core.util.ObjectUtil.notEqual; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime; +import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; + +/** + * 钱包充值 Service 实现类 + * + * @author jason + */ +@Service +@Slf4j +public class PayWalletRechargeServiceImpl implements PayWalletRechargeService { + /** + * TODO 放到 配置文件中 + */ + private static final Long WALLET_PAY_APP_ID = 8L; + + private static final String WALLET_RECHARGE_ORDER_SUBJECT = "钱包余额充值"; + + @Resource + private PayWalletRechargeMapper walletRechargeMapper; + @Resource + private PayWalletService payWalletService; + @Resource + private PayOrderService payOrderService; + + + @Override + @Transactional(rollbackFor = Exception.class) + public PayWalletRechargeDO createWalletRecharge(Long userId, Integer userType, AppPayWalletRechargeCreateReqVO vo) { + // 1. 获取钱包 + PayWalletDO wallet = payWalletService.getOrCreateWallet(userId, userType); + // 2. 新增钱包充值记录 + PayWalletRechargeDO walletRecharge = PayWalletRechargeConvert.INSTANCE.convert(wallet.getId(), vo); + walletRechargeMapper.insert(walletRecharge); + // 3.创建支付单 + Long payOrderId = payOrderService.createOrder(new PayOrderCreateReqDTO() + .setAppId(WALLET_PAY_APP_ID).setUserIp(getClientIP()) + .setMerchantOrderId(walletRecharge.getId().toString()) // 业务的订单编号 + .setSubject(WALLET_RECHARGE_ORDER_SUBJECT).setBody("").setPrice(walletRecharge.getPayPrice()) + .setExpireTime(addTime(Duration.ofHours(2L)))); + // 4.更新钱包充值记录中支付订单 + walletRechargeMapper.updateById(new PayWalletRechargeDO().setPayOrderId(payOrderId) + .setId(walletRecharge.getId())); + return walletRechargeMapper.selectById(walletRecharge.getId()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateWalletRechargerPaid(Long walletRechargeId, Long payOrderId) { + // 1. 获取钱包充值记录 + PayWalletRechargeDO walletRecharge = walletRechargeMapper.selectById(walletRechargeId); + if (walletRecharge == null) { + log.error("[updateWalletRechargerPaid],钱包充值记录不存在,钱包充值 Id:{} ", walletRechargeId); + throw exception(WALLET_RECHARGE_NOT_FOUND); + } + // 2. 校验钱包充值是否可以支付 + PayOrderDO payOrderDO = validateWalletRechargerCanPaid(walletRecharge, payOrderId); + // 3. 更新钱包充值的支付状态 + int updateCount = walletRechargeMapper.updateByIdAndPaid(walletRechargeId,false, new PayWalletRechargeDO().setId(walletRechargeId) + .setPayStatus(true).setPayTime(LocalDateTime.now()) + .setPayChannelCode(payOrderDO.getChannelCode())); + if (updateCount == 0) { + throw exception(WALLET_RECHARGE_UPDATE_PAID_STATUS_NOT_UNPAID); + } + // 4. 更新钱包余额 + payWalletService.addWalletBalance(walletRecharge.getWalletId(), String.valueOf(walletRechargeId), + PayWalletBizTypeEnum.RECHARGE, walletRecharge.getPrice()); + } + + private PayOrderDO validateWalletRechargerCanPaid(PayWalletRechargeDO walletRecharge, Long payOrderId) { + + // 1.1 校验充值记录的支付状态 + if (walletRecharge.getPayStatus()) { + log.error("[validateWalletRechargerCanPaid][钱包({}) 不处于未支付状态! 钱包数据是:{}]", + walletRecharge.getId(), toJsonString(walletRecharge)); + throw exception(WALLET_RECHARGE_UPDATE_PAID_STATUS_NOT_UNPAID); + } + // 1.2 校验支付订单匹配 + if (notEqual(walletRecharge.getPayOrderId(), payOrderId)) { // 支付单号 + log.error("[validateWalletRechargerCanPaid][钱包({}) 支付单不匹配({}),请进行处理! 钱包数据是:{}]", + walletRecharge.getId(), payOrderId, toJsonString(walletRecharge)); + throw exception(WALLET_RECHARGE_UPDATE_PAID_PAY_ORDER_ID_ERROR); + } + // 2.1 校验支付单是否存在 + PayOrderDO payOrder = payOrderService.getOrder(payOrderId); + if (payOrder == null) { + log.error("[validateWalletRechargerCanPaid][钱包({}) payOrder({}) 不存在,请进行处理!]", + walletRecharge.getId(), payOrderId); + throw exception(PAY_ORDER_NOT_FOUND); + } + // 2.2 校验支付单已支付 + if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) { + log.error("[validateWalletRechargerCanPaid][钱包({}) payOrder({}) 未支付,请进行处理!payOrder 数据是:{}]", + walletRecharge.getId(), payOrderId, toJsonString(payOrder)); + throw exception(WALLET_RECHARGE_UPDATE_PAID_PAY_ORDER_STATUS_NOT_SUCCESS); + } + // 2.3 校验支付金额一致 + if (notEqual(payOrder.getPrice(), walletRecharge.getPayPrice())) { + log.error("[validateDemoOrderCanPaid][钱包({}) payOrder({}) 支付金额不匹配,请进行处理!钱包 数据是:{},payOrder 数据是:{}]", + walletRecharge.getId(), payOrderId, toJsonString(walletRecharge), toJsonString(payOrder)); + throw exception(WALLET_RECHARGE_UPDATE_PAID_PAY_PRICE_NOT_MATCH); + } + // 2.4 校验支付订单的商户订单匹配 + if (notEqual(payOrder.getMerchantOrderId(), walletRecharge.getId().toString())) { + log.error("[validateDemoOrderCanPaid][钱包({}) 支付单不匹配({}),请进行处理!payOrder 数据是:{}]", + walletRecharge.getId(), payOrderId, toJsonString(payOrder)); + throw exception(WALLET_RECHARGE_UPDATE_PAID_PAY_ORDER_ID_ERROR); + } + return payOrder; + } +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java index 28f9849b5..ed8dcee9f 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java @@ -21,6 +21,13 @@ public interface PayWalletService { */ PayWalletDO getOrCreateWallet(Long userId, Integer userType); + /** + * 获取钱包信息 + * + * @param walletId 钱包 id + */ + PayWalletDO getWallet(Long walletId); + /** * 钱包订单支付 * @@ -56,14 +63,13 @@ public interface PayWalletService { /** * 增加钱包余额 * - * @param userId 用户 id - * @param userType 用户类型 + * @param walletId 钱包 id * @param bizId 业务关联 id * @param bizType 业务关联分类 * @param price 增加金额 * @return 钱包流水 */ - PayWalletTransactionDO addWalletBalance(Long userId, Integer userType, - Long bizId, PayWalletBizTypeEnum bizType, Integer price); + PayWalletTransactionDO addWalletBalance(Long walletId, String bizId, + PayWalletBizTypeEnum bizType, Integer price); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java index 93c653154..8e24ed705 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java @@ -55,6 +55,11 @@ public class PayWalletServiceImpl implements PayWalletService { return wallet; } + @Override + public PayWalletDO getWallet(Long walletId) { + return walletMapper.selectById(walletId); + } + @Override @Transactional(rollbackFor = Exception.class) public PayWalletTransactionDO orderPay(Long userId, Integer userType, String outTradeNo, Integer price) { @@ -80,7 +85,7 @@ public class PayWalletServiceImpl implements PayWalletService { PayWalletDO wallet = walletMapper.selectById(walletId); Assert.notNull(wallet, "钱包 {} 不存在", walletId); // 2. 增加余额 - return addWalletBalance(wallet.getUserId(), wallet.getUserType(), payRefund.getId(), PAYMENT_REFUND, refundPrice); + return addWalletBalance(walletId, String.valueOf(payRefund.getId()), PAYMENT_REFUND, refundPrice); } /** @@ -139,25 +144,33 @@ public class PayWalletServiceImpl implements PayWalletService { } @Override - public PayWalletTransactionDO addWalletBalance(Long userId, Integer userType, - Long bizId, PayWalletBizTypeEnum bizType, Integer price) { + public PayWalletTransactionDO addWalletBalance(Long walletId, + String bizId, PayWalletBizTypeEnum bizType, Integer price) { // 1. 获取钱包 - PayWalletDO payWallet = getOrCreateWallet(userId, userType); + PayWalletDO payWallet = getWallet(walletId); + + if (payWallet == null) { + log.error("[addWalletBalance],用户钱包({})不存在.", walletId); + throw exception(WALLET_NOT_FOUND); + } + switch (bizType) { case PAYMENT_REFUND: { - // 更新退款 + // 退款更新 walletMapper.updateWhenConsumptionRefund(price, payWallet.getId()); break; } case RECHARGE: { - //TODO + // 充值更新 + walletMapper.updateWhenRecharge(price, payWallet.getId()); break; } + // TODO 其它类型 } // 2. 生成钱包流水 CreateWalletTransactionBO bo = new CreateWalletTransactionBO().setWalletId(payWallet.getId()) - .setPrice(price).setBalance(payWallet.getBalance()+price).setBizId(String.valueOf(bizId)) + .setPrice(price).setBalance(payWallet.getBalance()+price).setBizId(bizId) .setBizType(bizType.getType()).setTitle(bizType.getDescription()); return walletTransactionService.createWalletTransaction(bo); }