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

This commit is contained in:
YunaiV 2023-10-19 23:31:45 +08:00
commit 64b842ed94
22 changed files with 168 additions and 92 deletions

View File

@ -34,10 +34,6 @@ public class ArticleBaseVO {
@Schema(description = "文章简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "这是一个简介") @Schema(description = "文章简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "这是一个简介")
private String introduction; private String introduction;
// TODO @puhui999浏览量的字段应该不是后端新增设置的哈
@Schema(description = "浏览次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "111")
private String browseCount;
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "排序不能为空") @NotNull(message = "排序不能为空")
private Integer sort; private Integer sort;

View File

@ -16,6 +16,9 @@ public class ArticleRespVO extends ArticleBaseVO {
@Schema(description = "文章编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8606") @Schema(description = "文章编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8606")
private Long id; private Long id;
@Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "99999")
private Integer browseCount;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime; private LocalDateTime createTime;

View File

@ -22,6 +22,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*; import java.util.*;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -63,10 +64,11 @@ public class AppActivityController {
if (CollUtil.isEmpty(spuIds)) { if (CollUtil.isEmpty(spuIds)) {
return new ArrayList<>(); return new ArrayList<>();
} }
LocalDateTime now = LocalDateTime.now();
List<AppActivityRespVO> activityList = new ArrayList<>(); List<AppActivityRespVO> activityList = new ArrayList<>();
// 拼团活动 // 拼团活动-获取开启的且开始的且没有结束的活动
List<CombinationActivityDO> combinationActivities = combinationActivityService.getCombinationActivityBySpuIdsAndStatus( List<CombinationActivityDO> combinationActivities = combinationActivityService.getCombinationActivityBySpuIdsAndStatusAndDateTimeLt(
spuIds, CommonStatusEnum.ENABLE.getStatus()); spuIds, CommonStatusEnum.ENABLE.getStatus(), now);
if (CollUtil.isNotEmpty(combinationActivities)) { if (CollUtil.isNotEmpty(combinationActivities)) {
combinationActivities.forEach(item -> { combinationActivities.forEach(item -> {
activityList.add(new AppActivityRespVO().setId(item.getId()) activityList.add(new AppActivityRespVO().setId(item.getId())
@ -74,9 +76,9 @@ public class AppActivityController {
.setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime()));
}); });
} }
// 秒杀活动 // 秒杀活动-获取开启的且开始的且没有结束的活动
List<SeckillActivityDO> seckillActivities = seckillActivityService.getSeckillActivityBySpuIdsAndStatus( List<SeckillActivityDO> seckillActivities = seckillActivityService.getSeckillActivityBySpuIdsAndStatusAndDateTimeLt(
spuIds, CommonStatusEnum.ENABLE.getStatus()); spuIds, CommonStatusEnum.ENABLE.getStatus(), now);
if (CollUtil.isNotEmpty(seckillActivities)) { if (CollUtil.isNotEmpty(seckillActivities)) {
seckillActivities.forEach(item -> { seckillActivities.forEach(item -> {
activityList.add(new AppActivityRespVO().setId(item.getId()) activityList.add(new AppActivityRespVO().setId(item.getId())
@ -84,9 +86,9 @@ public class AppActivityController {
.setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime()));
}); });
} }
// 砍价活动 // 砍价活动-获取开启的且开始的且没有结束的活动
List<BargainActivityDO> bargainActivities = bargainActivityService.getBargainActivityBySpuIdsAndStatus( List<BargainActivityDO> bargainActivities = bargainActivityService.getBargainActivityBySpuIdsAndStatusAndDateTimeLt(
spuIds, CommonStatusEnum.ENABLE.getStatus()); spuIds, CommonStatusEnum.ENABLE.getStatus(), now);
if (CollUtil.isNotEmpty(bargainActivities)) { if (CollUtil.isNotEmpty(bargainActivities)) {
bargainActivities.forEach(item -> { bargainActivities.forEach(item -> {
activityList.add(new AppActivityRespVO().setId(item.getId()) activityList.add(new AppActivityRespVO().setId(item.getId())

View File

@ -13,6 +13,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List; import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -31,7 +32,7 @@ public class AppArticleCategoryController {
public CommonResult<List<AppArticleCategoryRespVO>> getArticleCategoryList() { public CommonResult<List<AppArticleCategoryRespVO>> getArticleCategoryList() {
List<ArticleCategoryDO> categoryList = articleCategoryService.getArticleCategoryListByStatus( List<ArticleCategoryDO> categoryList = articleCategoryService.getArticleCategoryListByStatus(
CommonStatusEnum.ENABLE.getStatus()); CommonStatusEnum.ENABLE.getStatus());
// TODO @puhui999排序下 categoryList.sort(Comparator.comparing(ArticleCategoryDO::getSort).reversed()); // sort 降序排列
return success(ArticleCategoryConvert.INSTANCE.convertList04(categoryList)); return success(ArticleCategoryConvert.INSTANCE.convertList04(categoryList));
} }

View File

@ -11,6 +11,7 @@ import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@ -55,5 +56,12 @@ public class AppArticleController {
return success(ArticleConvert.INSTANCE.convert01(articleService.getArticle(id))); return success(ArticleConvert.INSTANCE.convert01(articleService.getArticle(id)));
} }
// TODO @puhui999增加浏览量实现一个接口先简单做用户规模不大 +1 即可psuniapp 那边也要接下噢 @PutMapping("/add-browseCount")
@Operation(summary = "增加文章浏览量")
@Parameter(name = "id", description = "文章编号", example = "1024")
public CommonResult<Boolean> addBrowseCount(@RequestParam("id") Long id) {
articleService.addBrowseCount(id);
return success(true);
}
} }

View File

@ -204,25 +204,22 @@ public interface CombinationActivityConvert {
return respVO; return respVO;
} }
@Mapping(target = "id", ignore = true)
CombinationRecordDO convert5(CombinationRecordDO headRecord);
/** /**
* 转换生成虚拟成团虚拟记录 * 转换生成虚拟成团虚拟记录
* *
* @param virtualGroupHeadRecord 虚拟成团团长记录 * @param headRecord 虚拟成团团长记录
* @return 虚拟记录列表 * @return 虚拟记录列表
*/ */
// TODO @puhui9991方法名建议改成 convertVirtualRecordList(CombinationRecordDO headRecord)2 220 225 可以搞成 mapstruct 一个方法默认都 copy 进去然后 set 226 232 的字段 default List<CombinationRecordDO> convertVirtualRecordList(CombinationRecordDO headRecord) {
default List<CombinationRecordDO> convertVirtualGroupList(CombinationRecordDO virtualGroupHeadRecord) {
List<CombinationRecordDO> createRecords = new ArrayList<>(); List<CombinationRecordDO> createRecords = new ArrayList<>();
// 计算需要创建的虚拟成团记录数量 // 计算需要创建的虚拟成团记录数量
int count = virtualGroupHeadRecord.getUserSize() - virtualGroupHeadRecord.getUserCount(); int count = headRecord.getUserSize() - headRecord.getUserCount();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
// 基础信息和团长保持一致 // 基础信息和团长保持一致
CombinationRecordDO newRecord = new CombinationRecordDO().setActivityId(virtualGroupHeadRecord.getActivityId()) CombinationRecordDO newRecord = convert5(headRecord);
.setCombinationPrice(virtualGroupHeadRecord.getCombinationPrice()).setSpuId(virtualGroupHeadRecord.getSpuId()).setSpuName(virtualGroupHeadRecord.getSpuName())
.setPicUrl(virtualGroupHeadRecord.getPicUrl()).setSkuId(virtualGroupHeadRecord.getSkuId()).setHeadId(virtualGroupHeadRecord.getId())
.setStatus(virtualGroupHeadRecord.getStatus()) // 状态保持和创建时一致创建完成后会接着处理
.setVirtualGroup(virtualGroupHeadRecord.getVirtualGroup()).setExpireTime(virtualGroupHeadRecord.getExpireTime())
.setStartTime(virtualGroupHeadRecord.getStartTime()).setUserSize(virtualGroupHeadRecord.getUserSize()).setUserCount(virtualGroupHeadRecord.getUserCount());
// 虚拟信息 // 虚拟信息
newRecord.setCount(0); newRecord.setCount(0);
newRecord.setUserId(0L); newRecord.setUserId(0L);

View File

@ -54,7 +54,7 @@ public class ArticleDO extends BaseDO {
/** /**
* 浏览次数 * 浏览次数
*/ */
private String browseCount; private Integer browseCount;
/** /**
* 排序 * 排序
*/ */

View File

@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.category.Ar
import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleCategoryDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleCategoryDO;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/** /**
* 文章分类 Mapper * 文章分类 Mapper
* *
@ -23,4 +25,8 @@ public interface ArticleCategoryMapper extends BaseMapperX<ArticleCategoryDO> {
.orderByDesc(ArticleCategoryDO::getSort)); .orderByDesc(ArticleCategoryDO::getSort));
} }
default List<ArticleCategoryDO> selectListByStatus(Integer status) {
return selectList(ArticleCategoryDO::getStatus, status);
}
} }

View File

@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticlePageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticlePageReqVO;
import cn.iocoder.yudao.module.promotion.controller.app.article.vo.article.AppArticlePageReqVO; import cn.iocoder.yudao.module.promotion.controller.app.article.vo.article.AppArticlePageReqVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import java.util.List; import java.util.List;
@ -42,5 +43,10 @@ public interface ArticleMapper extends BaseMapperX<ArticleDO> {
.eqIfPresent(ArticleDO::getCategoryId, pageReqVO.getCategoryId())); .eqIfPresent(ArticleDO::getCategoryId, pageReqVO.getCategoryId()));
} }
default void updateBrowseCount(Long id) {
update(null, new LambdaUpdateWrapper<ArticleDO>()
.eq(ArticleDO::getId, id)
.setSql("browse_count = browse_count + 1"));
}
} }

View File

@ -102,9 +102,19 @@ public interface BargainActivityMapper extends BaseMapperX<BargainActivityDO> {
.groupBy("spu_id")); .groupBy("spu_id"));
} }
default List<BargainActivityDO> selectListByIds(Collection<Long> ids) { /**
* 获取指定活动编号的活动列表且
* 开始时间和结束时间小于给定时间 dateTime 的活动列表
*
* @param ids 活动编号
* @param dateTime 指定日期
* @return 活动列表
*/
default List<BargainActivityDO> selectListByIdsAndDateTimeLt(Collection<Long> ids, LocalDateTime dateTime) {
return selectList(new LambdaQueryWrapperX<BargainActivityDO>() return selectList(new LambdaQueryWrapperX<BargainActivityDO>()
.in(BargainActivityDO::getId, ids) .in(BargainActivityDO::getId, ids)
.lt(BargainActivityDO::getStartTime, dateTime)
.lt(BargainActivityDO::getEndTime, dateTime)
.orderByDesc(BargainActivityDO::getCreateTime)); .orderByDesc(BargainActivityDO::getCreateTime));
} }

View File

@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.time.LocalDateTime;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -58,9 +59,19 @@ public interface CombinationActivityMapper extends BaseMapperX<CombinationActivi
.groupBy("spu_id")); .groupBy("spu_id"));
} }
default List<CombinationActivityDO> selectListByIds(Collection<Long> ids) { /**
* 获取指定活动编号的活动列表且
* 开始时间和结束时间小于给定时间 dateTime 的活动列表
*
* @param ids 活动编号
* @param dateTime 指定日期
* @return 活动列表
*/
default List<CombinationActivityDO> selectListByIdsAndDateTimeLt(Collection<Long> ids, LocalDateTime dateTime) {
return selectList(new LambdaQueryWrapperX<CombinationActivityDO>() return selectList(new LambdaQueryWrapperX<CombinationActivityDO>()
.in(CombinationActivityDO::getId, ids) .in(CombinationActivityDO::getId, ids)
.lt(CombinationActivityDO::getStartTime, dateTime)
.lt(CombinationActivityDO::getEndTime, dateTime)
.orderByDesc(CombinationActivityDO::getCreateTime)); .orderByDesc(CombinationActivityDO::getCreateTime));
} }

View File

@ -13,6 +13,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.time.LocalDateTime;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -90,9 +91,19 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> {
.groupBy("spu_id")); .groupBy("spu_id"));
} }
default List<SeckillActivityDO> selectListByIds(Collection<Long> ids) { /**
* 获取指定活动编号的活动列表且
* 开始时间和结束时间小于给定时间 dateTime 的活动列表
*
* @param ids 活动编号
* @param dateTime 指定日期
* @return 活动列表
*/
default List<SeckillActivityDO> selectListByIdsAndDateTimeLt(Collection<Long> ids, LocalDateTime dateTime) {
return selectList(new LambdaQueryWrapperX<SeckillActivityDO>() return selectList(new LambdaQueryWrapperX<SeckillActivityDO>()
.in(SeckillActivityDO::getId, ids) .in(SeckillActivityDO::getId, ids)
.lt(SeckillActivityDO::getStartTime, dateTime)
.lt(SeckillActivityDO::getEndTime, dateTime)
.orderByDesc(SeckillActivityDO::getCreateTime)); .orderByDesc(SeckillActivityDO::getCreateTime));
} }

View File

@ -1,13 +1,11 @@
package cn.iocoder.yudao.module.promotion.service.article; package cn.iocoder.yudao.module.promotion.service.article;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.category.ArticleCategoryCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.category.ArticleCategoryCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.category.ArticleCategoryPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.category.ArticleCategoryPageReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.category.ArticleCategoryUpdateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.category.ArticleCategoryUpdateReqVO;
import cn.iocoder.yudao.module.promotion.convert.article.ArticleCategoryConvert; import cn.iocoder.yudao.module.promotion.convert.article.ArticleCategoryConvert;
import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleCategoryDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleCategoryDO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO;
import cn.iocoder.yudao.module.promotion.dal.mysql.article.ArticleCategoryMapper; import cn.iocoder.yudao.module.promotion.dal.mysql.article.ArticleCategoryMapper;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -59,9 +57,8 @@ public class ArticleCategoryServiceImpl implements ArticleCategoryService {
// 校验存在 // 校验存在
validateArticleCategoryExists(id); validateArticleCategoryExists(id);
// 校验是不是存在关联文章 // 校验是不是存在关联文章
// TODO @puhui999最好获得数量哈 Long count = articleService.getArticleCountByCategoryId(id);
List<ArticleDO> articleList = articleService.getArticleByCategoryId(id); if (count > 0) {
if (CollUtil.isNotEmpty(articleList)) {
throw exception(ARTICLE_CATEGORY_DELETE_FAIL_HAVE_ARTICLES); throw exception(ARTICLE_CATEGORY_DELETE_FAIL_HAVE_ARTICLES);
} }
@ -87,8 +84,7 @@ public class ArticleCategoryServiceImpl implements ArticleCategoryService {
@Override @Override
public List<ArticleCategoryDO> getArticleCategoryListByStatus(Integer status) { public List<ArticleCategoryDO> getArticleCategoryListByStatus(Integer status) {
// TODO @puhui999selectListByStatus return articleCategoryMapper.selectListByStatus(status);
return articleCategoryMapper.selectList(ArticleCategoryDO::getStatus, status);
} }
} }

View File

@ -80,4 +80,19 @@ public interface ArticleService {
*/ */
List<ArticleDO> getArticleByCategoryId(Long categoryId); List<ArticleDO> getArticleByCategoryId(Long categoryId);
/**
* 获得指定分类的文章数量
*
* @param categoryId 文章分类编号
* @return 文章数量
*/
Long getArticleCountByCategoryId(Long categoryId);
/**
* 增加文章浏览量
*
* @param id 文章编号
*/
void addBrowseCount(Long id);
} }

View File

@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleCategoryD
import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO;
import cn.iocoder.yudao.module.promotion.dal.mysql.article.ArticleMapper; import cn.iocoder.yudao.module.promotion.dal.mysql.article.ArticleMapper;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -41,6 +42,7 @@ public class ArticleServiceImpl implements ArticleService {
// 插入 // 插入
ArticleDO article = ArticleConvert.INSTANCE.convert(createReqVO); ArticleDO article = ArticleConvert.INSTANCE.convert(createReqVO);
article.setBrowseCount(0); // 初始浏览量
articleMapper.insert(article); articleMapper.insert(article);
// 返回 // 返回
return article.getId(); return article.getId();
@ -104,4 +106,19 @@ public class ArticleServiceImpl implements ArticleService {
return articleMapper.selectList(ArticleDO::getCategoryId, categoryId); return articleMapper.selectList(ArticleDO::getCategoryId, categoryId);
} }
@Override
public Long getArticleCountByCategoryId(Long categoryId) {
return articleMapper.selectCount(ArticleDO::getCategoryId, categoryId);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void addBrowseCount(Long id) {
// 校验文章是否存在
validateArticleExists(id);
// 增加浏览次数 TODO 先简单做用户规模不大 +1
articleMapper.updateBrowseCount(id);
}
} }

View File

@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.activity.Ba
import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO;
import javax.validation.Valid; import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -104,8 +105,9 @@ public interface BargainActivityService {
* *
* @param spuIds spu 编号 * @param spuIds spu 编号
* @param status 状态 * @param status 状态
* @param dateTime 日期时间
* @return 砍价活动列表 * @return 砍价活动列表
*/ */
List<BargainActivityDO> getBargainActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status); List<BargainActivityDO> getBargainActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime);
} }

