营销活动:完善 review 提到的问题

This commit is contained in:
puhui999 2023-10-16 18:53:25 +08:00
parent 01ef5f7911
commit 4273b8f09c
14 changed files with 167 additions and 154 deletions

View File

@ -111,9 +111,10 @@ public interface ErrorCodeConstants {
ErrorCode BARGAIN_HELP_CREATE_FAIL_HELP_EXISTS = new ErrorCode(1_013_014_004, "助力失败,您已经助力过了"); ErrorCode BARGAIN_HELP_CREATE_FAIL_HELP_EXISTS = new ErrorCode(1_013_014_004, "助力失败,您已经助力过了");
// ========== 文章分类 1-013-015-000 ========== // ========== 文章分类 1-013-015-000 ==========
ErrorCode ARTICLE_CATEGORY_NOT_EXISTS = new ErrorCode(1_013_015_000, "分类不存在"); ErrorCode ARTICLE_CATEGORY_NOT_EXISTS = new ErrorCode(1_013_015_000, "文章分类不存在");
ErrorCode ARTICLE_CATEGORY_DELETE_FAIL_HAVE_ARTICLES = new ErrorCode(1_013_015_001, "文章分类删除失败,存在关联文章");
// ========== 文章管理 1-013-016-000 ========== // ========== 文章管理 1-013-016-000 ==========
ErrorCode ARTICLE_NOT_EXISTS = new ErrorCode(1_013_016_000, "文章管理不存在"); ErrorCode ARTICLE_NOT_EXISTS = new ErrorCode(1_013_016_000, "文章不存在");
} }

View File

@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticleCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticleCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticleRespVO; import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticleRespVO;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticleUpdateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticleUpdateReqVO;
import cn.iocoder.yudao.module.promotion.controller.app.article.vo.article.AppArticleRespVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
@ -30,4 +31,10 @@ public interface ArticleConvert {
PageResult<ArticleRespVO> convertPage(PageResult<ArticleDO> page); PageResult<ArticleRespVO> convertPage(PageResult<ArticleDO> page);
AppArticleRespVO convert01(ArticleDO article);
PageResult<AppArticleRespVO> convertPage02(PageResult<ArticleDO> articlePage);
List<AppArticleRespVO> convertList03(List<ArticleDO> articleCategoryListByRecommendHotAndRecommendBanner);
} }

View File

@ -207,31 +207,29 @@ public interface CombinationActivityConvert {
/** /**
* 转换生成虚拟成团虚拟记录 * 转换生成虚拟成团虚拟记录
* *
* @param virtualGroupHeadRecords 虚拟成团团长记录列表 * @param virtualGroupHeadRecord 虚拟成团团长记录
* @return 虚拟记录列表 * @return 虚拟记录列表
*/ */
default List<CombinationRecordDO> convertVirtualGroupList(List<CombinationRecordDO> virtualGroupHeadRecords) { default List<CombinationRecordDO> convertVirtualGroupList(CombinationRecordDO virtualGroupHeadRecord) {
List<CombinationRecordDO> createRecords = new ArrayList<>(); List<CombinationRecordDO> createRecords = new ArrayList<>();
virtualGroupHeadRecords.forEach(headRecord -> { // 计算需要创建的虚拟成团记录数量
// 计算需要创建的虚拟成团记录数量 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 = new CombinationRecordDO().setActivityId(headRecord.getActivityId()) .setCombinationPrice(virtualGroupHeadRecord.getCombinationPrice()).setSpuId(virtualGroupHeadRecord.getSpuId()).setSpuName(virtualGroupHeadRecord.getSpuName())
.setCombinationPrice(headRecord.getCombinationPrice()).setSpuId(headRecord.getSpuId()).setSpuName(headRecord.getSpuName()) .setPicUrl(virtualGroupHeadRecord.getPicUrl()).setSkuId(virtualGroupHeadRecord.getSkuId()).setHeadId(virtualGroupHeadRecord.getId())
.setPicUrl(headRecord.getPicUrl()).setSkuId(headRecord.getSkuId()).setHeadId(headRecord.getId()) .setStatus(virtualGroupHeadRecord.getStatus()) // 状态保持和创建时一致创建完成后会接着处理
.setStatus(headRecord.getStatus()) // 状态保持和创建时一致创建完成后会接着处理 .setVirtualGroup(virtualGroupHeadRecord.getVirtualGroup()).setExpireTime(virtualGroupHeadRecord.getExpireTime())
.setVirtualGroup(headRecord.getVirtualGroup()).setExpireTime(headRecord.getExpireTime()) .setStartTime(virtualGroupHeadRecord.getStartTime()).setUserSize(virtualGroupHeadRecord.getUserSize()).setUserCount(virtualGroupHeadRecord.getUserCount());
.setStartTime(headRecord.getStartTime()).setUserSize(headRecord.getUserSize()).setUserCount(headRecord.getUserCount()); // 虚拟信息
// 虚拟信息 newRecord.setCount(0);
newRecord.setCount(0); newRecord.setUserId(0L);
newRecord.setUserId(0L); newRecord.setNickname("");
newRecord.setNickname(""); newRecord.setAvatar("");
newRecord.setAvatar(""); newRecord.setOrderId(0L);
newRecord.setOrderId(0L); createRecords.add(newRecord);
createRecords.add(newRecord); }
}
});
return createRecords; return createRecords;
} }

