code review:拼团、秒杀活动的代码

This commit is contained in:
YunaiV 2023-08-05 20:51:48 +08:00
parent 7a7ae3b8ec
commit 5e2fa48f20
24 changed files with 149 additions and 108 deletions

View File

@ -27,6 +27,7 @@ public class CollectionUtils {
return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty);
}
// TODO @puhui999anyMatch 更统一点
public static <T> boolean isAny(Collection<T> from, Predicate<T> predicate) {
return from.stream().anyMatch(predicate);
}

View File

@ -84,11 +84,11 @@ public class LocalDateTimeUtils {
public static boolean isOverlap(LocalTime startTime1, LocalTime endTime1, LocalTime startTime2, LocalTime endTime2) {
// 日期部分使用了当前日期LocalDate.now()
// TODO @puhui999LocalDate.now() 抽一个变量啊哈然后注释写下之后 4 个变量不用直接调方法的时候直接计算作为入参
LocalDateTime startDateTime1 = LocalDateTime.of(LocalDate.now(), startTime1);
LocalDateTime endDateTime1 = LocalDateTime.of(LocalDate.now(), endTime1);
LocalDateTime startDateTime2 = LocalDateTime.of(LocalDate.now(), startTime2);
LocalDateTime endDateTime2 = LocalDateTime.of(LocalDate.now(), endTime2);
return LocalDateTimeUtil.isOverlap(startDateTime1, endDateTime1, startDateTime2, endDateTime2);
}

View File

@ -44,6 +44,12 @@ public interface BaseMapperX<T> extends BaseMapper<T> {
return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
}
default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2,
SFunction<T, ?> field3, Object value3) {
return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2)
.eq(field3, value3));
}
default Long selectCount() {
return selectCount(new QueryWrapper<T>());
}

View File

