Commit 7bc1ae5f35e3e095a0950020658772421b701cc8

Authored by halfninety
1 parent cd62c4d2

秒杀活动增删改查

Showing 19 changed files with 472 additions and 235 deletions
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -48,4 +48,9 @@ public interface ErrorCodeConstants { @@ -48,4 +48,9 @@ public interface ErrorCodeConstants {
48 // ========== 秒杀活动 1003008000 ========== 48 // ========== 秒杀活动 1003008000 ==========
49 ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1003008000, "秒杀活动不存在"); 49 ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1003008000, "秒杀活动不存在");
50 ErrorCode SECKILL_TIME_NOT_EXISTS = new ErrorCode(1003008001, "秒杀时段不存在"); 50 ErrorCode SECKILL_TIME_NOT_EXISTS = new ErrorCode(1003008001, "秒杀时段不存在");
  51 + ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1003008001, "存在商品参加了其它秒杀活动");
  52 + ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1003006002, "秒杀活动已关闭,不能修改");
  53 + ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1003006003, "秒杀活动未关闭,不能删除");
  54 + ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1003006004, "秒杀活动已关闭,不能重复关闭");
  55 + ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1003006004, "秒杀活动已结束,不能关闭");
51 } 56 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckillactivity/SeckillActivityController.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity;
2 2
  3 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.*;
  6 +import cn.iocoder.yudao.module.promotion.convert.seckillactivity.SeckillActivityConvert;
  7 +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity.SeckillActivityDO;
  8 +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity.SeckillProductDO;
  9 +import cn.iocoder.yudao.module.promotion.service.seckillactivity.SeckillActivityService;
  10 +import io.swagger.annotations.Api;
  11 +import io.swagger.annotations.ApiImplicitParam;
  12 +import io.swagger.annotations.ApiOperation;
  13 +import org.springframework.security.access.prepost.PreAuthorize;
  14 +import org.springframework.validation.annotation.Validated;
3 import org.springframework.web.bind.annotation.*; 15 import org.springframework.web.bind.annotation.*;
4 16
5 import javax.annotation.Resource; 17 import javax.annotation.Resource;
6 -  
7 -import org.springframework.validation.annotation.Validated;  
8 -import org.springframework.security.access.prepost.PreAuthorize;  
9 -import io.swagger.annotations.*;  
10 -  
11 -import javax.validation.constraints.*;  
12 -import javax.validation.*;  
13 -import javax.servlet.http.*;  
14 -import java.util.*;  
15 -import java.io.IOException;  
16 -  
17 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
18 -import cn.iocoder.yudao.framework.common.pojo.CommonResult; 18 +import javax.validation.Valid;
  19 +import java.util.Collection;
  20 +import java.util.List;
19 21
20 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 22 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
21 23
22 -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;  
23 -  
24 -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;  
25 -  
26 -import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;  
27 -  
28 -import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.*;  
29 -import cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity.SeckillActivityDO;  
30 -import cn.iocoder.yudao.module.promotion.convert.seckillactivity.SeckillActivityConvert;  
31 -import cn.iocoder.yudao.module.promotion.service.seckillactivity.SeckillActivityService;  
32 -  
33 @Api(tags = "管理后台 - 秒杀活动") 24 @Api(tags = "管理后台 - 秒杀活动")
34 @RestController 25 @RestController
35 @RequestMapping("/promotion/seckill-activity") 26 @RequestMapping("/promotion/seckill-activity")
@@ -54,6 +45,15 @@ public class SeckillActivityController { @@ -54,6 +45,15 @@ public class SeckillActivityController {
54 return success(true); 45 return success(true);
55 } 46 }
56 47
  48 + @PutMapping("/close")
  49 + @ApiOperation("关闭秒杀活动")
  50 + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
  51 + @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:close')")
  52 + public CommonResult<Boolean> closeSeckillActivity(@RequestParam("id") Long id) {
  53 + seckillActivityService.closeSeckillActivity(id);
  54 + return success(true);
  55 + }
  56 +
57 @DeleteMapping("/delete") 57 @DeleteMapping("/delete")
58 @ApiOperation("删除秒杀活动") 58 @ApiOperation("删除秒杀活动")
59 @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) 59 @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@@ -67,12 +67,13 @@ public class SeckillActivityController { @@ -67,12 +67,13 @@ public class SeckillActivityController {
67 @ApiOperation("获得秒杀活动") 67 @ApiOperation("获得秒杀活动")
68 @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) 68 @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
69 @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')") 69 @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")
70 - public CommonResult<SeckillActivityRespVO> getSeckillActivity(@RequestParam("id") Long id) { 70 + public CommonResult<SeckillActivityDetailRespVO> getSeckillActivity(@RequestParam("id") Long id) {
71 SeckillActivityDO seckillActivity = seckillActivityService.getSeckillActivity(id); 71 SeckillActivityDO seckillActivity = seckillActivityService.getSeckillActivity(id);
72 if (seckillActivity == null) { 72 if (seckillActivity == null) {
73 return success(null); 73 return success(null);
74 } 74 }
75 - return success(SeckillActivityConvert.INSTANCE.convert(seckillActivity)); 75 + List<SeckillProductDO> seckillProducts = seckillActivityService.getSeckillProductListByActivityId(id);
  76 + return success(SeckillActivityConvert.INSTANCE.convert(seckillActivity,seckillProducts));
76 } 77 }
77 78
78 @GetMapping("/list") 79 @GetMapping("/list")
@@ -92,16 +93,4 @@ public class SeckillActivityController { @@ -92,16 +93,4 @@ public class SeckillActivityController {
92 return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult)); 93 return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult));
93 } 94 }
94 95
95 - @GetMapping("/export-excel")  
96 - @ApiOperation("导出秒杀活动 Excel")  
97 - @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:export')")  
98 - @OperateLog(type = EXPORT)  
99 - public void exportSeckillActivityExcel(@Valid SeckillActivityExportReqVO exportReqVO,  
100 - HttpServletResponse response) throws IOException {  
101 - List<SeckillActivityDO> list = seckillActivityService.getSeckillActivityList(exportReqVO);  
102 - // 导出 Excel  
103 - List<SeckillActivityExcelVO> datas = SeckillActivityConvert.INSTANCE.convertList02(list);  
104 - ExcelUtils.write(response, "秒杀活动.xls", "数据", SeckillActivityExcelVO.class, datas);  
105 - }  
106 -  
107 } 96 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckillactivity/vo/SeckillActivityBaseVO.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo;
2 2
3 -import lombok.*;  
4 -import java.util.*;  
5 -import java.math.BigDecimal;  
6 -import io.swagger.annotations.*;  
7 -import javax.validation.constraints.*; 3 +import com.fasterxml.jackson.annotation.JsonFormat;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import lombok.Data;
8 import org.springframework.format.annotation.DateTimeFormat; 7 import org.springframework.format.annotation.DateTimeFormat;
9 8
  9 +import javax.validation.constraints.Min;
  10 +import javax.validation.constraints.NotNull;
  11 +import java.time.LocalDateTime;
  12 +
