Commit 7a7ae3b8ec8117457bb7f23a31e45ec2feba7a99

Authored by 芋道源码
Committed by Gitee
2 parents 105f1a27 92b10e2e

!545 完善 review 拼团、秒杀活动的实现提到的问题

Merge pull request !545 from puhui999/feature/mall_product
Showing 48 changed files with 688 additions and 708 deletions
@@ -16,11 +16,11 @@ @@ -16,11 +16,11 @@
16 <module>yudao-module-member</module> 16 <module>yudao-module-member</module>
17 <module>yudao-module-system</module> 17 <module>yudao-module-system</module>
18 <module>yudao-module-infra</module> 18 <module>yudao-module-infra</module>
19 -<!-- <module>yudao-module-pay</module>--> 19 + <module>yudao-module-pay</module>
20 <!-- <module>yudao-module-bpm</module>--> 20 <!-- <module>yudao-module-bpm</module>-->
21 <!-- <module>yudao-module-report</module>--> 21 <!-- <module>yudao-module-report</module>-->
22 <!-- <module>yudao-module-mp</module>--> 22 <!-- <module>yudao-module-mp</module>-->
23 -<!-- <module>yudao-module-mall</module>--> 23 + <module>yudao-module-mall</module>
24 <!-- 示例项目 --> 24 <!-- 示例项目 -->
25 <module>yudao-example</module> 25 <module>yudao-example</module>
26 </modules> 26 </modules>
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.common.util.collection; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.common.util.collection;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.collection.CollectionUtil; 4 import cn.hutool.core.collection.CollectionUtil;
  5 +import cn.hutool.core.map.MapUtil;
5 import com.google.common.collect.ImmutableMap; 6 import com.google.common.collect.ImmutableMap;
6 7
7 import java.util.*; 8 import java.util.*;
@@ -26,6 +27,10 @@ public class CollectionUtils { @@ -26,6 +27,10 @@ public class CollectionUtils {
26 return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty); 27 return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty);
27 } 28 }
28 29
  30 + public static <T> boolean isAny(Collection<T> from, Predicate<T> predicate) {
  31 + return from.stream().anyMatch(predicate);
  32 + }
  33 +
