diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
index 89b583a5c..9dddd959d 100644
--- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -3,14 +3,19 @@ package cn.iocoder.yudao.module.promotion.enums;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
/**
- * market 错误码枚举类
- *
+ * promotion 错误码枚举类
+ *
* market 系统,使用 1-003-000-000 段
*/
public interface ErrorCodeConstants {
- // ========== 促销活动相关 1003001000 ============ TODO 芋艿:看看是不是要删除掉
- ErrorCode ACTIVITY_NOT_EXISTS = new ErrorCode(1003001000, "促销活动不存在");
+ // ========== 促销活动相关 1003001000 ============
+ ErrorCode DISCOUNT_ACTIVITY_NOT_EXISTS = new ErrorCode(1003001000, "限时折扣活动不存在");
+ ErrorCode DISCOUNT_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1003006001, "存在商品参加了其它限时折扣活动");
+ ErrorCode DISCOUNT_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1003006002, "限时折扣活动已关闭,不能修改");
+ ErrorCode DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1003006003, "限时折扣活动未关闭,不能删除");
+ ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1003006004, "限时折扣活动已关闭,不能重复关闭");
+ ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1003006004, "限时折扣活动已结束,不能关闭");
// ========== Banner 相关 1003002000 ============
ErrorCode BANNER_NOT_EXISTS = new ErrorCode(1003002000, "Banner 不存在");
@@ -29,7 +34,7 @@ public interface ErrorCodeConstants {
// ========== 满减送活动 1003006000 ==========
ErrorCode REWARD_ACTIVITY_NOT_EXISTS = new ErrorCode(1003006000, "满减送活动不存在");
- ErrorCode REWARD_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1003006001, "商品({}) 已经参加满减送活动({})");
+ ErrorCode REWARD_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1003006001, "存在商品参加了其它满减送活动");
ErrorCode REWARD_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1003006002, "满减送活动已关闭,不能修改");
ErrorCode REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1003006003, "满减送活动未关闭,不能删除");
ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1003006004, "满减送活动已关闭,不能重复关闭");
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/DiscountActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/DiscountActivityController.java
new file mode 100755
index 000000000..5010a3124
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/DiscountActivityController.java
@@ -0,0 +1,83 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.discount;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityPageReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityRespVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO;
+import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Api(tags = "管理后台 - 限时折扣活动")
+@RestController
+@RequestMapping("/promotion/discount-activity")
+@Validated
+public class DiscountActivityController {
+
+ @Resource
+ private DiscountActivityService discountActivityService;
+
+ @PostMapping("/create")
+ @ApiOperation("创建限时折扣活动")
+ @PreAuthorize("@ss.hasPermission('promotion:discount-activity:create')")
+ public CommonResult createDiscountActivity(@Valid @RequestBody DiscountActivityCreateReqVO createReqVO) {
+ return success(discountActivityService.createDiscountActivity(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @ApiOperation("更新限时折扣活动")
+ @PreAuthorize("@ss.hasPermission('promotion:discount-activity:update')")
+ public CommonResult updateDiscountActivity(@Valid @RequestBody DiscountActivityUpdateReqVO updateReqVO) {
+ discountActivityService.updateDiscountActivity(updateReqVO);
+ return success(true);
+ }
+
+ @PutMapping("/close")
+ @ApiOperation("关闭限时折扣活动")
+ @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
+ @PreAuthorize("@ss.hasPermission('promotion:discount-activity:close')")
+ public CommonResult closeRewardActivity(@RequestParam("id") Long id) {
+ discountActivityService.closeRewardActivity(id);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @ApiOperation("删除限时折扣活动")
+ @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
+ @PreAuthorize("@ss.hasPermission('promotion:discount-activity:delete')")
+ public CommonResult deleteDiscountActivity(@RequestParam("id") Long id) {
+ discountActivityService.deleteDiscountActivity(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @ApiOperation("获得限时折扣活动")
+ @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
+ @PreAuthorize("@ss.hasPermission('promotion:discount-activity:query')")
+ public CommonResult getDiscountActivity(@RequestParam("id") Long id) {
+ DiscountActivityDO discountActivity = discountActivityService.getDiscountActivity(id);
+ return success(DiscountActivityConvert.INSTANCE.convert(discountActivity));
+ }
+
+ @GetMapping("/page")
+ @ApiOperation("获得限时折扣活动分页")
+ @PreAuthorize("@ss.hasPermission('promotion:discount-activity:query')")
+ public CommonResult> getDiscountActivityPage(@Valid DiscountActivityPageReqVO pageVO) {
+ PageResult pageResult = discountActivityService.getDiscountActivityPage(pageVO);
+ return success(DiscountActivityConvert.INSTANCE.convertPage(pageResult));
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/package-info.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/package-info.java
deleted file mode 100644
index 06f40bb4f..000000000
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * TODO 占位
- */
-package cn.iocoder.yudao.module.promotion.controller.admin.discount;
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityBaseVO.java
new file mode 100755
index 000000000..370a22848
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityBaseVO.java
@@ -0,0 +1,56 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.discount.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import java.util.Date;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+/**
+* 限时折扣活动 Base VO,提供给添加、修改、详细的子 VO 使用
+* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+*/
+@Data
+public class DiscountActivityBaseVO {
+
+ @ApiModelProperty(value = "活动标题", required = true, example = "一个标题")
+ @NotNull(message = "活动标题不能为空")
+ private String name;
+
+ @ApiModelProperty(value = "开始时间", required = true)
+ @NotNull(message = "开始时间不能为空")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date startTime;
+
+ @ApiModelProperty(value = "结束时间", required = true)
+ @NotNull(message = "结束时间不能为空")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date endTime;
+
+ @ApiModelProperty(value = "备注", example = "我是备注")
+ private String remark;
+
+ @ApiModel("商品")
+ @Data
+ public static class Product {
+
+ @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1")
+ @NotNull(message = "商品 SPU 编号不能为空")
+ private Long spuId;
+
+ @ApiModelProperty(value = "商品 SKU 编号", required = true, example = "1")
+ @NotNull(message = "商品 SKU 编号不能为空")
+ private Long skuId;
+
+ @ApiModelProperty(value = "折扣价格,单位:分", required = true, example = "1000")
+ @NotNull(message = "折扣价格不能为空")
+ @Min(value = 1, message = "折扣价格必须大于 0")
+ private Integer discountPrice;
+
+ }
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityCreateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityCreateReqVO.java
new file mode 100755
index 000000000..6bf08ab97
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityCreateReqVO.java
@@ -0,0 +1,23 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.discount.vo;
+
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@ApiModel("管理后台 - 限时折扣活动创建 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class DiscountActivityCreateReqVO extends DiscountActivityBaseVO {
+
+ /**
+ * 商品列表
+ */
+ @NotNull(message = "商品列表不能为空")
+ private List products;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityPageReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityPageReqVO.java
new file mode 100755
index 000000000..84f068df4
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityPageReqVO.java
@@ -0,0 +1,27 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.discount.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@ApiModel("管理后台 - 限时折扣活动分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class DiscountActivityPageReqVO extends PageParam {
+
+ @ApiModelProperty(value = "活动标题", example = "一个标题")
+ private String name;
+
+ @ApiModelProperty(value = "活动状态", example = "1")
+ private Integer status;
+
+ @ApiModelProperty(value = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date[] createTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityRespVO.java
new file mode 100755
index 000000000..fda1b23fc
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityRespVO.java
@@ -0,0 +1,28 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.discount.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import javax.validation.constraints.NotNull;
+import java.util.Date;
+
+@ApiModel("管理后台 - 限时折扣活动 Response VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class DiscountActivityRespVO extends DiscountActivityBaseVO {
+
+ @ApiModelProperty(value = "活动编号", required = true, example = "1024")
+ private Long id;
+
+ @ApiModelProperty(value = "活动状态", required = true, example = "1")
+ @NotNull(message = "活动状态不能为空")
+ private Integer status;
+
+ @ApiModelProperty(value = "创建时间", required = true)
+ private Date createTime;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityUpdateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityUpdateReqVO.java
new file mode 100755
index 000000000..675dfb529
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/discount/vo/DiscountActivityUpdateReqVO.java
@@ -0,0 +1,28 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.discount.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@ApiModel("管理后台 - 限时折扣活动更新 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class DiscountActivityUpdateReqVO extends DiscountActivityBaseVO {
+
+ @ApiModelProperty(value = "活动编号", required = true, example = "1024")
+ @NotNull(message = "活动编号不能为空")
+ private Long id;
+
+ /**
+ * 商品列表
+ */
+ @NotNull(message = "商品列表不能为空")
+ private List products;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java
new file mode 100755
index 000000000..982b91e90
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java
@@ -0,0 +1,49 @@
+package cn.iocoder.yudao.module.promotion.convert.discount;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityRespVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
+import cn.iocoder.yudao.module.promotion.service.discount.bo.DiscountProductDetailBO;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 限时折扣活动 Convert
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface DiscountActivityConvert {
+
+ DiscountActivityConvert INSTANCE = Mappers.getMapper(DiscountActivityConvert.class);
+
+ DiscountActivityDO convert(DiscountActivityCreateReqVO bean);
+
+ DiscountActivityDO convert(DiscountActivityUpdateReqVO bean);
+
+ DiscountActivityRespVO convert(DiscountActivityDO bean);
+
+ List convertList(List list);
+
+ PageResult convertPage(PageResult page);
+
+ DiscountProductDetailBO convert(DiscountProductDO product);
+
+ default List convertList(List products, Map activityMap) {
+ return CollectionUtils.convertList(products, product -> {
+ DiscountProductDetailBO detail = convert(product);
+ MapUtils.findAndThen(activityMap, product.getActivityId(), activity -> {
+ detail.setActivityName(activity.getName());
+ });
+ return detail;
+ });
+ }
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/package-info.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/package-info.java
deleted file mode 100644
index ce5ff843e..000000000
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * TODO 占位
- */
-package cn.iocoder.yudao.module.promotion.convert.discount;
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java
index aacbc287b..7f5323515 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java
@@ -7,8 +7,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
-import java.util.Date;
-
/**
* 限时折扣商品 DO
*
@@ -31,12 +29,6 @@ public class DiscountProductDO extends BaseDO {
* 关联 {@link DiscountActivityDO#getId()}
*/
private Long activityId;
- /**
- * 限时折扣活动的名字
- *
- * 冗余 {@link DiscountActivityDO#getName()}
- */
- private String activityName;
/**
* 商品 SPU 编号
*
@@ -49,23 +41,9 @@ public class DiscountProductDO extends BaseDO {
* 关联 ProductSkuDO 的 id 编号
*/
private Long skuId;
- /**
- * 开始时间
- */
- private Date startTime;
- /**
- * 结束时间
- */
- private Date endTime;
- /**
- * 销售价格,单位:分
- *
- * 冗余 ProductSkuDO 的 price 字段
- */
- private Integer originalPrice;
/**
* 优惠价格,单位:分
*/
- private Integer promotionPrice;
+ private Integer discountPrice;
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountActivityMapper.java
new file mode 100755
index 000000000..534ce627a
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountActivityMapper.java
@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.promotion.dal.mysql.discount;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityPageReqVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 限时折扣活动 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface DiscountActivityMapper extends BaseMapperX {
+
+ default PageResult selectPage(DiscountActivityPageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .likeIfPresent(DiscountActivityDO::getName, reqVO.getName())
+ .eqIfPresent(DiscountActivityDO::getStatus, reqVO.getStatus())
+ .betweenIfPresent(DiscountActivityDO::getCreateTime, reqVO.getCreateTime())
+ .orderByDesc(DiscountActivityDO::getId));
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java
new file mode 100755
index 000000000..deca21741
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.promotion.dal.mysql.discount;
+
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 限时折扣商城 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface DiscountProductMapper extends BaseMapperX {
+
+ default List selectListBySkuId(Collection skuIds) {
+ return selectList(DiscountProductDO::getSkuId, skuIds);
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/package-info.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/package-info.java
deleted file mode 100644
index 3588ffd83..000000000
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * TODO 占位
- */
-package cn.iocoder.yudao.module.promotion.dal.mysql.discount;
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java
index 8be2694df..0b2e721d9 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java
@@ -7,6 +7,9 @@ import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivi
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
import org.apache.ibatis.annotations.Mapper;
+import java.util.Collection;
+import java.util.List;
+
/**
* 满减送活动 Mapper
*
@@ -22,4 +25,8 @@ public interface RewardActivityMapper extends BaseMapperX {
.orderByDesc(RewardActivityDO::getId));
}
+ default List selectListByStatus(Collection statuses) {
+ return selectList(RewardActivityDO::getStatus, statuses);
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java
new file mode 100644
index 000000000..ac8d9ac17
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java
@@ -0,0 +1,76 @@
+package cn.iocoder.yudao.module.promotion.service.discount;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityPageReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
+
+import javax.validation.Valid;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * 限时折扣 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface DiscountActivityService {
+
+ /**
+ * 基于指定 SKU 编号数组,获得匹配的限时折扣商品
+ *
+ * 注意,匹配的条件,仅仅是日期符合,并且处于开启状态
+ *
+ * @param skuIds SKU 编号数组
+ * @return 匹配的限时折扣商品
+ */
+ Map getMatchDiscountProducts(Collection skuIds);
+
+ /**
+ * 创建限时折扣活动
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createDiscountActivity(@Valid DiscountActivityCreateReqVO createReqVO);
+
+ /**
+ * 更新限时折扣活动
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateDiscountActivity(@Valid DiscountActivityUpdateReqVO updateReqVO);
+
+ /**
+ * 关闭限时折扣活动
+ *
+ * @param id 编号
+ */
+ void closeRewardActivity(Long id);
+
+ /**
+ * 删除限时折扣活动
+ *
+ * @param id 编号
+ */
+ void deleteDiscountActivity(Long id);
+
+ /**
+ * 获得限时折扣活动
+ *
+ * @param id 编号
+ * @return 限时折扣活动
+ */
+ DiscountActivityDO getDiscountActivity(Long id);
+
+ /**
+ * 获得限时折扣活动分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 限时折扣活动分页
+ */
+ PageResult getDiscountActivityPage(DiscountActivityPageReqVO pageReqVO);
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java
new file mode 100644
index 000000000..076caff5d
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java
@@ -0,0 +1,169 @@
+package cn.iocoder.yudao.module.promotion.service.discount;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityBaseVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityPageReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
+import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountActivityMapper;
+import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountProductMapper;
+import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
+import cn.iocoder.yudao.module.promotion.service.discount.bo.DiscountProductDetailBO;
+import cn.iocoder.yudao.module.promotion.util.PromotionUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.util.*;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
+import static java.util.Arrays.asList;
+
+/**
+ * 限时折扣 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+public class DiscountActivityServiceImpl implements DiscountActivityService {
+
+ @Resource
+ private DiscountActivityMapper discountActivityMapper;
+ @Resource
+ private DiscountProductMapper discountProductMapper;
+
+ // TODO 芋艿:待实现
+ @Override
+ public Map getMatchDiscountProducts(Collection skuIds) {
+ Map products = new HashMap<>();
+ products.put(1L, new DiscountProductDO().setDiscountPrice(100));
+ products.put(2L, new DiscountProductDO().setDiscountPrice(50));
+ return products;
+ }
+
+ @Override
+ public Long createDiscountActivity(DiscountActivityCreateReqVO createReqVO) {
+ // 校验商品是否冲突
+ validateDiscountActivityProductConflicts(null, createReqVO.getProducts());
+
+ // 插入
+ DiscountActivityDO discountActivity = DiscountActivityConvert.INSTANCE.convert(createReqVO)
+ .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getStartTime(), createReqVO.getEndTime()));
+ discountActivityMapper.insert(discountActivity);
+ // 返回
+ return discountActivity.getId();
+ }
+
+ @Override
+ public void updateDiscountActivity(DiscountActivityUpdateReqVO updateReqVO) {
+ // 校验存在
+ DiscountActivityDO discountActivity = validateDiscountActivityExists(updateReqVO.getId());
+ if (discountActivity.getStatus().equals(PromotionActivityStatusEnum.CLOSE.getStatus())) { // 已关闭的活动,不能修改噢
+ throw exception(DISCOUNT_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED);
+ }
+ // 校验商品是否冲突
+ validateDiscountActivityProductConflicts(updateReqVO.getId(), updateReqVO.getProducts());
+
+ // 更新
+ DiscountActivityDO updateObj = DiscountActivityConvert.INSTANCE.convert(updateReqVO)
+ .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getStartTime(), updateReqVO.getEndTime()));
+ discountActivityMapper.updateById(updateObj);
+ }
+
+
+ /**
+ * 校验商品是否冲突
+ *
+ * @param id 编号
+ * @param products 商品列表
+ */
+ private void validateDiscountActivityProductConflicts(Long id, List products) {
+ if (CollUtil.isEmpty(products)) {
+ return;
+ }
+ // 查询商品参加的活动
+ List discountActivityProductList = getRewardActivityListBySkuIds(
+ convertSet(products, DiscountActivityBaseVO.Product::getSkuId),
+ asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus()));
+ if (id != null) { // 排除自己这个活动
+ discountActivityProductList.removeIf(product -> id.equals(product.getActivityId()));
+ }
+ // 如果非空,则说明冲突
+ if (CollUtil.isNotEmpty(discountActivityProductList)) {
+ throw exception(DISCOUNT_ACTIVITY_SPU_CONFLICTS);
+ }
+ }
+
+ private List getRewardActivityListBySkuIds(Collection skuIds,
+ Collection statuses) {
+ // 查询商品
+ List products = discountProductMapper.selectListBySkuId(skuIds);
+ if (CollUtil.isEmpty(products)) {
+ return new ArrayList<>(0);
+ }
+
+ // 查询活动
+ List activities = discountActivityMapper.selectBatchIds(skuIds);
+ activities.removeIf(activity -> !statuses.contains(activity.getStatus())); // 移除不满足 statuses 状态的
+ Map activityMap = CollectionUtils.convertMap(activities, DiscountActivityDO::getId);
+
+ // 移除不满足活动的商品
+ products.removeIf(product -> !activityMap.containsKey(product.getActivityId()));
+ return DiscountActivityConvert.INSTANCE.convertList(products, activityMap);
+ }
+
+ @Override
+ public void closeRewardActivity(Long id) {
+ // 校验存在
+ DiscountActivityDO dbDiscountActivity = validateDiscountActivityExists(id);
+ if (dbDiscountActivity.getStatus().equals(PromotionActivityStatusEnum.CLOSE.getStatus())) { // 已关闭的活动,不能关闭噢
+ throw exception(DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED);
+ }
+ if (dbDiscountActivity.getStatus().equals(PromotionActivityStatusEnum.END.getStatus())) { // 已关闭的活动,不能关闭噢
+ throw exception(DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_END);
+ }
+
+ // 更新
+ DiscountActivityDO updateObj = new DiscountActivityDO().setId(id).setStatus(PromotionActivityStatusEnum.CLOSE.getStatus());
+ discountActivityMapper.updateById(updateObj);
+ }
+
+ @Override
+ public void deleteDiscountActivity(Long id) {
+ // 校验存在
+ DiscountActivityDO discountActivity = validateDiscountActivityExists(id);
+ if (!discountActivity.getStatus().equals(PromotionActivityStatusEnum.CLOSE.getStatus())) { // 未关闭的活动,不能删除噢
+ throw exception(DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED);
+ }
+
+ // 删除
+ discountActivityMapper.deleteById(id);
+ }
+
+ private DiscountActivityDO validateDiscountActivityExists(Long id) {
+ DiscountActivityDO discountActivity = discountActivityMapper.selectById(id);
+ if (discountActivity == null) {
+ throw exception(DISCOUNT_ACTIVITY_NOT_EXISTS);
+ }
+ return discountActivity;
+ }
+
+ @Override
+ public DiscountActivityDO getDiscountActivity(Long id) {
+ return discountActivityMapper.selectById(id);
+ }
+
+ @Override
+ public PageResult getDiscountActivityPage(DiscountActivityPageReqVO pageReqVO) {
+ return discountActivityMapper.selectPage(pageReqVO);
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountService.java
deleted file mode 100644
index 9af23898f..000000000
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountService.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package cn.iocoder.yudao.module.promotion.service.discount;
-
-import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
-
-import java.util.Collection;
-import java.util.Map;
-
-/**
- * 限时折扣 Service 接口
- *
- * @author 芋道源码
- */
-public interface DiscountService {
-
- /**
- * 基于指定 SKU 编号数组,获得匹配的限时折扣商品
- *
- * 注意,匹配的条件,仅仅是日期符合,并且处于开启状态
- *
- * @param skuIds SKU 编号数组
- * @return 匹配的限时折扣商品
- */
- Map getMatchDiscountProducts(Collection skuIds);
-
-}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountServiceImpl.java
deleted file mode 100644
index 5b241e010..000000000
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountServiceImpl.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package cn.iocoder.yudao.module.promotion.service.discount;
-
-import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
-import org.springframework.stereotype.Service;
-import org.springframework.validation.annotation.Validated;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 限时折扣 Service 实现类
- *
- * @author 芋道源码
- */
-@Service
-@Validated
-public class DiscountServiceImpl implements DiscountService {
-
- // TODO 芋艿:待实现
- @Override
- public Map getMatchDiscountProducts(Collection skuIds) {
- Map products = new HashMap<>();
- products.put(1L, new DiscountProductDO().setPromotionPrice(100));
- products.put(2L, new DiscountProductDO().setPromotionPrice(50));
- return products;
- }
-
-}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/bo/DiscountProductDetailBO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/bo/DiscountProductDetailBO.java
new file mode 100644
index 000000000..e09fcfcd2
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/bo/DiscountProductDetailBO.java
@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.promotion.service.discount.bo;
+
+import lombok.Data;
+
+/**
+ * 限时折扣活动商品 BO
+ *
+ * @author 芋道源码
+ */
+@Data
+public class DiscountProductDetailBO {
+
+ // ========== DiscountProductDO 字段 ==========
+
+ /**
+ * 编号,主键自增
+ */
+ private Long id;
+ /**
+ * 限时折扣活动的编号
+ */
+ private Long activityId;
+ /**
+ * 商品 SPU 编号
+ */
+ private Long spuId;
+ /**
+ * 商品 SKU 编号
+ */
+ private Long skuId;
+ /**
+ * 优惠价格,单位:分
+ */
+ private Integer discountPrice;
+
+ // ========== DiscountActivityDO 字段 ==========
+ /**
+ * 活动标题
+ */
+ private String activityName;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java
index 0f50254e6..9d1aa3289 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java
@@ -12,7 +12,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProduct
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
import cn.iocoder.yudao.module.promotion.enums.common.*;
import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
-import cn.iocoder.yudao.module.promotion.service.discount.DiscountService;
+import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService;
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService;
@@ -54,7 +54,7 @@ import static java.util.Collections.singletonList;
public class PriceServiceImpl implements PriceService {
@Resource
- private DiscountService discountService;
+ private DiscountActivityService discountService;
@Resource
private RewardActivityService rewardActivityService;
@Resource
@@ -121,7 +121,7 @@ public class PriceServiceImpl implements PriceService {
Double memberDiscountPercent = memberDiscountPercentSupplier.get();
DiscountProductDO discountProduct = discountProducts.get(orderItem.getSkuId());
if (discountProduct != null // 假设优惠价格更贵,则认为没优惠
- && discountProduct.getPromotionPrice() >= orderItem.getOriginalUnitPrice()) {
+ && discountProduct.getDiscountPrice() >= orderItem.getOriginalUnitPrice()) {
discountProduct = null;
}
if (memberDiscountPercent == null && discountProduct == null) {
@@ -129,7 +129,7 @@ public class PriceServiceImpl implements PriceService {
}
// 计算价格,判断选择哪个折扣
Integer memberPrice = memberDiscountPercent != null ? (int) (orderItem.getPayPrice() * memberDiscountPercent / 100) : null;
- Integer promotionPrice = discountProduct != null ? discountProduct.getPromotionPrice() * orderItem.getCount() : null;
+ Integer promotionPrice = discountProduct != null ? discountProduct.getDiscountPrice() * orderItem.getCount() : null;
if (memberPrice == null) {
calculatePriceByDiscountActivity(priceCalculate, orderItem, discountProduct, promotionPrice);
} else if (promotionPrice == null) {
@@ -155,7 +155,8 @@ public class PriceServiceImpl implements PriceService {
private void calculatePriceByDiscountActivity(PriceCalculateRespDTO priceCalculate, PriceCalculateRespDTO.OrderItem orderItem,
DiscountProductDO discountProduct, Integer promotionPrice) {
// 记录优惠明细
- addPromotion(priceCalculate, orderItem, discountProduct.getActivityId(), discountProduct.getActivityName(),
+ addPromotion(priceCalculate, orderItem, discountProduct.getActivityId(), null
+ /* TODO 芋艿:修复下 discountProduct.getActivityName()*/,
PromotionTypeEnum.DISCOUNT_ACTIVITY.getType(), PromotionLevelEnum.SKU.getLevel(), promotionPrice,
true, StrUtil.format("限时折扣:省 {} 元", formatPrice(orderItem.getPayPrice() - promotionPrice)));
// 修改 SKU 的优惠
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
index 327770413..eb091efb1 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
@@ -14,13 +14,11 @@ import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
+import static java.util.Arrays.asList;
/**
* 满减送活动 Service 实现类
@@ -54,6 +52,7 @@ public class RewardActivityServiceImpl implements RewardActivityService {
if (dbRewardActivity.getStatus().equals(PromotionActivityStatusEnum.CLOSE.getStatus())) { // 已关闭的活动,不能修改噢
throw exception(REWARD_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED);
}
+ // 校验商品是否冲突
validateRewardActivitySpuConflicts(updateReqVO.getId(), updateReqVO.getProductSpuIds());
// 更新
@@ -109,8 +108,9 @@ public class RewardActivityServiceImpl implements RewardActivityService {
return;
}
// 查询商品参加的活动
- List rewardActivityList = getRewardActivityListBySpuIds(spuIds);
- if (id != null) { // 排除活动
+ List rewardActivityList = getRewardActivityListBySpuIds(spuIds,
+ asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus()));
+ if (id != null) { // 排除自己这个活动
rewardActivityList.removeIf(activity -> id.equals(activity.getId()));
}
// 如果非空,则说明冲突
@@ -123,10 +123,12 @@ public class RewardActivityServiceImpl implements RewardActivityService {
* 获得商品参加的满减送活动的数组
*
* @param spuIds 商品 SPU 编号数组
+ * @param statuses 活动状态数组
* @return 商品参加的满减送活动的数组
*/
- private List getRewardActivityListBySpuIds(Collection spuIds) {
- List list = rewardActivityMapper.selectList();
+ private List getRewardActivityListBySpuIds(Collection spuIds,
+ Collection statuses) {
+ List list = rewardActivityMapper.selectListByStatus(statuses);
return CollUtil.filter(list, activity -> CollUtil.containsAny(activity.getProductSpuIds(), spuIds));
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImplTest.java b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImplTest.java
new file mode 100755
index 000000000..e3190b49b
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImplTest.java
@@ -0,0 +1,137 @@
+package cn.iocoder.yudao.module.promotion.service.discount;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
+import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityPageReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO;
+import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountActivityMapper;
+import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.Import;
+
+import javax.annotation.Resource;
+import java.time.Duration;
+import java.util.Date;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
+import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
+import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.DISCOUNT_ACTIVITY_NOT_EXISTS;
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+* {@link DiscountActivityServiceImpl} 的单元测试类
+*
+* @author 芋道源码
+*/
+@Import(DiscountActivityServiceImpl.class)
+public class DiscountActivityServiceImplTest extends BaseDbUnitTest {
+
+ @Resource
+ private DiscountActivityServiceImpl discountActivityService;
+
+ @Resource
+ private DiscountActivityMapper discountActivityMapper;
+
+ @Test
+ public void testCreateDiscountActivity_success() {
+ // 准备参数
+ DiscountActivityCreateReqVO reqVO = randomPojo(DiscountActivityCreateReqVO.class, o -> {
+ // 用于触发进行中的状态
+ o.setStartTime(addTime(Duration.ofDays(1))).setEndTime(addTime(Duration.ofDays(2)));
+ });
+
+ // 调用
+ Long discountActivityId = discountActivityService.createDiscountActivity(reqVO);
+ // 断言
+ assertNotNull(discountActivityId);
+ // 校验记录的属性是否正确
+ DiscountActivityDO discountActivity = discountActivityMapper.selectById(discountActivityId);
+ assertPojoEquals(reqVO, discountActivity);
+ }
+
+ @Test
+ public void testUpdateDiscountActivity_success() {
+ // mock 数据
+ DiscountActivityDO dbDiscountActivity = randomPojo(DiscountActivityDO.class);
+ discountActivityMapper.insert(dbDiscountActivity);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ DiscountActivityUpdateReqVO reqVO = randomPojo(DiscountActivityUpdateReqVO.class, o -> {
+ o.setId(dbDiscountActivity.getId()); // 设置更新的 ID
+ });
+
+ // 调用
+ discountActivityService.updateDiscountActivity(reqVO);
+ // 校验是否更新正确
+ DiscountActivityDO discountActivity = discountActivityMapper.selectById(reqVO.getId()); // 获取最新的
+ assertPojoEquals(reqVO, discountActivity);
+ }
+
+ @Test
+ public void testUpdateDiscountActivity_notExists() {
+ // 准备参数
+ DiscountActivityUpdateReqVO reqVO = randomPojo(DiscountActivityUpdateReqVO.class);
+
+ // 调用, 并断言异常
+ assertServiceException(() -> discountActivityService.updateDiscountActivity(reqVO), DISCOUNT_ACTIVITY_NOT_EXISTS);
+ }
+
+ @Test
+ public void testDeleteDiscountActivity_success() {
+ // mock 数据
+ DiscountActivityDO dbDiscountActivity = randomPojo(DiscountActivityDO.class);
+ discountActivityMapper.insert(dbDiscountActivity);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ Long id = dbDiscountActivity.getId();
+
+ // 调用
+ discountActivityService.deleteDiscountActivity(id);
+ // 校验数据不存在了
+ assertNull(discountActivityMapper.selectById(id));
+ }
+
+ @Test
+ public void testDeleteDiscountActivity_notExists() {
+ // 准备参数
+ Long id = randomLongId();
+
+ // 调用, 并断言异常
+ assertServiceException(() -> discountActivityService.deleteDiscountActivity(id), DISCOUNT_ACTIVITY_NOT_EXISTS);
+ }
+
+ @Test
+ public void testGetDiscountActivityPage() {
+ // mock 数据
+ DiscountActivityDO dbDiscountActivity = randomPojo(DiscountActivityDO.class, o -> { // 等会查询到
+ o.setName("芋艿");
+ o.setStatus(PromotionActivityStatusEnum.WAIT.getStatus());
+ o.setCreateTime(buildTime(2021, 1, 15));
+ });
+ discountActivityMapper.insert(dbDiscountActivity);
+ // 测试 name 不匹配
+ discountActivityMapper.insert(cloneIgnoreId(dbDiscountActivity, o -> o.setName("土豆")));
+ // 测试 status 不匹配
+ discountActivityMapper.insert(cloneIgnoreId(dbDiscountActivity, o -> o.setStatus(PromotionActivityStatusEnum.END.getStatus())));
+ // 测试 createTime 不匹配
+ discountActivityMapper.insert(cloneIgnoreId(dbDiscountActivity, o -> o.setCreateTime(buildTime(2021, 2, 10))));
+ // 准备参数
+ DiscountActivityPageReqVO reqVO = new DiscountActivityPageReqVO();
+ reqVO.setName("芋艿");
+ reqVO.setStatus(PromotionActivityStatusEnum.WAIT.getStatus());
+ reqVO.setCreateTime((new Date[]{buildTime(2021, 1, 1), buildTime(2021, 1, 31)}));
+
+ // 调用
+ PageResult pageResult = discountActivityService.getDiscountActivityPage(reqVO);
+ // 断言
+ assertEquals(1, pageResult.getTotal());
+ assertEquals(1, pageResult.getList().size());
+ assertPojoEquals(dbDiscountActivity, pageResult.getList().get(0));
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java
index 786da6c10..5362064d9 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java
@@ -11,7 +11,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProduct
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
import cn.iocoder.yudao.module.promotion.enums.common.*;
import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
-import cn.iocoder.yudao.module.promotion.service.discount.DiscountService;
+import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService;
import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
@@ -41,7 +41,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest {
private PriceServiceImpl priceService;
@Mock
- private DiscountService discountService;
+ private DiscountActivityService discountService;
@Mock
private RewardActivityService rewardActivityService;
@Mock
@@ -109,10 +109,10 @@ public class PriceServiceTest extends BaseMockitoUnitTest {
ProductSkuRespDTO productSku02 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(20L).setPrice(50));
when(productSkuApi.getSkuList(eq(asSet(10L, 20L)))).thenReturn(asList(productSku01, productSku02));
// mock 方法(限时折扣 DiscountActivity 信息)
- DiscountProductDO discountProduct01 = randomPojo(DiscountProductDO.class, o -> o.setActivityId(1000L).setActivityName("活动 1000 号")
- .setSkuId(10L).setPromotionPrice(80));
- DiscountProductDO discountProduct02 = randomPojo(DiscountProductDO.class, o -> o.setActivityId(2000L).setActivityName("活动 2000 号")
- .setSkuId(20L).setPromotionPrice(40));
+ DiscountProductDO discountProduct01 = randomPojo(DiscountProductDO.class, o -> o.setActivityId(1000L)/*.setActsivityName("活动 1000 号") TODO 芋艿:待完善 */
+ .setSkuId(10L).setDiscountPrice(80));
+ DiscountProductDO discountProduct02 = randomPojo(DiscountProductDO.class, o -> o.setActivityId(2000L)/*.setActivityName("活动 2000 号") TODO 芋艿:待完善 */
+ .setSkuId(20L).setDiscountPrice(80));
when(discountService.getMatchDiscountProducts(eq(asSet(10L, 20L)))).thenReturn(
MapUtil.builder(10L, discountProduct01).put(20L, discountProduct02).map());
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/clean.sql b/yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/clean.sql
index b3308c269..d3f8e3718 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/clean.sql
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/clean.sql
@@ -2,3 +2,5 @@ DELETE FROM "market_activity";
DELETE FROM "promotion_coupon_template";
DELETE FROM "promotion_coupon";
DELETE FROM "promotion_reward_activity";
+DELETE FROM "promotion_discount_activity";
+DELETE FROM "promotion_discount_product";
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/create_tables.sql b/yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/create_tables.sql
index 4e3557578..f7a9db229 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/create_tables.sql
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/test/resources/sql/create_tables.sql
@@ -91,3 +91,32 @@ CREATE TABLE IF NOT EXISTS "promotion_reward_activity" (
"deleted" bit NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT '满减送活动';
+
+CREATE TABLE IF NOT EXISTS "promotion_discount_activity" (
+ "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+ "name" varchar NOT NULL,
+ "status" int NOT NULL,
+ "start_time" datetime NOT NULL,
+ "end_time" datetime NOT NULL,
+ "remark" varchar,
+ "creator" varchar DEFAULT '',
+ "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updater" varchar DEFAULT '',
+ "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ "deleted" bit NOT NULL DEFAULT FALSE,
+ PRIMARY KEY ("id")
+) COMMENT '限时折扣活动';
+
+CREATE TABLE IF NOT EXISTS "promotion_discount_product" (
+ "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+ "activity_id" bigint NOT NULL,
+ "spu_id" bigint NOT NULL,
+ "sku_id" bigint NOT NULL,
+ "discount_price" int NOT NULL,
+ "creator" varchar DEFAULT '',
+ "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updater" varchar DEFAULT '',
+ "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ "deleted" bit NOT NULL DEFAULT FALSE,
+ PRIMARY KEY ("id")
+) COMMENT '限时折扣活动';
diff --git a/yudao-ui-admin/src/api/mall/promotion/discountActivity.js b/yudao-ui-admin/src/api/mall/promotion/discountActivity.js
new file mode 100755
index 000000000..fd32597e3
--- /dev/null
+++ b/yudao-ui-admin/src/api/mall/promotion/discountActivity.js
@@ -0,0 +1,52 @@
+import request from '@/utils/request'
+
+// 创建限时折扣活动
+export function createDiscountActivity(data) {
+ return request({
+ url: '/promotion/discount-activity/create',
+ method: 'post',
+ data: data
+ })
+}
+
+// 更新限时折扣活动
+export function updateDiscountActivity(data) {
+ return request({
+ url: '/promotion/discount-activity/update',
+ method: 'put',
+ data: data
+ })
+}
+
+// 关闭限时折扣活动
+export function closeDiscountActivity(id) {
+ return request({
+ url: '/promotion/discount-activity/close?id=' + id,
+ method: 'put'
+ })
+}
+
+// 删除限时折扣活动
+export function deleteDiscountActivity(id) {
+ return request({
+ url: '/promotion/discount-activity/delete?id=' + id,
+ method: 'delete'
+ })
+}
+
+// 获得限时折扣活动
+export function getDiscountActivity(id) {
+ return request({
+ url: '/promotion/discount-activity/get?id=' + id,
+ method: 'get'
+ })
+}
+
+// 获得限时折扣活动分页
+export function getDiscountActivityPage(query) {
+ return request({
+ url: '/promotion/discount-activity/page',
+ method: 'get',
+ params: query
+ })
+}
diff --git a/yudao-ui-admin/src/views/mall/promotion/discountActivity/index.vue b/yudao-ui-admin/src/views/mall/promotion/discountActivity/index.vue
new file mode 100755
index 000000000..fa7f8ccf6
--- /dev/null
+++ b/yudao-ui-admin/src/views/mall/promotion/discountActivity/index.vue
@@ -0,0 +1,246 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+
+ 新增
+
+
+
+
+
+
+
+
+
+ 开始:{{ parseTime(scope.row.startTime) }}
+ 结束:{{ parseTime(scope.row.endTime) }}
+
+
+
+
+
+
+
+
+
+ {{ parseTime(scope.row.createTime) }}
+
+
+
+
+ 修改
+ 关闭
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+