View File

@ -182,15 +182,15 @@ public class BargainActivityServiceImpl implements BargainActivityService {
} }
@Override @Override
public List<BargainActivityDO> getBargainActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) { public List<BargainActivityDO> getBargainActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime) {
// 1. 查询出指定 spuId spu 参加的活动最接近现在的一条记录多个的话一个 spuId 对应一个最近的活动编号 // 1. 查询出指定 spuId spu 参加的活动最接近现在的一条记录多个的话一个 spuId 对应一个最近的活动编号
// TODO @puhui999我想了下这种是不是只展示当前正在进行中的已经结束或者未开始的可能没啥意义
List<Map<String, Object>> spuIdAndActivityIdMaps = bargainActivityMapper.selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(spuIds, status); List<Map<String, Object>> spuIdAndActivityIdMaps = bargainActivityMapper.selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(spuIds, status);
if (CollUtil.isEmpty(spuIdAndActivityIdMaps)) { if (CollUtil.isEmpty(spuIdAndActivityIdMaps)) {
return Collections.emptyList(); return Collections.emptyList();
} }
// 2. 查询活动详情 // 2. 查询活动详情
return bargainActivityMapper.selectListByIds(convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId"))); return bargainActivityMapper.selectListByIdsAndDateTimeLt(
convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId")), dateTime);
} }
} }