@ -1,8 +1,8 @@
package cn.iocoder.yudao.module.product.controller.app.comment;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO;
@ -27,6 +27,7 @@ import java.util.List;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@Tag(name = "用户 APP - 商品评价")
@RestController
@ -56,10 +57,17 @@ public class AppProductCommentController {
@GetMapping("/page")
@Operation(summary = "获得商品评价分页")
public CommonResult<PageResult<AppProductCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) {
PageResult<ProductCommentDO> commentDOPage = productCommentService.getCommentPage(pageVO, Boolean.TRUE);
Set<Long> skuIds = CollectionUtils.convertSet(commentDOPage.getList(), ProductCommentDO::getSkuId);
PageResult<AppProductCommentRespVO> page = ProductCommentConvert.INSTANCE.convertPage02(commentDOPage, productSkuService.getSkuList(skuIds));
return success(page);
// 查询评论分页
PageResult<ProductCommentDO> commentPageResult = productCommentService.getCommentPage(pageVO, Boolean.TRUE);
if (CollUtil.isEmpty(commentPageResult.getList())) {
return success(PageResult.empty(commentPageResult.getTotal()));
}
// 拼接返回
Set<Long> skuIds = convertSet(commentPageResult.getList(), ProductCommentDO::getSkuId);
PageResult<AppProductCommentRespVO> commentVOPageResult = ProductCommentConvert.INSTANCE.convertPage02(
commentPageResult, productSkuService.getSkuList(skuIds));
return success(commentVOPageResult);
}
// TODO 芋艿需要搞下

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.product.convert.comment;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
@ -15,7 +14,6 @@ import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProdu
import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import com.google.common.collect.Maps;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
@ -52,17 +50,16 @@ public interface ProductCommentConvert {
PageResult<AppProductCommentRespVO> convertPage01(PageResult<ProductCommentDO> pageResult);
default PageResult<AppProductCommentRespVO> convertPage02(PageResult<ProductCommentDO> pageResult, List<ProductSkuDO> skuList) {
Map<Long, ProductSkuDO> skuMap = Maps.newLinkedHashMapWithExpectedSize(skuList.size());
if (CollUtil.isNotEmpty(skuList)) {
skuMap.putAll(CollectionUtils.convertMap(skuList, ProductSkuDO::getId));
}
default PageResult<AppProductCommentRespVO> convertPage02(PageResult<ProductCommentDO> pageResult,
List<ProductSkuDO> skuList) {
Map<Long, ProductSkuDO> skuMap = CollectionUtils.convertMap(skuList, ProductSkuDO::getId);
PageResult<AppProductCommentRespVO> page = convertPage01(pageResult);
page.getList().forEach(item -> {
// 判断用户是否选择匿名
if (ObjectUtil.equal(item.getAnonymous(), true)) {
item.setUserNickname(ProductCommentDO.NICKNAME_ANONYMOUS);
}
// 设置 SKU 规格值
MapUtils.findAndThen(skuMap, item.getSkuId(),
sku -> item.setSkuProperties(convertList01(sku.getProperties())));
});

View File

@ -112,10 +112,9 @@ public interface ProductSpuConvert {
}
default List<ProductSpuDetailRespVO> convertForSpuDetailRespListVO(List<ProductSpuDO> spus, List<ProductSkuDO> skus) {
List<ProductSpuDetailRespVO> vos = new ArrayList<>(spus.size());
Map<Long, List<ProductSkuDO>> skuMultiMap = convertMultiMap(skus, ProductSkuDO::getSpuId);
CollectionUtils.convertList(spus, spu -> vos.add(convert03(spu).setSkus(ProductSkuConvert.INSTANCE.convertList(skuMultiMap.get(spu.getId())))));
return vos;
return CollectionUtils.convertList(spus, spu -> convert03(spu)
.setSkus(ProductSkuConvert.INSTANCE.convertList(skuMultiMap.get(spu.getId()))));
}
}

View File

@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.promotion.api.combination;
import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
import javax.validation.Valid;
// TODO @芋艿后面也再撸撸这几个接口
// TODO @芋艿后面也再撸撸这几个接口
/**
* 拼团记录 API 接口
*
@ -17,17 +17,18 @@ public interface CombinationRecordApi {
*
* @param reqDTO 请求 DTO
*/
void createRecord(@Valid CombinationRecordCreateReqDTO reqDTO);
void createCombinationRecord(@Valid CombinationRecordCreateReqDTO reqDTO);
/**
* 校验拼团是否成功
* 查询拼团记录是否成功
*
* @param userId 用户编号
* @param orderId 订单编号
* @return 拼团是否成功
*/
boolean validateRecordStatusIsSuccess(Long userId, Long orderId);
boolean isCombinationRecordSuccess(Long userId, Long orderId);
// TODO @puhui999updateRecordStatus updateRecordStatusAndStartTime 看看后续是不是可以统一掉
/**
* 更新开团记录状态
*
@ -35,7 +36,7 @@ public interface CombinationRecordApi {
* @param orderId 订单编号
* @param status 状态值
*/
void updateRecordStatus(Long userId, Long orderId, Integer status);
void updateCombinationRecordStatus(Long userId, Long orderId, Integer status);
/**
* 更新开团记录状态和开始时间
@ -44,6 +45,6 @@ public interface CombinationRecordApi {
* @param orderId 订单编号
* @param status 状态值
*/
void updateRecordStatusAndStartTime(Long userId, Long orderId, Integer status);
void updateCombinationRecordStatusAndStartTime(Long userId, Long orderId, Integer status);
}

View File

@ -5,8 +5,9 @@ import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
// TODO @芋艿这块要在看看
/**
* 拼团记录 Request DTO
* 拼团记录的创建 Request DTO
*
* @author HUIHUI
*/

View File

@ -20,23 +20,23 @@ public class CombinationRecordApiImpl implements CombinationRecordApi {
private CombinationRecordService recordService;
@Override
public void createRecord(CombinationRecordCreateReqDTO reqDTO) {
recordService.createRecord(reqDTO);
public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) {
recordService.createCombinationRecord(reqDTO);
}
@Override
public boolean validateRecordStatusIsSuccess(Long userId, Long orderId) {
return CombinationRecordStatusEnum.isSuccess(recordService.getRecord(userId, orderId).getStatus());
public boolean isCombinationRecordSuccess(Long userId, Long orderId) {
return CombinationRecordStatusEnum.isSuccess(recordService.getCombinationRecord(userId, orderId).getStatus());
}
@Override
public void updateRecordStatus(Long userId, Long orderId, Integer status) {
recordService.updateRecordStatusByUserIdAndOrderId(userId, orderId, status);
public void updateCombinationRecordStatus(Long userId, Long orderId, Integer status) {
recordService.updateCombinationRecordStatusByUserIdAndOrderId(userId, orderId, status);
}
@Override
public void updateRecordStatusAndStartTime(Long userId, Long orderId, Integer status) {
recordService.updateRecordStatusAndStartTimeByUserIdAndOrderId(userId, orderId, status, LocalDateTime.now());
public void updateCombinationRecordStatusAndStartTime(Long userId, Long orderId, Integer status) {
recordService.updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(userId, orderId, status, LocalDateTime.now());
}
}

View File

@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.promotion.controller.admin.combination;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
@ -23,9 +22,11 @@ import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import static cn.hutool.core.collection.CollectionUtil.newArrayList;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@Tag(name = "管理后台 - 拼团活动")
@RestController
@ -35,6 +36,7 @@ public class CombinationActivityController {
@Resource
private CombinationActivityService combinationActivityService;
@Resource
private ProductSpuApi spuApi;
@ -68,17 +70,18 @@ public class CombinationActivityController {
@PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')")
public CommonResult<CombinationActivityRespVO> getCombinationActivity(@RequestParam("id") Long id) {
CombinationActivityDO activity = combinationActivityService.getCombinationActivity(id);
List<CombinationProductDO> products = combinationActivityService.getProductsByActivityIds(newArrayList(id));
List<CombinationProductDO> products = combinationActivityService.getCombinationProductsByActivityIds(newArrayList(id));
return success(CombinationActivityConvert.INSTANCE.convert(activity, products));
}
// TODO @puhui999是不是可以删掉貌似没用
@GetMapping("/list")
@Operation(summary = "获得拼团活动列表")
@Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
@PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')")
public CommonResult<List<CombinationActivityRespVO>> getCombinationActivityList(@RequestParam("ids") Collection<Long> ids) {
List<CombinationActivityDO> list = combinationActivityService.getCombinationActivityList(ids);
return success(CombinationActivityConvert.INSTANCE.complementList(list));
return success(CombinationActivityConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@ -86,10 +89,14 @@ public class CombinationActivityController {
@PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')")
public CommonResult<PageResult<CombinationActivityRespVO>> getCombinationActivityPage(
@Valid CombinationActivityPageReqVO pageVO) {
// 查询拼团活动
PageResult<CombinationActivityDO> pageResult = combinationActivityService.getCombinationActivityPage(pageVO);
// 拼接数据
Set<Long> activityIds = convertSet(pageResult.getList(), CombinationActivityDO::getId);
Set<Long> spuIds = convertSet(pageResult.getList(), CombinationActivityDO::getSpuId);
return success(CombinationActivityConvert.INSTANCE.convertPage(pageResult,
combinationActivityService.getProductsByActivityIds(CollectionUtils.convertSet(pageResult.getList(), CombinationActivityDO::getId)),
spuApi.getSpuList(CollectionUtils.convertSet(pageResult.getList(), CombinationActivityDO::getSpuId))));
combinationActivityService.getCombinationProductsByActivityIds(activityIds),
spuApi.getSpuList(spuIds)));
}
}

View File

@ -79,6 +79,7 @@ public class SeckillActivityController {
return success(SeckillActivityConvert.INSTANCE.convert(seckillActivity, seckillProducts));
}
// TODO @puhui999是不是可以删掉貌似没用
@GetMapping("/list")
@Operation(summary = "获得秒杀活动列表")
@Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.promotion.convert.combination;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
@ -70,7 +71,7 @@ public interface CombinationActivityConvert {
return respVO;
}
List<CombinationActivityRespVO> complementList(List<CombinationActivityDO> list);
List<CombinationActivityRespVO> convertList(List<CombinationActivityDO> list);
PageResult<CombinationActivityRespVO> convertPage(PageResult<CombinationActivityDO> page);
@ -80,8 +81,10 @@ public interface CombinationActivityConvert {
Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
PageResult<CombinationActivityRespVO> pageResult = convertPage(page);
pageResult.getList().forEach(item -> {
MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> item.setSpuName(spu.getName()));
MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl()));
MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> {
item.setSpuName(spu.getName());
item.setPicUrl(spu.getPicUrl());
});
item.setProducts(convertList2(productList));
});
return pageResult;
@ -100,7 +103,7 @@ public interface CombinationActivityConvert {
})
CombinationProductDO convert(CombinationActivityDO activityDO, CombinationProductBaseVO vo);
default List<CombinationProductDO> complementList(List<? extends CombinationProductBaseVO> products, CombinationActivityDO activityDO) {
default List<CombinationProductDO> convertList(List<? extends CombinationProductBaseVO> products, CombinationActivityDO activityDO) {
List<CombinationProductDO> list = new ArrayList<>();
products.forEach(sku -> {
CombinationProductDO productDO = convert(activityDO, sku);
@ -110,16 +113,12 @@ public interface CombinationActivityConvert {
return list;
}
default List<CombinationProductDO> complementList(List<CombinationProductDO> productDOs, List<CombinationProductUpdateReqVO> vos, CombinationActivityDO activityDO) {
Map<Long, Long> longMap = convertMap(productDOs, CombinationProductDO::getSkuId, CombinationProductDO::getId);
List<CombinationProductDO> list = new ArrayList<>();
vos.forEach(sku -> {
CombinationProductDO productDO = convert(activityDO, sku);
productDO.setId(longMap.get(sku.getSkuId()));
productDO.setActivityStatus(activityDO.getStatus());
list.add(productDO);
});
return list;
default List<CombinationProductDO> convertList(List<CombinationProductUpdateReqVO> updateProductVOs,
List<CombinationProductDO> products, CombinationActivityDO activity) {
Map<Long, Long> productMap = convertMap(products, CombinationProductDO::getSkuId, CombinationProductDO::getId);
return CollectionUtils.convertList(updateProductVOs, updateProductVO -> convert(activity, updateProductVO)
.setId(productMap.get(updateProductVO.getSkuId()))
.setActivityStatus(activity.getStatus()));
}
CombinationRecordDO convert(CombinationRecordCreateReqDTO reqDTO);

View File

@ -21,6 +21,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
/**
* 秒杀活动 Convert
*
@ -37,6 +39,7 @@ public interface SeckillActivityConvert {
SeckillActivityRespVO convert(SeckillActivityDO bean);
// TODO @puhui999这个是不是还是 convertList 好点
List<SeckillActivityRespVO> complementList(List<SeckillActivityDO> list);
PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page);
@ -73,7 +76,7 @@ public interface SeckillActivityConvert {
})
SeckillProductDO convert(SeckillActivityDO activityDO, SeckillProductBaseVO vo);
default List<SeckillProductDO> complementList(List<? extends SeckillProductBaseVO> products, SeckillActivityDO activityDO) {
default List<SeckillProductDO> convertList(List<? extends SeckillProductBaseVO> products, SeckillActivityDO activityDO) {
List<SeckillProductDO> list = new ArrayList<>();
products.forEach(sku -> {
SeckillProductDO productDO = convert(activityDO, sku);
@ -83,16 +86,12 @@ public interface SeckillActivityConvert {
return list;
}
default List<SeckillProductDO> complementList(List<SeckillProductDO> productDOs, List<SeckillProductUpdateReqVO> vos, SeckillActivityDO activityDO) {
Map<Long, Long> longMap = CollectionUtils.convertMap(productDOs, SeckillProductDO::getSkuId, SeckillProductDO::getId);
List<SeckillProductDO> list = new ArrayList<>();
vos.forEach(sku -> {
SeckillProductDO productDO = convert(activityDO, sku);
productDO.setId(longMap.get(sku.getSkuId()));
productDO.setActivityStatus(activityDO.getStatus());
list.add(productDO);
});
return list;
default List<SeckillProductDO> convertList(List<SeckillProductUpdateReqVO> updateProductVOs,
List<SeckillProductDO> products, SeckillActivityDO activity) {
Map<Long, Long> productMap = convertMap(products, SeckillProductDO::getSkuId, SeckillProductDO::getId);
return CollectionUtils.convertList(updateProductVOs, updateProductVO -> convert(activity, updateProductVO)
.setId(productMap.get(updateProductVO.getSkuId()))
.setActivityStatus(activity.getStatus()));
}
List<SeckillProductRespVO> convertList2(List<SeckillProductDO> productDOs);

View File

@ -12,6 +12,9 @@ import java.time.LocalDateTime;
/**
* 拼团记录 DO
*
* 1. 用户参与拼团时会创建一条记录
* 2. 团长的拼团记录和参团人的拼团记录通过 {@link #headId} 关联
*
* @author HUIHUI
*/
@TableName("promotion_combination_record")

View File

@ -15,6 +15,7 @@ import java.util.List;
@Mapper
public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO> {
// TODO @puhui999selectByUserIdAndOrderId
default CombinationRecordDO selectRecord(Long userId, Long orderId) {
return selectOne(CombinationRecordDO::getUserId, userId,
CombinationRecordDO::getOrderId, orderId);
@ -28,7 +29,8 @@ public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO
* @return 拼团记录
*/
default CombinationRecordDO selectRecordByHeadId(Long headId, Long activityId, Integer status) {
return selectOne(CombinationRecordDO::getUserId, headId, CombinationRecordDO::getActivityId, activityId,
return selectOne(CombinationRecordDO::getHeadId, headId,
CombinationRecordDO::getActivityId, activityId,
CombinationRecordDO::getStatus, status);
}

View File

@ -70,6 +70,6 @@ public interface CombinationActivityService {
* @param ids 拼团活动 ids
* @return 拼团活动的商品列表
*/
List<CombinationProductDO> getProductsByActivityIds(Collection<Long> ids);
List<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> ids);
}

View File

@ -19,14 +19,14 @@ public interface CombinationRecordService {
* @param orderId 订单编号
* @param status 状态
*/
void updateRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status);
void updateCombinationRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status);
/**
* 创建拼团记录
*
* @param reqDTO 创建信息
*/
void createRecord(CombinationRecordCreateReqDTO reqDTO);
void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO);
/**
* 更新拼团状态和开始时间
@ -36,7 +36,8 @@ public interface CombinationRecordService {
* @param status 状态
* @param startTime 开始时间
*/
void updateRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId, Integer status, LocalDateTime startTime);
void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId,
Integer status, LocalDateTime startTime);
/**
* 获得拼团状态
@ -45,6 +46,6 @@ public interface CombinationRecordService {
* @param orderId 订单编号
* @return 拼团状态
*/
CombinationRecordDO getRecord(Long userId, Long orderId);
CombinationRecordDO getCombinationRecord(Long userId, Long orderId);
}

View File

@ -37,7 +37,7 @@ import java.util.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuExistence;
import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuAllExists;
/**
* 拼团活动 Service 实现类
@ -66,7 +66,7 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi
// 获取所选 spu下的所有 sku
List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(createReqVO.getSpuId()));
// 校验商品 sku 是否存在
validateProductSkuExistence(createReqVO.getProducts(), skus, CombinationProductCreateReqVO::getSkuId);
validateProductSkuAllExists(createReqVO.getProducts(), skus, CombinationProductCreateReqVO::getSkuId);
// TODO 艿艿 有个小问题现在有活动时间和限制时长活动时间的结束时间早于设置的限制时间怎么算状态比如
// 活动时间 2023-08-05 15:00:00 - 2023-08-05 15:20:00 限制时长 2小时那么活动时间结束就结束还是加时到满两小时
@ -80,7 +80,7 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi
activityDO.setStatus(CommonStatusEnum.ENABLE.getStatus());
combinationActivityMapper.insert(activityDO);
// 插入商品
List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.complementList(createReqVO.getProducts(), activityDO);
List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), activityDO);
combinationProductMapper.insertBatch(productDOs);
// 返回
return activityDO.getId();
@ -118,7 +118,7 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi
// 获取所选 spu下的所有 sku
List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(updateReqVO.getSpuId()));
// 校验商品 sku 是否存在
validateProductSkuExistence(updateReqVO.getProducts(), skus, CombinationProductUpdateReqVO::getSkuId);
validateProductSkuAllExists(updateReqVO.getProducts(), skus, CombinationProductUpdateReqVO::getSkuId);
// 更新
CombinationActivityDO updateObj = CombinationActivityConvert.INSTANCE.convert(updateReqVO);
@ -140,18 +140,21 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi
// 前端传过来的活动商品
Set<Long> convertSet1 = CollectionUtils.convertSet(products, CombinationProductUpdateReqVO::getSkuId);
// 分化数据
// TODO @芋艿看下这个实现
Map<String, List<CombinationProductDO>> data = CollectionUtils.convertCDUMap(convertSet1, convertSet, mapData -> {
HashMap<String, List<CombinationProductDO>> cdu = MapUtil.newHashMap(3);
MapUtils.findAndThen(mapData, "create", list -> {
cdu.put("create", CombinationActivityConvert.INSTANCE.complementList(CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj));
cdu.put("create", CombinationActivityConvert.INSTANCE.convertList(CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj));
});
MapUtils.findAndThen(mapData, "delete", list -> {
cdu.put("create", CollectionUtils.filterList(combinationProductDOs, item -> list.contains(item.getSkuId())));
});
MapUtils.findAndThen(mapData, "update", list -> {
cdu.put("update", CombinationActivityConvert.INSTANCE.complementList(combinationProductDOs,
CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj));
});
// TODO @芋艿临时注释避免有问题
// MapUtils.findAndThen(mapData, "update", list -> {
// cdu.put("update", CombinationActivityConvert.INSTANCE.convertList(
// combinationProductDOs,
// CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj));
// });
return cdu;
});
@ -199,12 +202,12 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi
}
@Override
public List<CombinationProductDO> getProductsByActivityIds(Collection<Long> ids) {
public List<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> ids) {
return combinationProductMapper.selectListByActivityIds(ids);
}
@Override
public void updateRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status) {
public void updateCombinationRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status) {
// 校验拼团是否存在
CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId);
@ -215,7 +218,7 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi
@Override
@Transactional(rollbackFor = Exception.class)
public void updateRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId, Integer status, LocalDateTime startTime) {
public void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId, Integer status, LocalDateTime startTime) {
CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId);
// 更新状态
recordDO.setStatus(status);
@ -247,15 +250,15 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi
}
@Override
public void createRecord(CombinationRecordCreateReqDTO reqDTO) {
// 校验拼团活动
public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) {
// 1.1 校验拼团活动
CombinationActivityDO activity = validateCombinationActivityExists(reqDTO.getActivityId());
// 需要校验下当前是不是已经参加了该拼团
// 1.2 需要校验下当前是不是已经参加了该拼团
CombinationRecordDO recordDO = recordMapper.selectRecord(reqDTO.getUserId(), reqDTO.getOrderId());
if (recordDO != null) {
throw exception(COMBINATION_RECORD_EXISTS);
}
// 父拼团是否存在,是否已经满了
// 1.3 父拼团是否存在,是否已经满了
if (reqDTO.getHeadId() != null) {
CombinationRecordDO recordDO1 = recordMapper.selectRecordByHeadId(reqDTO.getHeadId(), reqDTO.getActivityId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
if (recordDO1 == null) {
@ -266,9 +269,12 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi
throw exception(COMBINATION_RECORD_USER_FULL);
}
}
// TODO @puhui999应该还有一些校验后续补噶例如说一个团自己已经参与进去了不能再参与进去
// 2. 创建拼团记录
CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO);
if (reqDTO.getHeadId() == null) {
// TODO @puhui999不是自己呀headId 是父团长的 CombinationRecordDO.id
record.setHeadId(reqDTO.getUserId());
}
record.setVirtualGroup(false);
@ -279,7 +285,7 @@ public class CombinationServiceImpl implements CombinationActivityService, Combi
}
@Override
public CombinationRecordDO getRecord(Long userId, Long orderId) {
public CombinationRecordDO getCombinationRecord(Long userId, Long orderId) {
return validateCombinationRecord(userId, orderId);
}

View File

@ -34,7 +34,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuExistence;
import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuAllExists;
/**
* 秒杀活动 Service 实现类
@ -74,7 +74,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
.setTotalStock(CollectionUtils.getSumValue(createReqVO.getProducts(), SeckillProductCreateReqVO::getStock, Integer::sum));
seckillActivityMapper.insert(activity);
// 插入商品
List<SeckillProductDO> products = SeckillActivityConvert.INSTANCE.complementList(createReqVO.getProducts(), activity);
List<SeckillProductDO> products = SeckillActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), activity);
seckillProductMapper.insertBatch(products);
return activity.getId();
}
@ -121,7 +121,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
// 获取所选 spu下的所有 sku
List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollUtil.newArrayList(updateReqVO.getSpuId()));
// 校验商品 sku 是否存在
validateProductSkuExistence(updateReqVO.getProducts(), skus, SeckillProductUpdateReqVO::getSkuId);
validateProductSkuAllExists(updateReqVO.getProducts(), skus, SeckillProductUpdateReqVO::getSkuId);
// 更新活动
SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO)
@ -150,16 +150,17 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
Map<String, List<SeckillProductDO>> data = CollectionUtils.convertCDUMap(voSkuIds, dbSkuIds, mapData -> {
HashMap<String, List<SeckillProductDO>> cdu = MapUtil.newHashMap(3);
MapUtils.findAndThen(mapData, "create", list -> {
cdu.put("create", SeckillActivityConvert.INSTANCE.complementList(
cdu.put("create", SeckillActivityConvert.INSTANCE.convertList(
CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj));
});
MapUtils.findAndThen(mapData, "delete", list -> {
cdu.put("create", CollectionUtils.filterList(seckillProductDOs, item -> list.contains(item.getSkuId())));
});
MapUtils.findAndThen(mapData, "update", list -> {
cdu.put("update", SeckillActivityConvert.INSTANCE.complementList(seckillProductDOs,
CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj));
});
// TODO @芋艿临时注释
// MapUtils.findAndThen(mapData, "update", list -> {
// cdu.put("update", SeckillActivityConvert.INSTANCE.convertList(seckillProductDOs,
// CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj));
// });
return cdu;
});

View File

@ -31,18 +31,20 @@ public class PromotionUtils {
return LocalDateTimeUtils.beforeNow(endTime) ? CommonStatusEnum.DISABLE.getStatus() : CommonStatusEnum.ENABLE.getStatus();
}
// TODO @puhui999是不是第一个参数是 sku然后是 products这样关联性好点
/**
* 校验商品 sku 是否存在
* 校验商品 sku 是否存在
*
* @param products 需要校验的商品
* @param skus 数据库中的商品 skus
* @param func 获取需要校验的商品的 skuId
*/
public static <T> void validateProductSkuExistence(List<T> products, List<ProductSkuRespDTO> skus, Function<T, Long> func) {
public static <T> void validateProductSkuAllExists(List<T> products, List<ProductSkuRespDTO> skus, Function<T, Long> func) {
// 校验 sku 个数是否一致
Set<Long> skuIdsSet = CollectionUtils.convertSet(products, func);
Set<Long> skuIdsSet1 = CollectionUtils.convertSet(skus, ProductSkuRespDTO::getId);
// 校验 skuId 是否存在
// TODO @puhui999findFirst
List<Long> f = CollectionUtils.filterList(skuIdsSet, s -> !skuIdsSet1.contains(s));
if (CollUtil.isNotEmpty(f)) {
throw exception(SKU_NOT_EXISTS);

View File

@ -332,6 +332,7 @@ public interface TradeOrderConvert {
@Mapping(target = "avatar", source = "user.avatar"),
@Mapping(target = "status", ignore = true)
})
CombinationRecordCreateReqDTO convert(TradeOrderDO order, TradeOrderItemDO orderItem, AppTradeOrderCreateReqVO createReqVO, MemberUserRespDTO user);
CombinationRecordCreateReqDTO convert(TradeOrderDO order, TradeOrderItemDO orderItem,
AppTradeOrderCreateReqVO createReqVO, MemberUserRespDTO user);
}

View File

@ -27,11 +27,13 @@ public class TradeMessageServiceImpl implements TradeMessageService {
// 1构造消息
Map<String, Object> msgMap = new HashMap<>();
msgMap.put("orderId", reqDTO.getOrderId());
// TODO puhui999应该不是 msg 应该是涉及到的模版参数哈msg 太大了
msgMap.put("msg", reqDTO.getMessage());
// 2发送站内信
notifyMessageSendApi.sendSingleMessageToMember(
new NotifySendSingleToUserReqDTO()
.setUserId(reqDTO.getUserId())
// TODO puhui999短信模版编号枚举起来
.setTemplateCode("order_delivery")
.setTemplateParams(msgMap));
}

View File

@ -5,6 +5,7 @@ import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
// TODO @puhui999改成 ReqBO 包名也换了service 我们还是同一用 bo 对象
/**
* 订单发货时 Req DTO
*

View File

@ -174,7 +174,8 @@ public class TradeOrderServiceImpl implements TradeOrderService {
if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
MemberUserRespDTO user = memberUserApi.getUser(userId);
// TODO 拼团一次应该只能选择一种规格的商品
combinationRecordApi.createRecord(TradeOrderConvert.INSTANCE.convert(order, orderItems.get(0), createReqVO, user)
// TODO @puhui999应该是前置校验哈然后不应该设置状态而是交给拼团记录那处理
combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(order, orderItems.get(0), createReqVO, user)
.setStatus(CombinationRecordStatusEnum.WAITING.getStatus()));
}
// TODO 秒杀扣减库存是下单就扣除还是等待订单支付成功再扣除
@ -311,7 +312,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
// 1拼团活动
if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
// 更新拼团状态 TODO puhui999订单支付失败或订单支付过期删除这条拼团记录
combinationRecordApi.updateRecordStatusAndStartTime(order.getUserId(), order.getId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
combinationRecordApi.updateCombinationRecordStatusAndStartTime(order.getUserId(), order.getId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
}
// TODO 芋艿发送订单变化的消息
@ -376,10 +377,11 @@ public class TradeOrderServiceImpl implements TradeOrderService {
return new KeyValue<>(order, payOrder);
}
// TODO @芋艿后续在 review 下发货逻辑
@Override
@Transactional(rollbackFor = Exception.class)
public void deliveryOrder(Long userId, TradeOrderDeliveryReqVO deliveryReqVO) {
// 校验并获得交易订单可发货
// 1.1 校验并获得交易订单可发货
TradeOrderDO order = validateOrderDeliverable(deliveryReqVO.getId());
/* TODO
@ -388,35 +390,36 @@ public class TradeOrderServiceImpl implements TradeOrderService {
* 2.如果店铺只支持到店自提那么下单后默认发货不需要物流
* 3.如果店铺支持 物流-配送-自提 的情况下后台不需要选择配送方式按前端用户选择的配送方式发货即可
*/
TradeOrderDO tradeOrderDO = new TradeOrderDO();
TradeOrderDO updateOrderObj = new TradeOrderDO();
// 判断发货类型
// 快递发货
// 2.1 快递发货
if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.EXPRESS.getMode())) {
// 校验快递公司
// TODO @puhui999getDeliveryExpress 直接封装一个校验的会不会好点因为还有开启关闭啥的
DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(deliveryReqVO.getLogisticsId());
if (deliveryExpress == null) {
throw exception(EXPRESS_NOT_EXISTS);
}
tradeOrderDO.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo());
updateOrderObj.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo());
}
// 用户自提
// 2.2 用户自提
if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.PICK_UP.getMode())) {
// TODO 校验自提门店是否存在
// 重置一下确保快递公司和快递单号为空
tradeOrderDO.setLogisticsId(null).setLogisticsNo("");
updateOrderObj.setLogisticsId(null).setLogisticsNo("");
}
// TODO 芋艿如果无需发货需要怎么存储
// 2.3 TODO 芋艿如果无需发货需要怎么存储回复需要把 deliverType 设置为 DeliveryTypeEnum.NULL
if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.NULL.getMode())) {
// TODO 情况一正常走发货逻辑和用户自提有点像 不同点不需要自提门店只需要用户确认收货
// TODO 情况二用户下单付款后直接确认收货或等待用户确认收货
// 重置一下确保快递公司和快递单号为空
tradeOrderDO.setLogisticsId(null).setLogisticsNo("");
updateOrderObj.setLogisticsId(null).setLogisticsNo("");
}
// 更新 TradeOrderDO 状态为已发货等待收货
tradeOrderDO.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus())
updateOrderObj.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus())
.setDeliveryStatus(TradeOrderDeliveryStatusEnum.DELIVERED.getStatus()).setDeliveryTime(LocalDateTime.now());
int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), tradeOrderDO);
int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), updateOrderObj);
if (updateCount == 0) {
throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED);
}
@ -457,7 +460,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
// 校验订单拼团是否成功
// TODO 用户 ID 使用当前登录用户的还是订单保存的
if (combinationRecordApi.validateRecordStatusIsSuccess(order.getUserId(), order.getId())) {
if (combinationRecordApi.isCombinationRecordSuccess(order.getUserId(), order.getId())) {
throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS);
}
}