10 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; 13 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  14 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
11 15
12 /** 16 /**
13 * 秒杀活动 Base VO,提供给添加、修改、详细的子 VO 使用 17 * 秒杀活动 Base VO,提供给添加、修改、详细的子 VO 使用
@@ -20,22 +24,43 @@ public class SeckillActivityBaseVO { @@ -20,22 +24,43 @@ public class SeckillActivityBaseVO {
20 @NotNull(message = "秒杀活动名称不能为空") 24 @NotNull(message = "秒杀活动名称不能为空")
21 private String name; 25 private String name;
22 26
23 - @ApiModelProperty(value = "活动状态", required = true, example = "进行中")  
24 - @NotNull(message = "活动状态不能为空")  
25 - private Integer status;  
26 -  
27 @ApiModelProperty(value = "活动开始时间", required = true) 27 @ApiModelProperty(value = "活动开始时间", required = true)
28 @NotNull(message = "活动开始时间不能为空") 28 @NotNull(message = "活动开始时间不能为空")
29 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 29 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
30 - private Date startTime; 30 + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
  31 + private LocalDateTime startTime;
31 32
32 @ApiModelProperty(value = "活动结束时间", required = true) 33 @ApiModelProperty(value = "活动结束时间", required = true)
33 @NotNull(message = "活动结束时间不能为空") 34 @NotNull(message = "活动结束时间不能为空")
34 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 35 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
35 - private Date endTime; 36 + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
  37 + private LocalDateTime endTime;
  38 +
  39 +
  40 + @ApiModel("商品")
  41 + @Data
  42 + public static class Product {
  43 +
  44 + @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1")
  45 + @NotNull(message = "商品 SPU 编号不能为空")
  46 + private Long spuId;
  47 +
  48 + @ApiModelProperty(value = "商品 SKU 编号", required = true, example = "1")
  49 + @NotNull(message = "商品 SKU 编号不能为空")
  50 + private Long skuId;
  51 +
  52 + @ApiModelProperty(value = "秒杀金额", required = true, example = "12.00")
  53 + @NotNull(message = "秒杀金额不能为空")
  54 + private Integer seckillPrice;
  55 +
  56 + @ApiModelProperty(value = "秒杀库存", example = "80")
  57 + @Min(value = 0, message = "秒杀库存需要大于等于 0")
  58 + private Integer stock;
  59 +
  60 + @ApiModelProperty(value = "每人限购", example = "10", notes = "如果为0则不限购")
  61 + @Min(value = 0, message = "每人限购需要大于等于 0")
  62 + private Integer limitBuyCount;
36 63
37 - @ApiModelProperty(value = "订单实付金额,单位:分", required = true)  
38 - @NotNull(message = "订单实付金额,单位:分不能为空")  
39 - private BigDecimal totalPrice; 64 + }
40 65
41 } 66 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckillactivity/vo/SeckillActivityCreateReqVO.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo;
2 2
3 -import lombok.*;  
4 -import java.util.*;  
5 -import io.swagger.annotations.*;  
6 -import javax.validation.constraints.*; 3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +import javax.validation.Valid;
  10 +import javax.validation.constraints.NotBlank;
  11 +import javax.validation.constraints.NotEmpty;
  12 +import javax.validation.constraints.NotNull;
  13 +import java.util.List;
7 14
8 @ApiModel("管理后台 - 秒杀活动创建 Request VO") 15 @ApiModel("管理后台 - 秒杀活动创建 Request VO")
9 @Data 16 @Data
@@ -19,7 +26,14 @@ public class SeckillActivityCreateReqVO extends SeckillActivityBaseVO { @@ -19,7 +26,14 @@ public class SeckillActivityCreateReqVO extends SeckillActivityBaseVO {
19 private Integer sort; 26 private Integer sort;
20 27
21 @ApiModelProperty(value = "秒杀时段id", required = true) 28 @ApiModelProperty(value = "秒杀时段id", required = true)
22 - @NotNull(message = "秒杀时段id不能为空") 29 + @NotBlank(message = "参与场次不能为空")
23 private String timeId; 30 private String timeId;
24 31
  32 + /**
  33 + * 商品列表
  34 + */
  35 + @NotEmpty(message = "商品列表不能为空")
  36 + @Valid
  37 + private List<Product> products;
  38 +