View File

@ -4,9 +4,12 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 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.dal.dataobject.article.ArticleDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/** /**
* 文章管理 Mapper * 文章管理 Mapper
* *
@ -28,4 +31,16 @@ public interface ArticleMapper extends BaseMapperX<ArticleDO> {
.orderByDesc(ArticleDO::getId)); .orderByDesc(ArticleDO::getId));
} }
default List<ArticleDO> selectList(Boolean recommendHot, Boolean recommendBanner) {
return selectList(new LambdaQueryWrapperX<ArticleDO>()
.eqIfPresent(ArticleDO::getRecommendHot, recommendHot)
.eqIfPresent(ArticleDO::getRecommendBanner, recommendBanner));
}
default PageResult<ArticleDO> selectPage(AppArticlePageReqVO pageReqVO) {
return selectPage(pageReqVO, new LambdaQueryWrapperX<ArticleDO>()
.eqIfPresent(ArticleDO::getCategoryId, pageReqVO.getCategoryId()));
}
} }

View File

@ -127,11 +127,9 @@ public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO
* *
* @return 参加过拼团的用户数 * @return 参加过拼团的用户数
*/ */
// TODO @puhui9991方法名直接 selectUserCount2COUNT(DISTINCT(user_id)) 就可以啦不用 group by default Long selectUserCount() {
default Long selectUserDistinctCount() {
return selectCount(new QueryWrapper<CombinationRecordDO>() return selectCount(new QueryWrapper<CombinationRecordDO>()
.select("DISTINCT (user_id)") .select("DISTINCT (user_id)"));
.groupBy("user_id"));
} }
default List<CombinationRecordDO> selectListByHeadIdAndStatusAndExpireTimeLt(Long headId, Integer status, LocalDateTime dateTime) { default List<CombinationRecordDO> selectListByHeadIdAndStatusAndExpireTimeLt(Long headId, Integer status, LocalDateTime dateTime) {
@ -141,8 +139,8 @@ public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO
.lt(CombinationRecordDO::getExpireTime, dateTime)); .lt(CombinationRecordDO::getExpireTime, dateTime));
} }
default List<CombinationRecordDO> selectListByHeadIds(Collection<Long> headIds) { default List<CombinationRecordDO> selectListByHeadId(Long headId) {
return selectList(new LambdaQueryWrapperX<CombinationRecordDO>().in(CombinationRecordDO::getHeadId, headIds)); return selectList(new LambdaQueryWrapperX<CombinationRecordDO>().eq(CombinationRecordDO::getHeadId, headId));
} }
} }

View File

