Commit 785fbeeb5bc09ba65e570f1e500a87719bbd42e0
1 parent
90fb2c62
code review:限时折扣活动
Showing
10 changed files
with
58 additions
and
68 deletions
pom.xml
| ... | ... | @@ -13,14 +13,14 @@ |
| 13 | 13 | <!-- Server 主项目 --> |
| 14 | 14 | <module>yudao-server</module> |
| 15 | 15 | <!-- 各种 module 拓展 --> |
| 16 | -<!-- <module>yudao-module-member</module>--> | |
| 16 | + <module>yudao-module-member</module> | |
| 17 | 17 | <module>yudao-module-system</module> |
| 18 | 18 | <module>yudao-module-infra</module> |
| 19 | 19 | <!-- <module>yudao-module-bpm</module>--> |
| 20 | 20 | <!-- <module>yudao-module-report</module>--> |
| 21 | 21 | <!-- <module>yudao-module-mp</module>--> |
| 22 | -<!-- <module>yudao-module-pay</module>--> | |
| 23 | -<!-- <module>yudao-module-mall</module>--> | |
| 22 | + <module>yudao-module-pay</module> | |
| 23 | + <module>yudao-module-mall</module> | |
| 24 | 24 | <!-- 示例项目 --> |
| 25 | 25 | <module>yudao-example</module> |
| 26 | 26 | </modules> | ... | ... |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
| ... | ... | @@ -15,7 +15,6 @@ public interface ErrorCodeConstants { |
| 15 | 15 | ErrorCode DISCOUNT_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_001_002, "限时折扣活动已关闭,不能修改"); |
| 16 | 16 | ErrorCode DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_001_003, "限时折扣活动未关闭,不能删除"); |
| 17 | 17 | ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_001_004, "限时折扣活动已关闭,不能重复关闭"); |
| 18 | - ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1_013_001_005, "限时折扣活动已结束,不能关闭"); | |
| 19 | 18 | |
| 20 | 19 | // ========== Banner 相关 1-013-002-000 ============ |
| 21 | 20 | ErrorCode BANNER_NOT_EXISTS = new ErrorCode(1_013_002_000, "Banner 不存在"); | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/DiscountActivityController.java
| ... | ... | @@ -7,11 +7,8 @@ import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; |
| 7 | 7 | import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; |
| 8 | 8 | import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.*; |
| 9 | 9 | import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert; |
| 10 | -import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert; | |
| 11 | 10 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; |
| 12 | 11 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; |
| 13 | -import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO; | |
| 14 | -import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO; | |
| 15 | 12 | import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService; |
| 16 | 13 | import io.swagger.v3.oas.annotations.Operation; |
| 17 | 14 | import io.swagger.v3.oas.annotations.Parameter; |
| ... | ... | @@ -23,8 +20,6 @@ import org.springframework.web.bind.annotation.*; |
| 23 | 20 | import javax.annotation.Resource; |
| 24 | 21 | import javax.validation.Valid; |
| 25 | 22 | import java.util.List; |
| 26 | -import java.util.Set; | |
| 27 | -import java.util.stream.Collectors; | |
| 28 | 23 | |
| 29 | 24 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 30 | 25 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| ... | ... | @@ -94,7 +89,7 @@ public class DiscountActivityController { |
| 94 | 89 | public CommonResult<PageResult<DiscountActivityRespVO>> getDiscountActivityPage(@Valid DiscountActivityPageReqVO pageVO) { |
| 95 | 90 | PageResult<DiscountActivityDO> pageResult = discountActivityService.getDiscountActivityPage(pageVO); |
| 96 | 91 | |
| 97 | - if (CollUtil.isEmpty(pageResult.getList())) { | |
| 92 | + if (CollUtil.isEmpty(pageResult.getList())) { // TODO @zhangshuai:方法里的空行,目的是让代码分块,可以更清晰;所以上面这个空格可以不要,而下面判断之后的,空格,其实加下比较好;类似的还有 spuList、以及后面的 convert | |
| 98 | 93 | return success(PageResult.empty(pageResult.getTotal())); |
| 99 | 94 | } |
| 100 | 95 | // 拼接数据 | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityRespVO.java
| ... | ... | @@ -26,15 +26,16 @@ public class DiscountActivityRespVO extends DiscountActivityBaseVO { |
| 26 | 26 | private LocalDateTime createTime; |
| 27 | 27 | |
| 28 | 28 | |
| 29 | - @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") | |
| 29 | + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") // TODO @zhangshuai:属性和属性之间,最多空一行噢; | |
| 30 | 30 | private Long spuId; |
| 31 | 31 | |
| 32 | 32 | @Schema(description = "限时折扣商品", requiredMode = Schema.RequiredMode.REQUIRED) |
| 33 | 33 | private List<DiscountActivityBaseVO.Product> products; |
| 34 | 34 | |
| 35 | - | |
| 36 | 35 | // ========== 商品字段 ========== |
| 37 | 36 | |
| 37 | + // TODO @zhangshuai:一个优惠活动,会关联多个商品,所以它不用返回 spuName 哈; | |
| 38 | + // TODO 最终界面展示字段就:编号、活动名称、参与商品数、活动状态、开始时间、结束时间、操作 | |
| 38 | 39 | @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, // 从 SPU 的 name 读取 |
| 39 | 40 | example = "618大促") |
| 40 | 41 | private String spuName; |
| ... | ... | @@ -45,5 +46,4 @@ public class DiscountActivityRespVO extends DiscountActivityBaseVO { |
| 45 | 46 | example = "50") |
| 46 | 47 | private Integer marketPrice; |
| 47 | 48 | |
| 48 | - | |
| 49 | 49 | } | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java
| ... | ... | @@ -7,11 +7,8 @@ import cn.iocoder.yudao.framework.common.util.collection.MapUtils; |
| 7 | 7 | import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; |
| 8 | 8 | import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; |
| 9 | 9 | import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.*; |
| 10 | -import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityRespVO; | |
| 11 | -import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductRespVO; | |
| 12 | 10 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; |
| 13 | 11 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; |
| 14 | -import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO; | |
| 15 | 12 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; |
| 16 | 13 | import org.mapstruct.Mapper; |
| 17 | 14 | import org.mapstruct.factory.Mappers; |
| ... | ... | @@ -47,7 +44,7 @@ public interface DiscountActivityConvert { |
| 47 | 44 | List<ProductSpuRespDTO> spuList) { |
| 48 | 45 | PageResult<DiscountActivityRespVO> pageResult = convertPage(page); |
| 49 | 46 | |
| 50 | - // 拼接商品 | |
| 47 | + // 拼接商品 TODO @zhangshuai:类似空行的问题,也可以看看 | |
| 51 | 48 | Map<Long, DiscountProductDO> discountActivityMap = CollectionUtils.convertMap(discountProductDOList, DiscountProductDO::getActivityId); |
| 52 | 49 | Map<Long, ProductSpuRespDTO> spuMap = CollectionUtils.convertMap(spuList, ProductSpuRespDTO::getId); |
| 53 | 50 | pageResult.getList().forEach(item -> { | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java
| ... | ... | @@ -34,7 +34,6 @@ public class DiscountProductDO extends BaseDO { |
| 34 | 34 | */ |
| 35 | 35 | private Long activityId; |
| 36 | 36 | |
| 37 | - | |
| 38 | 37 | /** |
| 39 | 38 | * 商品 SPU 编号 |
| 40 | 39 | * |
| ... | ... | @@ -67,7 +66,6 @@ public class DiscountProductDO extends BaseDO { |
| 67 | 66 | */ |
| 68 | 67 | private Integer discountPrice; |
| 69 | 68 | |
| 70 | - // TODO 芋艿:这几个字段,要新增下; | |
| 71 | 69 | /** |
| 72 | 70 | * 活动状态 |
| 73 | 71 | * | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java
| ... | ... | @@ -28,6 +28,6 @@ public interface DiscountProductMapper extends BaseMapperX<DiscountProductDO> { |
| 28 | 28 | return selectList(DiscountProductDO::getActivityId, activityIds); |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | - | |
| 31 | + // TODO @zhangshuai:逻辑里,尽量避免写 join 语句哈,你可以看看这个查询,有什么办法优化?目前的一个思路,是分 2 次查询,性能也是 ok 的 | |
| 32 | 32 | List<DiscountProductDO> getMatchDiscountProductList(@Param("skuIds") Collection<Long> skuIds); |
| 33 | 33 | } | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java
| ... | ... | @@ -43,7 +43,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { |
| 43 | 43 | |
| 44 | 44 | @Override |
| 45 | 45 | public List<DiscountProductDO> getMatchDiscountProductList(Collection<Long> skuIds) { |
| 46 | - // 芋艿:开启、满足 skuId、日期内 | |
| 46 | + // TODO @zhangshuai:这里是不是可以直接 return discountProductMapper.getMatchDiscountProductList(skuIds); 一般来说,如果 idea 报“黄色”的警告,尽量都处理下哈;原则是,一切警告,皆为异常(错误),这样可以写出更好的代码。 | |
| 47 | 47 | List<DiscountProductDO> matchDiscountProductList = discountProductMapper.getMatchDiscountProductList(skuIds); |
| 48 | 48 | return matchDiscountProductList; |
| 49 | 49 | } |
| ... | ... | @@ -55,9 +55,11 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { |
| 55 | 55 | |
| 56 | 56 | // 插入活动 |
| 57 | 57 | DiscountActivityDO discountActivity = DiscountActivityConvert.INSTANCE.convert(createReqVO) |
| 58 | + // TODO @zhangshuai:这里的调用去掉哈,强制就是开启的; | |
| 58 | 59 | .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime())); |
| 59 | 60 | discountActivityMapper.insert(discountActivity); |
| 60 | 61 | // 插入商品 |
| 62 | + // TODO @zhangshuai:activityStatus 最好代码里,也做下设置噢。 | |
| 61 | 63 | List<DiscountProductDO> discountProducts = convertList(createReqVO.getProducts(), |
| 62 | 64 | product -> DiscountActivityConvert.INSTANCE.convert(product).setActivityId(discountActivity.getId())); |
| 63 | 65 | discountProductMapper.insertBatch(discountProducts); |
| ... | ... | @@ -84,6 +86,8 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { |
| 84 | 86 | } |
| 85 | 87 | |
| 86 | 88 | private void updateDiscountProduct(DiscountActivityUpdateReqVO updateReqVO) { |
| 89 | + // TODO @zhangshuai:这里的逻辑,可以优化下哈;参考 CombinationActivityServiceImpl 的 updateCombinationProduct,主要是 CollectionUtils.diffList 的使用哈; | |
| 90 | + // 然后原先是使用 DiscountActivityConvert.INSTANCE.isEquals 对比,现在看看是不是简化就基于 skuId 对比就完事了;之前写的太精细,意义不大; | |
| 87 | 91 | List<DiscountProductDO> dbDiscountProducts = discountProductMapper.selectListByActivityId(updateReqVO.getId()); |
| 88 | 92 | // 计算要删除的记录 |
| 89 | 93 | List<Long> deleteIds = convertList(dbDiscountProducts, DiscountProductDO::getId, |
| ... | ... | @@ -102,7 +106,6 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { |
| 102 | 106 | } |
| 103 | 107 | } |
| 104 | 108 | |
| 105 | - // 芋艿:校验逻辑简化,只查询时间冲突的活动,开启状态的。 | |
| 106 | 109 | /** |
| 107 | 110 | * 校验商品是否冲突 |
| 108 | 111 | * |
| ... | ... | @@ -114,13 +117,11 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { |
| 114 | 117 | return; |
| 115 | 118 | } |
| 116 | 119 | // 查询商品参加的活动 |
| 117 | - | |
| 120 | + // TODO @zhangshuai:下面 121 这个查询,是不是不用做呀;直接 convert 出 skuId 集合就 ok 啦; | |
| 118 | 121 | List<DiscountProductDO> list = discountProductMapper.selectListByActivityId(id); |
| 122 | + // TODO @zhangshuai:一般简单的 stream 方法,建议是使用 CollectionUtils,例如说这里是 convertList 对把。 | |
| 119 | 123 | List<Long> skuIds = list.stream().map(item -> item.getSkuId()).collect(Collectors.toList()); |
| 120 | 124 | List<DiscountProductDO> matchDiscountProductList = getMatchDiscountProductList(skuIds); |
| 121 | -// getRewardProductListBySkuIds( | |
| 122 | -// convertSet(products, DiscountActivityBaseVO.Product::getSkuId), | |
| 123 | -// asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus())); | |
| 124 | 125 | if (id != null) { // 排除自己这个活动 |
| 125 | 126 | matchDiscountProductList.removeIf(product -> id.equals(product.getActivityId())); |
| 126 | 127 | } |
| ... | ... | @@ -133,15 +134,12 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { |
| 133 | 134 | @Override |
| 134 | 135 | public void closeDiscountActivity(Long id) { |
| 135 | 136 | // 校验存在 |
| 136 | - DiscountActivityDO dbDiscountActivity = validateDiscountActivityExists(id); | |
| 137 | - if (dbDiscountActivity.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) { // 已关闭的活动,不能关闭噢 | |
| 137 | + DiscountActivityDO activity = validateDiscountActivityExists(id); | |
| 138 | + if (activity.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) { // 已关闭的活动,不能关闭噢 | |
| 138 | 139 | throw exception(DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED); |
| 139 | 140 | } |
| 140 | - if (dbDiscountActivity.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) { // 已关闭的活动,不能关闭噢 | |
| 141 | - throw exception(DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_END); | |
| 142 | - } | |
| 143 | 141 | |
| 144 | - // 更新为关闭。 | |
| 142 | + // 更新 | |
| 145 | 143 | DiscountActivityDO updateObj = new DiscountActivityDO().setId(id).setStatus(PromotionActivityStatusEnum.CLOSE.getStatus()); |
| 146 | 144 | discountActivityMapper.updateById(updateObj); |
| 147 | 145 | } |
| ... | ... | @@ -185,4 +183,5 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { |
| 185 | 183 | public List<DiscountProductDO> getDiscountProductsByActivityId(Collection<Long> activityIds) { |
| 186 | 184 | return discountProductMapper.selectList("activity_id", activityIds); |
| 187 | 185 | } |
| 186 | + | |
| 188 | 187 | } | ... | ... |
yudao-server/pom.xml
| ... | ... | @@ -37,11 +37,11 @@ |
| 37 | 37 | </dependency> |
| 38 | 38 | |
| 39 | 39 | <!-- 会员中心。默认注释,保证编译速度 --> |
| 40 | -<!-- <dependency>--> | |
| 41 | -<!-- <groupId>cn.iocoder.boot</groupId>--> | |
| 42 | -<!-- <artifactId>yudao-module-member-biz</artifactId>--> | |
| 43 | -<!-- <version>${revision}</version>--> | |
| 44 | -<!-- </dependency>--> | |
| 40 | + <dependency> | |
| 41 | + <groupId>cn.iocoder.boot</groupId> | |
| 42 | + <artifactId>yudao-module-member-biz</artifactId> | |
| 43 | + <version>${revision}</version> | |
| 44 | + </dependency> | |
| 45 | 45 | |
| 46 | 46 | <!-- 数据报表。默认注释,保证编译速度 --> |
| 47 | 47 | <!-- <dependency>--> |
| ... | ... | @@ -56,40 +56,40 @@ |
| 56 | 56 | <!-- <version>${revision}</version>--> |
| 57 | 57 | <!-- </dependency>--> |
| 58 | 58 | <!-- 支付服务。默认注释,保证编译速度 --> |
| 59 | -<!-- <dependency>--> | |
| 60 | -<!-- <groupId>cn.iocoder.boot</groupId>--> | |
| 61 | -<!-- <artifactId>yudao-module-pay-biz</artifactId>--> | |
| 62 | -<!-- <version>${revision}</version>--> | |
| 63 | -<!-- </dependency>--> | |
| 59 | + <dependency> | |
| 60 | + <groupId>cn.iocoder.boot</groupId> | |
| 61 | + <artifactId>yudao-module-pay-biz</artifactId> | |
| 62 | + <version>${revision}</version> | |
| 63 | + </dependency> | |
| 64 | 64 | |
| 65 | 65 | <!-- 微信公众号模块。默认注释,保证编译速度 --> |
| 66 | -<!-- <dependency>--> | |
| 67 | -<!-- <groupId>cn.iocoder.boot</groupId>--> | |
| 68 | -<!-- <artifactId>yudao-module-mp-biz</artifactId>--> | |
| 69 | -<!-- <version>${revision}</version>--> | |
| 70 | -<!-- </dependency>--> | |
| 66 | + <dependency> | |
| 67 | + <groupId>cn.iocoder.boot</groupId> | |
| 68 | + <artifactId>yudao-module-mp-biz</artifactId> | |
| 69 | + <version>${revision}</version> | |
| 70 | + </dependency> | |
| 71 | 71 | |
| 72 | - <!-- 商城相关模块。默认注释,保证编译速度 --> | |
| 73 | -<!-- <dependency>--> | |
| 74 | -<!-- <groupId>cn.iocoder.boot</groupId>--> | |
| 75 | -<!-- <artifactId>yudao-module-promotion-biz</artifactId>--> | |
| 76 | -<!-- <version>${revision}</version>--> | |
| 77 | -<!-- </dependency>--> | |
| 78 | -<!-- <dependency>--> | |
| 79 | -<!-- <groupId>cn.iocoder.boot</groupId>--> | |
| 80 | -<!-- <artifactId>yudao-module-product-biz</artifactId>--> | |
| 81 | -<!-- <version>${revision}</version>--> | |
| 82 | -<!-- </dependency>--> | |
| 83 | -<!-- <dependency>--> | |
| 84 | -<!-- <groupId>cn.iocoder.boot</groupId>--> | |
| 85 | -<!-- <artifactId>yudao-module-trade-biz</artifactId>--> | |
| 86 | -<!-- <version>${revision}</version>--> | |
| 87 | -<!-- </dependency>--> | |
| 88 | -<!-- <dependency>--> | |
| 89 | -<!-- <groupId>cn.iocoder.boot</groupId>--> | |
| 90 | -<!-- <artifactId>yudao-module-statistics-biz</artifactId>--> | |
| 91 | -<!-- <version>${revision}</version>--> | |
| 92 | -<!-- </dependency>--> | |
| 72 | +<!-- 商城相关模块。默认注释,保证编译速度--> | |
| 73 | + <dependency> | |
| 74 | + <groupId>cn.iocoder.boot</groupId> | |
| 75 | + <artifactId>yudao-module-promotion-biz</artifactId> | |
| 76 | + <version>${revision}</version> | |
| 77 | + </dependency> | |
| 78 | + <dependency> | |
| 79 | + <groupId>cn.iocoder.boot</groupId> | |
| 80 | + <artifactId>yudao-module-product-biz</artifactId> | |
| 81 | + <version>${revision}</version> | |
| 82 | + </dependency> | |
| 83 | + <dependency> | |
| 84 | + <groupId>cn.iocoder.boot</groupId> | |
| 85 | + <artifactId>yudao-module-trade-biz</artifactId> | |
| 86 | + <version>${revision}</version> | |
| 87 | + </dependency> | |
| 88 | + <dependency> | |
| 89 | + <groupId>cn.iocoder.boot</groupId> | |
| 90 | + <artifactId>yudao-module-statistics-biz</artifactId> | |
| 91 | + <version>${revision}</version> | |
| 92 | + </dependency> | |
| 93 | 93 | |
| 94 | 94 | <!-- spring boot 配置所需依赖 --> |
| 95 | 95 | <dependency> | ... | ... |