Merge remote-tracking branch 'origin/master' into feature/springdoc

# Conflicts:
#	README.md
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyCreateReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyListReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyUpdateReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueCreateReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueUpdateReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageRespVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuRespVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/property/AppProductPropertyValueDetailRespVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderPageReqVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderItemRespVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderRespVO.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/PayNotifyOrderReqVO.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/PayRefundOrderReqVO.java
#	yudao-server/pom.xml
#	yudao-server/src/main/java/cn/iocoder/yudao/module/shop/controller/app/AppShopOrderController.java
This commit is contained in:
xingyu
2023-01-04 10:48:18 +08:00
471 changed files with 17761 additions and 4522 deletions

View File

@@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.UserRespDTO;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageItemRespVO;
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO;
import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert;
@@ -66,7 +66,7 @@ public class CouponController {
}
// 读取用户信息,进行拼接
Set<Long> userIds = convertSet(pageResult.getList(), CouponDO::getUserId);
Map<Long, UserRespDTO> userMap = memberUserApi.getUserMap(userIds);
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
pageResulVO.getList().forEach(itemRespVO -> MapUtils.findAndThen(userMap, itemRespVO.getUserId(),
userRespDTO -> itemRespVO.setNickname(userRespDTO.getNickname())));
return success(pageResulVO);

View File

