diff --git a/yudao-framework/yudao-common/pom.xml b/yudao-framework/yudao-common/pom.xml index 760160330..877da7582 100644 --- a/yudao-framework/yudao-common/pom.xml +++ b/yudao-framework/yudao-common/pom.xml @@ -133,6 +133,11 @@ transmittable-thread-local + + + org.springframework.boot + spring-boot-starter-test + diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java index e2e420838..0817eb178 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java @@ -6,12 +6,11 @@ import cn.hutool.core.map.MapUtil; import com.google.common.collect.ImmutableMap; import java.util.*; -import java.util.function.BinaryOperator; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.function.Supplier; +import java.util.function.*; import java.util.stream.Collectors; +import static java.util.Arrays.asList; + /** * Collection 工具类 * @@ -20,13 +19,14 @@ import java.util.stream.Collectors; public class CollectionUtils { public static boolean containsAny(Object source, Object... targets) { - return Arrays.asList(targets).contains(source); + return asList(targets).contains(source); } public static boolean isAnyEmpty(Collection... collections) { return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty); } + // TODO @puhui999:anyMatch 更统一点 public static boolean isAny(Collection from, Predicate predicate) { return from.stream().anyMatch(predicate); } @@ -189,6 +189,46 @@ public class CollectionUtils { return func.apply(mapData); } + /** + * 对比老、新两个列表,找出新增、修改、删除的数据 + * + * @param oldList 老列表 + * @param newList 新列表 + * @param sameFunc 对比函数,返回 true 表示相同,返回 false 表示不同 + * 注意,same 是通过每个元素的“标识”,判断它们是不是同一个数据 + * @return [新增列表、修改列表、删除列表] + */ + public static List> diffList(Collection oldList, Collection newList, + BiFunction sameFunc) { + List createList = new LinkedList<>(newList); // 默认都认为是新增的,后续会进行移除 + List updateList = new ArrayList<>(); + List deleteList = new ArrayList<>(); + + // 通过以 oldList 为主遍历,找出 updateList 和 deleteList + for (T oldObj : oldList) { + // 1. 寻找是否有匹配的 + T foundObj = null; + for (Iterator iterator = createList.iterator(); iterator.hasNext(); ) { + T newObj = iterator.next(); + // 1.1 不匹配,则直接跳过 + if (!sameFunc.apply(oldObj, newObj)) { + continue; + } + // 1.2 匹配,则移除,并结束寻找 + iterator.remove(); + foundObj = newObj; + break; + } + // 2. 匹配添加到 updateList;不匹配则添加到 deleteList 中 + if (foundObj != null) { + updateList.add(foundObj); + } else { + deleteList.add(oldObj); + } + } + return asList(createList, updateList, deleteList); + } + public static boolean containsAny(Collection source, Collection candidates) { return org.springframework.util.CollectionUtils.containsAny(source, candidates); } diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java index 29ffad603..35d6c4f5d 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java @@ -84,11 +84,11 @@ public class LocalDateTimeUtils { public static boolean isOverlap(LocalTime startTime1, LocalTime endTime1, LocalTime startTime2, LocalTime endTime2) { // 日期部分使用了当前日期LocalDate.now() + // TODO @puhui999:LocalDate.now() 抽一个变量,啊哈;然后注释写下;之后 4 个变量不用,直接调方法的时候,直接计算作为入参; LocalDateTime startDateTime1 = LocalDateTime.of(LocalDate.now(), startTime1); LocalDateTime endDateTime1 = LocalDateTime.of(LocalDate.now(), endTime1); LocalDateTime startDateTime2 = LocalDateTime.of(LocalDate.now(), startTime2); LocalDateTime endDateTime2 = LocalDateTime.of(LocalDate.now(), endTime2); - return LocalDateTimeUtil.isOverlap(startDateTime1, endDateTime1, startDateTime2, endDateTime2); } diff --git a/yudao-framework/yudao-common/src/test/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtilsTest.java b/yudao-framework/yudao-common/src/test/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtilsTest.java new file mode 100644 index 000000000..0e44645bc --- /dev/null +++ b/yudao-framework/yudao-common/src/test/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtilsTest.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.framework.common.util.collection; + +import lombok.AllArgsConstructor; +import lombok.Data; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.function.BiFunction; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link CollectionUtils} 的单元测试 + */ +public class CollectionUtilsTest { + + @Data + @AllArgsConstructor + private static class Dog { + + private Integer id; + private String name; + private String code; + + } + + @Test + public void testDiffList() { + // 准备参数 + Collection oldList = Arrays.asList( + new Dog(1, "花花", "hh"), + new Dog(2, "旺财", "wc") + ); + Collection newList = Arrays.asList( + new Dog(null, "花花2", "hh"), + new Dog(null, "小白", "xb") + ); + BiFunction sameFunc = (oldObj, newObj) -> { + boolean same = oldObj.getCode().equals(newObj.getCode()); + // 如果相等的情况下,需要设置下 id,后续好更新 + if (same) { + newObj.setId(oldObj.getId()); + } + return same; + }; + + // 调用 + List> result = CollectionUtils.diffList(oldList, newList, sameFunc); + // 断言 + assertEquals(result.size(), 3); + // 断言 create + assertEquals(result.get(0).size(), 1); + assertEquals(result.get(0).get(0), new Dog(null, "小白", "xb")); + // 断言 update + assertEquals(result.get(1).size(), 1); + assertEquals(result.get(1).get(0), new Dog(1, "花花2", "hh")); + // 断言 delete + assertEquals(result.get(2).size(), 1); + assertEquals(result.get(2).get(0), new Dog(2, "旺财", "wc")); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java b/yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java index 6d44b31ff..19aaf046c 100644 --- a/yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java +++ b/yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java @@ -17,20 +17,18 @@ import java.util.concurrent.TimeUnit; public class BannerApplicationRunner implements ApplicationRunner { @Override - public void run(ApplicationArguments args) throws Exception { + public void run(ApplicationArguments args) { ThreadUtil.execute(() -> { ThreadUtil.sleep(1, TimeUnit.SECONDS); // 延迟 1 秒,保证输出到结尾 log.info("\n----------------------------------------------------------\n\t" + "项目启动成功!\n\t" + "接口文档: \t{} \n\t" + "开发文档: \t{} \n\t" + - "视频教程: \t{} \n\t" + - "源码解析: \t{} \n" + + "视频教程: \t{} \n" + "----------------------------------------------------------", "https://doc.iocoder.cn/api-doc/", "https://doc.iocoder.cn", - "https://t.zsxq.com/02Yf6M7Qn", - "https://t.zsxq.com/02B6ujIee"); + "https://t.zsxq.com/02Yf6M7Qn"); // 数据报表 if (isNotPresent("cn.iocoder.yudao.module.report.framework.security.config.SecurityConfiguration")) { @@ -44,11 +42,11 @@ public class BannerApplicationRunner implements ApplicationRunner { if (isNotPresent("cn.iocoder.yudao.module.mp.framework.mp.config.MpConfiguration")) { System.out.println("[微信公众号 yudao-module-mp - 已禁用][参考 https://doc.iocoder.cn/mp/build/ 开启]"); } - // 商城 + // 商城系统 if (isNotPresent("cn.iocoder.yudao.module.trade.framework.web.config.TradeWebConfiguration")) { System.out.println("[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]"); } - // 支付 + // 支付平台 if (isNotPresent("cn.iocoder.yudao.module.pay.framework.pay.config.PayConfiguration")) { System.out.println("[支付系统 yudao-module-pay - 已禁用][参考 https://doc.iocoder.cn/pay/build/ 开启]"); } diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java index 9eed6d0e0..839b5abb8 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java @@ -44,6 +44,12 @@ public interface BaseMapperX extends BaseMapper { return selectOne(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2)); } + default T selectOne(SFunction field1, Object value1, SFunction field2, Object value2, + SFunction field3, Object value3) { + return selectOne(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2) + .eq(field3, value3)); + } + default Long selectCount() { return selectCount(new QueryWrapper()); } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java index d9e8e848d..bf241ba57 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.web.core.handler; import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLog; import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; import cn.iocoder.yudao.framework.common.exception.ServiceException; @@ -219,6 +220,13 @@ public class GlobalExceptionHandler { */ @ExceptionHandler(value = Exception.class) public CommonResult defaultExceptionHandler(HttpServletRequest req, Throwable ex) { + // 情况一:处理表不存在的异常 + CommonResult tableNotExistsResult = handleTableNotExists(ex); + if (tableNotExistsResult != null) { + return tableNotExistsResult; + } + + // 情况二:处理异常 log.error("[defaultExceptionHandler]", ex); // 插入异常日志 this.createExceptionLog(req, ex); @@ -269,4 +277,48 @@ public class GlobalExceptionHandler { errorLog.setExceptionTime(LocalDateTime.now()); } + /** + * 处理 Table 不存在的异常情况 + * + * @param ex 异常 + * @return 如果是 Table 不存在的异常,则返回对应的 CommonResult + */ + private CommonResult handleTableNotExists(Throwable ex) { + String message = ExceptionUtil.getRootCauseMessage(ex); + if (!message.contains("doesn't exist")) { + return null; + } + // 1. 数据报表 + if (message.contains("report_")) { + log.error("[报表模块 yudao-module-report - 表结构未导入][参考 https://doc.iocoder.cn/report/ 开启]"); + return CommonResult.error(NOT_IMPLEMENTED.getCode(), + "[报表模块 yudao-module-report - 表结构未导入][参考 https://doc.iocoder.cn/report/ 开启]"); + } + // 2. 工作流 + if (message.contains("bpm_")) { + log.error("[工作流模块 yudao-module-bpm - 表结构未导入][参考 https://doc.iocoder.cn/bpm/ 开启]"); + return CommonResult.error(NOT_IMPLEMENTED.getCode(), + "[工作流模块 yudao-module-bpm - 表结构未导入][参考 https://doc.iocoder.cn/bpm/ 开启]"); + } + // 3. 微信公众号 + if (message.contains("mp_")) { + log.error("[微信公众号 yudao-module-mp - 表结构未导入][参考 https://doc.iocoder.cn/mp/build/ 开启]"); + return CommonResult.error(NOT_IMPLEMENTED.getCode(), + "[微信公众号 yudao-module-mp - 表结构未导入][参考 https://doc.iocoder.cn/mp/build/ 开启]"); + } + // 4. 商城系统 + if (StrUtil.containsAny(message, "product_", "promotion_", "trade_")) { + log.error("[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]"); + return CommonResult.error(NOT_IMPLEMENTED.getCode(), + "[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]"); + } + // 5. 支付平台 + if (message.contains("pay_")) { + log.error("[支付模块 yudao-module-pay - 表结构未导入][参考 https://doc.iocoder.cn/pay/build/ 开启]"); + return CommonResult.error(NOT_IMPLEMENTED.getCode(), + "[支付模块 yudao-module-pay - 表结构未导入][参考 https://doc.iocoder.cn/pay/build/ 开启]"); + } + return null; + } + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java index 6df3426bf..5f997fdec 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.product.controller.app.comment; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO; import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO; @@ -27,6 +27,7 @@ import java.util.List; import java.util.Set; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @Tag(name = "用户 APP - 商品评价") @RestController @@ -56,10 +57,17 @@ public class AppProductCommentController { @GetMapping("/page") @Operation(summary = "获得商品评价分页") public CommonResult> getCommentPage(@Valid AppCommentPageReqVO pageVO) { - PageResult commentDOPage = productCommentService.getCommentPage(pageVO, Boolean.TRUE); - Set skuIds = CollectionUtils.convertSet(commentDOPage.getList(), ProductCommentDO::getSkuId); - PageResult page = ProductCommentConvert.INSTANCE.convertPage02(commentDOPage, productSkuService.getSkuList(skuIds)); - return success(page); + // 查询评论分页 + PageResult commentPageResult = productCommentService.getCommentPage(pageVO, Boolean.TRUE); + if (CollUtil.isEmpty(commentPageResult.getList())) { + return success(PageResult.empty(commentPageResult.getTotal())); + } + + // 拼接返回 + Set skuIds = convertSet(commentPageResult.getList(), ProductCommentDO::getSkuId); + PageResult commentVOPageResult = ProductCommentConvert.INSTANCE.convertPage02( + commentPageResult, productSkuService.getSkuList(skuIds)); + return success(commentVOPageResult); } // TODO 芋艿:需要搞下 diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java index db4ae03ed..cabc79a7d 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.product.convert.comment; -import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; @@ -15,7 +14,6 @@ import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProdu import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; -import com.google.common.collect.Maps; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Named; @@ -52,17 +50,16 @@ public interface ProductCommentConvert { PageResult convertPage01(PageResult pageResult); - default PageResult convertPage02(PageResult pageResult, List skuList) { - Map skuMap = Maps.newLinkedHashMapWithExpectedSize(skuList.size()); - if (CollUtil.isNotEmpty(skuList)) { - skuMap.putAll(CollectionUtils.convertMap(skuList, ProductSkuDO::getId)); - } + default PageResult convertPage02(PageResult pageResult, + List skuList) { + Map skuMap = CollectionUtils.convertMap(skuList, ProductSkuDO::getId); PageResult page = convertPage01(pageResult); page.getList().forEach(item -> { // 判断用户是否选择匿名 if (ObjectUtil.equal(item.getAnonymous(), true)) { item.setUserNickname(ProductCommentDO.NICKNAME_ANONYMOUS); } + // 设置 SKU 规格值 MapUtils.findAndThen(skuMap, item.getSkuId(), sku -> item.setSkuProperties(convertList01(sku.getProperties()))); }); diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java index 26254d33b..874b5673e 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java @@ -112,10 +112,9 @@ public interface ProductSpuConvert { } default List convertForSpuDetailRespListVO(List spus, List skus) { - List vos = new ArrayList<>(spus.size()); Map> skuMultiMap = convertMultiMap(skus, ProductSkuDO::getSpuId); - CollectionUtils.convertList(spus, spu -> vos.add(convert03(spu).setSkus(ProductSkuConvert.INSTANCE.convertList(skuMultiMap.get(spu.getId()))))); - return vos; + return CollectionUtils.convertList(spus, spu -> convert03(spu) + .setSkus(ProductSkuConvert.INSTANCE.convertList(skuMultiMap.get(spu.getId())))); } } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java index 0055e42bb..42972b659 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.promotion.api.combination; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; import javax.validation.Valid; -// TODO @芋艿:后面也再撸撸这几个接口 +// TODO @芋艿:后面也再撸撸这几个接口 /** * 拼团记录 API 接口 * @@ -17,17 +17,18 @@ public interface CombinationRecordApi { * * @param reqDTO 请求 DTO */ - void createRecord(@Valid CombinationRecordCreateReqDTO reqDTO); + void createCombinationRecord(@Valid CombinationRecordCreateReqDTO reqDTO); /** - * 校验拼团是否成功 + * 查询拼团记录是否成功 * * @param userId 用户编号 * @param orderId 订单编号 * @return 拼团是否成功 */ - boolean validateRecordStatusIsSuccess(Long userId, Long orderId); + boolean isCombinationRecordSuccess(Long userId, Long orderId); + // TODO @puhui999:updateRecordStatus 和 updateRecordStatusAndStartTime 看看后续是不是可以统一掉; /** * 更新开团记录状态 * @@ -35,7 +36,7 @@ public interface CombinationRecordApi { * @param orderId 订单编号 * @param status 状态值 */ - void updateRecordStatus(Long userId, Long orderId, Integer status); + void updateCombinationRecordStatus(Long userId, Long orderId, Integer status); /** * 更新开团记录状态和开始时间 @@ -44,6 +45,6 @@ public interface CombinationRecordApi { * @param orderId 订单编号 * @param status 状态值 */ - void updateRecordStatusAndStartTime(Long userId, Long orderId, Integer status); + void updateCombinationRecordStatusAndStartTime(Long userId, Long orderId, Integer status); } 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 ed017f354..efc63d5c1 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 @@ -5,8 +5,9 @@ import lombok.Data; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; +// TODO @芋艿:这块要在看看 /** - * 拼团记录 Request DTO + * 拼团记录的创建 Request DTO * * @author HUIHUI */ diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java index 065705197..cbb7a012f 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java @@ -20,23 +20,23 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { private CombinationRecordService recordService; @Override - public void createRecord(CombinationRecordCreateReqDTO reqDTO) { - recordService.createRecord(reqDTO); + public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { + recordService.createCombinationRecord(reqDTO); } @Override - public boolean validateRecordStatusIsSuccess(Long userId, Long orderId) { - return CombinationRecordStatusEnum.isSuccess(recordService.getRecord(userId, orderId).getStatus()); + public boolean isCombinationRecordSuccess(Long userId, Long orderId) { + return CombinationRecordStatusEnum.isSuccess(recordService.getCombinationRecord(userId, orderId).getStatus()); } @Override - public void updateRecordStatus(Long userId, Long orderId, Integer status) { - recordService.updateRecordStatusByUserIdAndOrderId(userId, orderId, status); + public void updateCombinationRecordStatus(Long userId, Long orderId, Integer status) { + recordService.updateCombinationRecordStatusByUserIdAndOrderId(userId, orderId, status); } @Override - public void updateRecordStatusAndStartTime(Long userId, Long orderId, Integer status) { - recordService.updateRecordStatusAndStartTimeByUserIdAndOrderId(userId, orderId, status, LocalDateTime.now()); + public void updateCombinationRecordStatusAndStartTime(Long userId, Long orderId, Integer status) { + recordService.updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(userId, orderId, status, LocalDateTime.now()); } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java index 4c0a440cb..4dedb3eb3 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.promotion.controller.admin.combination; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; @@ -23,9 +22,11 @@ import javax.annotation.Resource; import javax.validation.Valid; import java.util.Collection; import java.util.List; +import java.util.Set; import static cn.hutool.core.collection.CollectionUtil.newArrayList; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @Tag(name = "管理后台 - 拼团活动") @RestController @@ -35,6 +36,7 @@ public class CombinationActivityController { @Resource private CombinationActivityService combinationActivityService; + @Resource private ProductSpuApi spuApi; @@ -68,17 +70,18 @@ public class CombinationActivityController { @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')") public CommonResult getCombinationActivity(@RequestParam("id") Long id) { CombinationActivityDO activity = combinationActivityService.getCombinationActivity(id); - List products = combinationActivityService.getProductsByActivityIds(newArrayList(id)); + List products = combinationActivityService.getCombinationProductsByActivityIds(newArrayList(id)); return success(CombinationActivityConvert.INSTANCE.convert(activity, products)); } + // TODO @puhui999:是不是可以删掉,貌似没用? @GetMapping("/list") @Operation(summary = "获得拼团活动列表") @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048") @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')") public CommonResult> getCombinationActivityList(@RequestParam("ids") Collection ids) { List list = combinationActivityService.getCombinationActivityList(ids); - return success(CombinationActivityConvert.INSTANCE.complementList(list)); + return success(CombinationActivityConvert.INSTANCE.convertList(list)); } @GetMapping("/page") @@ -86,10 +89,14 @@ public class CombinationActivityController { @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')") public CommonResult> getCombinationActivityPage( @Valid CombinationActivityPageReqVO pageVO) { + // 查询拼团活动 PageResult pageResult = combinationActivityService.getCombinationActivityPage(pageVO); + // 拼接数据 + Set activityIds = convertSet(pageResult.getList(), CombinationActivityDO::getId); + Set spuIds = convertSet(pageResult.getList(), CombinationActivityDO::getSpuId); return success(CombinationActivityConvert.INSTANCE.convertPage(pageResult, - combinationActivityService.getProductsByActivityIds(CollectionUtils.convertSet(pageResult.getList(), CombinationActivityDO::getId)), - spuApi.getSpuList(CollectionUtils.convertSet(pageResult.getList(), CombinationActivityDO::getSpuId)))); + combinationActivityService.getCombinationProductsByActivityIds(activityIds), + spuApi.getSpuList(spuIds))); } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java index 2cdba335b..47883c9c4 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java @@ -79,6 +79,7 @@ public class SeckillActivityController { return success(SeckillActivityConvert.INSTANCE.convert(seckillActivity, seckillProducts)); } + // TODO @puhui999:是不是可以删掉,貌似没用? @GetMapping("/list") @Operation(summary = "获得秒杀活动列表") @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048") diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java index 5f5fb5b3e..02e5eb388 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.promotion.convert.combination; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; @@ -70,7 +71,7 @@ public interface CombinationActivityConvert { return respVO; } - List complementList(List list); + List convertList(List list); PageResult convertPage(PageResult page); @@ -80,8 +81,10 @@ public interface CombinationActivityConvert { Map spuMap = convertMap(spuList, ProductSpuRespDTO::getId); PageResult pageResult = convertPage(page); pageResult.getList().forEach(item -> { - MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> item.setSpuName(spu.getName())); - MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl())); + MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> { + item.setSpuName(spu.getName()); + item.setPicUrl(spu.getPicUrl()); + }); item.setProducts(convertList2(productList)); }); return pageResult; @@ -100,7 +103,7 @@ public interface CombinationActivityConvert { }) CombinationProductDO convert(CombinationActivityDO activityDO, CombinationProductBaseVO vo); - default List complementList(List products, CombinationActivityDO activityDO) { + default List convertList(List products, CombinationActivityDO activityDO) { List list = new ArrayList<>(); products.forEach(sku -> { CombinationProductDO productDO = convert(activityDO, sku); @@ -110,16 +113,12 @@ public interface CombinationActivityConvert { return list; } - default List complementList(List productDOs, List vos, CombinationActivityDO activityDO) { - Map longMap = convertMap(productDOs, CombinationProductDO::getSkuId, CombinationProductDO::getId); - List list = new ArrayList<>(); - vos.forEach(sku -> { - CombinationProductDO productDO = convert(activityDO, sku); - productDO.setId(longMap.get(sku.getSkuId())); - productDO.setActivityStatus(activityDO.getStatus()); - list.add(productDO); - }); - return list; + default List convertList(List updateProductVOs, + List products, CombinationActivityDO activity) { + Map productMap = convertMap(products, CombinationProductDO::getSkuId, CombinationProductDO::getId); + return CollectionUtils.convertList(updateProductVOs, updateProductVO -> convert(activity, updateProductVO) + .setId(productMap.get(updateProductVO.getSkuId())) + .setActivityStatus(activity.getStatus())); } CombinationRecordDO convert(CombinationRecordCreateReqDTO reqDTO); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java index a2aadc2f0..6c54ab4f3 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java @@ -21,6 +21,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + /** * 秒杀活动 Convert * @@ -37,6 +39,7 @@ public interface SeckillActivityConvert { SeckillActivityRespVO convert(SeckillActivityDO bean); + // TODO @puhui999:这个是不是还是 convertList 好点? List complementList(List list); PageResult convertPage(PageResult page); @@ -73,7 +76,7 @@ public interface SeckillActivityConvert { }) SeckillProductDO convert(SeckillActivityDO activityDO, SeckillProductBaseVO vo); - default List complementList(List products, SeckillActivityDO activityDO) { + default List convertList(List products, SeckillActivityDO activityDO) { List list = new ArrayList<>(); products.forEach(sku -> { SeckillProductDO productDO = convert(activityDO, sku); @@ -83,16 +86,12 @@ public interface SeckillActivityConvert { return list; } - default List complementList(List productDOs, List vos, SeckillActivityDO activityDO) { - Map longMap = CollectionUtils.convertMap(productDOs, SeckillProductDO::getSkuId, SeckillProductDO::getId); - List list = new ArrayList<>(); - vos.forEach(sku -> { - SeckillProductDO productDO = convert(activityDO, sku); - productDO.setId(longMap.get(sku.getSkuId())); - productDO.setActivityStatus(activityDO.getStatus()); - list.add(productDO); - }); - return list; + default List convertList(List updateProductVOs, + List products, SeckillActivityDO activity) { + Map productMap = convertMap(products, SeckillProductDO::getSkuId, SeckillProductDO::getId); + return CollectionUtils.convertList(updateProductVOs, updateProductVO -> convert(activity, updateProductVO) + .setId(productMap.get(updateProductVO.getSkuId())) + .setActivityStatus(activity.getStatus())); } List convertList2(List productDOs); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java index 9def86599..d9c4e45c3 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java @@ -12,6 +12,9 @@ import java.time.LocalDateTime; /** * 拼团记录 DO * + * 1. 用户参与拼团时,会创建一条记录 + * 2. 团长的拼团记录,和参团人的拼团记录,通过 {@link #headId} 关联 + * * @author HUIHUI */ @TableName("promotion_combination_record") diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java index 13582d127..453f76990 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java @@ -15,6 +15,7 @@ import java.util.List; @Mapper public interface CombinationRecordMapper extends BaseMapperX { + // TODO @puhui999:selectByUserIdAndOrderId default CombinationRecordDO selectRecord(Long userId, Long orderId) { return selectOne(CombinationRecordDO::getUserId, userId, CombinationRecordDO::getOrderId, orderId); @@ -28,7 +29,8 @@ public interface CombinationRecordMapper extends BaseMapperX getProductsByActivityIds(Collection ids); + List getCombinationProductsByActivityIds(Collection ids); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java index 6551a6208..5d39b5f7f 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java @@ -19,14 +19,14 @@ public interface CombinationRecordService { * @param orderId 订单编号 * @param status 状态 */ - void updateRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status); + void updateCombinationRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status); /** * 创建拼团记录 * * @param reqDTO 创建信息 */ - void createRecord(CombinationRecordCreateReqDTO reqDTO); + void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO); /** * 更新拼团状态和开始时间 @@ -36,7 +36,8 @@ public interface CombinationRecordService { * @param status 状态 * @param startTime 开始时间 */ - void updateRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId, Integer status, LocalDateTime startTime); + void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId, + Integer status, LocalDateTime startTime); /** * 获得拼团状态 @@ -45,6 +46,6 @@ public interface CombinationRecordService { * @param orderId 订单编号 * @return 拼团状态 */ - CombinationRecordDO getRecord(Long userId, Long orderId); + CombinationRecordDO getCombinationRecord(Long userId, Long orderId); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationServiceImpl.java index f0a77e3b6..e14d74ad3 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationServiceImpl.java @@ -37,7 +37,7 @@ import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; -import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuExistence; +import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuAllExists; /** * 拼团活动 Service 实现类 @@ -66,7 +66,7 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi // 获取所选 spu下的所有 sku List skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(createReqVO.getSpuId())); // 校验商品 sku 是否存在 - validateProductSkuExistence(createReqVO.getProducts(), skus, CombinationProductCreateReqVO::getSkuId); + validateProductSkuAllExists(createReqVO.getProducts(), skus, CombinationProductCreateReqVO::getSkuId); // TODO 艿艿 有个小问题:现在有活动时间和限制时长,活动时间的结束时间早于设置的限制时间怎么算状态比如: // 活动时间 2023-08-05 15:00:00 - 2023-08-05 15:20:00 限制时长 2小时,那么活动时间结束就结束还是加时到满两小时 @@ -80,7 +80,7 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi activityDO.setStatus(CommonStatusEnum.ENABLE.getStatus()); combinationActivityMapper.insert(activityDO); // 插入商品 - List productDOs = CombinationActivityConvert.INSTANCE.complementList(createReqVO.getProducts(), activityDO); + List productDOs = CombinationActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), activityDO); combinationProductMapper.insertBatch(productDOs); // 返回 return activityDO.getId(); @@ -118,7 +118,7 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi // 获取所选 spu下的所有 sku List skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(updateReqVO.getSpuId())); // 校验商品 sku 是否存在 - validateProductSkuExistence(updateReqVO.getProducts(), skus, CombinationProductUpdateReqVO::getSkuId); + validateProductSkuAllExists(updateReqVO.getProducts(), skus, CombinationProductUpdateReqVO::getSkuId); // 更新 CombinationActivityDO updateObj = CombinationActivityConvert.INSTANCE.convert(updateReqVO); @@ -140,18 +140,21 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi // 前端传过来的活动商品 Set convertSet1 = CollectionUtils.convertSet(products, CombinationProductUpdateReqVO::getSkuId); // 分化数据 + // TODO @芋艿:看下这个实现 Map> data = CollectionUtils.convertCDUMap(convertSet1, convertSet, mapData -> { HashMap> cdu = MapUtil.newHashMap(3); MapUtils.findAndThen(mapData, "create", list -> { - cdu.put("create", CombinationActivityConvert.INSTANCE.complementList(CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj)); + cdu.put("create", CombinationActivityConvert.INSTANCE.convertList(CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj)); }); MapUtils.findAndThen(mapData, "delete", list -> { cdu.put("create", CollectionUtils.filterList(combinationProductDOs, item -> list.contains(item.getSkuId()))); }); - MapUtils.findAndThen(mapData, "update", list -> { - cdu.put("update", CombinationActivityConvert.INSTANCE.complementList(combinationProductDOs, - CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj)); - }); + // TODO @芋艿:临时注释,避免有问题 +// MapUtils.findAndThen(mapData, "update", list -> { +// cdu.put("update", CombinationActivityConvert.INSTANCE.convertList( +// combinationProductDOs, +// CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj)); +// }); return cdu; }); @@ -199,12 +202,12 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi } @Override - public List getProductsByActivityIds(Collection ids) { + public List getCombinationProductsByActivityIds(Collection ids) { return combinationProductMapper.selectListByActivityIds(ids); } @Override - public void updateRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status) { + public void updateCombinationRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status) { // 校验拼团是否存在 CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId); @@ -215,7 +218,7 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi @Override @Transactional(rollbackFor = Exception.class) - public void updateRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId, Integer status, LocalDateTime startTime) { + public void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId, Integer status, LocalDateTime startTime) { CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId); // 更新状态 recordDO.setStatus(status); @@ -247,15 +250,15 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi } @Override - public void createRecord(CombinationRecordCreateReqDTO reqDTO) { - // 校验拼团活动 + public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { + // 1.1 校验拼团活动 CombinationActivityDO activity = validateCombinationActivityExists(reqDTO.getActivityId()); - // 需要校验下,它当前是不是已经参加了该拼团; + // 1.2 需要校验下,他当前是不是已经参加了该拼团; CombinationRecordDO recordDO = recordMapper.selectRecord(reqDTO.getUserId(), reqDTO.getOrderId()); if (recordDO != null) { throw exception(COMBINATION_RECORD_EXISTS); } - // 父拼团是否存在,是否已经满了 + // 1.3 父拼团是否存在,是否已经满了 if (reqDTO.getHeadId() != null) { CombinationRecordDO recordDO1 = recordMapper.selectRecordByHeadId(reqDTO.getHeadId(), reqDTO.getActivityId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); if (recordDO1 == null) { @@ -266,9 +269,12 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi throw exception(COMBINATION_RECORD_USER_FULL); } } + // TODO @puhui999:应该还有一些校验,后续补噶;例如说,一个团,自己已经参与进去了,不能再参与进去; + // 2. 创建拼团记录 CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO); if (reqDTO.getHeadId() == null) { + // TODO @puhui999:不是自己呀;headId 是父团长的 CombinationRecordDO.id 哈 record.setHeadId(reqDTO.getUserId()); } record.setVirtualGroup(false); @@ -279,7 +285,7 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi } @Override - public CombinationRecordDO getRecord(Long userId, Long orderId) { + public CombinationRecordDO getCombinationRecord(Long userId, Long orderId) { return validateCombinationRecord(userId, orderId); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java index 8471275d7..56e678183 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java @@ -34,7 +34,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU 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.*; -import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuExistence; +import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuAllExists; /** * 秒杀活动 Service 实现类 @@ -74,7 +74,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { .setTotalStock(CollectionUtils.getSumValue(createReqVO.getProducts(), SeckillProductCreateReqVO::getStock, Integer::sum)); seckillActivityMapper.insert(activity); // 插入商品 - List products = SeckillActivityConvert.INSTANCE.complementList(createReqVO.getProducts(), activity); + List products = SeckillActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), activity); seckillProductMapper.insertBatch(products); return activity.getId(); } @@ -121,7 +121,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { // 获取所选 spu下的所有 sku List skus = productSkuApi.getSkuListBySpuId(CollUtil.newArrayList(updateReqVO.getSpuId())); // 校验商品 sku 是否存在 - validateProductSkuExistence(updateReqVO.getProducts(), skus, SeckillProductUpdateReqVO::getSkuId); + validateProductSkuAllExists(updateReqVO.getProducts(), skus, SeckillProductUpdateReqVO::getSkuId); // 更新活动 SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO) @@ -150,16 +150,17 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { Map> data = CollectionUtils.convertCDUMap(voSkuIds, dbSkuIds, mapData -> { HashMap> cdu = MapUtil.newHashMap(3); MapUtils.findAndThen(mapData, "create", list -> { - cdu.put("create", SeckillActivityConvert.INSTANCE.complementList( + cdu.put("create", SeckillActivityConvert.INSTANCE.convertList( CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj)); }); MapUtils.findAndThen(mapData, "delete", list -> { cdu.put("create", CollectionUtils.filterList(seckillProductDOs, item -> list.contains(item.getSkuId()))); }); - MapUtils.findAndThen(mapData, "update", list -> { - cdu.put("update", SeckillActivityConvert.INSTANCE.complementList(seckillProductDOs, - CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj)); - }); + // TODO @芋艿:临时注释 +// MapUtils.findAndThen(mapData, "update", list -> { +// cdu.put("update", SeckillActivityConvert.INSTANCE.convertList(seckillProductDOs, +// CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj)); +// }); return cdu; }); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java index 4c16c7836..63cbd8bf1 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java @@ -31,18 +31,20 @@ public class PromotionUtils { return LocalDateTimeUtils.beforeNow(endTime) ? CommonStatusEnum.DISABLE.getStatus() : CommonStatusEnum.ENABLE.getStatus(); } + // TODO @puhui999:是不是第一个参数是 sku;然后是 products;这样关联性好点; /** - * 校验商品 sku 是否存在 + * 校验商品 sku 是否都存在 * * @param products 需要校验的商品 * @param skus 数据库中的商品 skus * @param func 获取需要校验的商品的 skuId */ - public static void validateProductSkuExistence(List products, List skus, Function func) { + public static void validateProductSkuAllExists(List products, List skus, Function func) { // 校验 sku 个数是否一致 Set skuIdsSet = CollectionUtils.convertSet(products, func); Set skuIdsSet1 = CollectionUtils.convertSet(skus, ProductSkuRespDTO::getId); // 校验 skuId 是否存在 + // TODO @puhui999:findFirst List f = CollectionUtils.filterList(skuIdsSet, s -> !skuIdsSet1.contains(s)); if (CollUtil.isNotEmpty(f)) { throw exception(SKU_NOT_EXISTS); 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 db763d0b8..788b8c413 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 @@ -332,6 +332,7 @@ public interface TradeOrderConvert { @Mapping(target = "avatar", source = "user.avatar"), @Mapping(target = "status", ignore = true) }) - CombinationRecordCreateReqDTO convert(TradeOrderDO order, TradeOrderItemDO orderItem, AppTradeOrderCreateReqVO createReqVO, MemberUserRespDTO user); + CombinationRecordCreateReqDTO convert(TradeOrderDO order, TradeOrderItemDO orderItem, + AppTradeOrderCreateReqVO createReqVO, MemberUserRespDTO user); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/message/TradeMessageServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/message/TradeMessageServiceImpl.java index 997b48287..7a435a53d 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/message/TradeMessageServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/message/TradeMessageServiceImpl.java @@ -27,11 +27,13 @@ public class TradeMessageServiceImpl implements TradeMessageService { // 1、构造消息 Map msgMap = new HashMap<>(); msgMap.put("orderId", reqDTO.getOrderId()); + // TODO puhui999:应该不是 msg 哇,应该是涉及到的模版参数哈;msg 太大了 msgMap.put("msg", reqDTO.getMessage()); // 2、发送站内信 notifyMessageSendApi.sendSingleMessageToMember( new NotifySendSingleToUserReqDTO() .setUserId(reqDTO.getUserId()) + // TODO puhui999:短信模版编号,枚举起来; .setTemplateCode("order_delivery") .setTemplateParams(msgMap)); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/message/dto/TradeOrderMessageWhenDeliveryOrderReqDTO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/message/dto/TradeOrderMessageWhenDeliveryOrderReqDTO.java index 68f6dcfc0..1374b5bd6 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/message/dto/TradeOrderMessageWhenDeliveryOrderReqDTO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/message/dto/TradeOrderMessageWhenDeliveryOrderReqDTO.java @@ -5,6 +5,7 @@ import lombok.Data; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; +// TODO @puhui999:改成 ReqBO 哈;包名也换了;service 我们还是同一用 bo 对象 /** * 订单发货时 Req DTO * 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 b9fa0297d..d8024a993 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 @@ -174,7 +174,8 @@ public class TradeOrderServiceImpl implements TradeOrderService { if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { MemberUserRespDTO user = memberUserApi.getUser(userId); // TODO 拼团一次应该只能选择一种规格的商品 - combinationRecordApi.createRecord(TradeOrderConvert.INSTANCE.convert(order, orderItems.get(0), createReqVO, user) + // TODO @puhui999:应该是前置校验哈;然后不应该设置状态,而是交给拼团记录那处理; + combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(order, orderItems.get(0), createReqVO, user) .setStatus(CombinationRecordStatusEnum.WAITING.getStatus())); } // TODO 秒杀扣减库存是下单就扣除还是等待订单支付成功再扣除 @@ -311,7 +312,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { // 1、拼团活动 if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { // 更新拼团状态 TODO puhui999:订单支付失败或订单支付过期删除这条拼团记录 - combinationRecordApi.updateRecordStatusAndStartTime(order.getUserId(), order.getId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); + combinationRecordApi.updateCombinationRecordStatusAndStartTime(order.getUserId(), order.getId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); } // TODO 芋艿:发送订单变化的消息 @@ -376,10 +377,11 @@ public class TradeOrderServiceImpl implements TradeOrderService { return new KeyValue<>(order, payOrder); } + // TODO @芋艿:后续在 review 下发货逻辑 @Override @Transactional(rollbackFor = Exception.class) public void deliveryOrder(Long userId, TradeOrderDeliveryReqVO deliveryReqVO) { - // 校验并获得交易订单(可发货) + // 1.1 校验并获得交易订单(可发货) TradeOrderDO order = validateOrderDeliverable(deliveryReqVO.getId()); /* TODO @@ -388,35 +390,36 @@ public class TradeOrderServiceImpl implements TradeOrderService { * 2.如果店铺只支持到店自提那么下单后默认发货不需要物流 * 3.如果店铺支持 物流-配送-自提 的情况下后台不需要选择配送方式按前端用户选择的配送方式发货即可 */ - TradeOrderDO tradeOrderDO = new TradeOrderDO(); + TradeOrderDO updateOrderObj = new TradeOrderDO(); // 判断发货类型 - // 快递发货 + // 2.1 快递发货 if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.EXPRESS.getMode())) { // 校验快递公司 + // TODO @puhui999:getDeliveryExpress 直接封装一个校验的,会不会好点;因为还有开启关闭啥的; DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(deliveryReqVO.getLogisticsId()); if (deliveryExpress == null) { throw exception(EXPRESS_NOT_EXISTS); } - tradeOrderDO.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo()); + updateOrderObj.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo()); } - // 用户自提 + // 2.2 用户自提 if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.PICK_UP.getMode())) { // TODO 校验自提门店是否存在 // 重置一下确保快递公司和快递单号为空 - tradeOrderDO.setLogisticsId(null).setLogisticsNo(""); + updateOrderObj.setLogisticsId(null).setLogisticsNo(""); } - // TODO 芋艿:如果无需发货,需要怎么存储? + // 2.3 TODO 芋艿:如果无需发货,需要怎么存储?回复:需要把 deliverType 设置为 DeliveryTypeEnum.NULL if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.NULL.getMode())) { // TODO 情况一:正常走发货逻辑和用户自提有点像 不同点:不需要自提门店只需要用户确认收货 // TODO 情况二:用户下单付款后直接确认收货或等待用户确认收货 // 重置一下确保快递公司和快递单号为空 - tradeOrderDO.setLogisticsId(null).setLogisticsNo(""); + updateOrderObj.setLogisticsId(null).setLogisticsNo(""); } // 更新 TradeOrderDO 状态为已发货,等待收货 - tradeOrderDO.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()) + updateOrderObj.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()) .setDeliveryStatus(TradeOrderDeliveryStatusEnum.DELIVERED.getStatus()).setDeliveryTime(LocalDateTime.now()); - int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), tradeOrderDO); + int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), updateOrderObj); if (updateCount == 0) { throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); } @@ -457,7 +460,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { // 校验订单拼团是否成功 // TODO 用户 ID 使用当前登录用户的还是订单保存的? - if (combinationRecordApi.validateRecordStatusIsSuccess(order.getUserId(), order.getId())) { + if (combinationRecordApi.isCombinationRecordSuccess(order.getUserId(), order.getId())) { throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS); } } diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/MpAccountServiceImpl.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/MpAccountServiceImpl.java index af359b02a..a8f9b78d1 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/MpAccountServiceImpl.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/account/MpAccountServiceImpl.java @@ -27,6 +27,7 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.time.LocalDateTime; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -68,7 +69,15 @@ public class MpAccountServiceImpl implements MpAccountService { // 注意:忽略自动多租户,因为要全局初始化缓存 TenantUtils.executeIgnore(() -> { // 第一步:查询数据 - List accounts = mpAccountMapper.selectList(); + List accounts = Collections.emptyList(); + try { + accounts = mpAccountMapper.selectList(); + } catch (Throwable ex) { + if (!ex.getMessage().contains("doesn't exist")) { + throw ex; + } + log.error("[微信公众号 yudao-module-mp - 表结构未导入][参考 https://doc.iocoder.cn/mp/build/ 开启]"); + } log.info("[initLocalCacheIfUpdate][缓存公众号账号,数量为:{}]", accounts.size()); // 第二步:构建缓存。创建或更新支付 Client diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java index 3eb996c4a..57aaf07d0 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java @@ -27,6 +27,7 @@ import javax.annotation.Resource; import javax.validation.Validator; import java.time.LocalDateTime; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; @@ -64,7 +65,15 @@ public class PayChannelServiceImpl implements PayChannelService { // 注意:忽略自动多租户,因为要全局初始化缓存 TenantUtils.executeIgnore(() -> { // 第一步:查询数据 - List channels = channelMapper.selectList(); + List channels = Collections.emptyList(); + try { + channels = channelMapper.selectList(); + } catch (Throwable ex) { + if (!ex.getMessage().contains("doesn't exist")) { + throw ex; + } + log.error("[支付模块 yudao-module-pay - 表结构未导入][参考 https://doc.iocoder.cn/pay/build/ 开启]"); + } log.info("[initLocalCache][缓存支付渠道,数量为:{}]", channels.size()); // 第二步:构建缓存:创建或更新支付 Client diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountServiceImpl.java index 457056f40..94b02dbab 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountServiceImpl.java @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; import cn.iocoder.yudao.module.system.dal.mysql.mail.MailAccountMapper; import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -46,7 +47,7 @@ public class MailAccountServiceImpl implements MailAccountService { } @Override - @Cacheable(value = RedisKeyConstants.MAIL_ACCOUNT, key = "#updateReqVO.id") + @CacheEvict(value = RedisKeyConstants.MAIL_ACCOUNT, key = "#updateReqVO.id") public void updateMailAccount(MailAccountUpdateReqVO updateReqVO) { // 校验是否存在 validateMailAccountExists(updateReqVO.getId()); @@ -57,7 +58,7 @@ public class MailAccountServiceImpl implements MailAccountService { } @Override - @Cacheable(value = RedisKeyConstants.MAIL_ACCOUNT, key = "#id") + @CacheEvict(value = RedisKeyConstants.MAIL_ACCOUNT, key = "#id") public void deleteMailAccount(Long id) { // 校验是否存在账号 validateMailAccountExists(id); diff --git a/yudao-ui-admin/src/views/pay/app/components/weixinChannelForm.vue b/yudao-ui-admin/src/views/pay/app/components/weixinChannelForm.vue index 00e0773b5..4c2e2823d 100644 --- a/yudao-ui-admin/src/views/pay/app/components/weixinChannelForm.vue +++ b/yudao-ui-admin/src/views/pay/app/components/weixinChannelForm.vue @@ -52,9 +52,9 @@ - + @@ -132,7 +132,7 @@ export default { 'config.apiVersion': [{ required: true, message: 'API版本不能为空', trigger: 'blur'}], 'config.mchKey': [{ required: true, message: '请输入商户密钥', trigger: 'blur' }], 'config.keyContent': [{ required: true, message: '请上传 apiclient_cert.p12 证书', trigger: 'blur' }], - 'config.privateKeyContent': [{ required: true, message: '请上传 apiclient_key.perm 证书', trigger: 'blur' }], + 'config.privateKeyContent': [{ required: true, message: '请上传 apiclient_key.pem 证书', trigger: 'blur' }], 'config.privateCertContent': [{ required: true, message: '请上传 apiclient_cert.perm证 书', trigger: 'blur' }], 'config.apiV3Key': [{ required: true, message: '请上传 api V3 密钥值', trigger: 'blur' }], },