适配 mall 模块的 openapi
This commit is contained in:
77
yudao-module-mall/yudao-module-promotion-biz/pom.xml
Normal file
77
yudao-module-mall/yudao-module-promotion-biz/pom.xml
Normal file
@@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-mall</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
<artifactId>yudao-module-promotion-biz</artifactId>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
|
||||
<description>
|
||||
market模块,主要实现营销相关功能
|
||||
例如:营销活动、banner广告、优惠券、优惠码等功能。
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-promotion-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-product-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-member-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 业务组件 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-weixin</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Web 相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- DB 相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test 测试相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 工具类相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-excel</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@@ -0,0 +1,27 @@
|
||||
package cn.iocoder.yudao.module.promotion.api.coupon;
|
||||
|
||||
|
||||
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO;
|
||||
import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 优惠劵 API 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
public class CouponApiImpl implements CouponApi {
|
||||
|
||||
@Resource
|
||||
private CouponService couponService;
|
||||
|
||||
@Override
|
||||
public void useCoupon(CouponUseReqDTO useReqDTO) {
|
||||
couponService.useCoupon(useReqDTO.getId(), useReqDTO.getUserId(),
|
||||
useReqDTO.getOrderId());
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1 @@
|
||||
package cn.iocoder.yudao.module.promotion.api.discount;
|
@@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.promotion.api.price;
|
||||
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.service.price.PriceService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 价格 API 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
public class PriceApiImpl implements PriceApi {
|
||||
|
||||
@Resource
|
||||
private PriceService priceService;
|
||||
|
||||
@Override
|
||||
public PriceCalculateRespDTO calculatePrice(PriceCalculateReqDTO calculateReqDTO) {
|
||||
return priceService.calculatePrice(calculateReqDTO);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.banner;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.banner.BannerConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.banner.BannerDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.banner.BannerService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
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;
|
||||
|
||||
@Tag(name = "管理后台 - Banner 管理")
|
||||
@RestController
|
||||
@RequestMapping("/market/banner")
|
||||
@Validated
|
||||
public class BannerController {
|
||||
|
||||
@Resource
|
||||
private BannerService bannerService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建 Banner")
|
||||
@PreAuthorize("@ss.hasPermission('market:banner:create')")
|
||||
public CommonResult<Long> createBanner(@Valid @RequestBody BannerCreateReqVO createReqVO) {
|
||||
return success(bannerService.createBanner(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新 Banner")
|
||||
@PreAuthorize("@ss.hasPermission('market:banner:update')")
|
||||
public CommonResult<Boolean> updateBanner(@Valid @RequestBody BannerUpdateReqVO updateReqVO) {
|
||||
bannerService.updateBanner(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除 Banner")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('market:banner:delete')")
|
||||
public CommonResult<Boolean> deleteBanner(@RequestParam("id") Long id) {
|
||||
bannerService.deleteBanner(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得 Banner")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('market:banner:query')")
|
||||
public CommonResult<BannerRespVO> getBanner(@RequestParam("id") Long id) {
|
||||
BannerDO banner = bannerService.getBanner(id);
|
||||
return success(BannerConvert.INSTANCE.convert(banner));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得 Banner 分页")
|
||||
@PreAuthorize("@ss.hasPermission('market:banner:query')")
|
||||
public CommonResult<PageResult<BannerRespVO>> getBannerPage(@Valid BannerPageReqVO pageVO) {
|
||||
PageResult<BannerDO> pageResult = bannerService.getBannerPage(pageVO);
|
||||
return success(BannerConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.banner.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* Banner Base VO,提供给添加、修改、详细的子 VO 使用
|
||||
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
||||
* @author xia
|
||||
*/
|
||||
@Data
|
||||
public class BannerBaseVO {
|
||||
|
||||
@Schema(description = "标题", required = true)
|
||||
@NotNull(message = "标题不能为空")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "跳转链接", required = true)
|
||||
@NotNull(message = "跳转链接不能为空")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "图片地址", required = true)
|
||||
@NotNull(message = "图片地址不能为空")
|
||||
private String picUrl;
|
||||
|
||||
@Schema(description = "排序", required = true)
|
||||
@NotNull(message = "排序不能为空")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "状态", required = true)
|
||||
@NotNull(message = "状态不能为空")
|
||||
@InEnum(CommonStatusEnum.class)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String memo;
|
||||
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.banner.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* @author xia
|
||||
*/
|
||||
@Schema(description = "管理后台 - Banner 创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class BannerCreateReqVO extends BannerBaseVO {
|
||||
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.banner.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author xia
|
||||
*/
|
||||
@Schema(description = "管理后台 - Banner 分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class BannerPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "标题")
|
||||
private String title;
|
||||
|
||||
|
||||
@Schema(description = "状态")
|
||||
@InEnum(CommonStatusEnum.class)
|
||||
private Integer status;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.banner.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author xia
|
||||
*/
|
||||
@Schema(description = "管理后台 - Banner Response VO")
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class BannerRespVO extends BannerBaseVO {
|
||||
|
||||
@Schema(description = "banner编号", required = true)
|
||||
@NotNull(message = "banner编号不能为空")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "创建时间", required = true)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.banner.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* @author xia
|
||||
*/
|
||||
@Schema(description = "管理后台 - Banner更新 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class BannerUpdateReqVO extends BannerBaseVO {
|
||||
|
||||
@Schema(description = "banner 编号", required = true)
|
||||
@NotNull(message = "banner 编号不能为空")
|
||||
private Long id;
|
||||
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.coupon;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
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.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;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
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.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
|
||||
@Tag(name = "管理后台 - 优惠劵")
|
||||
@RestController
|
||||
@RequestMapping("/promotion/coupon")
|
||||
@Validated
|
||||
public class CouponController {
|
||||
|
||||
@Resource
|
||||
private CouponService couponService;
|
||||
@Resource
|
||||
private MemberUserApi memberUserApi;
|
||||
|
||||
// @GetMapping("/get")
|
||||
// @Operation(summary = "获得优惠劵")
|
||||
// @Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
// @PreAuthorize("@ss.hasPermission('promotion:coupon:query')")
|
||||
// public CommonResult<CouponRespVO> getCoupon(@RequestParam("id") Long id) {
|
||||
// CouponDO coupon = couponService.getCoupon(id);
|
||||
// return success(CouponConvert.INSTANCE.convert(coupon));
|
||||
// }
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "回收优惠劵")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('promotion:coupon:delete')")
|
||||
public CommonResult<Boolean> deleteCoupon(@RequestParam("id") Long id) {
|
||||
couponService.deleteCoupon(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得优惠劵分页")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:coupon:query')")
|
||||
public CommonResult<PageResult<CouponPageItemRespVO>> getCouponPage(@Valid CouponPageReqVO pageVO) {
|
||||
PageResult<CouponDO> pageResult = couponService.getCouponPage(pageVO);
|
||||
PageResult<CouponPageItemRespVO> pageResulVO = CouponConvert.INSTANCE.convertPage(pageResult);
|
||||
if (CollUtil.isEmpty(pageResulVO.getList())) {
|
||||
return success(pageResulVO);
|
||||
}
|
||||
// 读取用户信息,进行拼接
|
||||
Set<Long> userIds = convertSet(pageResult.getList(), CouponDO::getUserId);
|
||||
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
|
||||
pageResulVO.getList().forEach(itemRespVO -> MapUtils.findAndThen(userMap, itemRespVO.getUserId(),
|
||||
userRespDTO -> itemRespVO.setNickname(userRespDTO.getNickname())));
|
||||
return success(pageResulVO);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
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.template.*;
|
||||
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.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
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;
|
||||
|
||||
@Tag(name = "管理后台 - 优惠劵模板")
|
||||
@RestController
|
||||
@RequestMapping("/promotion/coupon-template")
|
||||
@Validated
|
||||
public class CouponTemplateController {
|
||||
|
||||
@Resource
|
||||
private CouponTemplateService couponTemplateService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建优惠劵模板")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:coupon-template:create')")
|
||||
public CommonResult<Long> createCouponTemplate(@Valid @RequestBody CouponTemplateCreateReqVO createReqVO) {
|
||||
return success(couponTemplateService.createCouponTemplate(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新优惠劵模板")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:coupon-template:update')")
|
||||
public CommonResult<Boolean> updateCouponTemplate(@Valid @RequestBody CouponTemplateUpdateReqVO updateReqVO) {
|
||||
couponTemplateService.updateCouponTemplate(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/update-status")
|
||||
@Operation(summary = "更新优惠劵模板状态")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:coupon-template:update')")
|
||||
public CommonResult<Boolean> updateCouponTemplateStatus(@Valid @RequestBody CouponTemplateUpdateStatusReqVO reqVO) {
|
||||
couponTemplateService.updateCouponTemplateStatus(reqVO.getId(), reqVO.getStatus());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除优惠劵模板")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('promotion:coupon-template:delete')")
|
||||
public CommonResult<Boolean> deleteCouponTemplate(@RequestParam("id") Long id) {
|
||||
couponTemplateService.deleteCouponTemplate(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得优惠劵模板")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:coupon-template:query')")
|
||||
public CommonResult<CouponTemplateRespVO> getCouponTemplate(@RequestParam("id") Long id) {
|
||||
CouponTemplateDO couponTemplate = couponTemplateService.getCouponTemplate(id);
|
||||
return success(CouponTemplateConvert.INSTANCE.convert(couponTemplate));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得优惠劵模板分页")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:coupon-template:query')")
|
||||
public CommonResult<PageResult<CouponTemplateRespVO>> getCouponTemplatePage(@Valid CouponTemplatePageReqVO pageVO) {
|
||||
PageResult<CouponTemplateDO> pageResult = couponTemplateService.getCouponTemplatePage(pageVO);
|
||||
return success(CouponTemplateConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,103 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon;
|
||||
|
||||
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 com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
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 CouponBaseVO {
|
||||
|
||||
// ========== 基本信息 BEGIN ==========
|
||||
@Schema(description = "优惠劵模板编号", required = true, example = "1024")
|
||||
@NotNull(message = "优惠劵模板编号不能为空")
|
||||
private Integer templateId;
|
||||
|
||||
@Schema(description = "优惠劵名", required = true, example = "春节送送送")
|
||||
@NotNull(message = "优惠劵名不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "优惠码状态", required = true, example = "1")
|
||||
private Integer status;
|
||||
|
||||
// ========== 基本信息 END ==========
|
||||
|
||||
// ========== 领取情况 BEGIN ==========
|
||||
@Schema(description = "用户编号", required = true, example = "1")
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "领取方式", required = true, example = "1")
|
||||
@NotNull(message = "领取方式不能为空")
|
||||
private Integer takeType;
|
||||
// ========== 领取情况 END ==========
|
||||
|
||||
// ========== 使用规则 BEGIN ==========
|
||||
@Schema(description = "是否设置满多少金额可用", required = true, example = "100") // 单位:分;0 - 不限制
|
||||
@NotNull(message = "是否设置满多少金额可用不能为空")
|
||||
private Integer usePrice;
|
||||
|
||||
@Schema(description = "固定日期 - 生效开始时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
|
||||
private LocalDateTime validStartTime;
|
||||
|
||||
@Schema(description = "固定日期 - 生效结束时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
|
||||
private LocalDateTime validEndTime;
|
||||
|
||||
@Schema(description = "商品范围", required = true, example = "1")
|
||||
@NotNull(message = "商品范围不能为空")
|
||||
@InEnum(PromotionProductScopeEnum.class)
|
||||
private Integer productScope;
|
||||
|
||||
@Schema(description = "商品 SPU 编号的数组", example = "1,3")
|
||||
private List<Long> productSpuIds;
|
||||
// ========== 使用规则 END ==========
|
||||
|
||||
// ========== 使用效果 BEGIN ==========
|
||||
@Schema(description = "优惠类型", required = true, example = "1")
|
||||
@NotNull(message = "优惠类型不能为空")
|
||||
@InEnum(PromotionDiscountTypeEnum.class)
|
||||
private Integer discountType;
|
||||
|
||||
@Schema(description = "折扣百分比", example = "80") // 例如说,80% 为 80
|
||||
private Integer discountPercent;
|
||||
|
||||
@Schema(description = "优惠金额", example = "10")
|
||||
@Min(value = 0, message = "优惠金额需要大于等于 0")
|
||||
private Integer discountPrice;
|
||||
|
||||
@Schema(description = "折扣上限", example = "100") // 单位:分,仅在 discountType 为 PERCENT 使用
|
||||
private Integer discountLimitPrice;
|
||||
// ========== 使用效果 END ==========
|
||||
|
||||
// ========== 使用情况 BEGIN ==========
|
||||
|
||||
@Schema(description = "使用订单号", example = "4096")
|
||||
private Long useOrderId;
|
||||
|
||||
@Schema(description = "使用时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
|
||||
private LocalDateTime useTime;
|
||||
|
||||
// ========== 使用情况 END ==========
|
||||
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Schema(description = "管理后台 - 优惠劵分页的每一项 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class CouponPageItemRespVO extends CouponRespVO {
|
||||
|
||||
@Schema(description = "用户昵称", example = "老芋艿")
|
||||
private String nickname;
|
||||
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
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;
|
||||
|
||||
@Schema(description = "管理后台 - 优惠劵分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class CouponPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "优惠劵模板编号", example = "2048")
|
||||
private Long templateId;
|
||||
|
||||
@Schema(description = "优惠码状态", example = "1")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
@Schema(description = "用户昵称", example = "芋艿")
|
||||
private String nickname;
|
||||
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 优惠劵 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class CouponRespVO extends CouponBaseVO {
|
||||
|
||||
@Schema(description = "优惠劵编号", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "创建时间", required = true)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@@ -0,0 +1,154 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template;
|
||||
|
||||
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 com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
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.time.LocalDateTime;
|
||||
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;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
|
||||
|
||||
/**
|
||||
* 优惠劵模板 Base VO,提供给添加、修改、详细的子 VO 使用
|
||||
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
||||
*/
|
||||
@Data
|
||||
public class CouponTemplateBaseVO {
|
||||
|
||||
@Schema(description = "优惠劵名", required = true, example = "春节送送送")
|
||||
@NotNull(message = "优惠劵名不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "发行总量", required = true, example = "1024") // -1 - 则表示不限制发放数量
|
||||
@NotNull(message = "发行总量不能为空")
|
||||
private Integer totalCount;
|
||||
|
||||
@Schema(description = "每人限领个数", required = true, example = "66") // -1 - 则表示不限制
|
||||
@NotNull(message = "每人限领个数不能为空")
|
||||
private Integer takeLimitCount;
|
||||
|
||||
@Schema(description = "领取方式", required = true, example = "1")
|
||||
@NotNull(message = "领取方式不能为空")
|
||||
private Integer takeType;
|
||||
|
||||
@Schema(description = "是否设置满多少金额可用", required = true, example = "100") // 单位:分;0 - 不限制
|
||||
@NotNull(message = "是否设置满多少金额可用不能为空")
|
||||
private Integer usePrice;
|
||||
|
||||
@Schema(description = "商品范围", required = true, example = "1")
|
||||
@NotNull(message = "商品范围不能为空")
|
||||
@InEnum(PromotionProductScopeEnum.class)
|
||||
private Integer productScope;
|
||||
|
||||
@Schema(description = "商品 SPU 编号的数组", example = "1,3")
|
||||
private List<Long> productSpuIds;
|
||||
|
||||
@Schema(description = "生效日期类型", required = true, example = "1")
|
||||
@NotNull(message = "生效日期类型不能为空")
|
||||
@InEnum(CouponTemplateValidityTypeEnum.class)
|
||||
private Integer validityType;
|
||||
|
||||
@Schema(description = "固定日期 - 生效开始时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
|
||||
private LocalDateTime validStartTime;
|
||||
|
||||
@Schema(description = "固定日期 - 生效结束时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
|
||||
private LocalDateTime validEndTime;
|
||||
|
||||
@Schema(description = "领取日期 - 开始天数")
|
||||
@Min(value = 0L, message = "开始天数必须大于 0")
|
||||
private Integer fixedStartTerm;
|
||||
|
||||
@Schema(description = "领取日期 - 结束天数")
|
||||
@Min(value = 1L, message = "开始天数必须大于 1")
|
||||
private Integer fixedEndTerm;
|
||||
|
||||
@Schema(description = "优惠类型", required = true, example = "1")
|
||||
@NotNull(message = "优惠类型不能为空")
|
||||
@InEnum(PromotionDiscountTypeEnum.class)
|
||||
private Integer discountType;
|
||||
|
||||
@Schema(description = "折扣百分比", example = "80") // 例如说,80% 为 80
|
||||
private Integer discountPercent;
|
||||
|
||||
@Schema(description = "优惠金额", example = "10")
|
||||
@Min(value = 0, message = "优惠金额需要大于等于 0")
|
||||
private Integer discountPrice;
|
||||
|
||||
@Schema(description = "折扣上限", example = "100") // 单位:分,仅在 discountType 为 PERCENT 使用
|
||||
private Integer discountLimitPrice;
|
||||
|
||||
@AssertTrue(message = "商品 SPU 编号的数组不能为空")
|
||||
@JsonIgnore
|
||||
public boolean isProductSpuIdsValid() {
|
||||
return Objects.equals(productScope, PromotionProductScopeEnum.ALL.getScope()) // 全部范围时,可以为空
|
||||
|| CollUtil.isNotEmpty(productSpuIds);
|
||||
}
|
||||
|
||||
@AssertTrue(message = "生效开始时间不能为空")
|
||||
@JsonIgnore
|
||||
public boolean isValidStartTimeValid() {
|
||||
return ObjectUtil.notEqual(validityType, CouponTemplateValidityTypeEnum.DATE.getType())
|
||||
|| validStartTime != null;
|
||||
}
|
||||
|
||||
@AssertTrue(message = "生效结束时间不能为空")
|
||||
@JsonIgnore
|
||||
public boolean isValidEndTimeValid() {
|
||||
return ObjectUtil.notEqual(validityType, CouponTemplateValidityTypeEnum.DATE.getType())
|
||||
|| validEndTime != null;
|
||||
}
|
||||
|
||||
@AssertTrue(message = "开始天数不能为空")
|
||||
@JsonIgnore
|
||||
public boolean isFixedStartTermValid() {
|
||||
return ObjectUtil.notEqual(validityType, CouponTemplateValidityTypeEnum.TERM.getType())
|
||||
|| fixedStartTerm != null;
|
||||
}
|
||||
|
||||
@AssertTrue(message = "结束天数不能为空")
|
||||
@JsonIgnore
|
||||
public boolean isFixedEndTermValid() {
|
||||
return ObjectUtil.notEqual(validityType, CouponTemplateValidityTypeEnum.TERM.getType())
|
||||
|| fixedEndTerm != null;
|
||||
}
|
||||
|
||||
@AssertTrue(message = "折扣百分比需要大于等于 1,小于等于 99")
|
||||
@JsonIgnore
|
||||
public boolean isDiscountPercentValid() {
|
||||
return ObjectUtil.notEqual(discountType, PromotionDiscountTypeEnum.PERCENT.getType())
|
||||
|| (discountPercent != null && discountPercent >= 1 && discountPercent<= 99);
|
||||
}
|
||||
|
||||
@AssertTrue(message = "优惠金额不能为空")
|
||||
@JsonIgnore
|
||||
public boolean isDiscountPriceValid() {
|
||||
return ObjectUtil.notEqual(discountType, PromotionDiscountTypeEnum.PRICE.getType())
|
||||
|| discountPrice != null;
|
||||
}
|
||||
|
||||
@AssertTrue(message = "折扣上限不能为空")
|
||||
@JsonIgnore
|
||||
public boolean isDiscountLimitPriceValid() {
|
||||
return ObjectUtil.notEqual(discountType, PromotionDiscountTypeEnum.PERCENT.getType())
|
||||
|| discountLimitPrice != null;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Schema(description = "管理后台 - 优惠劵模板创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class CouponTemplateCreateReqVO extends CouponTemplateBaseVO {
|
||||
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
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;
|
||||
|
||||
@Schema(description = "管理后台 - 优惠劵模板分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class CouponTemplatePageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "优惠劵名", example = "你好")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "状态", example = "1")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "优惠类型", example = "1")
|
||||
private Integer discountType;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 优惠劵模板 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class CouponTemplateRespVO extends CouponTemplateBaseVO {
|
||||
|
||||
@Schema(description = "模板编号", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "状态", required = true, example = "1")
|
||||
@InEnum(CommonStatusEnum.class)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "领取优惠券的数量", required = true, example = "1024")
|
||||
private Integer takeCount;
|
||||
|
||||
@Schema(description = "使用优惠券的次数", required = true, example = "2048")
|
||||
private Integer useCount;
|
||||
|
||||
@Schema(description = "创建时间", required = true)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - 优惠劵模板更新 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class CouponTemplateUpdateReqVO extends CouponTemplateBaseVO {
|
||||
|
||||
@Schema(description = "模板编号", required = true, example = "1024")
|
||||
@NotNull(message = "模板编号不能为空")
|
||||
private Long id;
|
||||
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - 优惠劵模板更新状态 Request VO")
|
||||
@Data
|
||||
public class CouponTemplateUpdateStatusReqVO {
|
||||
|
||||
@Schema(description = "优惠劵模板编号", required = true, example = "1024")
|
||||
@NotNull(message = "优惠劵模板编号不能为空")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "状态", required = true, example = "1")
|
||||
@NotNull(message = "状态不能为空")
|
||||
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}")
|
||||
private Integer status;
|
||||
|
||||
}
|
@@ -0,0 +1,87 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.discount;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
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;
|
||||
|
||||
@Tag(name = "管理后台 - 限时折扣活动")
|
||||
@RestController
|
||||
@RequestMapping("/promotion/discount-activity")
|
||||
@Validated
|
||||
public class DiscountActivityController {
|
||||
|
||||
@Resource
|
||||
private DiscountActivityService discountActivityService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建限时折扣活动")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:discount-activity:create')")
|
||||
public CommonResult<Long> createDiscountActivity(@Valid @RequestBody DiscountActivityCreateReqVO createReqVO) {
|
||||
return success(discountActivityService.createDiscountActivity(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新限时折扣活动")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:discount-activity:update')")
|
||||
public CommonResult<Boolean> updateDiscountActivity(@Valid @RequestBody DiscountActivityUpdateReqVO updateReqVO) {
|
||||
discountActivityService.updateDiscountActivity(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/close")
|
||||
@Operation(summary = "关闭限时折扣活动")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('promotion:discount-activity:close')")
|
||||
public CommonResult<Boolean> closeRewardActivity(@RequestParam("id") Long id) {
|
||||
discountActivityService.closeRewardActivity(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除限时折扣活动")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('promotion:discount-activity:delete')")
|
||||
public CommonResult<Boolean> deleteDiscountActivity(@RequestParam("id") Long id) {
|
||||
discountActivityService.deleteDiscountActivity(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得限时折扣活动")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:discount-activity:query')")
|
||||
public CommonResult<DiscountActivityDetailRespVO> getDiscountActivity(@RequestParam("id") Long id) {
|
||||
DiscountActivityDO discountActivity = discountActivityService.getDiscountActivity(id);
|
||||
if (discountActivity == null) {
|
||||
return success(null);
|
||||
}
|
||||
// 拼接结果
|
||||
List<DiscountProductDO> discountProducts = discountActivityService.getDiscountProductsByActivityId(id);
|
||||
return success(DiscountActivityConvert.INSTANCE.convert(discountActivity, discountProducts));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得限时折扣活动分页")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:discount-activity:query')")
|
||||
public CommonResult<PageResult<DiscountActivityRespVO>> getDiscountActivityPage(@Valid DiscountActivityPageReqVO pageVO) {
|
||||
PageResult<DiscountActivityDO> pageResult = discountActivityService.getDiscountActivityPage(pageVO);
|
||||
return success(DiscountActivityConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.discount.vo;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
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.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
/**
|
||||
* 限时折扣活动 Base VO,提供给添加、修改、详细的子 VO 使用
|
||||
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
||||
*/
|
||||
@Data
|
||||
public class DiscountActivityBaseVO {
|
||||
|
||||
@Schema(description = "活动标题", required = true, example = "一个标题")
|
||||
@NotNull(message = "活动标题不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "开始时间", required = true)
|
||||
@NotNull(message = "开始时间不能为空")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime startTime;
|
||||
|
||||
@Schema(description = "结束时间", required = true)
|
||||
@NotNull(message = "结束时间不能为空")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@Schema(description = "备注", example = "我是备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "商品")
|
||||
@Data
|
||||
public static class Product {
|
||||
|
||||
@Schema(description = "商品 SPU 编号", required = true, example = "1")
|
||||
@NotNull(message = "商品 SPU 编号不能为空")
|
||||
private Long spuId;
|
||||
|
||||
@Schema(description = "商品 SKU 编号", required = true, example = "1")
|
||||
@NotNull(message = "商品 SKU 编号不能为空")
|
||||
private Long skuId;
|
||||
|
||||
@Schema(description = "优惠类型", required = true, example = "1")
|
||||
@NotNull(message = "优惠类型不能为空")
|
||||
@InEnum(PromotionDiscountTypeEnum.class)
|
||||
private Integer discountType;
|
||||
|
||||
@Schema(description = "折扣百分比", example = "80") // 例如说,80% 为 80
|
||||
private Integer discountPercent;
|
||||
|
||||
@Schema(description = "优惠金额", example = "10")
|
||||
@Min(value = 0, message = "优惠金额需要大于等于 0")
|
||||
private Integer discountPrice;
|
||||
|
||||
@AssertTrue(message = "折扣百分比需要大于等于 1,小于等于 99")
|
||||
@JsonIgnore
|
||||
public boolean isDiscountPercentValid() {
|
||||
return ObjectUtil.notEqual(discountType, PromotionDiscountTypeEnum.PERCENT.getType())
|
||||
|| (discountPercent != null && discountPercent >= 1 && discountPercent<= 99);
|
||||
}
|
||||
|
||||
@AssertTrue(message = "优惠金额不能为空")
|
||||
@JsonIgnore
|
||||
public boolean isDiscountPriceValid() {
|
||||
return ObjectUtil.notEqual(discountType, PromotionDiscountTypeEnum.PRICE.getType())
|
||||
|| discountPrice != null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.discount.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 限时折扣活动创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class DiscountActivityCreateReqVO extends DiscountActivityBaseVO {
|
||||
|
||||
/**
|
||||
* 商品列表
|
||||
*/
|
||||
@NotEmpty(message = "商品列表不能为空")
|
||||
@Valid
|
||||
private List<Product> products;
|
||||
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.discount.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 限时折扣活动的详细 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class DiscountActivityDetailRespVO extends DiscountActivityRespVO {
|
||||
|
||||
/**
|
||||
* 商品列表
|
||||
*/
|
||||
private List<Product> products;
|
||||
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.discount.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
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;
|
||||
|
||||
@Schema(description = "管理后台 - 限时折扣活动分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class DiscountActivityPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "活动标题", example = "一个标题")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "活动状态", example = "1")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.discount.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 限时折扣活动 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class DiscountActivityRespVO extends DiscountActivityBaseVO {
|
||||
|
||||
@Schema(description = "活动编号", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "活动状态", required = true, example = "1")
|
||||
@NotNull(message = "活动状态不能为空")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "创建时间", required = true)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.discount.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
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;
|
||||
|
||||
@Schema(description = "管理后台 - 限时折扣活动更新 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class DiscountActivityUpdateReqVO extends DiscountActivityBaseVO {
|
||||
|
||||
@Schema(description = "活动编号", required = true, example = "1024")
|
||||
@NotNull(message = "活动编号不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 商品列表
|
||||
*/
|
||||
@NotEmpty(message = "商品列表不能为空")
|
||||
@Valid
|
||||
private List<DiscountActivityCreateReqVO.Product> products;
|
||||
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.reward;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.reward.RewardActivityConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
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;
|
||||
|
||||
@Tag(name = "管理后台 - 满减送活动")
|
||||
@RestController
|
||||
@RequestMapping("/promotion/reward-activity")
|
||||
@Validated
|
||||
public class RewardActivityController {
|
||||
|
||||
@Resource
|
||||
private RewardActivityService rewardActivityService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建满减送活动")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:reward-activity:create')")
|
||||
public CommonResult<Long> createRewardActivity(@Valid @RequestBody RewardActivityCreateReqVO createReqVO) {
|
||||
return success(rewardActivityService.createRewardActivity(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新满减送活动")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:reward-activity:update')")
|
||||
public CommonResult<Boolean> updateRewardActivity(@Valid @RequestBody RewardActivityUpdateReqVO updateReqVO) {
|
||||
rewardActivityService.updateRewardActivity(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/close")
|
||||
@Operation(summary = "关闭满减送活动")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('promotion:reward-activity:close')")
|
||||
public CommonResult<Boolean> closeRewardActivity(@RequestParam("id") Long id) {
|
||||
rewardActivityService.closeRewardActivity(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除满减送活动")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('promotion:reward-activity:delete')")
|
||||
public CommonResult<Boolean> deleteRewardActivity(@RequestParam("id") Long id) {
|
||||
rewardActivityService.deleteRewardActivity(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得满减送活动")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:reward-activity:query')")
|
||||
public CommonResult<RewardActivityRespVO> getRewardActivity(@RequestParam("id") Long id) {
|
||||
RewardActivityDO rewardActivity = rewardActivityService.getRewardActivity(id);
|
||||
return success(RewardActivityConvert.INSTANCE.convert(rewardActivity));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得满减送活动分页")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:reward-activity:query')")
|
||||
public CommonResult<PageResult<RewardActivityRespVO>> getRewardActivityPage(@Valid RewardActivityPageReqVO pageVO) {
|
||||
PageResult<RewardActivityDO> pageResult = rewardActivityService.getRewardActivityPage(pageVO);
|
||||
return success(RewardActivityConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,98 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.reward.vo;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.AssertTrue;
|
||||
import javax.validation.constraints.Future;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
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 RewardActivityBaseVO {
|
||||
|
||||
@Schema(description = "活动标题", required = true, example = "满啦满啦")
|
||||
@NotNull(message = "活动标题不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "开始时间", required = true)
|
||||
@NotNull(message = "开始时间不能为空")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime startTime;
|
||||
|
||||
@Schema(description = "结束时间", required = true)
|
||||
@NotNull(message = "结束时间不能为空")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@Future(message = "结束时间必须大于当前时间")
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@Schema(description = "备注", example = "biubiubiu")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "条件类型", required = true, example = "1")
|
||||
@NotNull(message = "条件类型不能为空")
|
||||
@InEnum(value = PromotionConditionTypeEnum.class, message = "条件类型必须是 {value}")
|
||||
private Integer conditionType;
|
||||
|
||||
@Schema(description = "商品范围", required = true, example = "1")
|
||||
@NotNull(message = "商品范围不能为空")
|
||||
@InEnum(value = PromotionConditionTypeEnum.class, message = "商品范围必须是 {value}")
|
||||
private Integer productScope;
|
||||
|
||||
@Schema(description = "商品 SPU 编号的数组", example = "1,2,3")
|
||||
private List<Long> productSpuIds;
|
||||
|
||||
/**
|
||||
* 优惠规则的数组
|
||||
*/
|
||||
@Valid // 校验下子对象
|
||||
private List<Rule> rules;
|
||||
|
||||
@Schema(description = "优惠规则")
|
||||
@Data
|
||||
public static class Rule {
|
||||
|
||||
@Schema(description = "优惠门槛", required = true, example = "100") // 1. 满 N 元,单位:分; 2. 满 N 件
|
||||
@Min(value = 1L, message = "优惠门槛必须大于等于 1")
|
||||
private Integer limit;
|
||||
|
||||
@Schema(description = "优惠价格", required = true, example = "100")
|
||||
@Min(value = 1L, message = "优惠价格必须大于等于 1")
|
||||
private Integer discountPrice;
|
||||
|
||||
@Schema(description = "是否包邮", required = true, example = "true")
|
||||
private Boolean freeDelivery;
|
||||
|
||||
@Schema(description = "赠送的积分", required = true, example = "100")
|
||||
@Min(value = 1L, message = "赠送的积分必须大于等于 1")
|
||||
private Integer point;
|
||||
|
||||
@Schema(description = "赠送的优惠劵编号的数组", example = "1,2,3")
|
||||
private List<Long> couponIds;
|
||||
|
||||
@Schema(description = "赠送的优惠卷数量的数组", example = "1,2,3")
|
||||
private List<Integer> couponCounts;
|
||||
|
||||
@AssertTrue(message = "优惠劵和数量必须一一对应")
|
||||
@JsonIgnore
|
||||
public boolean isCouponCountsValid() {
|
||||
return CollUtil.size(couponCounts) == CollUtil.size(couponCounts);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.reward.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Schema(description = "管理后台 - 满减送活动创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class RewardActivityCreateReqVO extends RewardActivityBaseVO {
|
||||
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.reward.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Schema(description = "管理后台 - 满减送活动分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class RewardActivityPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "活动标题", example = "满啦满啦")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "活动状态", example = "1")
|
||||
private Integer status;
|
||||
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.reward.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 满减送活动 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class RewardActivityRespVO extends RewardActivityBaseVO {
|
||||
|
||||
@Schema(description = "活动编号", required = true, example = "1024")
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "活动状态", required = true, example = "1")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "创建时间", required = true)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.reward.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - 满减送活动更新 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class RewardActivityUpdateReqVO extends RewardActivityBaseVO {
|
||||
|
||||
@Schema(description = "活动编号", required = true, example = "1024")
|
||||
@NotNull(message = "活动编号不能为空")
|
||||
private Long id;
|
||||
|
||||
}
|
@@ -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.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
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;
|
||||
|
||||
@Tag(name = "管理后台 - 秒杀活动")
|
||||
@RestController
|
||||
@RequestMapping("/promotion/seckill-activity")
|
||||
@Validated
|
||||
public class SeckillActivityController {
|
||||
|
||||
@Resource
|
||||
private SeckillActivityService seckillActivityService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建秒杀活动")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:create')")
|
||||
public CommonResult<Long> createSeckillActivity(@Valid @RequestBody SeckillActivityCreateReqVO createReqVO) {
|
||||
return success(seckillActivityService.createSeckillActivity(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新秒杀活动")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:update')")
|
||||
public CommonResult<Boolean> updateSeckillActivity(@Valid @RequestBody SeckillActivityUpdateReqVO updateReqVO) {
|
||||
seckillActivityService.updateSeckillActivity(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/close")
|
||||
@Operation(summary = "关闭秒杀活动")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:close')")
|
||||
public CommonResult<Boolean> closeSeckillActivity(@RequestParam("id") Long id) {
|
||||
seckillActivityService.closeSeckillActivity(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除秒杀活动")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:delete')")
|
||||
public CommonResult<Boolean> deleteSeckillActivity(@RequestParam("id") Long id) {
|
||||
seckillActivityService.deleteSeckillActivity(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得秒杀活动")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@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")
|
||||
@Operation(summary = "获得秒杀活动列表")
|
||||
@Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
|
||||
@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")
|
||||
@Operation(summary = "获得秒杀活动分页")
|
||||
@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));
|
||||
}
|
||||
|
||||
}
|
@@ -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.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
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;
|
||||
|
||||
@Tag(name = "管理后台 - 秒杀时段")
|
||||
@RestController
|
||||
@RequestMapping("/promotion/seckill-time")
|
||||
@Validated
|
||||
public class SeckillTimeController {
|
||||
|
||||
@Resource
|
||||
private SeckillTimeService seckillTimeService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建秒杀时段")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:seckill-time:create')")
|
||||
public CommonResult<Long> createSeckillTime(@Valid @RequestBody SeckillTimeCreateReqVO createReqVO) {
|
||||
return success(seckillTimeService.createSeckillTime(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新秒杀时段")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:seckill-time:update')")
|
||||
public CommonResult<Boolean> updateSeckillTime(@Valid @RequestBody SeckillTimeUpdateReqVO updateReqVO) {
|
||||
seckillTimeService.updateSeckillTime(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除秒杀时段")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('promotion:seckill-time:delete')")
|
||||
public CommonResult<Boolean> deleteSeckillTime(@RequestParam("id") Long id) {
|
||||
seckillTimeService.deleteSeckillTime(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得秒杀时段")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@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")
|
||||
@Operation(summary = "获得所有秒杀时段列表")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:seckill-time:query')")
|
||||
public CommonResult<List<SeckillTimeRespVO>> getSeckillTimeList() {
|
||||
List<SeckillTimeDO> list = seckillTimeService.getSeckillTimeList();
|
||||
return success(SeckillTimeConvert.INSTANCE.convertList(list));
|
||||
}
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
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 {
|
||||
|
||||
@Schema(description = "秒杀活动名称", required = true, example = "晚九点限时秒杀")
|
||||
@NotNull(message = "秒杀活动名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "活动开始时间", 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;
|
||||
|
||||
@Schema(description = "活动结束时间", 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;
|
||||
|
||||
|
||||
@Schema(description = "商品")
|
||||
@Data
|
||||
public static class Product {
|
||||
|
||||
@Schema(description = "商品 SPU 编号", required = true, example = "1")
|
||||
@NotNull(message = "商品 SPU 编号不能为空")
|
||||
private Long spuId;
|
||||
|
||||
@Schema(description = "商品 SKU 编号", required = true, example = "1")
|
||||
@NotNull(message = "商品 SKU 编号不能为空")
|
||||
private Long skuId;
|
||||
|
||||
@Schema(description = "秒杀金额", required = true, example = "12.00")
|
||||
@NotNull(message = "秒杀金额不能为空")
|
||||
private Integer seckillPrice;
|
||||
|
||||
@Schema(description = "秒杀库存", example = "80")
|
||||
@Min(value = 0, message = "秒杀库存需要大于等于 0")
|
||||
private Integer stock;
|
||||
|
||||
@Schema(description = "每人限购", example = "10") // 如果为 0 则不限购
|
||||
@Min(value = 0, message = "每人限购需要大于等于 0")
|
||||
private Integer limitBuyCount;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
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;
|
||||
|
||||
@Schema(description = "管理后台 - 秒杀活动创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SeckillActivityCreateReqVO extends SeckillActivityBaseVO {
|
||||
|
||||
@Schema(description = "备注", example = "限时秒杀活动")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "排序", required = true, example = "1")
|
||||
@NotNull(message = "排序不能为空")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "秒杀时段id", required = true, example = "1,3")
|
||||
@NotEmpty(message = "参与场次不能为空")
|
||||
private List<Long> timeIds;
|
||||
|
||||
/**
|
||||
* 商品列表
|
||||
*/
|
||||
@NotEmpty(message = "商品列表不能为空")
|
||||
@Valid
|
||||
private List<Product> products;
|
||||
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 秒杀活动的详细 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SeckillActivityDetailRespVO extends SeckillActivityRespVO {
|
||||
|
||||
/**
|
||||
* 商品列表
|
||||
*/
|
||||
private List<Product> products;
|
||||
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
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.v3.oas.annotations.media.Schema;
|
||||
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;
|
||||
|
||||
@Schema(description = "管理后台 - 秒杀活动分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SeckillActivityPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "秒杀活动名称", example = "晚九点限时秒杀")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "活动状态", example = "进行中")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "秒杀时段id", example = "1")
|
||||
private Long timeId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@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;
|
||||
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 秒杀活动 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SeckillActivityRespVO extends SeckillActivityBaseVO {
|
||||
|
||||
@Schema(description = "秒杀活动id", required = true, example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "付款订单数", required = true, example = "1")
|
||||
private Integer orderCount;
|
||||
|
||||
@Schema(description = "付款人数", required = true, example = "1")
|
||||
private Integer userCount;
|
||||
|
||||
@Schema(description = "创建时间", required = true)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "秒杀时段id", required = true, example = "1,3")
|
||||
private List<Long> timeIds;
|
||||
|
||||
@Schema(description = "排序", required = true, example = "1")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "备注", example = "限时秒杀活动")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "活动状态", example = "进行中")
|
||||
private Integer status;
|
||||
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
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;
|
||||
|
||||
@Schema(description = "管理后台 - 秒杀活动更新 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SeckillActivityUpdateReqVO extends SeckillActivityBaseVO {
|
||||
|
||||
@Schema(description = "秒杀活动编号", required = true, example = "224")
|
||||
@NotNull(message = "秒杀活动编号不能为空")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "备注", example = "限时秒杀活动")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "排序", required = true, example = "1")
|
||||
@NotNull(message = "排序不能为空")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "秒杀时段id", required = true, example = "1,3")
|
||||
@NotEmpty(message = "秒杀时段id不能为空")
|
||||
private List<Long> timeIds;
|
||||
|
||||
/**
|
||||
* 商品列表
|
||||
*/
|
||||
@NotEmpty(message = "商品列表不能为空")
|
||||
@Valid
|
||||
private List<Product> products;
|
||||
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalTime;
|
||||
|
||||
/**
|
||||
* 秒杀时段 Base VO,提供给添加、修改、详细的子 VO 使用
|
||||
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
||||
*/
|
||||
@Data
|
||||
public class SeckillTimeBaseVO {
|
||||
|
||||
@Schema(description = "秒杀时段名称", required = true, example = "上午场")
|
||||
@NotNull(message = "秒杀时段名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "开始时间点", required = true, example = "16:30:40")
|
||||
@NotNull(message = "开始时间点不能为空")
|
||||
private LocalTime startTime;
|
||||
|
||||
@Schema(description = "结束时间点", required = true, example = "16:30:40")
|
||||
@NotNull(message = "结束时间点不能为空")
|
||||
private LocalTime endTime;
|
||||
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Schema(description = "管理后台 - 秒杀时段创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SeckillTimeCreateReqVO extends SeckillTimeBaseVO {
|
||||
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalTime;
|
||||
|
||||
@Schema(description = "管理后台 - 秒杀时段分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SeckillTimePageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "秒杀时段名称", example = "上午场")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "开始时间点", example = "16:30:40")
|
||||
@DateTimeFormat(pattern = "HH:mm:ss")
|
||||
private LocalTime startTime;
|
||||
|
||||
@Schema(description = "结束时间点", example = "16:30:40")
|
||||
@DateTimeFormat(pattern = "HH:mm:ss")
|
||||
private LocalTime endTime;
|
||||
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 秒杀时段 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SeckillTimeRespVO extends SeckillTimeBaseVO {
|
||||
|
||||
@Schema(description = "编号", required = true, example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "秒杀活动数量", required = true, example = "1")
|
||||
private Integer seckillActivityCount;
|
||||
|
||||
@Schema(description = "创建时间", required = true)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - 秒杀时段更新 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SeckillTimeUpdateReqVO extends SeckillTimeBaseVO {
|
||||
|
||||
@Schema(description = "编号", required = true, example = "1")
|
||||
@NotNull(message = "编号不能为空")
|
||||
private Long id;
|
||||
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.app;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "用户 App - 营销")
|
||||
@RestController
|
||||
@RequestMapping("/market/test")
|
||||
@Validated
|
||||
public class AppMarketTestController {
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获取 market 信息")
|
||||
public CommonResult<String> get() {
|
||||
return success("true");
|
||||
}
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.app.banner;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.banner.BannerConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.banner.BannerDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.banner.BannerService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
/**
|
||||
* @author: XIA
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/market/banner")
|
||||
@Tag(name = "用户APP- 首页Banner")
|
||||
@Validated
|
||||
public class AppBannerController {
|
||||
|
||||
@Resource
|
||||
private BannerService bannerService;
|
||||
|
||||
// TODO @xia:新建一个 AppBannerRespVO,只返回必要的字段。status 要过滤下。然后 sort 下结果
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "获得banner列表")
|
||||
@PreAuthorize("@ss.hasPermission('market:banner:query')")
|
||||
public CommonResult<List<BannerRespVO>> getBannerList() {
|
||||
List<BannerDO> list = bannerService.getBannerList();
|
||||
return success(BannerConvert.INSTANCE.convertList(list));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.module.promotion.convert.banner;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.banner.BannerDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface BannerConvert {
|
||||
|
||||
BannerConvert INSTANCE = Mappers.getMapper(BannerConvert.class);
|
||||
|
||||
List<BannerRespVO> convertList(List<BannerDO> list);
|
||||
|
||||
PageResult<BannerRespVO> convertPage(PageResult<BannerDO> pageResult);
|
||||
|
||||
BannerRespVO convert(BannerDO banner);
|
||||
|
||||
BannerDO convert(BannerCreateReqVO createReqVO);
|
||||
|
||||
BannerDO convert(BannerUpdateReqVO updateReqVO);
|
||||
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
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.coupon.CouponPageItemRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* 优惠劵 Convert
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface CouponConvert {
|
||||
|
||||
CouponConvert INSTANCE = Mappers.getMapper(CouponConvert.class);
|
||||
|
||||
PageResult<CouponPageItemRespVO> convertPage(PageResult<CouponDO> page);
|
||||
|
||||
}
|
@@ -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.template.CouponTemplateCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.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<CouponTemplateRespVO> convertPage(PageResult<CouponTemplateDO> page);
|
||||
|
||||
}
|
@@ -0,0 +1,102 @@
|
||||
package cn.iocoder.yudao.module.promotion.convert.discount;
|
||||
|
||||
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.framework.common.util.collection.MapUtils;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.service.discount.bo.DiscountProductDetailBO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 限时折扣活动 Convert
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface DiscountActivityConvert {
|
||||
|
||||
DiscountActivityConvert INSTANCE = Mappers.getMapper(DiscountActivityConvert.class);
|
||||
|
||||
DiscountActivityDO convert(DiscountActivityCreateReqVO bean);
|
||||
|
||||
DiscountActivityDO convert(DiscountActivityUpdateReqVO bean);
|
||||
|
||||
DiscountActivityRespVO convert(DiscountActivityDO bean);
|
||||
|
||||
List<DiscountActivityRespVO> convertList(List<DiscountActivityDO> list);
|
||||
|
||||
PageResult<DiscountActivityRespVO> convertPage(PageResult<DiscountActivityDO> page);
|
||||
|
||||
DiscountProductDetailBO convert(DiscountProductDO product);
|
||||
|
||||
default List<DiscountProductDetailBO> convertList(List<DiscountProductDO> products, Map<Long, DiscountActivityDO> activityMap) {
|
||||
return CollectionUtils.convertList(products, product -> {
|
||||
DiscountProductDetailBO detail = convert(product);
|
||||
MapUtils.findAndThen(activityMap, product.getActivityId(), activity -> {
|
||||
detail.setActivityName(activity.getName());
|
||||
});
|
||||
return detail;
|
||||
});
|
||||
}
|
||||
|
||||
DiscountProductDO convert(DiscountActivityBaseVO.Product bean);
|
||||
|
||||
DiscountActivityDetailRespVO convert(DiscountActivityDO activity, List<DiscountProductDO> products);
|
||||
|
||||
// =========== 比较是否相等 ==========
|
||||
/**
|
||||
* 比较两个限时折扣商品是否相等
|
||||
*
|
||||
* @param productDO 数据库中的商品
|
||||
* @param productVO 前端传入的商品
|
||||
* @return 是否匹配
|
||||
*/
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
default boolean isEquals(DiscountProductDO productDO, DiscountActivityBaseVO.Product productVO) {
|
||||
if (ObjectUtil.notEqual(productDO.getSpuId(), productVO.getSpuId())
|
||||
|| ObjectUtil.notEqual(productDO.getSkuId(), productVO.getSkuId())
|
||||
|| ObjectUtil.notEqual(productDO.getDiscountType(), productVO.getDiscountType())) {
|
||||
return false;
|
||||
}
|
||||
if (productDO.getDiscountType().equals(PromotionDiscountTypeEnum.PRICE.getType())) {
|
||||
return ObjectUtil.equal(productDO.getDiscountPrice(), productVO.getDiscountPrice());
|
||||
}
|
||||
if (productDO.getDiscountType().equals(PromotionDiscountTypeEnum.PERCENT.getType())) {
|
||||
return ObjectUtil.equal(productDO.getDiscountPercent(), productVO.getDiscountPercent());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较两个限时折扣商品是否相等
|
||||
* 注意,比较时忽略 id 编号
|
||||
*
|
||||
* @param productDO 商品 1
|
||||
* @param productVO 商品 2
|
||||
* @return 是否匹配
|
||||
*/
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
default boolean isEquals(DiscountProductDO productDO, DiscountProductDO productVO) {
|
||||
if (ObjectUtil.notEqual(productDO.getSpuId(), productVO.getSpuId())
|
||||
|| ObjectUtil.notEqual(productDO.getSkuId(), productVO.getSkuId())
|
||||
|| ObjectUtil.notEqual(productDO.getDiscountType(), productVO.getDiscountType())) {
|
||||
return false;
|
||||
}
|
||||
if (productDO.getDiscountType().equals(PromotionDiscountTypeEnum.PRICE.getType())) {
|
||||
return ObjectUtil.equal(productDO.getDiscountPrice(), productVO.getDiscountPrice());
|
||||
}
|
||||
if (productDO.getDiscountType().equals(PromotionDiscountTypeEnum.PERCENT.getType())) {
|
||||
return ObjectUtil.equal(productDO.getDiscountPercent(), productVO.getDiscountPercent());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
package cn.iocoder.yudao.module.promotion.convert.price;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.CouponMeetRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
|
||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface PriceConvert {
|
||||
|
||||
PriceConvert INSTANCE = Mappers.getMapper(PriceConvert.class);
|
||||
|
||||
default PriceCalculateRespDTO convert(PriceCalculateReqDTO calculateReqDTO, List<ProductSkuRespDTO> skuList) {
|
||||
// 创建 PriceCalculateRespDTO 对象
|
||||
PriceCalculateRespDTO priceCalculate = new PriceCalculateRespDTO();
|
||||
// 创建它的 Order 属性
|
||||
PriceCalculateRespDTO.Order order = new PriceCalculateRespDTO.Order().setOriginalPrice(0).setDiscountPrice(0)
|
||||
.setCouponPrice(0).setPointPrice(0).setDeliveryPrice(0).setPayPrice(0)
|
||||
.setItems(new ArrayList<>()).setCouponId(calculateReqDTO.getCouponId());
|
||||
priceCalculate.setOrder(order).setPromotions(new ArrayList<>());
|
||||
// 创建它的 OrderItem 属性
|
||||
Map<Long, Integer> skuIdCountMap = CollectionUtils.convertMap(calculateReqDTO.getItems(),
|
||||
PriceCalculateReqDTO.Item::getSkuId, PriceCalculateReqDTO.Item::getCount);
|
||||
skuList.forEach(sku -> {
|
||||
Integer count = skuIdCountMap.get(sku.getId());
|
||||
PriceCalculateRespDTO.OrderItem orderItem = new PriceCalculateRespDTO.OrderItem()
|
||||
.setSpuId(sku.getSpuId()).setSkuId(sku.getId()).setCount(count)
|
||||
.setOriginalUnitPrice(sku.getPrice()).setOriginalPrice(sku.getPrice() * count)
|
||||
.setDiscountPrice(0).setOrderPartPrice(0);
|
||||
orderItem.setPayPrice(orderItem.getOriginalPrice()).setOrderDividePrice(orderItem.getOriginalPrice());
|
||||
priceCalculate.getOrder().getItems().add(orderItem);
|
||||
// 补充价格信息到 Order 中
|
||||
order.setOriginalPrice(order.getOriginalPrice() + orderItem.getOriginalPrice())
|
||||
.setOrderPrice(order.getOriginalPrice()).setPayPrice(order.getOriginalPrice());
|
||||
});
|
||||
return priceCalculate;
|
||||
}
|
||||
|
||||
CouponMeetRespDTO convert(CouponDO coupon);
|
||||
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.module.promotion.convert.reward;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* 满减送活动 Convert
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface RewardActivityConvert {
|
||||
|
||||
RewardActivityConvert INSTANCE = Mappers.getMapper(RewardActivityConvert.class);
|
||||
|
||||
RewardActivityDO convert(RewardActivityCreateReqVO bean);
|
||||
|
||||
RewardActivityDO convert(RewardActivityUpdateReqVO bean);
|
||||
|
||||
RewardActivityRespVO convert(RewardActivityDO bean);
|
||||
|
||||
PageResult<RewardActivityRespVO> convertPage(PageResult<RewardActivityDO> page);
|
||||
|
||||
}
|
@@ -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()));
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.dataobject.banner;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* banner DO
|
||||
*
|
||||
* @author xia
|
||||
*/
|
||||
@TableName("market_banner")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BannerDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String title;
|
||||
/**
|
||||
* 跳转链接
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* 图片链接
|
||||
*/
|
||||
private String picUrl;
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 状态 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String memo;
|
||||
|
||||
// TODO 芋艿 点击次数。&& 其他数据相关
|
||||
|
||||
}
|
@@ -0,0 +1,139 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.dataobject.coupon;
|
||||
|
||||
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.PromotionDiscountTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 优惠劵 DO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "promotion_coupon", autoResultMap = true)
|
||||
@KeySequence("promotion_coupon_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class CouponDO extends BaseDO {
|
||||
|
||||
// ========== 基本信息 BEGIN ==========
|
||||
/**
|
||||
* 优惠劵编号
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 优惠劵模板编号
|
||||
*
|
||||
* 关联 {@link CouponTemplateDO#getId()}
|
||||
*/
|
||||
private Integer templateId;
|
||||
/**
|
||||
* 优惠劵名
|
||||
*
|
||||
* 冗余 {@link CouponTemplateDO#getName()}
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 优惠码状态
|
||||
*
|
||||
* 枚举 {@link CouponStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
// ========== 基本信息 END ==========
|
||||
|
||||
// ========== 领取情况 BEGIN ==========
|
||||
/**
|
||||
* 用户编号
|
||||
*
|
||||
* 关联 MemberUserDO 的 id 字段
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 领取类型
|
||||
*
|
||||
* 枚举 {@link CouponTakeTypeEnum}
|
||||
*/
|
||||
private Integer takeType;
|
||||
// ========== 领取情况 END ==========
|
||||
|
||||
// ========== 使用规则 BEGIN ==========
|
||||
/**
|
||||
* 是否设置满多少金额可用,单位:分
|
||||
*
|
||||
* 冗余 {@link CouponTemplateDO#getUsePrice()}
|
||||
*/
|
||||
private Integer usePrice;
|
||||
/**
|
||||
* 生效开始时间
|
||||
*/
|
||||
private LocalDateTime validStartTime;
|
||||
/**
|
||||
* 生效结束时间
|
||||
*/
|
||||
private LocalDateTime validEndTime;
|
||||
/**
|
||||
* 商品范围
|
||||
*
|
||||
* 枚举 {@link PromotionProductScopeEnum}
|
||||
*/
|
||||
private Integer productScope;
|
||||
/**
|
||||
* 商品 SPU 编号的数组
|
||||
*
|
||||
* 冗余 {@link CouponTemplateDO#getProductSpuIds()}
|
||||
*/
|
||||
@TableField(typeHandler = LongListTypeHandler.class)
|
||||
private List<Long> productSpuIds;
|
||||
// ========== 使用规则 END ==========
|
||||
|
||||
// ========== 使用效果 BEGIN ==========
|
||||
/**
|
||||
* 折扣类型
|
||||
*
|
||||
* 冗余 {@link CouponTemplateDO#getDiscountType()}
|
||||
*/
|
||||
private Integer discountType;
|
||||
/**
|
||||
* 折扣百分比
|
||||
*
|
||||
* 冗余 {@link CouponTemplateDO#getDiscountPercent()}
|
||||
*/
|
||||
private Integer discountPercent;
|
||||
/**
|
||||
* 优惠金额,单位:分
|
||||
*
|
||||
* 冗余 {@link CouponTemplateDO#getDiscountPrice()}
|
||||
*/
|
||||
private Integer discountPrice;
|
||||
/**
|
||||
* 折扣上限,仅在 {@link #discountType} 等于 {@link PromotionDiscountTypeEnum#PERCENT} 时生效
|
||||
*
|
||||
* 冗余 {@link CouponTemplateDO#getDiscountLimitPrice()}
|
||||
*/
|
||||
private Integer discountLimitPrice;
|
||||
// ========== 使用效果 END ==========
|
||||
|
||||
// ========== 使用情况 BEGIN ==========
|
||||
/**
|
||||
* 使用订单号
|
||||
*/
|
||||
private Long useOrderId;
|
||||
/**
|
||||
* 使用时间
|
||||
*/
|
||||
private LocalDateTime useTime;
|
||||
|
||||
// ========== 使用情况 END ==========
|
||||
|
||||
}
|
@@ -0,0 +1,162 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.dataobject.coupon;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
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.PromotionDiscountTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTemplateValidityTypeEnum;
|
||||
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 java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 优惠劵模板 DO
|
||||
*
|
||||
* 当用户领取时,会生成 {@link CouponDO} 优惠劵
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "promotion_coupon_template", autoResultMap = true)
|
||||
@KeySequence("promotion_coupon_template_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class CouponTemplateDO extends BaseDO {
|
||||
|
||||
// ========== 基本信息 BEGIN ==========
|
||||
/**
|
||||
* 模板编号,自增唯一
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 优惠劵名
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 状态
|
||||
*
|
||||
* 枚举 {@link CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
// ========== 基本信息 END ==========
|
||||
|
||||
// ========== 领取规则 BEGIN ==========
|
||||
/**
|
||||
* 发放数量
|
||||
*
|
||||
* -1 - 则表示不限制发放数量
|
||||
*/
|
||||
private Integer totalCount;
|
||||
/**
|
||||
* 每人限领个数
|
||||
*
|
||||
* -1 - 则表示不限制
|
||||
*/
|
||||
private Integer takeLimitCount;
|
||||
/**
|
||||
* 领取方式
|
||||
*
|
||||
* 枚举 {@link CouponTakeTypeEnum}
|
||||
*/
|
||||
private Integer takeType;
|
||||
// ========== 领取规则 END ==========
|
||||
|
||||
// ========== 使用规则 BEGIN ==========
|
||||
/**
|
||||
* 是否设置满多少金额可用,单位:分
|
||||
*
|
||||
* 0 - 不限制
|
||||
* 大于 0 - 多少金额可用
|
||||
*/
|
||||
private Integer usePrice;
|
||||
/**
|
||||
* 商品范围
|
||||
*
|
||||
* 枚举 {@link PromotionProductScopeEnum}
|
||||
*/
|
||||
private Integer productScope;
|
||||
/**
|
||||
* 商品 SPU 编号的数组
|
||||
*/
|
||||
@TableField(typeHandler = LongListTypeHandler.class)
|
||||
private List<Long> productSpuIds;
|
||||
/**
|
||||
* 生效日期类型
|
||||
*
|
||||
* 枚举 {@link CouponTemplateValidityTypeEnum}
|
||||
*/
|
||||
private Integer validityType;
|
||||
/**
|
||||
* 固定日期 - 生效开始时间
|
||||
*
|
||||
* 当 {@link #validityType} 为 {@link CouponTemplateValidityTypeEnum#DATE}
|
||||
*/
|
||||
private LocalDateTime validStartTime;
|
||||
/**
|
||||
* 固定日期 - 生效结束时间
|
||||
*
|
||||
* 当 {@link #validityType} 为 {@link CouponTemplateValidityTypeEnum#DATE}
|
||||
*/
|
||||
private LocalDateTime validEndTime;
|
||||
/**
|
||||
* 领取日期 - 开始天数
|
||||
*
|
||||
* 当 {@link #validityType} 为 {@link CouponTemplateValidityTypeEnum#TERM}
|
||||
*/
|
||||
private Integer fixedStartTerm;
|
||||
/**
|
||||
* 领取日期 - 结束天数
|
||||
*
|
||||
* 当 {@link #validityType} 为 {@link CouponTemplateValidityTypeEnum#TERM}
|
||||
*/
|
||||
private Integer fixedEndTerm;
|
||||
// ========== 使用规则 END ==========
|
||||
|
||||
// ========== 使用效果 BEGIN ==========
|
||||
/**
|
||||
* 折扣类型
|
||||
*
|
||||
* 枚举 {@link PromotionDiscountTypeEnum}
|
||||
*/
|
||||
private Integer discountType;
|
||||
/**
|
||||
* 折扣百分比
|
||||
*
|
||||
* 例如,80% 为 80
|
||||
*/
|
||||
private Integer discountPercent;
|
||||
/**
|
||||
* 优惠金额,单位:分
|
||||
*
|
||||
* 当 {@link #discountType} 为 {@link PromotionDiscountTypeEnum#PRICE} 生效
|
||||
*/
|
||||
private Integer discountPrice;
|
||||
/**
|
||||
* 折扣上限,仅在 {@link #discountType} 等于 {@link PromotionDiscountTypeEnum#PERCENT} 时生效
|
||||
*
|
||||
* 例如,折扣上限为 20 元,当使用 8 折优惠券,订单金额为 1000 元时,最高只可折扣 20 元,而非 80 元。
|
||||
*/
|
||||
private Integer discountLimitPrice;
|
||||
// ========== 使用效果 END ==========
|
||||
|
||||
// ========== 统计信息 BEGIN ==========
|
||||
/**
|
||||
* 领取优惠券的数量
|
||||
*/
|
||||
private Integer takeCount;
|
||||
/**
|
||||
* 使用优惠券的次数
|
||||
*/
|
||||
private Integer useCount;
|
||||
// ========== 统计信息 END ==========
|
||||
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.dataobject.discount;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
|
||||
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 java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 限时折扣活动 DO
|
||||
*
|
||||
* 一个活动下,可以有 {@link DiscountProductDO} 商品;
|
||||
* 一个商品,在指定时间段内,只能属于一个活动;
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "promotion_discount_activity", autoResultMap = true)
|
||||
@KeySequence("promotion_discount_activity_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DiscountActivityDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 活动编号,主键自增
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 活动标题
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 状态
|
||||
*
|
||||
* 枚举 {@link PromotionActivityStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
private LocalDateTime startTime;
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
private LocalDateTime endTime;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.dataobject.discount;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 限时折扣商品 DO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "promotion_discount_product", autoResultMap = true)
|
||||
@KeySequence("promotion_discount_product_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DiscountProductDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号,主键自增
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 限时折扣活动的编号
|
||||
*
|
||||
* 关联 {@link DiscountActivityDO#getId()}
|
||||
*/
|
||||
private Long activityId;
|
||||
/**
|
||||
* 商品 SPU 编号
|
||||
*
|
||||
* 关联 ProductSpuDO 的 id 编号
|
||||
*/
|
||||
private Long spuId;
|
||||
/**
|
||||
* 商品 SKU 编号
|
||||
*
|
||||
* 关联 ProductSkuDO 的 id 编号
|
||||
*/
|
||||
private Long skuId;
|
||||
|
||||
/**
|
||||
* 折扣类型
|
||||
*
|
||||
* 枚举 {@link PromotionDiscountTypeEnum}
|
||||
*/
|
||||
private Integer discountType;
|
||||
/**
|
||||
* 折扣百分比
|
||||
*
|
||||
* 例如,80% 为 80
|
||||
*/
|
||||
private Integer discountPercent;
|
||||
/**
|
||||
* 优惠金额,单位:分
|
||||
*
|
||||
* 当 {@link #discountType} 为 {@link PromotionDiscountTypeEnum#PRICE} 生效
|
||||
*/
|
||||
private Integer discountPrice;
|
||||
|
||||
}
|
@@ -0,0 +1,133 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.dataobject.reward;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
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 cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
|
||||
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 com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 满减送活动 DO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "promotion_reward_activity", autoResultMap = true)
|
||||
@KeySequence("promotion_reward_activity_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class RewardActivityDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 活动编号,主键自增
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 活动标题
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 状态
|
||||
*
|
||||
* 枚举 {@link PromotionActivityStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
private LocalDateTime startTime;
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
private LocalDateTime endTime;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
/**
|
||||
* 条件类型
|
||||
*
|
||||
* 枚举 {@link PromotionConditionTypeEnum}
|
||||
*/
|
||||
private Integer conditionType;
|
||||
/**
|
||||
* 商品范围
|
||||
*
|
||||
* 枚举 {@link PromotionProductScopeEnum}
|
||||
*/
|
||||
private Integer productScope;
|
||||
/**
|
||||
* 商品 SPU 编号的数组
|
||||
*/
|
||||
@TableField(typeHandler = LongListTypeHandler.class)
|
||||
private List<Long> productSpuIds;
|
||||
/**
|
||||
* 优惠规则的数组
|
||||
*/
|
||||
@TableField(typeHandler = RuleTypeHandler.class)
|
||||
private List<Rule> rules;
|
||||
|
||||
/**
|
||||
* 优惠规则
|
||||
*/
|
||||
@Data
|
||||
public static class Rule implements Serializable {
|
||||
|
||||
/**
|
||||
* 优惠门槛
|
||||
*
|
||||
* 1. 满 N 元,单位:分
|
||||
* 2. 满 N 件
|
||||
*/
|
||||
private Integer limit;
|
||||
/**
|
||||
* 优惠价格,单位:分
|
||||
*/
|
||||
private Integer discountPrice;
|
||||
/**
|
||||
* 是否包邮
|
||||
*/
|
||||
private Boolean freeDelivery;
|
||||
/**
|
||||
* 赠送的积分
|
||||
*/
|
||||
private Integer point;
|
||||
/**
|
||||
* 赠送的优惠劵编号的数组
|
||||
*/
|
||||
private List<Long> couponIds;
|
||||
/**
|
||||
* 赠送的优惠卷数量的数组
|
||||
*/
|
||||
private List<Integer> couponCounts;
|
||||
|
||||
}
|
||||
|
||||
// TODO @芋艿:可以找一些新的思路
|
||||
public static class RuleTypeHandler extends AbstractJsonTypeHandler<List<Rule>> {
|
||||
|
||||
@Override
|
||||
protected List<Rule> parse(String json) {
|
||||
return JsonUtils.parseArray(json, Rule.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String toJson(List<Rule> obj) {
|
||||
return JsonUtils.toJsonString(obj);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -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;
|
||||
|
||||
}
|
@@ -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;
|
||||
}
|
@@ -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;
|
||||
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.mysql.banner;
|
||||
|
||||
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.banner.vo.BannerPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.banner.BannerDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* Banner Mapper
|
||||
*
|
||||
* @author xia
|
||||
*/
|
||||
@Mapper
|
||||
public interface BannerMapper extends BaseMapperX<BannerDO> {
|
||||
|
||||
default PageResult<BannerDO> selectPage(BannerPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<BannerDO>()
|
||||
.likeIfPresent(BannerDO::getTitle, reqVO.getTitle())
|
||||
.eqIfPresent(BannerDO::getStatus, reqVO.getStatus())
|
||||
.betweenIfPresent(BannerDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(BannerDO::getSort));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
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.coupon.CouponPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 优惠劵 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface CouponMapper extends BaseMapperX<CouponDO> {
|
||||
|
||||
default PageResult<CouponDO> selectPage(CouponPageReqVO reqVO, Collection<Long> userIds) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<CouponDO>()
|
||||
.eqIfPresent(CouponDO::getTemplateId, reqVO.getTemplateId())
|
||||
.eqIfPresent(CouponDO::getStatus, reqVO.getStatus())
|
||||
.inIfPresent(CouponDO::getUserId, userIds)
|
||||
.betweenIfPresent(CouponDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(CouponDO::getId));
|
||||
}
|
||||
|
||||
default List<CouponDO> selectListByUserIdAndStatus(Long userId, Integer status) {
|
||||
return selectList(new LambdaQueryWrapperX<CouponDO>()
|
||||
.eq(CouponDO::getUserId, userId).eq(CouponDO::getStatus, status));
|
||||
}
|
||||
|
||||
default CouponDO selectByIdAndUserId(Long id, Long userId) {
|
||||
return selectOne(new LambdaQueryWrapperX<CouponDO>()
|
||||
.eq(CouponDO::getId, id).eq(CouponDO::getUserId, userId));
|
||||
}
|
||||
|
||||
default int delete(Long id, Collection<Integer> whereStatuses) {
|
||||
return update(null, new LambdaUpdateWrapper<CouponDO>()
|
||||
.eq(CouponDO::getId, id).in(CouponDO::getStatus, whereStatuses)
|
||||
.set(CouponDO::getDeleted, 1));
|
||||
}
|
||||
|
||||
default int updateByIdAndStatus(Long id, Integer status, CouponDO updateObj) {
|
||||
return update(updateObj, new LambdaUpdateWrapper<CouponDO>()
|
||||
.eq(CouponDO::getId, id).eq(CouponDO::getStatus, status));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
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.template.CouponTemplatePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* 优惠劵模板 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> {
|
||||
|
||||
default PageResult<CouponTemplateDO> selectPage(CouponTemplatePageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<CouponTemplateDO>()
|
||||
.likeIfPresent(CouponTemplateDO::getName, reqVO.getName())
|
||||
.eqIfPresent(CouponTemplateDO::getStatus, reqVO.getStatus())
|
||||
.eqIfPresent(CouponTemplateDO::getDiscountType, reqVO.getDiscountType())
|
||||
.betweenIfPresent(CouponTemplateDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(CouponTemplateDO::getId));
|
||||
}
|
||||
|
||||
void updateTakeCount(@Param("id") Long id, @Param("incrCount") Integer incrCount);
|
||||
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.mysql.discount;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 限时折扣活动 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface DiscountActivityMapper extends BaseMapperX<DiscountActivityDO> {
|
||||
|
||||
default PageResult<DiscountActivityDO> selectPage(DiscountActivityPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<DiscountActivityDO>()
|
||||
.likeIfPresent(DiscountActivityDO::getName, reqVO.getName())
|
||||
.eqIfPresent(DiscountActivityDO::getStatus, reqVO.getStatus())
|
||||
.betweenIfPresent(DiscountActivityDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(DiscountActivityDO::getId));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.mysql.discount;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 限时折扣商城 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface DiscountProductMapper extends BaseMapperX<DiscountProductDO> {
|
||||
|
||||
default List<DiscountProductDO> selectListBySkuId(Collection<Long> skuIds) {
|
||||
return selectList(DiscountProductDO::getSkuId, skuIds);
|
||||
}
|
||||
|
||||
default List<DiscountProductDO> selectListByActivityId(Long activityId) {
|
||||
return selectList(DiscountProductDO::getActivityId, activityId);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.mysql.reward;
|
||||
|
||||
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.reward.vo.RewardActivityPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 满减送活动 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface RewardActivityMapper extends BaseMapperX<RewardActivityDO> {
|
||||
|
||||
default PageResult<RewardActivityDO> selectPage(RewardActivityPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<RewardActivityDO>()
|
||||
.likeIfPresent(RewardActivityDO::getName, reqVO.getName())
|
||||
.eqIfPresent(RewardActivityDO::getStatus, reqVO.getStatus())
|
||||
.orderByDesc(RewardActivityDO::getId));
|
||||
}
|
||||
|
||||
default List<RewardActivityDO> selectListByStatus(Collection<Integer> statuses) {
|
||||
return selectList(RewardActivityDO::getStatus, statuses);
|
||||
}
|
||||
|
||||
default List<RewardActivityDO> selectListByProductScopeAndStatus(Integer productScope, Integer status) {
|
||||
return selectList(new LambdaQueryWrapperX<RewardActivityDO>()
|
||||
.eq(RewardActivityDO::getProductScope, productScope)
|
||||
.eq(RewardActivityDO::getStatus, status));
|
||||
}
|
||||
|
||||
}
|
@@ -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));
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* 属于 promotion 模块的 framework 封装
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
package cn.iocoder.yudao.module.promotion.framework;
|
@@ -0,0 +1,24 @@
|
||||
package cn.iocoder.yudao.module.promotion.framework.web.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration;
|
||||
import org.springdoc.core.GroupedOpenApi;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* promotion 模块的 web 组件的 Configuration
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class PromotionWebConfiguration {
|
||||
|
||||
/**
|
||||
* promotion 模块的 API 分组
|
||||
*/
|
||||
@Bean
|
||||
public GroupedOpenApi promotionGroupedOpenApi() {
|
||||
return YudaoSwaggerAutoConfiguration.buildGroupedOpenApi("promotion");
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* promotion 模块的 web 配置
|
||||
*/
|
||||
package cn.iocoder.yudao.module.promotion.framework.web;
|
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* promotion 模块,我们放营销业务。
|
||||
* 例如说:营销活动、banner、优惠券等等
|
||||
*
|
||||
* 1. Controller URL:以 /promotion/ 开头,避免和其它 Module 冲突
|
||||
* 2. DataObject 表名:以 promotion_ 开头,方便在数据库中区分
|
||||
*/
|
||||
package cn.iocoder.yudao.module.promotion;
|
@@ -0,0 +1,63 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.banner;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.banner.BannerDO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 首页 Banner Service 接口
|
||||
*
|
||||
* @author xia
|
||||
*/
|
||||
public interface BannerService {
|
||||
|
||||
/**
|
||||
* 创建 Banner
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createBanner(@Valid BannerCreateReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新 Banner
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateBanner(@Valid BannerUpdateReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除 Banner
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteBanner(Long id);
|
||||
|
||||
/**
|
||||
* 获得 Banner
|
||||
*
|
||||
* @param id 编号
|
||||
* @return Banner
|
||||
*/
|
||||
BannerDO getBanner(Long id);
|
||||
|
||||
/**
|
||||
* 获得所有 Banner列表
|
||||
* @return Banner列表
|
||||
*/
|
||||
List<BannerDO> getBannerList();
|
||||
|
||||
/**
|
||||
* 获得 Banner 分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return Banner分页
|
||||
*/
|
||||
PageResult<BannerDO> getBannerPage(BannerPageReqVO pageReqVO);
|
||||
|
||||
}
|
@@ -0,0 +1,78 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.banner;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.banner.BannerConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.banner.BannerDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.banner.BannerMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.BANNER_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
* 首页 banner 实现类
|
||||
*
|
||||
* @author xia
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class BannerServiceImpl implements BannerService {
|
||||
|
||||
@Resource
|
||||
private BannerMapper bannerMapper;
|
||||
|
||||
@Override
|
||||
public Long createBanner(BannerCreateReqVO createReqVO) {
|
||||
// 插入
|
||||
BannerDO banner = BannerConvert.INSTANCE.convert(createReqVO);
|
||||
bannerMapper.insert(banner);
|
||||
// 返回
|
||||
return banner.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBanner(BannerUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
this.validateBannerExists(updateReqVO.getId());
|
||||
// 更新
|
||||
BannerDO updateObj = BannerConvert.INSTANCE.convert(updateReqVO);
|
||||
bannerMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteBanner(Long id) {
|
||||
// 校验存在
|
||||
this.validateBannerExists(id);
|
||||
// 删除
|
||||
bannerMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private void validateBannerExists(Long id) {
|
||||
if (bannerMapper.selectById(id) == null) {
|
||||
throw exception(BANNER_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BannerDO getBanner(Long id) {
|
||||
return bannerMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BannerDO> getBannerList() {
|
||||
return bannerMapper.selectList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<BannerDO> getBannerPage(BannerPageReqVO pageReqVO) {
|
||||
return bannerMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
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.coupon.CouponPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 优惠劵 Service 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface CouponService {
|
||||
|
||||
/**
|
||||
* 校验优惠劵,包括状态、有限期
|
||||
*
|
||||
* 1. 如果校验通过,则返回优惠劵信息
|
||||
* 2. 如果校验不通过,则直接抛出业务异常
|
||||
*
|
||||
* @param id 优惠劵编号
|
||||
* @param userId 用户编号
|
||||
* @return 优惠劵信息
|
||||
*/
|
||||
CouponDO validCoupon(Long id, Long userId);
|
||||
|
||||
/**
|
||||
* 校验优惠劵,包括状态、有限期
|
||||
*
|
||||
* @see #validCoupon(Long, Long) 逻辑相同,只是入参不同
|
||||
*
|
||||
* @param coupon 优惠劵
|
||||
*/
|
||||
void validCoupon(CouponDO coupon);
|
||||
|
||||
/**
|
||||
* 获得优惠劵分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 优惠劵分页
|
||||
*/
|
||||
PageResult<CouponDO> getCouponPage(CouponPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 使用优惠劵
|
||||
*
|
||||
* @param id 优惠劵编号
|
||||
* @param userId 用户编号
|
||||
* @param orderId 订单编号
|
||||
*/
|
||||
void useCoupon(Long id, Long userId, Long orderId);
|
||||
|
||||
/**
|
||||
* 回收优惠劵
|
||||
*
|
||||
* @param id 优惠劵编号
|
||||
*/
|
||||
void deleteCoupon(Long id);
|
||||
|
||||
/**
|
||||
* 获得用户的优惠劵列表
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param status 优惠劵状态
|
||||
* @return 优惠劵列表
|
||||
*/
|
||||
List<CouponDO> getCouponList(Long userId, Integer status);
|
||||
|
||||
}
|
@@ -0,0 +1,123 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.coupon;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
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.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;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
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 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class CouponServiceImpl implements CouponService {
|
||||
|
||||
@Resource
|
||||
private CouponTemplateService couponTemplateService;
|
||||
|
||||
@Resource
|
||||
private CouponMapper couponMapper;
|
||||
|
||||
@Resource
|
||||
private MemberUserApi memberUserApi;
|
||||
|
||||
@Override
|
||||
public CouponDO validCoupon(Long id, Long userId) {
|
||||
CouponDO coupon = couponMapper.selectByIdAndUserId(id, userId);
|
||||
if (coupon == null) {
|
||||
throw exception(COUPON_NOT_EXISTS);
|
||||
}
|
||||
validCoupon(coupon);
|
||||
return coupon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validCoupon(CouponDO coupon) {
|
||||
// 校验状态
|
||||
if (ObjectUtil.notEqual(coupon.getStatus(), CouponStatusEnum.UNUSED.getStatus())) {
|
||||
throw exception(COUPON_STATUS_NOT_UNUSED);
|
||||
}
|
||||
// 校验有效期;为避免定时器没跑,实际优惠劵已经过期
|
||||
if (LocalDateTimeUtils.isBetween(coupon.getValidStartTime(), coupon.getValidEndTime())) {
|
||||
throw exception(COUPON_VALID_TIME_NOT_NOW);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<CouponDO> getCouponPage(CouponPageReqVO pageReqVO) {
|
||||
// 获得用户编号
|
||||
Set<Long> userIds = null;
|
||||
if (StrUtil.isNotEmpty(pageReqVO.getNickname())) {
|
||||
userIds = CollectionUtils.convertSet(memberUserApi.getUserListByNickname(pageReqVO.getNickname()),
|
||||
MemberUserRespDTO::getId);
|
||||
if (CollUtil.isEmpty(userIds)) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
}
|
||||
// 分页查询
|
||||
return couponMapper.selectPage(pageReqVO, userIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void useCoupon(Long id, Long userId, Long orderId) {
|
||||
// 校验优惠劵
|
||||
validCoupon(id, userId);
|
||||
// 更新状态
|
||||
int updateCount = couponMapper.updateByIdAndStatus(id, CouponStatusEnum.UNUSED.getStatus(),
|
||||
new CouponDO().setStatus(CouponStatusEnum.USED.getStatus())
|
||||
.setUseOrderId(orderId).setUseTime(LocalDateTime.now()));
|
||||
if (updateCount == 0) {
|
||||
throw exception(COUPON_STATUS_NOT_UNUSED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteCoupon(Long id) {
|
||||
// 校验存在
|
||||
validateCouponExists(id);
|
||||
|
||||
// 更新优惠劵
|
||||
int deleteCount = couponMapper.delete(id,
|
||||
asList(CouponStatusEnum.UNUSED.getStatus(), CouponStatusEnum.EXPIRE.getStatus()));
|
||||
if (deleteCount == 0) {
|
||||
throw exception(COUPON_DELETE_FAIL_USED);
|
||||
}
|
||||
// 减少优惠劵模板的领取数量 -1
|
||||
couponTemplateService.updateCouponTemplateTakeCount(id, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CouponDO> getCouponList(Long userId, Integer status) {
|
||||
return couponMapper.selectListByUserIdAndStatus(userId, status);
|
||||
}
|
||||
|
||||
private void validateCouponExists(Long id) {
|
||||
if (couponMapper.selectById(id) == null) {
|
||||
throw exception(COUPON_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
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.template.CouponTemplateCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplatePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.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 编号
|
||||
* @param status 状态
|
||||
*/
|
||||
void updateCouponTemplateStatus(Long id, Integer status);
|
||||
|
||||
/**
|
||||
* 删除优惠劵模板
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteCouponTemplate(Long id);
|
||||
|
||||
/**
|
||||
* 获得优惠劵模板
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 优惠劵模板
|
||||
*/
|
||||
CouponTemplateDO getCouponTemplate(Long id);
|
||||
|
||||
/**
|
||||
* 获得优惠劵模板分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 优惠劵模板分页
|
||||
*/
|
||||
PageResult<CouponTemplateDO> getCouponTemplatePage(CouponTemplatePageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 更新优惠劵模板的领取数量
|
||||
*
|
||||
* @param id 优惠劵模板编号
|
||||
* @param incrCount 增加数量
|
||||
*/
|
||||
void updateCouponTemplateTakeCount(Long id, int incrCount);
|
||||
|
||||
}
|
@@ -0,0 +1,94 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.coupon;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplatePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.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)
|
||||
.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
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 updateCouponTemplateStatus(Long id, Integer status) {
|
||||
// 校验存在
|
||||
validateCouponTemplateExists(id);
|
||||
// 更新
|
||||
couponTemplateMapper.updateById(new CouponTemplateDO().setId(id).setStatus(status));
|
||||
}
|
||||
|
||||
@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<CouponTemplateDO> getCouponTemplatePage(CouponTemplatePageReqVO pageReqVO) {
|
||||
return couponTemplateMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCouponTemplateTakeCount(Long id, int incrCount) {
|
||||
couponTemplateMapper.updateTakeCount(id, incrCount);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.discount;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.discount.bo.DiscountProductDetailBO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 限时折扣 Service 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface DiscountActivityService {
|
||||
|
||||
/**
|
||||
* 基于指定 SKU 编号数组,获得匹配的限时折扣商品
|
||||
*
|
||||
* 注意,匹配的条件,仅仅是日期符合,并且处于开启状态
|
||||
*
|
||||
* @param skuIds SKU 编号数组
|
||||
* @return 匹配的限时折扣商品
|
||||
*/
|
||||
Map<Long, DiscountProductDetailBO> getMatchDiscountProducts(Collection<Long> skuIds);
|
||||
|
||||
/**
|
||||
* 创建限时折扣活动
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createDiscountActivity(@Valid DiscountActivityCreateReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新限时折扣活动
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateDiscountActivity(@Valid DiscountActivityUpdateReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 关闭限时折扣活动
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void closeRewardActivity(Long id);
|
||||
|
||||
/**
|
||||
* 删除限时折扣活动
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteDiscountActivity(Long id);
|
||||
|
||||
/**
|
||||
* 获得限时折扣活动
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 限时折扣活动
|
||||
*/
|
||||
DiscountActivityDO getDiscountActivity(Long id);
|
||||
|
||||
/**
|
||||
* 获得限时折扣活动分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 限时折扣活动分页
|
||||
*/
|
||||
PageResult<DiscountActivityDO> getDiscountActivityPage(DiscountActivityPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 获得活动编号,对应对应的商品列表
|
||||
*
|
||||
* @param activityId 活动编号
|
||||
* @return 活动的商品列表
|
||||
*/
|
||||
List<DiscountProductDO> getDiscountProductsByActivityId(Long activityId);
|
||||
|
||||
}
|
@@ -0,0 +1,196 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.discount;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityBaseVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountActivityMapper;
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountProductMapper;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
|
||||
import cn.iocoder.yudao.module.promotion.service.discount.bo.DiscountProductDetailBO;
|
||||
import cn.iocoder.yudao.module.promotion.util.PromotionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
/**
|
||||
* 限时折扣 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class DiscountActivityServiceImpl implements DiscountActivityService {
|
||||
|
||||
@Resource
|
||||
private DiscountActivityMapper discountActivityMapper;
|
||||
@Resource
|
||||
private DiscountProductMapper discountProductMapper;
|
||||
|
||||
@Override
|
||||
public Map<Long, DiscountProductDetailBO> getMatchDiscountProducts(Collection<Long> skuIds) {
|
||||
List<DiscountProductDetailBO> discountProducts = getRewardProductListBySkuIds(skuIds, singleton(PromotionActivityStatusEnum.RUN.getStatus()));
|
||||
return convertMap(discountProducts, DiscountProductDetailBO::getSkuId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long createDiscountActivity(DiscountActivityCreateReqVO createReqVO) {
|
||||
// 校验商品是否冲突
|
||||
validateDiscountActivityProductConflicts(null, createReqVO.getProducts());
|
||||
|
||||
// 插入活动
|
||||
DiscountActivityDO discountActivity = DiscountActivityConvert.INSTANCE.convert(createReqVO)
|
||||
.setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getStartTime(), createReqVO.getEndTime()));
|
||||
discountActivityMapper.insert(discountActivity);
|
||||
// 插入商品
|
||||
List<DiscountProductDO> discountProducts = convertList(createReqVO.getProducts(),
|
||||
product -> DiscountActivityConvert.INSTANCE.convert(product).setActivityId(discountActivity.getId()));
|
||||
discountProductMapper.insertBatch(discountProducts);
|
||||
// 返回
|
||||
return discountActivity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDiscountActivity(DiscountActivityUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
DiscountActivityDO discountActivity = validateDiscountActivityExists(updateReqVO.getId());
|
||||
if (discountActivity.getStatus().equals(PromotionActivityStatusEnum.CLOSE.getStatus())) { // 已关闭的活动,不能修改噢
|
||||
throw exception(DISCOUNT_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED);
|
||||
}
|
||||
// 校验商品是否冲突
|
||||
validateDiscountActivityProductConflicts(updateReqVO.getId(), updateReqVO.getProducts());
|
||||
|
||||
// 更新活动
|
||||
DiscountActivityDO updateObj = DiscountActivityConvert.INSTANCE.convert(updateReqVO)
|
||||
.setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getStartTime(), updateReqVO.getEndTime()));
|
||||
discountActivityMapper.updateById(updateObj);
|
||||
// 更新商品
|
||||
updateDiscountProduct(updateReqVO);
|
||||
}
|
||||
|
||||
private void updateDiscountProduct(DiscountActivityUpdateReqVO updateReqVO) {
|
||||
List<DiscountProductDO> dbDiscountProducts = discountProductMapper.selectListByActivityId(updateReqVO.getId());
|
||||
// 计算要删除的记录
|
||||
List<Long> deleteIds = convertList(dbDiscountProducts, DiscountProductDO::getId,
|
||||
discountProductDO -> updateReqVO.getProducts().stream()
|
||||
.noneMatch(product -> DiscountActivityConvert.INSTANCE.isEquals(discountProductDO, product)));
|
||||
if (CollUtil.isNotEmpty(deleteIds)) {
|
||||
discountProductMapper.deleteBatchIds(deleteIds);
|
||||
}
|
||||
// 计算新增的记录
|
||||
List<DiscountProductDO> newDiscountProducts = convertList(updateReqVO.getProducts(),
|
||||
product -> DiscountActivityConvert.INSTANCE.convert(product).setActivityId(updateReqVO.getId()));
|
||||
newDiscountProducts.removeIf(product -> dbDiscountProducts.stream().anyMatch(
|
||||
dbProduct -> DiscountActivityConvert.INSTANCE.isEquals(dbProduct, product))); // 如果匹配到,说明是更新的
|
||||
if (CollectionUtil.isNotEmpty(newDiscountProducts)) {
|
||||
discountProductMapper.insertBatch(newDiscountProducts);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验商品是否冲突
|
||||
*
|
||||
* @param id 编号
|
||||
* @param products 商品列表
|
||||
*/
|
||||
private void validateDiscountActivityProductConflicts(Long id, List<DiscountActivityBaseVO.Product> products) {
|
||||
if (CollUtil.isEmpty(products)) {
|
||||
return;
|
||||
}
|
||||
// 查询商品参加的活动
|
||||
List<DiscountProductDetailBO> discountActivityProductList = getRewardProductListBySkuIds(
|
||||
convertSet(products, DiscountActivityBaseVO.Product::getSkuId),
|
||||
asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus()));
|
||||
if (id != null) { // 排除自己这个活动
|
||||
discountActivityProductList.removeIf(product -> id.equals(product.getActivityId()));
|
||||
}
|
||||
// 如果非空,则说明冲突
|
||||
if (CollUtil.isNotEmpty(discountActivityProductList)) {
|
||||
throw exception(DISCOUNT_ACTIVITY_SPU_CONFLICTS);
|
||||
}
|
||||
}
|
||||
|
||||
private List<DiscountProductDetailBO> getRewardProductListBySkuIds(Collection<Long> skuIds,
|
||||
Collection<Integer> statuses) {
|
||||
// 查询商品
|
||||
List<DiscountProductDO> products = discountProductMapper.selectListBySkuId(skuIds);
|
||||
if (CollUtil.isEmpty(products)) {
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
|
||||
// 查询活动
|
||||
List<DiscountActivityDO> activities = discountActivityMapper.selectBatchIds(skuIds);
|
||||
activities.removeIf(activity -> !statuses.contains(activity.getStatus())); // 移除不满足 statuses 状态的
|
||||
Map<Long, DiscountActivityDO> activityMap = CollectionUtils.convertMap(activities, DiscountActivityDO::getId);
|
||||
|
||||
// 移除不满足活动的商品
|
||||
products.removeIf(product -> !activityMap.containsKey(product.getActivityId()));
|
||||
return DiscountActivityConvert.INSTANCE.convertList(products, activityMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeRewardActivity(Long id) {
|
||||
// 校验存在
|
||||
DiscountActivityDO dbDiscountActivity = validateDiscountActivityExists(id);
|
||||
if (dbDiscountActivity.getStatus().equals(PromotionActivityStatusEnum.CLOSE.getStatus())) { // 已关闭的活动,不能关闭噢
|
||||
throw exception(DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED);
|
||||
}
|
||||
if (dbDiscountActivity.getStatus().equals(PromotionActivityStatusEnum.END.getStatus())) { // 已关闭的活动,不能关闭噢
|
||||
throw exception(DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_END);
|
||||
}
|
||||
|
||||
// 更新
|
||||
DiscountActivityDO updateObj = new DiscountActivityDO().setId(id).setStatus(PromotionActivityStatusEnum.CLOSE.getStatus());
|
||||
discountActivityMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteDiscountActivity(Long id) {
|
||||
// 校验存在
|
||||
DiscountActivityDO discountActivity = validateDiscountActivityExists(id);
|
||||
if (!discountActivity.getStatus().equals(PromotionActivityStatusEnum.CLOSE.getStatus())) { // 未关闭的活动,不能删除噢
|
||||
throw exception(DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED);
|
||||
}
|
||||
|
||||
// 删除
|
||||
discountActivityMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private DiscountActivityDO validateDiscountActivityExists(Long id) {
|
||||
DiscountActivityDO discountActivity = discountActivityMapper.selectById(id);
|
||||
if (discountActivity == null) {
|
||||
throw exception(DISCOUNT_ACTIVITY_NOT_EXISTS);
|
||||
}
|
||||
return discountActivity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiscountActivityDO getDiscountActivity(Long id) {
|
||||
return discountActivityMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<DiscountActivityDO> getDiscountActivityPage(DiscountActivityPageReqVO pageReqVO) {
|
||||
return discountActivityMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DiscountProductDO> getDiscountProductsByActivityId(Long activityId) {
|
||||
return discountProductMapper.selectListByActivityId(activityId);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.discount.bo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 限时折扣活动商品 BO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class DiscountProductDetailBO {
|
||||
|
||||
// ========== DiscountProductDO 字段 ==========
|
||||
|
||||
/**
|
||||
* 编号,主键自增
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 限时折扣活动的编号
|
||||
*/
|
||||
private Long activityId;
|
||||
/**
|
||||
* 商品 SPU 编号
|
||||
*/
|
||||
private Long spuId;
|
||||
/**
|
||||
* 商品 SKU 编号
|
||||
*/
|
||||
private Long skuId;
|
||||
/**
|
||||
* 折扣类型
|
||||
*/
|
||||
private Integer discountType;
|
||||
/**
|
||||
* 折扣百分比
|
||||
*/
|
||||
private Integer discountPercent;
|
||||
/**
|
||||
* 优惠金额,单位:分
|
||||
*/
|
||||
private Integer discountPrice;
|
||||
|
||||
// ========== DiscountActivityDO 字段 ==========
|
||||
/**
|
||||
* 活动标题
|
||||
*/
|
||||
private String activityName;
|
||||
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.price;
|
||||
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.CouponMeetRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 价格计算 Service 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface PriceService {
|
||||
|
||||
/**
|
||||
* 计算商品的价格
|
||||
*
|
||||
* @param calculateReqDTO 价格请求
|
||||
* @return 价格响应
|
||||
*/
|
||||
PriceCalculateRespDTO calculatePrice(PriceCalculateReqDTO calculateReqDTO);
|
||||
|
||||
/**
|
||||
* 获得优惠劵的匹配信息列表
|
||||
*
|
||||
* @param calculateReqDTO 价格请求
|
||||
* @return 价格响应
|
||||
*/
|
||||
List<CouponMeetRespDTO> getMeetCouponList(PriceCalculateReqDTO calculateReqDTO);
|
||||
|
||||
}
|
@@ -0,0 +1,547 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.price;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
|
||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.CouponMeetRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.price.PriceConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.*;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;
|
||||
import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
|
||||
import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService;
|
||||
import cn.iocoder.yudao.module.promotion.service.discount.bo.DiscountProductDetailBO;
|
||||
import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService;
|
||||
import com.google.common.base.Suppliers;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue;
|
||||
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
/**
|
||||
* 价格计算 Service 实现类
|
||||
*
|
||||
* 优惠计算顺序:min(限时折扣, 会员折扣) > 满减送 > 优惠券。
|
||||
* 参考文档:
|
||||
* 1. <a href="https://help.youzan.com/displaylist/detail_4_4-1-60384">有赞文档:限时折扣、满减送、优惠券哪个优先计算?</a>
|
||||
*
|
||||
* TODO 芋艿:进一步完善
|
||||
* 1. 限时折扣:指定金额、减免金额、折扣
|
||||
* 2. 满减送:循环、折扣
|
||||
* 3. 优惠劵:待定
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class PriceServiceImpl implements PriceService {
|
||||
|
||||
@Resource
|
||||
private DiscountActivityService discountService;
|
||||
@Resource
|
||||
private RewardActivityService rewardActivityService;
|
||||
@Resource
|
||||
private CouponService couponService;
|
||||
|
||||
@Resource
|
||||
private ProductSkuApi productSkuApi;
|
||||
|
||||
@Override
|
||||
public PriceCalculateRespDTO calculatePrice(PriceCalculateReqDTO calculateReqDTO) {
|
||||
// 获得商品 SKU 数组
|
||||
List<ProductSkuRespDTO> skuList = checkSkus(calculateReqDTO);
|
||||
// 初始化 PriceCalculateRespDTO 对象
|
||||
PriceCalculateRespDTO priceCalculate = PriceConvert.INSTANCE.convert(calculateReqDTO, skuList);
|
||||
|
||||
// 计算商品级别的价格
|
||||
calculatePriceForSkuLevel(calculateReqDTO.getUserId(), priceCalculate);
|
||||
// 计算订单级别的价格
|
||||
calculatePriceForOrderLevel(calculateReqDTO.getUserId(), priceCalculate);
|
||||
// 计算优惠劵级别的价格
|
||||
calculatePriceForCouponLevel(calculateReqDTO.getUserId(), calculateReqDTO.getCouponId(), priceCalculate);
|
||||
|
||||
// 如果最终支付金额小于等于 0,则抛出业务异常
|
||||
if (priceCalculate.getOrder().getPayPrice() <= 0) {
|
||||
log.error("[calculatePrice][价格计算不正确,请求 calculateReqDTO({}),结果 priceCalculate({})]",
|
||||
calculateReqDTO, priceCalculate);
|
||||
throw exception(PRICE_CALCULATE_PAY_PRICE_ILLEGAL);
|
||||
}
|
||||
return priceCalculate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CouponMeetRespDTO> getMeetCouponList(PriceCalculateReqDTO calculateReqDTO) {
|
||||
// 先计算一轮价格
|
||||
PriceCalculateRespDTO priceCalculate = calculatePrice(calculateReqDTO);
|
||||
|
||||
// 获得用户的待使用优惠劵
|
||||
List<CouponDO> couponList = couponService.getCouponList(calculateReqDTO.getUserId(), CouponStatusEnum.UNUSED.getStatus());
|
||||
if (CollUtil.isEmpty(couponList)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 获得优惠劵的匹配信息
|
||||
return CollectionUtils.convertList(couponList, coupon -> {
|
||||
CouponMeetRespDTO couponMeetRespDTO = PriceConvert.INSTANCE.convert(coupon);
|
||||
try {
|
||||
// 校验优惠劵
|
||||
couponService.validCoupon(coupon);
|
||||
|
||||
// 获得匹配的商品 SKU 数组
|
||||
List<PriceCalculateRespDTO.OrderItem> orderItems = getMatchCouponOrderItems(priceCalculate, coupon);
|
||||
if (CollUtil.isEmpty(orderItems)) {
|
||||
return couponMeetRespDTO.setMeet(false).setMeetTip("所结算商品没有符合条件的商品");
|
||||
}
|
||||
|
||||
// 计算是否满足优惠劵的使用金额
|
||||
Integer originPrice = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum);
|
||||
assert originPrice != null;
|
||||
if (originPrice < coupon.getUsePrice()) {
|
||||
return couponMeetRespDTO.setMeet(false)
|
||||
// .setMeetTip(String.format("差 %s 元可用优惠劵", formatPrice(coupon.getUsePrice() - originPrice)));
|
||||
.setMeetTip("所结算的商品中未满足使用的金额");
|
||||
}
|
||||
} catch (ServiceException serviceException) {
|
||||
couponMeetRespDTO.setMeet(false);
|
||||
if (serviceException.getCode().equals(COUPON_VALID_TIME_NOT_NOW.getCode())) {
|
||||
couponMeetRespDTO.setMeetTip("优惠劵未到使用时间");
|
||||
} else {
|
||||
log.error("[getMeetCouponList][calculateReqDTO({}) 获得优惠劵匹配信息异常]", calculateReqDTO, serviceException);
|
||||
couponMeetRespDTO.setMeetTip("优惠劵不满足使用条件");
|
||||
}
|
||||
return couponMeetRespDTO;
|
||||
}
|
||||
// 满足
|
||||
return couponMeetRespDTO.setMeet(true);
|
||||
});
|
||||
}
|
||||
|
||||
private List<ProductSkuRespDTO> checkSkus(PriceCalculateReqDTO calculateReqDTO) {
|
||||
// 获得商品 SKU 数组
|
||||
Map<Long, Integer> skuIdCountMap = CollectionUtils.convertMap(calculateReqDTO.getItems(),
|
||||
PriceCalculateReqDTO.Item::getSkuId, PriceCalculateReqDTO.Item::getCount);
|
||||
List<ProductSkuRespDTO> skus = productSkuApi.getSkuList(skuIdCountMap.keySet());
|
||||
|
||||
// 校验商品 SKU
|
||||
skus.forEach(sku -> {
|
||||
Integer count = skuIdCountMap.get(sku.getId());
|
||||
if (count == null) {
|
||||
throw exception(SKU_NOT_EXISTS);
|
||||
}
|
||||
// 不校验库存不足,避免购物车场景,商品无货的情况
|
||||
});
|
||||
return skus;
|
||||
}
|
||||
|
||||
// ========== 计算商品级别的价格 ==========
|
||||
|
||||
/**
|
||||
* 计算商品级别的价格,例如说:
|
||||
* 1. 会员折扣
|
||||
* 2. 限时折扣 {@link cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO}
|
||||
*
|
||||
* 其中,会员折扣、限时折扣取最低价
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param priceCalculate 价格计算的结果
|
||||
*/
|
||||
private void calculatePriceForSkuLevel(Long userId, PriceCalculateRespDTO priceCalculate) {
|
||||
// 获取 SKU 级别的所有优惠信息
|
||||
Supplier<Double> memberDiscountPercentSupplier = getMemberDiscountPercentSupplier(userId);
|
||||
Map<Long, DiscountProductDetailBO> discountProducts = discountService.getMatchDiscountProducts(
|
||||
convertSet(priceCalculate.getOrder().getItems(), PriceCalculateRespDTO.OrderItem::getSkuId));
|
||||
|
||||
// 处理每个 SKU 的优惠
|
||||
priceCalculate.getOrder().getItems().forEach(orderItem -> {
|
||||
// 获取该 SKU 的优惠信息
|
||||
Double memberDiscountPercent = memberDiscountPercentSupplier.get();
|
||||
DiscountProductDetailBO discountProduct = discountProducts.get(orderItem.getSkuId());
|
||||
if (memberDiscountPercent == null && discountProduct == null) {
|
||||
return;
|
||||
}
|
||||
// 计算价格,判断选择哪个折扣
|
||||
Integer memberPrice = memberDiscountPercent != null ? (int) (orderItem.getPayPrice() * memberDiscountPercent / 100) : null;
|
||||
Integer promotionPrice = discountProduct != null ? getDiscountProductPrice(discountProduct, orderItem) : null;
|
||||
if (memberPrice == null) {
|
||||
calculatePriceByDiscountActivity(priceCalculate, orderItem, discountProduct, promotionPrice);
|
||||
} else if (promotionPrice == null) {
|
||||
calculatePriceByMemberDiscount(priceCalculate, orderItem, memberPrice);
|
||||
} else if (memberPrice < promotionPrice) {
|
||||
calculatePriceByDiscountActivity(priceCalculate, orderItem, discountProduct, promotionPrice);
|
||||
} else {
|
||||
calculatePriceByMemberDiscount(priceCalculate, orderItem, memberPrice);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Integer getDiscountProductPrice(DiscountProductDetailBO discountProduct,
|
||||
PriceCalculateRespDTO.OrderItem orderItem) {
|
||||
Integer price = orderItem.getPayPrice();
|
||||
if (PromotionDiscountTypeEnum.PRICE.getType().equals(discountProduct.getDiscountType())) { // 减价
|
||||
price -= discountProduct.getDiscountPrice() * orderItem.getCount();
|
||||
} else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(discountProduct.getDiscountType())) { // 打折
|
||||
price = price * discountProduct.getDiscountPercent() / 100;
|
||||
} else {
|
||||
throw new IllegalArgumentException(String.format("优惠活动的商品(%s) 的优惠类型不正确", discountProduct));
|
||||
}
|
||||
return price;
|
||||
}
|
||||
|
||||
private void calculatePriceByMemberDiscount(PriceCalculateRespDTO priceCalculate, PriceCalculateRespDTO.OrderItem orderItem,
|
||||
Integer memberPrice) {
|
||||
// 记录优惠明细
|
||||
addPromotion(priceCalculate, orderItem, null, PromotionTypeEnum.MEMBER.getName(),
|
||||
PromotionTypeEnum.MEMBER.getType(), PromotionLevelEnum.SKU.getLevel(), memberPrice,
|
||||
true, StrUtil.format("会员折扣:省 {} 元", formatPrice(orderItem.getPayPrice() - memberPrice)));
|
||||
// 修改 SKU 的优惠
|
||||
modifyOrderItemPayPrice(orderItem, memberPrice, priceCalculate);
|
||||
}
|
||||
|
||||
private void calculatePriceByDiscountActivity(PriceCalculateRespDTO priceCalculate, PriceCalculateRespDTO.OrderItem orderItem,
|
||||
DiscountProductDetailBO discountProduct, Integer promotionPrice) {
|
||||
// 记录优惠明细
|
||||
addPromotion(priceCalculate, orderItem, discountProduct.getActivityId(), discountProduct.getActivityName(),
|
||||
PromotionTypeEnum.DISCOUNT_ACTIVITY.getType(), PromotionLevelEnum.SKU.getLevel(), promotionPrice,
|
||||
true, StrUtil.format("限时折扣:省 {} 元", formatPrice(orderItem.getPayPrice() - promotionPrice)));
|
||||
// 修改 SKU 的优惠
|
||||
modifyOrderItemPayPrice(orderItem, promotionPrice, priceCalculate);
|
||||
}
|
||||
|
||||
// TODO 芋艿:提前实现
|
||||
private Supplier<Double> getMemberDiscountPercentSupplier(Long userId) {
|
||||
return Suppliers.memoize(() -> {
|
||||
if (userId == 1) {
|
||||
return 90d;
|
||||
}
|
||||
if (userId == 2) {
|
||||
return 80d;
|
||||
}
|
||||
return null; // 无优惠
|
||||
});
|
||||
}
|
||||
|
||||
// ========== 计算商品级别的价格 ==========
|
||||
|
||||
/**
|
||||
* 计算订单级别的价格,例如说:
|
||||
* 1. 满减送 {@link cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO}
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param priceCalculate 价格计算的结果
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void calculatePriceForOrderLevel(Long userId, PriceCalculateRespDTO priceCalculate) {
|
||||
// 获取 SKU 级别的所有优惠信息
|
||||
Set<Long> spuIds = convertSet(priceCalculate.getOrder().getItems(), PriceCalculateRespDTO.OrderItem::getSpuId);
|
||||
Map<RewardActivityDO, Set<Long>> rewardActivities = rewardActivityService.getMatchRewardActivities(spuIds);
|
||||
|
||||
// 处理满减送活动
|
||||
if (CollUtil.isNotEmpty(rewardActivities)) {
|
||||
rewardActivities.forEach((rewardActivity, activitySpuIds) -> {
|
||||
List<PriceCalculateRespDTO.OrderItem> orderItems = CollectionUtils.filterList(priceCalculate.getOrder().getItems(),
|
||||
orderItem -> CollUtil.contains(activitySpuIds, orderItem.getSpuId()));
|
||||
calculatePriceByRewardActivity(priceCalculate, orderItems, rewardActivity);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void calculatePriceByRewardActivity(PriceCalculateRespDTO priceCalculate, List<PriceCalculateRespDTO.OrderItem> orderItems,
|
||||
RewardActivityDO rewardActivity) {
|
||||
// 获得最大匹配的满减送活动的规则
|
||||
RewardActivityDO.Rule rule = getLastMatchRewardActivityRule(rewardActivity, orderItems);
|
||||
if (rule == null) {
|
||||
// 获取不到的情况下,记录不满足的优惠明细
|
||||
addNotMeetPromotion(priceCalculate, orderItems, rewardActivity.getId(), rewardActivity.getName(),
|
||||
PromotionTypeEnum.REWARD_ACTIVITY.getType(), PromotionLevelEnum.ORDER.getLevel(),
|
||||
getRewardActivityNotMeetTip(rewardActivity));
|
||||
return;
|
||||
}
|
||||
|
||||
// 分摊金额
|
||||
List<Integer> discountPartPrices = dividePrice(orderItems, rule.getDiscountPrice());
|
||||
// 记录优惠明细
|
||||
addPromotion(priceCalculate, orderItems, rewardActivity.getId(), rewardActivity.getName(),
|
||||
PromotionTypeEnum.REWARD_ACTIVITY.getType(), PromotionLevelEnum.ORDER.getLevel(), discountPartPrices,
|
||||
true, StrUtil.format("满减送:省 {} 元", formatPrice(rule.getDiscountPrice())));
|
||||
// 修改 SKU 的分摊
|
||||
for (int i = 0; i < orderItems.size(); i++) {
|
||||
modifyOrderItemOrderPartPriceFromDiscountPrice(orderItems.get(i), discountPartPrices.get(i), priceCalculate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得最大匹配的满减送活动的规则
|
||||
*
|
||||
* @param rewardActivity 满减送活动
|
||||
* @param orderItems 商品项
|
||||
* @return 匹配的活动规则
|
||||
*/
|
||||
private RewardActivityDO.Rule getLastMatchRewardActivityRule(RewardActivityDO rewardActivity,
|
||||
List<PriceCalculateRespDTO.OrderItem> orderItems) {
|
||||
Integer count = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getCount, Integer::sum);
|
||||
// price 的计算逻辑,使用 orderDividePrice 的原因,主要考虑分摊后,这个才是该 SKU 当前真实的支付总价
|
||||
Integer price = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum);
|
||||
assert count != null && price != null;
|
||||
for (int i = rewardActivity.getRules().size() - 1; i >= 0; i--) {
|
||||
RewardActivityDO.Rule rule = rewardActivity.getRules().get(i);
|
||||
if (PromotionConditionTypeEnum.PRICE.getType().equals(rewardActivity.getConditionType())
|
||||
&& price >= rule.getLimit()) {
|
||||
return rule;
|
||||
}
|
||||
if (PromotionConditionTypeEnum.COUNT.getType().equals(rewardActivity.getConditionType())
|
||||
&& count >= rule.getLimit()) {
|
||||
return rule;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得满减送活动部匹配时的提示
|
||||
*
|
||||
* @param rewardActivity 满减送活动
|
||||
* @return 提示
|
||||
*/
|
||||
private String getRewardActivityNotMeetTip(RewardActivityDO rewardActivity) {
|
||||
return "TODO"; // TODO 芋艿:后面再想想
|
||||
}
|
||||
|
||||
// ========== 计算优惠劵级别的价格 ==========
|
||||
|
||||
private void calculatePriceForCouponLevel(Long userId, Long couponId, PriceCalculateRespDTO priceCalculate) {
|
||||
// 校验优惠劵
|
||||
if (couponId == null) {
|
||||
return;
|
||||
}
|
||||
CouponDO coupon = couponService.validCoupon(couponId, userId);
|
||||
|
||||
// 获得匹配的商品 SKU 数组
|
||||
List<PriceCalculateRespDTO.OrderItem> orderItems = getMatchCouponOrderItems(priceCalculate, coupon);
|
||||
if (CollUtil.isEmpty(orderItems)) {
|
||||
throw exception(COUPON_NO_MATCH_SPU);
|
||||
}
|
||||
|
||||
// 计算是否满足优惠劵的使用金额
|
||||
Integer originPrice = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum);
|
||||
assert originPrice != null;
|
||||
if (originPrice < coupon.getUsePrice()) {
|
||||
throw exception(COUPON_NO_MATCH_MIN_PRICE);
|
||||
}
|
||||
|
||||
// 计算可以优惠的金额
|
||||
priceCalculate.getOrder().setCouponId(couponId);
|
||||
Integer couponPrice = getCouponPrice(coupon, originPrice);
|
||||
// 分摊金额
|
||||
List<Integer> couponPartPrices = dividePrice(orderItems, couponPrice);
|
||||
// 记录优惠明细
|
||||
addPromotion(priceCalculate, orderItems, coupon.getId(), coupon.getName(),
|
||||
PromotionTypeEnum.COUPON.getType(), PromotionLevelEnum.COUPON.getLevel(), couponPartPrices,
|
||||
true, StrUtil.format("优惠劵:省 {} 元", formatPrice(couponPrice)));
|
||||
// 修改 SKU 的分摊
|
||||
for (int i = 0; i < orderItems.size(); i++) {
|
||||
modifyOrderItemOrderPartPriceFromCouponPrice(orderItems.get(i), couponPartPrices.get(i), priceCalculate);
|
||||
}
|
||||
}
|
||||
|
||||
private List<PriceCalculateRespDTO.OrderItem> getMatchCouponOrderItems(PriceCalculateRespDTO priceCalculate,
|
||||
CouponDO coupon) {
|
||||
if (PromotionProductScopeEnum.ALL.getScope().equals(coupon.getProductScope())) {
|
||||
return priceCalculate.getOrder().getItems();
|
||||
}
|
||||
return CollectionUtils.filterList(priceCalculate.getOrder().getItems(),
|
||||
orderItem -> coupon.getProductSpuIds().contains(orderItem.getSpuId()));
|
||||
}
|
||||
|
||||
private Integer getCouponPrice(CouponDO coupon, Integer originPrice) {
|
||||
if (PromotionDiscountTypeEnum.PRICE.getType().equals(coupon.getDiscountType())) { // 减价
|
||||
return coupon.getDiscountPrice();
|
||||
} else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(coupon.getDiscountType())) { // 打折
|
||||
int couponPrice = originPrice * coupon.getDiscountPercent() / 100;
|
||||
return coupon.getDiscountLimitPrice() == null ? couponPrice
|
||||
: Math.min(couponPrice, coupon.getDiscountLimitPrice()); // 优惠上限
|
||||
}
|
||||
throw new IllegalArgumentException(String.format("优惠劵(%s) 的优惠类型不正确", coupon));
|
||||
}
|
||||
|
||||
// ========== 其它相对通用的方法 ==========
|
||||
|
||||
/**
|
||||
* 添加单个 OrderItem 的营销明细
|
||||
*
|
||||
* @param priceCalculate 价格计算结果
|
||||
* @param orderItem 单个订单商品 SKU
|
||||
* @param id 营销编号
|
||||
* @param name 营销名字
|
||||
* @param type 营销类型
|
||||
* @param level 营销级别
|
||||
* @param newPayPrice 新的单实付金额(总)
|
||||
* @param meet 是否满足优惠条件
|
||||
* @param meetTip 满足条件的提示
|
||||
*/
|
||||
private void addPromotion(PriceCalculateRespDTO priceCalculate, PriceCalculateRespDTO.OrderItem orderItem,
|
||||
Long id, String name, Integer type, Integer level,
|
||||
Integer newPayPrice, Boolean meet, String meetTip) {
|
||||
// 创建营销明细 Item
|
||||
// TODO 芋艿:orderItem.getPayPrice() 要不要改成 orderDividePrice;同时,newPayPrice 要不要改成直接传递 discountPrice
|
||||
PriceCalculateRespDTO.PromotionItem promotionItem = new PriceCalculateRespDTO.PromotionItem().setSkuId(orderItem.getSkuId())
|
||||
.setOriginalPrice(orderItem.getPayPrice()).setDiscountPrice(orderItem.getPayPrice() - newPayPrice);
|
||||
// 创建营销明细
|
||||
PriceCalculateRespDTO.Promotion promotion = new PriceCalculateRespDTO.Promotion()
|
||||
.setId(id).setName(name).setType(type).setLevel(level)
|
||||
.setOriginalPrice(promotionItem.getOriginalPrice()).setDiscountPrice(promotionItem.getDiscountPrice())
|
||||
.setItems(singletonList(promotionItem)).setMeet(meet).setMeetTip(meetTip);
|
||||
priceCalculate.getPromotions().add(promotion);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加多个 OrderItem 的营销明细
|
||||
*
|
||||
* @param priceCalculate 价格计算结果
|
||||
* @param orderItems 多个订单商品 SKU
|
||||
* @param id 营销编号
|
||||
* @param name 营销名字
|
||||
* @param type 营销类型
|
||||
* @param level 营销级别
|
||||
* @param discountPrices 多个订单商品 SKU 的优惠价格(总),和 orderItems 一一对应
|
||||
* @param meet 是否满足优惠条件
|
||||
* @param meetTip 满足条件的提示
|
||||
*/
|
||||
private void addPromotion(PriceCalculateRespDTO priceCalculate, List<PriceCalculateRespDTO.OrderItem> orderItems,
|
||||
Long id, String name, Integer type, Integer level,
|
||||
List<Integer> discountPrices, Boolean meet, String meetTip) {
|
||||
// 创建营销明细 Item
|
||||
List<PriceCalculateRespDTO.PromotionItem> promotionItems = new ArrayList<>(discountPrices.size());
|
||||
for (int i = 0; i < orderItems.size(); i++) {
|
||||
PriceCalculateRespDTO.OrderItem orderItem = orderItems.get(i);
|
||||
promotionItems.add(new PriceCalculateRespDTO.PromotionItem().setSkuId(orderItem.getSkuId())
|
||||
.setOriginalPrice(orderItem.getPayPrice()).setDiscountPrice(discountPrices.get(i)));
|
||||
}
|
||||
// 创建营销明细
|
||||
PriceCalculateRespDTO.Promotion promotion = new PriceCalculateRespDTO.Promotion()
|
||||
.setId(id).setName(name).setType(type).setLevel(level)
|
||||
.setOriginalPrice(getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum))
|
||||
.setDiscountPrice(getSumValue(discountPrices, value -> value, Integer::sum))
|
||||
.setItems(promotionItems).setMeet(meet).setMeetTip(meetTip);
|
||||
priceCalculate.getPromotions().add(promotion);
|
||||
}
|
||||
|
||||
private void addNotMeetPromotion(PriceCalculateRespDTO priceCalculate, List<PriceCalculateRespDTO.OrderItem> orderItems,
|
||||
Long id, String name, Integer type, Integer level, String meetTip) {
|
||||
// 创建营销明细 Item
|
||||
List<PriceCalculateRespDTO.PromotionItem> promotionItems = CollectionUtils.convertList(orderItems,
|
||||
orderItem -> new PriceCalculateRespDTO.PromotionItem().setSkuId(orderItem.getSkuId())
|
||||
.setOriginalPrice(orderItem.getOrderDividePrice()).setDiscountPrice(0));
|
||||
// 创建营销明细
|
||||
Integer originalPrice = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum);
|
||||
PriceCalculateRespDTO.Promotion promotion = new PriceCalculateRespDTO.Promotion()
|
||||
.setId(id).setName(name).setType(type).setLevel(level)
|
||||
.setOriginalPrice(originalPrice).setDiscountPrice(0)
|
||||
.setItems(promotionItems).setMeet(false).setMeetTip(meetTip);
|
||||
priceCalculate.getPromotions().add(promotion);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改 OrderItem 的 payPrice 价格,同时会修改 Order 的 payPrice 价格
|
||||
*
|
||||
* @param orderItem 订单商品 SKU
|
||||
* @param newPayPrice 新的 payPrice 价格
|
||||
* @param priceCalculate 价格计算结果
|
||||
*/
|
||||
private void modifyOrderItemPayPrice(PriceCalculateRespDTO.OrderItem orderItem, Integer newPayPrice,
|
||||
PriceCalculateRespDTO priceCalculate) {
|
||||
// diffPayPrice 等于额外增加的商品级的优惠
|
||||
int diffPayPrice = orderItem.getPayPrice() - newPayPrice;
|
||||
// 设置 OrderItem 价格相关字段
|
||||
orderItem.setDiscountPrice(orderItem.getDiscountPrice() + diffPayPrice);
|
||||
orderItem.setPayPrice(newPayPrice);
|
||||
orderItem.setOrderDividePrice(orderItem.getPayPrice() - orderItem.getOrderPartPrice());
|
||||
// 设置 Order 相关相关字段
|
||||
PriceCalculateRespDTO.Order order = priceCalculate.getOrder();
|
||||
order.setPayPrice(order.getPayPrice() - diffPayPrice);
|
||||
order.setOrderPrice(order.getOrderPrice() - diffPayPrice);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改 OrderItem 的 orderPartPrice 价格,同时会修改 Order 的 discountPrice 价格
|
||||
*
|
||||
* 本质:分摊 Order 的 discountPrice 价格,到对应的 OrderItem 的 orderPartPrice 价格中
|
||||
*
|
||||
* @param orderItem 订单商品 SKU
|
||||
* @param addOrderPartPrice 新增的 discountPrice 价格
|
||||
* @param priceCalculate 价格计算结果
|
||||
*/
|
||||
private void modifyOrderItemOrderPartPriceFromDiscountPrice(PriceCalculateRespDTO.OrderItem orderItem, Integer addOrderPartPrice,
|
||||
PriceCalculateRespDTO priceCalculate) {
|
||||
// 设置 OrderItem 价格相关字段
|
||||
orderItem.setOrderPartPrice(orderItem.getOrderPartPrice() + addOrderPartPrice);
|
||||
orderItem.setOrderDividePrice(orderItem.getPayPrice() - orderItem.getOrderPartPrice());
|
||||
// 设置 Order 相关相关字段
|
||||
PriceCalculateRespDTO.Order order = priceCalculate.getOrder();
|
||||
order.setDiscountPrice(order.getDiscountPrice() + addOrderPartPrice);
|
||||
order.setPayPrice(order.getPayPrice() - addOrderPartPrice);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改 OrderItem 的 orderPartPrice 价格,同时会修改 Order 的 couponPrice 价格
|
||||
*
|
||||
* 本质:分摊 Order 的 couponPrice 价格,到对应的 OrderItem 的 orderPartPrice 价格中
|
||||
*
|
||||
* @param orderItem 订单商品 SKU
|
||||
* @param addOrderPartPrice 新增的 couponPrice 价格
|
||||
* @param priceCalculate 价格计算结果
|
||||
*/
|
||||
private void modifyOrderItemOrderPartPriceFromCouponPrice(PriceCalculateRespDTO.OrderItem orderItem, Integer addOrderPartPrice,
|
||||
PriceCalculateRespDTO priceCalculate) {
|
||||
// 设置 OrderItem 价格相关字段
|
||||
orderItem.setOrderPartPrice(orderItem.getOrderPartPrice() + addOrderPartPrice);
|
||||
orderItem.setOrderDividePrice(orderItem.getPayPrice() - orderItem.getOrderPartPrice());
|
||||
// 设置 Order 相关相关字段
|
||||
PriceCalculateRespDTO.Order order = priceCalculate.getOrder();
|
||||
order.setCouponPrice(order.getCouponPrice() + addOrderPartPrice);
|
||||
order.setPayPrice(order.getPayPrice() - addOrderPartPrice);
|
||||
}
|
||||
|
||||
private List<Integer> dividePrice(List<PriceCalculateRespDTO.OrderItem> orderItems, Integer price) {
|
||||
List<Integer> prices = new ArrayList<>(orderItems.size());
|
||||
Integer total = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum);
|
||||
assert total != null;
|
||||
int remainPrice = price;
|
||||
// 遍历每一个,进行分摊
|
||||
for (int i = 0; i < orderItems.size(); i++) {
|
||||
PriceCalculateRespDTO.OrderItem orderItem = orderItems.get(i);
|
||||
int partPrice;
|
||||
if (i < orderItems.size() - 1) { // 减一的原因,是因为拆分时,如果按照比例,可能会出现.所以最后一个,使用反减
|
||||
partPrice = (int) (price * (1.0D * orderItem.getOrderDividePrice() / total));
|
||||
remainPrice -= partPrice;
|
||||
} else {
|
||||
partPrice = remainPrice;
|
||||
}
|
||||
Assert.isTrue(partPrice > 0, "分摊金额必须大于 0");
|
||||
prices.add(partPrice);
|
||||
}
|
||||
return prices;
|
||||
}
|
||||
|
||||
private String formatPrice(Integer price) {
|
||||
return String.format("%.2f", price / 100d);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.reward;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 满减送活动 Service 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface RewardActivityService {
|
||||
|
||||
/**
|
||||
* 创建满减送活动
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createRewardActivity(@Valid RewardActivityCreateReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新满减送活动
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateRewardActivity(@Valid RewardActivityUpdateReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 关闭满减送活动
|
||||
*
|
||||
* @param id 活动编号
|
||||
*/
|
||||
void closeRewardActivity(Long id);
|
||||
|
||||
/**
|
||||
* 删除满减送活动
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteRewardActivity(Long id);
|
||||
|
||||
/**
|
||||
* 获得满减送活动
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 满减送活动
|
||||
*/
|
||||
RewardActivityDO getRewardActivity(Long id);
|
||||
|
||||
/**
|
||||
* 获得满减送活动分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 满减送活动分页
|
||||
*/
|
||||
PageResult<RewardActivityDO> getRewardActivityPage(RewardActivityPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 基于指定的 SPU 编号数组,获得它们匹配的满减送活动
|
||||
*
|
||||
* @param spuIds SPU 编号数组
|
||||
* @return 满减送活动,与对应的 SPU 编号的映射。即,value 就是 SPU 编号的集合
|
||||
*/
|
||||
Map<RewardActivityDO, Set<Long>> getMatchRewardActivities(Set<Long> spuIds);
|
||||
|
||||
}
|
@@ -0,0 +1,169 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.reward;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.reward.RewardActivityConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.reward.RewardActivityMapper;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
|
||||
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 java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.hutool.core.collection.CollUtil.intersectionDistinct;
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.singleton;
|
||||
|
||||
/**
|
||||
* 满减送活动 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class RewardActivityServiceImpl implements RewardActivityService {
|
||||
|
||||
@Resource
|
||||
private RewardActivityMapper rewardActivityMapper;
|
||||
|
||||
@Override
|
||||
public Long createRewardActivity(RewardActivityCreateReqVO createReqVO) {
|
||||
// 校验商品是否冲突
|
||||
validateRewardActivitySpuConflicts(null, createReqVO.getProductSpuIds());
|
||||
|
||||
// 插入
|
||||
RewardActivityDO rewardActivity = RewardActivityConvert.INSTANCE.convert(createReqVO)
|
||||
.setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getStartTime(), createReqVO.getEndTime()));
|
||||
rewardActivityMapper.insert(rewardActivity);
|
||||
// 返回
|
||||
return rewardActivity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateRewardActivity(RewardActivityUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
RewardActivityDO dbRewardActivity = validateRewardActivityExists(updateReqVO.getId());
|
||||
if (dbRewardActivity.getStatus().equals(PromotionActivityStatusEnum.CLOSE.getStatus())) { // 已关闭的活动,不能修改噢
|
||||
throw exception(REWARD_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED);
|
||||
}
|
||||
// 校验商品是否冲突
|
||||
validateRewardActivitySpuConflicts(updateReqVO.getId(), updateReqVO.getProductSpuIds());
|
||||
|
||||
// 更新
|
||||
RewardActivityDO updateObj = RewardActivityConvert.INSTANCE.convert(updateReqVO)
|
||||
.setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getStartTime(), updateReqVO.getEndTime()));
|
||||
rewardActivityMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeRewardActivity(Long id) {
|
||||
// 校验存在
|
||||
RewardActivityDO dbRewardActivity = validateRewardActivityExists(id);
|
||||
if (dbRewardActivity.getStatus().equals(PromotionActivityStatusEnum.CLOSE.getStatus())) { // 已关闭的活动,不能关闭噢
|
||||
throw exception(REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED);
|
||||
}
|
||||
if (dbRewardActivity.getStatus().equals(PromotionActivityStatusEnum.END.getStatus())) { // 已关闭的活动,不能关闭噢
|
||||
throw exception(REWARD_ACTIVITY_CLOSE_FAIL_STATUS_END);
|
||||
}
|
||||
|
||||
// 更新
|
||||
RewardActivityDO updateObj = new RewardActivityDO().setId(id).setStatus(PromotionActivityStatusEnum.CLOSE.getStatus());
|
||||
rewardActivityMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteRewardActivity(Long id) {
|
||||
// 校验存在
|
||||
RewardActivityDO dbRewardActivity = validateRewardActivityExists(id);
|
||||
if (!dbRewardActivity.getStatus().equals(PromotionActivityStatusEnum.CLOSE.getStatus())) { // 未关闭的活动,不能删除噢
|
||||
throw exception(REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED);
|
||||
}
|
||||
|
||||
// 删除
|
||||
rewardActivityMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private RewardActivityDO validateRewardActivityExists(Long id) {
|
||||
RewardActivityDO activity = rewardActivityMapper.selectById(id);
|
||||
if (activity == null) {
|
||||
throw exception(REWARD_ACTIVITY_NOT_EXISTS);
|
||||
}
|
||||
return activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验商品参加的活动是否冲突
|
||||
*
|
||||
* @param id 活动编号
|
||||
* @param spuIds 商品 SPU 编号数组
|
||||
*/
|
||||
private void validateRewardActivitySpuConflicts(Long id, Collection<Long> spuIds) {
|
||||
if (CollUtil.isEmpty(spuIds)) {
|
||||
return;
|
||||
}
|
||||
// 查询商品参加的活动
|
||||
List<RewardActivityDO> rewardActivityList = getRewardActivityListBySpuIds(spuIds,
|
||||
asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus()));
|
||||
if (id != null) { // 排除自己这个活动
|
||||
rewardActivityList.removeIf(activity -> id.equals(activity.getId()));
|
||||
}
|
||||
// 如果非空,则说明冲突
|
||||
if (CollUtil.isNotEmpty(rewardActivityList)) {
|
||||
throw exception(REWARD_ACTIVITY_SPU_CONFLICTS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得商品参加的满减送活动的数组
|
||||
*
|
||||
* @param spuIds 商品 SPU 编号数组
|
||||
* @param statuses 活动状态数组
|
||||
* @return 商品参加的满减送活动的数组
|
||||
*/
|
||||
private List<RewardActivityDO> getRewardActivityListBySpuIds(Collection<Long> spuIds,
|
||||
Collection<Integer> statuses) {
|
||||
List<RewardActivityDO> list = rewardActivityMapper.selectListByStatus(statuses);
|
||||
return CollUtil.filter(list, activity -> CollUtil.containsAny(activity.getProductSpuIds(), spuIds));
|
||||
}
|
||||
|
||||
@Override
|
||||
public RewardActivityDO getRewardActivity(Long id) {
|
||||
return rewardActivityMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<RewardActivityDO> getRewardActivityPage(RewardActivityPageReqVO pageReqVO) {
|
||||
return rewardActivityMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<RewardActivityDO, Set<Long>> getMatchRewardActivities(Set<Long> spuIds) {
|
||||
// 如果有全局活动,则直接选择它
|
||||
List<RewardActivityDO> allActivities = rewardActivityMapper.selectListByProductScopeAndStatus(
|
||||
PromotionProductScopeEnum.ALL.getScope(), PromotionActivityStatusEnum.RUN.getStatus());
|
||||
if (CollUtil.isNotEmpty(allActivities)) {
|
||||
return MapUtil.builder(allActivities.get(0), spuIds).build();
|
||||
}
|
||||
|
||||
// 查询某个活动参加的活动
|
||||
List<RewardActivityDO> productActivityList = getRewardActivityListBySpuIds(spuIds,
|
||||
singleton(PromotionActivityStatusEnum.RUN.getStatus()));
|
||||
return convertMap(productActivityList, activity -> activity,
|
||||
rewardActivityDO -> intersectionDistinct(rewardActivityDO.getProductSpuIds(), spuIds)); // 求交集返回
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
package cn.iocoder.yudao.module.promotion.util;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 活动工具类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class PromotionUtils {
|
||||
|
||||
/**
|
||||
* 根据时间,计算活动状态
|
||||
*
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return 活动状态
|
||||
*/
|
||||
public static Integer calculateActivityStatus(LocalDateTime startTime, LocalDateTime endTime) {
|
||||
if (LocalDateTimeUtils.beforeNow(endTime)) {
|
||||
return PromotionActivityStatusEnum.END.getStatus();
|
||||
}
|
||||
if (LocalDateTimeUtils.afterNow(startTime)) {
|
||||
return PromotionActivityStatusEnum.WAIT.getStatus();
|
||||
}
|
||||
return PromotionActivityStatusEnum.RUN.getStatus();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponTemplateMapper">
|
||||
|
||||
<update id="updateTakeCount">
|
||||
UPDATE promotion_coupon_template
|
||||
SET take_count = take_count + #{incrCount}
|
||||
WHERE id = #{id}
|
||||
</update>
|
||||
|
||||
</mapper>
|
@@ -0,0 +1,147 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.coupon;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
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.coupon.vo.template.CouponTemplateCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplatePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponTemplateMapper;
|
||||
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 org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.hutool.core.util.RandomUtil.randomEle;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
|
||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_NOT_EXISTS;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* {@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,
|
||||
o -> o.setProductScope(randomEle(PromotionProductScopeEnum.values()).getScope())
|
||||
.setValidityType(randomEle(CouponTemplateValidityTypeEnum.values()).getType())
|
||||
.setDiscountType(randomEle(PromotionDiscountTypeEnum.values()).getType()));
|
||||
|
||||
// 调用
|
||||
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
|
||||
// 其它通用字段
|
||||
o.setProductScope(randomEle(PromotionProductScopeEnum.values()).getScope())
|
||||
.setValidityType(randomEle(CouponTemplateValidityTypeEnum.values()).getType())
|
||||
.setDiscountType(randomEle(PromotionDiscountTypeEnum.values()).getType());
|
||||
});
|
||||
|
||||
// 调用
|
||||
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
|
||||
public void testGetCouponTemplatePage() {
|
||||
// mock 数据
|
||||
CouponTemplateDO dbCouponTemplate = randomPojo(CouponTemplateDO.class, o -> { // 等会查询到
|
||||
o.setName("芋艿");
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setDiscountType(PromotionDiscountTypeEnum.PERCENT.getType());
|
||||
o.setCreateTime(buildTime(2022, 2, 2));
|
||||
});
|
||||
couponTemplateMapper.insert(dbCouponTemplate);
|
||||
// 测试 name 不匹配
|
||||
couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setName("土豆")));
|
||||
// 测试 status 不匹配
|
||||
couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
|
||||
// 测试 type 不匹配
|
||||
couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setDiscountType(PromotionDiscountTypeEnum.PRICE.getType())));
|
||||
// 测试 createTime 不匹配
|
||||
couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setCreateTime(buildTime(2022, 1, 1))));
|
||||
// 准备参数
|
||||
CouponTemplatePageReqVO reqVO = new CouponTemplatePageReqVO();
|
||||
reqVO.setName("芋艿");
|
||||
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
reqVO.setDiscountType(PromotionDiscountTypeEnum.PERCENT.getType());
|
||||
reqVO.setCreateTime((new LocalDateTime[]{buildTime(2022, 2, 1), buildTime(2022, 2, 3)}));
|
||||
|
||||
// 调用
|
||||
PageResult<CouponTemplateDO> pageResult = couponTemplateService.getCouponTemplatePage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(dbCouponTemplate, pageResult.getList().get(0));
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user