@@ -0,0 +1,96 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.*;
import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
import cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity.SeckillActivityService;
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 java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Api(tags = "管理后台 - 秒杀活动")
@RestController
@RequestMapping("/promotion/seckill-activity")
@Validated
public class SeckillActivityController {
@Resource
private SeckillActivityService seckillActivityService;
@PostMapping("/create")
@ApiOperation("创建秒杀活动")
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:create')")
public CommonResult<Long> createSeckillActivity(@Valid @RequestBody SeckillActivityCreateReqVO createReqVO) {
return success(seckillActivityService.createSeckillActivity(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新秒杀活动")
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:update')")
public CommonResult<Boolean> updateSeckillActivity(@Valid @RequestBody SeckillActivityUpdateReqVO updateReqVO) {
seckillActivityService.updateSeckillActivity(updateReqVO);
return success(true);
}
@PutMapping("/close")
@ApiOperation("关闭秒杀活动")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:close')")
public CommonResult<Boolean> closeSeckillActivity(@RequestParam("id") Long id) {
seckillActivityService.closeSeckillActivity(id);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除秒杀活动")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:delete')")
public CommonResult<Boolean> deleteSeckillActivity(@RequestParam("id") Long id) {
seckillActivityService.deleteSeckillActivity(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得秒杀活动")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")
public CommonResult<SeckillActivityDetailRespVO> getSeckillActivity(@RequestParam("id") Long id) {
SeckillActivityDO seckillActivity = seckillActivityService.getSeckillActivity(id);
if (seckillActivity == null) {
return success(null);
}
List<SeckillProductDO> seckillProducts = seckillActivityService.getSeckillProductListByActivityId(id);
return success(SeckillActivityConvert.INSTANCE.convert(seckillActivity,seckillProducts));
}
@GetMapping("/list")
@ApiOperation("获得秒杀活动列表")
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")
public CommonResult<List<SeckillActivityRespVO>> getSeckillActivityList(@RequestParam("ids") Collection<Long> ids) {
List<SeckillActivityDO> list = seckillActivityService.getSeckillActivityList(ids);
return success(SeckillActivityConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@ApiOperation("获得秒杀活动分页")
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")
public CommonResult<PageResult<SeckillActivityRespVO>> getSeckillActivityPage(@Valid SeckillActivityPageReqVO pageVO) {
PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(pageVO);
return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult));
}
}

View File

@@ -0,0 +1,72 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeRespVO;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeUpdateReqVO;
import cn.iocoder.yudao.module.promotion.convert.seckill.seckilltime.SeckillTimeConvert;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO;
import cn.iocoder.yudao.module.promotion.service.seckill.seckilltime.SeckillTimeService;
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 java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Api(tags = "管理后台 - 秒杀时段")
@RestController
@RequestMapping("/promotion/seckill-time")
@Validated
public class SeckillTimeController {
@Resource
private SeckillTimeService seckillTimeService;
@PostMapping("/create")
@ApiOperation("创建秒杀时段")
@PreAuthorize("@ss.hasPermission('promotion:seckill-time:create')")
public CommonResult<Long> createSeckillTime(@Valid @RequestBody SeckillTimeCreateReqVO createReqVO) {
return success(seckillTimeService.createSeckillTime(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新秒杀时段")
@PreAuthorize("@ss.hasPermission('promotion:seckill-time:update')")
public CommonResult<Boolean> updateSeckillTime(@Valid @RequestBody SeckillTimeUpdateReqVO updateReqVO) {
seckillTimeService.updateSeckillTime(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除秒杀时段")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('promotion:seckill-time:delete')")
public CommonResult<Boolean> deleteSeckillTime(@RequestParam("id") Long id) {
seckillTimeService.deleteSeckillTime(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得秒杀时段")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('promotion:seckill-time:query')")
public CommonResult<SeckillTimeRespVO> getSeckillTime(@RequestParam("id") Long id) {
SeckillTimeDO seckillTime = seckillTimeService.getSeckillTime(id);
return success(SeckillTimeConvert.INSTANCE.convert(seckillTime));
}
@GetMapping("/list")
@ApiOperation("获得所有秒杀时段列表")
@PreAuthorize("@ss.hasPermission('promotion:seckill-time:query')")
public CommonResult<List<SeckillTimeRespVO>> getSeckillTimeList() {
List<SeckillTimeDO> list = seckillTimeService.getSeckillTimeList();
return success(SeckillTimeConvert.INSTANCE.convertList(list));
}
}

View File

@@ -0,0 +1,66 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
import com.fasterxml.jackson.annotation.JsonFormat;
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.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
/**
* 秒杀活动 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class SeckillActivityBaseVO {
@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)
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
private LocalDateTime startTime;
@ApiModelProperty(value = "活动结束时间", required = true)
@NotNull(message = "活动结束时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
private LocalDateTime endTime;
@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 = "12.00")
@NotNull(message = "秒杀金额不能为空")
private Integer seckillPrice;
@ApiModelProperty(value = "秒杀库存", example = "80")
@Min(value = 0, message = "秒杀库存需要大于等于 0")
private Integer stock;
@ApiModelProperty(value = "每人限购", example = "10", notes = "如果为0则不限购")
@Min(value = 0, message = "每人限购需要大于等于 0")
private Integer limitBuyCount;
}
}

View File

@@ -0,0 +1,38 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
@ApiModel("管理后台 - 秒杀活动创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SeckillActivityCreateReqVO extends SeckillActivityBaseVO {
@ApiModelProperty(value = "备注", example = "限时秒杀活动")
private String remark;
@ApiModelProperty(value = "排序", required = true, example = "1")
@NotNull(message = "排序不能为空")
private Integer sort;
@ApiModelProperty(value = "秒杀时段id", required = true, example = "1,3")
@NotEmpty(message = "参与场次不能为空")
private List<Long> timeIds;
/**
* 商品列表
*/
@NotEmpty(message = "商品列表不能为空")
@Valid
private List<Product> products;
}

View File

@@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.List;
@ApiModel("管理后台 - 秒杀活动的详细 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SeckillActivityDetailRespVO extends SeckillActivityRespVO {
/**
* 商品列表
*/
private List<Product> products;
}

View File

@@ -0,0 +1,37 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
@ApiModel("管理后台 - 秒杀活动分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SeckillActivityPageReqVO extends PageParam {
@ApiModelProperty(value = "秒杀活动名称", example = "晚九点限时秒杀")
private String name;
@ApiModelProperty(value = "活动状态", example = "进行中")
private Integer status;
@ApiModelProperty(value = "秒杀时段id", example = "1")
private Long timeId;
@ApiModelProperty(value = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
private LocalDateTime[] createTime;
}

View File

@@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
import java.util.List;
@ApiModel("管理后台 - 秒杀活动 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SeckillActivityRespVO extends SeckillActivityBaseVO {
@ApiModelProperty(value = "秒杀活动id", required = true, example = "1")
private Long id;
@ApiModelProperty(value = "付款订单数", required = true, example = "1")
private Integer orderCount;
@ApiModelProperty(value = "付款人数", required = true, example = "1")
private Integer userCount;
@ApiModelProperty(value = "创建时间", required = true)
private LocalDateTime createTime;
@ApiModelProperty(value = "秒杀时段id", required = true, example = "1,3")
private List<Long> timeIds;
@ApiModelProperty(value = "排序", required = true, example = "1")
private Integer sort;
@ApiModelProperty(value = "备注", example = "限时秒杀活动")
private String remark;
@ApiModelProperty(value = "活动状态", example = "进行中")
private Integer status;
}

View File

@@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
@ApiModel("管理后台 - 秒杀活动更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SeckillActivityUpdateReqVO extends SeckillActivityBaseVO {
@ApiModelProperty(value = "秒杀活动编号", required = true, example = "224")
@NotNull(message = "秒杀活动编号不能为空")
private Long id;
@ApiModelProperty(value = "备注", example = "限时秒杀活动")
private String remark;
@ApiModelProperty(value = "排序", required = true, example = "1")
@NotNull(message = "排序不能为空")
private Integer sort;
@ApiModelProperty(value = "秒杀时段id", required = true, example = "1,3")
@NotEmpty(message = "秒杀时段id不能为空")
private List<Long> timeIds;
/**
* 商品列表
*/
@NotEmpty(message = "商品列表不能为空")
@Valid
private List<Product> products;
}

View File

@@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.time.LocalTime;
/**
* 秒杀时段 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class SeckillTimeBaseVO {
@ApiModelProperty(value = "秒杀时段名称", required = true, example = "上午场")
@NotNull(message = "秒杀时段名称不能为空")
private String name;
@ApiModelProperty(value = "开始时间点", required = true, example = "16:30:40")
@NotNull(message = "开始时间点不能为空")
private LocalTime startTime;
@ApiModelProperty(value = "结束时间点", required = true, example = "16:30:40")
@NotNull(message = "结束时间点不能为空")
private LocalTime endTime;
}

View File

@@ -0,0 +1,12 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time;
import lombok.*;
import io.swagger.annotations.*;
@ApiModel("管理后台 - 秒杀时段创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SeckillTimeCreateReqVO extends SeckillTimeBaseVO {
}

View File

@@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalTime;
@ApiModel("管理后台 - 秒杀时段分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SeckillTimePageReqVO extends PageParam {
@ApiModelProperty(value = "秒杀时段名称", example = "上午场")
private String name;
@ApiModelProperty(value = "开始时间点", example = "16:30:40")
@DateTimeFormat(pattern = "HH:mm:ss")
private LocalTime startTime;
@ApiModelProperty(value = "结束时间点", example = "16:30:40")
@DateTimeFormat(pattern = "HH:mm:ss")
private LocalTime endTime;
}

View File

@@ -0,0 +1,26 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
@ApiModel("管理后台 - 秒杀时段 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SeckillTimeRespVO extends SeckillTimeBaseVO {
@ApiModelProperty(value = "编号", required = true, example = "1")
private Long id;
@ApiModelProperty(value = "秒杀活动数量", required = true, example = "1")
private Integer seckillActivityCount;
@ApiModelProperty(value = "创建时间", required = true)
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@ApiModel("管理后台 - 秒杀时段更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SeckillTimeUpdateReqVO extends SeckillTimeBaseVO {
@ApiModelProperty(value = "编号", required = true, example = "1")
@NotNull(message = "编号不能为空")
private Long id;
}

View File

@@ -0,0 +1,83 @@
package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity;
import cn.hutool.core.util.ObjectUtil;
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.seckill.vo.activity.*;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* 秒杀活动 Convert
*
* @author 芋道源码
*/
@Mapper
public interface SeckillActivityConvert {
SeckillActivityConvert INSTANCE = Mappers.getMapper(SeckillActivityConvert.class);
SeckillProductDO convert(SeckillActivityBaseVO.Product product);
SeckillActivityDO convert(SeckillActivityCreateReqVO bean);
default String map(Long[] value) {
return value.toString();
}
SeckillActivityDO convert(SeckillActivityUpdateReqVO bean);
SeckillActivityRespVO convert(SeckillActivityDO bean);
List<SeckillActivityRespVO> convertList(List<SeckillActivityDO> list);
PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page);
@Mappings({@Mapping(target = "products", source = "seckillProducts")})
SeckillActivityDetailRespVO convert(SeckillActivityDO seckillActivity, List<SeckillProductDO> seckillProducts);
/**
* 比较两个秒杀商品对象是否相等
*
* @param productDO 数据库中的商品
* @param productVO 前端传入的商品
* @return 是否匹配
*/
default boolean isEquals(SeckillProductDO productDO, SeckillActivityBaseVO.Product productVO) {
return ObjectUtil.equals(productDO.getSpuId(), productVO.getSpuId())
&& ObjectUtil.equals(productDO.getSkuId(), productVO.getSkuId())
&& ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice())
&& ObjectUtil.equals(productDO.getStock(), productVO.getStock())
&& ObjectUtil.equals(productDO.getLimitBuyCount(), productVO.getLimitBuyCount());
}
/**
* 比较两个秒杀商品对象是否相等
*
* @param productDO 商品1
* @param productVO 商品2
* @return 是否匹配
*/
default boolean isEquals(SeckillProductDO productDO, SeckillProductDO productVO) {
return ObjectUtil.equals(productDO.getSpuId(), productVO.getSpuId())
&& ObjectUtil.equals(productDO.getSkuId(), productVO.getSkuId())
&& ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice())
&& ObjectUtil.equals(productDO.getStock(), productVO.getStock())
&& ObjectUtil.equals(productDO.getLimitBuyCount(), productVO.getLimitBuyCount());
}
default List<SeckillProductDO> convertList(List<SeckillActivityBaseVO.Product> products, SeckillActivityDO seckillActivity) {
return CollectionUtils.convertList(products, product -> convert(product)
.setActivityId(seckillActivity.getId()).setTimeIds(seckillActivity.getTimeIds()));
}
}

View File

@@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.promotion.convert.seckill.seckilltime;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeRespVO;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeUpdateReqVO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO;
/**
* 秒杀时段 Convert
*
* @author 芋道源码
*/
@Mapper
public interface SeckillTimeConvert {
SeckillTimeConvert INSTANCE = Mappers.getMapper(SeckillTimeConvert.class);
SeckillTimeDO convert(SeckillTimeCreateReqVO bean);
SeckillTimeDO convert(SeckillTimeUpdateReqVO bean);
SeckillTimeRespVO convert(SeckillTimeDO bean);
List<SeckillTimeRespVO> convertList(List<SeckillTimeDO> list);
PageResult<SeckillTimeRespVO> convertPage(PageResult<SeckillTimeDO> page);
}

View File

@@ -0,0 +1,78 @@
package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
import java.util.List;
/**
* 秒杀活动 DO
*
* @author halfninety
*/
@TableName(value = "promotion_seckill_activity", autoResultMap = true)
@KeySequence("promotion_seckill_activity_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SeckillActivityDO extends BaseDO {
/**
* 秒杀活动编号
*/
@TableId
private Long id;
/**
* 秒杀活动名称
*/
private String name;
/**
* 活动状态
* <p>
* 枚举 {@link PromotionActivityStatusEnum 对应的类}
*/
private Integer status;
/**
* 备注
*/
private String remark;
/**
* 活动开始时间
*/
private LocalDateTime startTime;
/**
* 活动结束时间
*/
private LocalDateTime endTime;
/**
* 排序
*/
private Integer sort;
/**
* 秒杀时段 id
*/
@TableField(typeHandler = LongListTypeHandler.class)
private List<Long> timeIds;
/**
* 付款订单数
*/
private Integer orderCount;
/**
* 付款人数
*/
private Integer userCount;
/**
* 订单实付金额,单位:分
*/
private Long totalPrice;
}

View File

@@ -0,0 +1,65 @@
package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.List;
/**
* 秒杀参与商品
*
* @author halfninety
* @TableName promotion_seckill_product
*/
@TableName(value = "promotion_seckill_product", autoResultMap = true)
@KeySequence("promotion_seckill_product_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SeckillProductDO extends BaseDO {
/**
* 秒杀参与商品编号
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 秒杀活动id
*/
private Long activityId;
/**
* 秒杀时段id
*/
@TableField(typeHandler = LongListTypeHandler.class)
private List<Long> timeIds;
/**
* 商品id
*/
private Long spuId;
/**
* 商品sku_id
*/
private Long skuId;
/**
* 秒杀金额
*/
private Integer seckillPrice;
/**
* 秒杀库存
*/
private Integer stock;
/**
* 每人限购
*/
private Integer limitBuyCount;
}

View File

@@ -0,0 +1,47 @@
package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalTime;
/**
* 秒杀时段 DO
*
* @author 芋道源码
*/
@TableName("promotion_seckill_time")
@KeySequence("promotion_seckill_time_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SeckillTimeDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 秒杀时段名称
*/
private String name;
/**
* 开始时间点
*/
private LocalTime startTime;
/**
* 结束时间点
*/
private LocalTime endTime;
/**
* 秒杀活动数量
*/
private Integer seckillActivityCount;
}

View File

@@ -0,0 +1,26 @@
package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity;
import cn.hutool.core.util.ObjectUtil;
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.seckill.vo.activity.SeckillActivityPageReqVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 秒杀活动 Mapper
*
* @author halfninety
*/
@Mapper
public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> {
default PageResult<SeckillActivityDO> selectPage(SeckillActivityPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<SeckillActivityDO>()
.likeIfPresent(SeckillActivityDO::getName, reqVO.getName())
.eqIfPresent(SeckillActivityDO::getStatus, reqVO.getStatus())
.betweenIfPresent(SeckillActivityDO::getCreateTime, reqVO.getCreateTime())
.apply(ObjectUtil.isNotNull(reqVO.getTimeId()),"FIND_IN_SET(" + reqVO.getTimeId() + ",time_ids) > 0")
.orderByDesc(SeckillActivityDO::getId));
}
}

View File

@@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.List;
/**
* 秒杀活动商品 Mapper
*
* @author halfninety
*/
@Mapper
public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> {
default List<SeckillProductDO> selectListByActivityId(Long id) {
return selectList(SeckillProductDO::getActivityId, id);
}
default List<SeckillProductDO> selectListBySkuIds(Collection<Long> skuIds) {
return selectList(SeckillProductDO::getSkuId, skuIds);
}
default void updateTimeIdsByActivityId(Long id, List<Long> timeIds) {
new LambdaUpdateChainWrapper<>(this)
.set(SeckillProductDO::getTimeIds, CollUtil.join(timeIds, ","))
.eq(SeckillProductDO::getActivityId, id)
.update();
}
}

View File

@@ -0,0 +1,37 @@
package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckilltime;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.time.LocalTime;
import java.util.Collection;
import java.util.List;
/**
* 秒杀时段 Mapper
*
* @author halfninety
*/
@Mapper
public interface SeckillTimeMapper extends BaseMapperX<SeckillTimeDO> {
default List<SeckillTimeDO> selectListByTime(LocalTime time) {
return selectList(SeckillTimeDO::getStartTime, SeckillTimeDO::getEndTime, time);
}
default List<SeckillTimeDO> selectListByTime(LocalTime startTime, LocalTime endTime) {
return selectList(new LambdaQueryWrapper<SeckillTimeDO>()
.ge(SeckillTimeDO::getStartTime, startTime)
.le(SeckillTimeDO::getEndTime, endTime));
}
default void updateActivityCount(Collection<Long> ids, String type, Integer count) {
new LambdaUpdateChainWrapper<>(this)
.in(SeckillTimeDO::getId, ids)
.setSql("`seckill_activity_count` = `seckill_activity_count` " + type + count)
.update();
}
}

View File

@@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.UserRespDTO;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponMapper;
@@ -71,7 +71,7 @@ public class CouponServiceImpl implements CouponService {
Set<Long> userIds = null;
if (StrUtil.isNotEmpty(pageReqVO.getNickname())) {
userIds = CollectionUtils.convertSet(memberUserApi.getUserListByNickname(pageReqVO.getNickname()),
UserRespDTO::getId);
MemberUserRespDTO::getId);
if (CollUtil.isEmpty(userIds)) {
return PageResult.empty();
}

View File

@@ -265,7 +265,7 @@ public class PriceServiceImpl implements PriceService {
private void calculatePriceByRewardActivity(PriceCalculateRespDTO priceCalculate, List<PriceCalculateRespDTO.OrderItem> orderItems,
RewardActivityDO rewardActivity) {
// 获得最大匹配的满减送活动的规
// 获得最大匹配的满减送活动的规
RewardActivityDO.Rule rule = getLastMatchRewardActivityRule(rewardActivity, orderItems);
if (rule == null) {
// 获取不到的情况下,记录不满足的优惠明细
@@ -288,11 +288,11 @@ public class PriceServiceImpl implements PriceService {
}
/**
* 获得最大匹配的满减送活动的规
* 获得最大匹配的满减送活动的规
*
* @param rewardActivity 满减送活动
* @param orderItems 商品项
* @return 匹配的活动规
* @return 匹配的活动规
*/
private RewardActivityDO.Rule getLastMatchRewardActivityRule(RewardActivityDO rewardActivity,
List<PriceCalculateRespDTO.OrderItem> orderItems) {

View File

@@ -0,0 +1,80 @@
package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
/**
* 秒杀活动 Service 接口
*
* @author halfninety
*/
public interface SeckillActivityService {
/**
* 创建秒杀活动
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createSeckillActivity(@Valid SeckillActivityCreateReqVO createReqVO);
/**
* 更新秒杀活动
*
* @param updateReqVO 更新信息
*/
void updateSeckillActivity(@Valid SeckillActivityUpdateReqVO updateReqVO);
/**
* 关闭秒杀活动
*
* @param id 编号
*/
void closeSeckillActivity(Long id);
/**
* 删除秒杀活动
*
* @param id 编号
*/
void deleteSeckillActivity(Long id);
/**
* 获得秒杀活动
*
* @param id 编号
* @return 秒杀活动
*/
SeckillActivityDO getSeckillActivity(Long id);
/**
* 获得秒杀活动列表
*
* @param ids 编号
* @return 秒杀活动列表
*/
List<SeckillActivityDO> getSeckillActivityList(Collection<Long> ids);
/**
* 获得秒杀活动分页
*
* @param pageReqVO 分页查询
* @return 秒杀活动分页
*/
PageResult<SeckillActivityDO> getSeckillActivityPage(SeckillActivityPageReqVO pageReqVO);
/**
* 通过活动编号获取活动商品
*
* @param id 活动编号
* @return 活动商品列表
*/
List<SeckillProductDO> getSeckillProductListByActivityId(Long id);
}

View File

@@ -0,0 +1,226 @@
package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity;
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.seckill.vo.activity.SeckillActivityBaseVO;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper;
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillProductMapper;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
import cn.iocoder.yudao.module.promotion.service.seckill.seckilltime.SeckillTimeService;
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.Collection;
import java.util.List;
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 实现类
*
* @author halfninety
*/
@Service
@Validated
public class SeckillActivityServiceImpl implements SeckillActivityService {
@Resource
private SeckillActivityMapper seckillActivityMapper;
@Resource
private SeckillProductMapper seckillProductMapper;
@Resource
private SeckillTimeService seckillTimeService;
@Override
public Long createSeckillActivity(SeckillActivityCreateReqVO createReqVO) {
// 校验商品是否冲突
validateSeckillActivityProductConflicts(null, createReqVO.getProducts());
// 校验秒杀时段是否存在
seckillTimeService.validateSeckillTimeExists(createReqVO.getTimeIds());
// 插入秒杀活动
SeckillActivityDO seckillActivity = SeckillActivityConvert.INSTANCE.convert(createReqVO)
.setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getStartTime(), createReqVO.getEndTime()));
seckillActivityMapper.insert(seckillActivity);
// 插入商品
List<SeckillProductDO> productDOS = SeckillActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), seckillActivity);
seckillProductMapper.insertBatch(productDOS);
// 更新秒杀时段的秒杀活动数量
seckillTimeService.sekillActivityCountIncr(createReqVO.getTimeIds());
return seckillActivity.getId();
}
@Override
public void updateSeckillActivity(SeckillActivityUpdateReqVO updateReqVO) {
// 校验存在
SeckillActivityDO seckillActivity = validateSeckillActivityExists(updateReqVO.getId());
if (PromotionActivityStatusEnum.CLOSE.getStatus().equals(seckillActivity.getStatus())) {
throw exception(SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED);
}
// 校验商品是否冲突
validateSeckillActivityProductConflicts(updateReqVO.getId(), updateReqVO.getProducts());
// 更新活动
SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO)
.setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getStartTime(), updateReqVO.getEndTime()));
seckillActivityMapper.updateById(updateObj);
// 更新商品
updateSeckillProduct(updateReqVO);
// 更新秒杀时段的秒杀活动数量
updateSeckillTimeActivityCount(seckillActivity, updateReqVO.getTimeIds());
}
/**
* 更新秒杀时段的秒杀活动数量
*
* @param seckillActivity 查询出的秒杀活动
* @param updateTimeIds 更新后的秒杀时段id列表
*/
private void updateSeckillTimeActivityCount(SeckillActivityDO seckillActivity, List<Long> updateTimeIds) {
// 查询出 timeIds
List<Long> existsTimeIds = seckillActivity.getTimeIds();
// 需要减少的时间段
Collection<Long> reduceIds = CollUtil.filterNew(existsTimeIds, existsTimeId -> !updateTimeIds.contains(existsTimeId));
// 需要添加的时间段
updateTimeIds.removeIf(existsTimeIds::contains);
// 更新减少时间段和增加时间段
if (CollUtil.isNotEmpty(updateTimeIds)) {
seckillTimeService.sekillActivityCountIncr(updateTimeIds);
}
if (CollUtil.isNotEmpty(reduceIds)) {
seckillTimeService.sekillActivityCountDecr(reduceIds);
}
}
/**
* 更新秒杀商品
* 后台查出的数据和前台查出的数据进行遍历,
* 1. 对前台数据进行遍历:如果不存在于后台的 sku 中需要新增
* 2. 对后台数据进行遍历:如果不存在于前台的 sku 中需要删除
* 3. 最后对当前活动商品全部更新更新秒杀时段id列表
*
* @param updateReqVO 更新的请求VO
*/
private void updateSeckillProduct(SeckillActivityUpdateReqVO updateReqVO) {
List<SeckillProductDO> seckillProductDOS = seckillProductMapper.selectListByActivityId(updateReqVO.getId());
List<SeckillActivityBaseVO.Product> products = updateReqVO.getProducts();
// 计算需要删除的数据
List<Long> deleteIds = CollectionUtils.convertList(seckillProductDOS, SeckillProductDO::getId,
seckillProductDO -> products.stream()
.noneMatch(product -> SeckillActivityConvert.INSTANCE.isEquals(seckillProductDO, product)));
if (CollUtil.isNotEmpty(deleteIds)) {
seckillProductMapper.deleteBatchIds(deleteIds);
}
// 计算需要新增的数据
List<SeckillProductDO> newSeckillProductDOs = CollectionUtils.convertList(products,
product -> SeckillActivityConvert.INSTANCE.convert(product).setActivityId(updateReqVO.getId()));
newSeckillProductDOs.removeIf(product -> seckillProductDOS.stream()
.anyMatch(seckillProduct -> SeckillActivityConvert.INSTANCE.isEquals(seckillProduct, product)));
if (CollUtil.isNotEmpty(newSeckillProductDOs)) {
seckillProductMapper.insertBatch(newSeckillProductDOs);
}
//全量更新当前活动商品的秒杀时段id列表timeIds
seckillProductMapper.updateTimeIdsByActivityId(updateReqVO.getId(), updateReqVO.getTimeIds());
}
/**
* 校验商品是否冲突
*
* @param id 秒杀活动编号
* @param products 商品列表
*/
private void validateSeckillActivityProductConflicts(Long id, List<SeckillActivityBaseVO.Product> products) {
if (CollUtil.isEmpty(products)) {
return;
}
List<SeckillProductDO> seckillProductDOS = seckillProductMapper
.selectListBySkuIds(CollectionUtils.convertSet(products, SeckillActivityBaseVO.Product::getSkuId));
if (CollUtil.isEmpty(seckillProductDOS)) {
return;
}
List<SeckillActivityDO> seckillActivityDOS = seckillActivityMapper
.selectBatchIds(CollectionUtils.convertSet(seckillProductDOS, SeckillProductDO::getActivityId));
if (id != null) { // 排除自己这个活动
seckillActivityDOS.removeIf(item -> id.equals(item.getId()));
}
// 排除不满足 status 的活动
List<Integer> statuses = asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus());
seckillActivityDOS.removeIf(item -> !statuses.contains(item.getStatus()));
// 如果非空,则说明冲突
if (CollUtil.isNotEmpty(seckillActivityDOS)) {
throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS);
}
}
@Override
public void closeSeckillActivity(Long id) {
// 校验存在
SeckillActivityDO seckillActivity = this.validateSeckillActivityExists(id);
if (PromotionActivityStatusEnum.CLOSE.getStatus().equals(seckillActivity.getStatus())) {
throw exception(SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED);
}
if (PromotionActivityStatusEnum.END.getStatus().equals(seckillActivity.getStatus())) {
throw exception(SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_END);
}
// 更新
SeckillActivityDO updateObj = new SeckillActivityDO().setId(id).setStatus(PromotionActivityStatusEnum.CLOSE.getStatus());
seckillActivityMapper.updateById(updateObj);
}
@Override
public void deleteSeckillActivity(Long id) {
// 校验存在
SeckillActivityDO seckillActivity = this.validateSeckillActivityExists(id);
List<Integer> statuses = asList(PromotionActivityStatusEnum.CLOSE.getStatus(), PromotionActivityStatusEnum.END.getStatus());
if (!statuses.contains(seckillActivity.getStatus())) {
throw exception(SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END);
}
// 更新秒杀时段的秒杀活动数量
seckillTimeService.sekillActivityCountDecr(seckillActivity.getTimeIds());
// 删除
seckillActivityMapper.deleteById(id);
}
private SeckillActivityDO validateSeckillActivityExists(Long id) {
SeckillActivityDO seckillActivity = seckillActivityMapper.selectById(id);
if (seckillActivity == null) {
throw exception(SECKILL_ACTIVITY_NOT_EXISTS);
}
return seckillActivity;
}
@Override
public SeckillActivityDO getSeckillActivity(Long id) {
return seckillActivityMapper.selectById(id);
}
@Override
public List<SeckillActivityDO> getSeckillActivityList(Collection<Long> ids) {
return seckillActivityMapper.selectBatchIds(ids);
}
@Override
public PageResult<SeckillActivityDO> getSeckillActivityPage(SeckillActivityPageReqVO pageReqVO) {
return seckillActivityMapper.selectPage(pageReqVO);
}
@Override
public List<SeckillProductDO> getSeckillProductListByActivityId(Long id) {
return seckillProductMapper.selectListByActivityId(id);
}
}

View File

@@ -0,0 +1,76 @@
package cn.iocoder.yudao.module.promotion.service.seckill.seckilltime;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeUpdateReqVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
/**
* 秒杀时段 Service 接口
*
* @author halfninety
*/
public interface SeckillTimeService {
/**
* 创建秒杀时段
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createSeckillTime(@Valid SeckillTimeCreateReqVO createReqVO);
/**
* 更新秒杀时段
*
* @param updateReqVO 更新信息
*/
void updateSeckillTime(@Valid SeckillTimeUpdateReqVO updateReqVO);
/**
* 删除秒杀时段
*
* @param id 编号
*/
void deleteSeckillTime(Long id);
/**
* 获得秒杀时段
*
* @param id 编号
* @return 秒杀时段
*/
SeckillTimeDO getSeckillTime(Long id);
/**
* 获得所有秒杀时段列表
*
* @return 所有秒杀时段列表
*/
List<SeckillTimeDO> getSeckillTimeList();
/**
* 校验秒杀时段是否存在
*
* @param timeIds 秒杀时段id集合
*/
void validateSeckillTimeExists(Collection<Long> timeIds);
/**
* 秒杀时段列表的秒杀活动数量加 1
*
* @param ids 秒杀时段id列表
*/
void sekillActivityCountIncr(Collection<Long> ids);
/**
* 秒杀时段列表的秒杀活动数量减 1
*
* @param ids 秒杀时段id列表
*/
void sekillActivityCountDecr(Collection<Long> ids);
}

View File

@@ -0,0 +1,124 @@
package cn.iocoder.yudao.module.promotion.service.seckill.seckilltime;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeUpdateReqVO;
import cn.iocoder.yudao.module.promotion.convert.seckill.seckilltime.SeckillTimeConvert;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO;
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckilltime.SeckillTimeMapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.time.LocalTime;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_TIME_CONFLICTS;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_TIME_NOT_EXISTS;
/**
* 秒杀时段 Service 实现类
*
* @author halfninety
*/
@Service
@Validated
public class SeckillTimeServiceImpl implements SeckillTimeService {
@Resource
private SeckillTimeMapper seckillTimeMapper;
@Override
public Long createSeckillTime(SeckillTimeCreateReqVO createReqVO) {
// 校验时间段是否冲突
validateSeckillTimeConflict(null, createReqVO.getStartTime(), createReqVO.getEndTime());
// 插入
SeckillTimeDO seckillTime = SeckillTimeConvert.INSTANCE.convert(createReqVO);
seckillTimeMapper.insert(seckillTime);
// 返回
return seckillTime.getId();
}
@Override
public void updateSeckillTime(SeckillTimeUpdateReqVO updateReqVO) {
// 校验存在
this.validateSeckillTimeExists(updateReqVO.getId());
// 校验时间段是否冲突
validateSeckillTimeConflict(updateReqVO.getId(), updateReqVO.getStartTime(), updateReqVO.getEndTime());
// 更新
SeckillTimeDO updateObj = SeckillTimeConvert.INSTANCE.convert(updateReqVO);
seckillTimeMapper.updateById(updateObj);
}
@Override
public void deleteSeckillTime(Long id) {
// 校验存在
this.validateSeckillTimeExists(id);
// 删除
seckillTimeMapper.deleteById(id);
}
private void validateSeckillTimeExists(Long id) {
if (seckillTimeMapper.selectById(id) == null) {
throw exception(SECKILL_TIME_NOT_EXISTS);
}
}
/**
* 校验时间是否存在冲突
*
* @param startTime 开始时间
* @param endTime 结束时间
*/
private void validateSeckillTimeConflict(Long id, LocalTime startTime, LocalTime endTime) {
//查询开始时间,结束时间,是否在别人的时间段内
List<SeckillTimeDO> startTimeList = seckillTimeMapper.selectListByTime(startTime);
List<SeckillTimeDO> endTimeList = seckillTimeMapper.selectListByTime(endTime);
//查询自己时间段内是否有时间段
List<SeckillTimeDO> startEndTimeList = seckillTimeMapper.selectListByTime(startTime, endTime);
if (id != null) {
//移除自己
startTimeList.removeIf(seckillTime -> Objects.equals(seckillTime.getId(), id));
endTimeList.removeIf(seckillTime -> Objects.equals(seckillTime.getId(), id));
startEndTimeList.removeIf(seckillTime -> Objects.equals(seckillTime.getId(), id));
}
if (CollUtil.isNotEmpty(startTimeList) || CollUtil.isNotEmpty(endTimeList)
|| CollUtil.isNotEmpty(startEndTimeList)) {
throw exception(SECKILL_TIME_CONFLICTS);
}
}
@Override
public SeckillTimeDO getSeckillTime(Long id) {
return seckillTimeMapper.selectById(id);
}
@Override
public List<SeckillTimeDO> getSeckillTimeList() {
return seckillTimeMapper.selectList();
}
@Override
public void validateSeckillTimeExists(Collection<Long> timeIds) {
if (CollUtil.isEmpty(timeIds)) {
throw exception(SECKILL_TIME_NOT_EXISTS);
}
if (seckillTimeMapper.selectBatchIds(timeIds).size() != timeIds.size()) {
throw exception(SECKILL_TIME_NOT_EXISTS);
}
}
@Override
public void sekillActivityCountIncr(Collection<Long> ids) {
seckillTimeMapper.updateActivityCount(ids, "+", 1);
}
@Override
public void sekillActivityCountDecr(Collection<Long> ids) {
seckillTimeMapper.updateActivityCount(ids, "-", 1);
}
}

View File

@@ -0,0 +1,170 @@
package cn.iocoder.yudao.module.promotion.service.seckillactivity;
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.seckill.vo.activity.SeckillActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper;
import cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity.SeckillActivityServiceImpl;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import java.time.LocalDateTime;
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.SECKILL_ACTIVITY_NOT_EXISTS;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link SeckillActivityServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@Import(SeckillActivityServiceImpl.class)
public class SeckillActivityServiceImplTest extends BaseDbUnitTest {
@Resource
private SeckillActivityServiceImpl seckillActivityService;
@Resource
private SeckillActivityMapper seckillActivityMapper;
@Test
public void testCreateSeckillActivity_success() {
// 准备参数
SeckillActivityCreateReqVO reqVO = randomPojo(SeckillActivityCreateReqVO.class);
// 调用
Long seckillActivityId = seckillActivityService.createSeckillActivity(reqVO);
// 断言
assertNotNull(seckillActivityId);
// 校验记录的属性是否正确
SeckillActivityDO seckillActivity = seckillActivityMapper.selectById(seckillActivityId);
assertPojoEquals(reqVO, seckillActivity);
}
@Test
public void testUpdateSeckillActivity_success() {
// mock 数据
SeckillActivityDO dbSeckillActivity = randomPojo(SeckillActivityDO.class);
seckillActivityMapper.insert(dbSeckillActivity);// @Sql: 先插入出一条存在的数据
// 准备参数
SeckillActivityUpdateReqVO reqVO = randomPojo(SeckillActivityUpdateReqVO.class, o -> {
o.setId(dbSeckillActivity.getId()); // 设置更新的 ID
});
// 调用
seckillActivityService.updateSeckillActivity(reqVO);
// 校验是否更新正确
SeckillActivityDO seckillActivity = seckillActivityMapper.selectById(reqVO.getId()); // 获取最新的
assertPojoEquals(reqVO, seckillActivity);
}
@Test
public void testUpdateSeckillActivity_notExists() {
// 准备参数
SeckillActivityUpdateReqVO reqVO = randomPojo(SeckillActivityUpdateReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> seckillActivityService.updateSeckillActivity(reqVO), SECKILL_ACTIVITY_NOT_EXISTS);
}
@Test
public void testDeleteSeckillActivity_success() {
// mock 数据
SeckillActivityDO dbSeckillActivity = randomPojo(SeckillActivityDO.class);
seckillActivityMapper.insert(dbSeckillActivity);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbSeckillActivity.getId();
// 调用
seckillActivityService.deleteSeckillActivity(id);
// 校验数据不存在了
assertNull(seckillActivityMapper.selectById(id));
}
@Test
public void testDeleteSeckillActivity_notExists() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> seckillActivityService.deleteSeckillActivity(id), SECKILL_ACTIVITY_NOT_EXISTS);
}
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGetSeckillActivityPage() {
// mock 数据
SeckillActivityDO dbSeckillActivity = randomPojo(SeckillActivityDO.class, o -> { // 等会查询到
o.setName(null);
o.setStatus(null);
o.setTimeIds(null);
o.setCreateTime(null);
});
seckillActivityMapper.insert(dbSeckillActivity);
// 测试 name 不匹配
seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setName(null)));
// 测试 status 不匹配
seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setStatus(null)));
// 测试 timeId 不匹配
seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setTimeIds(null)));
// 测试 createTime 不匹配
seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setCreateTime(null)));
// 准备参数
SeckillActivityPageReqVO reqVO = new SeckillActivityPageReqVO();
reqVO.setName(null);
reqVO.setStatus(null);
reqVO.setTimeId(null);
reqVO.setCreateTime((new LocalDateTime[]{}));
// 调用
PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbSeckillActivity, pageResult.getList().get(0));
}
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGetSeckillActivityList() {
// mock 数据
SeckillActivityDO dbSeckillActivity = randomPojo(SeckillActivityDO.class, o -> { // 等会查询到
o.setName(null);
o.setStatus(null);
o.setTimeIds(null);
o.setCreateTime(null);
});
seckillActivityMapper.insert(dbSeckillActivity);
// 测试 name 不匹配
seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setName(null)));
// 测试 status 不匹配
seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setStatus(null)));
// 测试 timeId 不匹配
seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setTimeIds(null)));
// 测试 createTime 不匹配
seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setCreateTime(null)));
// 准备参数
// SeckillActivityExportReqVO reqVO = new SeckillActivityExportReqVO();
// reqVO.setName(null);
// reqVO.setStatus(null);
// reqVO.setTimeId(null);
// reqVO.setCreateTime((new Date[]{}));
//
// // 调用
// List<SeckillActivityDO> list = seckillActivityService.getSeckillActivityList(reqVO);
// // 断言
// assertEquals(1, list.size());
// assertPojoEquals(dbSeckillActivity, list.get(0));
}
}