@ -1,11 +1,13 @@
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.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -14,6 +16,7 @@ import javax.annotation.Resource;
import java.util.List; import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.ARTICLE_CATEGORY_DELETE_FAIL_HAVE_ARTICLES;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.ARTICLE_CATEGORY_NOT_EXISTS; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.ARTICLE_CATEGORY_NOT_EXISTS;
/** /**
@ -27,6 +30,8 @@ public class ArticleCategoryServiceImpl implements ArticleCategoryService {
@Resource @Resource
private ArticleCategoryMapper articleCategoryMapper; private ArticleCategoryMapper articleCategoryMapper;
@Resource
private ArticleService articleService;
@Override @Override
public Long createArticleCategory(ArticleCategoryCreateReqVO createReqVO) { public Long createArticleCategory(ArticleCategoryCreateReqVO createReqVO) {
@ -50,7 +55,11 @@ public class ArticleCategoryServiceImpl implements ArticleCategoryService {
public void deleteArticleCategory(Long id) { public void deleteArticleCategory(Long id) {
// 校验存在 // 校验存在
validateArticleCategoryExists(id); validateArticleCategoryExists(id);
// TODO @puhui999需要校验下是不是存在文章 // 校验是不是存在关联文章
List<ArticleDO> articleList = articleService.getArticleByCategoryId(id);
if (CollUtil.isNotEmpty(articleList)) {
throw exception(ARTICLE_CATEGORY_DELETE_FAIL_HAVE_ARTICLES);
}
// 删除 // 删除
articleCategoryMapper.deleteById(id); articleCategoryMapper.deleteById(id);

View File

@ -4,19 +4,21 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticleCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticleCreateReqVO;
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.admin.article.vo.article.ArticleUpdateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticleUpdateReqVO;
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 javax.validation.Valid; import javax.validation.Valid;
import java.util.List;
/** /**
* 文章管理 Service 接口 * 文章详情 Service 接口
* *
* @author HUIHUI * @author HUIHUI
*/ */
public interface ArticleService { public interface ArticleService {
/** /**
* 创建文章管理 * 创建文章详情
* *
* @param createReqVO 创建信息 * @param createReqVO 创建信息
* @return 编号 * @return 编号
@ -24,33 +26,58 @@ public interface ArticleService {
Long createArticle(@Valid ArticleCreateReqVO createReqVO); Long createArticle(@Valid ArticleCreateReqVO createReqVO);
/** /**
* 更新文章管理 * 更新文章详情
* *
* @param updateReqVO 更新信息 * @param updateReqVO 更新信息
*/ */
void updateArticle(@Valid ArticleUpdateReqVO updateReqVO); void updateArticle(@Valid ArticleUpdateReqVO updateReqVO);
/** /**
* 删除文章管理 * 删除文章详情
* *
* @param id 编号 * @param id 编号
*/ */
void deleteArticle(Long id); void deleteArticle(Long id);
/** /**
* 获得文章管理 * 获得文章详情
* *
* @param id 编号 * @param id 编号
* @return 文章管理 * @return 文章详情
*/ */
ArticleDO getArticle(Long id); ArticleDO getArticle(Long id);
/** /**
* 获得文章管理分页 * 获得文章详情分页
* *
* @param pageReqVO 分页查询 * @param pageReqVO 分页查询
* @return 文章管理分页 * @return 文章详情分页
*/ */
PageResult<ArticleDO> getArticlePage(ArticlePageReqVO pageReqVO); PageResult<ArticleDO> getArticlePage(ArticlePageReqVO pageReqVO);
/**
* 获得文章详情列表
*
* @param recommendHot 是否热门
* @param recommendBanner 是否轮播图
* @return 文章详情列表
*/
List<ArticleDO> getArticleCategoryListByRecommendHotAndRecommendBanner(Boolean recommendHot, Boolean recommendBanner);
/**
* 获得文章详情分页
*
* @param pageReqVO 分页查询
* @return 文章详情分页
*/
PageResult<ArticleDO> getArticlePage(AppArticlePageReqVO pageReqVO);
/**
* 获得指定分类的文章列表
*
* @param categoryId 文章分类编号
* @return 文章列表
*/
List<ArticleDO> getArticleByCategoryId(Long categoryId);
} }

View File