25 } 39 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckillactivity/vo/SeckillActivityDetailRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
  7 +
  8 +import java.util.List;
  9 +
  10 +@ApiModel("管理后台 - 秒杀活动的详细 Response VO")
  11 +@Data
  12 +@EqualsAndHashCode(callSuper = true)
  13 +@ToString(callSuper = true)
  14 +public class SeckillActivityDetailRespVO extends SeckillActivityRespVO{
  15 +
  16 + /**
  17 + * 商品列表
  18 + */
  19 + private List<Product> products;
  20 +
  21 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckillactivity/vo/SeckillActivityExcelVO.java deleted
1 -package cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo;  
2 -  
3 -import lombok.*;  
4 -import java.util.*;  
5 -import java.math.BigDecimal;  
6 -import io.swagger.annotations.*;  
7 -  
8 -import com.alibaba.excel.annotation.ExcelProperty;  
9 -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;  
10 -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;  
11 -  
12 -  
13 -/**  
14 - * 秒杀活动 Excel VO  
15 - *  
16 - * @author 芋道源码  
17 - */  
18 -@Data  
19 -public class SeckillActivityExcelVO {  
20 -  
21 - @ExcelProperty("秒杀活动名称")  
22 - private String name;  
23 -  
24 - @ExcelProperty(value = "活动状态", converter = DictConvert.class)  
25 - @DictFormat("promotion_activity_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中  
26 - private Integer status;  
27 -  
28 - @ExcelProperty("活动开始时间")  
29 - private Date startTime;  
30 -  
31 - @ExcelProperty("活动结束时间")  
32 - private Date endTime;  
33 -  
34 - @ExcelProperty("付款订单数")  
35 - private Integer orderCount;  
36 -  
37 - @ExcelProperty("付款人数")  
38 - private Integer userCount;  
39 -  
40 - @ExcelProperty("订单实付金额,单位:分")  
41 - private BigDecimal totalPrice;  
42 -  
43 - @ExcelProperty("创建时间")  
44 - private Date createTime;  
45 -  
46 -}  
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckillactivity/vo/SeckillActivityExportReqVO.java deleted
1 -package cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo;  
2 -  
3 -import lombok.*;  
4 -import java.util.*;  
5 -import io.swagger.annotations.*;  
6 -import cn.iocoder.yudao.framework.common.pojo.PageParam;  
7 -import org.springframework.format.annotation.DateTimeFormat;  
8 -  
9 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;  
10 -  
11 -@ApiModel(value = "管理后台 - 秒杀活动 Excel 导出 Request VO", description = "参数和 SeckillActivityPageReqVO 是一致的")  
12 -@Data  
13 -public class SeckillActivityExportReqVO {  
14 -  
15 - @ApiModelProperty(value = "秒杀活动名称", example = "晚九点限时秒杀")  
16 - private String name;  
17 -  
18 - @ApiModelProperty(value = "活动状态", example = "进行中")  
19 - private Integer status;  
20 -  
21 - @ApiModelProperty(value = "秒杀时段id")  
22 - private String timeId;  
23 -  
24 - @ApiModelProperty(value = "创建时间")  
25 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
26 - private Date[] createTime;  
27 -  
28 -}  
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckillactivity/vo/SeckillActivityPageReqVO.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo;
2 2
3 -import lombok.*;  
4 -import java.util.*;  
5 -import io.swagger.annotations.*;  
6 import cn.iocoder.yudao.framework.common.pojo.PageParam; 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import com.fasterxml.jackson.annotation.JsonFormat;
  5 +import io.swagger.annotations.ApiModel;
  6 +import io.swagger.annotations.ApiModelProperty;
  7 +import lombok.Data;
  8 +import lombok.EqualsAndHashCode;
  9 +import lombok.ToString;
7 import org.springframework.format.annotation.DateTimeFormat; 10 import org.springframework.format.annotation.DateTimeFormat;
8 11
  12 +import java.time.LocalDateTime;
  13 +
9 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; 14 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  15 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
10 16
11 @ApiModel("管理后台 - 秒杀活动分页 Request VO") 17 @ApiModel("管理后台 - 秒杀活动分页 Request VO")
12 @Data 18 @Data
@@ -25,6 +31,7 @@ public class SeckillActivityPageReqVO extends PageParam { @@ -25,6 +31,7 @@ public class SeckillActivityPageReqVO extends PageParam {
25 31
26 @ApiModelProperty(value = "创建时间") 32 @ApiModelProperty(value = "创建时间")
27 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 33 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
28 - private Date[] createTime; 34 + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
  35 + private LocalDateTime[] createTime;
29 36
30 } 37 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckillactivity/vo/SeckillActivityRespVO.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo;
2 2
3 -import lombok.*;  
4 -import java.util.*;  
5 -import io.swagger.annotations.*; 3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
6 8
7 -import javax.validation.constraints.NotNull; 9 +import java.time.LocalDateTime;
8 10
9 @ApiModel("管理后台 - 秒杀活动 Response VO") 11 @ApiModel("管理后台 - 秒杀活动 Response VO")
10 @Data 12 @Data
@@ -22,9 +24,18 @@ public class SeckillActivityRespVO extends SeckillActivityBaseVO { @@ -22,9 +24,18 @@ public class SeckillActivityRespVO extends SeckillActivityBaseVO {
22 private Integer userCount; 24 private Integer userCount;
23 25
24 @ApiModelProperty(value = "创建时间", required = true) 26 @ApiModelProperty(value = "创建时间", required = true)
25 - private Date createTime; 27 + private LocalDateTime createTime;
26 28
27 @ApiModelProperty(value = "秒杀时段id", required = true) 29 @ApiModelProperty(value = "秒杀时段id", required = true)
28 private String timeId; 30 private String timeId;
29 31
  32 + @ApiModelProperty(value = "排序", required = true)
  33 + private Integer sort;
  34 +
  35 + @ApiModelProperty(value = "备注", example = "限时秒杀活动")
  36 + private String remark;
  37 +
  38 + @ApiModelProperty(value = "活动状态", example = "进行中")
  39 + private Integer status;
  40 +
30 } 41 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckillactivity/vo/SeckillActivityUpdateReqVO.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo;
2 2
3 -import lombok.*;  
4 -import java.util.*;  
5 -import io.swagger.annotations.*;  
6 -import javax.validation.constraints.*; 3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +import javax.validation.Valid;
  10 +import javax.validation.constraints.NotEmpty;
  11 +import javax.validation.constraints.NotNull;
  12 +import java.util.List;
7 13
8 @ApiModel("管理后台 - 秒杀活动更新 Request VO") 14 @ApiModel("管理后台 - 秒杀活动更新 Request VO")
9 @Data 15 @Data
@@ -26,4 +32,11 @@ public class SeckillActivityUpdateReqVO extends SeckillActivityBaseVO { @@ -26,4 +32,11 @@ public class SeckillActivityUpdateReqVO extends SeckillActivityBaseVO {
26 @NotNull(message = "秒杀时段id不能为空") 32 @NotNull(message = "秒杀时段id不能为空")
27 private String timeId; 33 private String timeId;
28 34
  35 + /**
  36 + * 商品列表
  37 + */
  38 + @NotEmpty(message = "商品列表不能为空")
  39 + @Valid
  40 + private List<Product> products;
  41 +
29 } 42 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckillactivity/SeckillActivityConvert.java
1 package cn.iocoder.yudao.module.promotion.convert.seckillactivity; 1 package cn.iocoder.yudao.module.promotion.convert.seckillactivity;
2 2
3 -import java.util.*;  
4 - 3 +import cn.hutool.core.util.ObjectUtil;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 -  
7 -import org.mapstruct.Mapper;  
8 -import org.mapstruct.factory.Mappers;  
9 import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.*; 5 import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.*;
10 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity.SeckillActivityDO; 6 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity.SeckillActivityDO;
  7 +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity.SeckillProductDO;
  8 +import org.mapstruct.Mapper;
  9 +import org.mapstruct.Mapping;
  10 +import org.mapstruct.Mappings;
  11 +import org.mapstruct.factory.Mappers;
  12 +
  13 +import java.util.List;
11 14
12 /** 15 /**
13 * 秒杀活动 Convert 16 * 秒杀活动 Convert
@@ -19,8 +22,15 @@ public interface SeckillActivityConvert { @@ -19,8 +22,15 @@ public interface SeckillActivityConvert {
19 22
20 SeckillActivityConvert INSTANCE = Mappers.getMapper(SeckillActivityConvert.class); 23 SeckillActivityConvert INSTANCE = Mappers.getMapper(SeckillActivityConvert.class);
21 24
  25 + SeckillProductDO convert(SeckillActivityBaseVO.Product product);
  26 +
  27 +
22 SeckillActivityDO convert(SeckillActivityCreateReqVO bean); 28 SeckillActivityDO convert(SeckillActivityCreateReqVO bean);
23 29
  30 + default String map(Long[] value){
  31 + return value.toString();
  32 + }
  33 +
24 SeckillActivityDO convert(SeckillActivityUpdateReqVO bean); 34 SeckillActivityDO convert(SeckillActivityUpdateReqVO bean);
25 35
26 SeckillActivityRespVO convert(SeckillActivityDO bean); 36 SeckillActivityRespVO convert(SeckillActivityDO bean);
@@ -29,6 +39,39 @@ public interface SeckillActivityConvert { @@ -29,6 +39,39 @@ public interface SeckillActivityConvert {
29 39
30 PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page); 40 PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page);
31 41
32 - List<SeckillActivityExcelVO> convertList02(List<SeckillActivityDO> list); 42 + @Mappings({@Mapping(target = "products",source = "seckillProducts")})
  43 + SeckillActivityDetailRespVO convert(SeckillActivityDO seckillActivity,List<SeckillProductDO> seckillProducts);
  44 +
  45 +
  46 + /**
  47 + * 比较两个秒杀商品对象是否相等
  48 + *
  49 + * @param productDO 数据库中的商品
  50 + * @param productVO 前端传入的商品
  51 + * @return 是否匹配
  52 + */
  53 + default boolean isEquals(SeckillProductDO productDO, SeckillActivityBaseVO.Product productVO) {
  54 + return ObjectUtil.equals(productDO.getSpuId(), productVO.getSpuId())
  55 + && ObjectUtil.equals(productDO.getSkuId(), productVO.getSkuId())
  56 + && ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice())
  57 + && ObjectUtil.equals(productDO.getStock(), productVO.getStock())
  58 + && ObjectUtil.equals(productDO.getLimitBuyCount(), productVO.getLimitBuyCount());
  59 +
  60 + }
  61 +
  62 + /**
  63 + * 比较两个秒杀商品对象是否相等
  64 + *
  65 + * @param productDO 商品1
  66 + * @param productVO 商品2
  67 + * @return 是否匹配
  68 + */
  69 + default boolean isEquals(SeckillProductDO productDO, SeckillProductDO productVO) {
  70 + return ObjectUtil.equals(productDO.getSpuId(), productVO.getSpuId())
  71 + && ObjectUtil.equals(productDO.getSkuId(), productVO.getSkuId())
  72 + && ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice())
  73 + && ObjectUtil.equals(productDO.getStock(), productVO.getStock())
  74 + && ObjectUtil.equals(productDO.getLimitBuyCount(), productVO.getLimitBuyCount());
33 75
  76 + }
34 } 77 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckillactivity/SeckillActivityDO.java
1 package cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity; 1 package cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity;
2 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 cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
3 import lombok.*; 8 import lombok.*;
4 -import java.util.*; 9 +
5 import java.math.BigDecimal; 10 import java.math.BigDecimal;
6 -import com.baomidou.mybatisplus.annotation.*;  
7 -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 11 +import java.time.LocalDateTime;
8 12
9 /** 13 /**
10 * 秒杀活动 DO 14 * 秒杀活动 DO
@@ -33,7 +37,7 @@ public class SeckillActivityDO extends BaseDO { @@ -33,7 +37,7 @@ public class SeckillActivityDO extends BaseDO {
33 /** 37 /**
34 * 活动状态 38 * 活动状态
35 * 39 *
36 - * 枚举 {@link TODO promotion_activity_status 对应的类} 40 + * 枚举 {@link PromotionActivityStatusEnum 对应的类}
37 */ 41 */
38 private Integer status; 42 private Integer status;
39 /** 43 /**
@@ -43,11 +47,11 @@ public class SeckillActivityDO extends BaseDO { @@ -43,11 +47,11 @@ public class SeckillActivityDO extends BaseDO {
43 /** 47 /**
44 * 活动开始时间 48 * 活动开始时间
45 */ 49 */
46 - private Date startTime; 50 + private LocalDateTime startTime;
47 /** 51 /**
48 * 活动结束时间 52 * 活动结束时间
49 */ 53 */
50 - private Date endTime; 54 + private LocalDateTime endTime;
51 /** 55 /**
52 * 排序 56 * 排序
53 */ 57 */
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckillactivity/SeckillProductDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import com.baomidou.mybatisplus.annotation.IdType;
  5 +import com.baomidou.mybatisplus.annotation.TableField;
  6 +import com.baomidou.mybatisplus.annotation.TableId;
  7 +import com.baomidou.mybatisplus.annotation.TableName;
  8 +import java.io.Serializable;
  9 +import java.math.BigDecimal;
  10 +import java.util.Date;
  11 +import lombok.Data;
  12 +
  13 +/**
  14 + * 秒杀参与商品
  15 + * @TableName promotion_seckill_product
  16 + */
  17 +@TableName(value ="promotion_seckill_product")
  18 +@Data
  19 +public class SeckillProductDO extends BaseDO {
  20 + /**
  21 + * 秒杀参与商品编号
  22 + */
  23 + @TableId(type = IdType.AUTO)
  24 + private Long id;
  25 +
  26 + /**
  27 + * 秒杀活动id
  28 + */
  29 + private Long activityId;
  30 +
  31 + /**
  32 + * 秒杀时段id
  33 + */
  34 + private Long timeId;
  35 +
  36 + /**
  37 + * 商品id
  38 + */
  39 + private Long spuId;
  40 +
  41 + /**
  42 + * 商品sku_id
  43 + */
  44 + private Long skuId;
  45 +
  46 + /**
  47 + * 秒杀金额
  48 + */
  49 + private Integer seckillPrice;
  50 +
  51 + /**
  52 + * 秒杀库存
  53 + */
  54 + private Integer stock;
  55 +
  56 + /**
  57 + * 每人限购
  58 + */
  59 + private Integer limitBuyCount;
  60 +}
0 \ No newline at end of file 61 \ No newline at end of file
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckillactivity/SeckillActivityMapper.java
1 package cn.iocoder.yudao.module.promotion.dal.mysql.seckillactivity; 1 package cn.iocoder.yudao.module.promotion.dal.mysql.seckillactivity;
2 2
3 -import java.util.*;  
4 -  
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;  
7 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;
  6 +import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.SeckillActivityPageReqVO;
8 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity.SeckillActivityDO; 7 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity.SeckillActivityDO;
9 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
10 -import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.*;  
11 9
12 /** 10 /**
13 * 秒杀活动 Mapper 11 * 秒杀活动 Mapper
@@ -16,21 +14,13 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.*; @@ -16,21 +14,13 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.*;
16 */ 14 */
17 @Mapper 15 @Mapper
18 public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> { 16 public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> {
19 - 17 +// TODO: 2022/11/28 halfninety 秒杀活动通过场次查询使用like会出现问题,查询活动场次编号为1,则活动场次编号为 1,11,......的都会被查出来
20 default PageResult<SeckillActivityDO> selectPage(SeckillActivityPageReqVO reqVO) { 18 default PageResult<SeckillActivityDO> selectPage(SeckillActivityPageReqVO reqVO) {
21 return selectPage(reqVO, new LambdaQueryWrapperX<SeckillActivityDO>() 19 return selectPage(reqVO, new LambdaQueryWrapperX<SeckillActivityDO>()
22 .likeIfPresent(SeckillActivityDO::getName, reqVO.getName()) 20 .likeIfPresent(SeckillActivityDO::getName, reqVO.getName())
23 .eqIfPresent(SeckillActivityDO::getStatus, reqVO.getStatus()) 21 .eqIfPresent(SeckillActivityDO::getStatus, reqVO.getStatus())
24 - .eqIfPresent(SeckillActivityDO::getTimeId, reqVO.getTimeId())  
25 - .betweenIfPresent(SeckillActivityDO::getCreateTime, reqVO.getCreateTime())  
26 - .orderByDesc(SeckillActivityDO::getId));  
27 - }  
28 -  
29 - default List<SeckillActivityDO> selectList(SeckillActivityExportReqVO reqVO) {  
30 - return selectList(new LambdaQueryWrapperX<SeckillActivityDO>()  
31 - .likeIfPresent(SeckillActivityDO::getName, reqVO.getName())  
32 - .eqIfPresent(SeckillActivityDO::getStatus, reqVO.getStatus())  
33 - .eqIfPresent(SeckillActivityDO::getTimeId, reqVO.getTimeId()) 22 + .likeIfPresent(SeckillActivityDO::getTimeId, reqVO.getTimeId())
  23 +// .like(StringUtils.hasText(reqVO.getTimeId()),SeckillActivityDO::getTimeId, reqVO.getTimeId() + ",")
34 .betweenIfPresent(SeckillActivityDO::getCreateTime, reqVO.getCreateTime()) 24 .betweenIfPresent(SeckillActivityDO::getCreateTime, reqVO.getCreateTime())
35 .orderByDesc(SeckillActivityDO::getId)); 25 .orderByDesc(SeckillActivityDO::getId));
36 } 26 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckillactivity/SeckillProductMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.dal.mysql.seckillactivity;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  4 +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity.SeckillProductDO;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +import java.util.Collection;
  8 +import java.util.List;
  9 +
  10 +@Mapper
  11 +public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> {
  12 +
  13 + default List<SeckillProductDO> selectListByActivityId(Long id){
  14 + return selectList(SeckillProductDO::getActivityId,id);
  15 + }
  16 +
  17 + default List<SeckillProductDO> selectListBySkuIds(Collection<Long> skuIds){
  18 + return selectList(SeckillProductDO::getSkuId,skuIds);
  19 + }
  20 +
  21 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckillactivity/SeckillActivityService.java
@@ -5,6 +5,7 @@ import javax.validation.*; @@ -5,6 +5,7 @@ import javax.validation.*;
5 import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.*; 5 import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.*;
6 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity.SeckillActivityDO; 6 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity.SeckillActivityDO;
7 import cn.iocoder.yudao.framework.common.pojo.PageResult; 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  8 +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity.SeckillProductDO;
8 9
9 /** 10 /**
10 * 秒杀活动 Service 接口 11 * 秒杀活动 Service 接口
@@ -29,6 +30,12 @@ public interface SeckillActivityService { @@ -29,6 +30,12 @@ public interface SeckillActivityService {
29 void updateSeckillActivity(@Valid SeckillActivityUpdateReqVO updateReqVO); 30 void updateSeckillActivity(@Valid SeckillActivityUpdateReqVO updateReqVO);
30 31
31 /** 32 /**
  33 + * 关闭秒杀活动
  34 + * @param id 编号
  35 + */
  36 + void closeSeckillActivity(Long id);
  37 +
  38 + /**
32 * 删除秒杀活动 39 * 删除秒杀活动
33 * 40 *
34 * @param id 编号 41 * @param id 编号
@@ -60,11 +67,9 @@ public interface SeckillActivityService { @@ -60,11 +67,9 @@ public interface SeckillActivityService {
60 PageResult<SeckillActivityDO> getSeckillActivityPage(SeckillActivityPageReqVO pageReqVO); 67 PageResult<SeckillActivityDO> getSeckillActivityPage(SeckillActivityPageReqVO pageReqVO);
61 68
62 /** 69 /**
63 - * 获得秒杀活动列表, 用于 Excel 导出  
64 - *  
65 - * @param exportReqVO 查询条件  
66 - * @return 秒杀活动列表 70 + * 通过活动编号获取活动商品
  71 + * @param id 活动编号
  72 + * @return 活动商品列表
67 */ 73 */
68 - List<SeckillActivityDO> getSeckillActivityList(SeckillActivityExportReqVO exportReqVO);  
69 - 74 + List<SeckillProductDO> getSeckillProductListByActivityId(Long id);
70 } 75 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckillactivity/SeckillActivityServiceImpl.java
1 package cn.iocoder.yudao.module.promotion.service.seckillactivity; 1 package cn.iocoder.yudao.module.promotion.service.seckillactivity;
2 2
3 -import org.springframework.stereotype.Service;  
4 -import javax.annotation.Resource;  
5 -import org.springframework.validation.annotation.Validated;  
6 -  
7 -import java.util.*;  
8 -import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.*;  
9 -import cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity.SeckillActivityDO; 3 +import cn.hutool.core.collection.CollUtil;
10 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
11 - 5 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  6 +import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.SeckillActivityBaseVO;
  7 +import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.SeckillActivityCreateReqVO;
  8 +import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.SeckillActivityPageReqVO;
  9 +import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.SeckillActivityUpdateReqVO;
12 import cn.iocoder.yudao.module.promotion.convert.seckillactivity.SeckillActivityConvert; 10 import cn.iocoder.yudao.module.promotion.convert.seckillactivity.SeckillActivityConvert;
  11 +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity.SeckillActivityDO;
  12 +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity.SeckillProductDO;
13 import cn.iocoder.yudao.module.promotion.dal.mysql.seckillactivity.SeckillActivityMapper; 13 import cn.iocoder.yudao.module.promotion.dal.mysql.seckillactivity.SeckillActivityMapper;
  14 +import cn.iocoder.yudao.module.promotion.dal.mysql.seckillactivity.SeckillProductMapper;
  15 +import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
  16 +import cn.iocoder.yudao.module.promotion.util.PromotionUtils;
  17 +import org.springframework.stereotype.Service;
  18 +import org.springframework.validation.annotation.Validated;
  19 +
  20 +import javax.annotation.Resource;
  21 +import java.util.Collection;
  22 +import java.util.List;
14 23
15 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 24 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
16 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; 25 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
  26 +import static java.util.Arrays.asList;
17 27
18 /** 28 /**
19 * 秒杀活动 Service 实现类 29 * 秒杀活动 Service 实现类
@@ -27,11 +37,24 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -27,11 +37,24 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
27 @Resource 37 @Resource
28 private SeckillActivityMapper seckillActivityMapper; 38 private SeckillActivityMapper seckillActivityMapper;
29 39
  40 + @Resource
  41 + private SeckillProductMapper seckillProductMapper;
  42 +
30 @Override 43 @Override
31 public Long createSeckillActivity(SeckillActivityCreateReqVO createReqVO) { 44 public Long createSeckillActivity(SeckillActivityCreateReqVO createReqVO) {
32 - // 插入  
33 - SeckillActivityDO seckillActivity = SeckillActivityConvert.INSTANCE.convert(createReqVO); 45 +// validateSeckillActivityProductConflicts(null,createReqVO.getProducts());
  46 + List<Integer> statuses = asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus());
  47 + // 校验商品是否冲突
  48 + validateSeckillActivityProductConflicts(null, createReqVO.getProducts());
  49 + // 插入秒杀活动
  50 + SeckillActivityDO seckillActivity = SeckillActivityConvert.INSTANCE.convert(createReqVO)
  51 + .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getStartTime(), createReqVO.getEndTime()));;
34 seckillActivityMapper.insert(seckillActivity); 52 seckillActivityMapper.insert(seckillActivity);
  53 +
  54 + // 插入商品
  55 + List<SeckillProductDO> productDOS = CollectionUtils.convertList(createReqVO.getProducts(),
  56 + product -> SeckillActivityConvert.INSTANCE.convert(product).setActivityId(seckillActivity.getId()));
  57 + seckillProductMapper.insertBatch(productDOS);
35 // 返回 58 // 返回
36 return seckillActivity.getId(); 59 return seckillActivity.getId();
37 } 60 }
@@ -39,24 +62,110 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -39,24 +62,110 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
39 @Override 62 @Override
40 public void updateSeckillActivity(SeckillActivityUpdateReqVO updateReqVO) { 63 public void updateSeckillActivity(SeckillActivityUpdateReqVO updateReqVO) {
41 // 校验存在 64 // 校验存在
42 - this.validateSeckillActivityExists(updateReqVO.getId()); 65 + SeckillActivityDO seckillActivity = this.validateSeckillActivityExists(updateReqVO.getId());
  66 + if (PromotionActivityStatusEnum.CLOSE.getStatus().equals(seckillActivity.getStatus())) {
  67 + throw exception(SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED);
  68 + }
  69 + List<Integer> statuses = asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus());
  70 + // 校验商品是否冲突
  71 + validateSeckillActivityProductConflicts(updateReqVO.getId(), updateReqVO.getProducts());
  72 + // 更新活动
  73 + SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO)
  74 + .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getStartTime(), updateReqVO.getEndTime()));
  75 + seckillActivityMapper.updateById(updateObj);
  76 + // 更新商品
  77 + updateSeckillProduct(updateReqVO);
  78 + }
  79 +
  80 + /**
  81 + * 更新秒杀商品
  82 + */
  83 + private void updateSeckillProduct(SeckillActivityUpdateReqVO updateReqVO) {
  84 + List<SeckillProductDO> seckillProductDOS = seckillProductMapper.selectListByActivityId(updateReqVO.getId());
  85 + List<SeckillActivityBaseVO.Product> products = updateReqVO.getProducts();
  86 + //对后台查出的数据和前台查出的数据进行遍历,
  87 + //1.对前台数据进行遍历:如果不存在于后台的sku中需要新增
  88 + //2.对后台数据进行遍历:如果不存在于前台的sku中需要删除
  89 + //计算需要删除的数据
  90 + List<Long> deleteIds = CollectionUtils.convertList(seckillProductDOS, SeckillProductDO::getId,
  91 + seckillProductDO -> products.stream()
  92 + .noneMatch(product -> SeckillActivityConvert.INSTANCE.isEquals(seckillProductDO, product)));
  93 + if (CollUtil.isNotEmpty(deleteIds)) {
  94 + seckillProductMapper.deleteBatchIds(deleteIds);
  95 + }
  96 + //计算需要新增的数据
  97 + List<SeckillProductDO> newSeckillProductDOs = CollectionUtils.convertList(products,
  98 + product -> SeckillActivityConvert.INSTANCE.convert(product).setActivityId(updateReqVO.getId()));
  99 + newSeckillProductDOs.removeIf(product -> seckillProductDOS.stream()
  100 + .anyMatch(seckillProduct -> SeckillActivityConvert.INSTANCE.isEquals(seckillProduct, product)));
  101 + if (CollUtil.isNotEmpty(newSeckillProductDOs)) {
  102 + seckillProductMapper.insertBatch(newSeckillProductDOs);
  103 + }
  104 + }
  105 +
  106 + /**
  107 + * 校验商品是否冲突
  108 + *
  109 + * @param id 秒杀活动编号
  110 + * @param products 商品列表
  111 + */
  112 + public void validateSeckillActivityProductConflicts(Long id, List<SeckillActivityBaseVO.Product> products) {
  113 + if (CollUtil.isEmpty(products)) {
  114 + return;
  115 + }
  116 + List<SeckillProductDO> seckillProductDOS = seckillProductMapper
  117 + .selectListBySkuIds(CollectionUtils.convertSet(products, SeckillActivityBaseVO.Product::getSkuId));
  118 + if (CollUtil.isEmpty(seckillProductDOS)) {
  119 + return;
  120 + }
  121 + List<SeckillActivityDO> seckillActivityDOS = seckillActivityMapper
  122 + .selectBatchIds(CollectionUtils.convertSet(seckillProductDOS, SeckillProductDO::getActivityId));
  123 + if (id != null) {// 排除自己这个活动
  124 + seckillActivityDOS.removeIf(item -> id.equals(item.getId()));
  125 + }
  126 + // 排除不满足status的活动
  127 + List<Integer> statuses = asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus());
  128 + seckillActivityDOS.removeIf(item -> !statuses.contains(item.getStatus()));
  129 + //如果非空,则说明冲突
  130 + if (CollUtil.isNotEmpty(seckillActivityDOS)) {
  131 + throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS);
  132 + }
  133 +
  134 + }
  135 +
  136 + @Override
  137 + public void closeSeckillActivity(Long id) {
  138 + // 校验存在
  139 + SeckillActivityDO seckillActivity = this.validateSeckillActivityExists(id);
  140 + if (PromotionActivityStatusEnum.CLOSE.getStatus().equals(seckillActivity.getStatus())) {
  141 + throw exception(SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED);
  142 + }
  143 + if (PromotionActivityStatusEnum.END.getStatus().equals(seckillActivity.getStatus())) {
  144 + throw exception(SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_END);
  145 + }
43 // 更新 146 // 更新
44 - SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO); 147 + SeckillActivityDO updateObj = new SeckillActivityDO().setId(id).setStatus(PromotionActivityStatusEnum.CLOSE.getStatus());
45 seckillActivityMapper.updateById(updateObj); 148 seckillActivityMapper.updateById(updateObj);
  149 +
46 } 150 }
47 151
48 @Override 152 @Override
49 public void deleteSeckillActivity(Long id) { 153 public void deleteSeckillActivity(Long id) {
50 // 校验存在 154 // 校验存在
51 - this.validateSeckillActivityExists(id); 155 + SeckillActivityDO seckillActivity = this.validateSeckillActivityExists(id);
  156 + if (!PromotionActivityStatusEnum.CLOSE.getStatus().equals(seckillActivity.getStatus())) {
  157 + throw exception(SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED);
  158 + }
52 // 删除 159 // 删除
53 seckillActivityMapper.deleteById(id); 160 seckillActivityMapper.deleteById(id);
54 } 161 }
55 162
56 - private void validateSeckillActivityExists(Long id) {  
57 - if (seckillActivityMapper.selectById(id) == null) { 163 + private SeckillActivityDO validateSeckillActivityExists(Long id) {
  164 + SeckillActivityDO seckillActivity = seckillActivityMapper.selectById(id);
  165 + if (seckillActivity == null) {
58 throw exception(SECKILL_ACTIVITY_NOT_EXISTS); 166 throw exception(SECKILL_ACTIVITY_NOT_EXISTS);
59 } 167 }
  168 + return seckillActivity;
60 } 169 }
61 170
62 @Override 171 @Override
@@ -75,8 +184,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -75,8 +184,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
75 } 184 }
76 185
77 @Override 186 @Override
78 - public List<SeckillActivityDO> getSeckillActivityList(SeckillActivityExportReqVO exportReqVO) {  
79 - return seckillActivityMapper.selectList(exportReqVO); 187 + public List<SeckillProductDO> getSeckillProductListByActivityId(Long id) {
  188 + return seckillProductMapper.selectListByActivityId(id);
80 } 189 }
81 190
82 } 191 }
yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillactivity/SeckillActivityServiceImplTest.java
1 package cn.iocoder.yudao.module.promotion.service.seckillactivity; 1 package cn.iocoder.yudao.module.promotion.service.seckillactivity;
2 2
3 -import org.junit.jupiter.api.Disabled;  
4 -import org.junit.jupiter.api.Test;  
5 -import org.springframework.boot.test.mock.mockito.MockBean;  
6 -  
7 -import javax.annotation.Resource;  
8 - 3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
9 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; 4 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
10 -  
11 -import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.*; 5 +import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.SeckillActivityCreateReqVO;
  6 +import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.SeckillActivityPageReqVO;
  7 +import cn.iocoder.yudao.module.promotion.controller.admin.seckillactivity.vo.SeckillActivityUpdateReqVO;
