From 7581ebfa777b33a225e92c3151bc78bc5bea6172 Mon Sep 17 00:00:00 2001 From: XinWei <2718030729@qq.com> Date: Fri, 11 Oct 2024 14:23:23 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E7=A7=92=E6=9D=80=E6=B4=BB=E5=8A=A8?= =?UTF-8?q?=E9=A6=96=E9=A1=B5=E6=98=BE=E7=A4=BA=E6=AD=A3=E5=9C=A8=E8=BF=9B?= =?UTF-8?q?=E8=A1=8C=E6=B4=BB=E5=8A=A8=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/spu/vo/AppProductSpuDetailRespVO.java | 3 ++ .../promotion/enums/ErrorCodeConstants.java | 2 + .../app/activity/AppActivityController.java | 2 +- .../seckill/AppSeckillActivityController.java | 48 ++++++++++++++----- .../seckill/SeckillActivityService.java | 8 ++++ .../seckill/SeckillActivityServiceImpl.java | 18 ++++++- 6 files changed, 68 insertions(+), 13 deletions(-) diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java index f1ee49b..b26c5a0 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.product.controller.app.spu.vo; 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 lombok.Data; @@ -33,6 +34,8 @@ public class AppProductSpuDetailRespVO { @Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED) private List sliderPicUrls; + @Schema(description = "商品品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long brandId; // ========== 营销相关字段 ========= // ========== SKU 相关字段 ========= 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 1038bad..74fdb33 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 @@ -149,4 +149,6 @@ public interface ErrorCodeConstants { 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 TIME_FORMAT_ERROR = new ErrorCode(1_019_007_008, "秒杀时间段格式化错误"); + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java index 38dd72b..7f27de5 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java @@ -53,7 +53,7 @@ public class AppActivityController { private RewardActivityService rewardActivityService; @GetMapping("/list-by-spu-id") - @Operation(summary = "获得单个商品,近期参与的每个活动") + @Operation(summary = "获得单个商品,正在参与的所有活动") @Parameter(name = "spuId", description = "商品编号", required = true) public CommonResult> getActivityListBySpuId(@RequestParam("spuId") Long spuId) { // 每种活动,只返回一个 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java index ae33e40..464870f 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java @@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; 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.module.product.api.spu.ProductSpuApi; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; @@ -18,6 +19,7 @@ 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.service.seckill.SeckillActivityService; import cn.iocoder.yudao.module.promotion.service.seckill.SeckillConfigService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import io.swagger.v3.oas.annotations.Operation; @@ -31,19 +33,21 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; +import java.util.*; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 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.collection.CollectionUtils.convertList; 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.module.promotion.enums.ErrorCodeConstants.TIME_FORMAT_ERROR; @Tag(name = "用户 App - 秒杀活动") @RestController @@ -59,7 +63,7 @@ public class AppSeckillActivityController { @Override public AppSeckillActivityNowRespVO load(String key) { - return getNowSeckillActivity0(); + return getNowSeckillActivity0(); } }); @@ -113,15 +117,37 @@ public class AppSeckillActivityController { @GetMapping("/spuList") @Parameter(name = "count", description = "需要展示的数量", example = "6") - @Operation(summary = "获得秒杀活动分页") - public CommonResult> getSeckillActivitySupList(@RequestParam(name = "count", defaultValue = "6") Integer count) { + @Operation(summary = "获得现在进行的秒杀活动分页") + public CommonResult> getSeckillActivitySupList(@RequestParam(name = "count", defaultValue = "3") Integer count) { AppSeckillActivityPageReqVO pageReqVO = new AppSeckillActivityPageReqVO(); - if (count != null && count != 0){ - pageReqVO.setPageNo(1); - pageReqVO.setPageSize(count); + Page page = new Page<>(1, 3);; + if (count != null && count != 0) { + page = new Page<>(1, count); } + // 先找出当前时间对应的配置时间段id + List configIdList = new ArrayList<>(); + try { + List 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 pageResult = activityService.getRunningActivityByConfigIdsCount(configIdList, page); // 1. 查询满足当前阶段的活动 - PageResult pageResult = activityService.getSeckillActivityAppPageByConfigId(pageReqVO); +// PageResult pageResult = activityService.getSeckillActivityAppPageByConfigId(pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return success(null); } @@ -135,7 +161,7 @@ public class AppSeckillActivityController { HashMap hashMap = new HashMap<>(); for (AppSeckillActivityRespVO respVO : result.getList()) { arrayList.add(respVO.getSpuId()); - hashMap.put(respVO.getSpuId(),respVO.getId()); + hashMap.put(respVO.getSpuId(), respVO.getId()); } List list = spuApi.getSpuList(arrayList); for (ProductSpuRespDTO respDTO : list) { diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java index 0ed6a4f..347b3ea 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java @@ -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.dal.dataobject.seckill.SeckillActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import javax.validation.Valid; import java.time.LocalDateTime; @@ -139,4 +140,11 @@ public interface SeckillActivityService { */ List getSeckillActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime); + /** + * 获取当前正在进行的秒杀活动 + * @param configIdList 符合配置时间段的id + * @param page 分页 + * @return cn.iocoder.yudao.framework.common.pojo.PageResult + */ + PageResult getRunningActivityByConfigIdsCount(List configIdList, Page page); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java index 8ccfb30..2d9535a 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java @@ -7,6 +7,7 @@ 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.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.dto.ProductSkuRespDTO; 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.mysql.seckill.seckillactivity.SeckillActivityMapper; 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.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -85,7 +88,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { /** * 校验秒杀商品参与的活动是否存在冲突 - * + *

* 1. 校验秒杀时段是否存在 * 2. 秒杀商品是否参加其它活动 * @@ -336,4 +339,17 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId")), dateTime); } + @Override + public PageResult getRunningActivityByConfigIdsCount(List configIdList, Page page) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SeckillActivityDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) + .ge(SeckillActivityDO::getEndTime, LocalDateTime.now()) + .in(SeckillActivityDO::getConfigIds, configIdList); + Page seckillActivityDOPage = seckillActivityMapper.selectPage(page, wrapper); + PageResult pageResult = new PageResult<>(); + pageResult.setTotal(seckillActivityDOPage.getTotal()); + pageResult.setList(seckillActivityDOPage.getRecords()); + return pageResult; + } + } -- 2.45.2 From 82662663873ee8d5740ed0d0ef92de60ca4b6d8f Mon Sep 17 00:00:00 2001 From: XinWei <2718030729@qq.com> Date: Sat, 12 Oct 2024 09:35:10 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=8B=BC=E5=9B=A2=E5=92=8C=E7=A7=92?= =?UTF-8?q?=E6=9D=80=E6=B4=BB=E5=8A=A8=E8=8E=B7=E5=8F=96=E5=89=A9=E4=BD=99?= =?UTF-8?q?=E8=B4=AD=E4=B9=B0=E6=AC=A1=E6=95=B0=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppCombinationActivityController.java | 20 +++++++++++-- ...ombinationActivityPurchasesTimesReqVO.java | 19 ++++++++++++ .../seckill/AppSeckillActivityController.java | 29 +++++++++++++++---- .../AppSeckillPurchasesTimesReqVO.java | 24 +++++++++++++++ .../module/trade/api/order/TradeOrderApi.java | 15 ++++++++++ .../trade/api/order/TradeOrderApiImpl.java | 10 +++++++ .../dal/mysql/order/TradeOrderMapper.java | 5 ++++ .../service/order/TradeOrderQueryService.java | 8 +++++ .../order/TradeOrderQueryServiceImpl.java | 12 ++++++++ .../service/price/TradePriceServiceImpl.java | 5 +++- 10 files changed, 139 insertions(+), 8 deletions(-) create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityPurchasesTimesReqVO.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillPurchasesTimesReqVO.java diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java index 7b93908..71b13da 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java @@ -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.PageParam; 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.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.AppCombinationActivityPurchasesTimesReqVO; 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.dal.dataobject.combination.CombinationActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO; 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.LoadingCache; import io.swagger.v3.oas.annotations.Operation; @@ -60,7 +66,8 @@ public class AppCombinationActivityController { @Resource private ProductSpuApi spuApi; - + @Resource + private TradeOrderApi tradeOrderApi; @GetMapping("/list") @Operation(summary = "获得拼团活动列表", description = "用于小程序首页") @Parameter(name = "count", description = "需要展示的数量", example = "6") @@ -129,5 +136,14 @@ public class AppCombinationActivityController { List products = activityService.getCombinationProductsByActivityId(activity.getId()); return success(CombinationActivityConvert.INSTANCE.convert3(activity, products)); } - + @GetMapping("/getPurchaseTimes") + @Operation(summary = "获得剩余拼团购买次数") + public CommonResult 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)); + } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityPurchasesTimesReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityPurchasesTimesReqVO.java new file mode 100644 index 0000000..e8e8f74 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityPurchasesTimesReqVO.java @@ -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; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java index 464870f..e8d8119 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java @@ -7,18 +7,19 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; 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.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.app.seckill.vo.activity.AppSeckillActivityDetailRespVO; -import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityNowRespVO; -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.api.seckill.dto.SeckillValidateJoinRespDTO; +import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.*; 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.SeckillConfigDO; 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.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.LoadingCache; @@ -42,6 +43,7 @@ import java.time.LocalTime; import java.util.*; 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.util.cache.CacheUtils.buildAsyncReloadingCache; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @@ -77,6 +79,12 @@ public class AppSeckillActivityController { @Resource private ProductSpuApi spuApi; + @Resource + private ProductSkuApi skuApi; + + @Resource + private TradeOrderApi tradeOrderApi; + @GetMapping("/get-now") @Operation(summary = "获得当前秒杀活动", description = "获取当前正在进行的活动,提供给首页使用") public CommonResult getNowSeckillActivity() { @@ -120,7 +128,8 @@ public class AppSeckillActivityController { @Operation(summary = "获得现在进行的秒杀活动分页") public CommonResult> getSeckillActivitySupList(@RequestParam(name = "count", defaultValue = "3") Integer count) { AppSeckillActivityPageReqVO pageReqVO = new AppSeckillActivityPageReqVO(); - Page page = new Page<>(1, 3);; + Page page = new Page<>(1, 3); + ; if (count != null && count != 0) { page = new Page<>(1, count); } @@ -210,4 +219,14 @@ public class AppSeckillActivityController { return success(SeckillActivityConvert.INSTANCE.convert3(activity, productList, startTime, endTime)); } + @GetMapping("/getPurchaseTimes") + @Operation(summary = "获得剩余秒杀购买次数") + public CommonResult 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)); + } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillPurchasesTimesReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillPurchasesTimesReqVO.java new file mode 100644 index 0000000..7e82b13 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillPurchasesTimesReqVO.java @@ -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; + +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApi.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApi.java index 744a7b8..c03a5cf 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApi.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApi.java @@ -37,4 +37,19 @@ public interface TradeOrderApi { */ 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); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java index 3cb7bba..be59bcb 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java @@ -40,4 +40,14 @@ public class TradeOrderApiImpl implements TradeOrderApi { 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); + } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java index 21fc038..b348ee3 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java @@ -124,4 +124,9 @@ public interface TradeOrderMapper extends BaseMapperX { ); } + default List selectListByUserIdAndCombinationActivityId(Long userId, Long activityId){ + LambdaQueryWrapperX wrapperX = new LambdaQueryWrapperX<>(); + wrapperX.eq(TradeOrderDO::getUserId, userId).eq(TradeOrderDO::getSeckillActivityId, activityId); + return selectList(wrapperX); + } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java index 4457922..d95d524 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java @@ -155,4 +155,12 @@ public interface TradeOrderQueryService { */ List getOrderItemListByOrderId(Collection orderIds); + /** + * 在指定拼团活动下,用户购买的商品数量 + * + * @param userId 用户编号 + * @param activityId 活动编号 + * @return 拼团商品数量 + */ + Integer getCombinationProductCount(Long userId, Long activityId); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java index a1fa31c..d29641e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java @@ -247,6 +247,18 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { return tradeOrderItemMapper.selectListByOrderId(orderIds); } + @Override + public Integer getCombinationProductCount(Long userId, Long activityId) { + // 获得订单列表 + List 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 生效问题 * diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java index c070af1..82ea038 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java @@ -51,7 +51,10 @@ public class TradePriceServiceImpl implements TradePriceService { // 2.1 计算价格 TradePriceCalculateRespBO calculateRespBO = TradePriceCalculatorHelper .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,则抛出业务异常 if (calculateRespBO.getPrice().getPayPrice() <= 0) { log.error("[calculatePrice][价格计算不正确,请求 calculateReqDTO({}),结果 priceCalculate({})]", -- 2.45.2