View File

@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationA
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
import javax.validation.Valid; import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -122,8 +123,9 @@ public interface CombinationActivityService {
* *
* @param spuIds spu 编号 * @param spuIds spu 编号
* @param status 状态 * @param status 状态
* @param dateTime 日期时间
* @return 拼团活动列表 * @return 拼团活动列表
*/ */
List<CombinationActivityDO> getCombinationActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status); List<CombinationActivityDO> getCombinationActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime);
} }

View File

@ -25,6 +25,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -228,14 +229,15 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
} }
@Override @Override
public List<CombinationActivityDO> getCombinationActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) { public List<CombinationActivityDO> getCombinationActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime) {
// 1.查询出指定 spuId spu 参加的活动最接近现在的一条记录多个的话一个 spuId 对应一个最近的活动编号 // 1.查询出指定 spuId spu 参加的活动最接近现在的一条记录多个的话一个 spuId 对应一个最近的活动编号
List<Map<String, Object>> spuIdAndActivityIdMaps = combinationActivityMapper.selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(spuIds, status); List<Map<String, Object>> spuIdAndActivityIdMaps = combinationActivityMapper.selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(spuIds, status);
if (CollUtil.isEmpty(spuIdAndActivityIdMaps)) { if (CollUtil.isEmpty(spuIdAndActivityIdMaps)) {
return Collections.emptyList(); return Collections.emptyList();
} }
// 2.查询活动详情 // 2.查询活动详情
return combinationActivityMapper.selectListByIds(convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId"))); return combinationActivityMapper.selectListByIdsAndDateTimeLt(
convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId")), dateTime);
} }
} }