@ -4,15 +4,19 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticleCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticleCreateReqVO;
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.admin.article.vo.article.ArticleUpdateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticleUpdateReqVO;
import cn.iocoder.yudao.module.promotion.controller.app.article.vo.article.AppArticlePageReqVO;
import cn.iocoder.yudao.module.promotion.convert.article.ArticleConvert; import cn.iocoder.yudao.module.promotion.convert.article.ArticleConvert;
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.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.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.ARTICLE_CATEGORY_NOT_EXISTS;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.ARTICLE_NOT_EXISTS; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.ARTICLE_NOT_EXISTS;
/** /**
@ -26,10 +30,14 @@ public class ArticleServiceImpl implements ArticleService {
@Resource @Resource
private ArticleMapper articleMapper; private ArticleMapper articleMapper;
@Resource
private ArticleCategoryService articleCategoryService;
@Override @Override
public Long createArticle(ArticleCreateReqVO createReqVO) { public Long createArticle(ArticleCreateReqVO createReqVO) {
// TODO @puhui999需要校验分类存在 // 校验分类存在
validateArticleCategoryExists(createReqVO.getCategoryId());
// 插入 // 插入
ArticleDO article = ArticleConvert.INSTANCE.convert(createReqVO); ArticleDO article = ArticleConvert.INSTANCE.convert(createReqVO);
articleMapper.insert(article); articleMapper.insert(article);
@ -41,7 +49,8 @@ public class ArticleServiceImpl implements ArticleService {
public void updateArticle(ArticleUpdateReqVO updateReqVO) { public void updateArticle(ArticleUpdateReqVO updateReqVO) {
// 校验存在 // 校验存在
validateArticleExists(updateReqVO.getId()); validateArticleExists(updateReqVO.getId());
// TODO @puhui999需要校验分类存在 // 校验分类存在
validateArticleCategoryExists(updateReqVO.getCategoryId());
// 更新 // 更新
ArticleDO updateObj = ArticleConvert.INSTANCE.convert(updateReqVO); ArticleDO updateObj = ArticleConvert.INSTANCE.convert(updateReqVO);
@ -62,6 +71,13 @@ public class ArticleServiceImpl implements ArticleService {
} }
} }
private void validateArticleCategoryExists(Long categoryId) {
ArticleCategoryDO articleCategory = articleCategoryService.getArticleCategory(categoryId);
if (articleCategory == null) {
throw exception(ARTICLE_CATEGORY_NOT_EXISTS);
}
}
@Override @Override
public ArticleDO getArticle(Long id) { public ArticleDO getArticle(Long id) {
return articleMapper.selectById(id); return articleMapper.selectById(id);
@ -72,4 +88,19 @@ public class ArticleServiceImpl implements ArticleService {
return articleMapper.selectPage(pageReqVO); return articleMapper.selectPage(pageReqVO);
} }
@Override
public List<ArticleDO> getArticleCategoryListByRecommendHotAndRecommendBanner(Boolean recommendHot, Boolean recommendBanner) {
return articleMapper.selectList(recommendHot, recommendBanner);
}
@Override
public PageResult<ArticleDO> getArticlePage(AppArticlePageReqVO pageReqVO) {
return articleMapper.selectPage(pageReqVO);
}
@Override
public List<ArticleDO> getArticleByCategoryId(Long categoryId) {
return articleMapper.selectList(ArticleDO::getCategoryId, categoryId);
}
} }

View File

@ -247,7 +247,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
@Override @Override
public Long getCombinationUserCount() { public Long getCombinationUserCount() {
return combinationRecordMapper.selectUserDistinctCount(); return combinationRecordMapper.selectUserCount();
} }
@Override @Override
@ -351,48 +351,46 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
convertSet(headExpireRecords, CombinationRecordDO::getActivityId)); convertSet(headExpireRecords, CombinationRecordDO::getActivityId));
Map<Long, CombinationActivityDO> activityMap = convertMap(activities, CombinationActivityDO::getId); Map<Long, CombinationActivityDO> activityMap = convertMap(activities, CombinationActivityDO::getId);
// TODO @puhui999这里可以改成每个团处理一次哈这样 handleExpireRecordhandleVirtualGroupRecord 都改成按团处理每个是一个小事务 // 3. 改成每个团处理一次哈这样 handleExpireRecordhandleVirtualGroupRecord 都改成按团处理每个是一个小事务
// 3. 校验是否虚拟成团 KeyValue<Integer, Integer> keyValue = new KeyValue<>(0, 0); // 统计过期拼团和虚拟成团
List<CombinationRecordDO> virtualGroupHeadRecords = new ArrayList<>(); // 虚拟成团 for (CombinationRecordDO recordDO : headExpireRecords) {
for (Iterator<CombinationRecordDO> iterator = headExpireRecords.iterator(); iterator.hasNext(); ) { try {
CombinationRecordDO record = iterator.next(); CombinationActivityDO activity = activityMap.get(recordDO.getActivityId());
// 3.1.不匹配则直接跳过 if (activity == null || !activity.getVirtualGroup()) { // 取不到活动的或者不是虚拟拼团的
CombinationActivityDO activity = activityMap.get(record.getActivityId()); // 3.1. 处理过期的拼团
if (activity == null || !activity.getVirtualGroup()) { // 取不到活动的或者不是虚拟拼团的 getSelf().handleExpireRecord(recordDO);
continue; keyValue.setKey(keyValue.getKey() + 1);
} else {
// 3.2. 处理虚拟成团
getSelf().handleVirtualGroupRecord(recordDO);
keyValue.setValue(keyValue.getValue() + 1);
}
} catch (Exception ignored) { // 处理异常继续循环
} }
// 3.2.匹配则移除添加到虚拟成团中并结束寻找
virtualGroupHeadRecords.add(record);
iterator.remove();
break;
} }
// 4.处理过期的拼团 return keyValue;
getSelf().handleExpireRecord(headExpireRecords);
// 5.虚拟成团
getSelf().handleVirtualGroupRecord(virtualGroupHeadRecords);
return new KeyValue<>(headExpireRecords.size(), virtualGroupHeadRecords.size());
} }
/** /**
* 处理过期拼团 * 处理过期拼团
* *
* @param headExpireRecords 过期拼团团长记录列表 * @param headExpireRecord 过期拼团团长记录列表
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void handleExpireRecord(List<CombinationRecordDO> headExpireRecords) { public void handleExpireRecord(CombinationRecordDO headExpireRecord) {
if (CollUtil.isEmpty(headExpireRecords)) { if (headExpireRecord == null) {
return; return;
} }
// 1.更新拼团记录 // 1.更新拼团记录
List<CombinationRecordDO> headsAndRecords = updateBatchCombinationRecords(headExpireRecords, List<CombinationRecordDO> headsAndRecords = updateBatchCombinationRecords(headExpireRecord,
CombinationRecordStatusEnum.FAILED); CombinationRecordStatusEnum.FAILED);
if (headsAndRecords == null) { if (headsAndRecords == null) {
return; return;
} }
// 2.订单取消 TODO 以现在的取消回滚逻辑好像只能循环了 // 2.订单取消
headsAndRecords.forEach(item -> { headsAndRecords.forEach(item -> {
tradeOrderApi.cancelPaidOrder(item.getUserId(), item.getOrderId()); tradeOrderApi.cancelPaidOrder(item.getUserId(), item.getOrderId());
}); });
@ -401,36 +399,32 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
/** /**
* 处理虚拟拼团 * 处理虚拟拼团
* *
* @param virtualGroupHeadRecords 虚拟成团团长记录列表 * @param virtualGroupHeadRecord 虚拟成团团长记录列表
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void handleVirtualGroupRecord(List<CombinationRecordDO> virtualGroupHeadRecords) { public void handleVirtualGroupRecord(CombinationRecordDO virtualGroupHeadRecord) {
if (CollUtil.isEmpty(virtualGroupHeadRecords)) { if (virtualGroupHeadRecord == null) {
return; return;
} }
// 1. 团员补齐 // 1. 团员补齐
combinationRecordMapper.insertBatch(CombinationActivityConvert.INSTANCE.convertVirtualGroupList(virtualGroupHeadRecords)); combinationRecordMapper.insertBatch(CombinationActivityConvert.INSTANCE.convertVirtualGroupList(virtualGroupHeadRecord));
// 2. 更新拼团记录 // 2. 更新拼团记录
updateBatchCombinationRecords(virtualGroupHeadRecords, CombinationRecordStatusEnum.SUCCESS); updateBatchCombinationRecords(virtualGroupHeadRecord, CombinationRecordStatusEnum.SUCCESS);
} }
private List<CombinationRecordDO> updateBatchCombinationRecords(List<CombinationRecordDO> headRecords, CombinationRecordStatusEnum status) { private List<CombinationRecordDO> updateBatchCombinationRecords(CombinationRecordDO headRecord, CombinationRecordStatusEnum status) {
// 1. 查询团成员 // 1. 查询团成员包含团长
List<CombinationRecordDO> records = combinationRecordMapper.selectListByHeadIds( List<CombinationRecordDO> records = combinationRecordMapper.selectListByHeadId(headRecord.getId());
convertSet(headRecords, CombinationRecordDO::getId));
if (CollUtil.isEmpty(records)) { if (CollUtil.isEmpty(records)) {
return null; return null;
} }
Map<Long, List<CombinationRecordDO>> recordsMap = convertMultiMap(records, CombinationRecordDO::getHeadId); records.add(headRecord);// 把团长加进去
headRecords.forEach(item -> {
recordsMap.get(item.getId()).add(item); // 把团长加进团里
});
// 2.批量更新拼团记录 status 失败/成团时间 // 2.批量更新拼团记录 status 失败/成团时间
List<CombinationRecordDO> headsAndRecords = mergeValuesFromMap(recordsMap); List<CombinationRecordDO> updateRecords = new ArrayList<>(records.size());
List<CombinationRecordDO> updateRecords = new ArrayList<>(headsAndRecords.size());
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
headsAndRecords.forEach(item -> { records.forEach(item -> {
CombinationRecordDO record = 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())) { // 虚拟成团完事更改状态成功后还需要把参与人数修改为成团需要人数
@ -439,7 +433,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
updateRecords.add(record); updateRecords.add(record);
}); });
combinationRecordMapper.updateBatch(updateRecords); combinationRecordMapper.updateBatch(updateRecords);
return headsAndRecords; return records;
} }
/** /**

View File

@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.promotion.service.article;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticleCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticleCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.ArticleExportReqVO;
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.admin.article.vo.article.ArticleUpdateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticleUpdateReqVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO;
@ -13,7 +12,6 @@ import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
@ -166,68 +164,4 @@ public class ArticleServiceImplTest extends BaseDbUnitTest {
assertPojoEquals(dbArticle, pageResult.getList().get(0)); assertPojoEquals(dbArticle, pageResult.getList().get(0));
} }
@Test
@Disabled // TODO 请修改 null 为需要的值然后删除 @Disabled 注解
public void testGetArticleList() {
// mock 数据
ArticleDO dbArticle = randomPojo(ArticleDO.class, o -> { // 等会查询到
o.setCategoryId(null);
o.setTitle(null);
o.setAuthor(null);
o.setPicUrl(null);
o.setIntroduction(null);
o.setBrowseCount(null);
o.setSort(null);
o.setStatus(null);
o.setSpuId(null);
o.setRecommendHot(null);
o.setRecommendBanner(null);
o.setContent(null);
o.setCreateTime(null);
});
articleMapper.insert(dbArticle);
// 测试 categoryId 不匹配
articleMapper.insert(cloneIgnoreId(dbArticle, o -> o.setCategoryId(null)));
// 测试 title 不匹配
articleMapper.insert(cloneIgnoreId(dbArticle, o -> o.setTitle(null)));
// 测试 author 不匹配
articleMapper.insert(cloneIgnoreId(dbArticle, o -> o.setAuthor(null)));
// 测试 picUrl 不匹配
articleMapper.insert(cloneIgnoreId(dbArticle, o -> o.setPicUrl(null)));
// 测试 introduction 不匹配
articleMapper.insert(cloneIgnoreId(dbArticle, o -> o.setIntroduction(null)));
// 测试 browseCount 不匹配
articleMapper.insert(cloneIgnoreId(dbArticle, o -> o.setBrowseCount(null)));
// 测试 sort 不匹配
articleMapper.insert(cloneIgnoreId(dbArticle, o -> o.setSort(null)));
// 测试 status 不匹配
articleMapper.insert(cloneIgnoreId(dbArticle, o -> o.setStatus(null)));
// 测试 spuId 不匹配
articleMapper.insert(cloneIgnoreId(dbArticle, o -> o.setSpuId(null)));
// 测试 recommendHot 不匹配
articleMapper.insert(cloneIgnoreId(dbArticle, o -> o.setRecommendHot(null)));
// 测试 recommendBanner 不匹配
articleMapper.insert(cloneIgnoreId(dbArticle, o -> o.setRecommendBanner(null)));
// 测试 content 不匹配
articleMapper.insert(cloneIgnoreId(dbArticle, o -> o.setContent(null)));
// 测试 createTime 不匹配
articleMapper.insert(cloneIgnoreId(dbArticle, o -> o.setCreateTime(null)));
// 准备参数
ArticleExportReqVO reqVO = new ArticleExportReqVO();
reqVO.setCategoryId(null);
reqVO.setTitle(null);
reqVO.setAuthor(null);
reqVO.setStatus(null);
reqVO.setSpuId(null);
reqVO.setRecommendHot(null);
reqVO.setRecommendBanner(null);
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
// 调用
List<ArticleDO> list = articleService.getArticleList(reqVO);
// 断言
assertEquals(1, list.size());
assertPojoEquals(dbArticle, list.get(0));
}
} }

View File

@ -93,7 +93,6 @@ public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> {
return selectOne(TradeOrderDO::getPickUpVerifyCode, pickUpVerifyCode); return selectOne(TradeOrderDO::getPickUpVerifyCode, pickUpVerifyCode);
} }
// TODO @puhui999selectByUserIdAndCombinationActivityIdAndStatus这样更容易理解哈
/** /**
* 只针对 combinationActivityId 的查询 * 只针对 combinationActivityId 的查询
* *
@ -102,7 +101,7 @@ public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> {
* @param status 订单状态 * @param status 订单状态
* @return 交易订单 * @return 交易订单
*/ */
default TradeOrderDO selectByUserIdAndActivityIdAndStatus(Long userId, Long activityId, Integer status) { default TradeOrderDO selectByUserIdAndCombinationActivityIdAndStatus(Long userId, Long activityId, Integer status) {
return selectOne(new LambdaQueryWrapperX<TradeOrderDO>() return selectOne(new LambdaQueryWrapperX<TradeOrderDO>()
.eq(TradeOrderDO::getUserId, userId) .eq(TradeOrderDO::getUserId, userId)
.eq(TradeOrderDO::getStatus, status) .eq(TradeOrderDO::getStatus, status)

View File

@ -46,7 +46,7 @@ public interface TradeOrderQueryService {
* @param status 订单状态 * @param status 订单状态
* @return 交易订单 * @return 交易订单
*/ */
TradeOrderDO getActivityOrderByUserIdAndActivityIdAndStatus(Long userId, Long activityId, Integer status); TradeOrderDO getCombinationActivityOrderByUserIdAndCombinationActivityIdAndStatus(Long userId, Long activityId, Integer status);
/** /**
* 获得订单列表 * 获得订单列表

View File

@ -71,8 +71,8 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService {
} }
@Override @Override
public TradeOrderDO getActivityOrderByUserIdAndActivityIdAndStatus(Long userId, Long activityId, Integer status) { public TradeOrderDO getCombinationActivityOrderByUserIdAndCombinationActivityIdAndStatus(Long userId, Long activityId, Integer status) {
return tradeOrderMapper.selectByUserIdAndActivityIdAndStatus(userId, activityId, status); return tradeOrderMapper.selectByUserIdAndCombinationActivityIdAndStatus(userId, activityId, status);
} }
@Override @Override

View File

@ -49,7 +49,7 @@ public class TradeCombinationOrderHandler implements TradeOrderHandler {
order.getCombinationHeadId(), item.getSkuId(), item.getCount()); order.getCombinationHeadId(), item.getSkuId(), item.getCount());
// 2. 校验该用户是否存在未支付的拼团活动订单避免一个拼团可以下多个单子了 // 2. 校验该用户是否存在未支付的拼团活动订单避免一个拼团可以下多个单子了
TradeOrderDO activityOrder = orderQueryService.getActivityOrderByUserIdAndActivityIdAndStatus( TradeOrderDO activityOrder = orderQueryService.getCombinationActivityOrderByUserIdAndCombinationActivityIdAndStatus(
order.getUserId(), order.getCombinationActivityId(), TradeOrderStatusEnum.UNPAID.getStatus()); order.getUserId(), order.getCombinationActivityId(), TradeOrderStatusEnum.UNPAID.getStatus());
if (activityOrder != null) { if (activityOrder != null) {
throw exception(ORDER_CREATE_FAIL_EXIST_UNPAID); throw exception(ORDER_CREATE_FAIL_EXIST_UNPAID);