View File

@@ -0,0 +1,189 @@
package cn.iocoder.yudao.module.promotion.service.seckilltime;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeUpdateReqVO;
import cn.iocoder.yudao.module.promotion.service.seckill.seckilltime.SeckillTimeServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import javax.annotation.Resource;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO;
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckilltime.SeckillTimeMapper;
import org.springframework.context.annotation.Import;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link SeckillTimeServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@Import(SeckillTimeServiceImpl.class)
public class SeckillTimeServiceImplTest extends BaseDbUnitTest {
@Resource
private SeckillTimeServiceImpl seckillTimeService;
@Resource
private SeckillTimeMapper seckillTimeMapper;
@Resource
private ObjectMapper objectMapper;
@Test
public void testJacksonSerializ(){
// 准备参数
SeckillTimeCreateReqVO reqVO = randomPojo(SeckillTimeCreateReqVO.class);
// ObjectMapper objectMapper = new ObjectMapper();
try {
String string = objectMapper.writeValueAsString(reqVO);
System.out.println(string);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
@Test
public void testCreateSeckillTime_success() {
// 准备参数
SeckillTimeCreateReqVO reqVO = randomPojo(SeckillTimeCreateReqVO.class);
// 调用
Long seckillTimeId = seckillTimeService.createSeckillTime(reqVO);
// 断言
assertNotNull(seckillTimeId);
// 校验记录的属性是否正确
SeckillTimeDO seckillTime = seckillTimeMapper.selectById(seckillTimeId);
assertPojoEquals(reqVO, seckillTime);
}
@Test
public void testUpdateSeckillTime_success() {
// mock 数据
SeckillTimeDO dbSeckillTime = randomPojo(SeckillTimeDO.class);
seckillTimeMapper.insert(dbSeckillTime);// @Sql: 先插入出一条存在的数据
// 准备参数
SeckillTimeUpdateReqVO reqVO = randomPojo(SeckillTimeUpdateReqVO.class, o -> {
o.setId(dbSeckillTime.getId()); // 设置更新的 ID
});
// 调用
seckillTimeService.updateSeckillTime(reqVO);
// 校验是否更新正确
SeckillTimeDO seckillTime = seckillTimeMapper.selectById(reqVO.getId()); // 获取最新的
assertPojoEquals(reqVO, seckillTime);
}
@Test
public void testUpdateSeckillTime_notExists() {
// 准备参数
SeckillTimeUpdateReqVO reqVO = randomPojo(SeckillTimeUpdateReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> seckillTimeService.updateSeckillTime(reqVO), SECKILL_TIME_NOT_EXISTS);
}
@Test
public void testDeleteSeckillTime_success() {
// mock 数据
SeckillTimeDO dbSeckillTime = randomPojo(SeckillTimeDO.class);
seckillTimeMapper.insert(dbSeckillTime);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbSeckillTime.getId();
// 调用
seckillTimeService.deleteSeckillTime(id);
// 校验数据不存在了
assertNull(seckillTimeMapper.selectById(id));
}
@Test
public void testDeleteSeckillTime_notExists() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> seckillTimeService.deleteSeckillTime(id), SECKILL_TIME_NOT_EXISTS);
}
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGetSeckillTimePage() {
// mock 数据
// SeckillTimeDO dbSeckillTime = randomPojo(SeckillTimeDO.class, o -> { // 等会查询到
// o.setName(null);
// o.setStartTime(null);
// o.setEndTime(null);
// o.setCreateTime(null);
// });
// seckillTimeMapper.insert(dbSeckillTime);
// // 测试 name 不匹配
// seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setName(null)));
// // 测试 startTime 不匹配
// seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setStartTime(null)));
// // 测试 endTime 不匹配
// seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setEndTime(null)));
// // 测试 createTime 不匹配
// seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setCreateTime(null)));
// // 准备参数
// SeckillTimePageReqVO reqVO = new SeckillTimePageReqVO();
// reqVO.setName(null);
//// reqVO.setStartTime((new LocalTime()));
//// reqVO.setEndTime((new LocalTime[]{}));
//// reqVO.setCreateTime((new Date[]{}));
//
// // 调用
// PageResult<SeckillTimeDO> pageResult = seckillTimeService.getSeckillTimePage(reqVO);
// // 断言
// assertEquals(1, pageResult.getTotal());
// assertEquals(1, pageResult.getList().size());
// assertPojoEquals(dbSeckillTime, pageResult.getList().get(0));
}
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGetSeckillTimeList() {
// mock 数据
SeckillTimeDO dbSeckillTime = randomPojo(SeckillTimeDO.class, o -> { // 等会查询到
o.setName(null);
o.setStartTime(null);
o.setEndTime(null);
o.setCreateTime(null);
});
seckillTimeMapper.insert(dbSeckillTime);
// 测试 name 不匹配
seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setName(null)));
// 测试 startTime 不匹配
seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setStartTime(null)));
// 测试 endTime 不匹配
seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setEndTime(null)));
// 测试 createTime 不匹配
seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setCreateTime(null)));
// 准备参数
// SeckillTimeExportReqVO reqVO = new SeckillTimeExportReqVO();
// reqVO.setName(null);
// reqVO.setStartTime((new LocalTime[]{}));
// reqVO.setEndTime((new LocalTime[]{}));
// reqVO.setCreateTime((new Date[]{}));
//
// // 调用
// List<SeckillTimeDO> list = seckillTimeService.getSeckillTimeList(reqVO);
// // 断言
// assertEquals(1, list.size());
// assertPojoEquals(dbSeckillTime, list.get(0));
}
}

View File

@@ -9,7 +9,7 @@ spring:
# 数据源配置项
datasource:
name: ruoyi-vue-pro
url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false; # MODE 使用 MySQL 模式DATABASE_TO_UPPER 配置表和字段使用小写
url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模式DATABASE_TO_UPPER 配置表和字段使用小写
driver-class-name: org.h2.Driver
username: sa
password: