秒杀活动和拼团活动接口调整 #40
@ -1,6 +1,7 @@
|
|||||||
package cn.iocoder.yudao.module.product.controller.app.spu.vo;
|
package cn.iocoder.yudao.module.product.controller.app.spu.vo;
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
|
import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@ -33,6 +34,8 @@ public class AppProductSpuDetailRespVO {
|
|||||||
@Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private List<String> sliderPicUrls;
|
private List<String> sliderPicUrls;
|
||||||
|
|
||||||
|
@Schema(description = "商品品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
|
private Long brandId;
|
||||||
// ========== 营销相关字段 =========
|
// ========== 营销相关字段 =========
|
||||||
|
|
||||||
// ========== SKU 相关字段 =========
|
// ========== SKU 相关字段 =========
|
||||||
|
@ -149,4 +149,6 @@ public interface ErrorCodeConstants {
|
|||||||
ErrorCode POINT_ACTIVITY_JOIN_ACTIVITY_PRODUCT_NOT_EXISTS = new ErrorCode(1_013_007_007, "积分商品兑换失败,原因:商品不存在");
|
ErrorCode POINT_ACTIVITY_JOIN_ACTIVITY_PRODUCT_NOT_EXISTS = new ErrorCode(1_013_007_007, "积分商品兑换失败,原因:商品不存在");
|
||||||
ErrorCode POINT_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1_013_007_008, "积分商品兑换失败,原因:积分商品库存不足");
|
ErrorCode POINT_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1_013_007_008, "积分商品兑换失败,原因:积分商品库存不足");
|
||||||
|
|
||||||
|
ErrorCode TIME_FORMAT_ERROR = new ErrorCode(1_019_007_008, "秒杀时间段格式化错误");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ public class AppActivityController {
|
|||||||
private RewardActivityService rewardActivityService;
|
private RewardActivityService rewardActivityService;
|
||||||
|
|
||||||
@GetMapping("/list-by-spu-id")
|
@GetMapping("/list-by-spu-id")
|
||||||
@Operation(summary = "获得单个商品,近期参与的每个活动")
|
@Operation(summary = "获得单个商品,正在参与的所有活动")
|
||||||
@Parameter(name = "spuId", description = "商品编号", required = true)
|
@Parameter(name = "spuId", description = "商品编号", required = true)
|
||||||
public CommonResult<List<AppActivityRespVO>> getActivityListBySpuId(@RequestParam("spuId") Long spuId) {
|
public CommonResult<List<AppActivityRespVO>> getActivityListBySpuId(@RequestParam("spuId") Long spuId) {
|
||||||
// 每种活动,只返回一个
|
// 每种活动,只返回一个
|
||||||
|
@ -6,14 +6,20 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
|||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
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.ProductSpuApi;
|
||||||
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
|
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillValidateJoinRespDTO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityDetailRespVO;
|
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityDetailRespVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityPurchasesTimesReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityRespVO;
|
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityRespVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillPurchasesTimesReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
|
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.CombinationActivityDO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
|
||||||
import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService;
|
import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService;
|
||||||
|
import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
|
||||||
import com.google.common.cache.CacheLoader;
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
@ -60,7 +66,8 @@ public class AppCombinationActivityController {
|
|||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ProductSpuApi spuApi;
|
private ProductSpuApi spuApi;
|
||||||
|
@Resource
|
||||||
|
private TradeOrderApi tradeOrderApi;
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
@Operation(summary = "获得拼团活动列表", description = "用于小程序首页")
|
@Operation(summary = "获得拼团活动列表", description = "用于小程序首页")
|
||||||
@Parameter(name = "count", description = "需要展示的数量", example = "6")
|
@Parameter(name = "count", description = "需要展示的数量", example = "6")
|
||||||
@ -129,5 +136,14 @@ public class AppCombinationActivityController {
|
|||||||
List<CombinationProductDO> products = activityService.getCombinationProductsByActivityId(activity.getId());
|
List<CombinationProductDO> products = activityService.getCombinationProductsByActivityId(activity.getId());
|
||||||
return success(CombinationActivityConvert.INSTANCE.convert3(activity, products));
|
return success(CombinationActivityConvert.INSTANCE.convert3(activity, products));
|
||||||
}
|
}
|
||||||
|
@GetMapping("/getPurchaseTimes")
|
||||||
|
@Operation(summary = "获得剩余拼团购买次数")
|
||||||
|
public CommonResult<Integer> getSeckillActivityPage(AppCombinationActivityPurchasesTimesReqVO reqVO) {
|
||||||
|
// 1. 获取总限购数量
|
||||||
|
CombinationActivityDO combinationActivity = activityService.getCombinationActivity(reqVO.getActivityId());
|
||||||
|
// 2. 获取已购买数量
|
||||||
|
int seckillProductCount = tradeOrderApi.getCombinationProductCount(reqVO.getUserId(), reqVO.getActivityId());
|
||||||
|
// 3. 总次数减去下单过的次数 得到剩余次数
|
||||||
|
return success(Math.max(combinationActivity.getTotalLimitCount() - seckillProductCount, 0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
|
||||||
|
@Schema(description = "用户 App - 拼团剩余购买次数 Request VO")
|
||||||
|
@Data
|
||||||
|
@Valid
|
||||||
|
public class AppCombinationActivityPurchasesTimesReqVO {
|
||||||
|
|
||||||
|
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@Schema(description = "拼团活动编号", example = "1024")
|
||||||
|
private Long activityId;
|
||||||
|
|
||||||
|
}
|
@ -5,19 +5,22 @@ import cn.hutool.core.util.ObjectUtil;
|
|||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
|
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
|
||||||
|
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.ProductSpuApi;
|
||||||
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
|
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityDetailRespVO;
|
import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillValidateJoinRespDTO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityNowRespVO;
|
import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.*;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityPageReqVO;
|
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityRespVO;
|
|
||||||
import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert;
|
import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillConfigDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillConfigDO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO;
|
||||||
import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService;
|
import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService;
|
||||||
import cn.iocoder.yudao.module.promotion.service.seckill.SeckillConfigService;
|
import cn.iocoder.yudao.module.promotion.service.seckill.SeckillConfigService;
|
||||||
|
import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.google.common.cache.CacheLoader;
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
@ -31,19 +34,22 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache;
|
import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.findFirst;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.findFirst;
|
||||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.isBetween;
|
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.isBetween;
|
||||||
|
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.TIME_FORMAT_ERROR;
|
||||||
|
|
||||||
@Tag(name = "用户 App - 秒杀活动")
|
@Tag(name = "用户 App - 秒杀活动")
|
||||||
@RestController
|
@RestController
|
||||||
@ -73,6 +79,12 @@ public class AppSeckillActivityController {
|
|||||||
@Resource
|
@Resource
|
||||||
private ProductSpuApi spuApi;
|
private ProductSpuApi spuApi;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ProductSkuApi skuApi;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TradeOrderApi tradeOrderApi;
|
||||||
|
|
||||||
@GetMapping("/get-now")
|
@GetMapping("/get-now")
|
||||||
@Operation(summary = "获得当前秒杀活动", description = "获取当前正在进行的活动,提供给首页使用")
|
@Operation(summary = "获得当前秒杀活动", description = "获取当前正在进行的活动,提供给首页使用")
|
||||||
public CommonResult<AppSeckillActivityNowRespVO> getNowSeckillActivity() {
|
public CommonResult<AppSeckillActivityNowRespVO> getNowSeckillActivity() {
|
||||||
@ -113,15 +125,38 @@ public class AppSeckillActivityController {
|
|||||||
|
|
||||||
@GetMapping("/spuList")
|
@GetMapping("/spuList")
|
||||||
@Parameter(name = "count", description = "需要展示的数量", example = "6")
|
@Parameter(name = "count", description = "需要展示的数量", example = "6")
|
||||||
@Operation(summary = "获得秒杀活动分页")
|
@Operation(summary = "获得现在进行的秒杀活动分页")
|
||||||
public CommonResult<List<ProductSpuRespDTO>> getSeckillActivitySupList(@RequestParam(name = "count", defaultValue = "6") Integer count) {
|
public CommonResult<List<ProductSpuRespDTO>> getSeckillActivitySupList(@RequestParam(name = "count", defaultValue = "3") Integer count) {
|
||||||
AppSeckillActivityPageReqVO pageReqVO = new AppSeckillActivityPageReqVO();
|
AppSeckillActivityPageReqVO pageReqVO = new AppSeckillActivityPageReqVO();
|
||||||
if (count != null && count != 0){
|
Page<SeckillActivityDO> page = new Page<>(1, 3);
|
||||||
pageReqVO.setPageNo(1);
|
;
|
||||||
pageReqVO.setPageSize(count);
|
if (count != null && count != 0) {
|
||||||
|
page = new Page<>(1, count);
|
||||||
}
|
}
|
||||||
|
// 先找出当前时间对应的配置时间段id
|
||||||
|
List<Long> configIdList = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
List<SeckillConfigDO> timeList = configService.getSeckillConfigListByStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
|
||||||
|
// 当前时间
|
||||||
|
Date currentTime = format.parse(format.format(new Date()));
|
||||||
|
// 遍历所有配置时间段,找出符合时间段的id
|
||||||
|
for (SeckillConfigDO seckillConfigDO : timeList) {
|
||||||
|
if (currentTime.before(format.parse(seckillConfigDO.getEndTime())) && currentTime.after(format.parse(seckillConfigDO.getStartTime()))) {
|
||||||
|
configIdList.add(seckillConfigDO.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ParseException e) {
|
||||||
|
throw exception(TIME_FORMAT_ERROR);
|
||||||
|
}
|
||||||
|
// 对配置时间段的id数组进行判断
|
||||||
|
if (configIdList.isEmpty()) {
|
||||||
|
return success(null);
|
||||||
|
}
|
||||||
|
// 获取满足当前正在进行的活动
|
||||||
|
PageResult<SeckillActivityDO> pageResult = activityService.getRunningActivityByConfigIdsCount(configIdList, page);
|
||||||
// 1. 查询满足当前阶段的活动
|
// 1. 查询满足当前阶段的活动
|
||||||
PageResult<SeckillActivityDO> pageResult = activityService.getSeckillActivityAppPageByConfigId(pageReqVO);
|
// PageResult<SeckillActivityDO> pageResult = activityService.getSeckillActivityAppPageByConfigId(pageReqVO);
|
||||||
if (CollUtil.isEmpty(pageResult.getList())) {
|
if (CollUtil.isEmpty(pageResult.getList())) {
|
||||||
return success(null);
|
return success(null);
|
||||||
}
|
}
|
||||||
@ -135,7 +170,7 @@ public class AppSeckillActivityController {
|
|||||||
HashMap<Long, Long> hashMap = new HashMap<>();
|
HashMap<Long, Long> hashMap = new HashMap<>();
|
||||||
for (AppSeckillActivityRespVO respVO : result.getList()) {
|
for (AppSeckillActivityRespVO respVO : result.getList()) {
|
||||||
arrayList.add(respVO.getSpuId());
|
arrayList.add(respVO.getSpuId());
|
||||||
hashMap.put(respVO.getSpuId(),respVO.getId());
|
hashMap.put(respVO.getSpuId(), respVO.getId());
|
||||||
}
|
}
|
||||||
List<ProductSpuRespDTO> list = spuApi.getSpuList(arrayList);
|
List<ProductSpuRespDTO> list = spuApi.getSpuList(arrayList);
|
||||||
for (ProductSpuRespDTO respDTO : list) {
|
for (ProductSpuRespDTO respDTO : list) {
|
||||||
@ -184,4 +219,14 @@ public class AppSeckillActivityController {
|
|||||||
return success(SeckillActivityConvert.INSTANCE.convert3(activity, productList, startTime, endTime));
|
return success(SeckillActivityConvert.INSTANCE.convert3(activity, productList, startTime, endTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/getPurchaseTimes")
|
||||||
|
@Operation(summary = "获得剩余秒杀购买次数")
|
||||||
|
public CommonResult<Integer> getSeckillActivityPage(AppSeckillPurchasesTimesReqVO reqVO) {
|
||||||
|
// 1. 获取总限购数量
|
||||||
|
SeckillActivityDO seckillActivity = activityService.getSeckillActivity(reqVO.getActivityId());
|
||||||
|
// 2. 获取已购买数量
|
||||||
|
int seckillProductCount = tradeOrderApi.getSeckillProductCount(reqVO.getUserId(), reqVO.getActivityId());
|
||||||
|
// 3. 总次数减去下单过的次数 得到剩余次数
|
||||||
|
return success(Math.max(seckillActivity.getTotalLimitCount() - seckillProductCount, 0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||||
|
import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Schema(description = "用户 App - 秒杀剩余购买次数 Request VO")
|
||||||
|
@Data
|
||||||
|
@Valid
|
||||||
|
public class AppSeckillPurchasesTimesReqVO {
|
||||||
|
|
||||||
|
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@Schema(description = "秒杀活动编号", example = "1024")
|
||||||
|
private Long activityId;
|
||||||
|
|
||||||
|
}
|
@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.Se
|
|||||||
import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityPageReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityPageReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@ -139,4 +140,11 @@ public interface SeckillActivityService {
|
|||||||
*/
|
*/
|
||||||
List<SeckillActivityDO> getSeckillActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime);
|
List<SeckillActivityDO> getSeckillActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前正在进行的秒杀活动
|
||||||
|
* @param configIdList 符合配置时间段的id
|
||||||
|
* @param page 分页
|
||||||
|
* @return cn.iocoder.yudao.framework.common.pojo.PageResult<cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO>
|
||||||
|
*/
|
||||||
|
PageResult<SeckillActivityDO> getRunningActivityByConfigIdsCount(List<Long> configIdList, Page<SeckillActivityDO> page);
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import cn.hutool.core.util.ObjectUtil;
|
|||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
|
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
|
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.sku.dto.ProductSkuRespDTO;
|
||||||
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
|
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
|
||||||
@ -23,6 +24,8 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillConfigDO;
|
|||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper;
|
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.dal.mysql.seckill.seckillactivity.SeckillProductMapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
@ -85,7 +88,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验秒杀商品参与的活动是否存在冲突
|
* 校验秒杀商品参与的活动是否存在冲突
|
||||||
*
|
* <p>
|
||||||
* 1. 校验秒杀时段是否存在
|
* 1. 校验秒杀时段是否存在
|
||||||
* 2. 秒杀商品是否参加其它活动
|
* 2. 秒杀商品是否参加其它活动
|
||||||
*
|
*
|
||||||
@ -336,4 +339,17 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
|
|||||||
convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId")), dateTime);
|
convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId")), dateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResult<SeckillActivityDO> getRunningActivityByConfigIdsCount(List<Long> configIdList, Page<SeckillActivityDO> page) {
|
||||||
|
LambdaQueryWrapper<SeckillActivityDO> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(SeckillActivityDO::getStatus, CommonStatusEnum.ENABLE.getStatus())
|
||||||
|
.ge(SeckillActivityDO::getEndTime, LocalDateTime.now())
|
||||||
|
.in(SeckillActivityDO::getConfigIds, configIdList);
|
||||||
|
Page<SeckillActivityDO> seckillActivityDOPage = seckillActivityMapper.selectPage(page, wrapper);
|
||||||
|
PageResult<SeckillActivityDO> pageResult = new PageResult<>();
|
||||||
|
pageResult.setTotal(seckillActivityDOPage.getTotal());
|
||||||
|
pageResult.setList(seckillActivityDOPage.getRecords());
|
||||||
|
return pageResult;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -37,4 +37,19 @@ public interface TradeOrderApi {
|
|||||||
*/
|
*/
|
||||||
void cancelPaidOrder(Long userId, Long orderId);
|
void cancelPaidOrder(Long userId, Long orderId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取已经使用的秒杀次数
|
||||||
|
* @param userId 用户编号
|
||||||
|
* @param activityId 秒杀活动编号
|
||||||
|
* @return java.lang.Integer
|
||||||
|
*/
|
||||||
|
Integer getSeckillProductCount(Long userId, Long activityId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取已经使用的拼团次数
|
||||||
|
* @param userId 用户编号
|
||||||
|
* @param activityId 拼团活动编号
|
||||||
|
* @return java.lang.Integer
|
||||||
|
*/
|
||||||
|
Integer getCombinationProductCount(Long userId, Long activityId);
|
||||||
}
|
}
|
||||||
|
@ -40,4 +40,14 @@ public class TradeOrderApiImpl implements TradeOrderApi {
|
|||||||
tradeOrderUpdateService.cancelPaidOrder(userId, orderId);
|
tradeOrderUpdateService.cancelPaidOrder(userId, orderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getSeckillProductCount(Long userId, Long activityId) {
|
||||||
|
return tradeOrderQueryService.getSeckillProductCount(userId, activityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getCombinationProductCount(Long userId, Long activityId) {
|
||||||
|
return tradeOrderQueryService.getCombinationProductCount(userId, activityId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -124,4 +124,9 @@ public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default List<TradeOrderDO> selectListByUserIdAndCombinationActivityId(Long userId, Long activityId){
|
||||||
|
LambdaQueryWrapperX<TradeOrderDO> wrapperX = new LambdaQueryWrapperX<>();
|
||||||
|
wrapperX.eq(TradeOrderDO::getUserId, userId).eq(TradeOrderDO::getSeckillActivityId, activityId);
|
||||||
|
return selectList(wrapperX);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,4 +155,12 @@ public interface TradeOrderQueryService {
|
|||||||
*/
|
*/
|
||||||
List<TradeOrderItemDO> getOrderItemListByOrderId(Collection<Long> orderIds);
|
List<TradeOrderItemDO> getOrderItemListByOrderId(Collection<Long> orderIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在指定拼团活动下,用户购买的商品数量
|
||||||
|
*
|
||||||
|
* @param userId 用户编号
|
||||||
|
* @param activityId 活动编号
|
||||||
|
* @return 拼团商品数量
|
||||||
|
*/
|
||||||
|
Integer getCombinationProductCount(Long userId, Long activityId);
|
||||||
}
|
}
|
||||||
|
@ -247,6 +247,18 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService {
|
|||||||
return tradeOrderItemMapper.selectListByOrderId(orderIds);
|
return tradeOrderItemMapper.selectListByOrderId(orderIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getCombinationProductCount(Long userId, Long activityId) {
|
||||||
|
// 获得订单列表
|
||||||
|
List<TradeOrderDO> orders = tradeOrderMapper.selectListByUserIdAndCombinationActivityId(userId, activityId);
|
||||||
|
orders.removeIf(order -> TradeOrderStatusEnum.isCanceled(order.getStatus())); // 过滤掉【已取消】的订单
|
||||||
|
if (CollUtil.isEmpty(orders)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// 获得订单项列表
|
||||||
|
return tradeOrderItemMapper.selectProductSumByOrderId(convertSet(orders, TradeOrderDO::getId));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得自身的代理对象,解决 AOP 生效问题
|
* 获得自身的代理对象,解决 AOP 生效问题
|
||||||
*
|
*
|
||||||
|
@ -51,7 +51,10 @@ public class TradePriceServiceImpl implements TradePriceService {
|
|||||||
// 2.1 计算价格
|
// 2.1 计算价格
|
||||||
TradePriceCalculateRespBO calculateRespBO = TradePriceCalculatorHelper
|
TradePriceCalculateRespBO calculateRespBO = TradePriceCalculatorHelper
|
||||||
.buildCalculateResp(calculateReqBO, spuList, skuList);
|
.buildCalculateResp(calculateReqBO, spuList, skuList);
|
||||||
priceCalculators.forEach(calculator -> calculator.calculate(calculateReqBO, calculateRespBO));
|
// priceCalculators.forEach(calculator -> calculator.calculate(calculateReqBO, calculateRespBO));
|
||||||
|
for (TradePriceCalculator calculator : priceCalculators) {
|
||||||
|
calculator.calculate(calculateReqBO, calculateRespBO);
|
||||||
|
}
|
||||||
// 2.2 如果最终支付金额小于等于 0,则抛出业务异常
|
// 2.2 如果最终支付金额小于等于 0,则抛出业务异常
|
||||||
if (calculateRespBO.getPrice().getPayPrice() <= 0) {
|
if (calculateRespBO.getPrice().getPayPrice() <= 0) {
|
||||||
log.error("[calculatePrice][价格计算不正确,请求 calculateReqDTO({}),结果 priceCalculate({})]",
|
log.error("[calculatePrice][价格计算不正确,请求 calculateReqDTO({}),结果 priceCalculate({})]",
|
||||||
|
Loading…
Reference in New Issue
Block a user