View File

@ -6,6 +6,7 @@ import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi; import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
@ -22,6 +23,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationR
import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper; import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper;
import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi; import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -45,6 +47,7 @@ import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
* @author HUIHUI * @author HUIHUI
*/ */
@Service @Service
@Slf4j
@Validated @Validated
public class CombinationRecordServiceImpl implements CombinationRecordService { public class CombinationRecordServiceImpl implements CombinationRecordService {
@ -353,21 +356,21 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
// 3. 逐个处理拼团过期 or 虚拟成团 // 3. 逐个处理拼团过期 or 虚拟成团
KeyValue<Integer, Integer> keyValue = new KeyValue<>(0, 0); // 统计过期拼团和虚拟成团 KeyValue<Integer, Integer> keyValue = new KeyValue<>(0, 0); // 统计过期拼团和虚拟成团
for (CombinationRecordDO recordDO : headExpireRecords) { for (CombinationRecordDO record : headExpireRecords) {
// TODO @puhui999recordDO 非必要的情况下不用带 DO直接 record;
try { try {
CombinationActivityDO activity = activityMap.get(recordDO.getActivityId()); CombinationActivityDO activity = activityMap.get(record.getActivityId());
if (activity == null || !activity.getVirtualGroup()) { // 取不到活动的或者不是虚拟拼团的 if (activity == null || !activity.getVirtualGroup()) { // 取不到活动的或者不是虚拟拼团的
// 3.1. 处理过期的拼团 // 3.1. 处理过期的拼团
getSelf().handleExpireRecord(recordDO); getSelf().handleExpireRecord(record);
keyValue.setKey(keyValue.getKey() + 1); keyValue.setKey(keyValue.getKey() + 1);
} else { } else {
// 3.2. 处理虚拟成团 // 3.2. 处理虚拟成团
getSelf().handleVirtualGroupRecord(recordDO); getSelf().handleVirtualGroupRecord(record);
keyValue.setValue(keyValue.getValue() + 1); keyValue.setValue(keyValue.getValue() + 1);
} }
} catch (Exception ignored) { // 处理异常继续循环 } catch (Exception ignored) { // 处理异常继续循环
// TODO @puhui999需要打印异常日志 log.error("[拼团过期 or 虚拟成团][record({}) 处理异常请进行处理record 数据是:{}]",
record.getId(), JsonUtils.toJsonString(record));
} }
} }
return keyValue; return keyValue;
@ -376,68 +379,52 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
/** /**
* 处理过期拼团 * 处理过期拼团
* *
* @param headExpireRecord 过期拼团团长记录列表 * @param headRecord 过期拼团团长记录
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void handleExpireRecord(CombinationRecordDO headExpireRecord) { public void handleExpireRecord(CombinationRecordDO headRecord) {
// TODO @puhui999这里的 null 其实不用判断真出现应该要处个 npe因为就是要错哈
// TODO @puhui999headExpireRecord 可以简化成 headRecord
if (headExpireRecord == null) {
return;
}
// 1.更新拼团记录 // 1.更新拼团记录
List<CombinationRecordDO> headsAndRecords = updateBatchCombinationRecords(headExpireRecord, List<CombinationRecordDO> headAndRecords = updateBatchCombinationRecords(headRecord,
CombinationRecordStatusEnum.FAILED); CombinationRecordStatusEnum.FAILED);
// TODO @puhui999这里的 null 其实不用判断真出现应该要处个 npe因为就是要错哈
if (headsAndRecords == null) {
return;
}
// 2.订单取消 // 2.订单取消
headsAndRecords.forEach(item -> tradeOrderApi.cancelPaidOrder(item.getUserId(), item.getOrderId())); headAndRecords.forEach(item -> tradeOrderApi.cancelPaidOrder(item.getUserId(), item.getOrderId()));
} }
/** /**
* 处理虚拟拼团 * 处理虚拟拼团
* *
* @param virtualGroupHeadRecord 虚拟成团团长记录列表 * @param headRecord 虚拟成团团长记录
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void handleVirtualGroupRecord(CombinationRecordDO virtualGroupHeadRecord) { public void handleVirtualGroupRecord(CombinationRecordDO headRecord) {
// TODO @puhui999这里的 null 其实不用判断真出现应该要处个 npe因为就是要错哈
// TODO @puhui999headExpireRecord 可以简化成 headRecord
if (virtualGroupHeadRecord == null) {
return;
}
// 1. 团员补齐 // 1. 团员补齐
combinationRecordMapper.insertBatch(CombinationActivityConvert.INSTANCE.convertVirtualGroupList(virtualGroupHeadRecord)); combinationRecordMapper.insertBatch(CombinationActivityConvert.INSTANCE.convertVirtualRecordList(headRecord));
// 2. 更新拼团记录 // 2. 更新拼团记录
updateBatchCombinationRecords(virtualGroupHeadRecord, CombinationRecordStatusEnum.SUCCESS); updateBatchCombinationRecords(headRecord, CombinationRecordStatusEnum.SUCCESS);
} }
// TODO @puhui999写下方法注释 /**
* 更新拼团记录
*
* @param headRecord 团长记录
* @param status 状态-拼团失败 FAILED 成功 SUCCESS
* @return 整团记录包含团长和团成员
*/
private List<CombinationRecordDO> updateBatchCombinationRecords(CombinationRecordDO headRecord, CombinationRecordStatusEnum status) { private List<CombinationRecordDO> updateBatchCombinationRecords(CombinationRecordDO headRecord, CombinationRecordStatusEnum status) {
// 1. 查询团成员包含团长 // 1. 查询团成员包含团长
List<CombinationRecordDO> records = combinationRecordMapper.selectListByHeadId(headRecord.getId()); List<CombinationRecordDO> records = combinationRecordMapper.selectListByHeadId(headRecord.getId());
// TODO @puhui999是不是不用判断空哈例如说就一个团长然后过期
if (CollUtil.isEmpty(records)) {
return null;
}
records.add(headRecord);// 把团长加进去 records.add(headRecord);// 把团长加进去
// 2. 批量更新拼团记录 status endTime // 2. 批量更新拼团记录 status endTime
List<CombinationRecordDO> updateRecords = new ArrayList<>(records.size()); List<CombinationRecordDO> updateRecords = new ArrayList<>(records.size());
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
records.forEach(item -> { records.forEach(item -> {
// TODO @puhui999record 改成 updateRecord CombinationRecordDO updateRecord = new CombinationRecordDO().setId(item.getId())
CombinationRecordDO record = new CombinationRecordDO().setId(item.getId())
.setStatus(status.getStatus()).setEndTime(now); .setStatus(status.getStatus()).setEndTime(now);
if (CombinationRecordStatusEnum.isSuccess(status.getStatus())) { // 虚拟成团完事更改状态成功后还需要把参与人数修改为成团需要人数 if (CombinationRecordStatusEnum.isSuccess(status.getStatus())) { // 虚拟成团完事更改状态成功后还需要把参与人数修改为成团需要人数
record.setUserCount(record.getUserSize()); updateRecord.setUserCount(updateRecord.getUserSize());
} }
updateRecords.add(record); updateRecords.add(updateRecord);
}); });
combinationRecordMapper.updateBatch(updateRecords); combinationRecordMapper.updateBatch(updateRecords);
return records; return records;

View File

@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityD
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO;
import javax.validation.Valid; import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -133,8 +134,9 @@ public interface SeckillActivityService {
* *
* @param spuIds spu 编号 * @param spuIds spu 编号
* @param status 状态 * @param status 状态
* @param dateTime 日期时间
* @return 秒杀活动列表 * @return 秒杀活动列表
*/ */
List<SeckillActivityDO> getSeckillActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status); List<SeckillActivityDO> getSeckillActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime);
} }

View File

@ -28,6 +28,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -324,14 +325,15 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
} }
@Override @Override
public List<SeckillActivityDO> getSeckillActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) { public List<SeckillActivityDO> getSeckillActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime) {
// 1.查询出指定 spuId spu 参加的活动最接近现在的一条记录多个的话一个 spuId 对应一个最近的活动编号 // 1.查询出指定 spuId spu 参加的活动最接近现在的一条记录多个的话一个 spuId 对应一个最近的活动编号
List<Map<String, Object>> spuIdAndActivityIdMaps = seckillActivityMapper.selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(spuIds, status); List<Map<String, Object>> spuIdAndActivityIdMaps = seckillActivityMapper.selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(spuIds, status);
if (CollUtil.isEmpty(spuIdAndActivityIdMaps)) { if (CollUtil.isEmpty(spuIdAndActivityIdMaps)) {
return Collections.emptyList(); return Collections.emptyList();
} }
// 2.查询活动详情 // 2.查询活动详情
return seckillActivityMapper.selectListByIds(convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId"))); return seckillActivityMapper.selectListByIdsAndDateTimeLt(
convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId")), dateTime);
} }
} }