Commit 64b842ed944feec3eeaa0bda566a5c76f031fedc

Authored by YunaiV
2 parents f8e4aece e21422d1

Merge branch 'feature/mall_product' of https://gitee.com/zhijiantianya/ruoyi-vue…

…-pro into feature/mall_product
Showing 22 changed files with 168 additions and 92 deletions
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/article/vo/article/ArticleBaseVO.java
... ... @@ -34,10 +34,6 @@ public class ArticleBaseVO {
34 34 @Schema(description = "文章简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "这是一个简介")
35 35 private String introduction;
36 36  
37   - // TODO @puhui999:浏览量的字段,应该不是后端新增设置的哈;
38   - @Schema(description = "浏览次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "111")
39   - private String browseCount;
40   -
41 37 @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
42 38 @NotNull(message = "排序不能为空")
43 39 private Integer sort;
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/article/vo/article/ArticleRespVO.java
... ... @@ -16,6 +16,9 @@ public class ArticleRespVO extends ArticleBaseVO {
16 16 @Schema(description = "文章编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8606")
17 17 private Long id;
18 18  
  19 + @Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "99999")
  20 + private Integer browseCount;
  21 +
19 22 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
20 23 private LocalDateTime createTime;
21 24  
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java
... ... @@ -22,6 +22,7 @@ import org.springframework.web.bind.annotation.RequestParam;
22 22 import org.springframework.web.bind.annotation.RestController;
23 23  
24 24 import javax.annotation.Resource;
  25 +import java.time.LocalDateTime;
25 26 import java.util.*;
26 27  
27 28 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
... ... @@ -63,10 +64,11 @@ public class AppActivityController {
63 64 if (CollUtil.isEmpty(spuIds)) {
64 65 return new ArrayList<>();
65 66 }
  67 + LocalDateTime now = LocalDateTime.now();
66 68 List<AppActivityRespVO> activityList = new ArrayList<>();
67   - // 拼团活动
68   - List<CombinationActivityDO> combinationActivities = combinationActivityService.getCombinationActivityBySpuIdsAndStatus(
69   - spuIds, CommonStatusEnum.ENABLE.getStatus());
  69 + // 拼团活动-获取开启的且开始的且没有结束的活动
  70 + List<CombinationActivityDO> combinationActivities = combinationActivityService.getCombinationActivityBySpuIdsAndStatusAndDateTimeLt(
  71 + spuIds, CommonStatusEnum.ENABLE.getStatus(), now);
70 72 if (CollUtil.isNotEmpty(combinationActivities)) {
71 73 combinationActivities.forEach(item -> {
72 74 activityList.add(new AppActivityRespVO().setId(item.getId())
... ... @@ -74,9 +76,9 @@ public class AppActivityController {
74 76 .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime()));
75 77 });
76 78 }
77   - // 秒杀活动
78   - List<SeckillActivityDO> seckillActivities = seckillActivityService.getSeckillActivityBySpuIdsAndStatus(
79   - spuIds, CommonStatusEnum.ENABLE.getStatus());
  79 + // 秒杀活动-获取开启的且开始的且没有结束的活动
  80 + List<SeckillActivityDO> seckillActivities = seckillActivityService.getSeckillActivityBySpuIdsAndStatusAndDateTimeLt(
  81 + spuIds, CommonStatusEnum.ENABLE.getStatus(), now);
80 82 if (CollUtil.isNotEmpty(seckillActivities)) {
81 83 seckillActivities.forEach(item -> {
82 84 activityList.add(new AppActivityRespVO().setId(item.getId())
... ... @@ -84,9 +86,9 @@ public class AppActivityController {
84 86 .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime()));
85 87 });
86 88 }
87   - // 砍价活动
88   - List<BargainActivityDO> bargainActivities = bargainActivityService.getBargainActivityBySpuIdsAndStatus(
89   - spuIds, CommonStatusEnum.ENABLE.getStatus());
  89 + // 砍价活动-获取开启的且开始的且没有结束的活动
  90 + List<BargainActivityDO> bargainActivities = bargainActivityService.getBargainActivityBySpuIdsAndStatusAndDateTimeLt(
  91 + spuIds, CommonStatusEnum.ENABLE.getStatus(), now);
90 92 if (CollUtil.isNotEmpty(bargainActivities)) {
91 93 bargainActivities.forEach(item -> {
92 94 activityList.add(new AppActivityRespVO().setId(item.getId())
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/article/AppArticleCategoryController.java
... ... @@ -13,6 +13,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
13 13 import org.springframework.web.bind.annotation.RestController;
14 14  
15 15 import javax.annotation.Resource;
  16 +import java.util.Comparator;
16 17 import java.util.List;
17 18  
18 19 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
... ... @@ -31,7 +32,7 @@ public class AppArticleCategoryController {
31 32 public CommonResult<List<AppArticleCategoryRespVO>> getArticleCategoryList() {
32 33 List<ArticleCategoryDO> categoryList = articleCategoryService.getArticleCategoryListByStatus(
33 34 CommonStatusEnum.ENABLE.getStatus());
34   - // TODO @puhui999:排序下
  35 + categoryList.sort(Comparator.comparing(ArticleCategoryDO::getSort).reversed()); // 按 sort 降序排列
35 36 return success(ArticleCategoryConvert.INSTANCE.convertList04(categoryList));
36 37 }
37 38  
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/article/AppArticleController.java
... ... @@ -11,6 +11,7 @@ import io.swagger.v3.oas.annotations.Parameter;
11 11 import io.swagger.v3.oas.annotations.Parameters;
12 12 import io.swagger.v3.oas.annotations.tags.Tag;
13 13 import org.springframework.validation.annotation.Validated;
  14 +import org.springframework.web.bind.annotation.PutMapping;
14 15 import org.springframework.web.bind.annotation.RequestMapping;
15 16 import org.springframework.web.bind.annotation.RequestParam;
16 17 import org.springframework.web.bind.annotation.RestController;
... ... @@ -55,5 +56,12 @@ public class AppArticleController {
55 56 return success(ArticleConvert.INSTANCE.convert01(articleService.getArticle(id)));
56 57 }
57 58  
58   - // TODO @puhui999:增加浏览量,实现一个接口;先简单做,用户规模不大,只 +1 即可;ps:uniapp 那边也要接下噢
  59 + @PutMapping("/add-browseCount")
  60 + @Operation(summary = "增加文章浏览量")
  61 + @Parameter(name = "id", description = "文章编号", example = "1024")
  62 + public CommonResult<Boolean> addBrowseCount(@RequestParam("id") Long id) {
  63 + articleService.addBrowseCount(id);
  64 + return success(true);
  65 + }
  66 +
59 67 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java
... ... @@ -204,25 +204,22 @@ public interface CombinationActivityConvert {
204 204 return respVO;
205 205 }
206 206  
  207 + @Mapping(target = "id", ignore = true)
  208 + CombinationRecordDO convert5(CombinationRecordDO headRecord);
  209 +
207 210 /**
208 211 * 转换生成虚拟成团虚拟记录
209 212 *
210   - * @param virtualGroupHeadRecord 虚拟成团团长记录
  213 + * @param headRecord 虚拟成团团长记录
211 214 * @return 虚拟记录列表
212 215 */
213   - // TODO @puhui999:1)方法名,建议改成 convertVirtualRecordList(CombinationRecordDO headRecord);2)第 220 到 225 可以搞成 mapstruct 一个方法,默认都 copy 进去,然后 set 第 226 到 232 的字段
214   - default List<CombinationRecordDO> convertVirtualGroupList(CombinationRecordDO virtualGroupHeadRecord) {
  216 + default List<CombinationRecordDO> convertVirtualRecordList(CombinationRecordDO headRecord) {
215 217 List<CombinationRecordDO> createRecords = new ArrayList<>();
216 218 // 计算需要创建的虚拟成团记录数量
217   - int count = virtualGroupHeadRecord.getUserSize() - virtualGroupHeadRecord.getUserCount();
  219 + int count = headRecord.getUserSize() - headRecord.getUserCount();
218 220 for (int i = 0; i < count; i++) {
219 221 // 基础信息和团长保持一致
220   - CombinationRecordDO newRecord = new CombinationRecordDO().setActivityId(virtualGroupHeadRecord.getActivityId())
221   - .setCombinationPrice(virtualGroupHeadRecord.getCombinationPrice()).setSpuId(virtualGroupHeadRecord.getSpuId()).setSpuName(virtualGroupHeadRecord.getSpuName())
222   - .setPicUrl(virtualGroupHeadRecord.getPicUrl()).setSkuId(virtualGroupHeadRecord.getSkuId()).setHeadId(virtualGroupHeadRecord.getId())
223   - .setStatus(virtualGroupHeadRecord.getStatus()) // 状态保持和创建时一致,创建完成后会接着处理
224   - .setVirtualGroup(virtualGroupHeadRecord.getVirtualGroup()).setExpireTime(virtualGroupHeadRecord.getExpireTime())
225   - .setStartTime(virtualGroupHeadRecord.getStartTime()).setUserSize(virtualGroupHeadRecord.getUserSize()).setUserCount(virtualGroupHeadRecord.getUserCount());
  222 + CombinationRecordDO newRecord = convert5(headRecord);
226 223 // 虚拟信息
227 224 newRecord.setCount(0);
228 225 newRecord.setUserId(0L);
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/article/ArticleDO.java
... ... @@ -54,7 +54,7 @@ public class ArticleDO extends BaseDO {
54 54 /**
55 55 * 浏览次数
56 56 */
57   - private String browseCount;
  57 + private Integer browseCount;
58 58 /**
59 59 * 排序
60 60 */
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/article/ArticleCategoryMapper.java
... ... @@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.category.Ar
7 7 import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleCategoryDO;
8 8 import org.apache.ibatis.annotations.Mapper;
9 9  
  10 +import java.util.List;
  11 +
10 12 /**
11 13 * 文章分类 Mapper
12 14 *
... ... @@ -23,4 +25,8 @@ public interface ArticleCategoryMapper extends BaseMapperX&lt;ArticleCategoryDO&gt; {
23 25 .orderByDesc(ArticleCategoryDO::getSort));
24 26 }
25 27  
  28 + default List<ArticleCategoryDO> selectListByStatus(Integer status) {
  29 + return selectList(ArticleCategoryDO::getStatus, status);
  30 + }
  31 +
26 32 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/article/ArticleMapper.java
... ... @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 6 import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticlePageReqVO;
7 7 import cn.iocoder.yudao.module.promotion.controller.app.article.vo.article.AppArticlePageReqVO;
8 8 import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO;
  9 +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
9 10 import org.apache.ibatis.annotations.Mapper;
10 11  
11 12 import java.util.List;
... ... @@ -42,5 +43,10 @@ public interface ArticleMapper extends BaseMapperX&lt;ArticleDO&gt; {
42 43 .eqIfPresent(ArticleDO::getCategoryId, pageReqVO.getCategoryId()));
43 44 }
44 45  
  46 + default void updateBrowseCount(Long id) {
  47 + update(null, new LambdaUpdateWrapper<ArticleDO>()
  48 + .eq(ArticleDO::getId, id)
  49 + .setSql("browse_count = browse_count + 1"));
  50 + }
45 51  
46 52 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java
... ... @@ -102,9 +102,19 @@ public interface BargainActivityMapper extends BaseMapperX&lt;BargainActivityDO&gt; {
102 102 .groupBy("spu_id"));
103 103 }
104 104  
105   - default List<BargainActivityDO> selectListByIds(Collection<Long> ids) {
  105 + /**
  106 + * 获取指定活动编号的活动列表且
  107 + * 开始时间和结束时间小于给定时间 dateTime 的活动列表
  108 + *
  109 + * @param ids 活动编号
  110 + * @param dateTime 指定日期
  111 + * @return 活动列表
  112 + */
  113 + default List<BargainActivityDO> selectListByIdsAndDateTimeLt(Collection<Long> ids, LocalDateTime dateTime) {
106 114 return selectList(new LambdaQueryWrapperX<BargainActivityDO>()
107 115 .in(BargainActivityDO::getId, ids)
  116 + .lt(BargainActivityDO::getStartTime, dateTime)
  117 + .lt(BargainActivityDO::getEndTime, dateTime)
108 118 .orderByDesc(BargainActivityDO::getCreateTime));
109 119 }
110 120  
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationActivityMapper.java
... ... @@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
10 10 import org.apache.ibatis.annotations.Mapper;
11 11 import org.apache.ibatis.annotations.Param;
12 12  
  13 +import java.time.LocalDateTime;
13 14 import java.util.Collection;
14 15 import java.util.List;
15 16 import java.util.Map;
... ... @@ -58,9 +59,19 @@ public interface CombinationActivityMapper extends BaseMapperX&lt;CombinationActivi
58 59 .groupBy("spu_id"));
59 60 }
60 61  
61   - default List<CombinationActivityDO> selectListByIds(Collection<Long> ids) {
  62 + /**
  63 + * 获取指定活动编号的活动列表且
  64 + * 开始时间和结束时间小于给定时间 dateTime 的活动列表
  65 + *
  66 + * @param ids 活动编号
  67 + * @param dateTime 指定日期
  68 + * @return 活动列表
  69 + */
  70 + default List<CombinationActivityDO> selectListByIdsAndDateTimeLt(Collection<Long> ids, LocalDateTime dateTime) {
62 71 return selectList(new LambdaQueryWrapperX<CombinationActivityDO>()
63 72 .in(CombinationActivityDO::getId, ids)
  73 + .lt(CombinationActivityDO::getStartTime, dateTime)
  74 + .lt(CombinationActivityDO::getEndTime, dateTime)
64 75 .orderByDesc(CombinationActivityDO::getCreateTime));
65 76 }
66 77  
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java
... ... @@ -13,6 +13,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
13 13 import org.apache.ibatis.annotations.Mapper;
14 14 import org.apache.ibatis.annotations.Param;
15 15  
  16 +import java.time.LocalDateTime;
16 17 import java.util.Collection;
17 18 import java.util.List;
18 19 import java.util.Map;
... ... @@ -90,9 +91,19 @@ public interface SeckillActivityMapper extends BaseMapperX&lt;SeckillActivityDO&gt; {
90 91 .groupBy("spu_id"));
91 92 }
92 93  
93   - default List<SeckillActivityDO> selectListByIds(Collection<Long> ids) {
  94 + /**
  95 + * 获取指定活动编号的活动列表且
  96 + * 开始时间和结束时间小于给定时间 dateTime 的活动列表
  97 + *
  98 + * @param ids 活动编号
  99 + * @param dateTime 指定日期
  100 + * @return 活动列表
  101 + */
  102 + default List<SeckillActivityDO> selectListByIdsAndDateTimeLt(Collection<Long> ids, LocalDateTime dateTime) {
94 103 return selectList(new LambdaQueryWrapperX<SeckillActivityDO>()
95 104 .in(SeckillActivityDO::getId, ids)
  105 + .lt(SeckillActivityDO::getStartTime, dateTime)
  106 + .lt(SeckillActivityDO::getEndTime, dateTime)
96 107 .orderByDesc(SeckillActivityDO::getCreateTime));
97 108 }
98 109  
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/article/ArticleCategoryServiceImpl.java
1 1 package cn.iocoder.yudao.module.promotion.service.article;
2 2  
3   -import cn.hutool.core.collection.CollUtil;
4 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 4 import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.category.ArticleCategoryCreateReqVO;
6 5 import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.category.ArticleCategoryPageReqVO;
7 6 import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.category.ArticleCategoryUpdateReqVO;
8 7 import cn.iocoder.yudao.module.promotion.convert.article.ArticleCategoryConvert;
9 8 import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleCategoryDO;
10   -import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO;
11 9 import cn.iocoder.yudao.module.promotion.dal.mysql.article.ArticleCategoryMapper;
12 10 import org.springframework.context.annotation.Lazy;
13 11 import org.springframework.stereotype.Service;
... ... @@ -59,9 +57,8 @@ public class ArticleCategoryServiceImpl implements ArticleCategoryService {
59 57 // 校验存在
60 58 validateArticleCategoryExists(id);
61 59 // 校验是不是存在关联文章
62   - // TODO @puhui999:最好获得数量哈;
63   - List<ArticleDO> articleList = articleService.getArticleByCategoryId(id);
64   - if (CollUtil.isNotEmpty(articleList)) {
  60 + Long count = articleService.getArticleCountByCategoryId(id);
  61 + if (count > 0) {
65 62 throw exception(ARTICLE_CATEGORY_DELETE_FAIL_HAVE_ARTICLES);
66 63 }
67 64  
... ... @@ -87,8 +84,7 @@ public class ArticleCategoryServiceImpl implements ArticleCategoryService {
87 84  
88 85 @Override
89 86 public List<ArticleCategoryDO> getArticleCategoryListByStatus(Integer status) {
90   - // TODO @puhui999:selectListByStatus
91   - return articleCategoryMapper.selectList(ArticleCategoryDO::getStatus, status);
  87 + return articleCategoryMapper.selectListByStatus(status);
92 88 }
93 89  
94 90 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/article/ArticleService.java
... ... @@ -80,4 +80,19 @@ public interface ArticleService {
80 80 */
81 81 List<ArticleDO> getArticleByCategoryId(Long categoryId);
82 82  
  83 + /**
  84 + * 获得指定分类的文章数量
  85 + *
  86 + * @param categoryId 文章分类编号
  87 + * @return 文章数量
  88 + */
  89 + Long getArticleCountByCategoryId(Long categoryId);
  90 +
  91 + /**
  92 + * 增加文章浏览量
  93 + *
  94 + * @param id 文章编号
  95 + */
  96 + void addBrowseCount(Long id);
  97 +
83 98 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/article/ArticleServiceImpl.java
... ... @@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleCategoryD
10 10 import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO;
11 11 import cn.iocoder.yudao.module.promotion.dal.mysql.article.ArticleMapper;
12 12 import org.springframework.stereotype.Service;
  13 +import org.springframework.transaction.annotation.Transactional;
13 14 import org.springframework.validation.annotation.Validated;
14 15  
15 16 import javax.annotation.Resource;
... ... @@ -41,6 +42,7 @@ public class ArticleServiceImpl implements ArticleService {
41 42  
42 43 // 插入
43 44 ArticleDO article = ArticleConvert.INSTANCE.convert(createReqVO);
  45 + article.setBrowseCount(0); // 初始浏览量
44 46 articleMapper.insert(article);
45 47 // 返回
46 48 return article.getId();
... ... @@ -104,4 +106,19 @@ public class ArticleServiceImpl implements ArticleService {
104 106 return articleMapper.selectList(ArticleDO::getCategoryId, categoryId);
105 107 }
106 108  
  109 + @Override
  110 + public Long getArticleCountByCategoryId(Long categoryId) {
  111 + return articleMapper.selectCount(ArticleDO::getCategoryId, categoryId);
  112 + }
  113 +
  114 + @Override
  115 + @Transactional(rollbackFor = Exception.class)
  116 + public void addBrowseCount(Long id) {
  117 + // 校验文章是否存在
  118 + validateArticleExists(id);
  119 +
  120 + // 增加浏览次数 TODO 先简单做,用户规模不大,只 +1
  121 + articleMapper.updateBrowseCount(id);
  122 + }
  123 +
107 124 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityService.java
... ... @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.activity.Ba
8 8 import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO;
9 9  
10 10 import javax.validation.Valid;
  11 +import java.time.LocalDateTime;
11 12 import java.util.Collection;
12 13 import java.util.List;
13 14 import java.util.Set;
... ... @@ -102,10 +103,11 @@ public interface BargainActivityService {
102 103 /**
103 104 * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录
104 105 *
105   - * @param spuIds spu 编号
106   - * @param status 状态
  106 + * @param spuIds spu 编号
  107 + * @param status 状态
  108 + * @param dateTime 日期时间
107 109 * @return 砍价活动列表
108 110 */
109   - List<BargainActivityDO> getBargainActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status);
  111 + List<BargainActivityDO> getBargainActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime);
110 112  
111 113 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java
... ... @@ -182,15 +182,15 @@ public class BargainActivityServiceImpl implements BargainActivityService {
182 182 }
183 183  
184 184 @Override
185   - public List<BargainActivityDO> getBargainActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) {
  185 + public List<BargainActivityDO> getBargainActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime) {
186 186 // 1. 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号
187   - // TODO @puhui999:我想了下,这种是不是只展示当前正在进行中的。已经结束、或者未开始的,可能没啥意义?
188 187 List<Map<String, Object>> spuIdAndActivityIdMaps = bargainActivityMapper.selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(spuIds, status);
189 188 if (CollUtil.isEmpty(spuIdAndActivityIdMaps)) {
190 189 return Collections.emptyList();
191 190 }
192 191 // 2. 查询活动详情
193   - return bargainActivityMapper.selectListByIds(convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId")));
  192 + return bargainActivityMapper.selectListByIdsAndDateTimeLt(
  193 + convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId")), dateTime);
194 194 }
195 195  
196 196 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java
... ... @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationA
9 9 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
10 10  
11 11 import javax.validation.Valid;
  12 +import java.time.LocalDateTime;
12 13 import java.util.Collection;
13 14 import java.util.Collections;
14 15 import java.util.List;
... ... @@ -120,10 +121,11 @@ public interface CombinationActivityService {
120 121 /**
121 122 * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录
122 123 *
123   - * @param spuIds spu 编号
124   - * @param status 状态
  124 + * @param spuIds spu 编号
  125 + * @param status 状态
  126 + * @param dateTime 日期时间
125 127 * @return 拼团活动列表
126 128 */
127   - List<CombinationActivityDO> getCombinationActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status);
  129 + List<CombinationActivityDO> getCombinationActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime);
128 130  
129 131 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java
... ... @@ -25,6 +25,7 @@ import org.springframework.transaction.annotation.Transactional;
25 25 import org.springframework.validation.annotation.Validated;
26 26  
27 27 import javax.annotation.Resource;
  28 +import java.time.LocalDateTime;
28 29 import java.util.Collection;
29 30 import java.util.Collections;
30 31 import java.util.List;
... ... @@ -228,14 +229,15 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
228 229 }
229 230  
230 231 @Override
231   - public List<CombinationActivityDO> getCombinationActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) {
  232 + public List<CombinationActivityDO> getCombinationActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime) {
232 233 // 1.查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号
233 234 List<Map<String, Object>> spuIdAndActivityIdMaps = combinationActivityMapper.selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(spuIds, status);
234 235 if (CollUtil.isEmpty(spuIdAndActivityIdMaps)) {
235 236 return Collections.emptyList();
236 237 }
237 238 // 2.查询活动详情
238   - return combinationActivityMapper.selectListByIds(convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId")));
  239 + return combinationActivityMapper.selectListByIdsAndDateTimeLt(
  240 + convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId")), dateTime);
239 241 }
240 242  
241 243 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
... ... @@ -6,6 +6,7 @@ import cn.hutool.extra.spring.SpringUtil;
6 6 import cn.iocoder.yudao.framework.common.core.KeyValue;
7 7 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
8 8 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  9 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
9 10 import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
10 11 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
11 12 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
... ... @@ -22,6 +23,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationR
22 23 import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper;
23 24 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
24 25 import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
  26 +import lombok.extern.slf4j.Slf4j;
25 27 import org.springframework.stereotype.Service;
26 28 import org.springframework.transaction.annotation.Transactional;
27 29 import org.springframework.validation.annotation.Validated;
... ... @@ -45,6 +47,7 @@ import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
45 47 * @author HUIHUI
46 48 */
47 49 @Service
  50 +@Slf4j
48 51 @Validated
49 52 public class CombinationRecordServiceImpl implements CombinationRecordService {
50 53  
... ... @@ -353,21 +356,21 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
353 356  
354 357 // 3. 逐个处理拼团,过期 or 虚拟成团
355 358 KeyValue<Integer, Integer> keyValue = new KeyValue<>(0, 0); // 统计过期拼团和虚拟成团
356   - for (CombinationRecordDO recordDO : headExpireRecords) {
357   - // TODO @puhui999:recordDO 非必要的情况下,不用带 DO;直接 record;
  359 + for (CombinationRecordDO record : headExpireRecords) {
358 360 try {
359   - CombinationActivityDO activity = activityMap.get(recordDO.getActivityId());
  361 + CombinationActivityDO activity = activityMap.get(record.getActivityId());
360 362 if (activity == null || !activity.getVirtualGroup()) { // 取不到活动的或者不是虚拟拼团的
361 363 // 3.1. 处理过期的拼团
362   - getSelf().handleExpireRecord(recordDO);
  364 + getSelf().handleExpireRecord(record);
363 365 keyValue.setKey(keyValue.getKey() + 1);
364 366 } else {
365 367 // 3.2. 处理虚拟成团
366   - getSelf().handleVirtualGroupRecord(recordDO);
  368 + getSelf().handleVirtualGroupRecord(record);
367 369 keyValue.setValue(keyValue.getValue() + 1);
368 370 }
369 371 } catch (Exception ignored) { // 处理异常继续循环
370   - // TODO @puhui999:需要打印异常日志
  372 + log.error("[拼团过期 or 虚拟成团][record({}) 处理异常,请进行处理!record 数据是:{}]",
  373 + record.getId(), JsonUtils.toJsonString(record));
371 374 }
372 375 }
373 376 return keyValue;
... ... @@ -376,68 +379,52 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
376 379 /**
377 380 * 处理过期拼团
378 381 *
379   - * @param headExpireRecord 过期拼团团长记录列表
  382 + * @param headRecord 过期拼团团长记录
380 383 */
381 384 @Transactional(rollbackFor = Exception.class)
382   - public void handleExpireRecord(CombinationRecordDO headExpireRecord) {
383   - // TODO @puhui999:这里的 null 其实不用判断。真出现,应该要处个 npe,因为就是要错哈;
384   - // TODO @puhui999:headExpireRecord 可以简化成 headRecord
385   - if (headExpireRecord == null) {
386   - return;
387   - }
388   -
  385 + public void handleExpireRecord(CombinationRecordDO headRecord) {
389 386 // 1.更新拼团记录
390   - List<CombinationRecordDO> headsAndRecords = updateBatchCombinationRecords(headExpireRecord,
  387 + List<CombinationRecordDO> headAndRecords = updateBatchCombinationRecords(headRecord,
391 388 CombinationRecordStatusEnum.FAILED);
392   - // TODO @puhui999:这里的 null 其实不用判断。真出现,应该要处个 npe,因为就是要错哈;
393   - if (headsAndRecords == null) {
394   - return;
395   - }
396   -
397 389 // 2.订单取消
398   - headsAndRecords.forEach(item -> tradeOrderApi.cancelPaidOrder(item.getUserId(), item.getOrderId()));
  390 + headAndRecords.forEach(item -> tradeOrderApi.cancelPaidOrder(item.getUserId(), item.getOrderId()));
399 391 }
400 392  
401 393 /**
402 394 * 处理虚拟拼团
403 395 *
404   - * @param virtualGroupHeadRecord 虚拟成团团长记录列表
  396 + * @param headRecord 虚拟成团团长记录
405 397 */
406 398 @Transactional(rollbackFor = Exception.class)
407   - public void handleVirtualGroupRecord(CombinationRecordDO virtualGroupHeadRecord) {
408   - // TODO @puhui999:这里的 null 其实不用判断。真出现,应该要处个 npe,因为就是要错哈;
409   - // TODO @puhui999:headExpireRecord 可以简化成 headRecord
410   - if (virtualGroupHeadRecord == null) {
411   - return;
412   - }
413   -
  399 + public void handleVirtualGroupRecord(CombinationRecordDO headRecord) {
414 400 // 1. 团员补齐
415   - combinationRecordMapper.insertBatch(CombinationActivityConvert.INSTANCE.convertVirtualGroupList(virtualGroupHeadRecord));
  401 + combinationRecordMapper.insertBatch(CombinationActivityConvert.INSTANCE.convertVirtualRecordList(headRecord));
416 402 // 2. 更新拼团记录
417   - updateBatchCombinationRecords(virtualGroupHeadRecord, CombinationRecordStatusEnum.SUCCESS);
  403 + updateBatchCombinationRecords(headRecord, CombinationRecordStatusEnum.SUCCESS);
418 404 }
419 405  
420   - // TODO @puhui999:写下方法注释;
  406 + /**
  407 + * 更新拼团记录
  408 + *
  409 + * @param headRecord 团长记录
  410 + * @param status 状态-拼团失败 FAILED 成功 SUCCESS
  411 + * @return 整团记录(包含团长和团成员)
  412 + */
421 413 private List<CombinationRecordDO> updateBatchCombinationRecords(CombinationRecordDO headRecord, CombinationRecordStatusEnum status) {
422 414 // 1. 查询团成员(包含团长)
423 415 List<CombinationRecordDO> records = combinationRecordMapper.selectListByHeadId(headRecord.getId());
424   - // TODO @puhui999:是不是不用判断空哈;例如说,就一个团长,然后过期。
425   - if (CollUtil.isEmpty(records)) {
426   - return null;
427   - }
428 416 records.add(headRecord);// 把团长加进去
429 417  
430 418 // 2. 批量更新拼团记录 status 和 endTime
431 419 List<CombinationRecordDO> updateRecords = new ArrayList<>(records.size());
432 420 LocalDateTime now = LocalDateTime.now();
433 421 records.forEach(item -> {
434   - // TODO @puhui999:record 改成 updateRecord
435   - CombinationRecordDO record = new CombinationRecordDO().setId(item.getId())
  422 + CombinationRecordDO updateRecord = new CombinationRecordDO().setId(item.getId())
436 423 .setStatus(status.getStatus()).setEndTime(now);
437 424 if (CombinationRecordStatusEnum.isSuccess(status.getStatus())) { // 虚拟成团完事更改状态成功后还需要把参与人数修改为成团需要人数
438   - record.setUserCount(record.getUserSize());
  425 + updateRecord.setUserCount(updateRecord.getUserSize());
439 426 }
440   - updateRecords.add(record);
  427 + updateRecords.add(updateRecord);
441 428 });
442 429 combinationRecordMapper.updateBatch(updateRecords);
443 430 return records;
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java
... ... @@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityD
10 10 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO;
11 11  
12 12 import javax.validation.Valid;
  13 +import java.time.LocalDateTime;
13 14 import java.util.Collection;
14 15 import java.util.List;
15 16  
... ... @@ -131,10 +132,11 @@ public interface SeckillActivityService {
131 132 /**
132 133 * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录
133 134 *
134   - * @param spuIds spu 编号
135   - * @param status 状态
  135 + * @param spuIds spu 编号
  136 + * @param status 状态
  137 + * @param dateTime 日期时间
136 138 * @return 秒杀活动列表
137 139 */
138   - List<SeckillActivityDO> getSeckillActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status);
  140 + List<SeckillActivityDO> getSeckillActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime);
139 141  
140 142 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java
... ... @@ -28,6 +28,7 @@ import org.springframework.transaction.annotation.Transactional;
28 28 import org.springframework.validation.annotation.Validated;
29 29  
30 30 import javax.annotation.Resource;
  31 +import java.time.LocalDateTime;
31 32 import java.util.Collection;
32 33 import java.util.Collections;
33 34 import java.util.List;
... ... @@ -324,14 +325,15 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
324 325 }
325 326  
326 327 @Override
327   - public List<SeckillActivityDO> getSeckillActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) {
  328 + public List<SeckillActivityDO> getSeckillActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime) {
328 329 // 1.查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号
329 330 List<Map<String, Object>> spuIdAndActivityIdMaps = seckillActivityMapper.selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(spuIds, status);
330 331 if (CollUtil.isEmpty(spuIdAndActivityIdMaps)) {
331 332 return Collections.emptyList();
332 333 }
333 334 // 2.查询活动详情
334   - return seckillActivityMapper.selectListByIds(convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId")));
  335 + return seckillActivityMapper.selectListByIdsAndDateTimeLt(
  336 + convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId")), dateTime);
335 337 }
336 338  
337 339 }
... ...