29 public static <T> List<T> filterList(Collection<T> from, Predicate<T> predicate) { 34 public static <T> List<T> filterList(Collection<T> from, Predicate<T> predicate) {
30 if (CollUtil.isEmpty(from)) { 35 if (CollUtil.isEmpty(from)) {
31 return new ArrayList<>(); 36 return new ArrayList<>();
@@ -149,6 +154,41 @@ public class CollectionUtils { @@ -149,6 +154,41 @@ public class CollectionUtils {
149 return builder.build(); 154 return builder.build();
150 } 155 }
151 156
  157 + /**
  158 + * 数据划分为需要新增的、还是删除的、还是更新的。
  159 + *
  160 + * @param list1 需要处理的数据的相关编号列表
  161 + * @param list2 数据库中存在的数据的相关编号列表
  162 + * @param func 比较出哪些记录是新增,还是修改,还是删除
  163 + * @return 包含需要新增、修改、删除的数据 Map 对象
  164 + */
  165 + public static <D> Map<String, List<D>> convertCDUMap(Collection<Long> list1, Collection<Long> list2,
  166 + Function<Map<String, List<Long>>, Map<String, List<D>>> func) {
  167 + HashMap<String, List<Long>> mapData = MapUtil.newHashMap(3);
  168 + if (CollUtil.isEmpty(list1)) {
  169 + return func.apply(mapData);
  170 + }
  171 + if (CollUtil.isEmpty(list2)) {
  172 + return func.apply(mapData);
  173 + }
  174 + // 后台存在的前端不存在的
  175 + List<Long> d = CollectionUtils.filterList(list2, item -> !list1.contains(item));
  176 + if (CollUtil.isNotEmpty(d)) {
  177 + mapData.put("delete", d);
  178 + }
  179 + // 前端存在的后端不存在的
  180 + List<Long> c = CollectionUtils.filterList(list1, item -> !list2.contains(item));
  181 + if (CollUtil.isNotEmpty(c)) {
  182 + mapData.put("create", c);
  183 + }
  184 + // 更新已存在的
  185 + List<Long> u = CollectionUtils.filterList(list1, list2::contains);
  186 + if (CollUtil.isNotEmpty(u)) {
  187 + mapData.put("update", u);
  188 + }
  189 + return func.apply(mapData);
  190 + }
  191 +
152 public static boolean containsAny(Collection<?> source, Collection<?> candidates) { 192 public static boolean containsAny(Collection<?> source, Collection<?> candidates) {
153 return org.springframework.util.CollectionUtils.containsAny(source, candidates); 193 return org.springframework.util.CollectionUtils.containsAny(source, candidates);
154 } 194 }
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.common.util.date; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.common.util.date;
3 import cn.hutool.core.date.LocalDateTimeUtil; 3 import cn.hutool.core.date.LocalDateTimeUtil;
4 4
5 import java.time.Duration; 5 import java.time.Duration;
  6 +import java.time.LocalDate;
6 import java.time.LocalDateTime; 7 import java.time.LocalDateTime;
7 import java.time.LocalTime; 8 import java.time.LocalTime;
8 9
@@ -70,7 +71,7 @@ public class LocalDateTimeUtils { @@ -70,7 +71,7 @@ public class LocalDateTimeUtils {
70 * @param endTime2 校验所需的结束时间 71 * @param endTime2 校验所需的结束时间
71 * @return 是否重叠 72 * @return 是否重叠
72 */ 73 */
73 - // TODO @puhui999:LocalDateTimeUtil.isOverlap() 是不是可以满足呀? 74 + @Deprecated
74 public static boolean checkTimeOverlap(LocalTime startTime1, LocalTime endTime1, LocalTime startTime2, LocalTime endTime2) { 75 public static boolean checkTimeOverlap(LocalTime startTime1, LocalTime endTime1, LocalTime startTime2, LocalTime endTime2) {
75 // 判断时间是否重叠 76 // 判断时间是否重叠
76 // 开始时间在已配置时段的结束时间之前 且 结束时间在已配置时段的开始时间之后 [] 77 // 开始时间在已配置时段的结束时间之前 且 结束时间在已配置时段的开始时间之后 []
@@ -81,4 +82,14 @@ public class LocalDateTimeUtils { @@ -81,4 +82,14 @@ public class LocalDateTimeUtils {
81 || startTime1.isBefore(endTime2) && endTime1.isAfter(endTime2); 82 || startTime1.isBefore(endTime2) && endTime1.isAfter(endTime2);
82 } 83 }
83 84
  85 + public static boolean isOverlap(LocalTime startTime1, LocalTime endTime1, LocalTime startTime2, LocalTime endTime2) {
  86 + // 日期部分使用了当前日期LocalDate.now()
  87 + LocalDateTime startDateTime1 = LocalDateTime.of(LocalDate.now(), startTime1);
  88 + LocalDateTime endDateTime1 = LocalDateTime.of(LocalDate.now(), endTime1);
  89 + LocalDateTime startDateTime2 = LocalDateTime.of(LocalDate.now(), startTime2);
  90 + LocalDateTime endDateTime2 = LocalDateTime.of(LocalDate.now(), endTime2);
  91 +
  92 + return LocalDateTimeUtil.isOverlap(startDateTime1, endDateTime1, startDateTime2, endDateTime2);
  93 + }
  94 +
84 } 95 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java
1 package cn.iocoder.yudao.module.product.controller.app.comment; 1 package cn.iocoder.yudao.module.product.controller.app.comment;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 5 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
@@ -9,10 +8,8 @@ import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStati @@ -9,10 +8,8 @@ import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStati
9 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO; 8 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO;
10 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert; 9 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert;
11 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; 10 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
12 -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;  
13 import cn.iocoder.yudao.module.product.service.comment.ProductCommentService; 11 import cn.iocoder.yudao.module.product.service.comment.ProductCommentService;
14 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; 12 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
15 -import com.google.common.collect.Maps;  
16 import io.swagger.v3.oas.annotations.Operation; 13 import io.swagger.v3.oas.annotations.Operation;
17 import io.swagger.v3.oas.annotations.Parameter; 14 import io.swagger.v3.oas.annotations.Parameter;
18 import io.swagger.v3.oas.annotations.Parameters; 15 import io.swagger.v3.oas.annotations.Parameters;
@@ -27,7 +24,6 @@ import org.springframework.web.bind.annotation.RestController; @@ -27,7 +24,6 @@ import org.springframework.web.bind.annotation.RestController;
27 import javax.annotation.Resource; 24 import javax.annotation.Resource;
28 import javax.validation.Valid; 25 import javax.validation.Valid;
29 import java.util.List; 26 import java.util.List;
30 -import java.util.Map;  
31 import java.util.Set; 27 import java.util.Set;
32 28
33 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 29 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -60,15 +56,9 @@ public class AppProductCommentController { @@ -60,15 +56,9 @@ public class AppProductCommentController {
60 @GetMapping("/page") 56 @GetMapping("/page")
61 @Operation(summary = "获得商品评价分页") 57 @Operation(summary = "获得商品评价分页")
62 public CommonResult<PageResult<AppProductCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) { 58 public CommonResult<PageResult<AppProductCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) {
63 - // TODO @puhui999:写到 convert 里,可以更简洁哈。  
64 PageResult<ProductCommentDO> commentDOPage = productCommentService.getCommentPage(pageVO, Boolean.TRUE); 59 PageResult<ProductCommentDO> commentDOPage = productCommentService.getCommentPage(pageVO, Boolean.TRUE);
65 Set<Long> skuIds = CollectionUtils.convertSet(commentDOPage.getList(), ProductCommentDO::getSkuId); 60 Set<Long> skuIds = CollectionUtils.convertSet(commentDOPage.getList(), ProductCommentDO::getSkuId);
66 - List<ProductSkuDO> skuList = productSkuService.getSkuList(skuIds);  
67 - Map<Long, ProductSkuDO> skuDOMap = Maps.newLinkedHashMapWithExpectedSize(skuIds.size());  
68 - if (CollUtil.isNotEmpty(skuList)) {  
69 - skuDOMap.putAll(CollectionUtils.convertMap(skuList, ProductSkuDO::getId, c -> c));  
70 - }  
71 - PageResult<AppProductCommentRespVO> page = ProductCommentConvert.INSTANCE.convertPage02(commentDOPage, skuDOMap); 61 + PageResult<AppProductCommentRespVO> page = ProductCommentConvert.INSTANCE.convertPage02(commentDOPage, productSkuService.getSkuList(skuIds));
72 return success(page); 62 return success(page);
73 } 63 }
74 64
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java
1 package cn.iocoder.yudao.module.product.convert.comment; 1 package cn.iocoder.yudao.module.product.convert.comment;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.hutool.core.util.ObjectUtil; 4 import cn.hutool.core.util.ObjectUtil;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
5 import cn.iocoder.yudao.framework.common.util.collection.MapUtils; 7 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
6 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; 8 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
7 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; 9 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
@@ -13,6 +15,7 @@ import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProdu @@ -13,6 +15,7 @@ import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProdu
13 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; 15 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
14 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; 16 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
15 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; 17 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
  18 +import com.google.common.collect.Maps;
16 import org.mapstruct.Mapper; 19 import org.mapstruct.Mapper;
17 import org.mapstruct.Mapping; 20 import org.mapstruct.Mapping;
18 import org.mapstruct.Named; 21 import org.mapstruct.Named;
@@ -37,19 +40,23 @@ public interface ProductCommentConvert { @@ -37,19 +40,23 @@ public interface ProductCommentConvert {
37 40
38 @Mapping(target = "scores", expression = "java(calculateOverallScore(goodCount, mediocreCount, negativeCount))") 41 @Mapping(target = "scores", expression = "java(calculateOverallScore(goodCount, mediocreCount, negativeCount))")
39 AppCommentStatisticsRespVO convert(Long goodCount, Long mediocreCount, Long negativeCount); 42 AppCommentStatisticsRespVO convert(Long goodCount, Long mediocreCount, Long negativeCount);
  43 +
40 @Named("calculateOverallScore") 44 @Named("calculateOverallScore")
41 default double calculateOverallScore(long goodCount, long mediocreCount, long negativeCount) { 45 default double calculateOverallScore(long goodCount, long mediocreCount, long negativeCount) {
42 return (goodCount * 5 + mediocreCount * 3 + negativeCount) / (double) (goodCount + mediocreCount + negativeCount); 46 return (goodCount * 5 + mediocreCount * 3 + negativeCount) / (double) (goodCount + mediocreCount + negativeCount);
43 } 47 }
44 - 48 +
45 List<ProductCommentRespVO> convertList(List<ProductCommentDO> list); 49 List<ProductCommentRespVO> convertList(List<ProductCommentDO> list);
46 50
47 PageResult<ProductCommentRespVO> convertPage(PageResult<ProductCommentDO> page); 51 PageResult<ProductCommentRespVO> convertPage(PageResult<ProductCommentDO> page);
48 52
49 PageResult<AppProductCommentRespVO> convertPage01(PageResult<ProductCommentDO> pageResult); 53 PageResult<AppProductCommentRespVO> convertPage01(PageResult<ProductCommentDO> pageResult);
50 54
51 - default PageResult<AppProductCommentRespVO> convertPage02(PageResult<ProductCommentDO> pageResult,  
52 - Map<Long, ProductSkuDO> skuMap) { 55 + default PageResult<AppProductCommentRespVO> convertPage02(PageResult<ProductCommentDO> pageResult, List<ProductSkuDO> skuList) {
  56 + Map<Long, ProductSkuDO> skuMap = Maps.newLinkedHashMapWithExpectedSize(skuList.size());
  57 + if (CollUtil.isNotEmpty(skuList)) {
  58 + skuMap.putAll(CollectionUtils.convertMap(skuList, ProductSkuDO::getId));
  59 + }
53 PageResult<AppProductCommentRespVO> page = convertPage01(pageResult); 60 PageResult<AppProductCommentRespVO> page = convertPage01(pageResult);
54 page.getList().forEach(item -> { 61 page.getList().forEach(item -> {
55 // 判断用户是否选择匿名 62 // 判断用户是否选择匿名
@@ -61,6 +68,7 @@ public interface ProductCommentConvert { @@ -61,6 +68,7 @@ public interface ProductCommentConvert {
61 }); 68 });
62 return page; 69 return page;
63 } 70 }
  71 +
64 List<AppProductPropertyValueDetailRespVO> convertList01(List<ProductSkuDO.Property> properties); 72 List<AppProductPropertyValueDetailRespVO> convertList01(List<ProductSkuDO.Property> properties);
65 73
66 /** 74 /**
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
1 package cn.iocoder.yudao.module.product.convert.spu; 1 package cn.iocoder.yudao.module.product.convert.spu;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
4 import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; 5 import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
5 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; 6 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
6 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; 7 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
@@ -81,6 +82,7 @@ public interface ProductSpuConvert { @@ -81,6 +82,7 @@ public interface ProductSpuConvert {
81 } 82 }
82 return voList; 83 return voList;
83 } 84 }
  85 +
84 @Named("convertListForGetSpuList0") 86 @Named("convertListForGetSpuList0")
85 List<AppProductSpuPageRespVO> convertListForGetSpuList0(List<ProductSpuDO> list); 87 List<AppProductSpuPageRespVO> convertListForGetSpuList0(List<ProductSpuDO> list);
86 88
@@ -112,12 +114,7 @@ public interface ProductSpuConvert { @@ -112,12 +114,7 @@ public interface ProductSpuConvert {
112 default List<ProductSpuDetailRespVO> convertForSpuDetailRespListVO(List<ProductSpuDO> spus, List<ProductSkuDO> skus) { 114 default List<ProductSpuDetailRespVO> convertForSpuDetailRespListVO(List<ProductSpuDO> spus, List<ProductSkuDO> skus) {
113 List<ProductSpuDetailRespVO> vos = new ArrayList<>(spus.size()); 115 List<ProductSpuDetailRespVO> vos = new ArrayList<>(spus.size());
114 Map<Long, List<ProductSkuDO>> skuMultiMap = convertMultiMap(skus, ProductSkuDO::getSpuId); 116 Map<Long, List<ProductSkuDO>> skuMultiMap = convertMultiMap(skus, ProductSkuDO::getSpuId);
115 - // TODO @puhui999:可以直接使用 CollUtils.convertList  
116 - spus.forEach(spu -> {  
117 - ProductSpuDetailRespVO detailRespVO = convert03(spu);  
118 - detailRespVO.setSkus(ProductSkuConvert.INSTANCE.convertList(skuMultiMap.get(spu.getId())));  
119 - vos.add(detailRespVO);  
120 - }); 117 + CollectionUtils.convertList(spus, spu -> vos.add(convert03(spu).setSkus(ProductSkuConvert.INSTANCE.convertList(skuMultiMap.get(spu.getId())))));
121 return vos; 118 return vos;
122 } 119 }
123 120
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java
@@ -26,18 +26,19 @@ public interface ProductCommentMapper extends BaseMapperX&lt;ProductCommentDO&gt; { @@ -26,18 +26,19 @@ public interface ProductCommentMapper extends BaseMapperX&lt;ProductCommentDO&gt; {
26 } 26 }
27 27
28 static void appendTabQuery(LambdaQueryWrapperX<ProductCommentDO> queryWrapper, Integer type) { 28 static void appendTabQuery(LambdaQueryWrapperX<ProductCommentDO> queryWrapper, Integer type) {
29 - // TODO @puhui999:是不是不用 apply 拉?直接用 mybatis 的方法就好啦 29 + LambdaQueryWrapperX<ProductCommentDO> queryWrapperX = new LambdaQueryWrapperX<>();
30 // 构建好评查询语句:好评计算 总评 >= 4 30 // 构建好评查询语句:好评计算 总评 >= 4
31 if (ObjectUtil.equal(type, AppCommentPageReqVO.GOOD_COMMENT)) { 31 if (ObjectUtil.equal(type, AppCommentPageReqVO.GOOD_COMMENT)) {
32 - queryWrapper.apply("scores >= 4"); 32 + queryWrapperX.ge(ProductCommentDO::getScores, 4);
33 } 33 }
34 // 构建中评查询语句:中评计算 总评 >= 3 且 总评 < 4 34 // 构建中评查询语句:中评计算 总评 >= 3 且 总评 < 4
35 if (ObjectUtil.equal(type, AppCommentPageReqVO.MEDIOCRE_COMMENT)) { 35 if (ObjectUtil.equal(type, AppCommentPageReqVO.MEDIOCRE_COMMENT)) {
36 - queryWrapper.apply("scores >=3 and scores < 4"); 36 + queryWrapperX.ge(ProductCommentDO::getScores, 3);
  37 + queryWrapperX.lt(ProductCommentDO::getScores, 4);
37 } 38 }
38 // 构建差评查询语句:差评计算 总评 < 3 39 // 构建差评查询语句:差评计算 总评 < 3
39 if (ObjectUtil.equal(type, AppCommentPageReqVO.NEGATIVE_COMMENT)) { 40 if (ObjectUtil.equal(type, AppCommentPageReqVO.NEGATIVE_COMMENT)) {
40 - queryWrapper.apply("scores < 3"); 41 + queryWrapperX.lt(ProductCommentDO::getScores, 3);
41 } 42 }
42 } 43 }
43 44
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApi.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.api.combination;
  2 +
  3 +/**
  4 + * 拼团活动 API 接口
  5 + *
  6 + * @author HUIHUI
  7 + */
  8 +public interface CombinationActivityApi {
  9 +
  10 +}
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java renamed to yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java
1 package cn.iocoder.yudao.module.promotion.api.combination; 1 package cn.iocoder.yudao.module.promotion.api.combination;
2 2
3 -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO; 3 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
4 4
5 import javax.validation.Valid; 5 import javax.validation.Valid;
6 -  
7 -// TODO @puhui999:CombinationRecordApi 分成活动、记录哈  
8 // TODO @芋艿:后面也再撸撸这几个接口 6 // TODO @芋艿:后面也再撸撸这几个接口
  7 +
9 /** 8 /**
10 - * 拼团活动 API 接口 9 + * 拼团记录 API 接口
11 * 10 *
12 * @author HUIHUI 11 * @author HUIHUI
13 */ 12 */
14 -public interface CombinationApi { 13 +public interface CombinationRecordApi {
15 14
16 /** 15 /**
17 * 创建开团记录 16 * 创建开团记录
18 * 17 *
19 * @param reqDTO 请求 DTO 18 * @param reqDTO 请求 DTO
20 */ 19 */
21 - void createRecord(@Valid CombinationRecordReqDTO reqDTO); 20 + void createRecord(@Valid CombinationRecordCreateReqDTO reqDTO);
22 21
23 /** 22 /**
24 - * 获取开团记录状态 23 + * 校验拼团是否成功
25 * 24 *
26 * @param userId 用户编号 25 * @param userId 用户编号
27 * @param orderId 订单编号 26 * @param orderId 订单编号
  27 + * @return 拼团是否成功
28 */ 28 */
29 boolean validateRecordStatusIsSuccess(Long userId, Long orderId); 29 boolean validateRecordStatusIsSuccess(Long userId, Long orderId);
30 30
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordReqDTO.java renamed to yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java
@@ -5,14 +5,13 @@ import lombok.Data; @@ -5,14 +5,13 @@ import lombok.Data;
5 import javax.validation.constraints.NotEmpty; 5 import javax.validation.constraints.NotEmpty;
6 import javax.validation.constraints.NotNull; 6 import javax.validation.constraints.NotNull;
7 7
8 -// TODO @puhui999:CombinationRecordCreateReqDTO,这样更容易知道是创建噢  
9 /** 8 /**
10 * 拼团记录 Request DTO 9 * 拼团记录 Request DTO
11 * 10 *
12 * @author HUIHUI 11 * @author HUIHUI
13 */ 12 */
14 @Data 13 @Data
15 -public class CombinationRecordReqDTO { 14 +public class CombinationRecordCreateReqDTO {
16 15
17 /** 16 /**
18 * 拼团活动编号 17 * 拼团活动编号
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -65,5 +65,8 @@ public interface ErrorCodeConstants { @@ -65,5 +65,8 @@ public interface ErrorCodeConstants {
65 ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013010002, "拼团活动已关闭不能修改"); 65 ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013010002, "拼团活动已关闭不能修改");
66 ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013010003, "拼团活动未关闭或未结束,不能删除"); 66 ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013010003, "拼团活动未关闭或未结束,不能删除");
67 ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013010004, "拼团不存在"); 67 ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013010004, "拼团不存在");
  68 + ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1013010005, "拼团失败,已参与过该拼团");
  69 + ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013010006, "拼团失败,父拼团不存在");
  70 + ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1013010006, "拼团失败,拼团人数已满");
68 71
69 } 72 }
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/combination/CombinationRecordStatusEnum.java
1 package cn.iocoder.yudao.module.promotion.enums.combination; 1 package cn.iocoder.yudao.module.promotion.enums.combination;
2 2
  3 +import cn.hutool.core.util.ObjectUtil;
3 import cn.iocoder.yudao.framework.common.core.IntArrayValuable; 4 import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
4 import lombok.AllArgsConstructor; 5 import lombok.AllArgsConstructor;
5 import lombok.Getter; 6 import lombok.Getter;
@@ -36,4 +37,8 @@ public enum CombinationRecordStatusEnum implements IntArrayValuable { @@ -36,4 +37,8 @@ public enum CombinationRecordStatusEnum implements IntArrayValuable {
36 return ARRAYS; 37 return ARRAYS;
37 } 38 }
38 39
  40 + public static boolean isSuccess(Integer status) {
  41 + return ObjectUtil.equal(status, SUCCESS.getStatus());
  42 + }
  43 +
39 } 44 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java
1 package cn.iocoder.yudao.module.promotion.api.combination; 1 package cn.iocoder.yudao.module.promotion.api.combination;
2 2
3 -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO;  
4 -import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService; 3 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
  4 +import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
  5 +import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService;
5 import org.springframework.stereotype.Service; 6 import org.springframework.stereotype.Service;
6 7
7 import javax.annotation.Resource; 8 import javax.annotation.Resource;
@@ -13,30 +14,29 @@ import java.time.LocalDateTime; @@ -13,30 +14,29 @@ import java.time.LocalDateTime;
13 * @author HUIHUI 14 * @author HUIHUI
14 */ 15 */
15 @Service 16 @Service
16 -public class CombinationApiImpl implements CombinationApi { 17 +public class CombinationRecordApiImpl implements CombinationRecordApi {
17 18
18 @Resource 19 @Resource
19 - private CombinationActivityService activityService; 20 + private CombinationRecordService recordService;
20 21
21 @Override 22 @Override
22 - public void createRecord(CombinationRecordReqDTO reqDTO) {  
23 - activityService.createRecord(reqDTO); 23 + public void createRecord(CombinationRecordCreateReqDTO reqDTO) {
  24 + recordService.createRecord(reqDTO);
24 } 25 }
25 26
26 @Override 27 @Override
27 public boolean validateRecordStatusIsSuccess(Long userId, Long orderId) { 28 public boolean validateRecordStatusIsSuccess(Long userId, Long orderId) {
28 - return activityService.validateRecordStatusIsSuccess(userId, orderId); 29 + return CombinationRecordStatusEnum.isSuccess(recordService.getRecord(userId, orderId).getStatus());
29 } 30 }
30 31
31 @Override 32 @Override
32 public void updateRecordStatus(Long userId, Long orderId, Integer status) { 33 public void updateRecordStatus(Long userId, Long orderId, Integer status) {
33 - activityService.updateRecordStatusByUserIdAndOrderId(userId, orderId, status); 34 + recordService.updateRecordStatusByUserIdAndOrderId(userId, orderId, status);
34 } 35 }
35 36
36 @Override 37 @Override
37 public void updateRecordStatusAndStartTime(Long userId, Long orderId, Integer status) { 38 public void updateRecordStatusAndStartTime(Long userId, Long orderId, Integer status) {
38 - activityService.updateRecordStatusAndStartTimeByUserIdAndOrderId(userId, orderId, status, LocalDateTime.now()); 39 + recordService.updateRecordStatusAndStartTimeByUserIdAndOrderId(userId, orderId, status, LocalDateTime.now());
39 } 40 }
40 41
41 -  
42 } 42 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java
@@ -3,14 +3,14 @@ package cn.iocoder.yudao.module.promotion.controller.admin.combination; @@ -3,14 +3,14 @@ package cn.iocoder.yudao.module.promotion.controller.admin.combination;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 5 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
6 -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;  
7 -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;  
8 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; 6 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
9 -import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;  
10 -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.*; 7 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
  8 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
  9 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityRespVO;
  10 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
11 import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; 11 import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
12 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;  
13 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO; 12 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
  13 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
14 import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService; 14 import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService;
15 import io.swagger.v3.oas.annotations.Operation; 15 import io.swagger.v3.oas.annotations.Operation;
16 import io.swagger.v3.oas.annotations.Parameter; 16 import io.swagger.v3.oas.annotations.Parameter;
@@ -20,16 +20,12 @@ import org.springframework.validation.annotation.Validated; @@ -20,16 +20,12 @@ import org.springframework.validation.annotation.Validated;
20 import org.springframework.web.bind.annotation.*; 20 import org.springframework.web.bind.annotation.*;
21 21
22 import javax.annotation.Resource; 22 import javax.annotation.Resource;
23 -import javax.servlet.http.HttpServletResponse;  
24 import javax.validation.Valid; 23 import javax.validation.Valid;
25 -import java.io.IOException;  
26 import java.util.Collection; 24 import java.util.Collection;
27 import java.util.List; 25 import java.util.List;
28 -import java.util.Set;  
29 26
30 import static cn.hutool.core.collection.CollectionUtil.newArrayList; 27 import static cn.hutool.core.collection.CollectionUtil.newArrayList;
31 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 28 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
32 -import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;  
33 29
34 @Tag(name = "管理后台 - 拼团活动") 30 @Tag(name = "管理后台 - 拼团活动")
35 @RestController 31 @RestController
@@ -82,7 +78,7 @@ public class CombinationActivityController { @@ -82,7 +78,7 @@ public class CombinationActivityController {
82 @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')") 78 @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')")
83 public CommonResult<List<CombinationActivityRespVO>> getCombinationActivityList(@RequestParam("ids") Collection<Long> ids) { 79 public CommonResult<List<CombinationActivityRespVO>> getCombinationActivityList(@RequestParam("ids") Collection<Long> ids) {
84 List<CombinationActivityDO> list = combinationActivityService.getCombinationActivityList(ids); 80 List<CombinationActivityDO> list = combinationActivityService.getCombinationActivityList(ids);
85 - return success(CombinationActivityConvert.INSTANCE.convertList(list)); 81 + return success(CombinationActivityConvert.INSTANCE.complementList(list));
86 } 82 }
87 83
88 @GetMapping("/page") 84 @GetMapping("/page")
@@ -91,24 +87,9 @@ public class CombinationActivityController { @@ -91,24 +87,9 @@ public class CombinationActivityController {
91 public CommonResult<PageResult<CombinationActivityRespVO>> getCombinationActivityPage( 87 public CommonResult<PageResult<CombinationActivityRespVO>> getCombinationActivityPage(
92 @Valid CombinationActivityPageReqVO pageVO) { 88 @Valid CombinationActivityPageReqVO pageVO) {
93 PageResult<CombinationActivityDO> pageResult = combinationActivityService.getCombinationActivityPage(pageVO); 89 PageResult<CombinationActivityDO> pageResult = combinationActivityService.getCombinationActivityPage(pageVO);
94 - // TODO @puhui999:可以不一定 aIds,直接批量查询结果出来;下面也是类似;  
95 - Set<Long> aIds = CollectionUtils.convertSet(pageResult.getList(), CombinationActivityDO::getId);  
96 - List<CombinationProductDO> products = combinationActivityService.getProductsByActivityIds(aIds);  
97 - Set<Long> spuIds = CollectionUtils.convertSet(pageResult.getList(), CombinationActivityDO::getSpuId);  
98 - List<ProductSpuRespDTO> spus = spuApi.getSpuList(spuIds);  
99 - return success(CombinationActivityConvert.INSTANCE.convertPage(pageResult, products, spus));  
100 - }  
101 -  
102 - @GetMapping("/export-excel")  
103 - @Operation(summary = "导出拼团活动 Excel")  
104 - @PreAuthorize("@ss.hasPermission('promotion:combination-activity:export')")  
105 - @OperateLog(type = EXPORT)  
106 - public void exportCombinationActivityExcel(@Valid CombinationActivityExportReqVO exportReqVO,  
107 - HttpServletResponse response) throws IOException {  
108 - List<CombinationActivityDO> list = combinationActivityService.getCombinationActivityList(exportReqVO);  
109 - // 导出 Excel  
110 - List<CombinationActivityExcelVO> datas = CombinationActivityConvert.INSTANCE.convertList02(list);  
111 - ExcelUtils.write(response, "拼团活动.xls", "数据", CombinationActivityExcelVO.class, datas); 90 + return success(CombinationActivityConvert.INSTANCE.convertPage(pageResult,
  91 + combinationActivityService.getProductsByActivityIds(CollectionUtils.convertSet(pageResult.getList(), CombinationActivityDO::getId)),
  92 + spuApi.getSpuList(CollectionUtils.convertSet(pageResult.getList(), CombinationActivityDO::getSpuId))));
112 } 93 }
113 94
114 } 95 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityExcelVO.java deleted
1 -package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;  
2 -  
3 -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;  
4 -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;  
5 -import com.alibaba.excel.annotation.ExcelProperty;  
6 -import lombok.Data;  
7 -  
8 -import java.time.LocalDateTime;  
9 -  
10 -// TODO @puhui999:如无必要,导出都可以删除哈  
11 -/**  
12 - * 拼团活动 Excel VO  
13 - *  
14 - * @author HUIHUI  
15 - */  
16 -@Data  
17 -public class CombinationActivityExcelVO {  
18 -  
19 - @ExcelProperty("活动编号")  
20 - private Long id;  
21 -  
22 - @ExcelProperty("拼团名称")  
23 - private String name;  
24 -  
25 - @ExcelProperty("商品 SPU 编号关联 ProductSpuDO 的 id")  
26 - private Long spuId;  
27 -  
28 - @ExcelProperty("总限购数量")  
29 - private Integer totalLimitCount;  
30 -  
31 - @ExcelProperty("单次限购数量")  
32 - private Integer singleLimitCount;  
33 -  
34 - @ExcelProperty("开始时间")  
35 - private LocalDateTime startTime;  
36 -  
37 - @ExcelProperty("结束时间")  
38 - private LocalDateTime endTime;  
39 -  
40 - @ExcelProperty("开团人数")  
41 - private Integer userSize;  
42 -  
43 - @ExcelProperty("开团组数")  
44 - private Integer totalNum;  
45 -  
46 - @ExcelProperty("成团组数")  
47 - private Integer successNum;  
48 -  
49 - @ExcelProperty("参与人数")  
50 - private Integer orderUserCount;  
51 -  
52 - @ExcelProperty("虚拟成团")  
53 - private Integer virtualGroup;  
54 -  
55 - @ExcelProperty(value = "活动状态:0开启 1关闭", converter = DictConvert.class)  
56 - @DictFormat("common_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中  
57 - private Integer status;  
58 -  
59 - @ExcelProperty("限制时长(小时)")  
60 - private Integer limitDuration;  
61 -  
62 - @ExcelProperty("创建时间")  
63 - private LocalDateTime createTime;  
64 -  
65 -}  
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityExportReqVO.java deleted
1 -package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;  
2 -  
3 -import io.swagger.v3.oas.annotations.media.Schema;  
4 -import lombok.Data;  
5 -import org.springframework.format.annotation.DateTimeFormat;  
6 -  
7 -import java.time.LocalDateTime;  
8 -  
9 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;  
10 -  
11 -// TODO @puhui999:如无必要,导出都可以删除哈  
12 -@Schema(description = "管理后台 - 拼团活动 Excel 导出 Request VO,参数和 CombinationActivityPageReqVO 是一致的")  
13 -@Data  
14 -public class CombinationActivityExportReqVO {  
15 -  
16 - @Schema(description = "拼团名称", example = "赵六")  
17 - private String name;  
18 -  
19 - @Schema(description = "商品 SPU 编号关联 ProductSpuDO 的 id", example = "14016")  
20 - private Long spuId;  
21 -  
22 - @Schema(description = "总限购数量", example = "16218")  
23 - private Integer totalLimitCount;  
24 -  
25 - @Schema(description = "单次限购数量", example = "28265")  
26 - private Integer singleLimitCount;  
27 -  
28 - @Schema(description = "开始时间")  
29 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
30 - private LocalDateTime[] startTime;  
31 -  
32 - @Schema(description = "结束时间")  
33 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
34 - private LocalDateTime[] endTime;  
35 -  
36 - @Schema(description = "开团人数")  
37 - private Integer userSize;  
38 -  
39 - @Schema(description = "开团组数")  
40 - private Integer totalNum;  
41 -  
42 - @Schema(description = "成团组数")  
43 - private Integer successNum;  
44 -  
45 - @Schema(description = "参与人数", example = "25222")  
46 - private Integer orderUserCount;  
47 -  
48 - @Schema(description = "虚拟成团")  
49 - private Integer virtualGroup;  
50 -  
51 - @Schema(description = "活动状态:0开启 1关闭", example = "0")  
52 - private Integer status;  
53 -  
54 - @Schema(description = "限制时长(小时)")  
55 - private Integer limitDuration;  
56 -  
57 - @Schema(description = "创建时间")  
58 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
59 - private LocalDateTime[] createTime;  
60 -  
61 -}  
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductExcelVO.java deleted
1 -package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;  
2 -  
3 -import com.alibaba.excel.annotation.ExcelProperty;  
4 -import lombok.Data;  
5 -  
6 -import java.time.LocalDateTime;  
7 -  
8 -// TODO @puhui999:可以考虑删除 excel 导出哈  
9 -/**  
10 - * 拼团商品 Excel VO  
11 - *  
12 - * @author HUIHUI  
13 - */  
14 -@Data  
15 -public class CombinationProductExcelVO {  
16 -  
17 - @ExcelProperty("编号")  
18 - private Long id;  
19 -  
20 - @ExcelProperty("拼团活动编号")  
21 - private Long activityId;  
22 -  
23 - @ExcelProperty("商品 SPU 编号")  
24 - private Long spuId;  
25 -  
26 - @ExcelProperty("商品 SKU 编号")  
27 - private Long skuId;  
28 -  
29 - @ExcelProperty("拼团商品状态")  
30 - private Integer activityStatus;  
31 -  
32 - @ExcelProperty("活动开始时间点")  
33 - private LocalDateTime activityStartTime;  
34 -  
35 - @ExcelProperty("活动结束时间点")  
36 - private LocalDateTime activityEndTime;  
37 -  
38 - @ExcelProperty("拼团价格,单位分")  
39 - private Integer activePrice;  
40 -  
41 - @ExcelProperty("创建时间")  
42 - private LocalDateTime createTime;  
43 -  
44 -}  
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductExportReqVO.java deleted
1 -package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;  
2 -  
3 -import io.swagger.v3.oas.annotations.media.Schema;  
4 -import lombok.Data;  
5 -import org.springframework.format.annotation.DateTimeFormat;  
6 -  
7 -import java.time.LocalDateTime;  
8 -  
9 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;  
10 -  
11 -// TODO @puhui999:可以考虑删除 excel 导出哈  
12 -@Schema(description = "管理后台 - 拼团商品 Excel 导出 Request VO,参数和 CombinationProductPageReqVO 是一致的")  
13 -@Data  
14 -public class CombinationProductExportReqVO {  
15 -  
16 - @Schema(description = "拼团活动编号", example = "6829")  
17 - private Long activityId;  
18 -  
19 - @Schema(description = "商品 SPU 编号", example = "18731")  
20 - private Long spuId;  
21 -  
22 - @Schema(description = "商品 SKU 编号", example = "31675")  
23 - private Long skuId;  
24 -  
25 - @Schema(description = "拼团商品状态", example = "2")  
26 - private Integer activityStatus;  
27 -  
28 - @Schema(description = "活动开始时间点")  
29 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
30 - private LocalDateTime[] activityStartTime;  
31 -  
32 - @Schema(description = "活动结束时间点")  
33 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
34 - private LocalDateTime[] activityEndTime;  
35 -  
36 - @Schema(description = "拼团价格,单位分", example = "27682")  
37 - private Integer activePrice;  
38 -  
39 - @Schema(description = "创建时间")  
40 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
41 - private LocalDateTime[] createTime;  
42 -  
43 -}  
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java
@@ -85,7 +85,7 @@ public class SeckillActivityController { @@ -85,7 +85,7 @@ public class SeckillActivityController {
85 @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')") 85 @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")
86 public CommonResult<List<SeckillActivityRespVO>> getSeckillActivityList(@RequestParam("ids") Collection<Long> ids) { 86 public CommonResult<List<SeckillActivityRespVO>> getSeckillActivityList(@RequestParam("ids") Collection<Long> ids) {
87 List<SeckillActivityDO> list = seckillActivityService.getSeckillActivityList(ids); 87 List<SeckillActivityDO> list = seckillActivityService.getSeckillActivityList(ids);
88 - return success(SeckillActivityConvert.INSTANCE.convertList(list)); 88 + return success(SeckillActivityConvert.INSTANCE.complementList(list));
89 } 89 }
90 90
91 @GetMapping("/page") 91 @GetMapping("/page")
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill;
2 2
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.*; 6 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.*;
@@ -80,7 +81,7 @@ public class SeckillConfigController { @@ -80,7 +81,7 @@ public class SeckillConfigController {
80 @GetMapping("/list-all-simple") 81 @GetMapping("/list-all-simple")
81 @Operation(summary = "获得所有开启状态的秒杀时段精简列表", description = "主要用于前端的下拉选项") 82 @Operation(summary = "获得所有开启状态的秒杀时段精简列表", description = "主要用于前端的下拉选项")
82 public CommonResult<List<SeckillConfigSimpleRespVO>> getListAllSimple() { 83 public CommonResult<List<SeckillConfigSimpleRespVO>> getListAllSimple() {
83 - List<SeckillConfigDO> list = seckillConfigService.getListAllSimple(); 84 + List<SeckillConfigDO> list = seckillConfigService.getSeckillConfigListByStatus(CommonStatusEnum.ENABLE.getStatus());
84 return success(SeckillConfigConvert.INSTANCE.convertList1(list)); 85 return success(SeckillConfigConvert.INSTANCE.convertList1(list));
85 } 86 }
86 87
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java
1 package cn.iocoder.yudao.module.promotion.convert.combination; 1 package cn.iocoder.yudao.module.promotion.convert.combination;
2 2
3 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
5 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; 5 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
6 -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO; 6 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
7 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO; 7 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
8 -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExcelVO;  
9 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityRespVO; 8 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityRespVO;
10 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO; 9 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
11 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO; 10 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO;
12 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductRespVO; 11 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductRespVO;
13 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO; 12 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO;
14 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;  
15 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO;  
16 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationRecordDO; 13 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
  14 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
  15 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
17 import org.mapstruct.Mapper; 16 import org.mapstruct.Mapper;
18 import org.mapstruct.Mapping; 17 import org.mapstruct.Mapping;
19 import org.mapstruct.Mappings; 18 import org.mapstruct.Mappings;
@@ -71,20 +70,18 @@ public interface CombinationActivityConvert { @@ -71,20 +70,18 @@ public interface CombinationActivityConvert {
71 return respVO; 70 return respVO;
72 } 71 }
73 72
74 - List<CombinationActivityRespVO> convertList(List<CombinationActivityDO> list); 73 + List<CombinationActivityRespVO> complementList(List<CombinationActivityDO> list);
75 74
76 PageResult<CombinationActivityRespVO> convertPage(PageResult<CombinationActivityDO> page); 75 PageResult<CombinationActivityRespVO> convertPage(PageResult<CombinationActivityDO> page);
77 76
78 default PageResult<CombinationActivityRespVO> convertPage(PageResult<CombinationActivityDO> page, 77 default PageResult<CombinationActivityRespVO> convertPage(PageResult<CombinationActivityDO> page,
79 List<CombinationProductDO> productList, 78 List<CombinationProductDO> productList,
80 List<ProductSpuRespDTO> spuList) { 79 List<ProductSpuRespDTO> spuList) {
81 - // TODO @puhui999:c -> c 可以去掉哈  
82 - Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId, c -> c); 80 + Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
83 PageResult<CombinationActivityRespVO> pageResult = convertPage(page); 81 PageResult<CombinationActivityRespVO> pageResult = convertPage(page);
84 pageResult.getList().forEach(item -> { 82 pageResult.getList().forEach(item -> {
85 - // TODO @puhui999:最好 MapUtils.findAndThen,万一没找到呢,啊哈哈。  
86 - item.setSpuName(spuMap.get(item.getSpuId()).getName());  
87 - item.setPicUrl(spuMap.get(item.getSpuId()).getPicUrl()); 83 + MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> item.setSpuName(spu.getName()));
  84 + MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl()));
88 item.setProducts(convertList2(productList)); 85 item.setProducts(convertList2(productList));
89 }); 86 });
90 return pageResult; 87 return pageResult;
@@ -92,8 +89,6 @@ public interface CombinationActivityConvert { @@ -92,8 +89,6 @@ public interface CombinationActivityConvert {
92 89
93 List<CombinationProductRespVO> convertList2(List<CombinationProductDO> productDOs); 90 List<CombinationProductRespVO> convertList2(List<CombinationProductDO> productDOs);
94 91
95 - List<CombinationActivityExcelVO> convertList02(List<CombinationActivityDO> list);  
96 -  
97 @Mappings({ 92 @Mappings({
98 @Mapping(target = "id", ignore = true), 93 @Mapping(target = "id", ignore = true),
99 @Mapping(target = "activityId", source = "activityDO.id"), 94 @Mapping(target = "activityId", source = "activityDO.id"),
@@ -105,34 +100,28 @@ public interface CombinationActivityConvert { @@ -105,34 +100,28 @@ public interface CombinationActivityConvert {
105 }) 100 })
106 CombinationProductDO convert(CombinationActivityDO activityDO, CombinationProductBaseVO vo); 101 CombinationProductDO convert(CombinationActivityDO activityDO, CombinationProductBaseVO vo);
107 102
108 - default List<CombinationProductDO> convertList(CombinationActivityDO activityDO, List<? extends CombinationProductBaseVO> products) { 103 + default List<CombinationProductDO> complementList(List<? extends CombinationProductBaseVO> products, CombinationActivityDO activityDO) {
109 List<CombinationProductDO> list = new ArrayList<>(); 104 List<CombinationProductDO> list = new ArrayList<>();
110 products.forEach(sku -> { 105 products.forEach(sku -> {
111 CombinationProductDO productDO = convert(activityDO, sku); 106 CombinationProductDO productDO = convert(activityDO, sku);
112 - // TODO 状态设置  
113 - productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus()); 107 + productDO.setActivityStatus(activityDO.getStatus());
114 list.add(productDO); 108 list.add(productDO);
115 }); 109 });
116 return list; 110 return list;
117 } 111 }
118 112
119 - // TODO @puhui999:这个方法的参数,调整成 productDOs、vos、activityDO;因为 productDOs 是主角;  
120 - // 然后,这个方法,感觉不是为了 convert,而是为了补全;  
121 - default List<CombinationProductDO> convertList1(CombinationActivityDO activityDO,  
122 - List<CombinationProductUpdateReqVO> vos,  
123 - List<CombinationProductDO> productDOs) { 113 + default List<CombinationProductDO> complementList(List<CombinationProductDO> productDOs, List<CombinationProductUpdateReqVO> vos, CombinationActivityDO activityDO) {
124 Map<Long, Long> longMap = convertMap(productDOs, CombinationProductDO::getSkuId, CombinationProductDO::getId); 114 Map<Long, Long> longMap = convertMap(productDOs, CombinationProductDO::getSkuId, CombinationProductDO::getId);
125 List<CombinationProductDO> list = new ArrayList<>(); 115 List<CombinationProductDO> list = new ArrayList<>();
126 vos.forEach(sku -> { 116 vos.forEach(sku -> {
127 CombinationProductDO productDO = convert(activityDO, sku); 117 CombinationProductDO productDO = convert(activityDO, sku);
128 productDO.setId(longMap.get(sku.getSkuId())); 118 productDO.setId(longMap.get(sku.getSkuId()));
129 - // TODO @puhui999:是是不是用 activityDO 的状态;  
130 - productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus()); 119 + productDO.setActivityStatus(activityDO.getStatus());
131 list.add(productDO); 120 list.add(productDO);
132 }); 121 });
133 return list; 122 return list;
134 } 123 }
135 124
136 - CombinationRecordDO convert(CombinationRecordReqDTO reqDTO); 125 + CombinationRecordDO convert(CombinationRecordCreateReqDTO reqDTO);
137 126
138 } 127 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java
1 package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity; 1 package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity;
2 2
3 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 4 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
6 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; 5 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
@@ -38,7 +37,7 @@ public interface SeckillActivityConvert { @@ -38,7 +37,7 @@ public interface SeckillActivityConvert {
38 37
39 SeckillActivityRespVO convert(SeckillActivityDO bean); 38 SeckillActivityRespVO convert(SeckillActivityDO bean);
40 39
41 - List<SeckillActivityRespVO> convertList(List<SeckillActivityDO> list); 40 + List<SeckillActivityRespVO> complementList(List<SeckillActivityDO> list);
42 41
43 PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page); 42 PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page);
44 43
@@ -74,24 +73,23 @@ public interface SeckillActivityConvert { @@ -74,24 +73,23 @@ public interface SeckillActivityConvert {
74 }) 73 })
75 SeckillProductDO convert(SeckillActivityDO activityDO, SeckillProductBaseVO vo); 74 SeckillProductDO convert(SeckillActivityDO activityDO, SeckillProductBaseVO vo);
76 75
77 - default List<SeckillProductDO> convertList(SeckillActivityDO activityDO, List<? extends SeckillProductBaseVO> products) { 76 + default List<SeckillProductDO> complementList(List<? extends SeckillProductBaseVO> products, SeckillActivityDO activityDO) {
78 List<SeckillProductDO> list = new ArrayList<>(); 77 List<SeckillProductDO> list = new ArrayList<>();
79 products.forEach(sku -> { 78 products.forEach(sku -> {
80 SeckillProductDO productDO = convert(activityDO, sku); 79 SeckillProductDO productDO = convert(activityDO, sku);
81 - productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus()); 80 + productDO.setActivityStatus(activityDO.getStatus());
82 list.add(productDO); 81 list.add(productDO);
83 }); 82 });
84 return list; 83 return list;
85 } 84 }
86 85
87 - // TODO @puhui999:同拼团那个 convert 想通的情况哈。  
88 - default List<SeckillProductDO> convertList1(SeckillActivityDO activityDO, List<SeckillProductUpdateReqVO> vos, List<SeckillProductDO> productDOs) { 86 + default List<SeckillProductDO> complementList(List<SeckillProductDO> productDOs, List<SeckillProductUpdateReqVO> vos, SeckillActivityDO activityDO) {
89 Map<Long, Long> longMap = CollectionUtils.convertMap(productDOs, SeckillProductDO::getSkuId, SeckillProductDO::getId); 87 Map<Long, Long> longMap = CollectionUtils.convertMap(productDOs, SeckillProductDO::getSkuId, SeckillProductDO::getId);
90 List<SeckillProductDO> list = new ArrayList<>(); 88 List<SeckillProductDO> list = new ArrayList<>();
91 vos.forEach(sku -> { 89 vos.forEach(sku -> {
92 SeckillProductDO productDO = convert(activityDO, sku); 90 SeckillProductDO productDO = convert(activityDO, sku);
93 productDO.setId(longMap.get(sku.getSkuId())); 91 productDO.setId(longMap.get(sku.getSkuId()));
94 - productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus()); 92 + productDO.setActivityStatus(activityDO.getStatus());
95 list.add(productDO); 93 list.add(productDO);
96 }); 94 });
97 return list; 95 return list;
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/bargain/BargainActivityDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.dal.dataobject.bargain;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import com.baomidou.mybatisplus.annotation.KeySequence;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +import com.baomidou.mybatisplus.annotation.TableName;
  7 +import lombok.*;
  8 +
  9 +import java.time.LocalDateTime;
  10 +
  11 +/**
  12 + * 砍价活动 DO
  13 + *
  14 + * @author HUIHUI
  15 + */
  16 +@TableName("promotion_bargain_activity")
  17 +@KeySequence("promotion_bargain_activity_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  18 +@Data
  19 +@EqualsAndHashCode(callSuper = true)
  20 +@ToString(callSuper = true)
  21 +@Builder
  22 +@NoArgsConstructor
  23 +@AllArgsConstructor
  24 +public class BargainActivityDO extends BaseDO {
  25 +
  26 + /**
  27 + * 砍价活动编号
  28 + */
  29 + @TableId
  30 + private Long id;
  31 +
  32 + /**
  33 + * 砍价活动名称
  34 + */
  35 + private String name;
  36 +
  37 + /**
  38 + * 活动开始时间
  39 + */
  40 + private LocalDateTime startTime;
  41 +
  42 + /**
  43 + * 活动结束时间
  44 + */
  45 + private LocalDateTime endTime;
  46 +
  47 + /**
  48 + * 活动状态
  49 + */
  50 + private Integer status;
  51 +
  52 + /**
  53 + * 商品 SPU 编号
  54 + */
  55 + private Long spuId;
  56 +
  57 + /**
  58 + * 商品 SKU 编号
  59 + */
  60 + private Long skuId;
  61 +
  62 + /**
  63 + * 应付金额,单位分
  64 + */
  65 + private Integer bargainFirstPrice;
  66 +
  67 + /**
  68 + * 砍价底价,单位:分
  69 + */
  70 + private Integer bargainPrice;
  71 +
  72 + /**
  73 + * 达到该人数,才能砍到低价
  74 + */
  75 + private Integer userSize;
  76 +
  77 + /**
  78 + * 最大帮砍次数
  79 + */
  80 + private Integer bargainCount;
  81 +
  82 + /**
  83 + * 砍价库存
  84 + */
  85 + private Integer stock;
  86 +
  87 + /**
  88 + * 用户每次砍价的最小金额,单位:分
  89 + */
  90 + private Integer randomMinPrice;
  91 +
  92 + /**
  93 + * 用户每次砍价的最大金额,单位:分
  94 + */
  95 + private Integer randomMaxPrice;
  96 +
  97 + /**
  98 + * 砍价成功数量
  99 + */
  100 + private Integer successCount;
  101 +
  102 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDeliveryDO.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/bargain/BargainAssistDO.java
1 -package cn.iocoder.yudao.module.trade.dal.dataobject.order; 1 +package cn.iocoder.yudao.module.promotion.dal.dataobject.bargain;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 -import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;  
5 import com.baomidou.mybatisplus.annotation.KeySequence; 4 import com.baomidou.mybatisplus.annotation.KeySequence;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
6 import com.baomidou.mybatisplus.annotation.TableName; 6 import com.baomidou.mybatisplus.annotation.TableName;
7 import lombok.*; 7 import lombok.*;
8 8
9 -// TODO @puhui999:  
10 /** 9 /**
11 - * 交易订单发货记录 DO 10 + * 砍价助力 DO
12 * 11 *
13 * @author HUIHUI 12 * @author HUIHUI
14 */ 13 */
15 -@TableName("trade_order_delivery")  
16 -@KeySequence("trade_order_delivery_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 14 +@TableName("promotion_bargain_assist")
  15 +@KeySequence("promotion_bargain_assist_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
17 @Data 16 @Data
18 @EqualsAndHashCode(callSuper = true) 17 @EqualsAndHashCode(callSuper = true)
19 @ToString(callSuper = true) 18 @ToString(callSuper = true)
20 @Builder 19 @Builder
21 @NoArgsConstructor 20 @NoArgsConstructor
22 @AllArgsConstructor 21 @AllArgsConstructor
23 -public class TradeOrderDeliveryDO extends BaseDO { 22 +public class BargainAssistDO extends BaseDO {
24 23
25 /** 24 /**
26 - * 订单发货记录 id 25 + * 编号
27 */ 26 */
  27 + @TableId
28 private Long id; 28 private Long id;
  29 +
29 /** 30 /**
30 - * 订单 id 31 + * 砍价活动编号
31 */ 32 */
32 - private Long orderId; 33 + private Long activityId;
  34 +
33 /** 35 /**
34 - * 订单项 id TODO 要不要一个发货记录可对应多个订单项? 36 + * 砍价记录编号
35 */ 37 */
36 - private Long orderItemId; 38 + private Long recordId;
  39 +
37 /** 40 /**
38 * 用户编号 41 * 用户编号
39 - *  
40 - * 关联 MemberUserDO 的 id 编号  
41 */ 42 */
42 private Long userId; 43 private Long userId;
  44 +
43 /** 45 /**
44 - * 配送方式  
45 - *  
46 - * 枚举 {@link DeliveryTypeEnum}  
47 - */  
48 - private Integer deliveryType;  
49 - /**  
50 - * 发货物流公司编号  
51 - */  
52 - private Long logisticsId;  
53 - /**  
54 - * 发货物流单号 46 + * 减少价格。单位分
55 */ 47 */
56 - private String logisticsNo;  
57 -  
58 - // TODO 同城配送 48 + private Integer reducePrice;
59 49
60 } 50 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/bargain/BargainRecordDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.dal.dataobject.bargain;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import com.baomidou.mybatisplus.annotation.KeySequence;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +import com.baomidou.mybatisplus.annotation.TableName;
  7 +import lombok.*;
  8 +
  9 +import java.time.LocalDateTime;
  10 +
  11 +/**
  12 + * 砍价记录 DO
  13 + *
  14 + * @author HUIHUI
  15 + */
  16 +@TableName("promotion_bargain_record")
  17 +@KeySequence("promotion_bargain_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  18 +@Data
  19 +@EqualsAndHashCode(callSuper = true)
  20 +@ToString(callSuper = true)
  21 +@Builder
  22 +@NoArgsConstructor
  23 +@AllArgsConstructor
  24 +public class BargainRecordDO extends BaseDO {
  25 +
  26 + /**
  27 + * 编号
  28 + */
  29 + @TableId
  30 + private Long id;
  31 +
  32 + /**
  33 + * 砍价活动编号
  34 + */
  35 + private Long activityId;
  36 +
  37 + /**
  38 + * 用户编号
  39 + */
  40 + private Long userId;
  41 +
  42 + /**
  43 + * 商品 SPU 编号
  44 + */
  45 + private Long spuId;
  46 +
  47 + /**
  48 + * 商品 SKU 编号
  49 + */
  50 + private Long skuId;
  51 +
  52 + /**
  53 + * 砍价底价,单位分
  54 + */
  55 + private Integer bargainPrice;
  56 +
  57 + /**
  58 + * 商品原价,单位分
  59 + */
  60 + private Integer price;
  61 +
  62 + /**
  63 + * 应付金额,单位分
  64 + */
  65 + private Integer payPrice;
  66 +
  67 + /**
  68 + * 状态1 - 砍价中;2- 砍价成功;3 - 砍价失败
  69 + */
  70 + private Integer status;
  71 +
  72 + /**
  73 + * 订单编号
  74 + */
  75 + private Long orderId;
  76 +
  77 + /**
  78 + * 结束时间
  79 + */
  80 + private LocalDateTime endTime;
  81 +
  82 + /**
  83 + * 过期时间
  84 + */
  85 + private Data expireTime;
  86 +
  87 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationActivityDO.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationActivityDO.java
1 -package cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity; 1 +package cn.iocoder.yudao.module.promotion.dal.dataobject.combination;
2 2
3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
@@ -9,7 +9,6 @@ import lombok.*; @@ -9,7 +9,6 @@ import lombok.*;
9 9
10 import java.time.LocalDateTime; 10 import java.time.LocalDateTime;
11 11
12 -// TODO @puhui999:是不是应该在 combination 哈?  
13 /** 12 /**
14 * 拼团活动 DO 13 * 拼团活动 DO
15 * 14 *
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationProductDO.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationProductDO.java
1 -package cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity; 1 +package cn.iocoder.yudao.module.promotion.dal.dataobject.combination;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 import com.baomidou.mybatisplus.annotation.KeySequence; 4 import com.baomidou.mybatisplus.annotation.KeySequence;
@@ -42,6 +42,8 @@ public class CombinationProductDO extends BaseDO { @@ -42,6 +42,8 @@ public class CombinationProductDO extends BaseDO {
42 private Long skuId; 42 private Long skuId;
43 /** 43 /**
44 * 拼团商品状态 44 * 拼团商品状态
  45 + *
  46 + * 关联 {@link CombinationActivityDO#getStatus()}
45 */ 47 */
46 private Integer activityStatus; 48 private Integer activityStatus;
47 /** 49 /**
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationRecordDO.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java
1 -package cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity; 1 +package cn.iocoder.yudao.module.promotion.dal.dataobject.combination;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; 4 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationActivityMapper.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationActivityMapper.java
1 -package cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity; 1 +package cn.iocoder.yudao.module.promotion.dal.mysql.combination;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExportReqVO;  
7 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; 6 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
8 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO; 7 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
9 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
10 9
11 import java.util.List; 10 import java.util.List;
12 11
13 -// TODO @puhui999:是不是应该在 combination 哈?  
14 /** 12 /**
15 * 拼团活动 Mapper 13 * 拼团活动 Mapper
16 * 14 *
@@ -25,13 +23,6 @@ public interface CombinationActivityMapper extends BaseMapperX&lt;CombinationActivi @@ -25,13 +23,6 @@ public interface CombinationActivityMapper extends BaseMapperX&lt;CombinationActivi
25 .orderByDesc(CombinationActivityDO::getId)); 23 .orderByDesc(CombinationActivityDO::getId));
26 } 24 }
27 25
28 - default List<CombinationActivityDO> selectList(CombinationActivityExportReqVO reqVO) {  
29 - return selectList(new LambdaQueryWrapperX<CombinationActivityDO>()  
30 - .likeIfPresent(CombinationActivityDO::getName, reqVO.getName())  
31 - .eqIfPresent(CombinationActivityDO::getStatus, reqVO.getStatus())  
32 - .orderByDesc(CombinationActivityDO::getId));  
33 - }  
34 -  
35 default List<CombinationActivityDO> selectListByStatus(Integer status) { 26 default List<CombinationActivityDO> selectListByStatus(Integer status) {
36 return selectList(CombinationActivityDO::getStatus, status); 27 return selectList(CombinationActivityDO::getStatus, status);
37 } 28 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationProductMapper.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationProductMapper.java
1 -package cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity; 1 +package cn.iocoder.yudao.module.promotion.dal.mysql.combination;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductExportReqVO;  
7 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductPageReqVO; 6 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductPageReqVO;
8 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO; 7 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
9 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
10 9
11 import java.util.Collection; 10 import java.util.Collection;
@@ -32,19 +31,6 @@ public interface CombinationProductMapper extends BaseMapperX&lt;CombinationProduct @@ -32,19 +31,6 @@ public interface CombinationProductMapper extends BaseMapperX&lt;CombinationProduct
32 .orderByDesc(CombinationProductDO::getId)); 31 .orderByDesc(CombinationProductDO::getId));
33 } 32 }
34 33
35 - default List<CombinationProductDO> selectList(CombinationProductExportReqVO reqVO) {  
36 - return selectList(new LambdaQueryWrapperX<CombinationProductDO>()  
37 - .eqIfPresent(CombinationProductDO::getActivityId, reqVO.getActivityId())  
38 - .eqIfPresent(CombinationProductDO::getSpuId, reqVO.getSpuId())  
39 - .eqIfPresent(CombinationProductDO::getSkuId, reqVO.getSkuId())  
40 - .eqIfPresent(CombinationProductDO::getActivityStatus, reqVO.getActivityStatus())  
41 - .betweenIfPresent(CombinationProductDO::getActivityStartTime, reqVO.getActivityStartTime())  
42 - .betweenIfPresent(CombinationProductDO::getActivityEndTime, reqVO.getActivityEndTime())  
43 - .eqIfPresent(CombinationProductDO::getActivePrice, reqVO.getActivePrice())  
44 - .betweenIfPresent(CombinationProductDO::getCreateTime, reqVO.getCreateTime())  
45 - .orderByDesc(CombinationProductDO::getId));  
46 - }  
47 -  
48 default List<CombinationProductDO> selectListByActivityIds(Collection<Long> ids) { 34 default List<CombinationProductDO> selectListByActivityIds(Collection<Long> ids) {
49 return selectList(CombinationProductDO::getActivityId, ids); 35 return selectList(CombinationProductDO::getActivityId, ids);
50 } 36 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationRecordMapper.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java
1 -package cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity; 1 +package cn.iocoder.yudao.module.promotion.dal.mysql.combination;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
4 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
5 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationRecordDO; 5 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
6 import org.apache.ibatis.annotations.Mapper; 6 import org.apache.ibatis.annotations.Mapper;
7 7
8 import java.util.List; 8 import java.util.List;
@@ -20,6 +20,18 @@ public interface CombinationRecordMapper extends BaseMapperX&lt;CombinationRecordDO @@ -20,6 +20,18 @@ public interface CombinationRecordMapper extends BaseMapperX&lt;CombinationRecordDO
20 CombinationRecordDO::getOrderId, orderId); 20 CombinationRecordDO::getOrderId, orderId);
21 } 21 }
22 22
  23 + /**
  24 + * 查询拼团记录
  25 + *
  26 + * @param headId 团长编号
  27 + * @param activityId 活动编号
  28 + * @return 拼团记录
  29 + */
  30 + default CombinationRecordDO selectRecordByHeadId(Long headId, Long activityId, Integer status) {
  31 + return selectOne(CombinationRecordDO::getUserId, headId, CombinationRecordDO::getActivityId, activityId,
  32 + CombinationRecordDO::getStatus, status);
  33 + }
  34 +
23 default List<CombinationRecordDO> selectListByHeadIdAndStatus(Long headId, Integer status) { 35 default List<CombinationRecordDO> selectListByHeadIdAndStatus(Long headId, Integer status) {
24 return selectList(new LambdaQueryWrapperX<CombinationRecordDO>() 36 return selectList(new LambdaQueryWrapperX<CombinationRecordDO>()
25 .eq(CombinationRecordDO::getHeadId, headId) 37 .eq(CombinationRecordDO::getHeadId, headId)
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java
1 package cn.iocoder.yudao.module.promotion.service.combination; 1 package cn.iocoder.yudao.module.promotion.service.combination;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO;  
5 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO; 4 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
6 -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExportReqVO;  
7 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; 5 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
8 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO; 6 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
9 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;  
10 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO; 7 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
  8 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
11 9
12 import javax.validation.Valid; 10 import javax.validation.Valid;
13 -import java.time.LocalDateTime;  
14 import java.util.Collection; 11 import java.util.Collection;
15 import java.util.List; 12 import java.util.List;
16 13
@@ -68,14 +65,6 @@ public interface CombinationActivityService { @@ -68,14 +65,6 @@ public interface CombinationActivityService {
68 PageResult<CombinationActivityDO> getCombinationActivityPage(CombinationActivityPageReqVO pageReqVO); 65 PageResult<CombinationActivityDO> getCombinationActivityPage(CombinationActivityPageReqVO pageReqVO);
69 66
70 /** 67 /**
71 - * 获得拼团活动列表, 用于 Excel 导出  
72 - *  
73 - * @param exportReqVO 查询条件  
74 - * @return 拼团活动列表  
75 - */  
76 - List<CombinationActivityDO> getCombinationActivityList(CombinationActivityExportReqVO exportReqVO);  
77 -  
78 - /**  
79 * 获得拼团活动商品列表 68 * 获得拼团活动商品列表
80 * 69 *
81 * @param ids 拼团活动 ids 70 * @param ids 拼团活动 ids
@@ -83,41 +72,4 @@ public interface CombinationActivityService { @@ -83,41 +72,4 @@ public interface CombinationActivityService {
83 */ 72 */
84 List<CombinationProductDO> getProductsByActivityIds(Collection<Long> ids); 73 List<CombinationProductDO> getProductsByActivityIds(Collection<Long> ids);
85 74
86 - // TODO @puhui999:拆一个 CombinationRecordService 里,方法名可以简洁成 updateRecordStatusByOrderId;service 方法可以稍微简单一点,如果是 update 方法  
87 - /**  
88 - * 更新拼团状态  
89 - *  
90 - * @param userId 用户编号  
91 - * @param orderId 订单编号  
92 - * @param status 状态  
93 - */  
94 - void updateRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status);  
95 -  
96 - /**  
97 - * 更新拼团状态和开始时间  
98 - *  
99 - * @param userId 用户编号  
100 - * @param orderId 订单编号  
101 - * @param status 状态  
102 - * @param startTime 开始时间  
103 - */  
104 - void updateRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId, Integer status, LocalDateTime startTime);  
105 -  
106 - // TODO @puhui999:拆一个 CombinationRecordService 里  
107 - /**  
108 - * 创建拼团记录  
109 - *  
110 - * @param reqDTO 创建信息  
111 - */  
112 - void createRecord(CombinationRecordReqDTO reqDTO);  
113 -  
114 - /**  
115 - * 获得拼团状态  
116 - *  
117 - * @param userId 用户编号  
118 - * @param orderId 订单编号  
119 - * @return 拼团状态  
120 - */  
121 - boolean validateRecordStatusIsSuccess(Long userId, Long orderId);  
122 -  
123 } 75 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.service.combination;
  2 +
  3 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
  4 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
  5 +
  6 +import java.time.LocalDateTime;
  7 +
  8 +/**
  9 + * 商品活动记录 service
  10 + *
  11 + * @author HUIHUI
  12 + */
  13 +public interface CombinationRecordService {
  14 +
  15 + /**
  16 + * 更新拼团状态
  17 + *
  18 + * @param userId 用户编号
  19 + * @param orderId 订单编号
  20 + * @param status 状态
  21 + */
  22 + void updateRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status);
  23 +
  24 + /**
  25 + * 创建拼团记录
  26 + *
  27 + * @param reqDTO 创建信息
  28 + */
  29 + void createRecord(CombinationRecordCreateReqDTO reqDTO);
  30 +
  31 + /**
  32 + * 更新拼团状态和开始时间
  33 + *
  34 + * @param userId 用户编号
  35 + * @param orderId 订单编号
  36 + * @param status 状态
  37 + * @param startTime 开始时间
  38 + */
  39 + void updateRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId, Integer status, LocalDateTime startTime);
  40 +
  41 + /**
  42 + * 获得拼团状态
  43 + *
  44 + * @param userId 用户编号
  45 + * @param orderId 订单编号
  46 + * @return 拼团状态
  47 + */
  48 + CombinationRecordDO getRecord(Long userId, Long orderId);
  49 +
  50 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationServiceImpl.java
@@ -2,28 +2,29 @@ package cn.iocoder.yudao.module.promotion.service.combination; @@ -2,28 +2,29 @@ package cn.iocoder.yudao.module.promotion.service.combination;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.collection.CollectionUtil; 4 import cn.hutool.core.collection.CollectionUtil;
  5 +import cn.hutool.core.map.MapUtil;
5 import cn.hutool.core.util.ObjectUtil; 6 import cn.hutool.core.util.ObjectUtil;
6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 7 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
7 import cn.iocoder.yudao.framework.common.pojo.PageResult; 8 import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 9 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  10 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
9 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; 11 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
10 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; 12 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
11 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; 13 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
12 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; 14 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
13 -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO; 15 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
14 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO; 16 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
15 -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExportReqVO;  
16 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; 17 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
17 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO; 18 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
18 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductCreateReqVO; 19 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductCreateReqVO;
19 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO; 20 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO;
20 import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; 21 import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
21 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;  
22 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO;  
23 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationRecordDO;  
24 -import cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity.CombinationActivityMapper;  
25 -import cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity.CombinationProductMapper;  
26 -import cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity.CombinationRecordMapper; 22 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
  23 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
  24 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
  25 +import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationActivityMapper;
  26 +import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationProductMapper;
  27 +import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper;
27 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; 28 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
28 import org.springframework.stereotype.Service; 29 import org.springframework.stereotype.Service;
29 import org.springframework.transaction.annotation.Transactional; 30 import org.springframework.transaction.annotation.Transactional;
@@ -31,9 +32,7 @@ import org.springframework.validation.annotation.Validated; @@ -31,9 +32,7 @@ import org.springframework.validation.annotation.Validated;
31 32
32 import javax.annotation.Resource; 33 import javax.annotation.Resource;
33 import java.time.LocalDateTime; 34 import java.time.LocalDateTime;
34 -import java.util.Collection;  
35 -import java.util.List;  
36 -import java.util.Set; 35 +import java.util.*;
37 36
38 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 37 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
39 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; 38 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
@@ -47,7 +46,7 @@ import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProd @@ -47,7 +46,7 @@ import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProd
47 */ 46 */
48 @Service 47 @Service
49 @Validated 48 @Validated
50 -public class CombinationActivityServiceImpl implements CombinationActivityService { 49 +public class CombinationServiceImpl implements CombinationActivityService, CombinationRecordService {
51 50
52 @Resource 51 @Resource
53 private CombinationActivityMapper combinationActivityMapper; 52 private CombinationActivityMapper combinationActivityMapper;
@@ -67,7 +66,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @@ -67,7 +66,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
67 // 获取所选 spu下的所有 sku 66 // 获取所选 spu下的所有 sku
68 List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(createReqVO.getSpuId())); 67 List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(createReqVO.getSpuId()));
69 // 校验商品 sku 是否存在 68 // 校验商品 sku 是否存在
70 - validateProductSkuExistence(skus, createReqVO.getProducts(), CombinationProductCreateReqVO::getSkuId); 69 + validateProductSkuExistence(createReqVO.getProducts(), skus, CombinationProductCreateReqVO::getSkuId);
71 70
72 // TODO 艿艿 有个小问题:现在有活动时间和限制时长,活动时间的结束时间早于设置的限制时间怎么算状态比如: 71 // TODO 艿艿 有个小问题:现在有活动时间和限制时长,活动时间的结束时间早于设置的限制时间怎么算状态比如:
73 // 活动时间 2023-08-05 15:00:00 - 2023-08-05 15:20:00 限制时长 2小时,那么活动时间结束就结束还是加时到满两小时 72 // 活动时间 2023-08-05 15:00:00 - 2023-08-05 15:20:00 限制时长 2小时,那么活动时间结束就结束还是加时到满两小时
@@ -81,7 +80,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @@ -81,7 +80,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
81 activityDO.setStatus(CommonStatusEnum.ENABLE.getStatus()); 80 activityDO.setStatus(CommonStatusEnum.ENABLE.getStatus());
82 combinationActivityMapper.insert(activityDO); 81 combinationActivityMapper.insert(activityDO);
83 // 插入商品 82 // 插入商品
84 - List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.convertList(activityDO, createReqVO.getProducts()); 83 + List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.complementList(createReqVO.getProducts(), activityDO);
85 combinationProductMapper.insertBatch(productDOs); 84 combinationProductMapper.insertBatch(productDOs);
86 // 返回 85 // 返回
87 return activityDO.getId(); 86 return activityDO.getId();
@@ -119,7 +118,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @@ -119,7 +118,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
119 // 获取所选 spu下的所有 sku 118 // 获取所选 spu下的所有 sku
120 List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(updateReqVO.getSpuId())); 119 List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(updateReqVO.getSpuId()));
121 // 校验商品 sku 是否存在 120 // 校验商品 sku 是否存在
122 - validateProductSkuExistence(skus, updateReqVO.getProducts(), CombinationProductUpdateReqVO::getSkuId); 121 + validateProductSkuExistence(updateReqVO.getProducts(), skus, CombinationProductUpdateReqVO::getSkuId);
123 122
124 // 更新 123 // 更新
125 CombinationActivityDO updateObj = CombinationActivityConvert.INSTANCE.convert(updateReqVO); 124 CombinationActivityDO updateObj = CombinationActivityConvert.INSTANCE.convert(updateReqVO);
@@ -130,7 +129,6 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @@ -130,7 +129,6 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
130 129
131 /** 130 /**
132 * 更新秒杀商品 131 * 更新秒杀商品
133 - * TODO 更新商品要不要封装成通用方法  
134 * 132 *
135 * @param updateObj DO 133 * @param updateObj DO
136 * @param products 商品配置 134 * @param products 商品配置
@@ -141,25 +139,27 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @@ -141,25 +139,27 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
141 Set<Long> convertSet = CollectionUtils.convertSet(combinationProductDOs, CombinationProductDO::getSkuId); 139 Set<Long> convertSet = CollectionUtils.convertSet(combinationProductDOs, CombinationProductDO::getSkuId);
142 // 前端传过来的活动商品 140 // 前端传过来的活动商品
143 Set<Long> convertSet1 = CollectionUtils.convertSet(products, CombinationProductUpdateReqVO::getSkuId); 141 Set<Long> convertSet1 = CollectionUtils.convertSet(products, CombinationProductUpdateReqVO::getSkuId);
144 - // 删除后台存在的前端不存在的商品  
145 - List<Long> d = CollectionUtils.filterList(convertSet, item -> !convertSet1.contains(item));  
146 - if (CollUtil.isNotEmpty(d)) {  
147 - combinationProductMapper.deleteBatchIds(d);  
148 - }  
149 - // 前端存在的后端不存在的商品  
150 - List<Long> c = CollectionUtils.filterList(convertSet1, item -> !convertSet.contains(item));  
151 - if (CollUtil.isNotEmpty(c)) {  
152 - List<CombinationProductUpdateReqVO> vos = CollectionUtils.filterList(products, item -> c.contains(item.getSkuId()));  
153 - List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.convertList(updateObj, vos);  
154 - combinationProductMapper.insertBatch(productDOs);  
155 - }  
156 - // 更新已存在的商品  
157 - List<Long> u = CollectionUtils.filterList(convertSet1, convertSet::contains);  
158 - if (CollUtil.isNotEmpty(u)) {  
159 - List<CombinationProductUpdateReqVO> vos = CollectionUtils.filterList(products, item -> u.contains(item.getSkuId()));  
160 - List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.convertList1(updateObj, vos, combinationProductDOs);  
161 - combinationProductMapper.updateBatch(productDOs);  
162 - } 142 + // 分化数据
  143 + Map<String, List<CombinationProductDO>> data = CollectionUtils.convertCDUMap(convertSet1, convertSet, mapData -> {
  144 + HashMap<String, List<CombinationProductDO>> cdu = MapUtil.newHashMap(3);
  145 + MapUtils.findAndThen(mapData, "create", list -> {
  146 + cdu.put("create", CombinationActivityConvert.INSTANCE.complementList(CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj));
  147 + });
  148 + MapUtils.findAndThen(mapData, "delete", list -> {
  149 + cdu.put("create", CollectionUtils.filterList(combinationProductDOs, item -> list.contains(item.getSkuId())));
  150 + });
  151 + MapUtils.findAndThen(mapData, "update", list -> {
  152 + cdu.put("update", CombinationActivityConvert.INSTANCE.complementList(combinationProductDOs,
  153 + CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj));
  154 + });
  155 + return cdu;
  156 + });
  157 +
  158 + // 执行增删改
  159 + MapUtils.findAndThen(data, "create", item -> combinationProductMapper.insertBatch(item));
  160 + MapUtils.findAndThen(data, "delete", item -> combinationProductMapper.deleteBatchIds(
  161 + CollectionUtils.convertSet(item, CombinationProductDO::getId)));
  162 + MapUtils.findAndThen(data, "update", item -> combinationProductMapper.updateBatch(item));
163 } 163 }
164 164
165 @Override 165 @Override
@@ -199,11 +199,6 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @@ -199,11 +199,6 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
199 } 199 }
200 200
201 @Override 201 @Override
202 - public List<CombinationActivityDO> getCombinationActivityList(CombinationActivityExportReqVO exportReqVO) {  
203 - return combinationActivityMapper.selectList(exportReqVO);  
204 - }  
205 -  
206 - @Override  
207 public List<CombinationProductDO> getProductsByActivityIds(Collection<Long> ids) { 202 public List<CombinationProductDO> getProductsByActivityIds(Collection<Long> ids) {
208 return combinationProductMapper.selectListByActivityIds(ids); 203 return combinationProductMapper.selectListByActivityIds(ids);
209 } 204 }
@@ -234,7 +229,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @@ -234,7 +229,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
234 recordDOs.forEach(item -> { 229 recordDOs.forEach(item -> {
235 item.setUserCount(recordDOs.size()); 230 item.setUserCount(recordDOs.size());
236 // 校验拼团是否满足要求 231 // 校验拼团是否满足要求
237 - if (recordDOs.size() >= recordDO.getUserSize()) { 232 + if (ObjectUtil.equal(recordDOs.size(), recordDO.getUserSize())) {
238 item.setStatus(CombinationRecordStatusEnum.SUCCESS.getStatus()); 233 item.setStatus(CombinationRecordStatusEnum.SUCCESS.getStatus());
239 } 234 }
240 }); 235 });
@@ -252,13 +247,30 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @@ -252,13 +247,30 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
252 } 247 }
253 248
254 @Override 249 @Override
255 - public void createRecord(CombinationRecordReqDTO reqDTO) { 250 + public void createRecord(CombinationRecordCreateReqDTO reqDTO) {
256 // 校验拼团活动 251 // 校验拼团活动
257 CombinationActivityDO activity = validateCombinationActivityExists(reqDTO.getActivityId()); 252 CombinationActivityDO activity = validateCombinationActivityExists(reqDTO.getActivityId());
258 - // TODO @puhui999:需要校验下,它当前是不是已经参加了该拼团;  
259 - // TODO @puhui999: 父拼团是否存在,是否已经满了 253 + // 需要校验下,它当前是不是已经参加了该拼团;
  254 + CombinationRecordDO recordDO = recordMapper.selectRecord(reqDTO.getUserId(), reqDTO.getOrderId());
  255 + if (recordDO != null) {
  256 + throw exception(COMBINATION_RECORD_EXISTS);
  257 + }
  258 + // 父拼团是否存在,是否已经满了
  259 + if (reqDTO.getHeadId() != null) {
  260 + CombinationRecordDO recordDO1 = recordMapper.selectRecordByHeadId(reqDTO.getHeadId(), reqDTO.getActivityId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
  261 + if (recordDO1 == null) {
  262 + throw exception(COMBINATION_RECORD_HEAD_NOT_EXISTS);
  263 + }
  264 + // 校验拼团是否满足要求
  265 + if (ObjectUtil.equal(recordDO1.getUserCount(), recordDO1.getUserSize())) {
  266 + throw exception(COMBINATION_RECORD_USER_FULL);
  267 + }
  268 + }
260 269
261 CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO); 270 CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO);
  271 + if (reqDTO.getHeadId() == null) {
  272 + record.setHeadId(reqDTO.getUserId());
  273 + }
262 record.setVirtualGroup(false); 274 record.setVirtualGroup(false);
263 // TODO @puhui999:过期时间,应该是 Date 哈; 275 // TODO @puhui999:过期时间,应该是 Date 哈;
264 record.setExpireTime(activity.getLimitDuration()); 276 record.setExpireTime(activity.getLimitDuration());
@@ -267,20 +279,17 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @@ -267,20 +279,17 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
267 } 279 }
268 280
269 @Override 281 @Override
270 - public boolean validateRecordStatusIsSuccess(Long userId, Long orderId) {  
271 - CombinationRecordDO record = validateCombinationRecord(userId, orderId);  
272 - // TODO @puhui999:可以搞个 getRecrod 方法,然后业务通过 CombinationRecordStatusEnum.isSuccess 方法校验  
273 - return ObjectUtil.equal(record.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus()); 282 + public CombinationRecordDO getRecord(Long userId, Long orderId) {
  283 + return validateCombinationRecord(userId, orderId);
274 } 284 }
275 285
276 - // TODO @puhui999:status 传入进来搞哈;  
277 /** 286 /**
278 * APP 端获取开团记录 287 * APP 端获取开团记录
279 * 288 *
280 * @return 开团记录 289 * @return 开团记录
281 */ 290 */
282 - public List<CombinationRecordDO> getRecordList() {  
283 - return recordMapper.selectListByStatus(CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); 291 + public List<CombinationRecordDO> getRecordListByStatus(Integer status) {
  292 + return recordMapper.selectListByStatus(status);
284 } 293 }
285 294
286 } 295 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java
1 package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity; 1 package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.map.MapUtil;
4 import cn.hutool.core.util.ObjectUtil; 5 import cn.hutool.core.util.ObjectUtil;
5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 8 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  9 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
8 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; 10 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
9 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; 11 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
10 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; 12 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
@@ -26,11 +28,10 @@ import org.springframework.transaction.annotation.Transactional; @@ -26,11 +28,10 @@ import org.springframework.transaction.annotation.Transactional;
26 import org.springframework.validation.annotation.Validated; 28 import org.springframework.validation.annotation.Validated;
27 29
28 import javax.annotation.Resource; 30 import javax.annotation.Resource;
29 -import java.util.Collection;  
30 -import java.util.List;  
31 -import java.util.Set; 31 +import java.util.*;
32 32
33 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 33 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  34 +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
34 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; 35 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
35 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; 36 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
36 import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuExistence; 37 import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuExistence;
@@ -63,8 +64,9 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -63,8 +64,9 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
63 // 获取所选 spu 下的所有 sku 64 // 获取所选 spu 下的所有 sku
64 List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollUtil.newArrayList(createReqVO.getSpuId())); 65 List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollUtil.newArrayList(createReqVO.getSpuId()));
65 // 校验商品 sku 是否存在 66 // 校验商品 sku 是否存在
66 - // TODO @puhui999:直接校验 sku 数量,是不是就完事啦,不需要校验的特别严谨哈;  
67 - validateProductSkuExistence(skus, createReqVO.getProducts(), SeckillProductCreateReqVO::getSkuId); 67 + if (skus.size() != createReqVO.getProducts().size()) {
  68 + throw exception(SKU_NOT_EXISTS);
  69 + }
68 70
69 // 插入秒杀活动 71 // 插入秒杀活动
70 SeckillActivityDO activity = SeckillActivityConvert.INSTANCE.convert(createReqVO) 72 SeckillActivityDO activity = SeckillActivityConvert.INSTANCE.convert(createReqVO)
@@ -72,9 +74,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -72,9 +74,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
72 .setTotalStock(CollectionUtils.getSumValue(createReqVO.getProducts(), SeckillProductCreateReqVO::getStock, Integer::sum)); 74 .setTotalStock(CollectionUtils.getSumValue(createReqVO.getProducts(), SeckillProductCreateReqVO::getStock, Integer::sum));
73 seckillActivityMapper.insert(activity); 75 seckillActivityMapper.insert(activity);
74 // 插入商品 76 // 插入商品
75 - // TODO @puhui999:products 要注意复数哈  
76 - List<SeckillProductDO> product = SeckillActivityConvert.INSTANCE.convertList(activity, createReqVO.getProducts());  
77 - seckillProductMapper.insertBatch(product); 77 + List<SeckillProductDO> products = SeckillActivityConvert.INSTANCE.complementList(createReqVO.getProducts(), activity);
  78 + seckillProductMapper.insertBatch(products);
78 return activity.getId(); 79 return activity.getId();
79 } 80 }
80 81
@@ -99,11 +100,9 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -99,11 +100,9 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
99 } 100 }
100 List<SeckillActivityDO> activityDOs2 = CollectionUtils.convertList(activityDOs, c -> c, s -> { 101 List<SeckillActivityDO> activityDOs2 = CollectionUtils.convertList(activityDOs, c -> c, s -> {
101 // 判断秒杀时段是否有交集 102 // 判断秒杀时段是否有交集
102 - // TODO @puhui999:是不是 containsAny 就是有交集呀  
103 - List<Long> configIdsClone = CollUtil.newArrayList(s.getConfigIds());  
104 - configIdsClone.retainAll(configIds);  
105 - return CollUtil.isNotEmpty(configIdsClone); 103 + return CollectionUtils.containsAny(s.getConfigIds(), configIds);
106 }); 104 });
  105 +
107 if (CollUtil.isNotEmpty(activityDOs2)) { 106 if (CollUtil.isNotEmpty(activityDOs2)) {
108 throw exception(SECKILL_TIME_CONFLICTS); 107 throw exception(SECKILL_TIME_CONFLICTS);
109 } 108 }
@@ -122,7 +121,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -122,7 +121,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
122 // 获取所选 spu下的所有 sku 121 // 获取所选 spu下的所有 sku
123 List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollUtil.newArrayList(updateReqVO.getSpuId())); 122 List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollUtil.newArrayList(updateReqVO.getSpuId()));
124 // 校验商品 sku 是否存在 123 // 校验商品 sku 是否存在
125 - validateProductSkuExistence(skus, updateReqVO.getProducts(), SeckillProductUpdateReqVO::getSkuId); 124 + validateProductSkuExistence(updateReqVO.getProducts(), skus, SeckillProductUpdateReqVO::getSkuId);
126 125
127 // 更新活动 126 // 更新活动
128 SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO) 127 SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO)
@@ -147,31 +146,31 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -147,31 +146,31 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
147 // 数据库中的活动商品 146 // 数据库中的活动商品
148 List<SeckillProductDO> seckillProductDOs = seckillProductMapper.selectListByActivityId(updateObj.getId()); 147 List<SeckillProductDO> seckillProductDOs = seckillProductMapper.selectListByActivityId(updateObj.getId());
149 Set<Long> dbSkuIds = CollectionUtils.convertSet(seckillProductDOs, SeckillProductDO::getSkuId); 148 Set<Long> dbSkuIds = CollectionUtils.convertSet(seckillProductDOs, SeckillProductDO::getSkuId);
150 - // 1. 删除后台存在的前端不存在的商品  
151 - // TODO @puhui999:delete 应该是 id,不是 skuId 哈  
152 Set<Long> voSkuIds = CollectionUtils.convertSet(products, SeckillProductUpdateReqVO::getSkuId); 149 Set<Long> voSkuIds = CollectionUtils.convertSet(products, SeckillProductUpdateReqVO::getSkuId);
153 - List<Long> d = CollectionUtils.filterList(dbSkuIds, item -> !voSkuIds.contains(item));  
154 - if (CollUtil.isNotEmpty(d)) {  
155 - seckillProductMapper.deleteBatchIds(d);  
156 - }  
157 - // 2. 前端存在的后端不存在的商品  
158 - List<Long> c = CollectionUtils.filterList(voSkuIds, item -> !dbSkuIds.contains(item));  
159 - if (CollUtil.isNotEmpty(c)) {  
160 - List<SeckillProductUpdateReqVO> vos = CollectionUtils.filterList(products, item -> c.contains(item.getSkuId()));  
161 - List<SeckillProductDO> productDOs = SeckillActivityConvert.INSTANCE.convertList(updateObj, vos);  
162 - seckillProductMapper.insertBatch(productDOs);  
163 - }  
164 - // 3. 更新已存在的商品  
165 - List<Long> u = CollectionUtils.filterList(voSkuIds, dbSkuIds::contains);  
166 - if (CollUtil.isNotEmpty(u)) {  
167 - List<SeckillProductUpdateReqVO> vos = CollectionUtils.filterList(products, item -> u.contains(item.getSkuId()));  
168 - List<SeckillProductDO> productDOs = SeckillActivityConvert.INSTANCE.convertList1(updateObj, vos, seckillProductDOs);  
169 - seckillProductMapper.updateBatch(productDOs);  
170 - } 150 + Map<String, List<SeckillProductDO>> data = CollectionUtils.convertCDUMap(voSkuIds, dbSkuIds, mapData -> {
  151 + HashMap<String, List<SeckillProductDO>> cdu = MapUtil.newHashMap(3);
  152 + MapUtils.findAndThen(mapData, "create", list -> {
  153 + cdu.put("create", SeckillActivityConvert.INSTANCE.complementList(
  154 + CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj));
  155 + });
  156 + MapUtils.findAndThen(mapData, "delete", list -> {
  157 + cdu.put("create", CollectionUtils.filterList(seckillProductDOs, item -> list.contains(item.getSkuId())));
  158 + });
  159 + MapUtils.findAndThen(mapData, "update", list -> {
  160 + cdu.put("update", SeckillActivityConvert.INSTANCE.complementList(seckillProductDOs,
  161 + CollectionUtils.filterList(products, item -> list.contains(item.getSkuId())), updateObj));
  162 + });
  163 + return cdu;
  164 + });
  165 +
  166 + // 执行增删改
  167 + MapUtils.findAndThen(data, "create", item -> seckillProductMapper.insertBatch(item));
  168 + MapUtils.findAndThen(data, "delete", item -> seckillProductMapper.deleteBatchIds(
  169 + CollectionUtils.convertSet(item, SeckillProductDO::getId)));
  170 + MapUtils.findAndThen(data, "update", item -> seckillProductMapper.updateBatch(item));
171 } 171 }
172 172
173 @Override 173 @Override
174 - @Transactional(rollbackFor = Exception.class) // TODO @puhui999:这个不用加事务哈  
175 public void closeSeckillActivity(Long id) { 174 public void closeSeckillActivity(Long id) {
176 // TODO 待验证没使用过 175 // TODO 待验证没使用过
177 // 校验存在 176 // 校验存在
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigService.java
@@ -73,9 +73,10 @@ public interface SeckillConfigService { @@ -73,9 +73,10 @@ public interface SeckillConfigService {
73 /** 73 /**
74 * 获得所有正常状态的时段配置列表 74 * 获得所有正常状态的时段配置列表
75 * 75 *
  76 + * @param status 状态
76 * @return 秒杀时段列表 77 * @return 秒杀时段列表
77 */ 78 */
78 - List<SeckillConfigDO> getListAllSimple(); 79 + List<SeckillConfigDO> getSeckillConfigListByStatus(Integer status);
79 80
80 /** 81 /**
81 * 更新秒杀时段配置状态 82 * 更新秒杀时段配置状态
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigServiceImpl.java
@@ -62,7 +62,7 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { @@ -62,7 +62,7 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
62 seckillConfigMapper.updateById(updateObj); 62 seckillConfigMapper.updateById(updateObj);
63 } 63 }
64 64
65 - // TODO @puhui999: 这个要不合并到更新操作里? 不单独有个操作咧; 更新状态不用那么多必须的参数,更新的时候需要校验时间段 65 + // TODO @puhui999: 这个要不合并到更新操作里? 不单独有个操作咧; fix: 更新状态不用那么多必须的参数,更新的时候需要校验时间段
66 @Override 66 @Override
67 public void updateSeckillConfigStatus(Long id, Integer status) { 67 public void updateSeckillConfigStatus(Long id, Integer status) {
68 // 校验秒杀时段是否存在 68 // 校验秒杀时段是否存在
@@ -108,7 +108,7 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { @@ -108,7 +108,7 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
108 LocalTime startTime2 = LocalTime.parse(config.getStartTime()); 108 LocalTime startTime2 = LocalTime.parse(config.getStartTime());
109 LocalTime endTime2 = LocalTime.parse(config.getEndTime()); 109 LocalTime endTime2 = LocalTime.parse(config.getEndTime());
110 // 判断时间是否重叠 110 // 判断时间是否重叠
111 - return LocalDateTimeUtils.checkTimeOverlap(startTime1, endTime1, startTime2, endTime2); 111 + return LocalDateTimeUtils.isOverlap(startTime1, endTime1, startTime2, endTime2);
112 }); 112 });
113 113
114 if (hasConflict) { 114 if (hasConflict) {
@@ -151,10 +151,9 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { @@ -151,10 +151,9 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
151 return seckillConfigMapper.selectPage(pageVO); 151 return seckillConfigMapper.selectPage(pageVO);
152 } 152 }
153 153
154 - // TODO @puhui999:改成传入 enable 状态哈。一个通用的 getSeckillConfigList 方法  
155 @Override 154 @Override
156 - public List<SeckillConfigDO> getListAllSimple() {  
157 - return seckillConfigMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus()); 155 + public List<SeckillConfigDO> getSeckillConfigListByStatus(Integer status) {
  156 + return seckillConfigMapper.selectListByStatus(status);
158 } 157 }
159 158
160 } 159 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java
@@ -31,8 +31,14 @@ public class PromotionUtils { @@ -31,8 +31,14 @@ public class PromotionUtils {
31 return LocalDateTimeUtils.beforeNow(endTime) ? CommonStatusEnum.DISABLE.getStatus() : CommonStatusEnum.ENABLE.getStatus(); 31 return LocalDateTimeUtils.beforeNow(endTime) ? CommonStatusEnum.DISABLE.getStatus() : CommonStatusEnum.ENABLE.getStatus();
32 } 32 }
33 33
34 - // TODO @puhui999:写个注释哈。  
35 - public static <T> void validateProductSkuExistence(List<ProductSkuRespDTO> skus, List<T> products, Function<T, Long> func) { 34 + /**
  35 + * 校验商品 sku 是否存在
  36 + *
  37 + * @param products 需要校验的商品
  38 + * @param skus 数据库中的商品 skus
  39 + * @param func 获取需要校验的商品的 skuId
  40 + */
  41 + public static <T> void validateProductSkuExistence(List<T> products, List<ProductSkuRespDTO> skus, Function<T, Long> func) {
36 // 校验 sku 个数是否一致 42 // 校验 sku 个数是否一致
37 Set<Long> skuIdsSet = CollectionUtils.convertSet(products, func); 43 Set<Long> skuIdsSet = CollectionUtils.convertSet(products, func);
38 Set<Long> skuIdsSet1 = CollectionUtils.convertSet(skus, ProductSkuRespDTO::getId); 44 Set<Long> skuIdsSet1 = CollectionUtils.convertSet(skus, ProductSkuRespDTO::getId);
yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImplTest.java
@@ -3,17 +3,15 @@ package cn.iocoder.yudao.module.promotion.service.combination; @@ -3,17 +3,15 @@ package cn.iocoder.yudao.module.promotion.service.combination;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; 4 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
5 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO; 5 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
6 -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExportReqVO;  
7 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; 6 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
8 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO; 7 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
9 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;  
10 -import cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity.CombinationActivityMapper; 8 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
  9 +import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationActivityMapper;
11 import org.junit.jupiter.api.Disabled; 10 import org.junit.jupiter.api.Disabled;
12 import org.junit.jupiter.api.Test; 11 import org.junit.jupiter.api.Test;
13 import org.springframework.context.annotation.Import; 12 import org.springframework.context.annotation.Import;
14 13
15 import javax.annotation.Resource; 14 import javax.annotation.Resource;
16 -import java.util.List;  
17 15
18 import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; 16 import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
19 import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; 17 import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
@@ -26,15 +24,15 @@ import static org.junit.jupiter.api.Assertions.*; @@ -26,15 +24,15 @@ import static org.junit.jupiter.api.Assertions.*;
26 24
27 // TODO 芋艿:等完成后,在补全单测 25 // TODO 芋艿:等完成后,在补全单测
28 /** 26 /**
29 - * {@link CombinationActivityServiceImpl} 的单元测试类 27 + * {@link CombinationServiceImpl} 的单元测试类
30 * 28 *
31 * @author HUIHUI 29 * @author HUIHUI
32 */ 30 */
33 -@Import(CombinationActivityServiceImpl.class) 31 +@Import(CombinationServiceImpl.class)
34 public class CombinationActivityServiceImplTest extends BaseDbUnitTest { 32 public class CombinationActivityServiceImplTest extends BaseDbUnitTest {
35 33
36 @Resource 34 @Resource
37 - private CombinationActivityServiceImpl combinationActivityService; 35 + private CombinationServiceImpl combinationActivityService;
38 36
39 @Resource 37 @Resource
40 private CombinationActivityMapper combinationActivityMapper; 38 private CombinationActivityMapper combinationActivityMapper;
@@ -225,28 +223,7 @@ public class CombinationActivityServiceImplTest extends BaseDbUnitTest { @@ -225,28 +223,7 @@ public class CombinationActivityServiceImplTest extends BaseDbUnitTest {
225 combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setLimitDuration(null))); 223 combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setLimitDuration(null)));
226 // 测试 createTime 不匹配 224 // 测试 createTime 不匹配
227 combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setCreateTime(null))); 225 combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setCreateTime(null)));
228 - // 准备参数  
229 - CombinationActivityExportReqVO reqVO = new CombinationActivityExportReqVO();  
230 - reqVO.setName(null);  
231 - reqVO.setSpuId(null);  
232 - reqVO.setTotalLimitCount(null);  
233 - reqVO.setSingleLimitCount(null);  
234 - reqVO.setStartTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));  
235 - reqVO.setEndTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));  
236 - reqVO.setUserSize(null);  
237 - reqVO.setTotalNum(null);  
238 - reqVO.setSuccessNum(null);  
239 - reqVO.setOrderUserCount(null);  
240 - reqVO.setVirtualGroup(null);  
241 - reqVO.setStatus(null);  
242 - reqVO.setLimitDuration(null);  
243 - reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));  
244 226
245 - // 调用  
246 - List<CombinationActivityDO> list = combinationActivityService.getCombinationActivityList(reqVO);  
247 - // 断言  
248 - assertEquals(1, list.size());  
249 - assertPojoEquals(dbCombinationActivity, list.get(0));  
250 } 227 }
251 228
252 } 229 }
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
@@ -31,6 +31,10 @@ public interface ErrorCodeConstants { @@ -31,6 +31,10 @@ public interface ErrorCodeConstants {
31 ErrorCode ORDER_COMMENT_STATUS_NOT_FALSE = new ErrorCode(1011000020, "创建交易订单项的评价失败,订单已评价"); 31 ErrorCode ORDER_COMMENT_STATUS_NOT_FALSE = new ErrorCode(1011000020, "创建交易订单项的评价失败,订单已评价");
32 ErrorCode ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE = new ErrorCode(1011000021, "交易订单发货失败,订单已退款或部分退款"); 32 ErrorCode ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE = new ErrorCode(1011000021, "交易订单发货失败,订单已退款或部分退款");
33 ErrorCode ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1011000022, "交易订单发货失败,拼团未成功"); 33 ErrorCode ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1011000022, "交易订单发货失败,拼团未成功");
  34 + // TODO 已移除订单单独发货
  35 + ErrorCode ORDER_DELIVERY_FAILED_ITEMS_NOT_EMPTY = new ErrorCode(1011000023, "订单发货失败,请选择发货商品");
  36 + ErrorCode ORDER_DELIVERY_FAILED_ITEM_NOT_EXISTS = new ErrorCode(1011000024, "订单发货失败,所选发货商品不存在");
  37 + ErrorCode ORDER_DELIVERY_FAILED_ITEM_ALREADY_DELIVERY = new ErrorCode(1011000025, "订单发货失败,所选商品已发货");
34 38
35 // ========== After Sale 模块 1011000100 ========== 39 // ========== After Sale 模块 1011000100 ==========
36 ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在"); 40 ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在");
@@ -69,10 +73,4 @@ public interface ErrorCodeConstants { @@ -69,10 +73,4 @@ public interface ErrorCodeConstants {
69 // ========== 物流 PICK_UP 模块 1011006000 ========== 73 // ========== 物流 PICK_UP 模块 1011006000 ==========
70 ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1011006000, "自提门店不存在"); 74 ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1011006000, "自提门店不存在");
71 75
72 - // ========== 物流 PICK_UP 模块 1011007000 ==========  
73 - // TODO @puhui999:这几个错误码,应该属于订单哈  
74 - ErrorCode ORDER_DELIVERY_FAILED_ITEMS_NOT_EMPTY = new ErrorCode(1011007000, "订单发货失败,请选择发货商品");  
75 - ErrorCode ORDER_DELIVERY_FAILED_ITEM_NOT_EXISTS = new ErrorCode(1011007001, "订单发货失败,所选发货商品不存在");  
76 - ErrorCode ORDER_DELIVERY_FAILED_ITEM_ALREADY_DELIVERY = new ErrorCode(1011007002, "订单发货失败,所选商品已发货");  
77 -  
78 } 76 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderDeliveryReqVO.java
@@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; @@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
5 import io.swagger.v3.oas.annotations.media.Schema; 5 import io.swagger.v3.oas.annotations.media.Schema;
6 import lombok.Data; 6 import lombok.Data;
7 7
  8 +import javax.validation.constraints.NotEmpty;
8 import javax.validation.constraints.NotNull; 9 import javax.validation.constraints.NotNull;
9 -import java.util.List;  
10 10
11 @Schema(description = "管理后台 - 订单发货 Request VO") 11 @Schema(description = "管理后台 - 订单发货 Request VO")
12 @Data 12 @Data
@@ -21,20 +21,14 @@ public class TradeOrderDeliveryReqVO { @@ -21,20 +21,14 @@ public class TradeOrderDeliveryReqVO {
21 @NotNull(message = "发货类型不能为空") 21 @NotNull(message = "发货类型不能为空")
22 private Integer type; 22 private Integer type;
23 23
24 - // TODO @puhui999:还是要校验下  
25 -  
26 @Schema(description = "发货物流公司编号", example = "1") 24 @Schema(description = "发货物流公司编号", example = "1")
  25 + @NotNull(message = "发货物流公司不能为空")
27 private Long logisticsId; 26 private Long logisticsId;
28 27
29 @Schema(description = "发货物流单号", example = "SF123456789") 28 @Schema(description = "发货物流单号", example = "SF123456789")
  29 + @NotEmpty(message = "发货物流单号不能为空")
30 private String logisticsNo; 30 private String logisticsNo;
31 31
32 - // TODO 订单项商品单独发货;不做单独发  
33 -  
34 - @Schema(description = "发货订单项", example = "[1,2,3]")  
35 - @NotNull(message = "发货订单项不能为空")  
36 - private List<Long> orderItemIds;  
37 -  
38 // =============== 同城配送 ================ 32 // =============== 同城配送 ================
39 // TODO 33 // TODO
40 34
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
@@ -13,12 +13,11 @@ import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; @@ -13,12 +13,11 @@ import cn.iocoder.yudao.module.pay.enums.DictTypeConstants;
13 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; 13 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
14 import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; 14 import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
15 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; 15 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
16 -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO; 16 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
17 import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO; 17 import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
18 import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO; 18 import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
19 import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO; 19 import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO;
20 import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; 20 import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO;
21 -import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;  
22 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDetailRespVO; 21 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDetailRespVO;
23 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageItemRespVO; 22 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageItemRespVO;
24 import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO; 23 import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO;
@@ -27,7 +26,6 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderI @@ -27,7 +26,6 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderI
27 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO; 26 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO;
28 import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; 27 import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO;
29 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; 28 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
30 -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDeliveryDO;  
31 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; 29 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
32 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; 30 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum;
33 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; 31 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
@@ -334,17 +332,6 @@ public interface TradeOrderConvert { @@ -334,17 +332,6 @@ public interface TradeOrderConvert {
334 @Mapping(target = "avatar", source = "user.avatar"), 332 @Mapping(target = "avatar", source = "user.avatar"),
335 @Mapping(target = "status", ignore = true) 333 @Mapping(target = "status", ignore = true)
336 }) 334 })
337 - CombinationRecordReqDTO convert(TradeOrderDO order, TradeOrderItemDO orderItem, AppTradeOrderCreateReqVO createReqVO, MemberUserRespDTO user);  
338 -  
339 - TradeOrderDeliveryDO covert(Long orderId, Long orderItemId, Long userId, Integer deliveryType, Long logisticsId, String logisticsNo);  
340 -  
341 - default List<TradeOrderDeliveryDO> covert(TradeOrderDO order, TradeOrderDeliveryReqVO deliveryReqVO) {  
342 - ArrayList<TradeOrderDeliveryDO> arrayList = new ArrayList<>();  
343 - deliveryReqVO.getOrderItemIds().forEach(item -> {  
344 - arrayList.add(covert(order.getId(), item, order.getUserId(), deliveryReqVO.getType(),  
345 - deliveryReqVO.getLogisticsId(), deliveryReqVO.getLogisticsNo()));  
346 - });  
347 - return arrayList;  
348 - } 335 + CombinationRecordCreateReqDTO convert(TradeOrderDO order, TradeOrderItemDO orderItem, AppTradeOrderCreateReqVO createReqVO, MemberUserRespDTO user);
349 336
350 } 337 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderDeliveryMapper.java deleted
1 -package cn.iocoder.yudao.module.trade.dal.mysql.order;  
2 -  
3 -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;  
4 -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;  
5 -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDeliveryDO;  
6 -import org.apache.ibatis.annotations.Mapper;  
7 -  
8 -import java.util.List;  
9 -  
10 -// TODO @puhui999:应该去掉啦  
11 -/**  
12 - * 交易订单发货记录 Mapper  
13 - *  
14 - * @author HUIHUI  
15 - */  
16 -@Mapper  
17 -public interface TradeOrderDeliveryMapper extends BaseMapperX<TradeOrderDeliveryDO> {  
18 -  
19 - default List<TradeOrderDeliveryDO> selsectListByOrderIdAndItemIds(Long orderId, List<Long> orderItemIds) {  
20 - return selectList(new LambdaQueryWrapperX<TradeOrderDeliveryDO>()  
21 - .eq(TradeOrderDeliveryDO::getOrderId, orderId).in(TradeOrderDeliveryDO::getOrderItemId, orderItemIds));  
22 - }  
23 -  
24 -}  
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/message/TradeMessageService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.service.message;
  2 +
  3 +import cn.iocoder.yudao.module.trade.service.message.dto.TradeOrderMessageWhenDeliveryOrderReqDTO;
  4 +
  5 +/**
  6 + * Trade 消息 service 接口
  7 + *
  8 + * @author HUIHUI
  9 + */
  10 +public interface TradeMessageService {
  11 +
  12 + /**
  13 + * 订单发货时发送消息
  14 + *
  15 + * @param reqDTO 发送消息
  16 + */
  17 + void sendMessageWhenDeliveryOrder(TradeOrderMessageWhenDeliveryOrderReqDTO reqDTO);
  18 +
  19 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/message/TradeMessageServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.service.message;
  2 +
  3 +import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
  4 +import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
  5 +import cn.iocoder.yudao.module.trade.service.message.dto.TradeOrderMessageWhenDeliveryOrderReqDTO;
  6 +import org.springframework.stereotype.Service;
  7 +import org.springframework.validation.annotation.Validated;
  8 +
  9 +import javax.annotation.Resource;
  10 +import java.util.HashMap;
  11 +import java.util.Map;
  12 +
  13 +/**
  14 + * Trade 消息 service 实现类
  15 + *
  16 + * @author HUIHUI
  17 + */
  18 +@Service
  19 +@Validated
  20 +public class TradeMessageServiceImpl implements TradeMessageService {
  21 +
  22 + @Resource
  23 + private NotifyMessageSendApi notifyMessageSendApi;
  24 +
  25 + @Override
  26 + public void sendMessageWhenDeliveryOrder(TradeOrderMessageWhenDeliveryOrderReqDTO reqDTO) {
  27 + // 1、构造消息
  28 + Map<String, Object> msgMap = new HashMap<>();
  29 + msgMap.put("orderId", reqDTO.getOrderId());
  30 + msgMap.put("msg", reqDTO.getMessage());
  31 + // 2、发送站内信
  32 + notifyMessageSendApi.sendSingleMessageToMember(
  33 + new NotifySendSingleToUserReqDTO()
  34 + .setUserId(reqDTO.getUserId())
  35 + .setTemplateCode("order_delivery")
  36 + .setTemplateParams(msgMap));
  37 + }
  38 +
  39 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/message/dto/TradeOrderMessageWhenDeliveryOrderReqDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.service.message.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import javax.validation.constraints.NotEmpty;
  6 +import javax.validation.constraints.NotNull;
  7 +
  8 +/**
  9 + * 订单发货时 Req DTO
  10 + *
  11 + * @author HUIHUI
  12 + */
  13 +@Data
  14 +public class TradeOrderMessageWhenDeliveryOrderReqDTO {
  15 +
  16 + /**
  17 + * 订单编号
  18 + */
  19 + @NotNull(message = "订单编号不能为空")
  20 + private Long orderId;
  21 + /**
  22 + * 用户编号
  23 + */
  24 + @NotNull(message = "用户编号不能为空")
  25 + private Long userId;
  26 + /**
  27 + * 消息
  28 + */
  29 + @NotEmpty(message = "发送消息不能为空")
  30 + private String message;
  31 +
  32 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java
@@ -8,6 +8,7 @@ import cn.hutool.core.util.StrUtil; @@ -8,6 +8,7 @@ import cn.hutool.core.util.StrUtil;
8 import cn.iocoder.yudao.framework.common.core.KeyValue; 8 import cn.iocoder.yudao.framework.common.core.KeyValue;
9 import cn.iocoder.yudao.framework.common.enums.TerminalEnum; 9 import cn.iocoder.yudao.framework.common.enums.TerminalEnum;
10 import cn.iocoder.yudao.framework.common.pojo.PageResult; 10 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  11 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
11 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 12 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
12 import cn.iocoder.yudao.module.member.api.address.AddressApi; 13 import cn.iocoder.yudao.module.member.api.address.AddressApi;
13 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; 14 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
@@ -21,12 +22,10 @@ import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi; @@ -21,12 +22,10 @@ import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi;
21 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; 22 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
22 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; 23 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
23 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; 24 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
24 -import cn.iocoder.yudao.module.promotion.api.combination.CombinationApi; 25 +import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi;
25 import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; 26 import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
26 import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; 27 import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO;
27 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; 28 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
28 -import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;  
29 -import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;  
30 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; 29 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
31 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; 30 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO;
32 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; 31 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
@@ -38,9 +37,7 @@ import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; @@ -38,9 +37,7 @@ import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
38 import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; 37 import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO;
39 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; 38 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
40 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; 39 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
41 -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDeliveryDO;  
42 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; 40 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
43 -import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderDeliveryMapper;  
44 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; 41 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
45 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; 42 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
46 import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants; 43 import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants;
@@ -49,6 +46,8 @@ import cn.iocoder.yudao.module.trade.enums.order.*; @@ -49,6 +46,8 @@ import cn.iocoder.yudao.module.trade.enums.order.*;
49 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; 46 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
50 import cn.iocoder.yudao.module.trade.service.cart.TradeCartService; 47 import cn.iocoder.yudao.module.trade.service.cart.TradeCartService;
51 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; 48 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
  49 +import cn.iocoder.yudao.module.trade.service.message.TradeMessageService;
  50 +import cn.iocoder.yudao.module.trade.service.message.dto.TradeOrderMessageWhenDeliveryOrderReqDTO;
52 import cn.iocoder.yudao.module.trade.service.price.TradePriceService; 51 import cn.iocoder.yudao.module.trade.service.price.TradePriceService;
53 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; 52 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
54 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; 53 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
@@ -102,15 +101,13 @@ public class TradeOrderServiceImpl implements TradeOrderService { @@ -102,15 +101,13 @@ public class TradeOrderServiceImpl implements TradeOrderService {
102 @Resource 101 @Resource
103 private ProductCommentApi productCommentApi; 102 private ProductCommentApi productCommentApi;
104 @Resource 103 @Resource
105 - private NotifyMessageSendApi notifyMessageSendApi;  
106 - 104 + private TradeMessageService tradeMessageService;
107 @Resource 105 @Resource
108 private TradeOrderProperties tradeOrderProperties; 106 private TradeOrderProperties tradeOrderProperties;
109 107
110 @Resource 108 @Resource
111 - private CombinationApi combinationApi;  
112 - @Resource  
113 - private TradeOrderDeliveryMapper orderDeliveryMapper; 109 + private CombinationRecordApi combinationRecordApi;
  110 +
114 // =================== Order =================== 111 // =================== Order ===================
115 112
116 @Override 113 @Override
@@ -177,7 +174,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { @@ -177,7 +174,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
177 if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { 174 if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
178 MemberUserRespDTO user = memberUserApi.getUser(userId); 175 MemberUserRespDTO user = memberUserApi.getUser(userId);
179 // TODO 拼团一次应该只能选择一种规格的商品 176 // TODO 拼团一次应该只能选择一种规格的商品
180 - combinationApi.createRecord(TradeOrderConvert.INSTANCE.convert(order, orderItems.get(0), createReqVO, user) 177 + combinationRecordApi.createRecord(TradeOrderConvert.INSTANCE.convert(order, orderItems.get(0), createReqVO, user)
181 .setStatus(CombinationRecordStatusEnum.WAITING.getStatus())); 178 .setStatus(CombinationRecordStatusEnum.WAITING.getStatus()));
182 } 179 }
183 // TODO 秒杀扣减库存是下单就扣除还是等待订单支付成功再扣除 180 // TODO 秒杀扣减库存是下单就扣除还是等待订单支付成功再扣除
@@ -314,7 +311,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { @@ -314,7 +311,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
314 // 1、拼团活动 311 // 1、拼团活动
315 if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { 312 if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
316 // 更新拼团状态 TODO puhui999:订单支付失败或订单支付过期删除这条拼团记录 313 // 更新拼团状态 TODO puhui999:订单支付失败或订单支付过期删除这条拼团记录
317 - combinationApi.updateRecordStatusAndStartTime(order.getUserId(), order.getId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); 314 + combinationRecordApi.updateRecordStatusAndStartTime(order.getUserId(), order.getId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
318 } 315 }
319 // TODO 芋艿:发送订单变化的消息 316 // TODO 芋艿:发送订单变化的消息
320 317
@@ -385,23 +382,26 @@ public class TradeOrderServiceImpl implements TradeOrderService { @@ -385,23 +382,26 @@ public class TradeOrderServiceImpl implements TradeOrderService {
385 // 校验并获得交易订单(可发货) 382 // 校验并获得交易订单(可发货)
386 TradeOrderDO order = validateOrderDeliverable(deliveryReqVO.getId()); 383 TradeOrderDO order = validateOrderDeliverable(deliveryReqVO.getId());
387 384
388 - TradeOrderDO tradeOrderDO = new TradeOrderDO();  
389 - List<TradeOrderDeliveryDO> deliveryDOs = new ArrayList<>();  
390 /* TODO 385 /* TODO
391 * fix: 首先需要店铺设置配送方式如: 自提 、配送、物流-配送、物流-配送-自提、商家配送 386 * fix: 首先需要店铺设置配送方式如: 自提 、配送、物流-配送、物流-配送-自提、商家配送
392 * 1.如果店铺有设置配送方式用户只填写收货地址的情况下店家后台自己选择配送方式 387 * 1.如果店铺有设置配送方式用户只填写收货地址的情况下店家后台自己选择配送方式
393 * 2.如果店铺只支持到店自提那么下单后默认发货不需要物流 388 * 2.如果店铺只支持到店自提那么下单后默认发货不需要物流
394 * 3.如果店铺支持 物流-配送-自提 的情况下后台不需要选择配送方式按前端用户选择的配送方式发货即可 389 * 3.如果店铺支持 物流-配送-自提 的情况下后台不需要选择配送方式按前端用户选择的配送方式发货即可
395 */ 390 */
  391 + TradeOrderDO tradeOrderDO = new TradeOrderDO();
396 // 判断发货类型 392 // 判断发货类型
397 // 快递发货 393 // 快递发货
398 if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.EXPRESS.getMode())) { 394 if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.EXPRESS.getMode())) {
399 - deliveryDOs = express(order, deliveryReqVO); 395 + // 校验快递公司
  396 + DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(deliveryReqVO.getLogisticsId());
  397 + if (deliveryExpress == null) {
  398 + throw exception(EXPRESS_NOT_EXISTS);
  399 + }
400 tradeOrderDO.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo()); 400 tradeOrderDO.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo());
401 } 401 }
402 // 用户自提 402 // 用户自提
403 if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.PICK_UP.getMode())) { 403 if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.PICK_UP.getMode())) {
404 - deliveryDOs = pickUp(order, deliveryReqVO); 404 + // TODO 校验自提门店是否存在
405 // 重置一下确保快递公司和快递单号为空 405 // 重置一下确保快递公司和快递单号为空
406 tradeOrderDO.setLogisticsId(null).setLogisticsNo(""); 406 tradeOrderDO.setLogisticsId(null).setLogisticsNo("");
407 } 407 }
@@ -409,6 +409,8 @@ public class TradeOrderServiceImpl implements TradeOrderService { @@ -409,6 +409,8 @@ public class TradeOrderServiceImpl implements TradeOrderService {
409 if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.NULL.getMode())) { 409 if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.NULL.getMode())) {
410 // TODO 情况一:正常走发货逻辑和用户自提有点像 不同点:不需要自提门店只需要用户确认收货 410 // TODO 情况一:正常走发货逻辑和用户自提有点像 不同点:不需要自提门店只需要用户确认收货
411 // TODO 情况二:用户下单付款后直接确认收货或等待用户确认收货 411 // TODO 情况二:用户下单付款后直接确认收货或等待用户确认收货
  412 + // 重置一下确保快递公司和快递单号为空
  413 + tradeOrderDO.setLogisticsId(null).setLogisticsNo("");
412 } 414 }
413 415
414 // 更新 TradeOrderDO 状态为已发货,等待收货 416 // 更新 TradeOrderDO 状态为已发货,等待收货
@@ -418,72 +420,16 @@ public class TradeOrderServiceImpl implements TradeOrderService { @@ -418,72 +420,16 @@ public class TradeOrderServiceImpl implements TradeOrderService {
418 if (updateCount == 0) { 420 if (updateCount == 0) {
419 throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); 421 throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED);
420 } 422 }
421 - // 发货成功记录发货表  
422 - orderDeliveryMapper.insertBatch(deliveryDOs);  
423 // TODO 芋艿:发送订单变化的消息 423 // TODO 芋艿:发送订单变化的消息
424 424
425 - // TODO @puhui999:可以抽个 message 包,里面是 Order 所有的 message;类似工作流的  
426 // 发送站内信 425 // 发送站内信
427 - // 1、构造消息  
428 - Map<String, Object> msgMap = new HashMap<>();  
429 - msgMap.put("orderId", deliveryReqVO.getId());  
430 - msgMap.put("msg", TradeOrderStatusEnum.DELIVERED.getStatus());  
431 - // 2、发送站内信  
432 - notifyMessageSendApi.sendSingleMessageToMember(  
433 - new NotifySendSingleToUserReqDTO()  
434 - .setUserId(userId)  
435 - .setTemplateCode("order_delivery")  
436 - .setTemplateParams(msgMap)); 426 + tradeMessageService.sendMessageWhenDeliveryOrder(new TradeOrderMessageWhenDeliveryOrderReqDTO().setOrderId(order.getId())
  427 + .setUserId(userId).setMessage(TradeOrderDeliveryStatusEnum.DELIVERED.getName()));
437 428
438 // TODO 芋艿:OrderLog 429 // TODO 芋艿:OrderLog
439 // TODO 设计:lili:是不是发货后,才支持售后? 430 // TODO 设计:lili:是不是发货后,才支持售后?
440 } 431 }
441 432
442 - private List<TradeOrderDeliveryDO> express(TradeOrderDO order, TradeOrderDeliveryReqVO deliveryReqVO) {  
443 - // 校验快递公司  
444 - DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(deliveryReqVO.getLogisticsId());  
445 - if (deliveryExpress == null) {  
446 - throw exception(EXPRESS_NOT_EXISTS);  
447 - }  
448 - // 校验发货商品  
449 - validateDeliveryOrderItem(order, deliveryReqVO);  
450 - // 创建发货记录  
451 - return TradeOrderConvert.INSTANCE.covert(order, deliveryReqVO);  
452 - }  
453 -  
454 - private List<TradeOrderDeliveryDO> pickUp(TradeOrderDO order, TradeOrderDeliveryReqVO deliveryReqVO) {  
455 - // TODO 校验自提门店是否存在  
456 - // 重置一下确保快递公司和快递单号为空  
457 - deliveryReqVO.setLogisticsId(null);  
458 - deliveryReqVO.setLogisticsNo("");  
459 - // 校验发货商品  
460 - validateDeliveryOrderItem(order, deliveryReqVO);  
461 - // 创建发货记录  
462 - return TradeOrderConvert.INSTANCE.covert(order, deliveryReqVO);  
463 - }  
464 -  
465 - private void validateDeliveryOrderItem(TradeOrderDO order, TradeOrderDeliveryReqVO deliveryReqVO) {  
466 - // TODO 设计:like:是否要单独一个 delivery 发货单表??? fix: 多商品可分开单独发货,添加 trade_order_delivery 交易订单发货日志表关联发货所选订单项设置物流单号  
467 - // TODO 设计:niu:要不要支持一个订单下,多个 order item 单独发货,类似有赞 fix  
468 - // 校验发货商品  
469 - if (CollUtil.isEmpty(deliveryReqVO.getOrderItemIds())) {  
470 - throw exception(ORDER_DELIVERY_FAILED_ITEMS_NOT_EMPTY);  
471 - }  
472 - // 校验发货商品是否存在  
473 - List<TradeOrderItemDO> orderItemDOs = tradeOrderItemMapper.selectListByOrderId(order.getId());  
474 - Set<Long> itemIds = convertSet(orderItemDOs, TradeOrderItemDO::getId);  
475 - if (!itemIds.containsAll(deliveryReqVO.getOrderItemIds())) {  
476 - throw exception(ORDER_DELIVERY_FAILED_ITEM_NOT_EXISTS);  
477 - }  
478 - // 校验所选订单项是否存在有已发货的  
479 - List<TradeOrderDeliveryDO> deliveryDOList = orderDeliveryMapper.selsectListByOrderIdAndItemIds(order.getId(), deliveryReqVO.getOrderItemIds());  
480 - if (CollUtil.isNotEmpty(deliveryDOList)) {  
481 - HashSet<Long> hashSet = CollUtil.newHashSet(deliveryReqVO.getOrderItemIds());  
482 - hashSet.retainAll(convertSet(deliveryDOList, TradeOrderDeliveryDO::getOrderItemId));  
483 - throw exception(ORDER_DELIVERY_FAILED_ITEM_ALREADY_DELIVERY);  
484 - }  
485 - }  
486 -  
487 /** 433 /**
488 * 校验交易订单满足被发货的条件 434 * 校验交易订单满足被发货的条件
489 * 435 *
@@ -511,7 +457,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { @@ -511,7 +457,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
511 if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { 457 if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
512 // 校验订单拼团是否成功 458 // 校验订单拼团是否成功
513 // TODO 用户 ID 使用当前登录用户的还是订单保存的? 459 // TODO 用户 ID 使用当前登录用户的还是订单保存的?
514 - if (combinationApi.validateRecordStatusIsSuccess(order.getUserId(), order.getId())) { 460 + if (combinationRecordApi.validateRecordStatusIsSuccess(order.getUserId(), order.getId())) {
515 throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS); 461 throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS);
516 } 462 }
517 } 463 }
@@ -532,7 +478,6 @@ public class TradeOrderServiceImpl implements TradeOrderService { @@ -532,7 +478,6 @@ public class TradeOrderServiceImpl implements TradeOrderService {
532 if (updateCount == 0) { 478 if (updateCount == 0) {
533 throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); 479 throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED);
534 } 480 }
535 -  
536 // TODO 芋艿:OrderLog 481 // TODO 芋艿:OrderLog
537 482
538 // TODO 芋艿:lili 发送订单变化的消息 483 // TODO 芋艿:lili 发送订单变化的消息
@@ -683,6 +628,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { @@ -683,6 +628,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
683 } 628 }
684 629
685 @Override 630 @Override
  631 + @Transactional(rollbackFor = Exception.class)
686 public Long createOrderItemComment(AppTradeOrderItemCommentCreateReqVO createReqVO) { 632 public Long createOrderItemComment(AppTradeOrderItemCommentCreateReqVO createReqVO) {
687 Long loginUserId = getLoginUserId(); 633 Long loginUserId = getLoginUserId();
688 // 先通过订单项 ID,查询订单项是否存在 634 // 先通过订单项 ID,查询订单项是否存在
@@ -690,7 +636,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { @@ -690,7 +636,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
690 if (orderItem == null) { 636 if (orderItem == null) {
691 throw exception(ORDER_ITEM_NOT_FOUND); 637 throw exception(ORDER_ITEM_NOT_FOUND);
692 } 638 }
693 - // 校验订单 639 + // 校验订单相关状态
694 TradeOrderDO order = getOrderByIdAndUserId(orderItem.getOrderId(), loginUserId); 640 TradeOrderDO order = getOrderByIdAndUserId(orderItem.getOrderId(), loginUserId);
695 if (order == null) { 641 if (order == null) {
696 throw exception(ORDER_NOT_FOUND); 642 throw exception(ORDER_NOT_FOUND);
@@ -701,11 +647,18 @@ public class TradeOrderServiceImpl implements TradeOrderService { @@ -701,11 +647,18 @@ public class TradeOrderServiceImpl implements TradeOrderService {
701 if (ObjectUtil.notEqual(order.getCommentStatus(), Boolean.FALSE)) { 647 if (ObjectUtil.notEqual(order.getCommentStatus(), Boolean.FALSE)) {
702 throw exception(ORDER_COMMENT_STATUS_NOT_FALSE); 648 throw exception(ORDER_COMMENT_STATUS_NOT_FALSE);
703 } 649 }
704 - // TODO @puhui999:是不是评论完,要更新 status、commentStatus;另外,是不是上面 order 可以不校验,直接只判断 orderItem 就够;  
705 - // 对于 order 来说,就是评论完,把 order 更新完合理的 status 等字段。  
706 650
  651 + // 创建评价
707 ProductCommentCreateReqDTO productCommentCreateReqDTO = TradeOrderConvert.INSTANCE.convert04(createReqVO, orderItem); 652 ProductCommentCreateReqDTO productCommentCreateReqDTO = TradeOrderConvert.INSTANCE.convert04(createReqVO, orderItem);
708 - return productCommentApi.createComment(productCommentCreateReqDTO); 653 + Long comment = productCommentApi.createComment(productCommentCreateReqDTO);
  654 + // 更新订单项评价状态
  655 + tradeOrderItemMapper.updateById(new TradeOrderItemDO().setId(orderItem.getId()).setCommentStatus(Boolean.TRUE));
  656 + List<TradeOrderItemDO> orderItems = getOrderItemListByOrderId(CollUtil.newArrayList(order.getId()));
  657 + if (!CollectionUtils.isAny(orderItems, item -> ObjectUtil.equal(item.getCommentStatus(), Boolean.FALSE))) {
  658 + // 对于 order 来说,就是评论完,把 order 更新完合理的 status 等字段。
  659 + tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()).setCommentStatus(Boolean.TRUE));
  660 + }
  661 + return comment;
709 } 662 }
710 663
711 /** 664 /**
yudao-server/pom.xml
@@ -54,11 +54,11 @@ @@ -54,11 +54,11 @@
54 <!-- <version>${revision}</version>--> 54 <!-- <version>${revision}</version>-->
55 <!-- </dependency>--> 55 <!-- </dependency>-->
56 <!-- 支付服务。默认注释,保证编译速度 --> 56 <!-- 支付服务。默认注释,保证编译速度 -->
57 -<!-- <dependency>-->  
58 -<!-- <groupId>cn.iocoder.boot</groupId>-->  
59 -<!-- <artifactId>yudao-module-pay-biz</artifactId>-->  
60 -<!-- <version>${revision}</version>-->  
61 -<!-- </dependency>--> 57 + <dependency>
  58 + <groupId>cn.iocoder.boot</groupId>
  59 + <artifactId>yudao-module-pay-biz</artifactId>
  60 + <version>${revision}</version>
  61 + </dependency>
62 62
63 <!-- 微信公众号模块。默认注释,保证编译速度 --> 63 <!-- 微信公众号模块。默认注释,保证编译速度 -->
64 <!-- <dependency>--> 64 <!-- <dependency>-->
@@ -68,21 +68,21 @@ @@ -68,21 +68,21 @@
68 <!-- </dependency>--> 68 <!-- </dependency>-->
69 69
70 <!-- 商城相关模块。默认注释,保证编译速度 --> 70 <!-- 商城相关模块。默认注释,保证编译速度 -->
71 -<!-- <dependency>-->  
72 -<!-- <groupId>cn.iocoder.boot</groupId>-->  
73 -<!-- <artifactId>yudao-module-promotion-biz</artifactId>-->  
74 -<!-- <version>${revision}</version>-->  
75 -<!-- </dependency>-->  
76 -<!-- <dependency>-->  
77 -<!-- <groupId>cn.iocoder.boot</groupId>-->  
78 -<!-- <artifactId>yudao-module-product-biz</artifactId>-->  
79 -<!-- <version>${revision}</version>-->  
80 -<!-- </dependency>-->  
81 -<!-- <dependency>-->  
82 -<!-- <groupId>cn.iocoder.boot</groupId>-->  
83 -<!-- <artifactId>yudao-module-trade-biz</artifactId>-->  
84 -<!-- <version>${revision}</version>-->  
85 -<!-- </dependency>--> 71 + <dependency>
  72 + <groupId>cn.iocoder.boot</groupId>
  73 + <artifactId>yudao-module-promotion-biz</artifactId>
  74 + <version>${revision}</version>
  75 + </dependency>
  76 + <dependency>
  77 + <groupId>cn.iocoder.boot</groupId>
  78 + <artifactId>yudao-module-product-biz</artifactId>
  79 + <version>${revision}</version>
  80 + </dependency>
  81 + <dependency>
  82 + <groupId>cn.iocoder.boot</groupId>
  83 + <artifactId>yudao-module-trade-biz</artifactId>
  84 + <version>${revision}</version>
  85 + </dependency>
86 86
87 <!-- spring boot 配置所需依赖 --> 87 <!-- spring boot 配置所需依赖 -->
88 <dependency> 88 <dependency>