12 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity.SeckillActivityDO; 8 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckillactivity.SeckillActivityDO;
13 import cn.iocoder.yudao.module.promotion.dal.mysql.seckillactivity.SeckillActivityMapper; 9 import cn.iocoder.yudao.module.promotion.dal.mysql.seckillactivity.SeckillActivityMapper;
14 -import cn.iocoder.yudao.framework.common.pojo.PageResult; 10 +import org.junit.jupiter.api.Disabled;
  11 +import org.junit.jupiter.api.Test;
  12 +import org.springframework.context.annotation.Import;
15 13
16 import javax.annotation.Resource; 14 import javax.annotation.Resource;
17 -import org.springframework.context.annotation.Import;  
18 -import java.util.*;  
19 -  
20 -import static cn.hutool.core.util.RandomUtil.*;  
21 -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;  
22 -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;  
23 -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;  
24 -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;  
25 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; 15 +import java.time.LocalDateTime;
  16 +
  17 +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
  18 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
  19 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
  20 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
  21 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  22 +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_ACTIVITY_NOT_EXISTS;
26 import static org.junit.jupiter.api.Assertions.*; 23 import static org.junit.jupiter.api.Assertions.*;
27 -import static org.mockito.Mockito.*;  
28 24
29 /** 25 /**
30 * {@link SeckillActivityServiceImpl} 的单元测试类 26 * {@link SeckillActivityServiceImpl} 的单元测试类
@@ -127,7 +123,7 @@ public class SeckillActivityServiceImplTest extends BaseDbUnitTest { @@ -127,7 +123,7 @@ public class SeckillActivityServiceImplTest extends BaseDbUnitTest {
127 reqVO.setName(null); 123 reqVO.setName(null);
128 reqVO.setStatus(null); 124 reqVO.setStatus(null);
129 reqVO.setTimeId(null); 125 reqVO.setTimeId(null);
130 - reqVO.setCreateTime((new Date[]{})); 126 + reqVO.setCreateTime((new LocalDateTime[]{}));
131 127
132 // 调用 128 // 调用
133 PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(reqVO); 129 PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(reqVO);
@@ -157,17 +153,17 @@ public class SeckillActivityServiceImplTest extends BaseDbUnitTest { @@ -157,17 +153,17 @@ public class SeckillActivityServiceImplTest extends BaseDbUnitTest {
157 // 测试 createTime 不匹配 153 // 测试 createTime 不匹配
158 seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setCreateTime(null))); 154 seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setCreateTime(null)));
159 // 准备参数 155 // 准备参数
160 - SeckillActivityExportReqVO reqVO = new SeckillActivityExportReqVO();  
161 - reqVO.setName(null);  
162 - reqVO.setStatus(null);  
163 - reqVO.setTimeId(null);  
164 - reqVO.setCreateTime((new Date[]{}));  
165 -  
166 - // 调用  
167 - List<SeckillActivityDO> list = seckillActivityService.getSeckillActivityList(reqVO);  
168 - // 断言  
169 - assertEquals(1, list.size());  
170 - assertPojoEquals(dbSeckillActivity, list.get(0)); 156 +// SeckillActivityExportReqVO reqVO = new SeckillActivityExportReqVO();
  157 +// reqVO.setName(null);
  158 +// reqVO.setStatus(null);
  159 +// reqVO.setTimeId(null);
  160 +// reqVO.setCreateTime((new Date[]{}));
  161 +//
  162 +// // 调用
  163 +// List<SeckillActivityDO> list = seckillActivityService.getSeckillActivityList(reqVO);
  164 +// // 断言
  165 +// assertEquals(1, list.size());
  166 +// assertPojoEquals(dbSeckillActivity, list.get(0));
171 } 167 }
172 168
173 } 169 }
yudao-ui-admin/src/api/promotion/seckillActivity.js
@@ -18,6 +18,14 @@ export function updateSeckillActivity(data) { @@ -18,6 +18,14 @@ export function updateSeckillActivity(data) {
18 }) 18 })
19 } 19 }
20 20
  21 +// 关闭限时折扣活动
  22 +export function closeSeckillActivity(id) {
  23 + return request({
  24 + url: '/promotion/seckill-activity/close?id=' + id,
  25 + method: 'put'
  26 + })
  27 +}
  28 +
21 // 删除秒杀活动 29 // 删除秒杀活动
22 export function deleteSeckillActivity(id) { 30 export function deleteSeckillActivity(id) {
23 return request({ 31 return request({
@@ -42,13 +50,3 @@ export function getSeckillActivityPage(query) { @@ -42,13 +50,3 @@ export function getSeckillActivityPage(query) {
42 params: query 50 params: query
43 }) 51 })
44 } 52 }
45 -  
46 -// 导出秒杀活动 Excel  
47 -export function exportSeckillActivityExcel(query) {  
48 - return request({  
49 - url: '/promotion/seckill-activity/export-excel',  
50 - method: 'get',  
51 - params: query,  
52 - responseType: 'blob'  
53 - })  
54 -}