diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/AppFileController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/AppFileController.java new file mode 100644 index 000000000..62755fc68 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/AppFileController.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.infra.controller.app.file; + +import cn.hutool.core.io.IoUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.infra.controller.app.file.vo.AppFileUploadReqVO; +import cn.iocoder.yudao.module.infra.service.file.FileService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "用户 App - 文件存储") +@RestController +@RequestMapping("/infra/file") +@Validated +@Slf4j +public class AppFileController { + + @Resource + private FileService fileService; + + @PostMapping("/upload") + @Operation(summary = "上传文件") + public CommonResult uploadFile(AppFileUploadReqVO uploadReqVO) throws Exception { + MultipartFile file = uploadReqVO.getFile(); + String path = uploadReqVO.getPath(); + return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream()))); + } + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/AppFileUploadReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/AppFileUploadReqVO.java new file mode 100644 index 000000000..04666c14f --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/AppFileUploadReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.infra.controller.app.file.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; + +import javax.validation.constraints.NotNull; + +@Schema(description = "用户 App - 上传文件 Request VO") +@Data +public class AppFileUploadReqVO { + + @Schema(description = "文件附件", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "文件附件不能为空") + private MultipartFile file; + + @Schema(description = "文件附件", example = "yudaoyuanma.png") + private String path; + +} diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java index 8ba0fba7d..78c1154c1 100644 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java +++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java @@ -21,4 +21,11 @@ public interface ProductSpuApi { */ List getSpuList(Collection ids); + /** + * 获得 SPU + * + * @return SPU + */ + ProductSpuRespDTO getSpu(Long id); + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java index 6823e0a57..5803c097a 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java @@ -5,6 +5,8 @@ import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -24,15 +26,19 @@ import java.util.List; public class ProductSpuApiImpl implements ProductSpuApi { @Resource - private ProductSpuMapper productSpuMapper; + private ProductSpuService spuService; @Override - public List getSpuList(Collection spuIds) { - if (CollectionUtil.isEmpty(spuIds)) { + public List getSpuList(Collection ids) { + if (CollectionUtil.isEmpty(ids)) { return Collections.emptyList(); } - List productSpuDOList = productSpuMapper.selectBatchIds(spuIds); - return ProductSpuConvert.INSTANCE.convertList2(productSpuDOList); + return ProductSpuConvert.INSTANCE.convertList2(spuService.getSpuList(ids)); + } + + @Override + public ProductSpuRespDTO getSpu(Long id) { + return ProductSpuConvert.INSTANCE.convert02(spuService.getSpu(id)); } } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java index 874b5673e..6d52e5cad 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java @@ -64,6 +64,8 @@ public interface ProductSpuConvert { ProductSpuDetailRespVO convert03(ProductSpuDO spu); + ProductSpuRespDTO convert02(ProductSpuDO bean); + // ========== 用户 App 相关 ========== PageResult convertPageForGetSpuPage(PageResult page); diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java index 8770045e9..6668cd268 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java @@ -50,14 +50,11 @@ public interface ErrorCodeConstants { ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改"); ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除"); ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭"); - ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1013008006, "秒杀活动已结束,不能关闭"); // ========== 秒杀时段 1013009000 ========== - ErrorCode SECKILL_TIME_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在"); - ErrorCode SECKILL_TIME_CONFLICTS = new ErrorCode(1013009001, "秒杀时段冲突"); - ErrorCode SECKILL_TIME_EQUAL = new ErrorCode(1013009002, "秒杀时段开始时间和结束时间不能相等"); - ErrorCode SECKILL_START_TIME_BEFORE_END_TIME = new ErrorCode(1013009003, "秒杀时段开始时间不能在结束时间之后"); - ErrorCode SECKILL_TIME_DISABLE = new ErrorCode(1013009004, "秒杀时段已关闭"); + ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在"); + ErrorCode SECKILL_CONFIG_TIME_CONFLICTS = new ErrorCode(1013009001, "秒杀时段冲突"); + ErrorCode SECKILL_CONFIG_DISABLE = new ErrorCode(1013009004, "秒杀时段已关闭"); // ========== 拼团活动 1013010000 ========== ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在"); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/BargainActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/BargainActivityController.java index 673d4dd09..5f7e50a03 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/BargainActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/BargainActivityController.java @@ -1,12 +1,14 @@ package cn.iocoder.yudao.module.promotion.controller.admin.bargain; +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.module.product.api.spu.ProductSpuApi; -import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityCreateReqVO; -import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityPageReqVO; -import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityRespVO; -import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityUpdateReqVO; +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.activity.BargainActivityCreateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.activity.BargainActivityPageReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.activity.BargainActivityRespVO; +import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.activity.BargainActivityUpdateReqVO; import cn.iocoder.yudao.module.promotion.convert.bargain.BargainActivityConvert; import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService; import io.swagger.v3.oas.annotations.Operation; @@ -18,6 +20,8 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; +import java.util.Collections; +import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -31,7 +35,7 @@ public class BargainActivityController { private BargainActivityService activityService; @Resource - private ProductSpuApi spuApi; + private ProductSpuApi productSpuApi; @PostMapping("/create") @Operation(summary = "创建砍价活动") @@ -70,6 +74,19 @@ public class BargainActivityController { @PreAuthorize("@ss.hasPermission('promotion:bargain-activity:query')") public CommonResult> getBargainActivityPage( @Valid BargainActivityPageReqVO pageVO) { + // 查询砍价活动 + PageResult pageResult = activityService.getBargainActivityPage(pageVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty(pageResult.getTotal())); + } + + // 拼接数据 +// List products = activityService.getBargainProductsByActivityIds( +// convertSet(pageResult.getList(), BargainActivityDO::getId)); + List products = Collections.emptyList(); + List spus = productSpuApi.getSpuList( + convertSet(pageResult.getList(), BargainActivityDO::getSpuId)); + return success(BargainActivityConvert.INSTANCE.convertPage(pageResult, products, spus)); return success(BargainActivityConvert.INSTANCE.convertPage(activityService.getBargainActivityPage(pageVO))); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/vo/BargainActivityBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/vo/BargainActivityBaseVO.java index ec969c2c3..7387ae4cf 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/vo/BargainActivityBaseVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/vo/BargainActivityBaseVO.java @@ -22,7 +22,7 @@ public class BargainActivityBaseVO { @NotNull(message = "砍价名称不能为空") private String name; - @Schema(description = "商品 SPU 编号,关联 ProductSpuDO 的 id", example = "[1,2,3]") + @Schema(description = "商品 SPU 编号", example = "1") @NotNull(message = "砍价商品不能为空") private Long spuId; diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/vo/BargainActivityCreateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/vo/BargainActivityCreateReqVO.java deleted file mode 100644 index f49b489ea..000000000 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/vo/BargainActivityCreateReqVO.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.promotion.controller.admin.bargain.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 BargainActivityCreateReqVO extends BargainActivityBaseVO { - -} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java index ba0c6ec2c..28dd326e0 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java @@ -1,8 +1,10 @@ package cn.iocoder.yudao.module.promotion.controller.admin.combination; +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.module.product.api.spu.ProductSpuApi; +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityRespVO; @@ -21,7 +23,6 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; import java.util.List; -import java.util.Set; import static cn.hutool.core.collection.CollectionUtil.newArrayList; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -37,7 +38,7 @@ public class CombinationActivityController { private CombinationActivityService combinationActivityService; @Resource - private ProductSpuApi spuApi; + private ProductSpuApi productSpuApi; @PostMapping("/create") @Operation(summary = "创建拼团活动") @@ -80,12 +81,16 @@ public class CombinationActivityController { @Valid CombinationActivityPageReqVO pageVO) { // 查询拼团活动 PageResult pageResult = combinationActivityService.getCombinationActivityPage(pageVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty(pageResult.getTotal())); + } + // 拼接数据 - Set activityIds = convertSet(pageResult.getList(), CombinationActivityDO::getId); - Set spuIds = convertSet(pageResult.getList(), CombinationActivityDO::getSpuId); - return success(CombinationActivityConvert.INSTANCE.convertPage(pageResult, - combinationActivityService.getCombinationProductsByActivityIds(activityIds), - spuApi.getSpuList(spuIds))); + List products = combinationActivityService.getCombinationProductsByActivityIds( + convertSet(pageResult.getList(), CombinationActivityDO::getId)); + List spus = productSpuApi.getSpuList( + convertSet(pageResult.getList(), CombinationActivityDO::getSpuId)); + return success(CombinationActivityConvert.INSTANCE.convertPage(pageResult, products, spus)); } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityBaseVO.java index e593a2a47..634e3ae2e 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityBaseVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityBaseVO.java @@ -22,7 +22,7 @@ public class CombinationActivityBaseVO { @NotNull(message = "拼团名称不能为空") private String name; - @Schema(description = "商品 SPU 编号,关联 ProductSpuDO 的 id", example = "[1,2,3]") + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "拼团商品不能为空") private Long spuId; @@ -48,7 +48,7 @@ public class CombinationActivityBaseVO { @NotNull(message = "开团人数不能为空") private Integer userSize; - @Schema(description = "限制时长(小时)", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "限制时长(小时)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") @NotNull(message = "限制时长不能为空") private Integer limitDuration; diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityCreateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityCreateReqVO.java index ea7879e4e..dff1a6cdb 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityCreateReqVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityCreateReqVO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity; -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductCreateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -17,6 +17,6 @@ public class CombinationActivityCreateReqVO extends CombinationActivityBaseVO { @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED) @Valid - private List products; + private List products; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java index eea1f624d..267695250 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java @@ -17,40 +17,34 @@ import java.util.List; @ToString(callSuper = true) public class CombinationActivityRespVO extends CombinationActivityBaseVO { - @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618大促") + @Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22901") + private Long id; + + @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618 大促") private String spuName; @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") private String picUrl; - @Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22901") - private Long id; - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; - @Schema(description = "开团人数", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "开团人数不能为空") + @Schema(description = "开团人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") private Integer userSize; - @Schema(description = "开团组数", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "开团组数不能为空") - private Integer totalNum; + @Schema(description = "开团组数", requiredMode = Schema.RequiredMode.REQUIRED, example = "33") + private Integer totalCount; - @Schema(description = "成团组数", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "成团组数不能为空") - private Integer successNum; + @Schema(description = "成团组数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") + private Integer successCount; - @Schema(description = "虚拟成团", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "虚拟成团不能为空") + @Schema(description = "虚拟成团", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") private Integer virtualGroup; @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - @NotNull(message = "活动状态不能为空") private Integer status; @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED) - @Valid private List products; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityUpdateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityUpdateReqVO.java index c4f8cf0c3..f4483cee1 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityUpdateReqVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityUpdateReqVO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity; -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -22,6 +22,6 @@ public class CombinationActivityUpdateReqVO extends CombinationActivityBaseVO { @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED) @Valid - private List products; + private List products; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductBaseVO.java index fac9cddd0..452fb38ff 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductBaseVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductBaseVO.java @@ -21,7 +21,7 @@ public class CombinationProductBaseVO { private Long skuId; @Schema(description = "拼团价格,单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "27682") - @NotNull(message = "拼团价格,单位分不能为空") - private Integer activePrice; + @NotNull(message = "拼团价格不能为空") + private Integer combinationPrice; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductCreateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductCreateReqVO.java deleted file mode 100644 index ee805bccc..000000000 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductCreateReqVO.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product; - -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 CombinationProductCreateReqVO extends CombinationProductBaseVO { - -} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductUpdateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductUpdateReqVO.java deleted file mode 100644 index 5fab798da..000000000 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductUpdateReqVO.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product; - -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 CombinationProductUpdateReqVO extends CombinationProductBaseVO { - -} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java index 1bc015bf5..df2af1af8 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.promotion.controller.admin.seckill; +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.module.product.api.spu.ProductSpuApi; @@ -8,7 +9,7 @@ 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 cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -19,7 +20,6 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; import java.util.List; -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; @@ -33,7 +33,7 @@ public class SeckillActivityController { @Resource private SeckillActivityService seckillActivityService; @Resource - private ProductSpuApi spuApi; + private ProductSpuApi productSpuApi; @PostMapping("/create") @Operation(summary = "创建秒杀活动") @@ -73,21 +73,27 @@ public class SeckillActivityController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')") public CommonResult getSeckillActivity(@RequestParam("id") Long id) { - SeckillActivityDO seckillActivity = seckillActivityService.getSeckillActivity(id); - List seckillProducts = seckillActivityService.getSeckillProductListByActivityId(id); - return success(SeckillActivityConvert.INSTANCE.convert(seckillActivity, seckillProducts)); + SeckillActivityDO activity = seckillActivityService.getSeckillActivity(id); + List products = seckillActivityService.getSeckillProductListByActivityId(id); + return success(SeckillActivityConvert.INSTANCE.convert(activity, products)); } @GetMapping("/page") @Operation(summary = "获得秒杀活动分页") @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')") public CommonResult> getSeckillActivityPage(@Valid SeckillActivityPageReqVO pageVO) { + // 查询活动列表 PageResult pageResult = seckillActivityService.getSeckillActivityPage(pageVO); - Set aIds = convertSet(pageResult.getList(), SeckillActivityDO::getId); - List seckillProducts = seckillActivityService.getSeckillProductListByActivityId(aIds); - Set spuIds = convertSet(pageResult.getList(), SeckillActivityDO::getSpuId); - List spuList = spuApi.getSpuList(spuIds); - return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, seckillProducts, spuList)); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty(pageResult.getTotal())); + } + + // 拼接数据 + List products = seckillActivityService.getSeckillProductListByActivityId( + convertSet(pageResult.getList(), SeckillActivityDO::getId)); + List spuList = productSpuApi.getSpuList( + convertSet(pageResult.getList(), SeckillActivityDO::getSpuId)); + return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, products, spuList)); } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java index c6e3c5693..a8a793c77 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java @@ -6,7 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.*; import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillConfigConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO; -import cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig.SeckillConfigService; +import cn.iocoder.yudao.module.promotion.service.seckill.SeckillConfigService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -92,4 +92,5 @@ public class SeckillConfigController { PageResult pageResult = seckillConfigService.getSeckillConfigPage(pageVO); return success(SeckillConfigConvert.INSTANCE.convertPage(pageResult)); } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java index 504d4a057..8aada5a1f 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java @@ -20,7 +20,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @Data public class SeckillActivityBaseVO { - @Schema(description = "秒杀活动商品id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[121,1212]") + @Schema(description = "秒杀活动商品 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[121,1212]") @NotNull(message = "秒杀活动商品不能为空") private Long spuId; diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityCreateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityCreateReqVO.java index 46a58b565..9b6e7291a 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityCreateReqVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityCreateReqVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity; -import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductCreateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -16,6 +16,6 @@ import java.util.List; public class SeckillActivityCreateReqVO extends SeckillActivityBaseVO { @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED) - private List products; + private List products; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java index ad78a9464..84cb92db3 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java @@ -21,28 +21,28 @@ public class SeckillActivityRespVO extends SeckillActivityBaseVO { @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") private String picUrl; - @Schema(description = "秒杀活动id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @Schema(description = "秒杀活动 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long id; @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED) private List products; - @Schema(description = "活动状态 开启:0 禁用:1", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") private Integer status; @Schema(description = "订单实付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "22354") private Integer totalPrice; - @Schema(description = "秒杀库存", example = "10") + @Schema(description = "秒杀库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") private Integer stock; - @Schema(description = "秒杀总库存", example = "20") + @Schema(description = "秒杀总库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") private Integer totalStock; - @Schema(description = "新增订单数", example = "20") + @Schema(description = "新增订单数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") private Integer orderCount; - @Schema(description = "付款人数", example = "20") + @Schema(description = "付款人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") private Integer userCount; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityUpdateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityUpdateReqVO.java index 3fdf4ed6e..bf2ca35bb 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityUpdateReqVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityUpdateReqVO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity; -import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductUpdateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -18,6 +18,6 @@ public class SeckillActivityUpdateReqVO extends SeckillActivityBaseVO { private Long id; @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED) - private List products; + private List products; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java index a11d78930..6584b79cb 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java @@ -22,7 +22,7 @@ public class SeckillProductBaseVO { @NotNull(message = "秒杀金额,单位:分不能为空") private Integer seckillPrice; - @Schema(description = "秒杀库存", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "秒杀库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") @NotNull(message = "秒杀库存不能为空") private Integer stock; diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductCreateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductCreateReqVO.java deleted file mode 100644 index 8ee4884ea..000000000 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductCreateReqVO.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product; - -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 SeckillProductCreateReqVO extends SeckillProductBaseVO { - -} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductUpdateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductUpdateReqVO.java deleted file mode 100644 index 5fdccf8d0..000000000 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductUpdateReqVO.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product; - -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 SeckillProductUpdateReqVO extends SeckillProductBaseVO { - -} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationActivityDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationActivityDO.java index 512d64b07..84ce8fdc1 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationActivityDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationActivityDO.java @@ -62,11 +62,11 @@ public class CombinationActivityDO extends BaseDO { /** * 开团组数 */ - private Integer totalNum; + private Integer totalCount; /** * 成团组数 */ - private Integer successNum; + private Integer successCount; /** * 参与人数 */ @@ -76,7 +76,7 @@ public class CombinationActivityDO extends BaseDO { */ private Integer virtualGroup; /** - * 活动状态:0开启 1关闭 + * 活动状态 * * 枚举 {@link CommonStatusEnum} */ diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationProductDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationProductDO.java index bebd70bec..d793bb63e 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationProductDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationProductDO.java @@ -40,6 +40,11 @@ public class CombinationProductDO extends BaseDO { * 商品 SKU 编号 */ private Long skuId; + /** + * 拼团价格,单位分 + */ + private Integer combinationPrice; + /** * 拼团商品状态 * @@ -48,15 +53,15 @@ public class CombinationProductDO extends BaseDO { private Integer activityStatus; /** * 活动开始时间点 + * + * 冗余 {@link CombinationActivityDO#getStartTime()} */ private LocalDateTime activityStartTime; /** * 活动结束时间点 + * + * 冗余 {@link CombinationActivityDO#getEndTime()} */ private LocalDateTime activityEndTime; - /** - * 拼团价格,单位分 - */ - private Integer activePrice; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationProductMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationProductMapper.java index 5dded7a16..5d80b6d09 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationProductMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationProductMapper.java @@ -26,7 +26,7 @@ public interface CombinationProductMapper extends BaseMapperX { return selectList(SeckillProductDO::getActivityId, ids); } - default List selectListBySkuIds(Collection skuIds) { - return selectList(SeckillProductDO::getSkuId, skuIds); - } - - default void updateTimeIdsByActivityId(Long id, List timeIds) { - new LambdaUpdateChainWrapper<>(this) - .set(SeckillProductDO::getConfigIds, CollUtil.join(timeIds, ",")) - .eq(SeckillProductDO::getActivityId, id) - .update(); - } - } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java similarity index 100% rename from yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainServiceImpl.java rename to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java index 3f0ae3671..99b87df6c 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java @@ -40,6 +40,14 @@ public interface CombinationActivityService { */ void deleteCombinationActivity(Long id); + /** + * 校验拼团活动是否存在 + * + * @param id 编号 + * @return 拼团活动 + */ + CombinationActivityDO validateCombinationActivityExists(Long id); + /** * 获得拼团活动 * @@ -48,14 +56,6 @@ public interface CombinationActivityService { */ CombinationActivityDO getCombinationActivity(Long id); - /** - * 获得拼团活动列表 - * - * @param ids 编号 - * @return 拼团活动列表 - */ - List getCombinationActivityList(Collection ids); - /** * 获得拼团活动分页 * @@ -67,9 +67,9 @@ public interface CombinationActivityService { /** * 获得拼团活动商品列表 * - * @param ids 拼团活动 ids + * @param activityIds 拼团活动 ids * @return 拼团活动的商品列表 */ - List getCombinationProductsByActivityIds(Collection ids); + List getCombinationProductsByActivityIds(Collection activityIds); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java new file mode 100644 index 000000000..c6a7c8c49 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java @@ -0,0 +1,208 @@ +package cn.iocoder.yudao.module.promotion.service.combination; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.product.api.spu.ProductSpuApi; +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO; +import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO; +import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationActivityMapper; +import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationProductMapper; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +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.framework.common.util.collection.CollectionUtils.filterList; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; +import static java.util.Collections.singletonList; + +/** + * 拼团活动 Service 实现类 + * + * @author HUIHUI + */ +@Service +@Validated +public class CombinationActivityServiceImpl implements CombinationActivityService { + + @Resource + private CombinationActivityMapper combinationActivityMapper; + @Resource + private CombinationProductMapper combinationProductMapper; + + @Resource + private ProductSpuApi productSpuApi; + @Resource + private ProductSkuApi productSkuApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createCombinationActivity(CombinationActivityCreateReqVO createReqVO) { + // 校验商品 SPU 是否存在是否参加的别的活动 + validateProductConflict(createReqVO.getSpuId(), null); + // 校验商品是否存在 + validateProductExists(createReqVO.getSpuId(), createReqVO.getProducts()); + + // 插入拼团活动 + CombinationActivityDO activity = CombinationActivityConvert.INSTANCE.convert(createReqVO) + .setStatus(CommonStatusEnum.ENABLE.getStatus()) + .setTotalCount(0).setSuccessCount(0).setOrderUserCount(0).setVirtualGroup(0); + combinationActivityMapper.insert(activity); + // 插入商品 + List products = CombinationActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), activity); + combinationProductMapper.insertBatch(products); + // 返回 + return activity.getId(); + } + + /** + * 校验拼团商品参与的活动是否存在冲突 + * + * @param spuId 商品 SPU 编号 + * @param activityId 拼团活动编号 + */ + private void validateProductConflict(Long spuId, Long activityId) { + // 查询所有开启的拼团活动 + List activityList = combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus()); + if (activityId != null) { // 时排除自己 + activityList.removeIf(item -> ObjectUtil.equal(item.getId(), activityId)); + } + // 查找是否有其它活动,选择了该产品 + List matchActivityList = filterList(activityList, activity -> ObjectUtil.equal(activity.getId(), spuId)); + if (CollUtil.isNotEmpty(matchActivityList)) { + throw exception(COMBINATION_ACTIVITY_SPU_CONFLICTS); + } + } + + /** + * 校验拼团商品是否都存在 + * + * @param spuId 商品 SPU 编号 + * @param products 秒杀商品 + */ + private void validateProductExists(Long spuId, List products) { + // 1. 校验商品 spu 是否存在 + ProductSpuRespDTO spu = productSpuApi.getSpu(spuId); + if (spu == null) { + throw exception(SPU_NOT_EXISTS); + } + + // 2. 校验商品 sku 都存在 + Map skuMap = convertMap(productSkuApi.getSkuListBySpuId(singletonList(spuId)), + ProductSkuRespDTO::getId); + products.forEach(product -> { + if (!skuMap.containsKey(product.getSkuId())) { + throw exception(SKU_NOT_EXISTS); + } + }); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateCombinationActivity(CombinationActivityUpdateReqVO updateReqVO) { + // 校验存在 + CombinationActivityDO activityDO = validateCombinationActivityExists(updateReqVO.getId()); + // 校验状态 + if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { + throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE); + } + // 校验商品冲突 + validateProductConflict(updateReqVO.getSpuId(), updateReqVO.getId()); + // 校验商品是否存在 + validateProductExists(updateReqVO.getSpuId(), updateReqVO.getProducts()); + + // 更新活动 + CombinationActivityDO updateObj = CombinationActivityConvert.INSTANCE.convert(updateReqVO); + combinationActivityMapper.updateById(updateObj); + // 更新商品 + updateCombinationProduct(updateObj, updateReqVO.getProducts()); + } + + /** + * 更新拼团商品 + * + * @param activity 拼团活动 + * @param products 该活动的最新商品配置 + */ + private void updateCombinationProduct(CombinationActivityDO activity, List products) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List newList = CombinationActivityConvert.INSTANCE.convertList(products, activity); + List oldList = combinationProductMapper.selectListByActivityIds(CollUtil.newArrayList(activity.getId())); + List> diffList = CollectionUtils.diffList(oldList, newList, (oldVal, newVal) -> { + boolean same = ObjectUtil.equal(oldVal.getSkuId(), newVal.getSkuId()); + if (same) { + newVal.setId(oldVal.getId()); + } + return same; + }); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + combinationProductMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + combinationProductMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + combinationProductMapper.deleteBatchIds(CollectionUtils.convertList(diffList.get(2), CombinationProductDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteCombinationActivity(Long id) { + // 校验存在 + CombinationActivityDO activityDO = validateCombinationActivityExists(id); + // 校验状态 + if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) { + throw exception(COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END); + } + + // 删除 + combinationActivityMapper.deleteById(id); + } + + @Override + public CombinationActivityDO validateCombinationActivityExists(Long id) { + CombinationActivityDO activityDO = combinationActivityMapper.selectById(id); + if (activityDO == null) { + throw exception(COMBINATION_ACTIVITY_NOT_EXISTS); + } + return activityDO; + } + + @Override + public CombinationActivityDO getCombinationActivity(Long id) { + return validateCombinationActivityExists(id); + } + + @Override + public PageResult getCombinationActivityPage(CombinationActivityPageReqVO pageReqVO) { + return combinationActivityMapper.selectPage(pageReqVO); + } + + @Override + public List getCombinationProductsByActivityIds(Collection activityIds) { + return combinationProductMapper.selectListByActivityIds(activityIds); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java index 72d68c780..6c12cb551 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java @@ -7,7 +7,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationR import java.util.List; /** - * 商品活动记录 service + * 拼团记录 Service 接口 * * @author HUIHUI */ diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java new file mode 100644 index 000000000..efbc0d1d0 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java @@ -0,0 +1,127 @@ +package cn.iocoder.yudao.module.promotion.service.combination; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO; +import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; +import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper; +import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +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.*; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINATION_RECORD_USER_FULL; + +// TODO 芋艿:等拼团记录做完,完整 review 下 +/** + * 拼团记录 Service 实现类 + * + * @author HUIHUI + */ +@Service +@Validated +public class CombinationRecordServiceImpl implements CombinationRecordService { + + @Resource + private CombinationActivityService combinationActivityService; + + @Resource + private CombinationRecordMapper recordMapper; + + @Override + public void updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO) { + // 校验拼团是否存在 + CombinationRecordDO recordDO = validateCombinationRecord(reqDTO.getUserId(), reqDTO.getOrderId()); + + // 更新状态 + recordDO.setStatus(reqDTO.getStatus()); + recordMapper.updateById(recordDO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO) { + CombinationRecordDO recordDO = validateCombinationRecord(reqDTO.getUserId(), reqDTO.getOrderId()); + // 更新状态 + recordDO.setStatus(reqDTO.getStatus()); + // 更新开始时间 + recordDO.setStartTime(reqDTO.getStartTime()); + recordMapper.updateById(recordDO); + + // 更新拼团参入人数 + List recordDOs = recordMapper.selectListByHeadIdAndStatus(recordDO.getHeadId(), reqDTO.getStatus()); + if (CollUtil.isNotEmpty(recordDOs)) { + recordDOs.forEach(item -> { + item.setUserCount(recordDOs.size()); + // 校验拼团是否满足要求 + if (ObjectUtil.equal(recordDOs.size(), recordDO.getUserSize())) { + item.setStatus(CombinationRecordStatusEnum.SUCCESS.getStatus()); + } + }); + } + recordMapper.updateBatch(recordDOs); + } + + private CombinationRecordDO validateCombinationRecord(Long userId, Long orderId) { + // 校验拼团是否存在 + CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(userId, orderId); + if (recordDO == null) { + throw exception(COMBINATION_RECORD_NOT_EXISTS); + } + return recordDO; + } + + @Override + public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { + // 1.1 校验拼团活动 + CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(reqDTO.getActivityId()); + // 1.2 需要校验下,他当前是不是已经参加了该拼团; + CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(reqDTO.getUserId(), reqDTO.getOrderId()); + if (recordDO != null) { + throw exception(COMBINATION_RECORD_EXISTS); + } + // 1.3 父拼团是否存在,是否已经满了 + if (reqDTO.getHeadId() != null) { + CombinationRecordDO recordDO1 = recordMapper.selectRecordByHeadId(reqDTO.getHeadId(), reqDTO.getActivityId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); + if (recordDO1 == null) { + throw exception(COMBINATION_RECORD_HEAD_NOT_EXISTS); + } + // 校验拼团是否满足要求 + if (ObjectUtil.equal(recordDO1.getUserCount(), recordDO1.getUserSize())) { + throw exception(COMBINATION_RECORD_USER_FULL); + } + } + // TODO @puhui999:应该还有一些校验,后续补噶;例如说,一个团,自己已经参与进去了,不能再参与进去; + + // 2. 创建拼团记录 + CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO); + record.setVirtualGroup(false); + // TODO @puhui999:过期时间,应该是 Date 哈; + record.setExpireTime(activity.getLimitDuration()); + record.setUserSize(activity.getUserSize()); + recordMapper.insert(record); + } + + @Override + public CombinationRecordDO getCombinationRecord(Long userId, Long orderId) { + return validateCombinationRecord(userId, orderId); + } + + /** + * APP 端获取开团记录 + * + * @return 开团记录 + */ + public List getRecordListByStatus(Integer status) { + return recordMapper.selectListByStatus(status); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java similarity index 85% rename from yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityService.java rename to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java index 4096f0087..2e33a944d 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity; +package cn.iocoder.yudao.module.promotion.service.seckill; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; @@ -55,14 +55,6 @@ public interface SeckillActivityService { */ SeckillActivityDO getSeckillActivity(Long id); - /** - * 获得秒杀活动列表 - * - * @param ids 编号 - * @return 秒杀活动列表 - */ - List getSeckillActivityList(Collection ids); - /** * 获得秒杀活动分页 * @@ -74,17 +66,17 @@ public interface SeckillActivityService { /** * 通过活动编号获取活动商品 * - * @param id 活动编号 + * @param activityId 活动编号 * @return 活动商品列表 */ - List getSeckillProductListByActivityId(Long id); + List getSeckillProductListByActivityId(Long activityId); /** * 通过活动编号获取活动商品 * - * @param ids 活动编号 + * @param activityIds 活动编号 * @return 活动商品列表 */ - List getSeckillProductListByActivityId(Collection ids); + List getSeckillProductListByActivityId(Collection activityIds); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java similarity index 70% rename from yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java rename to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java index 72f985656..a3577a50b 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java @@ -1,6 +1,5 @@ -package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity; +package cn.iocoder.yudao.module.promotion.service.seckill; -import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -11,14 +10,12 @@ import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; 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.controller.admin.seckill.vo.product.SeckillProductCreateReqVO; -import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductUpdateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO; 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.service.seckill.seckillconfig.SeckillConfigService; import cn.iocoder.yudao.module.promotion.util.PromotionUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -27,7 +24,7 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.Collection; import java.util.List; -import java.util.Set; +import java.util.Map; import static cn.hutool.core.collection.CollUtil.isNotEmpty; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -35,7 +32,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; -import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuAllExists; +import static java.util.Collections.singletonList; /** * 秒杀活动 Service 实现类 @@ -60,19 +57,15 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @Override @Transactional(rollbackFor = Exception.class) public Long createSeckillActivity(SeckillActivityCreateReqVO createReqVO) { - // 校验商品秒秒杀时段是否冲突 - validateProductSpuSeckillConflict(createReqVO.getConfigIds(), createReqVO.getSpuId(), null); - // 获取所选 spu 下的所有 sku - List skus = productSkuApi.getSkuListBySpuId(CollUtil.newArrayList(createReqVO.getSpuId())); - // 校验商品 sku 是否存在 - if (skus.size() != createReqVO.getProducts().size()) { - throw exception(SKU_NOT_EXISTS); - } + // 校验商品秒杀时段是否冲突 + validateProductConflict(createReqVO.getConfigIds(), createReqVO.getSpuId(), null); + // 校验商品是否存在 + validateProductExists(createReqVO.getSpuId(), createReqVO.getProducts()); // 插入秒杀活动 SeckillActivityDO activity = SeckillActivityConvert.INSTANCE.convert(createReqVO) .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime())) - .setTotalStock(getSumValue(createReqVO.getProducts(), SeckillProductCreateReqVO::getStock, Integer::sum)); + .setTotalStock(getSumValue(createReqVO.getProducts(), SeckillProductBaseVO::getStock, Integer::sum)); seckillActivityMapper.insert(activity); // 插入商品 List products = SeckillActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), activity); @@ -80,35 +73,61 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { return activity.getId(); } - private void validateProductSpuSeckillConflict(List configIds, Long spuId, Long activityId) { - // 校验秒杀时段是否存在 + /** + * 校验秒杀商品参与的活动是否存在冲突 + * + * 1. 校验秒杀时段是否存在 + * 2. 秒杀商品是否参加其它活动 + * + * @param configIds 秒杀时段数组 + * @param spuId 商品 SPU 编号 + * @param activityId 秒杀活动编号 + */ + private void validateProductConflict(List configIds, Long spuId, Long activityId) { + // 1. 校验秒杀时段是否存在 seckillConfigService.validateSeckillConfigExists(configIds); - // 校验商品 spu 是否存在 - List spuList = productSpuApi.getSpuList(CollUtil.newArrayList(spuId)); - if (CollUtil.isEmpty(spuList)) { - throw exception(SPU_NOT_EXISTS); + + // 2.1 查询所有开启的秒杀活动 + List activityList = seckillActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus()); + if (activityId != null) { // 排除自己 + activityList.removeIf(item -> ObjectUtil.equal(item.getId(), activityId)); } - // 查询所有开启的秒杀活动 - List activityDOs = seckillActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus()); - if (activityId != null) { - // 更新时移除本活动 - activityDOs.removeIf(item -> ObjectUtil.equal(item.getId(), activityId)); - } - // 过滤出所有 spuId 有交集的活动 - List activityDOs1 = convertList(activityDOs, c -> c, s -> ObjectUtil.equal(s.getSpuId(), spuId)); + // TODO @puhui999:一个 spu,参与两个活动应该没关系,关键是活动时间不充能重叠; + // 2.2 过滤出所有 spuId 有交集的活动,判断是否存在重叠 + List activityDOs1 = filterList(activityList, s -> ObjectUtil.equal(s.getSpuId(), spuId)); if (isNotEmpty(activityDOs1)) { throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS); } - List activityDOs2 = convertList(activityDOs, c -> c, s -> { - // 判断秒杀时段是否有交集 - return containsAny(s.getConfigIds(), configIds); - }); - + // 2.3 过滤出所有 configIds 有交集的活动,判断是否存在重叠 + List activityDOs2 = filterList(activityList, s -> containsAny(s.getConfigIds(), configIds)); if (isNotEmpty(activityDOs2)) { - throw exception(SECKILL_TIME_CONFLICTS); + throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS); } } + /** + * 校验秒杀商品是否都存在 + * + * @param spuId 商品 SPU 编号 + * @param products 秒杀商品 + */ + private void validateProductExists(Long spuId, List products) { + // 1. 校验商品 spu 是否存在 + ProductSpuRespDTO spu = productSpuApi.getSpu(spuId); + if (spu == null) { + throw exception(SPU_NOT_EXISTS); + } + + // 2. 校验商品 sku 都存在 + Map skuMap = convertMap(productSkuApi.getSkuListBySpuId(singletonList(spuId)), + ProductSkuRespDTO::getId); + products.forEach(product -> { + if (!skuMap.containsKey(product.getSkuId())) { + throw exception(SKU_NOT_EXISTS); + } + }); + } + @Override @Transactional(rollbackFor = Exception.class) public void updateSeckillActivity(SeckillActivityUpdateReqVO updateReqVO) { @@ -118,29 +137,26 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { throw exception(SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED); } // 校验商品是否冲突 - validateProductSpuSeckillConflict(updateReqVO.getConfigIds(), updateReqVO.getSpuId(), updateReqVO.getId()); - // 获取所选 spu下的所有 sku - List skus = productSkuApi.getSkuListBySpuId(CollUtil.newArrayList(updateReqVO.getSpuId())); - // 校验商品 sku 是否存在 - validateProductSkuAllExists(skus, updateReqVO.getProducts(), SeckillProductUpdateReqVO::getSkuId); + validateProductConflict(updateReqVO.getConfigIds(), updateReqVO.getSpuId(), updateReqVO.getId()); + // 校验商品是否存在 + validateProductExists(updateReqVO.getSpuId(), updateReqVO.getProducts()); // 更新活动 SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO) .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getEndTime())) - .setTotalStock(getSumValue(updateReqVO.getProducts(), SeckillProductUpdateReqVO::getStock, Integer::sum)); + .setTotalStock(getSumValue(updateReqVO.getProducts(), SeckillProductBaseVO::getStock, Integer::sum)); seckillActivityMapper.updateById(updateObj); // 更新商品 updateSeckillProduct(updateObj, updateReqVO.getProducts()); } - /** * 更新秒杀商品 * * @param activity 秒杀活动 * @param products 该活动的最新商品配置 */ - private void updateSeckillProduct(SeckillActivityDO activity, List products) { + private void updateSeckillProduct(SeckillActivityDO activity, List products) { // 第一步,对比新老数据,获得添加、修改、删除的列表 List newList = SeckillActivityConvert.INSTANCE.convertList(products, activity); List oldList = seckillProductMapper.selectListByActivityId(activity.getId()); @@ -159,7 +175,6 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { if (isNotEmpty(diffList.get(1))) { seckillProductMapper.updateBatch(diffList.get(1)); } - // delete if (isNotEmpty(diffList.get(2))) { seckillProductMapper.deleteBatchIds(convertList(diffList.get(2), SeckillProductDO::getId)); } @@ -167,7 +182,6 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @Override public void closeSeckillActivity(Long id) { - // TODO 待验证没使用过 // 校验存在 SeckillActivityDO activity = validateSeckillActivityExists(id); if (CommonStatusEnum.DISABLE.getStatus().equals(activity.getStatus())) { @@ -191,9 +205,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { // 删除活动 seckillActivityMapper.deleteById(id); // 删除活动商品 - List productDOs = seckillProductMapper.selectListByActivityId(id); - Set convertSet = convertSet(productDOs, SeckillProductDO::getSkuId); - seckillProductMapper.deleteBatchIds(convertSet); + List products = seckillProductMapper.selectListByActivityId(id); + seckillProductMapper.deleteBatchIds(convertSet(products, SeckillProductDO::getId)); } private SeckillActivityDO validateSeckillActivityExists(Long id) { @@ -209,24 +222,19 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { return validateSeckillActivityExists(id); } - @Override - public List getSeckillActivityList(Collection ids) { - return seckillActivityMapper.selectBatchIds(ids); - } - @Override public PageResult getSeckillActivityPage(SeckillActivityPageReqVO pageReqVO) { return seckillActivityMapper.selectPage(pageReqVO); } @Override - public List getSeckillProductListByActivityId(Long id) { - return seckillProductMapper.selectListByActivityId(id); + public List getSeckillProductListByActivityId(Long activityId) { + return seckillProductMapper.selectListByActivityId(activityId); } @Override - public List getSeckillProductListByActivityId(Collection ids) { - return seckillProductMapper.selectListByActivityId(ids); + public List getSeckillProductListByActivityId(Collection activityIds) { + return seckillProductMapper.selectListByActivityId(activityIds); } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillConfigService.java similarity index 92% rename from yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigService.java rename to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillConfigService.java index e8cbce199..5cbf4fd32 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillConfigService.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig; +package cn.iocoder.yudao.module.promotion.service.seckill; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO; @@ -57,10 +57,9 @@ public interface SeckillConfigService { /** * 校验秒杀时段是否存在 * - * @param timeIds 秒杀时段id集合 + * @param ids 秒杀时段 id 集合 */ - void validateSeckillConfigExists(Collection timeIds); - + void validateSeckillConfigExists(Collection ids); /** * 获得秒杀时间段配置分页数据 @@ -85,4 +84,5 @@ public interface SeckillConfigService { * @param status 状态 */ void updateSeckillConfigStatus(Long id, Integer status); + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillConfigServiceImpl.java similarity index 63% rename from yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigServiceImpl.java rename to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillConfigServiceImpl.java index 4ba3b26a5..ce2171079 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillConfigServiceImpl.java @@ -1,10 +1,9 @@ -package cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig; +package cn.iocoder.yudao.module.promotion.service.seckill; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 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.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigPageReqVO; @@ -13,7 +12,6 @@ import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillCo import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO; import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillconfig.SeckillConfigMapper; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; @@ -37,7 +35,6 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { private SeckillConfigMapper seckillConfigMapper; @Override - @Transactional(rollbackFor = Exception.class) public Long createSeckillConfig(SeckillConfigCreateReqVO createReqVO) { // 校验时间段是否冲突 validateSeckillConfigConflict(createReqVO.getStartTime(), createReqVO.getEndTime(), null); @@ -50,7 +47,6 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { } @Override - @Transactional(rollbackFor = Exception.class) public void updateSeckillConfig(SeckillConfigUpdateReqVO updateReqVO) { // 校验存在 validateSeckillConfigExists(updateReqVO.getId()); @@ -72,7 +68,6 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { } @Override - @Transactional(rollbackFor = Exception.class) public void deleteSeckillConfig(Long id) { // 校验存在 validateSeckillConfigExists(id); @@ -83,35 +78,31 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { private void validateSeckillConfigExists(Long id) { if (seckillConfigMapper.selectById(id) == null) { - throw exception(SECKILL_TIME_NOT_EXISTS); + throw exception(SECKILL_CONFIG_NOT_EXISTS); } } /** * 校验时间是否存在冲突 * - * @param startTime 开始时间 - * @param endTime 结束时间 + * @param startTimeStr 开始时间 + * @param endTimeStr 结束时间 */ - private void validateSeckillConfigConflict(String startTime, String endTime, Long seckillConfigId) { - LocalTime startTime1 = LocalTime.parse(startTime); - LocalTime endTime1 = LocalTime.parse(endTime); - // 查询出所有的时段配置 - List configDOs = seckillConfigMapper.selectList(); + private void validateSeckillConfigConflict(String startTimeStr, String endTimeStr, Long id) { + // 1. 查询出所有的时段配置 + LocalTime startTime = LocalTime.parse(startTimeStr); + LocalTime endTime = LocalTime.parse(endTimeStr); + List configs = seckillConfigMapper.selectList(); // 更新时排除自己 - if (seckillConfigId != null) { - configDOs.removeIf(item -> ObjectUtil.equal(item.getId(), seckillConfigId)); + if (id != null) { + configs.removeIf(item -> ObjectUtil.equal(item.getId(), id)); } - // 过滤出重叠的时段 ids - boolean hasConflict = configDOs.stream().anyMatch(config -> { - LocalTime startTime2 = LocalTime.parse(config.getStartTime()); - LocalTime endTime2 = LocalTime.parse(config.getEndTime()); - // 判断时间是否重叠 - return LocalDateTimeUtils.isOverlap(startTime1, endTime1, startTime2, endTime2); - }); + // 2. 判断是否有重叠的时间 + boolean hasConflict = configs.stream().anyMatch(config -> LocalDateTimeUtils.isOverlap(startTime, endTime, + LocalTime.parse(config.getStartTime()), LocalTime.parse(config.getEndTime()))); if (hasConflict) { - throw exception(SECKILL_TIME_CONFLICTS); + throw exception(SECKILL_CONFIG_TIME_CONFLICTS); } } @@ -127,22 +118,22 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { } @Override - public void validateSeckillConfigExists(Collection configIds) { - if (CollUtil.isEmpty(configIds)) { - throw exception(SECKILL_TIME_NOT_EXISTS); + public void validateSeckillConfigExists(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return; } - List configDOs = seckillConfigMapper.selectBatchIds(configIds); - if (CollUtil.isEmpty(configDOs)) { - throw exception(SECKILL_TIME_NOT_EXISTS); - } - // 过滤出关闭的时段 - List filterList = CollectionUtils.filterList(configDOs, item -> ObjectUtil.equal(item.getStatus(), CommonStatusEnum.DISABLE.getStatus())); - if (CollUtil.isNotEmpty(filterList)) { - throw exception(SECKILL_TIME_DISABLE); - } - if (configDOs.size() != configIds.size()) { - throw exception(SECKILL_TIME_NOT_EXISTS); + // 1. 如果有数量不匹配,说明有不存在的,则抛出 SECKILL_CONFIG_NOT_EXISTS 业务异常 + List configs = seckillConfigMapper.selectBatchIds(ids); + if (configs.size() != ids.size()) { + throw exception(SECKILL_CONFIG_NOT_EXISTS); } + + // 2. 如果存在关闭,则抛出 SECKILL_CONFIG_DISABLE 业务异常 + configs.forEach(config -> { + if (ObjectUtil.equal(config.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { + throw exception(SECKILL_CONFIG_DISABLE); + } + }); } @Override diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillactivity/SeckillActivityServiceImplTest.java b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillactivity/SeckillActivityServiceImplTest.java index e24c9d3ce..ab34f7d8f 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillactivity/SeckillActivityServiceImplTest.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillactivity/SeckillActivityServiceImplTest.java @@ -7,7 +7,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.Se import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper; -import cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity.SeckillActivityServiceImpl; +import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityServiceImpl; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillconfig/SeckillConfigServiceImplTest.java b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillconfig/SeckillConfigServiceImplTest.java index d6d5e90df..80f477444 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillconfig/SeckillConfigServiceImplTest.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillconfig/SeckillConfigServiceImplTest.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.Seck import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigUpdateReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO; import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillconfig.SeckillConfigMapper; -import cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig.SeckillConfigServiceImpl; +import cn.iocoder.yudao.module.promotion.service.seckill.SeckillConfigServiceImpl; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Disabled; @@ -19,7 +19,7 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEq import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_TIME_NOT_EXISTS; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_CONFIG_NOT_EXISTS; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; @@ -94,7 +94,7 @@ public class SeckillConfigServiceImplTest extends BaseDbUnitTest { SeckillConfigUpdateReqVO reqVO = randomPojo(SeckillConfigUpdateReqVO.class); // 调用, 并断言异常 - assertServiceException(() -> SeckillConfigService.updateSeckillConfig(reqVO), SECKILL_TIME_NOT_EXISTS); + assertServiceException(() -> SeckillConfigService.updateSeckillConfig(reqVO), SECKILL_CONFIG_NOT_EXISTS); } @Test @@ -117,7 +117,7 @@ public class SeckillConfigServiceImplTest extends BaseDbUnitTest { Long id = randomLongId(); // 调用, 并断言异常 - assertServiceException(() -> SeckillConfigService.deleteSeckillConfig(id), SECKILL_TIME_NOT_EXISTS); + assertServiceException(() -> SeckillConfigService.deleteSeckillConfig(id), SECKILL_CONFIG_NOT_EXISTS); } @Test diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderDeliveryStatusEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderDeliveryStatusEnum.java deleted file mode 100644 index 27b061e37..000000000 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderDeliveryStatusEnum.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.trade.enums.order; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -/** - * 交易订单 - 发货状态 - * - * @author 芋道源码 - */ -@RequiredArgsConstructor -@Getter -public enum TradeOrderDeliveryStatusEnum { - - UNDELIVERED(0, "未发货"), - DELIVERED(1, "已发货"), - RECEIVED(2, "已收货"); - - /** - * 状态值 - */ - private final Integer status; - /** - * 状态名 - */ - private final String name; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java index c20742a67..2077c5a41 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java @@ -10,10 +10,12 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.*; import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO; import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; +import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; import cn.iocoder.yudao.module.trade.service.order.TradeOrderService; import com.google.common.collect.Maps; import io.swagger.v3.oas.annotations.Operation; @@ -42,8 +44,12 @@ public class AppTradeOrderController { @Resource private TradeOrderService tradeOrderService; + @Resource + private DeliveryExpressService deliveryExpressService; + @Resource private ProductPropertyValueApi productPropertyValueApi; + @Resource private TradeOrderProperties tradeOrderProperties; @@ -76,14 +82,21 @@ public class AppTradeOrderController { public CommonResult getOrder(@RequestParam("id") Long id) { // 查询订单 TradeOrderDO order = tradeOrderService.getOrder(getLoginUserId(), id); + if (order == null) { + return success(null); + } + // 查询订单项 List orderItems = tradeOrderService.getOrderItemListByOrderId(order.getId()); // 查询商品属性 List propertyValueDetails = productPropertyValueApi .getPropertyValueDetailList(TradeOrderConvert.INSTANCE.convertPropertyValueIds(orderItems)); + // 查询物流公司 + DeliveryExpressDO express = order.getLogisticsId() != null && order.getLogisticsId() > 0 ? + deliveryExpressService.getDeliveryExpress(order.getLogisticsId()) : null; // 最终组合 return success(TradeOrderConvert.INSTANCE.convert02(order, orderItems, - propertyValueDetails, tradeOrderProperties)); + propertyValueDetails, tradeOrderProperties, express)); } @GetMapping("/page") @@ -122,7 +135,7 @@ public class AppTradeOrderController { return success(orderCount); } - @PutMapping("/take") + @PutMapping("/receive") @Operation(summary = "确认交易订单收货") @Parameter(name = "id", description = "交易订单编号") public CommonResult takeOrder(@RequestParam("id") Long id) { diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java index 7a67190fc..9b417ee74 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java @@ -80,6 +80,12 @@ public class AppTradeOrderDetailRespVO { @Schema(description = "配送方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Integer deliveryType; + @Schema(description = "发货物流公司编号", example = "10") + private Long logisticsId; + + @Schema(description = "发货物流名称", example = "顺丰快递") + private String logisticsName; + @Schema(description = "发货物流单号", example = "1024") private String logisticsNo; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/item/AppTradeOrderItemCommentCreateReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/item/AppTradeOrderItemCommentCreateReqVO.java index 69ffef241..a6a8b9582 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/item/AppTradeOrderItemCommentCreateReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/item/AppTradeOrderItemCommentCreateReqVO.java @@ -35,5 +35,4 @@ public class AppTradeOrderItemCommentCreateReqVO { @Size(max = 9, message = "评论图片地址数组长度不能超过 9 张") private List picUrls; - } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/item/AppTradeOrderItemRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/item/AppTradeOrderItemRespVO.java index 872d47468..49749020a 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/item/AppTradeOrderItemRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/item/AppTradeOrderItemRespVO.java @@ -13,6 +13,9 @@ public class AppTradeOrderItemRespVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long id; + @Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long orderId; + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long spuId; @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") @@ -48,5 +51,5 @@ public class AppTradeOrderItemRespVO { @Schema(description = "售后状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Integer afterSaleStatus; - + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java index 788b8c413..ac0a47ca5 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java @@ -25,6 +25,7 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.*; import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO; import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; @@ -234,7 +235,8 @@ public interface TradeOrderConvert { // TODO 芋艿:可简化 default AppTradeOrderDetailRespVO convert02(TradeOrderDO order, List orderItems, - List propertyValueDetails, TradeOrderProperties tradeOrderProperties) { + List propertyValueDetails, TradeOrderProperties tradeOrderProperties, + DeliveryExpressDO express) { AppTradeOrderDetailRespVO orderVO = convert3(order, orderItems); orderVO.setPayExpireTime(addTime(tradeOrderProperties.getExpireTime())); if (StrUtil.isNotEmpty(order.getPayChannelCode())) { @@ -260,6 +262,9 @@ public interface TradeOrderConvert { } // 处理收货地址 orderVO.setReceiverAreaName(AreaUtils.format(order.getReceiverAreaId())); + if (express != null) { + orderVO.setLogisticsId(express.getId()).setLogisticsName(express.getName()); + } return orderVO; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java index 011e8546f..b9177fb66 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.trade.dal.dataobject.order; import cn.iocoder.yudao.framework.common.enums.TerminalEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO; import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; import cn.iocoder.yudao.module.trade.enums.order.*; @@ -174,18 +175,18 @@ public class TradeOrderDO extends BaseDO { private Integer deliveryType; /** * 发货物流公司编号 + * + * 如果无需发货,则 logisticsId 设置为 0。原因是,不想再添加额外字段 + * + * 关联 {@link DeliveryExpressDO#getId()} */ private Long logisticsId; /** * 发货物流单号 + * + * 如果无需发货,则 logisticsNo 设置 ""。原因是,不想再添加额外字段 */ private String logisticsNo; - /** - * 发货状态 - * - * 枚举 {@link TradeOrderDeliveryStatusEnum} - */ - private Integer deliveryStatus; /** * 发货时间 */ diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java index 0a37021fd..be815a726 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java @@ -233,8 +233,8 @@ public class TradeOrderServiceImpl implements TradeOrderService { order.setTerminal(TerminalEnum.H5.getTerminal()); // todo 数据来源? // 支付信息 order.setAdjustPrice(0).setPayStatus(false); - // 物流信息 TODO 芋艿:暂时写死物流方式;应该是前端选择的 - order.setDeliveryType(createReqVO.getDeliveryType()).setDeliveryStatus(TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus()); + // 物流信息 + order.setDeliveryType(createReqVO.getDeliveryType()); // 退款信息 order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()).setRefundPrice(0); tradeOrderMapper.insert(order); @@ -418,8 +418,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { } // 更新 TradeOrderDO 状态为已发货,等待收货 - updateOrderObj.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()) - .setDeliveryStatus(TradeOrderDeliveryStatusEnum.DELIVERED.getStatus()).setDeliveryTime(LocalDateTime.now()); + updateOrderObj.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()).setDeliveryTime(LocalDateTime.now()); int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), updateOrderObj); if (updateCount == 0) { throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); @@ -428,7 +427,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { // 发送站内信 tradeMessageService.sendMessageWhenDeliveryOrder(new TradeOrderMessageWhenDeliveryOrderReqBO().setOrderId(order.getId()) - .setUserId(userId).setMessage(TradeOrderDeliveryStatusEnum.DELIVERED.getName())); + .setUserId(userId).setMessage(null)); // TODO 芋艿:OrderLog // TODO 设计:lili:是不是发货后,才支持售后? @@ -449,8 +448,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { throw exception(ORDER_NOT_FOUND); } // 校验订单是否是待发货状态 - if (!TradeOrderStatusEnum.isUndelivered(order.getStatus()) - || ObjectUtil.notEqual(order.getDeliveryStatus(), TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus())) { + if (!TradeOrderStatusEnum.isUndelivered(order.getStatus())) { throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); } // 校验订单是否退款 @@ -482,8 +480,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { // 更新 TradeOrderDO 状态为已完成 int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), - new TradeOrderDO().setStatus(TradeOrderStatusEnum.COMPLETED.getStatus()) - .setDeliveryStatus(TradeOrderDeliveryStatusEnum.RECEIVED.getStatus()).setReceiveTime(LocalDateTime.now())); + new TradeOrderDO().setStatus(TradeOrderStatusEnum.COMPLETED.getStatus()).setReceiveTime(LocalDateTime.now())); if (updateCount == 0) { throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); } @@ -495,11 +492,6 @@ public class TradeOrderServiceImpl implements TradeOrderService { return Boolean.TRUE; } - @Override - public TradeOrderDO getOrder(Long id) { - return tradeOrderMapper.selectById(id); - } - /** * 校验交易订单满足可售货的条件 * @@ -516,13 +508,17 @@ public class TradeOrderServiceImpl implements TradeOrderService { throw exception(ORDER_NOT_FOUND); } // 校验订单是否是待收货状态 - if (!TradeOrderStatusEnum.isDelivered(order.getStatus()) - || ObjectUtil.notEqual(order.getDeliveryStatus(), TradeOrderDeliveryStatusEnum.DELIVERED.getStatus())) { + if (!TradeOrderStatusEnum.isDelivered(order.getStatus())) { throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); } return order; } + @Override + public TradeOrderDO getOrder(Long id) { + return tradeOrderMapper.selectById(id); + } + @Override public TradeOrderDO getOrder(Long userId, Long id) { TradeOrderDO order = tradeOrderMapper.selectById(id); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java index 5507f4307..f9dc071dd 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java @@ -177,7 +177,6 @@ public class TradeOrderServiceTest extends BaseDbUnitTest { assertEquals(tradeOrderDO.getPayOrderId(), 1000L); assertNull(tradeOrderDO.getPayChannelCode()); assertNull(tradeOrderDO.getLogisticsId()); - assertEquals(tradeOrderDO.getDeliveryStatus(), TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus()); assertNull(tradeOrderDO.getDeliveryTime()); assertNull(tradeOrderDO.getReceiveTime()); assertEquals(tradeOrderDO.getReceiverName(), "芋艿"); @@ -274,8 +273,7 @@ public class TradeOrderServiceTest extends BaseDbUnitTest { // mock 数据(TradeOrder) TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> { o.setId(1L).setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()); - o.setLogisticsId(null).setLogisticsNo(null).setDeliveryTime(null) - .setDeliveryStatus(TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus()); + o.setLogisticsId(null).setLogisticsNo(null).setDeliveryTime(null); }); tradeOrderMapper.insert(order); // 准备参数 @@ -288,7 +286,6 @@ public class TradeOrderServiceTest extends BaseDbUnitTest { // 断言 TradeOrderDO dbOrder = tradeOrderMapper.selectById(1L); assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.DELIVERED.getStatus()); - assertEquals(dbOrder.getDeliveryStatus(), TradeOrderDeliveryStatusEnum.DELIVERED.getStatus()); assertPojoEquals(dbOrder, deliveryReqVO); assertNotNull(dbOrder.getDeliveryTime()); } @@ -298,7 +295,7 @@ public class TradeOrderServiceTest extends BaseDbUnitTest { // mock 数据(TradeOrder) TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> { o.setId(1L).setUserId(10L).setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()); - o.setDeliveryStatus(TradeOrderDeliveryStatusEnum.DELIVERED.getStatus()).setReceiveTime(null); + o.setReceiveTime(null); }); tradeOrderMapper.insert(order); // 准备参数 @@ -311,7 +308,6 @@ public class TradeOrderServiceTest extends BaseDbUnitTest { // 断言 TradeOrderDO dbOrder = tradeOrderMapper.selectById(1L); assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus()); - assertEquals(dbOrder.getDeliveryStatus(), TradeOrderDeliveryStatusEnum.RECEIVED.getStatus()); assertNotNull(dbOrder.getReceiveTime()); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql index d4ce5cc9f..e30b0d225 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql @@ -25,7 +25,6 @@ CREATE TABLE IF NOT EXISTS "trade_order" ( "delivery_template_id" bigint, "logistics_id" bigint, "logistics_no" varchar, - "delivery_status" smallint NOT NULL, "delivery_time" datetime, "receive_time" datetime, "receiver_name" varchar NOT NULL,