From 979ba0f9161f36e76aeb14486f1549c9180669c0 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 31 Oct 2022 23:47:06 +0800 Subject: [PATCH] =?UTF-8?q?promotion=EF=BC=9A=E5=AE=9E=E7=8E=B0=E4=BC=98?= =?UTF-8?q?=E6=83=A0=E5=8A=B5=E6=A8=A1=E6=9D=BF=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../promotion/enums/ErrorCodeConstants.java | 4 + .../CouponTemplateValidityTypeEnum.java | 4 +- .../coupon/CouponTemplateController.java | 74 ++++++++ .../admin/coupon/vo/CouponTemplateBaseVO.java | 142 ++++++++++++++ .../coupon/vo/CouponTemplateCreateReqVO.java | 14 ++ .../coupon/vo/CouponTemplatePageReqVO.java | 37 ++++ .../admin/coupon/vo/CouponTemplateRespVO.java | 35 ++++ .../coupon/vo/CouponTemplateUpdateReqVO.java | 21 +++ .../convert/coupon/CouponTemplateConvert.java | 29 +++ .../dataobject/coupon/CouponTemplateDO.java | 12 +- .../mysql/coupon/CouponTemplateMapper.java | 27 +++ .../service/coupon/CouponTemplateService.java | 56 ++++++ .../coupon/CouponTemplateServiceImpl.java | 79 ++++++++ .../coupon/CouponTemplateServiceImplTest.java | 173 ++++++++++++++++++ 14 files changed, 699 insertions(+), 8 deletions(-) create mode 100755 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/CouponTemplateController.java create mode 100755 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplateBaseVO.java create mode 100755 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplateCreateReqVO.java create mode 100755 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplatePageReqVO.java create mode 100755 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplateRespVO.java create mode 100755 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplateUpdateReqVO.java create mode 100755 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponTemplateConvert.java create mode 100755 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java create mode 100755 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateService.java create mode 100755 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java create mode 100755 yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImplTest.java 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 0976f846d..4b6cb8ca6 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 @@ -19,4 +19,8 @@ public interface ErrorCodeConstants { ErrorCode COUPON_NO_MATCH_SPU = new ErrorCode(1003003000, "优惠劵没有可使用的商品!"); ErrorCode COUPON_NO_MATCH_MIN_PRICE = new ErrorCode(1003003000, "不满足优惠劵使用的最低金额"); + // ========== 优惠劵模板 1003004000 ========== + ErrorCode COUPON_TEMPLATE_NOT_EXISTS = new ErrorCode(1003004000, "优惠劵模板不存在"); + ErrorCode COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL = new ErrorCode(1003004001, "发放数量不能小于已领取数量({})"); + } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/coupon/CouponTemplateValidityTypeEnum.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/coupon/CouponTemplateValidityTypeEnum.java index a524502e3..e940900b7 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/coupon/CouponTemplateValidityTypeEnum.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/coupon/CouponTemplateValidityTypeEnum.java @@ -15,8 +15,8 @@ import java.util.Arrays; @Getter public enum CouponTemplateValidityTypeEnum implements IntArrayValuable { - FIXED_DATE(1, "固定日期"), - FIXED_TERM_TODAY(2, "领取日期"), + DATE(1, "固定日期可用"), + TERM(2, "领取之后可用"), ; public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CouponTemplateValidityTypeEnum::getType).toArray(); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/CouponTemplateController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/CouponTemplateController.java new file mode 100755 index 000000000..4f1d51c61 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/CouponTemplateController.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.coupon; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.CouponTemplateCreateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.CouponTemplatePageReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.CouponTemplateRespVO; +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.CouponTemplateUpdateReqVO; +import cn.iocoder.yudao.module.promotion.convert.coupon.CouponTemplateConvert; +import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; +import cn.iocoder.yudao.module.promotion.service.coupon.CouponTemplateService; +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/coupon-template") +@Validated +public class CouponTemplateController { + + @Resource + private CouponTemplateService couponTemplateService; + + @PostMapping("/create") + @ApiOperation("创建优惠劵模板") + @PreAuthorize("@ss.hasPermission('promotion:coupon-template:create')") + public CommonResult createCouponTemplate(@Valid @RequestBody CouponTemplateCreateReqVO createReqVO) { + return success(couponTemplateService.createCouponTemplate(createReqVO)); + } + + @PutMapping("/update") + @ApiOperation("更新优惠劵模板") + @PreAuthorize("@ss.hasPermission('promotion:coupon-template:update')") + public CommonResult updateCouponTemplate(@Valid @RequestBody CouponTemplateUpdateReqVO updateReqVO) { + couponTemplateService.updateCouponTemplate(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @ApiOperation("删除优惠劵模板") + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) + @PreAuthorize("@ss.hasPermission('promotion:coupon-template:delete')") + public CommonResult deleteCouponTemplate(@RequestParam("id") Long id) { + couponTemplateService.deleteCouponTemplate(id); + return success(true); + } + + @GetMapping("/get") + @ApiOperation("获得优惠劵模板") + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) + @PreAuthorize("@ss.hasPermission('promotion:coupon-template:query')") + public CommonResult getCouponTemplate(@RequestParam("id") Long id) { + CouponTemplateDO couponTemplate = couponTemplateService.getCouponTemplate(id); + return success(CouponTemplateConvert.INSTANCE.convert(couponTemplate)); + } + + @GetMapping("/page") + @ApiOperation("获得优惠劵模板分页") + @PreAuthorize("@ss.hasPermission('promotion:coupon-template:query')") + public CommonResult> getCouponTemplatePage(@Valid CouponTemplatePageReqVO pageVO) { + PageResult pageResult = couponTemplateService.getCouponTemplatePage(pageVO); + return success(CouponTemplateConvert.INSTANCE.convertPage(pageResult)); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplateBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplateBaseVO.java new file mode 100755 index 000000000..813c31c6b --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplateBaseVO.java @@ -0,0 +1,142 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTemplateValidityTypeEnum; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.AssertTrue; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import java.util.Date; +import java.util.List; +import java.util.Objects; + +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 CouponTemplateBaseVO { + + @ApiModelProperty(value = "优惠劵名", required = true, example = "春节送送送") + @NotNull(message = "优惠劵名不能为空") + private String name; + + @ApiModelProperty(value = "发行总量", required = true, example = "1024", notes = "-1 - 则表示不限制发放数量") + @NotNull(message = "发行总量不能为空") + private Integer totalCount; + + @ApiModelProperty(value = "每人限领个数", required = true, example = "66", notes = "-1 - 则表示不限制") + @NotNull(message = "每人限领个数不能为空") + private Integer takeLimitCount; + + @ApiModelProperty(value = "领取方式", required = true, example = "1", notes = "参见 CouponTakeTypeEnum 枚举类") + @NotNull(message = "领取方式不能为空") + private Integer takeType; + + @ApiModelProperty(value = "是否设置满多少金额可用", required = true, example = "100", notes = "单位:分;0 - 不限制") + @NotNull(message = "是否设置满多少金额可用不能为空") + private Integer usePrice; + + @ApiModelProperty(value = "商品范围", required = true, example = "1", notes = "参见 PromotionProductScopeEnum 枚举类") + @NotNull(message = "商品范围不能为空") + @InEnum(PromotionProductScopeEnum.class) + private Integer productScope; + + @ApiModelProperty(value = "商品 SPU 编号的数组", example = "1,3") + private List productSpuIds; + + @ApiModelProperty(value = "生效日期类型", required = true, example = "1") + @NotNull(message = "生效日期类型不能为空") + @InEnum(CouponTemplateValidityTypeEnum.class) + private Integer validityType; + + @ApiModelProperty(value = "固定日期 - 生效开始时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private Date validStartTime; + + @ApiModelProperty(value = "固定日期 - 生效结束时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private Date validEndTime; + + @ApiModelProperty(value = "领取日期 - 开始天数") + @Min(value = 0L, message = "开始天数必须大于 0") + private Integer fixedStartTerm; + + @ApiModelProperty(value = "领取日期 - 结束天数") + @Min(value = 1L, message = "开始天数必须大于 1") + private Integer fixedEndTerm; + + @ApiModelProperty(value = "优惠类型", required = true, example = "1", notes = "参见 PromotionDiscountTypeEnum 枚举") + @NotNull(message = "优惠类型不能为空") + @InEnum(PromotionDiscountTypeEnum.class) + private Integer discountType; + + @ApiModelProperty(value = "折扣百分比", example = "80", notes = "例如说,80% 为 80") + @Min(value = 1) + private Integer discountPercent; + + @ApiModelProperty(value = "优惠金额", example = "10", notes = "单位:分") + @Min(value = 1) + private Integer discountPrice; + + @ApiModelProperty(value = "折扣上限", example = "100", notes = "单位:分,仅在 discountType 为 PERCENT 使用") + private Integer discountPriceLimit; + + @AssertTrue(message = "商品 SPU 编号的数组不能为空") + public boolean isProductSpuIdsValid() { + return Objects.equals(productScope, PromotionProductScopeEnum.ALL.getScope()) // 全部范围时,可以为空 + || CollUtil.isNotEmpty(productSpuIds); + } + + @AssertTrue(message = "生效开始时间不能为空") + public boolean isValidStartTimeValid() { + return ObjectUtil.notEqual(validityType, CouponTemplateValidityTypeEnum.DATE.getType()) + || validStartTime != null; + } + + @AssertTrue(message = "生效结束时间不能为空") + public boolean isValidEndTimeValid() { + return ObjectUtil.notEqual(validityType, CouponTemplateValidityTypeEnum.DATE.getType()) + || validEndTime != null; + } + + @AssertTrue(message = "开始天数不能为空") + public boolean isFixedStartTermValid() { + return ObjectUtil.notEqual(validityType, CouponTemplateValidityTypeEnum.TERM.getType()) + || fixedStartTerm != null; + } + + @AssertTrue(message = "结束天数不能为空") + public boolean isFixedEndTermValid() { + return ObjectUtil.notEqual(validityType, CouponTemplateValidityTypeEnum.TERM.getType()) + || fixedEndTerm != null; + } + + @AssertTrue(message = "折扣百分比不能为空") + public boolean isDiscountPercentValid() { + return ObjectUtil.notEqual(discountType, PromotionDiscountTypeEnum.PERCENT.getType()) + || discountPercent != null; + } + + @AssertTrue(message = "优惠金额不能为空") + public boolean isDiscountPriceValid() { + return ObjectUtil.notEqual(discountType, PromotionDiscountTypeEnum.PRICE.getType()) + || discountPrice != null; + } + + @AssertTrue(message = "折扣上限不能为空") + public boolean isDiscountPriceLimit() { + return ObjectUtil.notEqual(discountType, PromotionDiscountTypeEnum.PERCENT.getType()) + || discountPriceLimit != null; + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplateCreateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplateCreateReqVO.java new file mode 100755 index 000000000..60f658b90 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplateCreateReqVO.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo; + +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@ApiModel("管理后台 - 优惠劵模板创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CouponTemplateCreateReqVO extends CouponTemplateBaseVO { + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplatePageReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplatePageReqVO.java new file mode 100755 index 000000000..2092112c3 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplatePageReqVO.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; +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 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; + +@ApiModel("管理后台 - 优惠劵模板分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CouponTemplatePageReqVO extends PageParam { + + @ApiModelProperty(value = "优惠劵名", example = "你好") + private String name; + + @ApiModelProperty(value = "状态", example = "1", notes = "参见 CommonStatusEnum 枚举类") + private Integer status; + + @ApiModelProperty(value = "优惠类型", example = "1", notes = "参见 PromotionDiscountTypeEnum 枚举") + private Integer discountType; + + @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/coupon/vo/CouponTemplateRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplateRespVO.java new file mode 100755 index 000000000..294055590 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplateRespVO.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.Date; + +@ApiModel("管理后台 - 优惠劵模板 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CouponTemplateRespVO extends CouponTemplateBaseVO { + + @ApiModelProperty(value = "模板编号", required = true, example = "1024") + private Long id; + + @ApiModelProperty(value = "状态", required = true, example = "1") + @InEnum(CommonStatusEnum.class) + private Integer status; + + @ApiModelProperty(value = "领取优惠券的数量", required = true, example = "1024") + private Integer takeNum; + + @ApiModelProperty(value = "使用优惠券的次数", required = true, example = "2048") + private Integer useCount; + + @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/coupon/vo/CouponTemplateUpdateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplateUpdateReqVO.java new file mode 100755 index 000000000..afa62ce6c --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/CouponTemplateUpdateReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.coupon.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; + +@ApiModel("管理后台 - 优惠劵模板更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CouponTemplateUpdateReqVO extends CouponTemplateBaseVO { + + @ApiModelProperty(value = "模板编号", required = true, example = "1024") + @NotNull(message = "模板编号不能为空") + private Long id; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponTemplateConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponTemplateConvert.java new file mode 100755 index 000000000..5fedd9678 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponTemplateConvert.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.promotion.convert.coupon; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.CouponTemplateCreateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.CouponTemplateRespVO; +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.CouponTemplateUpdateReqVO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 优惠劵模板 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface CouponTemplateConvert { + + CouponTemplateConvert INSTANCE = Mappers.getMapper(CouponTemplateConvert.class); + + CouponTemplateDO convert(CouponTemplateCreateReqVO bean); + + CouponTemplateDO convert(CouponTemplateUpdateReqVO bean); + + CouponTemplateRespVO convert(CouponTemplateDO bean); + + PageResult convertPage(PageResult page); + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponTemplateDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponTemplateDO.java index e8d9aec49..c583a30b1 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponTemplateDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponTemplateDO.java @@ -73,7 +73,7 @@ public class CouponTemplateDO extends BaseDO { * 是否设置满多少金额可用,单位:分 * * 0 - 不限制 - * 大于0 - 多少金额可用 + * 大于 0 - 多少金额可用 */ private Integer usePrice; /** @@ -96,19 +96,19 @@ public class CouponTemplateDO extends BaseDO { /** * 固定日期 - 生效开始时间 * - * 当 {@link #validityType} 为 {@link CouponTemplateValidityTypeEnum#FIXED_DATE} + * 当 {@link #validityType} 为 {@link CouponTemplateValidityTypeEnum#DATE} */ private Date validStartTime; /** * 固定日期 - 生效结束时间 * - * 当 {@link #validityType} 为 {@link CouponTemplateValidityTypeEnum#FIXED_DATE} + * 当 {@link #validityType} 为 {@link CouponTemplateValidityTypeEnum#DATE} */ private Date validEndTime; /** * 领取日期 - 结束天数 * - * 当 {@link #validityType} 为 {@link CouponTemplateValidityTypeEnum#FIXED_TERM_TODAY} + * 当 {@link #validityType} 为 {@link CouponTemplateValidityTypeEnum#TERM} */ private Integer fixedEndTerm; // ========== 使用规则 END ========== @@ -129,11 +129,11 @@ public class CouponTemplateDO extends BaseDO { /** * 优惠金额,单位:分 * - * 当 {@link #discountType} 为 {@link PromotionDiscountTypeEnum#PRICE} + * 当 {@link #discountType} 为 {@link PromotionDiscountTypeEnum#PRICE} 生效 */ private Integer discountPrice; /** - * 折扣上限,仅在 {@link #discountType} 等于 {@link PromotionDiscountTypeEnum#PRICE} 时生效 + * 折扣上限,仅在 {@link #discountType} 等于 {@link PromotionDiscountTypeEnum#PERCENT} 时生效 * * 例如,折扣上限为 20 元,当使用 8 折优惠券,订单金额为 1000 元时,最高只可折扣 20 元,而非 80 元。 */ diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java new file mode 100755 index 000000000..f99e658fb --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.promotion.dal.mysql.coupon; + +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.coupon.vo.CouponTemplatePageReqVO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 优惠劵模板 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface CouponTemplateMapper extends BaseMapperX { + + default PageResult selectPage(CouponTemplatePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(CouponTemplateDO::getName, reqVO.getName()) + .eqIfPresent(CouponTemplateDO::getStatus, reqVO.getStatus()) + .eqIfPresent(CouponTemplateDO::getDiscountType, reqVO.getDiscountType()) + .betweenIfPresent(CouponTemplateDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(CouponTemplateDO::getId)); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateService.java new file mode 100755 index 000000000..a1fc14d13 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateService.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.promotion.service.coupon; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.CouponTemplateCreateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.CouponTemplatePageReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.CouponTemplateUpdateReqVO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; + +import javax.validation.Valid; + +/** + * 优惠劵模板 Service 接口 + * + * @author 芋道源码 + */ +public interface CouponTemplateService { + + /** + * 创建优惠劵模板 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createCouponTemplate(@Valid CouponTemplateCreateReqVO createReqVO); + + /** + * 更新优惠劵模板 + * + * @param updateReqVO 更新信息 + */ + void updateCouponTemplate(@Valid CouponTemplateUpdateReqVO updateReqVO); + + /** + * 删除优惠劵模板 + * + * @param id 编号 + */ + void deleteCouponTemplate(Long id); + + /** + * 获得优惠劵模板 + * + * @param id 编号 + * @return 优惠劵模板 + */ + CouponTemplateDO getCouponTemplate(Long id); + + /** + * 获得优惠劵模板分页 + * + * @param pageReqVO 分页查询 + * @return 优惠劵模板分页 + */ + PageResult getCouponTemplatePage(CouponTemplatePageReqVO pageReqVO); + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java new file mode 100755 index 000000000..ef7c93db6 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java @@ -0,0 +1,79 @@ +package cn.iocoder.yudao.module.promotion.service.coupon; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.CouponTemplateCreateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.CouponTemplatePageReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.CouponTemplateUpdateReqVO; +import cn.iocoder.yudao.module.promotion.convert.coupon.CouponTemplateConvert; +import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; +import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponTemplateMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; + +/** + * 优惠劵模板 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class CouponTemplateServiceImpl implements CouponTemplateService { + + @Resource + private CouponTemplateMapper couponTemplateMapper; + + @Override + public Long createCouponTemplate(CouponTemplateCreateReqVO createReqVO) { + // 插入 + CouponTemplateDO couponTemplate = CouponTemplateConvert.INSTANCE.convert(createReqVO); + couponTemplateMapper.insert(couponTemplate); + // 返回 + return couponTemplate.getId(); + } + + @Override + public void updateCouponTemplate(CouponTemplateUpdateReqVO updateReqVO) { + // 校验存在 + CouponTemplateDO couponTemplate = validateCouponTemplateExists(updateReqVO.getId()); + // 校验发放数量不能过小 + if (updateReqVO.getTotalCount() < couponTemplate.getTakeCount()) { + throw exception(COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL, couponTemplate.getTakeCount()); + } + + // 更新 + CouponTemplateDO updateObj = CouponTemplateConvert.INSTANCE.convert(updateReqVO); + couponTemplateMapper.updateById(updateObj); + } + + @Override + public void deleteCouponTemplate(Long id) { + // 校验存在 + validateCouponTemplateExists(id); + // 删除 + couponTemplateMapper.deleteById(id); + } + + private CouponTemplateDO validateCouponTemplateExists(Long id) { + CouponTemplateDO couponTemplate = couponTemplateMapper.selectById(id); + if (couponTemplate == null) { + throw exception(COUPON_TEMPLATE_NOT_EXISTS); + } + return couponTemplate; + } + + @Override + public CouponTemplateDO getCouponTemplate(Long id) { + return couponTemplateMapper.selectById(id); + } + + @Override + public PageResult getCouponTemplatePage(CouponTemplatePageReqVO pageReqVO) { + return couponTemplateMapper.selectPage(pageReqVO); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImplTest.java b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImplTest.java new file mode 100755 index 000000000..27152005b --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImplTest.java @@ -0,0 +1,173 @@ +package cn.iocoder.yudao.module.promotion.service.coupon; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; + +import javax.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.*; +import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; +import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponTemplateMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import javax.annotation.Resource; +import org.springframework.context.annotation.Import; +import java.util.*; + +import static cn.hutool.core.util.RandomUtil.*; +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 cn.iocoder.yudao.framework.common.util.date.DateUtils.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** +* {@link CouponTemplateServiceImpl} 的单元测试类 +* +* @author 芋道源码 +*/ +@Import(CouponTemplateServiceImpl.class) +public class CouponTemplateServiceImplTest extends BaseDbUnitTest { + + @Resource + private CouponTemplateServiceImpl couponTemplateService; + + @Resource + private CouponTemplateMapper couponTemplateMapper; + + @Test + public void testCreateCouponTemplate_success() { + // 准备参数 + CouponTemplateCreateReqVO reqVO = randomPojo(CouponTemplateCreateReqVO.class); + + // 调用 + Long couponTemplateId = couponTemplateService.createCouponTemplate(reqVO); + // 断言 + assertNotNull(couponTemplateId); + // 校验记录的属性是否正确 + CouponTemplateDO couponTemplate = couponTemplateMapper.selectById(couponTemplateId); + assertPojoEquals(reqVO, couponTemplate); + } + + @Test + public void testUpdateCouponTemplate_success() { + // mock 数据 + CouponTemplateDO dbCouponTemplate = randomPojo(CouponTemplateDO.class); + couponTemplateMapper.insert(dbCouponTemplate);// @Sql: 先插入出一条存在的数据 + // 准备参数 + CouponTemplateUpdateReqVO reqVO = randomPojo(CouponTemplateUpdateReqVO.class, o -> { + o.setId(dbCouponTemplate.getId()); // 设置更新的 ID + }); + + // 调用 + couponTemplateService.updateCouponTemplate(reqVO); + // 校验是否更新正确 + CouponTemplateDO couponTemplate = couponTemplateMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, couponTemplate); + } + + @Test + public void testUpdateCouponTemplate_notExists() { + // 准备参数 + CouponTemplateUpdateReqVO reqVO = randomPojo(CouponTemplateUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> couponTemplateService.updateCouponTemplate(reqVO), COUPON_TEMPLATE_NOT_EXISTS); + } + + @Test + public void testDeleteCouponTemplate_success() { + // mock 数据 + CouponTemplateDO dbCouponTemplate = randomPojo(CouponTemplateDO.class); + couponTemplateMapper.insert(dbCouponTemplate);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbCouponTemplate.getId(); + + // 调用 + couponTemplateService.deleteCouponTemplate(id); + // 校验数据不存在了 + assertNull(couponTemplateMapper.selectById(id)); + } + + @Test + public void testDeleteCouponTemplate_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> couponTemplateService.deleteCouponTemplate(id), COUPON_TEMPLATE_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetCouponTemplatePage() { + // mock 数据 + CouponTemplateDO dbCouponTemplate = randomPojo(CouponTemplateDO.class, o -> { // 等会查询到 + o.setName(null); + o.setStatus(null); + o.setType(null); + o.setCreateTime(null); + }); + couponTemplateMapper.insert(dbCouponTemplate); + // 测试 name 不匹配 + couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setName(null))); + // 测试 status 不匹配 + couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setStatus(null))); + // 测试 type 不匹配 + couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setType(null))); + // 测试 createTime 不匹配 + couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setCreateTime(null))); + // 准备参数 + CouponTemplatePageReqVO reqVO = new CouponTemplatePageReqVO(); + reqVO.setName(null); + reqVO.setStatus(null); + reqVO.setType(null); + reqVO.setCreateTime((new Date[]{})); + + // 调用 + PageResult pageResult = couponTemplateService.getCouponTemplatePage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbCouponTemplate, pageResult.getList().get(0)); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetCouponTemplateList() { + // mock 数据 + CouponTemplateDO dbCouponTemplate = randomPojo(CouponTemplateDO.class, o -> { // 等会查询到 + o.setName(null); + o.setStatus(null); + o.setType(null); + o.setCreateTime(null); + }); + couponTemplateMapper.insert(dbCouponTemplate); + // 测试 name 不匹配 + couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setName(null))); + // 测试 status 不匹配 + couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setStatus(null))); + // 测试 type 不匹配 + couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setType(null))); + // 测试 createTime 不匹配 + couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setCreateTime(null))); + // 准备参数 + CouponTemplateExportReqVO reqVO = new CouponTemplateExportReqVO(); + reqVO.setName(null); + reqVO.setStatus(null); + reqVO.setType(null); + reqVO.setCreateTime((new Date[]{})); + + // 调用 + List list = couponTemplateService.getCouponTemplateList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbCouponTemplate, list.get(0)); + } + +}