Commit e7d86436650ba7850026d7ba760a4d512b8f6737

Authored by puhui999
1 parent 9cbd0fec

fix:修复 mall review @puhui999

Showing 38 changed files with 207 additions and 244 deletions
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
@@ -4,6 +4,7 @@ import cn.hutool.core.date.LocalDateTimeUtil; @@ -4,6 +4,7 @@ import cn.hutool.core.date.LocalDateTimeUtil;
4 4
5 import java.time.Duration; 5 import java.time.Duration;
6 import java.time.LocalDateTime; 6 import java.time.LocalDateTime;
  7 +import java.time.LocalTime;
7 8
8 /** 9 /**
9 * 时间工具类,用于 {@link java.time.LocalDateTime} 10 * 时间工具类,用于 {@link java.time.LocalDateTime}
@@ -50,7 +51,7 @@ public class LocalDateTimeUtils { @@ -50,7 +51,7 @@ public class LocalDateTimeUtils {
50 * 判断当前时间是否在该时间范围内 51 * 判断当前时间是否在该时间范围内
51 * 52 *
52 * @param startTime 开始时间 53 * @param startTime 开始时间
53 - * @param endTime 结束时间 54 + * @param endTime 结束时间
54 * @return 是否 55 * @return 是否
55 */ 56 */
56 public static boolean isBetween(LocalDateTime startTime, LocalDateTime endTime) { 57 public static boolean isBetween(LocalDateTime startTime, LocalDateTime endTime) {
@@ -60,4 +61,23 @@ public class LocalDateTimeUtils { @@ -60,4 +61,23 @@ public class LocalDateTimeUtils {
60 return LocalDateTimeUtil.isIn(LocalDateTime.now(), startTime, endTime); 61 return LocalDateTimeUtil.isIn(LocalDateTime.now(), startTime, endTime);
61 } 62 }
62 63
  64 + /**
  65 + * 检查时间重叠 不包含日期
  66 + *
  67 + * @param startTime1 需要校验的开始时间
  68 + * @param endTime1 需要校验的结束时间
  69 + * @param startTime2 校验所需的开始时间
  70 + * @param endTime2 校验所需的结束时间
  71 + * @return 是否重叠
  72 + */
  73 + public static boolean checkTimeOverlap(LocalTime startTime1, LocalTime endTime1, LocalTime startTime2, LocalTime endTime2) {
  74 + // 判断时间是否重叠
  75 + // 开始时间在已配置时段的结束时间之前 且 结束时间在已配置时段的开始时间之后 []
  76 + return startTime1.isBefore(endTime2) && endTime1.isAfter(startTime2)
  77 + // 开始时间在已配置时段的开始时间之前 且 结束时间在已配置时段的开始时间之后 (] 或 ()
  78 + || startTime1.isBefore(startTime2) && endTime1.isAfter(startTime2)
  79 + // 开始时间在已配置时段的结束时间之前 且 结束时间在已配值时段的结束时间之后 [) 或 ()
  80 + || startTime1.isBefore(endTime2) && endTime1.isAfter(endTime2);
  81 + }
  82 +
63 } 83 }
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
@@ -46,7 +46,7 @@ public interface ErrorCodeConstants { @@ -46,7 +46,7 @@ public interface ErrorCodeConstants {
46 46
47 // ========== 商品 评价 1008007000 ========== 47 // ========== 商品 评价 1008007000 ==========
48 ErrorCode COMMENT_NOT_EXISTS = new ErrorCode(1008007000, "商品 评价 不存在"); 48 ErrorCode COMMENT_NOT_EXISTS = new ErrorCode(1008007000, "商品 评价 不存在");
49 - ErrorCode ORDER_SPU_COMMENT_EXISTS = new ErrorCode(1008007001, "订单 商品评价 已存在"); 49 + ErrorCode ORDER_SKU_COMMENT_EXISTS = new ErrorCode(1008007001, "订单 商品评价 已存在");
50 ErrorCode COMMENT_ERROR_OPT = new ErrorCode(1008007002, "商品评价非法操作"); 50 ErrorCode COMMENT_ERROR_OPT = new ErrorCode(1008007002, "商品评价非法操作");
51 ErrorCode COMMENT_ADDITIONAL_EXISTS = new ErrorCode(1008007003, "商品追加评价已存在"); 51 ErrorCode COMMENT_ADDITIONAL_EXISTS = new ErrorCode(1008007003, "商品追加评价已存在");
52 52
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentBaseVO.java
@@ -26,23 +26,10 @@ public class ProductCommentBaseVO { @@ -26,23 +26,10 @@ public class ProductCommentBaseVO {
26 @NotNull(message = "评价人头像不能为空") 26 @NotNull(message = "评价人头像不能为空")
27 private String userAvatar; 27 private String userAvatar;
28 28
29 - // TODO @puhui:spuId、spuName 是不是只有 ProductCommentRespVO 有呀。  
30 - @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑透气小短袖")  
31 - @NotNull(message = "商品 SPU 编号不能为空")  
32 - private Long spuId;  
33 -  
34 - @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")  
35 - @NotNull(message = "商品 SPU 名称不能为空")  
36 - private String spuName;  
37 -  
38 @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 29 @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
39 @NotNull(message = "商品 SKU 编号不能为空") 30 @NotNull(message = "商品 SKU 编号不能为空")
40 private Long skuId; 31 private Long skuId;
41 32
42 - @Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")  
43 - @NotNull(message = "评分星级不能为空")  
44 - private Integer scores;  
45 -  
46 @Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") 33 @Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
47 @NotNull(message = "描述星级不能为空") 34 @NotNull(message = "描述星级不能为空")
48 private Integer descriptionScores; 35 private Integer descriptionScores;
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java
@@ -35,9 +35,8 @@ public class ProductCommentPageReqVO extends PageParam { @@ -35,9 +35,8 @@ public class ProductCommentPageReqVO extends PageParam {
35 @InEnum(ProductCommentScoresEnum.class) 35 @InEnum(ProductCommentScoresEnum.class)
36 private Integer scores; 36 private Integer scores;
37 37
38 - // TODO @puhui999:replyStatus 哈  
39 @Schema(description = "商家是否回复", example = "true") 38 @Schema(description = "商家是否回复", example = "true")
40 - private Boolean replied; 39 + private Boolean replyStatus;
41 40
42 @Schema(description = "创建时间") 41 @Schema(description = "创建时间")
43 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 42 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java
@@ -5,6 +5,7 @@ import lombok.Data; @@ -5,6 +5,7 @@ import lombok.Data;
5 import lombok.EqualsAndHashCode; 5 import lombok.EqualsAndHashCode;
6 import lombok.ToString; 6 import lombok.ToString;
7 7
  8 +import javax.validation.constraints.NotNull;
8 import java.time.LocalDateTime; 9 import java.time.LocalDateTime;
9 10
10 @Schema(description = "管理后台 - 商品评价 Response VO") 11 @Schema(description = "管理后台 - 商品评价 Response VO")
@@ -40,4 +41,15 @@ public class ProductCommentRespVO extends ProductCommentBaseVO { @@ -40,4 +41,15 @@ public class ProductCommentRespVO extends ProductCommentBaseVO {
40 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) 41 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
41 private LocalDateTime createTime; 42 private LocalDateTime createTime;
42 43
  44 + @Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
  45 + private Integer scores;
  46 +
  47 + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑透气小短袖")
  48 + @NotNull(message = "商品 SPU 编号不能为空")
  49 + private Long spuId;
  50 +
  51 + @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
  52 + @NotNull(message = "商品 SPU 名称不能为空")
  53 + private String spuName;
  54 +
43 } 55 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
@@ -30,11 +30,6 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -30,11 +30,6 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
30 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; 30 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
31 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; 31 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
32 32
33 -/**  
34 - * 商品 SPU 相关接口  
35 - *  
36 - * @author HUIHUI  
37 - */  
38 @Tag(name = "管理后台 - 商品 SPU") 33 @Tag(name = "管理后台 - 商品 SPU")
39 @RestController 34 @RestController
40 @RequestMapping("/product/spu") 35 @RequestMapping("/product/spu")
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuCreateReqVO.java
@@ -9,11 +9,6 @@ import lombok.ToString; @@ -9,11 +9,6 @@ import lombok.ToString;
9 import javax.validation.Valid; 9 import javax.validation.Valid;
10 import java.util.List; 10 import java.util.List;
11 11
12 -/**  
13 - * 商品 SPU 创建 Request VO  
14 - *  
15 - * @author HUIHUI  
16 - */  
17 @Schema(description = "管理后台 - 商品 SPU 创建 Request VO") 12 @Schema(description = "管理后台 - 商品 SPU 创建 Request VO")
18 @Data 13 @Data
19 @EqualsAndHashCode(callSuper = true) 14 @EqualsAndHashCode(callSuper = true)
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
@@ -8,12 +8,6 @@ import lombok.ToString; @@ -8,12 +8,6 @@ import lombok.ToString;
8 8
9 import java.util.List; 9 import java.util.List;
10 10
11 -/**  
12 - * 商品 SPU 详细 Response VO  
13 - * 包括关联的 SKU 等信息  
14 - *  
15 - * @author HUIHUI  
16 - */  
17 @Schema(description = "管理后台 - 商品 SPU 详细 Response VO") 11 @Schema(description = "管理后台 - 商品 SPU 详细 Response VO")
18 @Data 12 @Data
19 @EqualsAndHashCode(callSuper = true) 13 @EqualsAndHashCode(callSuper = true)
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuExportReqVO.java
@@ -10,11 +10,6 @@ import java.time.LocalDateTime; @@ -10,11 +10,6 @@ import java.time.LocalDateTime;
10 10
11 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; 11 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
12 12
13 -/**  
14 - * 商品Spu导出 Request VO,参数和 ProductSpuPageReqVO 是一致的  
15 - *  
16 - * @author HUIHUI  
17 - */  
18 @Schema(description = "管理后台 - 商品Spu导出 Request VO,参数和 ProductSpuPageReqVO 是一致的") 13 @Schema(description = "管理后台 - 商品Spu导出 Request VO,参数和 ProductSpuPageReqVO 是一致的")
19 @Data 14 @Data
20 @NoArgsConstructor 15 @NoArgsConstructor
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
@@ -11,11 +11,6 @@ import java.time.LocalDateTime; @@ -11,11 +11,6 @@ import java.time.LocalDateTime;
11 11
12 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; 12 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
13 13
14 -/**  
15 - * 商品 SPU 分页 Request VO  
16 - *  
17 - * @author HUIHUI  
18 - */  
19 @Schema(description = "管理后台 - 商品 SPU 分页 Request VO") 14 @Schema(description = "管理后台 - 商品 SPU 分页 Request VO")
20 @Data 15 @Data
21 @EqualsAndHashCode(callSuper = true) 16 @EqualsAndHashCode(callSuper = true)
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
@@ -7,11 +7,6 @@ import lombok.ToString; @@ -7,11 +7,6 @@ import lombok.ToString;
7 7
8 import java.time.LocalDateTime; 8 import java.time.LocalDateTime;
9 9
10 -/**  
11 - * 商品 SPU Response VO  
12 - *  
13 - * @author HUIHUI  
14 - */  
15 @Schema(description = "管理后台 - 商品 SPU Response VO") 10 @Schema(description = "管理后台 - 商品 SPU Response VO")
16 @Data 11 @Data
17 @EqualsAndHashCode(callSuper = true) 12 @EqualsAndHashCode(callSuper = true)
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java
@@ -4,11 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema; @@ -4,11 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
4 import lombok.Data; 4 import lombok.Data;
5 import lombok.ToString; 5 import lombok.ToString;
6 6
7 -/**  
8 - * 商品 SPU 精简 Response VO  
9 - * TODO 商品 SPU 精简 VO 暂时没有使用到,用到的时候再按需添加\修改属性  
10 - * @author HUIHUI  
11 - */  
12 @Schema(description = "管理后台 - 商品 SPU 精简 Response VO") 7 @Schema(description = "管理后台 - 商品 SPU 精简 Response VO")
13 @Data 8 @Data
14 @ToString(callSuper = true) 9 @ToString(callSuper = true)
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateReqVO.java
@@ -12,11 +12,6 @@ import javax.validation.Valid; @@ -12,11 +12,6 @@ import javax.validation.Valid;
12 import javax.validation.constraints.NotNull; 12 import javax.validation.constraints.NotNull;
13 import java.util.List; 13 import java.util.List;
14 14
15 -/**  
16 - * 商品 SPU 更新 Request VO  
17 - *  
18 - * @author HUIHUI  
19 - */  
20 @Schema(description = "管理后台 - 商品 SPU 更新 Request VO") 15 @Schema(description = "管理后台 - 商品 SPU 更新 Request VO")
21 @Data 16 @Data
22 @EqualsAndHashCode(callSuper = true) 17 @EqualsAndHashCode(callSuper = true)
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java
@@ -7,11 +7,6 @@ import lombok.Data; @@ -7,11 +7,6 @@ import lombok.Data;
7 7
8 import javax.validation.constraints.NotNull; 8 import javax.validation.constraints.NotNull;
9 9
10 -/**  
11 - * 商品 SPU Status 更新 Request VO  
12 - *  
13 - * @author HUIHUI  
14 - */  
15 @Schema(description = "管理后台 - 商品 SPU Status 更新 Request VO") 10 @Schema(description = "管理后台 - 商品 SPU Status 更新 Request VO")
16 @Data 11 @Data
17 public class ProductSpuUpdateStatusReqVO{ 12 public class ProductSpuUpdateStatusReqVO{
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; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.hutool.core.util.ObjectUtil;  
5 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 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;
7 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; 7 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO;
8 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO; 8 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO;
9 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO; 9 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO;
10 -import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;  
11 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert; 10 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert;
12 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; 11 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
13 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; 12 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
14 import cn.iocoder.yudao.module.product.service.comment.ProductCommentService; 13 import cn.iocoder.yudao.module.product.service.comment.ProductCommentService;
15 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; 14 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
  15 +import com.google.common.collect.Maps;
16 import io.swagger.v3.oas.annotations.Operation; 16 import io.swagger.v3.oas.annotations.Operation;
17 import io.swagger.v3.oas.annotations.Parameter; 17 import io.swagger.v3.oas.annotations.Parameter;
18 import io.swagger.v3.oas.annotations.Parameters; 18 import io.swagger.v3.oas.annotations.Parameters;
@@ -26,11 +26,9 @@ import org.springframework.web.bind.annotation.RestController; @@ -26,11 +26,9 @@ import org.springframework.web.bind.annotation.RestController;
26 26
27 import javax.annotation.Resource; 27 import javax.annotation.Resource;
28 import javax.validation.Valid; 28 import javax.validation.Valid;
29 -import java.util.HashMap;  
30 import java.util.List; 29 import java.util.List;
31 import java.util.Map; 30 import java.util.Map;
32 import java.util.Set; 31 import java.util.Set;
33 -import java.util.stream.Collectors;  
34 32
35 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 33 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
36 34
@@ -61,26 +59,14 @@ public class AppProductCommentController { @@ -61,26 +59,14 @@ public class AppProductCommentController {
61 @GetMapping("/page") 59 @GetMapping("/page")
62 @Operation(summary = "获得商品评价分页") 60 @Operation(summary = "获得商品评价分页")
63 public CommonResult<PageResult<AppProductCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) { 61 public CommonResult<PageResult<AppProductCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) {
64 - PageResult<AppProductCommentRespVO> page = productCommentService.getCommentPage(pageVO, Boolean.TRUE);  
65 - // TODO @puhui CollUtils 有简化 convertmap 和 list 的方法  
66 - Set<Long> skuIds = page.getList().stream().map(AppProductCommentRespVO::getSkuId).collect(Collectors.toSet()); 62 + PageResult<ProductCommentDO> commentDOPage = productCommentService.getCommentPage(pageVO, Boolean.TRUE);
  63 + Set<Long> skuIds = CollectionUtils.convertSet(commentDOPage.getList(), ProductCommentDO::getSkuId);
67 List<ProductSkuDO> skuList = productSkuService.getSkuList(skuIds); 64 List<ProductSkuDO> skuList = productSkuService.getSkuList(skuIds);
68 - Map<Long, ProductSkuDO> skuDOMap = new HashMap<>(skuIds.size()); 65 + Map<Long, ProductSkuDO> skuDOMap = Maps.newLinkedHashMapWithExpectedSize(skuIds.size());
69 if (CollUtil.isNotEmpty(skuList)) { 66 if (CollUtil.isNotEmpty(skuList)) {
70 - skuDOMap.putAll(skuList.stream().collect(Collectors.toMap(ProductSkuDO::getId, c -> c))); 67 + skuDOMap.putAll(CollectionUtils.convertMap(skuList, ProductSkuDO::getId, c -> c));
71 } 68 }
72 - // TODO @puihui999:下面也可以放到 convert 里哈  
73 - page.getList().forEach(item -> {  
74 - // 判断用户是否选择匿名  
75 - if (ObjectUtil.equal(item.getAnonymous(), true)) {  
76 - item.setUserNickname(ProductCommentDO.NICKNAME_ANONYMOUS);  
77 - }  
78 - ProductSkuDO productSkuDO = skuDOMap.get(item.getSkuId());  
79 - if (productSkuDO != null) {  
80 - List<AppProductPropertyValueDetailRespVO> skuProperties = ProductCommentConvert.INSTANCE.convertList01(productSkuDO.getProperties());  
81 - item.setSkuProperties(skuProperties);  
82 - }  
83 - }); 69 + PageResult<AppProductCommentRespVO> page = ProductCommentConvert.INSTANCE.convertPage02(commentDOPage, skuDOMap);
84 return success(page); 70 return success(page);
85 } 71 }
86 72
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java
@@ -10,11 +10,6 @@ import javax.validation.constraints.Size; @@ -10,11 +10,6 @@ import javax.validation.constraints.Size;
10 import java.time.LocalDateTime; 10 import java.time.LocalDateTime;
11 import java.util.List; 11 import java.util.List;
12 12
13 -/**  
14 - * 用户 App - 商品评价详情 Response VO  
15 - *  
16 - * @author HUIHUI  
17 - */  
18 @Schema(description = "用户 App - 商品评价详情 Response VO") 13 @Schema(description = "用户 App - 商品评价详情 Response VO")
19 @Data 14 @Data
20 @ToString(callSuper = true) 15 @ToString(callSuper = true)
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.util.ObjectUtil;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; 5 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
5 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; 6 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
@@ -19,6 +20,7 @@ import org.mapstruct.factory.Mappers; @@ -19,6 +20,7 @@ import org.mapstruct.factory.Mappers;
19 import java.math.BigDecimal; 20 import java.math.BigDecimal;
20 import java.math.RoundingMode; 21 import java.math.RoundingMode;
21 import java.util.List; 22 import java.util.List;
  23 +import java.util.Map;
22 24
23 /** 25 /**
24 * 商品评价 Convert 26 * 商品评价 Convert
@@ -32,10 +34,12 @@ public interface ProductCommentConvert { @@ -32,10 +34,12 @@ public interface ProductCommentConvert {
32 34
33 ProductCommentRespVO convert(ProductCommentDO bean); 35 ProductCommentRespVO convert(ProductCommentDO bean);
34 36
35 - // TODO @puhui999:这里貌似字段对上,就不用 mapping 了;可以测试下看看哈  
36 - @Mapping(target = "goodCount", source = "goodCount")  
37 - @Mapping(target = "mediocreCount", source = "mediocreCount")  
38 - @Mapping(target = "negativeCount", source = "negativeCount") 37 + @Named("calculateOverallScore")
  38 + default double calculateOverallScore(long goodCount, long mediocreCount, long negativeCount) {
  39 + return (goodCount * 5 + mediocreCount * 3 + negativeCount) / (double) (goodCount + mediocreCount + negativeCount);
  40 + }
  41 +
  42 + @Mapping(target = "scores", expression = "java(calculateOverallScore(goodCount, mediocreCount, negativeCount))")
39 AppCommentStatisticsRespVO convert(Long goodCount, Long mediocreCount, Long negativeCount); 43 AppCommentStatisticsRespVO convert(Long goodCount, Long mediocreCount, Long negativeCount);
40 44
41 List<ProductCommentRespVO> convertList(List<ProductCommentDO> list); 45 List<ProductCommentRespVO> convertList(List<ProductCommentDO> list);
@@ -44,7 +48,23 @@ public interface ProductCommentConvert { @@ -44,7 +48,23 @@ public interface ProductCommentConvert {
44 48
45 PageResult<ProductCommentRespVO> convertPage(PageResult<ProductCommentDO> page); 49 PageResult<ProductCommentRespVO> convertPage(PageResult<ProductCommentDO> page);
46 50
47 - PageResult<AppProductCommentRespVO> convertPage02(PageResult<ProductCommentDO> pageResult); 51 + PageResult<AppProductCommentRespVO> convertPage01(PageResult<ProductCommentDO> pageResult);
  52 +
  53 + default PageResult<AppProductCommentRespVO> convertPage02(PageResult<ProductCommentDO> pageResult, Map<Long, ProductSkuDO> skuDOMap) {
  54 + PageResult<AppProductCommentRespVO> page = convertPage01(pageResult);
  55 + page.getList().forEach(item -> {
  56 + // 判断用户是否选择匿名
  57 + if (ObjectUtil.equal(item.getAnonymous(), true)) {
  58 + item.setUserNickname(ProductCommentDO.NICKNAME_ANONYMOUS);
  59 + }
  60 + ProductSkuDO productSkuDO = skuDOMap.get(item.getSkuId());
  61 + if (productSkuDO != null) {
  62 + List<AppProductPropertyValueDetailRespVO> skuProperties = ProductCommentConvert.INSTANCE.convertList01(productSkuDO.getProperties());
  63 + item.setSkuProperties(skuProperties);
  64 + }
  65 + });
  66 + return page;
  67 + }
48 68
49 /** 69 /**
50 * 计算综合评分 70 * 计算综合评分
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java
@@ -51,11 +51,11 @@ public interface ProductCommentMapper extends BaseMapperX&lt;ProductCommentDO&gt; { @@ -51,11 +51,11 @@ public interface ProductCommentMapper extends BaseMapperX&lt;ProductCommentDO&gt; {
51 return selectPage(reqVO, queryWrapper); 51 return selectPage(reqVO, queryWrapper);
52 } 52 }
53 53
54 - default ProductCommentDO selectByUserIdAndOrderItemIdAndSpuId(Long userId, Long orderItemId, Long spuId) { 54 + default ProductCommentDO selectByUserIdAndOrderItemIdAndSpuId(Long userId, Long orderItemId, Long skuId) {
55 return selectOne(new LambdaQueryWrapperX<ProductCommentDO>() 55 return selectOne(new LambdaQueryWrapperX<ProductCommentDO>()
56 .eq(ProductCommentDO::getUserId, userId) 56 .eq(ProductCommentDO::getUserId, userId)
57 .eq(ProductCommentDO::getOrderItemId, orderItemId) 57 .eq(ProductCommentDO::getOrderItemId, orderItemId)
58 - .eq(ProductCommentDO::getSpuId, spuId)); 58 + .eq(ProductCommentDO::getSpuId, skuId));
59 } 59 }
60 60
61 default Long selectCountBySpuId(Long spuId, Boolean visible, Integer type) { 61 default Long selectCountBySpuId(Long spuId, Boolean visible, Integer type) {
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java
@@ -54,7 +54,7 @@ public interface ProductCommentService { @@ -54,7 +54,7 @@ public interface ProductCommentService {
54 * @param visible 是否可见 54 * @param visible 是否可见
55 * @return 商品评价分页 55 * @return 商品评价分页
56 */ 56 */
57 - PageResult<AppProductCommentRespVO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible); 57 + PageResult<ProductCommentDO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible);
58 58
59 /** 59 /**
60 * 创建商品评论 60 * 创建商品评论
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java
@@ -81,7 +81,7 @@ public class ProductCommentServiceImpl implements ProductCommentService { @@ -81,7 +81,7 @@ public class ProductCommentServiceImpl implements ProductCommentService {
81 @Transactional(rollbackFor = Exception.class) 81 @Transactional(rollbackFor = Exception.class)
82 public void createComment(ProductCommentCreateReqVO createReqVO) { 82 public void createComment(ProductCommentCreateReqVO createReqVO) {
83 // 校验评论 83 // 校验评论
84 - validateComment(createReqVO.getSpuId(), createReqVO.getUserId(), createReqVO.getOrderItemId()); 84 + validateComment(createReqVO.getSkuId(), createReqVO.getUserId(), createReqVO.getOrderItemId());
85 85
86 ProductCommentDO commentDO = ProductCommentConvert.INSTANCE.convert(createReqVO); 86 ProductCommentDO commentDO = ProductCommentConvert.INSTANCE.convert(createReqVO);
87 productCommentMapper.insert(commentDO); 87 productCommentMapper.insert(commentDO);
@@ -108,11 +108,11 @@ public class ProductCommentServiceImpl implements ProductCommentService { @@ -108,11 +108,11 @@ public class ProductCommentServiceImpl implements ProductCommentService {
108 return commentDO.getId(); 108 return commentDO.getId();
109 } 109 }
110 110
111 - private void validateComment(Long spuId, Long userId, Long orderItemId) { 111 + private void validateComment(Long skuId, Long userId, Long orderItemId) {
112 // 判断当前订单的当前商品用户是否评价过 112 // 判断当前订单的当前商品用户是否评价过
113 - ProductCommentDO exist = productCommentMapper.selectByUserIdAndOrderItemIdAndSpuId(userId, orderItemId, spuId); 113 + ProductCommentDO exist = productCommentMapper.selectByUserIdAndOrderItemIdAndSpuId(userId, orderItemId, skuId);
114 if (null != exist) { 114 if (null != exist) {
115 - throw exception(ORDER_SPU_COMMENT_EXISTS); 115 + throw exception(ORDER_SKU_COMMENT_EXISTS);
116 } 116 }
117 } 117 }
118 118
@@ -141,23 +141,17 @@ public class ProductCommentServiceImpl implements ProductCommentService { @@ -141,23 +141,17 @@ public class ProductCommentServiceImpl implements ProductCommentService {
141 productCommentMapper.selectCountBySpuId(spuId, visible, AppCommentPageReqVO.MEDIOCRE_COMMENT), 141 productCommentMapper.selectCountBySpuId(spuId, visible, AppCommentPageReqVO.MEDIOCRE_COMMENT),
142 // 查询商品 id = spuId 的所有差评数量 142 // 查询商品 id = spuId 的所有差评数量
143 productCommentMapper.selectCountBySpuId(spuId, visible, AppCommentPageReqVO.NEGATIVE_COMMENT) 143 productCommentMapper.selectCountBySpuId(spuId, visible, AppCommentPageReqVO.NEGATIVE_COMMENT)
144 - ).setScores(3.0); // TODO @puhui999:这里要实现下;; 144 + );
145 } 145 }
146 146
147 @Override 147 @Override
148 public List<AppProductCommentRespVO> getCommentList(Long spuId, Integer count) { 148 public List<AppProductCommentRespVO> getCommentList(Long spuId, Integer count) {
149 - // 校验商品 spu 是否存在  
150 - // TODO @puhui 这里校验可以去掉哈。  
151 - ProductSpuDO spuDO = validateSpu(spuId);  
152 - return ProductCommentConvert.INSTANCE.convertList02(productCommentMapper.selectCommentList(spuDO.getId(), count).getList()); 149 + return ProductCommentConvert.INSTANCE.convertList02(productCommentMapper.selectCommentList(spuId, count).getList());
153 } 150 }
154 151
155 - // TODO @puhui 可以放到 controller 去 convert 哈  
156 @Override 152 @Override
157 - public PageResult<AppProductCommentRespVO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible) {  
158 - // TODO @puhui 可以放到 controller 去 convert 哈  
159 - return ProductCommentConvert.INSTANCE.convertPage02(  
160 - productCommentMapper.selectPage(pageVO, visible)); 153 + public PageResult<ProductCommentDO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible) {
  154 + return productCommentMapper.selectPage(pageVO, visible);
161 } 155 }
162 156
163 @Override 157 @Override
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java
@@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommen @@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommen
10 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO; 10 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO;
11 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; 11 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO;
12 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO; 12 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO;
13 -import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO;  
14 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert; 13 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert;
15 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; 14 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
16 import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper; 15 import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper;
@@ -128,7 +127,7 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest { @@ -128,7 +127,7 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
128 productCommentPageReqVO.setSpuId(spuId); 127 productCommentPageReqVO.setSpuId(spuId);
129 productCommentPageReqVO.setSpuName("感冒药"); 128 productCommentPageReqVO.setSpuName("感冒药");
130 productCommentPageReqVO.setScores(ProductCommentScoresEnum.FOUR.getScores()); 129 productCommentPageReqVO.setScores(ProductCommentScoresEnum.FOUR.getScores());
131 - productCommentPageReqVO.setReplied(Boolean.TRUE); 130 + productCommentPageReqVO.setReplyStatus(Boolean.TRUE);
132 131
133 PageResult<ProductCommentDO> commentPage = productCommentService.getCommentPage(productCommentPageReqVO); 132 PageResult<ProductCommentDO> commentPage = productCommentService.getCommentPage(productCommentPageReqVO);
134 PageResult<ProductCommentRespVO> result = ProductCommentConvert.INSTANCE.convertPage(productCommentMapper.selectPage(productCommentPageReqVO)); 133 PageResult<ProductCommentRespVO> result = ProductCommentConvert.INSTANCE.convertPage(productCommentMapper.selectPage(productCommentPageReqVO));
@@ -138,15 +137,15 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest { @@ -138,15 +137,15 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
138 assertEquals(8, all.getTotal()); 137 assertEquals(8, all.getTotal());
139 138
140 // 测试获取所有商品分页评论数据 139 // 测试获取所有商品分页评论数据
141 - PageResult<AppProductCommentRespVO> result1 = productCommentService.getCommentPage(new AppCommentPageReqVO(), Boolean.TRUE); 140 + PageResult<ProductCommentDO> result1 = productCommentService.getCommentPage(new AppCommentPageReqVO(), Boolean.TRUE);
142 assertEquals(7, result1.getTotal()); 141 assertEquals(7, result1.getTotal());
143 142
144 // 测试获取所有商品分页中评数据 143 // 测试获取所有商品分页中评数据
145 - PageResult<AppProductCommentRespVO> result2 = productCommentService.getCommentPage(new AppCommentPageReqVO().setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE); 144 + PageResult<ProductCommentDO> result2 = productCommentService.getCommentPage(new AppCommentPageReqVO().setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE);
146 assertEquals(2, result2.getTotal()); 145 assertEquals(2, result2.getTotal());
147 146
148 // 测试获取指定 spuId 商品分页中评数据 147 // 测试获取指定 spuId 商品分页中评数据
149 - PageResult<AppProductCommentRespVO> result3 = productCommentService.getCommentPage(new AppCommentPageReqVO().setSpuId(spuId).setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE); 148 + PageResult<ProductCommentDO> result3 = productCommentService.getCommentPage(new AppCommentPageReqVO().setSpuId(spuId).setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE);
150 assertEquals(2, result3.getTotal()); 149 assertEquals(2, result3.getTotal());
151 150
152 // 测试分页 tab count 151 // 测试分页 tab count
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java
@@ -19,11 +19,6 @@ import java.util.List; @@ -19,11 +19,6 @@ import java.util.List;
19 19
20 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 20 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
21 21
22 -/**  
23 - * 管理后台 - 秒杀时段相关接口  
24 - *  
25 - * @author HUIHUI  
26 - */  
27 @Tag(name = "管理后台 - 秒杀时段") 22 @Tag(name = "管理后台 - 秒杀时段")
28 @RestController 23 @RestController
29 @RequestMapping("/promotion/seckill-config") 24 @RequestMapping("/promotion/seckill-config")
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java
@@ -9,11 +9,6 @@ import lombok.ToString; @@ -9,11 +9,6 @@ import lombok.ToString;
9 import java.time.LocalDateTime; 9 import java.time.LocalDateTime;
10 import java.util.List; 10 import java.util.List;
11 11
12 -/**  
13 - * 管理后台 - 秒杀活动 Response VO  
14 - *  
15 - * @author HUIHUI  
16 - */  
17 @Schema(description = "管理后台 - 秒杀活动 Response VO") 12 @Schema(description = "管理后台 - 秒杀活动 Response VO")
18 @Data 13 @Data
19 @EqualsAndHashCode(callSuper = true) 14 @EqualsAndHashCode(callSuper = true)
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigBaseVO.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config;
2 2
  3 +import com.fasterxml.jackson.annotation.JsonIgnore;
3 import io.swagger.v3.oas.annotations.media.Schema; 4 import io.swagger.v3.oas.annotations.media.Schema;
4 import lombok.Data; 5 import lombok.Data;
5 6
  7 +import javax.validation.constraints.AssertTrue;
6 import javax.validation.constraints.NotNull; 8 import javax.validation.constraints.NotNull;
  9 +import java.time.LocalTime;
  10 +import java.util.List;
7 11
8 /** 12 /**
9 * 秒杀时段 Base VO,提供给添加、修改、详细的子 VO 使用 13 * 秒杀时段 Base VO,提供给添加、修改、详细的子 VO 使用
@@ -26,12 +30,24 @@ public class SeckillConfigBaseVO { @@ -26,12 +30,24 @@ public class SeckillConfigBaseVO {
26 @NotNull(message = "结束时间点不能为空") 30 @NotNull(message = "结束时间点不能为空")
27 private String endTime; 31 private String endTime;
28 32
29 - @Schema(description = "秒杀主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn")  
30 - @NotNull(message = "秒杀主图不能为空")  
31 - private String picUrl; 33 + @Schema(description = "秒杀轮播图", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png]")
  34 + @NotNull(message = "秒杀轮播图不能为空")
  35 + private List<String> sliderPicUrls;
32 36
33 @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") 37 @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
34 @NotNull(message = "状态不能为空") 38 @NotNull(message = "状态不能为空")
35 private Integer status; 39 private Integer status;
36 40
  41 + @AssertTrue(message = "秒杀时段开始时间和结束时间不能相等")
  42 + @JsonIgnore
  43 + public boolean isValidStartTimeValid() {
  44 + return !LocalTime.parse(startTime).equals(LocalTime.parse(endTime));
  45 + }
  46 +
  47 + @AssertTrue(message = "秒杀时段开始时间不能在结束时间之后")
  48 + @JsonIgnore
  49 + public boolean isValidEndTimeValid() {
  50 + return !LocalTime.parse(startTime).isAfter(LocalTime.parse(endTime));
  51 + }
  52 +
37 } 53 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigPageReqVO.java
@@ -6,12 +6,6 @@ import lombok.Data; @@ -6,12 +6,6 @@ import lombok.Data;
6 import lombok.EqualsAndHashCode; 6 import lombok.EqualsAndHashCode;
7 import lombok.ToString; 7 import lombok.ToString;
8 8
9 -// TODO @puhui:VO 上不写注释,已经有注解啦。  
10 -/**  
11 - * 管理后台 - 秒杀时段分页 Request VO  
12 - *  
13 - * @author HUIHUI  
14 - */  
15 @Schema(description = "管理后台 - 秒杀时段分页 Request VO") 9 @Schema(description = "管理后台 - 秒杀时段分页 Request VO")
16 @Data 10 @Data
17 @EqualsAndHashCode(callSuper = true) 11 @EqualsAndHashCode(callSuper = true)
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductCreateReqVO.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;
2 2
3 -import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;  
4 -import lombok.*;  
5 -import java.util.*;  
6 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
7 -import javax.validation.constraints.*;  
8 -  
9 -/**  
10 - * 管理后台 - 秒杀参与商品创建 Request VO  
11 - *  
12 - * @author HUIHUI  
13 - */ 4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
14 @Schema(description = "管理后台 - 秒杀参与商品创建 Request VO") 7 @Schema(description = "管理后台 - 秒杀参与商品创建 Request VO")
15 @Data 8 @Data
16 @EqualsAndHashCode(callSuper = true) 9 @EqualsAndHashCode(callSuper = true)
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductRespVO.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;
2 2
3 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 -import lombok.*; 4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
  7 +
5 import java.time.LocalDateTime; 8 import java.time.LocalDateTime;
6 9
7 -/**  
8 - * 管理后台 - 秒杀参与商品 Response VO  
9 - *  
10 - * @author HUIHUI  
11 - */  
12 @Schema(description = "管理后台 - 秒杀参与商品 Response VO") 10 @Schema(description = "管理后台 - 秒杀参与商品 Response VO")
13 @Data 11 @Data
14 @EqualsAndHashCode(callSuper = true) 12 @EqualsAndHashCode(callSuper = true)
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductUpdateReqVO.java
@@ -5,11 +5,6 @@ import lombok.Data; @@ -5,11 +5,6 @@ import lombok.Data;
5 import lombok.EqualsAndHashCode; 5 import lombok.EqualsAndHashCode;
6 import lombok.ToString; 6 import lombok.ToString;
7 7
8 -/**  
9 - * 管理后台 - 秒杀参与商品更新 Request VO  
10 - *  
11 - * @author HUIHUI  
12 - */  
13 @Schema(description = "管理后台 - 秒杀参与商品更新 Request VO") 8 @Schema(description = "管理后台 - 秒杀参与商品更新 Request VO")
14 @Data 9 @Data
15 @EqualsAndHashCode(callSuper = true) 10 @EqualsAndHashCode(callSuper = true)
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillconfig/SeckillConfigDO.java
@@ -3,22 +3,27 @@ package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig; @@ -3,22 +3,27 @@ package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig;
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;
5 import com.baomidou.mybatisplus.annotation.KeySequence; 5 import com.baomidou.mybatisplus.annotation.KeySequence;
  6 +import com.baomidou.mybatisplus.annotation.TableField;
6 import com.baomidou.mybatisplus.annotation.TableId; 7 import com.baomidou.mybatisplus.annotation.TableId;
7 import com.baomidou.mybatisplus.annotation.TableName; 8 import com.baomidou.mybatisplus.annotation.TableName;
8 -import lombok.Data;  
9 -import lombok.EqualsAndHashCode;  
10 -import lombok.ToString; 9 +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
  10 +import lombok.*;
  11 +
  12 +import java.util.List;
11 13
12 /** 14 /**
13 * 秒杀时段 DO 15 * 秒杀时段 DO
14 * 16 *
15 * @author 芋道源码 17 * @author 芋道源码
16 */ 18 */
17 -@TableName("promotion_seckill_config") 19 +@TableName(value = "promotion_seckill_config", autoResultMap = true)
18 @KeySequence("promotion_seckill_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 20 @KeySequence("promotion_seckill_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
19 @Data 21 @Data
20 @EqualsAndHashCode(callSuper = true) 22 @EqualsAndHashCode(callSuper = true)
21 @ToString(callSuper = true) 23 @ToString(callSuper = true)
  24 +@Builder
  25 +@NoArgsConstructor
  26 +@AllArgsConstructor
22 public class SeckillConfigDO extends BaseDO { 27 public class SeckillConfigDO extends BaseDO {
23 28
24 /** 29 /**
@@ -38,14 +43,14 @@ public class SeckillConfigDO extends BaseDO { @@ -38,14 +43,14 @@ public class SeckillConfigDO extends BaseDO {
38 * 结束时间点 43 * 结束时间点
39 */ 44 */
40 private String endTime; 45 private String endTime;
41 - // TODO puhui999:应该是轮播图; private List<String> sliderPicUrls;  
42 /** 46 /**
43 - * 秒杀主图 47 + * 秒杀轮播图
44 */ 48 */
45 - private String picUrl; 49 + @TableField(typeHandler = JacksonTypeHandler.class)
  50 + private List<String> sliderPicUrls;
46 /** 51 /**
47 * 状态 52 * 状态
48 - * 53 + * <p>
49 * 枚举 {@link CommonStatusEnum 对应的类} 54 * 枚举 {@link CommonStatusEnum 对应的类}
50 */ 55 */
51 private Integer status; 56 private Integer status;
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillconfig/SeckillConfigMapper.java
@@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.Seck @@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.Seck
7 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO; 7 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
8 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
9 9
  10 +import java.util.List;
  11 +
10 @Mapper 12 @Mapper
11 public interface SeckillConfigMapper extends BaseMapperX<SeckillConfigDO> { 13 public interface SeckillConfigMapper extends BaseMapperX<SeckillConfigDO> {
12 14
@@ -17,4 +19,9 @@ public interface SeckillConfigMapper extends BaseMapperX&lt;SeckillConfigDO&gt; { @@ -17,4 +19,9 @@ public interface SeckillConfigMapper extends BaseMapperX&lt;SeckillConfigDO&gt; {
17 .orderByDesc(SeckillConfigDO::getId)); 19 .orderByDesc(SeckillConfigDO::getId));
18 } 20 }
19 21
  22 + default List<SeckillConfigDO> selectListByStatus(Integer status) {
  23 + return selectList(SeckillConfigDO::getStatus, status);
  24 + }
  25 +
  26 +
20 } 27 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigServiceImpl.java
@@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjectUtil; @@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 7 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  8 +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
8 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO; 9 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO;
9 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigPageReqVO; 10 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigPageReqVO;
10 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigUpdateReqVO; 11 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigUpdateReqVO;
@@ -12,14 +13,13 @@ import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillCo @@ -12,14 +13,13 @@ import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillCo
12 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO; 13 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
13 import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillconfig.SeckillConfigMapper; 14 import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillconfig.SeckillConfigMapper;
14 import org.springframework.stereotype.Service; 15 import org.springframework.stereotype.Service;
  16 +import org.springframework.transaction.annotation.Transactional;
15 import org.springframework.validation.annotation.Validated; 17 import org.springframework.validation.annotation.Validated;
16 18
17 import javax.annotation.Resource; 19 import javax.annotation.Resource;
18 import java.time.LocalTime; 20 import java.time.LocalTime;
19 import java.util.Collection; 21 import java.util.Collection;
20 import java.util.List; 22 import java.util.List;
21 -import java.util.Set;  
22 -import java.util.stream.Collectors;  
23 23
24 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 24 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
25 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; 25 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
@@ -37,9 +37,10 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { @@ -37,9 +37,10 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
37 private SeckillConfigMapper seckillConfigMapper; 37 private SeckillConfigMapper seckillConfigMapper;
38 38
39 @Override 39 @Override
  40 + @Transactional(rollbackFor = Exception.class)
40 public Long createSeckillConfig(SeckillConfigCreateReqVO createReqVO) { 41 public Long createSeckillConfig(SeckillConfigCreateReqVO createReqVO) {
41 // 校验时间段是否冲突 42 // 校验时间段是否冲突
42 - validateSeckillConfigConflict(createReqVO.getStartTime(), createReqVO.getEndTime()); 43 + validateSeckillConfigConflict(createReqVO.getStartTime(), createReqVO.getEndTime(), null);
43 44
44 // 插入 45 // 插入
45 SeckillConfigDO seckillConfig = SeckillConfigConvert.INSTANCE.convert(createReqVO); 46 SeckillConfigDO seckillConfig = SeckillConfigConvert.INSTANCE.convert(createReqVO);
@@ -49,18 +50,30 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { @@ -49,18 +50,30 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
49 } 50 }
50 51
51 @Override 52 @Override
  53 + @Transactional(rollbackFor = Exception.class)
52 public void updateSeckillConfig(SeckillConfigUpdateReqVO updateReqVO) { 54 public void updateSeckillConfig(SeckillConfigUpdateReqVO updateReqVO) {
53 // 校验存在 55 // 校验存在
54 validateSeckillConfigExists(updateReqVO.getId()); 56 validateSeckillConfigExists(updateReqVO.getId());
55 // 校验时间段是否冲突 57 // 校验时间段是否冲突
56 - validateSeckillConfigConflict(updateReqVO.getStartTime(), updateReqVO.getEndTime()); 58 + validateSeckillConfigConflict(updateReqVO.getStartTime(), updateReqVO.getEndTime(), updateReqVO.getId());
57 59
58 // 更新 60 // 更新
59 SeckillConfigDO updateObj = SeckillConfigConvert.INSTANCE.convert(updateReqVO); 61 SeckillConfigDO updateObj = SeckillConfigConvert.INSTANCE.convert(updateReqVO);
60 seckillConfigMapper.updateById(updateObj); 62 seckillConfigMapper.updateById(updateObj);
61 } 63 }
62 64
  65 + // TODO @puhui999: 这个要不合并到更新操作里? 不单独有个操作咧; 更新状态不用那么多必须的参数,更新的时候需要校验时间段
63 @Override 66 @Override
  67 + public void updateSeckillConfigStatus(Long id, Integer status) {
  68 + // 校验秒杀时段是否存在
  69 + validateSeckillConfigExists(id);
  70 +
  71 + // 更新状态
  72 + seckillConfigMapper.updateById(new SeckillConfigDO().setId(id).setStatus(status));
  73 + }
  74 +
  75 + @Override
  76 + @Transactional(rollbackFor = Exception.class)
64 public void deleteSeckillConfig(Long id) { 77 public void deleteSeckillConfig(Long id) {
65 // 校验存在 78 // 校验存在
66 validateSeckillConfigExists(id); 79 validateSeckillConfigExists(id);
@@ -81,39 +94,29 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { @@ -81,39 +94,29 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
81 * @param startTime 开始时间 94 * @param startTime 开始时间
82 * @param endTime 结束时间 95 * @param endTime 结束时间
83 */ 96 */
84 - private void validateSeckillConfigConflict(String startTime, String endTime) { 97 + private void validateSeckillConfigConflict(String startTime, String endTime, Long seckillConfigId) {
85 LocalTime startTime1 = LocalTime.parse(startTime); 98 LocalTime startTime1 = LocalTime.parse(startTime);
86 LocalTime endTime1 = LocalTime.parse(endTime); 99 LocalTime endTime1 = LocalTime.parse(endTime);
87 - // TODO @puhui999: 这个可以用 validator 里的 assertTrue 去做哈;  
88 - // 检查选择的时间是否相等  
89 - if (startTime1.equals(endTime1)) {  
90 - throw exception(SECKILL_TIME_EQUAL);  
91 - }  
92 - // 检查开始时间是否在结束时间之前  
93 - if (startTime1.isAfter(endTime1)) {  
94 - throw exception(SECKILL_START_TIME_BEFORE_END_TIME);  
95 - }  
96 // 查询出所有的时段配置 100 // 查询出所有的时段配置
97 List<SeckillConfigDO> configDOs = seckillConfigMapper.selectList(); 101 List<SeckillConfigDO> configDOs = seckillConfigMapper.selectList();
  102 + // 更新时排除自己
  103 + if (seckillConfigId != null) {
  104 + configDOs.removeIf(item -> ObjectUtil.equal(item.getId(), seckillConfigId));
  105 + }
98 // 过滤出重叠的时段 ids 106 // 过滤出重叠的时段 ids
99 - // TODO @puhui999:感觉 findOne 就可以了?  
100 - Set<Long> ids = configDOs.stream().filter((config) -> { 107 + boolean hasConflict = configDOs.stream().anyMatch(config -> {
101 LocalTime startTime2 = LocalTime.parse(config.getStartTime()); 108 LocalTime startTime2 = LocalTime.parse(config.getStartTime());
102 LocalTime endTime2 = LocalTime.parse(config.getEndTime()); 109 LocalTime endTime2 = LocalTime.parse(config.getEndTime());
103 // 判断时间是否重叠 110 // 判断时间是否重叠
104 - // 开始时间在已配置时段的结束时间之前 且 结束时间在已配置时段的开始时间之后 []  
105 - // todo @puhui999:LocalDateUtils 可以写个工具类?是否是有重叠的时间?感觉别的场景,可能也会有需要  
106 - return startTime1.isBefore(endTime2) && endTime1.isAfter(startTime2)  
107 - // 开始时间在已配置时段的开始时间之前 且 结束时间在已配置时段的开始时间之后 (] 或 ()  
108 - || startTime1.isBefore(startTime2) && endTime1.isAfter(startTime2)  
109 - // 开始时间在已配置时段的结束时间之前 且 结束时间在已配值时段的结束时间之后 [) 或 ()  
110 - || startTime1.isBefore(endTime2) && endTime1.isAfter(endTime2);  
111 - }).map(SeckillConfigDO::getId).collect(Collectors.toSet());  
112 - if (CollUtil.isNotEmpty(ids)) { 111 + return LocalDateTimeUtils.checkTimeOverlap(startTime1, endTime1, startTime2, endTime2);
  112 + });
  113 +
  114 + if (hasConflict) {
113 throw exception(SECKILL_TIME_CONFLICTS); 115 throw exception(SECKILL_TIME_CONFLICTS);
114 } 116 }
115 } 117 }
116 118
  119 +
117 @Override 120 @Override
118 public SeckillConfigDO getSeckillConfig(Long id) { 121 public SeckillConfigDO getSeckillConfig(Long id) {
119 return seckillConfigMapper.selectById(id); 122 return seckillConfigMapper.selectById(id);
@@ -148,23 +151,9 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { @@ -148,23 +151,9 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
148 return seckillConfigMapper.selectPage(pageVO); 151 return seckillConfigMapper.selectPage(pageVO);
149 } 152 }
150 153
151 - // TODO @puhui999:写个查询状态的; 尽可能通用哈  
152 @Override 154 @Override
153 public List<SeckillConfigDO> getListAllSimple() { 155 public List<SeckillConfigDO> getListAllSimple() {
154 - return seckillConfigMapper.selectList(SeckillConfigDO::getStatus, CommonStatusEnum.ENABLE.getStatus());  
155 - }  
156 -  
157 - // TODO @puhui999: 这个要不合并到更新操作里? 不单独有个操作咧;  
158 - @Override  
159 - public void updateSeckillConfigStatus(Long id, Integer status) {  
160 - // 校验秒杀时段是否存在  
161 - validateSeckillConfigExists(id);  
162 -  
163 - SeckillConfigDO seckillConfigDO = new SeckillConfigDO();  
164 - seckillConfigDO.setId(id);  
165 - seckillConfigDO.setStatus(status);  
166 - // 更新状态  
167 - seckillConfigMapper.updateById(seckillConfigDO); 156 + return seckillConfigMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
168 } 157 }
169 158
170 } 159 }
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
@@ -27,6 +27,8 @@ public interface ErrorCodeConstants { @@ -27,6 +27,8 @@ public interface ErrorCodeConstants {
27 ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1011000016, "交易订单更新支付状态失败,支付单金额不匹配"); 27 ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1011000016, "交易订单更新支付状态失败,支付单金额不匹配");
28 ErrorCode ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED = new ErrorCode(1011000017, "交易订单发货失败,订单不是【待发货】状态"); 28 ErrorCode ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED = new ErrorCode(1011000017, "交易订单发货失败,订单不是【待发货】状态");
29 ErrorCode ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED = new ErrorCode(1011000018, "交易订单收货失败,订单不是【待收货】状态"); 29 ErrorCode ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED = new ErrorCode(1011000018, "交易订单收货失败,订单不是【待收货】状态");
  30 + ErrorCode ORDER_COMMENT_FAIL_STATUS_NOT_COMPLETED = new ErrorCode(1011000019, "创建交易订单项的评价失败,订单不是【已完成】状态");
  31 + ErrorCode ORDER_COMMENT_STATUS_NOT_FALSE = new ErrorCode(1011000019, "创建交易订单项的评价失败,订单已评价");
30 32
31 // ========== After Sale 模块 1011000100 ========== 33 // ========== After Sale 模块 1011000100 ==========
32 ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在"); 34 ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在");
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
@@ -4,8 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; @@ -4,8 +4,6 @@ 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.security.core.annotations.PreAuthenticated; 5 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
6 import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO; 6 import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
7 -import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi;  
8 -import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;  
9 import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi; 7 import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi;
10 import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; 8 import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
11 import cn.iocoder.yudao.module.trade.controller.app.order.vo.*; 9 import cn.iocoder.yudao.module.trade.controller.app.order.vo.*;
@@ -30,13 +28,10 @@ import javax.validation.Valid; @@ -30,13 +28,10 @@ import javax.validation.Valid;
30 import java.util.List; 28 import java.util.List;
31 import java.util.Map; 29 import java.util.Map;
32 30
33 -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;  
34 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 31 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
35 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 32 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
36 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; 33 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
37 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; 34 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
38 -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_ITEM_NOT_FOUND;  
39 -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_NOT_FOUND;  
40 35
41 @Tag(name = "用户 App - 交易订单") 36 @Tag(name = "用户 App - 交易订单")
42 @RestController 37 @RestController
@@ -47,13 +42,9 @@ public class AppTradeOrderController { @@ -47,13 +42,9 @@ public class AppTradeOrderController {
47 42
48 @Resource 43 @Resource
49 private TradeOrderService tradeOrderService; 44 private TradeOrderService tradeOrderService;
50 -  
51 @Resource 45 @Resource
52 private ProductPropertyValueApi productPropertyValueApi; 46 private ProductPropertyValueApi productPropertyValueApi;
53 @Resource 47 @Resource
54 - private ProductCommentApi productCommentApi;  
55 -  
56 - @Resource  
57 private TradeOrderProperties tradeOrderProperties; 48 private TradeOrderProperties tradeOrderProperties;
58 49
59 @GetMapping("/settlement") 50 @GetMapping("/settlement")
@@ -121,7 +112,7 @@ public class AppTradeOrderController { @@ -121,7 +112,7 @@ public class AppTradeOrderController {
121 // 待发货 112 // 待发货
122 orderCount.put("undeliveredCount", tradeOrderService.getOrderCount(getLoginUserId(), TradeOrderStatusEnum.UNDELIVERED.getStatus(), null)); 113 orderCount.put("undeliveredCount", tradeOrderService.getOrderCount(getLoginUserId(), TradeOrderStatusEnum.UNDELIVERED.getStatus(), null));
123 // 待收货 114 // 待收货
124 - orderCount.put("deliveredCount", tradeOrderService.getOrderCount(getLoginUserId(), TradeOrderStatusEnum.DELIVERED.getStatus(), null)); 115 + orderCount.put("deliveredCount", tradeOrderService.getOrderCount(getLoginUserId(), TradeOrderStatusEnum.DELIVERED.getStatus(), null));
125 // 待评价 116 // 待评价
126 orderCount.put("uncommentedCount", tradeOrderService.getOrderCount(getLoginUserId(), TradeOrderStatusEnum.COMPLETED.getStatus(), false)); 117 orderCount.put("uncommentedCount", tradeOrderService.getOrderCount(getLoginUserId(), TradeOrderStatusEnum.COMPLETED.getStatus(), false));
127 return success(orderCount); 118 return success(orderCount);
@@ -164,22 +155,7 @@ public class AppTradeOrderController { @@ -164,22 +155,7 @@ public class AppTradeOrderController {
164 @PostMapping("/item/create-comment") 155 @PostMapping("/item/create-comment")
165 @Operation(summary = "创建交易订单项的评价") 156 @Operation(summary = "创建交易订单项的评价")
166 public CommonResult<Long> createOrderItemComment(@RequestBody AppTradeOrderItemCommentCreateReqVO createReqVO) { 157 public CommonResult<Long> createOrderItemComment(@RequestBody AppTradeOrderItemCommentCreateReqVO createReqVO) {
167 - // TODO @puhui999:这个逻辑,最好写到 service 哈;  
168 - Long loginUserId = getLoginUserId();  
169 - // 先通过订单项 ID 查询订单项是否存在  
170 - TradeOrderItemDO orderItemDO = tradeOrderService.getOrderItemByIdAndUserId(createReqVO.getOrderItemId(), loginUserId);  
171 - if (orderItemDO == null) {  
172 - throw exception(ORDER_ITEM_NOT_FOUND);  
173 - }  
174 - // 校验订单  
175 - TradeOrderDO orderDO = tradeOrderService.getOrderByIdAndUserId(orderItemDO.getOrderId(), loginUserId);  
176 - if (orderDO == null) {  
177 - throw exception(ORDER_NOT_FOUND);  
178 - }  
179 - // TODO @puhui999:要校验订单已完成,但是未评价;  
180 -  
181 - ProductCommentCreateReqDTO productCommentCreateReqDTO = TradeOrderConvert.INSTANCE.convert04(createReqVO, orderItemDO);  
182 - return success(productCommentApi.createComment(productCommentCreateReqDTO)); 158 + return success(tradeOrderService.createOrderItemComment(createReqVO));
183 } 159 }
184 160
185 } 161 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/item/AppTradeOrderItemCommentCreateReqVO.java
@@ -19,11 +19,6 @@ public class AppTradeOrderItemCommentCreateReqVO { @@ -19,11 +19,6 @@ public class AppTradeOrderItemCommentCreateReqVO {
19 @NotNull(message = "交易订单项编号不能为空") 19 @NotNull(message = "交易订单项编号不能为空")
20 private Long orderItemId; 20 private Long orderItemId;
21 21
22 - // TODO @puhui999:貌似不用这个字段哈;  
23 - @Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")  
24 - @NotNull(message = "评分星级 1-5 分不能为空")  
25 - private Integer scores;  
26 -  
27 @Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") 22 @Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
28 @NotNull(message = "描述星级 1-5 分不能为空") 23 @NotNull(message = "描述星级 1-5 分不能为空")
29 private Integer descriptionScores; 24 private Integer descriptionScores;
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
@@ -270,7 +270,6 @@ public interface TradeOrderConvert { @@ -270,7 +270,6 @@ public interface TradeOrderConvert {
270 @Mapping(target = "skuId", source = "tradeOrderItemDO.skuId") 270 @Mapping(target = "skuId", source = "tradeOrderItemDO.skuId")
271 @Mapping(target = "orderId", source = "tradeOrderItemDO.orderId") 271 @Mapping(target = "orderId", source = "tradeOrderItemDO.orderId")
272 @Mapping(target = "orderItemId", source = "tradeOrderItemDO.id") 272 @Mapping(target = "orderItemId", source = "tradeOrderItemDO.id")
273 - @Mapping(target = "scores", source = "createReqVO.scores")  
274 @Mapping(target = "descriptionScores", source = "createReqVO.descriptionScores") 273 @Mapping(target = "descriptionScores", source = "createReqVO.descriptionScores")
275 @Mapping(target = "benefitScores", source = "createReqVO.benefitScores") 274 @Mapping(target = "benefitScores", source = "createReqVO.benefitScores")
276 @Mapping(target = "content", source = "createReqVO.content") 275 @Mapping(target = "content", source = "createReqVO.content")
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java
@@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreate @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreate
7 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO; 7 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO;
8 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO; 8 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO;
9 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; 9 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO;
  10 +import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
10 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; 11 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
11 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; 12 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
12 13
@@ -177,4 +178,14 @@ public interface TradeOrderService { @@ -177,4 +178,14 @@ public interface TradeOrderService {
177 * @return 得到订单 178 * @return 得到订单
178 */ 179 */
179 TradeOrderDO getOrderByIdAndUserId(Long orderId, Long loginUserId); 180 TradeOrderDO getOrderByIdAndUserId(Long orderId, Long loginUserId);
  181 +
  182 + /**
  183 + * 创建订单项评论
  184 + * 创建交易订单项的评价
  185 + *
  186 + * @param createReqVO 创建请求
  187 + * @return 得到评价 id
  188 + */
  189 + Long createOrderItemComment(AppTradeOrderItemCommentCreateReqVO createReqVO);
  190 +
180 } 191 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java
@@ -17,19 +17,21 @@ import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; @@ -17,19 +17,21 @@ import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
17 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; 17 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
18 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; 18 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
19 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; 19 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
  20 +import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi;
  21 +import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
20 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; 22 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
21 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; 23 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
22 import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; 24 import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
23 import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; 25 import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO;
24 import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi; 26 import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
25 import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO; 27 import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
26 -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;  
27 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; 28 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
28 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; 29 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO;
29 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; 30 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
30 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO; 31 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO;
31 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO; 32 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO;
32 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; 33 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO;
  34 +import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
33 import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; 35 import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
34 import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; 36 import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO;
35 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; 37 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
@@ -57,6 +59,7 @@ import java.util.*; @@ -57,6 +59,7 @@ import java.util.*;
57 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 59 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
58 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 60 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
59 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; 61 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue;
  62 +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
60 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_ORDER_NOT_FOUND; 63 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_ORDER_NOT_FOUND;
61 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; 64 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
62 65
@@ -93,7 +96,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { @@ -93,7 +96,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
93 @Resource 96 @Resource
94 private MemberUserApi memberUserApi; 97 private MemberUserApi memberUserApi;
95 @Resource 98 @Resource
96 - private AdminUserApi adminUserApi; 99 + private ProductCommentApi productCommentApi;
97 @Resource 100 @Resource
98 private NotifyMessageSendApi notifyMessageSendApi; 101 private NotifyMessageSendApi notifyMessageSendApi;
99 102
@@ -556,6 +559,30 @@ public class TradeOrderServiceImpl implements TradeOrderService { @@ -556,6 +559,30 @@ public class TradeOrderServiceImpl implements TradeOrderService {
556 return tradeOrderMapper.selectOrderByIdAndUserId(orderId, loginUserId); 559 return tradeOrderMapper.selectOrderByIdAndUserId(orderId, loginUserId);
557 } 560 }
558 561
  562 + @Override
  563 + public Long createOrderItemComment(AppTradeOrderItemCommentCreateReqVO createReqVO) {
  564 + Long loginUserId = getLoginUserId();
  565 + // 先通过订单项 ID 查询订单项是否存在
  566 + TradeOrderItemDO orderItemDO = getOrderItemByIdAndUserId(createReqVO.getOrderItemId(), loginUserId);
  567 + if (orderItemDO == null) {
  568 + throw exception(ORDER_ITEM_NOT_FOUND);
  569 + }
  570 + // 校验订单
  571 + TradeOrderDO orderDO = getOrderByIdAndUserId(orderItemDO.getOrderId(), loginUserId);
  572 + if (orderDO == null) {
  573 + throw exception(ORDER_NOT_FOUND);
  574 + }
  575 + if (ObjectUtil.notEqual(orderDO.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus())) {
  576 + throw exception(ORDER_COMMENT_FAIL_STATUS_NOT_COMPLETED);
  577 + }
  578 + if (ObjectUtil.notEqual(orderDO.getCommentStatus(), Boolean.FALSE)) {
  579 + throw exception(ORDER_COMMENT_STATUS_NOT_FALSE);
  580 + }
  581 +
  582 + ProductCommentCreateReqDTO productCommentCreateReqDTO = TradeOrderConvert.INSTANCE.convert04(createReqVO, orderItemDO);
  583 + return productCommentApi.createComment(productCommentCreateReqDTO);
  584 + }
  585 +
559 /** 586 /**
560 * 判断指定订单的所有订单项,是不是都售后成功 587 * 判断指定订单的所有订单项,是不是都售后成功
561 * 588 *
yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java
@@ -19,10 +19,10 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -19,10 +19,10 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
19 import static org.junit.jupiter.api.Assertions.assertNull; 19 import static org.junit.jupiter.api.Assertions.assertNull;
20 20
21 /** 21 /**
22 -* {@link AddressServiceImpl} 的单元测试类  
23 -*  
24 -* @author 芋道源码  
25 -*/ 22 + * {@link AddressServiceImpl} 的单元测试类
  23 + *
  24 + * @author 芋道源码
  25 + */
26 @Import(AddressServiceImpl.class) 26 @Import(AddressServiceImpl.class)
27 public class AddressServiceImplTest extends BaseDbUnitTest { 27 public class AddressServiceImplTest extends BaseDbUnitTest {
28 28
@@ -82,8 +82,8 @@ public class AddressServiceImplTest extends BaseDbUnitTest { @@ -82,8 +82,8 @@ public class AddressServiceImplTest extends BaseDbUnitTest {
82 82
83 // 调用 83 // 调用
84 addressService.deleteAddress(dbAddress.getUserId(), id); 84 addressService.deleteAddress(dbAddress.getUserId(), id);
85 - // 校验数据不存在了  
86 - assertNull(addressMapper.selectById(id)); 85 + // 校验数据不存在了
  86 + assertNull(addressMapper.selectById(id));
87 } 87 }
88 88
89 @Test 89 @Test